v2.0.2: fix SQLite — UUID in all INSERTs, now()→datetime, ::jsonb cleanup
Deploy contracts-flask / validate (push) Successful in 0s
Deploy contracts-flask / validate (push) Successful in 0s
This commit is contained in:
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
"""Конфигурация приложения — все настройки в одном месте."""
|
"""Конфигурация приложения — все настройки в одном месте."""
|
||||||
import os
|
import os
|
||||||
|
|
||||||
VERSION = "2.0.1"
|
VERSION = "2.0.2"
|
||||||
|
|
||||||
LLM_URL = os.getenv("LLM_API_URL", "https://api.aillm.ru/v1/chat/completions")
|
LLM_URL = os.getenv("LLM_API_URL", "https://api.aillm.ru/v1/chat/completions")
|
||||||
LLM_KEY = os.getenv("LLM_API_KEY", "")
|
LLM_KEY = os.getenv("LLM_API_KEY", "")
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
"""Contracts CRUD."""
|
"""Contracts CRUD."""
|
||||||
from db.connection import query, execute, execute_returning
|
import uuid
|
||||||
|
from db.connection import query, execute
|
||||||
|
|
||||||
|
|
||||||
def insert(number, client=""):
|
def insert(number, client=""):
|
||||||
return execute_returning(
|
cid = str(uuid.uuid4())
|
||||||
"INSERT INTO contracts (number, client) VALUES (%s, %s) RETURNING *",
|
execute(
|
||||||
(number, client),
|
"INSERT INTO contracts (id, number, client) VALUES (%s, %s, %s)",
|
||||||
|
(cid, number, client),
|
||||||
)
|
)
|
||||||
|
return get(cid)
|
||||||
|
|
||||||
|
|
||||||
def get(contract_id):
|
def get(contract_id):
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
"""Documents CRUD."""
|
"""Documents CRUD."""
|
||||||
|
import uuid
|
||||||
from db.connection import query, execute, execute_returning
|
from db.connection import query, execute, execute_returning
|
||||||
|
|
||||||
|
|
||||||
def insert(filename, mime_type, original_bytes, status="uploaded", batch_id=None, zip_source=None, content_hash=None):
|
def insert(filename, mime_type, original_bytes, status="uploaded", batch_id=None, zip_source=None, content_hash=None):
|
||||||
"""Insert document, return row dict."""
|
"""Insert document, return row dict."""
|
||||||
return execute_returning(
|
doc_id = str(uuid.uuid4())
|
||||||
"""INSERT INTO documents (filename, mime_type, original_bytes, status, batch_id, zip_source, content_hash)
|
execute(
|
||||||
VALUES (%s, %s, %s, %s, %s, %s, %s) RETURNING *""",
|
"""INSERT INTO documents (id, filename, mime_type, original_bytes, status, batch_id, zip_source, content_hash)
|
||||||
(filename, mime_type, original_bytes, status, batch_id, zip_source, content_hash),
|
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)""",
|
||||||
|
(doc_id, filename, mime_type, original_bytes, status, batch_id, zip_source, content_hash),
|
||||||
)
|
)
|
||||||
|
return get(doc_id)
|
||||||
|
|
||||||
|
|
||||||
def get(doc_id):
|
def get(doc_id):
|
||||||
|
|||||||
+12
-9
@@ -1,5 +1,6 @@
|
|||||||
"""Prompts CRUD."""
|
"""Prompts CRUD."""
|
||||||
from db.connection import query, execute, execute_returning
|
import uuid
|
||||||
|
from db.connection import query, execute
|
||||||
|
|
||||||
|
|
||||||
def _serialize(row):
|
def _serialize(row):
|
||||||
@@ -46,8 +47,8 @@ def seed_defaults():
|
|||||||
"ТЕКСТ ДОКУМЕНТА:\n---\n{doc_text}\n---"
|
"ТЕКСТ ДОКУМЕНТА:\n---\n{doc_text}\n---"
|
||||||
)
|
)
|
||||||
execute(
|
execute(
|
||||||
"INSERT INTO prompts (role, name, body, is_active, notes) VALUES (%s, %s, %s, %s, %s)",
|
"INSERT INTO prompts (id, role, name, body, is_active, notes) VALUES (%s, %s, %s, %s, %s, %s)",
|
||||||
("extract", "default-v1", extract_body, True, "Авто-создан из llm_prompt.py _build_initial"),
|
(str(uuid.uuid4()), "extract", "default-v1", extract_body, True, "Авто-создан из llm_prompt.py _build_initial"),
|
||||||
)
|
)
|
||||||
|
|
||||||
if "diff" not in existing_roles:
|
if "diff" not in existing_roles:
|
||||||
@@ -75,8 +76,8 @@ def seed_defaults():
|
|||||||
"ТЕКСТ ДОПСОГЛАШЕНИЯ:\n---\n{doc_text}\n---"
|
"ТЕКСТ ДОПСОГЛАШЕНИЯ:\n---\n{doc_text}\n---"
|
||||||
)
|
)
|
||||||
execute(
|
execute(
|
||||||
"INSERT INTO prompts (role, name, body, is_active, notes) VALUES (%s, %s, %s, %s, %s)",
|
"INSERT INTO prompts (id, role, name, body, is_active, notes) VALUES (%s, %s, %s, %s, %s, %s)",
|
||||||
("diff", "default-v1", diff_body, True, "Авто-создан из llm_prompt.py _build_diff"),
|
(str(uuid.uuid4()), "diff", "default-v1", diff_body, True, "Авто-создан из llm_prompt.py _build_diff"),
|
||||||
)
|
)
|
||||||
_ensure_classify_prompt()
|
_ensure_classify_prompt()
|
||||||
|
|
||||||
@@ -97,11 +98,13 @@ def save_new_version(role, name, body, notes="", is_active=True):
|
|||||||
"""Save new prompt version. Deactivates all others for this role, inserts new one."""
|
"""Save new prompt version. Deactivates all others for this role, inserts new one."""
|
||||||
if is_active:
|
if is_active:
|
||||||
execute("UPDATE prompts SET is_active=false WHERE role=%s", (role,))
|
execute("UPDATE prompts SET is_active=false WHERE role=%s", (role,))
|
||||||
return execute_returning(
|
pid = str(uuid.uuid4())
|
||||||
"""INSERT INTO prompts (role, name, body, is_active, notes)
|
execute(
|
||||||
VALUES (%s, %s, %s, %s, %s) RETURNING *""",
|
"""INSERT INTO prompts (id, role, name, body, is_active, notes)
|
||||||
(role, name, body, is_active, notes),
|
VALUES (%s, %s, %s, %s, %s, %s)""",
|
||||||
|
(pid, role, name, body, is_active, notes),
|
||||||
)
|
)
|
||||||
|
return get(pid)
|
||||||
|
|
||||||
|
|
||||||
def activate(prompt_id):
|
def activate(prompt_id):
|
||||||
|
|||||||
+20
-20
@@ -40,11 +40,11 @@ def apply_ops(contract_id, supplement_id, document_id, ops, prompt_id, raw_llm_r
|
|||||||
continue
|
continue
|
||||||
name_hash = _hash(name, nr.get("date_start"))
|
name_hash = _hash(name, nr.get("date_start"))
|
||||||
execute(
|
execute(
|
||||||
"""INSERT INTO spec_events (contract_id, supplement_id, seq, action, target_hash,
|
"""INSERT INTO spec_events (id, contract_id, supplement_id, seq, action, target_hash,
|
||||||
new_values, comment, status, prompt_version, source_document_id, raw_llm_response)
|
new_values, comment, status, prompt_version, source_document_id, raw_llm_response)
|
||||||
VALUES (%s, %s, %s, 'ADD', %s, %s, %s, 'applied', %s, %s, %s)""",
|
VALUES (%s, %s, %s, %s, 'ADD', %s, %s, %s, 'applied', %s, %s, %s)""",
|
||||||
(
|
(
|
||||||
contract_id, supplement_id, seq, name_hash,
|
str(uuid.uuid4()), contract_id, supplement_id, seq, name_hash,
|
||||||
json.dumps(nr, ensure_ascii=False),
|
json.dumps(nr, ensure_ascii=False),
|
||||||
op.get("comment", ""), prompt_id, document_id,
|
op.get("comment", ""), prompt_id, document_id,
|
||||||
json.dumps(raw_llm_response, ensure_ascii=False),
|
json.dumps(raw_llm_response, ensure_ascii=False),
|
||||||
@@ -62,11 +62,11 @@ def apply_ops(contract_id, supplement_id, document_id, ops, prompt_id, raw_llm_r
|
|||||||
seq += 1
|
seq += 1
|
||||||
continue
|
continue
|
||||||
execute(
|
execute(
|
||||||
"""INSERT INTO spec_events (contract_id, supplement_id, seq, action, target_hash,
|
"""INSERT INTO spec_events (id, contract_id, supplement_id, seq, action, target_hash,
|
||||||
new_values, comment, status, prompt_version, source_document_id, raw_llm_response)
|
new_values, comment, status, prompt_version, source_document_id, raw_llm_response)
|
||||||
VALUES (%s, %s, %s, 'UPDATE', %s, %s, %s, 'applied', %s, %s, %s)""",
|
VALUES (%s, %s, %s, %s, 'UPDATE', %s, %s, %s, 'applied', %s, %s, %s)""",
|
||||||
(
|
(
|
||||||
contract_id, supplement_id, seq, th,
|
str(uuid.uuid4()), contract_id, supplement_id, seq, th,
|
||||||
json.dumps(nv, ensure_ascii=False),
|
json.dumps(nv, ensure_ascii=False),
|
||||||
op.get("comment", ""), prompt_id, document_id,
|
op.get("comment", ""), prompt_id, document_id,
|
||||||
json.dumps(raw_llm_response, ensure_ascii=False),
|
json.dumps(raw_llm_response, ensure_ascii=False),
|
||||||
@@ -83,11 +83,11 @@ def apply_ops(contract_id, supplement_id, document_id, ops, prompt_id, raw_llm_r
|
|||||||
seq += 1
|
seq += 1
|
||||||
continue
|
continue
|
||||||
execute(
|
execute(
|
||||||
"""INSERT INTO spec_events (contract_id, supplement_id, seq, action, target_hash,
|
"""INSERT INTO spec_events (id, contract_id, supplement_id, seq, action, target_hash,
|
||||||
new_values, comment, status, prompt_version, source_document_id, raw_llm_response)
|
new_values, comment, status, prompt_version, source_document_id, raw_llm_response)
|
||||||
VALUES (%s, %s, %s, 'DELETE', %s, %s, %s, 'applied', %s, %s, %s)""",
|
VALUES (%s, %s, %s, %s, 'DELETE', %s, %s, %s, 'applied', %s, %s, %s)""",
|
||||||
(
|
(
|
||||||
contract_id, supplement_id, seq, th,
|
str(uuid.uuid4()), contract_id, supplement_id, seq, th,
|
||||||
json.dumps({}), op.get("comment", ""),
|
json.dumps({}), op.get("comment", ""),
|
||||||
prompt_id, document_id,
|
prompt_id, document_id,
|
||||||
json.dumps(raw_llm_response, ensure_ascii=False),
|
json.dumps(raw_llm_response, ensure_ascii=False),
|
||||||
@@ -100,11 +100,11 @@ def apply_ops(contract_id, supplement_id, document_id, ops, prompt_id, raw_llm_r
|
|||||||
elif action == "UNRESOLVED":
|
elif action == "UNRESOLVED":
|
||||||
# Log but don't apply
|
# Log but don't apply
|
||||||
execute(
|
execute(
|
||||||
"""INSERT INTO spec_events (contract_id, supplement_id, seq, action, target_hash,
|
"""INSERT INTO spec_events (id, contract_id, supplement_id, seq, action, target_hash,
|
||||||
new_values, comment, status, prompt_version, source_document_id, raw_llm_response)
|
new_values, comment, status, prompt_version, source_document_id, raw_llm_response)
|
||||||
VALUES (%s, %s, %s, 'UNRESOLVED', %s, %s, %s, 'unresolved', %s, %s, %s)""",
|
VALUES (%s, %s, %s, %s, 'UNRESOLVED', %s, %s, %s, 'unresolved', %s, %s, %s)""",
|
||||||
(
|
(
|
||||||
contract_id, supplement_id, seq,
|
str(uuid.uuid4()), contract_id, supplement_id, seq,
|
||||||
op.get("target_hash", ""),
|
op.get("target_hash", ""),
|
||||||
json.dumps(op.get("new_values", {}), ensure_ascii=False),
|
json.dumps(op.get("new_values", {}), ensure_ascii=False),
|
||||||
op.get("reason", op.get("comment", "")),
|
op.get("reason", op.get("comment", "")),
|
||||||
@@ -125,11 +125,11 @@ def apply_ops(contract_id, supplement_id, document_id, ops, prompt_id, raw_llm_r
|
|||||||
def _log_unresolved(contract_id, supplement_id, seq, op, prompt_id, document_id, raw_llm_response, reason):
|
def _log_unresolved(contract_id, supplement_id, seq, op, prompt_id, document_id, raw_llm_response, reason):
|
||||||
"""Log an op as UNRESOLVED instead of silently ignoring it."""
|
"""Log an op as UNRESOLVED instead of silently ignoring it."""
|
||||||
execute(
|
execute(
|
||||||
"""INSERT INTO spec_events (contract_id, supplement_id, seq, action, target_hash,
|
"""INSERT INTO spec_events (id, contract_id, supplement_id, seq, action, target_hash,
|
||||||
new_values, comment, status, prompt_version, source_document_id, raw_llm_response)
|
new_values, comment, status, prompt_version, source_document_id, raw_llm_response)
|
||||||
VALUES (%s, %s, %s, 'UNRESOLVED', %s, %s, %s, 'unresolved', %s, %s, %s)""",
|
VALUES (%s, %s, %s, %s, 'UNRESOLVED', %s, %s, %s, 'unresolved', %s, %s, %s)""",
|
||||||
(
|
(
|
||||||
contract_id, supplement_id, seq,
|
str(uuid.uuid4()), contract_id, supplement_id, seq,
|
||||||
op.get("target_hash", ""),
|
op.get("target_hash", ""),
|
||||||
json.dumps(op.get("new_values", op.get("new_row", {})) or {}, ensure_ascii=False),
|
json.dumps(op.get("new_values", op.get("new_row", {})) or {}, ensure_ascii=False),
|
||||||
reason,
|
reason,
|
||||||
@@ -159,16 +159,16 @@ def _upsert_spec_current(contract_id, name_hash, row):
|
|||||||
)
|
)
|
||||||
if existing:
|
if existing:
|
||||||
execute(
|
execute(
|
||||||
"""UPDATE spec_current SET name=%s, price=%s, qty=%s, sum=%s, date_start=%s, updated_at=now()
|
"""UPDATE spec_current SET name=%s, price=%s, qty=%s, sum=%s, date_start=%s, updated_at=datetime('now')
|
||||||
WHERE contract_id=%s AND name_hash=%s""",
|
WHERE contract_id=%s AND name_hash=%s""",
|
||||||
(row.get("name"), row.get("price"), row.get("qty"), row.get("sum"),
|
(row.get("name"), row.get("price"), row.get("qty"), row.get("sum"),
|
||||||
row.get("date_start"), contract_id, name_hash),
|
row.get("date_start"), contract_id, name_hash),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
execute(
|
execute(
|
||||||
"""INSERT INTO spec_current (contract_id, name_hash, name, price, qty, sum, date_start)
|
"""INSERT INTO spec_current (id, contract_id, name_hash, name, price, qty, sum, date_start)
|
||||||
VALUES (%s, %s, %s, %s, %s, %s, %s)""",
|
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)""",
|
||||||
(contract_id, name_hash, row.get("name"), row.get("price"),
|
(str(uuid.uuid4()), contract_id, name_hash, row.get("name"), row.get("price"),
|
||||||
row.get("qty"), row.get("sum"), row.get("date_start")),
|
row.get("qty"), row.get("sum"), row.get("date_start")),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -182,7 +182,7 @@ def _update_spec_current(contract_id, name_hash, new_values):
|
|||||||
sets.append(f"{field} = %s")
|
sets.append(f"{field} = %s")
|
||||||
params.append(new_values[field])
|
params.append(new_values[field])
|
||||||
if sets:
|
if sets:
|
||||||
sets.append("updated_at = now()")
|
sets.append("updated_at = datetime('now')")
|
||||||
params.extend([contract_id, name_hash])
|
params.extend([contract_id, name_hash])
|
||||||
execute(
|
execute(
|
||||||
f"UPDATE spec_current SET {', '.join(sets)} WHERE contract_id = %s AND name_hash = %s",
|
f"UPDATE spec_current SET {', '.join(sets)} WHERE contract_id = %s AND name_hash = %s",
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
"""Supplements CRUD."""
|
"""Supplements CRUD."""
|
||||||
from db.connection import query, execute, execute_returning
|
import uuid
|
||||||
|
from db.connection import query, execute
|
||||||
|
|
||||||
|
|
||||||
def insert(contract_id, document_id, supp_type="additional"):
|
def insert(contract_id, document_id, supp_type="additional"):
|
||||||
return execute_returning(
|
sid = str(uuid.uuid4())
|
||||||
"""INSERT INTO supplements (contract_id, document_id, type)
|
execute(
|
||||||
VALUES (%s, %s, %s) RETURNING *""",
|
"""INSERT INTO supplements (id, contract_id, document_id, type)
|
||||||
(contract_id, document_id, supp_type),
|
VALUES (%s, %s, %s, %s)""",
|
||||||
|
(sid, contract_id, document_id, supp_type),
|
||||||
)
|
)
|
||||||
|
return get(sid)
|
||||||
|
|
||||||
|
|
||||||
def list_by_contract(contract_id):
|
def list_by_contract(contract_id):
|
||||||
|
|||||||
@@ -73,7 +73,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<div class="topbar">
|
<div class="topbar">
|
||||||
<img src="/static/logo.svg" alt="Nubes">
|
<img src="/static/logo.svg" alt="Nubes">
|
||||||
<span class="title">Сверка договоров — LLM AI-driven Event Sourcing <span style="font-weight:400;color:var(--muted);font-size:12px;">v2.0.1</span></span>
|
<span class="title">Сверка договоров — LLM AI-driven Event Sourcing <span style="font-weight:400;color:var(--muted);font-size:12px;">v2.0.2</span></span>
|
||||||
<div id="pipelineStepper" style="display:flex;gap:8px;font-size:11px;align-items:center;color:var(--muted);">
|
<div id="pipelineStepper" style="display:flex;gap:8px;font-size:11px;align-items:center;color:var(--muted);">
|
||||||
<span id="stepUpload">○ Загрузка</span><span>→</span>
|
<span id="stepUpload">○ Загрузка</span><span>→</span>
|
||||||
<span id="stepClassify">○ Классификация</span><span>→</span>
|
<span id="stepClassify">○ Классификация</span><span>→</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user