diff --git a/apply_events.cfm b/apply_events.cfm index a30f6e0..35ac362 100644 --- a/apply_events.cfm +++ b/apply_events.cfm @@ -25,6 +25,10 @@ + + + SELECT pg_advisory_xact_lock(hashtext()) + SELECT COALESCE(MAX(seq), 0) as m FROM spec_events @@ -114,7 +118,7 @@ INSERT INTO spec_current (contract_id, name_hash, name, price, qty, sum, date_start, last_event_id) VALUES ( , - md5(lower(trim()) || coalesce(, '')), + md5(lower(trim(regexp_replace(translate(normalize(, NFKC), '–—‑−«»""', '------""'), '\s+', ' ', 'g'))) || coalesce(, '')), , , , diff --git a/deploy/convert_server.py b/deploy/convert_server.py index 0e71e4e..0744c92 100755 --- a/deploy/convert_server.py +++ b/deploy/convert_server.py @@ -212,6 +212,19 @@ class Handler(BaseHTTPRequestHandler): llm_result = result[0] ops = llm_result.get("ops", []) mode = llm_result.get("mode", "partial") + + # Маппинг target_id (r1, r2...) → target_hash из current_spec + id_map = {f"r{i+1}": r["hash"] for i, r in enumerate(current_spec)} + # Обогащение ops: target_id → target_hash + имя из current_spec + spec_names = {r["hash"]: r["name"] for r in current_spec} + for op in ops: + tid = op.get("target_id") + if tid and tid in id_map: + op["target_hash"] = id_map[tid] + # Добавить имя для UPDATE/DELETE из spec_current + th = op.get("target_hash") + if th and th in spec_names and not op.get("new_row", {}).get("name"): + op.setdefault("new_row", {})["name"] = spec_names[th] self._sse({"type": "llm_done", "supplement_id": sid, "filename": s["filename"], "ops_count": len(ops), "mode": mode, "time_s": elapsed}) diff --git a/deploy/llm_prompt.py b/deploy/llm_prompt.py index b7cddd0..847c25a 100644 --- a/deploy/llm_prompt.py +++ b/deploy/llm_prompt.py @@ -39,9 +39,9 @@ def _build_initial(doc_text: str) -> str: def _build_diff(current_spec: list, doc_text: str) -> str: lines = [] - for r in current_spec: + for i, r in enumerate(current_spec): lines.append( - f"[hash: {r.get('hash', '?')}] {r.get('name', '?')} | " + f"[id: r{i+1}] {r.get('name', '?')} | " f"цена={r.get('price', '')} | объём={r.get('qty', '')} | " f"сумма={r.get('sum', '')} | начало={r.get('date_start', '')}" ) @@ -59,8 +59,8 @@ def _build_diff(current_spec: list, doc_text: str) -> str: "mode": "partial" | "full_replace", "ops": [ {{"action": "ADD", "new_row": {{"name": "...", "price": число, "qty": число, "sum": число, "date_start": "YYYY-MM-DD"}}, "comment": "..."}}, - {{"action": "UPDATE", "target_hash": "hash_строки", "new_values": {{"price": число}}, "comment": "..."}}, - {{"action": "DELETE", "target_hash": "hash_строки", "comment": "..."}}, + {{"action": "UPDATE", "target_id": "rN", "new_values": {{"price": число}}, "comment": "..."}}, + {{"action": "DELETE", "target_id": "rN", "comment": "..."}}, {{"action": "UNRESOLVED", "new_values": {{"name": "...", "price": число, ...}}, "reason": "почему не смог сопоставить"}} ] }} @@ -68,7 +68,7 @@ def _build_diff(current_spec: list, doc_text: str) -> str: ПРАВИЛА: 1. mode = "full_replace" — если в тексте есть фразы: «в следующей редакции», «заменить приложение», «излагается в следующей редакции». При full_replace — опиши ВСЕ новые строки как ADD. 2. mode = "partial" — если ДС меняет только отдельные строки. -3. Для UPDATE/DELETE — находи соответствующую строку по target_hash. +3. Для UPDATE/DELETE — укажи target_id (r1, r2...) из списка текущей спецификации. НЕ придумывай новые id. 4. new_values в UPDATE — только ИЗМЕНЁННЫЕ поля (не все). 5. Если не можешь однозначно сопоставить строку — action: UNRESOLVED с reason. 6. Пропускай итоговые строки и подписи. diff --git a/index.cfm b/index.cfm index f697e54..98b9190 100644 --- a/index.cfm +++ b/index.cfm @@ -71,7 +71,7 @@
Nubes - Сверка договоров — LLM AI-driven Event Sourcing v1.0.107 — Lucee + Сверка договоров — LLM AI-driven Event Sourcing v1.0.108 — Lucee