diff --git a/deploy/llm_prompt.py b/deploy/llm_prompt.py index 847c25a..23dfcd3 100644 --- a/deploy/llm_prompt.py +++ b/deploy/llm_prompt.py @@ -1,16 +1,14 @@ -"""llm_prompt.py — Формирование промпта для LLM-анализа ДС.""" +"""llm_prompt.py — Формирование промпта для LLM-анализа ДС. +Читает активный промпт из БД (через Lucee API). При ошибке — fallback на хардкод.""" +import os +import httpx -def build_prompt(current_spec: list, doc_text: str) -> str: - is_first = len(current_spec) == 0 - if is_first: - return _build_initial(doc_text) - else: - return _build_diff(current_spec, doc_text) +LUCEE_URL = os.environ.get("LUCEE_URL", "https://contractor.luceek8s.dev.nubes.ru") +# ── Fallback-промпты (если БД недоступна) ────────────────────── -def _build_initial(doc_text: str) -> str: - return f"""Ты — анализатор договоров облачного провайдера. +FALLBACK_EXTRACT = """Ты — анализатор договоров облачного провайдера. Ниже текст спецификации услуг из ПЕРВОГО документа (базовый договор). Извлеки ВСЕ строки спецификации в JSON-массив. @@ -36,18 +34,7 @@ def _build_initial(doc_text: str) -> str: {doc_text} ---""" - -def _build_diff(current_spec: list, doc_text: str) -> str: - lines = [] - for i, r in enumerate(current_spec): - lines.append( - f"[id: r{i+1}] {r.get('name', '?')} | " - f"цена={r.get('price', '')} | объём={r.get('qty', '')} | " - f"сумма={r.get('sum', '')} | начало={r.get('date_start', '')}" - ) - spec_text = "\n".join(lines) - - return f"""Ты — анализатор допсоглашений к договорам облачного провайдера. +FALLBACK_DIFF = """Ты — анализатор допсоглашений к договорам облачного провайдера. У тебя есть текущая спецификация услуг и текст нового допсоглашения (ДС). Твоя задача — определить, какие изменения вносит ДС в текущую спецификацию. @@ -75,9 +62,61 @@ def _build_diff(current_spec: list, doc_text: str) -> str: 7. price, qty, sum — ЧИСЛА (не строки). ТЕКУЩАЯ СПЕЦИФИКАЦИЯ: -{spec_text} +{spec_current} ТЕКСТ ДОПСОГЛАШЕНИЯ: --- {doc_text} ---""" + + +def _fetch_prompt(role: str) -> dict | None: + """Получить активный промпт из БД. Возвращает {id, body} или None.""" + try: + with httpx.Client(http2=True, timeout=10, verify=False) as client: + resp = client.get( + f"{LUCEE_URL}/prompt.cfm", + params={"action": "get_active", "role": role}, + ) + resp.raise_for_status() + data = resp.json() + if data.get("ok") and data.get("body"): + return {"id": data.get("id", ""), "body": data["body"]} + except Exception: + pass + return None + + +def _build_spec_text(current_spec: list) -> str: + """Перечисление строк спецификации для подстановки в {spec_current}.""" + lines = [] + for i, r in enumerate(current_spec): + lines.append( + f"[id: r{i+1}] {r.get('name', '?')} | " + f"цена={r.get('price', '')} | объём={r.get('qty', '')} | " + f"сумма={r.get('sum', '')} | начало={r.get('date_start', '')}" + ) + return "\n".join(lines) + + +def build_prompt(current_spec: list, doc_text: str) -> str: + """ + Формирует промпт для LLM. + 1. Пробует получить активный промпт из БД (Lucee API). + 2. При неудаче — fallback на хардкод. + Возвращает готовый текст промпта. + """ + is_first = len(current_spec) == 0 + role = "extract" if is_first else "diff" + + db = _fetch_prompt(role) + if db: + template = db["body"] + else: + template = FALLBACK_EXTRACT if is_first else FALLBACK_DIFF + + # Подстановка плейсхолдеров + result = template.replace("{doc_text}", doc_text) + result = result.replace("{spec_current}", _build_spec_text(current_spec)) + + return result diff --git a/index.cfm b/index.cfm index 95adb9e..074e982 100644 --- a/index.cfm +++ b/index.cfm @@ -75,7 +75,7 @@
Nubes - Сверка договоров — LLM AI-driven Event Sourcing v1.0.110 — Lucee + Сверка договоров — LLM AI-driven Event Sourcing v1.0.111 — Lucee