-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrunner.py
More file actions
96 lines (72 loc) · 3.32 KB
/
Copy pathrunner.py
File metadata and controls
96 lines (72 loc) · 3.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
"""Single-case runner for the Financial Links vertical slice.
The runner is the public Python API used by ``scripts/run_case.py``,
``scripts/run_eval.py``, and the eval-loop tests. Its execution path
is graph-backed (see ``app.graph``): every case flows through
``IntakeNormalizer → OrchestratorAgent → FinancialLinksReliabilityAgent
→ EvaluatorNode → HumanApprovalNode? → FinalResponseComposer``. The
graph itself is deterministic and never calls an external API or model.
Public surface:
- ``run_case(case_dict, ...)`` — runs one case and returns a ``RunResult``
wrapping the ``AgentOutput`` and the ``TraceRecord``.
- ``load_default_approval_matrix()`` — reads ``configs/approval_matrix.yaml``.
The function signature and ``RunResult`` shape are preserved across
the graph migration so existing callers and tests keep working.
"""
from __future__ import annotations
import uuid
from pathlib import Path
from typing import Any
import yaml
from pydantic import BaseModel
from app.agents.profiles import DEFAULT_PROFILE, normalize_profile
from app.graph import invoke_graph
from app.schemas import AgentOutput, TraceRecord
REPO_ROOT = Path(__file__).resolve().parents[1]
_APPROVAL_MATRIX_PATH = REPO_ROOT / "configs" / "approval_matrix.yaml"
class RunResult(BaseModel):
"""Wraps the trace and the underlying agent output from one run."""
trace: TraceRecord
agent_output: AgentOutput
def load_default_approval_matrix() -> dict[str, Any]:
return yaml.safe_load(_APPROVAL_MATRIX_PATH.read_text())
def run_case(
case_dict: dict[str, Any],
approval_matrix: dict[str, Any] | None = None,
*,
agent_system_version: str = DEFAULT_PROFILE.value,
policy_version: str = "financial_links_policies_v0",
dataset_id: str | None = None,
) -> RunResult:
"""Run one Financial Links case end-to-end through the graph.
``agent_system_version`` selects the agent-system profile (see
``app.agents.profiles``); the value is also recorded on the trace.
Deterministic. No external API, model, or service is called. All
tool calls are synthetic.
"""
profile = normalize_profile(agent_system_version)
matrix = approval_matrix or load_default_approval_matrix()
final_state = invoke_graph(case_dict, profile=profile, approval_matrix=matrix)
case = final_state["case"]
agent_output: AgentOutput = final_state["agent_output"]
dataset_id_value = dataset_id or case_dict.get("dataset_id") or "unknown_dataset"
trace = TraceRecord(
trace_id=str(uuid.uuid4()),
dataset_id=dataset_id_value,
case_id=case.case_id,
workflow=case.workflow,
risk_band=case.risk_band,
agent_system_version=profile,
policy_version=policy_version,
orchestrator_decision=final_state["orchestrator_decision"],
specialist_path=list(final_state.get("specialist_path", [])),
handoff=final_state["handoff"],
tool_calls=list(agent_output.tool_calls),
evaluator_report=final_state["evaluator_report"],
approval=final_state.get("approval", agent_output.approval),
final_response=final_state.get("final_response", agent_output.draft_text),
grader_results=[],
failure_labels=[],
latency_ms=0,
est_cost_usd=agent_output.est_cost_usd,
)
return RunResult(trace=trace, agent_output=agent_output)