feat(matching): implement two-stage matching with DeepSeek arbiter, fail-stop guard, and zero-probability filter

This commit is contained in:
2026-10-16 03:13:21 +03:30
parent 9e848f535f
commit 787824a19e
6 changed files with 475 additions and 48 deletions
+18 -6
View File
@@ -13,7 +13,8 @@ import logging
from app import drafts as draft_store
from app import observability as obs
from app.config import settings
from app.nlu import understand
from app.fallback_matcher import MatchingFailureError
from app.nlu import NLUFailureError, understand
from app.runtime import BotContext, LinkedUser
from app.storage import save_proforma_file
from app.stt import transcribe, transcribe_multi
@@ -222,23 +223,34 @@ async def handle_message(ctx: BotContext, chat_id: int, message: dict) -> None:
draft_summary = _draft_summary(target_draft) if target_draft else None
input_payload = voice_transcripts if voice_transcripts else text
result = await understand(settings, input_payload, draft_summary, trace_id=trace_id)
try:
result = await understand(settings, input_payload, draft_summary, trace_id=trace_id)
except (MatchingFailureError, NLUFailureError):
logger.error("NLU processing failed completely (Universal Fail-Stop Guard)")
await ctx.send(
chat_id,
"⚠️ سامانه در پردازش هوشمند موجودیت‌ها با اختلال مواجه شد. لطفاً دوباره پیام را ارسال کنید.",
reply_to=message_id,
)
return
intent, patch = result.get("intent"), result.get("patch") or {}
consensus_text = result.get("consensus_text") or text
consensus_text = result.get("consensus_text") or (text if isinstance(text, str) else "")
mentions = result.get("entity_mentions") or []
await obs.event(trace_id, "entities.extracted",
payload={"patch": patch, "intent": intent, "entity_mentions": mentions})
# Entity matching (Jev primary, DeepSeek crisis fallback)
# Entity matching (Two-Stage: Jev scorer + DeepSeek final arbiter; DeepSeek crisis fallback if Jev down)
jev_map: dict = {}
if mentions and intent in ("register_quote", "update_draft", "add_material"):
try:
from app import matching
jev_map = await matching.resolve_mentions(
ctx, patch, mentions, trace_id=trace_id, raw_input=input_payload
ctx, patch, mentions, trace_id=trace_id, raw_input=input_payload,
consensus_text=consensus_text,
)
except matching.MatchingFailureError:
logger.error("entity matching failed completely (crisis fallback failed)")
logger.error("entity matching failed completely (Universal Fail-Stop Guard)")
await ctx.send(
chat_id,
"⚠️ سامانه در پردازش هوشمند موجودیت‌ها با اختلال مواجه شد. لطفاً دوباره پیام را ارسال کنید.",