Фикс состояния

This commit is contained in:
2026-03-12 16:55:23 +03:00
parent 417b8b6f72
commit 6ba0a18ac9
1445 changed files with 620025 additions and 885 deletions

View File

@@ -0,0 +1,120 @@
"""Diagnostics for the CODE_QA pipeline: Level 1 summary and Level 2 detail."""
from __future__ import annotations
from typing import Any
from app.modules.rag.code_qa_pipeline.contracts import (
DiagnosticsReport,
EvidenceBundle,
RetrievalRequest,
RetrievalResult,
RouterResult,
)
def build_diagnostics_report(
*,
router_result: RouterResult,
retrieval_request: RetrievalRequest | None,
retrieval_result: RetrievalResult | None,
evidence_bundle: EvidenceBundle | None,
answer_mode: str = "normal",
timings_ms: dict[str, int] | None = None,
) -> DiagnosticsReport:
"""Build full diagnostics: Level 1 summary + Level 2 detail + failure reasons."""
timings = dict(timings_ms or {})
req = retrieval_request
res = retrieval_result
bundle = evidence_bundle
intent_correct = None
target_found = bool(bundle and bundle.resolved_target)
layers_used = list(req.requested_layers) if req else []
retrieval_sufficient = bool(bundle and bundle.sufficient)
if not retrieval_sufficient and bundle:
answer_mode = "degraded" if bundle.evidence_count else "insufficient"
failure_reasons = list(bundle.failure_reasons) if bundle else []
router_result_dict = _router_result_to_dict(router_result)
retrieval_request_dict = _retrieval_request_to_dict(req) if req else {}
per_layer = []
if res:
for o in res.layer_outcomes:
per_layer.append({
"layer_id": o.layer_id,
"hit_count": o.hit_count,
"empty": o.empty,
"fallback_used": o.fallback_used,
})
empty_layers = list(res.missing_layers) if res else []
evidence_gate_decision = {}
if bundle is not None:
evidence_gate_decision = {
"sufficient": bundle.sufficient,
"failure_reasons": list(bundle.failure_reasons),
"evidence_count": bundle.evidence_count,
}
return DiagnosticsReport(
intent_correct=intent_correct,
target_found=target_found,
layers_used=layers_used,
retrieval_sufficient=retrieval_sufficient,
answer_mode=answer_mode,
router_result=router_result_dict,
retrieval_request=retrieval_request_dict,
per_layer_outcome=per_layer,
empty_layers=empty_layers,
evidence_gate_decision=evidence_gate_decision,
failure_reasons=failure_reasons,
timings_ms=timings,
)
def build_level1_summary(report: DiagnosticsReport) -> dict[str, Any]:
"""Human-readable summary: intent, target, layers, sufficiency, answer mode."""
return {
"intent_correct": report.intent_correct,
"target_found": report.target_found,
"layers_used": report.layers_used,
"retrieval_sufficient": report.retrieval_sufficient,
"answer_mode": report.answer_mode,
"failure_reasons": report.failure_reasons,
}
def build_level2_detail(report: DiagnosticsReport) -> dict[str, Any]:
"""Detailed diagnostics for tuning and tests."""
return {
"router_result": report.router_result,
"retrieval_request": report.retrieval_request,
"per_layer_outcome": report.per_layer_outcome,
"empty_layers": report.empty_layers,
"evidence_gate_decision": report.evidence_gate_decision,
"failure_reasons": report.failure_reasons,
"timings_ms": report.timings_ms,
}
def _router_result_to_dict(r: RouterResult) -> dict[str, Any]:
return {
"intent": r.intent,
"graph_id": r.graph_id,
"conversation_mode": r.conversation_mode,
"retrieval_profile": r.retrieval_profile,
"sub_intent": r.query_plan.sub_intent if r.query_plan else None,
"path_scope": list(getattr(r.retrieval_spec.filters, "path_scope", []) or []),
"layers": [str(q.layer_id) for q in (r.retrieval_spec.layer_queries or [])],
"symbol_resolution_status": r.symbol_resolution.status if r.symbol_resolution else None,
}
def _retrieval_request_to_dict(req: RetrievalRequest) -> dict[str, Any]:
return {
"rag_session_id": req.rag_session_id,
"query": req.query,
"sub_intent": req.sub_intent,
"path_scope": list(req.path_scope),
"requested_layers": list(req.requested_layers),
}