63 lines
2.6 KiB
Python
63 lines
2.6 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
|
|
from app.modules.rag.explain.models import ExplainPack
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class EvidenceGateDecision:
|
|
passed: bool
|
|
answer: str = ""
|
|
diagnostics: dict[str, list[str]] = field(default_factory=dict)
|
|
|
|
|
|
class CodeExplainEvidenceGate:
|
|
def __init__(self, min_excerpts: int = 2) -> None:
|
|
self._min_excerpts = min_excerpts
|
|
|
|
def evaluate(self, pack: ExplainPack) -> EvidenceGateDecision:
|
|
diagnostics = self._diagnostics(pack)
|
|
if len(pack.code_excerpts) >= self._min_excerpts:
|
|
return EvidenceGateDecision(passed=True, diagnostics=diagnostics)
|
|
return EvidenceGateDecision(
|
|
passed=False,
|
|
answer=self._build_answer(pack, diagnostics),
|
|
diagnostics=diagnostics,
|
|
)
|
|
|
|
def _diagnostics(self, pack: ExplainPack) -> dict[str, list[str]]:
|
|
return {
|
|
"entrypoints": [item.title for item in pack.selected_entrypoints[:3] if item.title],
|
|
"symbols": [item.title for item in pack.seed_symbols[:5] if item.title],
|
|
"paths": self._paths(pack),
|
|
"missing": list(pack.missing),
|
|
}
|
|
|
|
def _paths(self, pack: ExplainPack) -> list[str]:
|
|
values: list[str] = []
|
|
for item in pack.selected_entrypoints + pack.seed_symbols:
|
|
path = item.source or (item.location.path if item.location else "")
|
|
if path and path not in values:
|
|
values.append(path)
|
|
for excerpt in pack.code_excerpts:
|
|
if excerpt.path and excerpt.path not in values:
|
|
values.append(excerpt.path)
|
|
return values[:6]
|
|
|
|
def _build_answer(self, pack: ExplainPack, diagnostics: dict[str, list[str]]) -> str:
|
|
lines = [
|
|
"Недостаточно опоры в коде, чтобы дать объяснение без догадок.",
|
|
"",
|
|
f"Найдено фрагментов кода: {len(pack.code_excerpts)} из {self._min_excerpts} минимально необходимых.",
|
|
]
|
|
if diagnostics["paths"]:
|
|
lines.append(f"Пути: {', '.join(diagnostics['paths'])}")
|
|
if diagnostics["entrypoints"]:
|
|
lines.append(f"Entrypoints: {', '.join(diagnostics['entrypoints'])}")
|
|
if diagnostics["symbols"]:
|
|
lines.append(f"Символы: {', '.join(diagnostics['symbols'])}")
|
|
if diagnostics["missing"]:
|
|
lines.append(f"Диагностика: {', '.join(diagnostics['missing'])}")
|
|
return "\n".join(lines).strip()
|