v2.0.15: фиксы по ревью Соннета (10 находок)
Deploy contracts-flask / validate (push) Canceled after 0s
Deploy contracts-flask / validate (push) Canceled after 0s
- #1 process.py: target_id→target_hash (UPDATE/DELETE больше не UNRESOLVED) - #2 Dockerfile: COPY upload - #3 prompts.py: убран created_by из SELECT - #4 prompts_bp.py: save_new_version/delete_prompt - #5 llm.py/classify.py: LLM-конфиг из config.py - #6/#7 compare.js: escHtml (XSS) - #8-#10: комментарии + мёртвый gen_random_uuid
This commit is contained in:
@@ -10,7 +10,7 @@ Classify service — LLM-based document classification.
|
||||
- Двухпроходная архитектура: LLM извлекает строки (тип/номер/дата/контрагент),
|
||||
Python в grouping.py нормализует и группирует детерминированно.
|
||||
"""
|
||||
import json, re, os
|
||||
import json, re
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
|
||||
import httpx
|
||||
@@ -23,9 +23,7 @@ log = __import__("logging").getLogger(__name__)
|
||||
# Увеличивать осторожно — api.aillm.ru может троттлить
|
||||
MAX_WORKERS = 4
|
||||
|
||||
LLM_URL = "https://api.aillm.ru/v1/chat/completions"
|
||||
LLM_KEY = os.environ.get("LLM_KEY") or os.environ.get("LLM_API_KEY", "")
|
||||
LLM_MODEL = "gpt-oss-120b"
|
||||
from config import LLM_URL, LLM_KEY, LLM_MODEL
|
||||
|
||||
# Ленивый singleton — обратная совместимость
|
||||
_classify_llm = None
|
||||
@@ -91,7 +89,7 @@ def classify_batch(batch_id, llm_client=None, repo=None):
|
||||
_db = repo if repo else db_docs
|
||||
_llm = llm_client if llm_client else _get_classify_client()
|
||||
|
||||
# Сбросить статус — allow re-classify after file changes
|
||||
# Сбросить 'processing' -> 'pending' (crash recovery); уже классифицированные не трогаем
|
||||
_db.reset_classify_status(batch_id)
|
||||
pending = _db.list_pending(batch_id)
|
||||
if not pending:
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
"""LLM service — call LLM API with optional DI."""
|
||||
import os, json
|
||||
import json
|
||||
|
||||
LLM_URL = "https://api.aillm.ru/v1/chat/completions"
|
||||
LLM_KEY = os.environ.get("LLM_KEY") or os.environ.get("LLM_API_KEY", "")
|
||||
LLM_MODEL = "gpt-oss-120b"
|
||||
from config import LLM_URL, LLM_KEY, LLM_MODEL
|
||||
|
||||
# Ленивый singleton — обратная совместимость
|
||||
_llm_client = None
|
||||
|
||||
@@ -77,6 +77,18 @@ def run_pipeline(contract_id, order_ids, build_prompt_fn):
|
||||
ops = result.get("ops", [])
|
||||
mode = result.get("mode", "llm")
|
||||
|
||||
# Трансляция target_id ("r1","r2"...) → target_hash (name_hash из current_spec).
|
||||
# LLM возвращает target_id, а apply_ops() читает target_hash — без этого UPDATE/DELETE уходят в UNRESOLVED.
|
||||
for _op in ops:
|
||||
_tid = _op.get("target_id", "")
|
||||
if _tid and isinstance(_tid, str) and _tid.startswith("r"):
|
||||
try:
|
||||
_idx = int(_tid[1:]) - 1
|
||||
if 0 <= _idx < len(current_spec):
|
||||
_op["target_hash"] = current_spec[_idx]["hash"]
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
yield {
|
||||
"type": "llm_done",
|
||||
"supplement_id": sid,
|
||||
|
||||
Reference in New Issue
Block a user