feat(etl): stable pipeline, exception registry in SQLite, multi-pass aggregation and db_cli
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
"""
|
||||
===============================================================================
|
||||
FILE: services/prompts/diff_engine.py
|
||||
PROJECT: SCUD Orion AI (Unified Architecture)
|
||||
MODULE: services / prompts
|
||||
ROLE: Формирование превью изменений промпта и генерация визуального HTML-Diff.
|
||||
|
||||
AI-CONTEXT-ANCHORS:
|
||||
- ANCHOR[PROMPT_DIFF_BUILDER]: Генерация черновика и HTML-разметки изменений.
|
||||
===============================================================================
|
||||
"""
|
||||
|
||||
from typing import Tuple, Dict, List, Set
|
||||
from core.connection import get_connection
|
||||
|
||||
def build_prompt_diff(
|
||||
action: str,
|
||||
section_id: int = None,
|
||||
item_id: int = None,
|
||||
content: str = "",
|
||||
delete_nodes: List[Tuple[int, int]] = None,
|
||||
prompt_name: str = "main_agent"
|
||||
) -> Tuple[str, str]:
|
||||
act = (action or "ADD").upper()
|
||||
nodes_to_delete: Set[Tuple[int, int]] = set()
|
||||
|
||||
if delete_nodes:
|
||||
nodes_to_delete.update(delete_nodes)
|
||||
elif act == "DELETE" and section_id is not None and item_id is not None:
|
||||
nodes_to_delete.add((section_id, item_id))
|
||||
|
||||
with get_connection(row_factory=True) as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("""
|
||||
SELECT section_id, item_id, content
|
||||
FROM system_prompt_nodes
|
||||
WHERE prompt_name = ? AND is_active = 1
|
||||
ORDER BY section_id, item_id
|
||||
""", (prompt_name,))
|
||||
existing_nodes = cursor.fetchall()
|
||||
|
||||
nodes_dict = {(r["section_id"], r["item_id"]): r["content"] for r in existing_nodes}
|
||||
nodes_dict_for_draft = {k: v for k, v in nodes_dict.items() if k not in nodes_to_delete}
|
||||
|
||||
if act not in ["DELETE", "BATCH_DELETE"] and section_id is not None and item_id is not None:
|
||||
nodes_dict_for_draft[(section_id, item_id)] = content
|
||||
|
||||
draft_lines = []
|
||||
curr_sec = None
|
||||
for (s_id, i_id), txt in sorted(nodes_dict_for_draft.items()):
|
||||
if i_id == 0:
|
||||
if curr_sec is not None: draft_lines.append("")
|
||||
draft_lines.append(f"{s_id}. {txt}")
|
||||
curr_sec = s_id
|
||||
else:
|
||||
draft_lines.append(f" {s_id}.{i_id}. {txt}")
|
||||
merged_prompt = "\n".join(draft_lines)
|
||||
|
||||
diff_lines = []
|
||||
curr_sec = None
|
||||
display_nodes = dict(nodes_dict)
|
||||
if act not in ["DELETE", "BATCH_DELETE"] and section_id is not None and item_id is not None:
|
||||
display_nodes[(section_id, item_id)] = content
|
||||
|
||||
for (s_id, i_id), txt in sorted(display_nodes.items()):
|
||||
if i_id == 0:
|
||||
if curr_sec is not None: diff_lines.append("")
|
||||
diff_lines.append(f"{s_id}. {txt}")
|
||||
curr_sec = s_id
|
||||
else:
|
||||
if (s_id, i_id) in nodes_to_delete:
|
||||
line_str = f' <span class="line-through text-rose-600 font-bold bg-rose-50 px-1.5 py-0.5 rounded border border-rose-300 opacity-80">{s_id}.{i_id}. {txt} [УДАЛЕНИЕ]</span>'
|
||||
elif act == "ADD" and s_id == section_id and i_id == item_id:
|
||||
line_str = f' <span class="text-rose-600 font-bold bg-rose-50 px-1.5 py-0.5 rounded border border-rose-300">{s_id}.{i_id}. {txt}</span>'
|
||||
else:
|
||||
line_str = f" {s_id}.{i_id}. {txt}"
|
||||
diff_lines.append(line_str)
|
||||
|
||||
return merged_prompt, "\n".join(diff_lines)
|
||||
Reference in New Issue
Block a user