fix(legal): NotebookLM priority query, fix model name to gemini-2.5-flash fallback

This commit is contained in:
Admin 2026-10-13 11:17:07 +04:00
parent 0aac30187b
commit 0dcea20739

View file

@ -23,7 +23,7 @@ class AILegalEngine:
self.api_key = raw_key.strip("\"'") if raw_key else "" self.api_key = raw_key.strip("\"'") if raw_key else ""
self.client = None self.client = None
self.model_name = "gemini-2.5-flash" self.model_name = "gemini-2.5-flash"
self.deep_model_name = "gemini-2.5-pro" self.deep_model_name = "gemini-2.5-flash"
self._init_sdk_client() self._init_sdk_client()
def _init_sdk_client(self): def _init_sdk_client(self):
@ -111,8 +111,60 @@ class AILegalEngine:
data = await resp.json() data = await resp.json()
return data["candidates"][0]["content"]["parts"][0]["text"] return data["candidates"][0]["content"]["parts"][0]["text"]
async def query_notebooklm(self, prompt: str) -> dict:
"""Прямой запрос к блокноту NotebookLM «Разбор ответов строго по ЖК РФ»."""
notebook_id = os.getenv("NOTEBOOKLM_ID", "00ed7d92-1ab2-4159-ac72-1d0c4be21377")
nlm_bins = ["/home/matrixhasyou/.local/bin/nlm", "/usr/local/bin/nlm", "nlm"]
nlm_bin = next((b for b in nlm_bins if os.path.exists(b)), "nlm")
cmd = [
nlm_bin, "query", "notebook",
notebook_id,
prompt
]
env = os.environ.copy()
env["SSL_CERT_FILE"] = "/etc/ssl/certs/ca-certificates.crt"
try:
proc = await asyncio.create_subprocess_exec(
*cmd,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
env=env
)
stdout, stderr = await proc.communicate()
out_str = stdout.decode('utf-8', errors='ignore').strip()
err_str = stderr.decode('utf-8', errors='ignore').strip()
if proc.returncode == 0 and out_str and "Authentication Error" not in out_str and "ConnectError" not in out_str:
# Очистка предупреждений об апдейте nlm
if "Update available:" in out_str:
out_str = out_str.split("Update available:")[0].strip()
return {"success": True, "text": out_str, "source": "notebooklm"}
else:
return {"success": False, "error": err_str or out_str, "source": "notebooklm"}
except Exception as e:
return {"success": False, "error": str(e), "source": "notebooklm"}
async def query(self, prompt: str, role: str = "resident", audio_path: str = None) -> dict: async def query(self, prompt: str, role: str = "resident", audio_path: str = None) -> dict:
"""Основной метод запроса к юридическому ядру.""" """Основной метод запроса: NotebookLM (первый приоритет) -> Gemini (fallback)."""
start_time = datetime.now()
# Если вопрос от Админа и нет аудио — пробуем NotebookLM в первую очередь!
if role in ("admin", "lawyer") and not audio_path and prompt:
nlm_res = await self.query_notebooklm(prompt)
if nlm_res.get("success"):
latency = (datetime.now() - start_time).total_seconds()
return {
"success": True,
"text": nlm_res["text"],
"answer": nlm_res["text"],
"role": role,
"latency_sec": round(latency, 2),
"model": "NotebookLM: Разбор ответов строго по ЖК РФ"
}
# Резервный контур через Gemini API (если сессия блокнота требует продления или жилец)
if not self.api_key: if not self.api_key:
return { return {
"success": False, "success": False,
@ -121,17 +173,15 @@ class AILegalEngine:
"latency_sec": 0.0 "latency_sec": 0.0
} }
start_time = datetime.now()
system_instruction = ( system_instruction = (
"Ты — интеллектуальный юридический щит 10-подъездного многоквартирного дома по адресу: г. Ульяновск, пр-кт Ленинского Комсомола, д. 37 (МКД ЛенКом 37).\n" "Ты — интеллектуальный юридический щит 10-подъездного многоквартирного дома по адресу: г. Ульяновск, пр-кт Ленинского Комсомола, д. 37 (МКД ЛенКом 37).\n"
"Дом ведет системную юридическую защиту прав собственников против нарушений управляющей компании, бездействия надзорных органов и фальсификаций.\n" "Дом ведет системную юридическую защиту прав собственников против нарушений управляющей компании, бездействия надзорных органов и фальсификаций.\n"
f"{self.get_role_instructions(role)}" f"{self.get_role_instructions(role)}"
) )
model_to_use = self.deep_model_name if role in ("lawyer", "admin") else self.model_name model_to_use = self.model_name
try: try:
# Используем прямой REST (наивысшая надежность без конфликтов библиотек)
reply_text = await self._query_rest_api( reply_text = await self._query_rest_api(
prompt=prompt, prompt=prompt,
system_instruction=system_instruction, system_instruction=system_instruction,
@ -140,6 +190,12 @@ class AILegalEngine:
) )
latency = (datetime.now() - start_time).total_seconds() latency = (datetime.now() - start_time).total_seconds()
# Если для админа не сработал блокнот, честно добавляем статус
if role == "admin" and not audio_path:
prefix = "📚 <b>[Источник: База законов РФ / Резервный шлюз Gemini]</b>\n<i>(Сессия NotebookLM требует обновления куков)</i>\n\n"
reply_text = prefix + reply_text
return { return {
"success": True, "success": True,
"text": reply_text.strip(), "text": reply_text.strip(),