Watch
1
0
Fork
You've already forked Seyyed_arc
0
forked from hesabix/arc
Seyyed_arc/hesabixAPI/app/services/ai/ai_content_sanitize.py
Babak Alizadeh 0c4079d765 fix(ai): evidence-based agent loop without semantic regex on model text
Replace regex/LLM shims for continue/stop decisions with structural evidence
(API tool_calls, Harmony parser, ObservationStore). Add DB regression fixtures
and remove unused aux.agent_continuation prompt.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-16 09:44:43 +00:00

105 lines
3.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
پاک‌سازی خروجی مدل — حذف توکن‌های Harmony و بازیابی tool callهای نشت‌کرده.
تنها پارس پروتکل Harmony (فرمت ثابت API) — بدون حدس intent از متن طبیعی.
"""
from __future__ import annotations
import json
import re
import uuid
from typing import Any, Dict, List, Optional
# فرمت ثابت نشت tool call در متن Harmony (پروتکل مدل، نه semantics)
_HARMONY_TOOL_LEAK = re.compile(
r"<\|start\|>assistant<\|channel\|>commentary"
r"(?:\s+to=functions\.(\w+))?"
r"(?:\s*<\|constrain\|>\w+)?"
r"<\|message\|>(\{.*?\})<\|call\|>",
re.DOTALL,
)
_HARMONY_CONTROL_TOKEN = re.compile(
r"<\|(?:start|end|channel|message|call|constrain)\|>[^<\n]*"
)
_HARMONY_TAIL = re.compile(r"<\|start\|>.*", re.DOTALL)
def extract_leaked_function_calls(text: str) -> List[Dict[str, Any]]:
"""استخراج tool callهای نشت‌کرده از فرمت Harmony در متن."""
if not text:
return []
calls: List[Dict[str, Any]] = []
seen: set[str] = set()
for match in _HARMONY_TOOL_LEAK.finditer(text):
name = (match.group(1) or "").strip()
raw_json = (match.group(2) or "").strip()
if not raw_json:
continue
try:
arguments = json.loads(raw_json)
except json.JSONDecodeError:
continue
if not isinstance(arguments, dict):
continue
if not name:
inferred = arguments.pop("name", None) or arguments.pop("tool", None)
if isinstance(inferred, str) and inferred.strip():
name = inferred.strip()
if not name:
continue
dedupe_key = f"{name}:{json.dumps(arguments, sort_keys=True, ensure_ascii=False)}"
if dedupe_key in seen:
continue
seen.add(dedupe_key)
calls.append(
{
"id": f"leaked_{uuid.uuid4().hex[:12]}",
"name": name,
"arguments": arguments,
}
)
return calls
def resolve_round_function_calls(
*,
api_function_calls: Optional[List[Dict[str, Any]]],
round_text: str,
round_reasoning: str,
) -> Optional[List[Dict[str, Any]]]:
"""ترکیب tool_calls API با recovery پروتکل Harmony — بدون infer از متن طبیعی."""
if api_function_calls:
return api_function_calls
for source in (round_text, round_reasoning):
leaked = extract_leaked_function_calls(source or "")
if leaked:
return leaked
return None
def sanitize_assistant_content(text: str) -> str:
"""حذف توکن‌های Harmony و نشت tool call از متن قابل‌نمایش."""
if not text:
return text
cleaned = _HARMONY_TOOL_LEAK.sub("", text)
cleaned = _HARMONY_TAIL.sub("", cleaned)
cleaned = _HARMONY_CONTROL_TOKEN.sub("", cleaned)
cleaned = re.sub(r"[ \t]+\n", "\n", cleaned)
cleaned = re.sub(r"\n{3,}", "\n\n", cleaned)
return cleaned.strip()
def prepare_assistant_content_for_persist(
accumulated_content: str,
trace_steps: Optional[List[Dict[str, Any]]],
) -> str:
"""ترکیب متن stream/trace و پاک‌سازی قبل از ذخیره."""
from app.services.ai.ai_trace import merge_accumulated_and_trace_content
merged = merge_accumulated_and_trace_content(
accumulated_content or "",
trace_steps,
)
return sanitize_assistant_content(merged)