Skip to content

Develop#59

Merged
AttiR merged 56 commits into
mainfrom
develop
Jul 2, 2026
Merged

Develop#59
AttiR merged 56 commits into
mainfrom
develop

Conversation

@AttiR

@AttiR AttiR commented Jul 2, 2026

Copy link
Copy Markdown
Owner

No description provided.

AttiR added 30 commits June 26, 2026 10:53
Build the data half of Phase 1: a reproducible generator that turns
real severity-labelled vehicle images into complete multimodal claims
for development and evaluation.

- make_manifest.py: flattens the train/val dataset into one
  severity-balanced pool (40 minor / 40 moderate / 40 severe) and
  writes data/raw/manifest.csv
- policies.py: synthetic auto policies rendered to PDF (the document
  the extractor reads), with deductibles, limits, and exclusions
- notes.py: seeded, deliberately messy adjuster notes (abbreviations,
  missing fields) — deterministic so the dataset is reproducible
- labels.py: deterministic ground-truth decisions derived from
  severity + policy (exclusion -> deny, fraud -> investigate,
  total-loss ratio -> capped payout); three-severity model, no 'total'
- build.py: assembles 80 claims, plants a 15% fraud subset
  (image_reuse / incident_mismatch / pre_existing), writes the
  index/eval split, seed=42

Decision distribution across 80 claims: 57 approve / 12 deny /
11 investigate — all three paths represented for a meaningful eval.

Bulk images and generated claims are gitignored; two sample claims
committed under data/samples/ for tests.
- split multi-import and semicolon/colon one-liners (E401/E701/E702)
- remove unused imports: random (labels), os (embed)
- drop duplicate/unused Langfuse import (extractor)
- add pyproject.toml: pythonpath=["."] so `services` imports, and skip
  integration tests by default via the `integration` marker
- add requirements.txt with runtime deps
- install requirements in CI before running ruff/pytest
- add requirements.txt with runtime deps
- add pyproject.toml: pythonpath=["."] and skip integration tests by default
- CI installs requirements before ruff/pytest
- resolve ruff E401/E701/E702/F401/F811 across data generator and services
feat(index): multimodal embeddings + pinecone store
Embed each index-split claim as image + text vectors (voyage-multimodal-3,
1024-d) and upsert to Pinecone. Eval-split claims are excluded as a leakage
guard. Prints claim/vector counts and index stats.
feat(index): build Pinecone index from generated claims
Query image+text vectors, fuse by best score per claim, return top-k
with outcome metadata + matched_on. Leakage guard verified: eval claims
never indexed, never retrieve themselves. Embedding calls traced.
Closes #N, #N
Constructing the Voyage/Langfuse clients at import time made `from
services.index.embed import DIM` require VOYAGE_API_KEY, breaking pytest
collection in CI. Build clients lazily on first embed instead.
Also split multi-import in test_index.py (ruff E401).
feat(index): dual-vector precedent retrieval + leakage tests
Wrap multimodal precedent retrieval as a FastMCP stdio tool
(find_precedents_tool) returning JSON-safe decision/payout metadata.
Bootstrap repo root onto sys.path and declare deps so  runs
the standalone file; strip tool inputs for robustness. Lazy-init the
Pinecone client so the module imports without credentials.
feat(mcp): precedent server exposing find_precedents over MCP (#15)(#16)
Three FastMCP stdio tools for claim decisioning:
- policy.check_coverage: coverage decision from exclusions + terms
- cost.estimate_repair: repair-cost range from severity and parts
- fraud.fraud_signals: risk score from extraction signals + precedent spread
feat(mcp): add policy, cost, and fraud MCP servers
Four FastMCP servers over stdio (precedent/policy/cost/fraud). Host
launches + discovers tools at runtime, exposes them to Claude, routes
calls, traces the turn. precedent-server wraps Phase-2 retrieval.
Closes #20
Add free tests for policy/cost/fraud tools and pin mcp==1.28.1 so CI can
import the servers. Also split a semicolon statement in demo (ruff E702).
feat(mcp): host discovers 4 servers, Claude-driven tool calls
- state.py: ClaimState TypedDict shared across the graph (inputs,
  per-specialist outputs, recommendation, human gate)
- tools.py: call_tool bridges a node to the MCP host for one tool call
- specialists.py: coverage/cost/precedent/fraud nodes that each fill
  their slice of state
feat(agents): claim state, MCP tool bridge, and specialist nodes
Claude reasons over coverage/cost/fraud/precedent findings via a forced
tool schema and returns a Pydantic-validated Recommendation (decision,
payout range, fraud_risk, confidence, rationale, cited precedent
claim_ids, policy_basis). Traced as agents.synthesise; loads .env so the
clients authenticate. Adds scripts/try_synthesiser.py to exercise it.
feat(agents): synthesiser node producing a validated Recommendation
Specialist tool-callers (coverage/cost/fraud/precedent) over the MCP host
feed an LLM synthesiser that returns a typed Recommendation. Graph pauses
at a human-approval interrupt; only after approval is a tamper-evident
audit entry written. Synthesiser traced; cost = vision+embeddings+1 call.
Closes #27
AttiR added 26 commits June 29, 2026 13:57
feat(agents): LangGraph recommender + human gate + audit
Minor claims produced $0 'approvals' when repair fell below the
deductible — incoherent ground truth that would skew the Phase-5 eval.
Fix: payout <= 0 now denies (reason 'below_deductible'); deductibles
lowered to [100,250,500]. Regenerated data + rebuilt index.
Distribution after fix: 56 approve / 13 deny / 11 investigate; minor
approvals now $100-$1,205.
fix(data): deny below-deductible claims instead of approving for $0
- eval/dataset.py: load split=='eval' claims and assert_integrity()
  (all three decisions present, no $0 approvals, and no eval claim
  leaked into the index)
- stop tracking data/evincta.sqlite (runtime checkpoint store) and
  ignore it
feat(eval): eval-set loader with integrity guards; ignore runtime db
Cost-aware decision accuracy (exact + weighted, penalising dangerous
approve-when-deny/investigate errors most), fraud recall, payout-in-range
for approvals, and Phase-1 extraction accuracy on severity/incident.
feat(eval): scoring metrics for the claims pipeline
The eval surfaced the synthesiser over-investigating (17/18 claims). Root causes found by tracing the held-out set:

1. fraud_risk was a free 'str' field — the model wrote prose instead of the tool's categorical risk. Constrained to a FraudRisk enum.
2. The synthesiser approved excluded claims, ignoring the coverage tool. The prompt now treats coverage.covered=false as an absolute deny gate, applied in priority order (coverage > fraud > deductible > approve).
3. fraud_server flagged 'payout_outlier_vs_precedent' on normal payout variance (and on $0 deny precedents). Removed; not a fraud signal.
4. image_inconsistency was decoupled from fraud risk. It's a data/extraction signal (flows to extraction_confidence/needs_human), not fraud evidence.

Result on the held-out evaluation: weighted decision accuracy 0.722 with zero dangerous (approve-when-deny) errors; payout-in-range 0.769.

feat(eval): add held-out evaluation, asymmetric scoring, and CI gate

Run the 18 eval-split claims through the full Phase-4 graph and score:
- Decision (asymmetric/weighted)
- Fraud recall
- Payout-in-range
- Extraction accuracy

The integrity gate rejects unsound data (leakage or $0 approvals). Operational metrics (cost, p50/p95 latency, escalation rate) are reported. thresholds.yaml now gates the build, and CI fails on regression.

Closes #35
- fix ruff E401/E701/E702/F401 across eval gate/report/run_eval
- pin langgraph + langgraph-checkpoint-sqlite + pyyaml in requirements
- eval workflow gates the committed eval/results.json against thresholds
  instead of running the full (data- and API-dependent) eval in CI
fix(agents): correct synthesiser decision logic
- api/main.py: FastAPI app whose lifespan boots one MCP host (reused
  across requests) and a /health endpoint; dev CORS for the UI
- api/store.py: simple lock-guarded JSON claim store (upsert/get/all)
- tools.py: reuse a shared MCP host when set by the API, else fall back
  to a throwaway host for scripts/eval
feat(api): FastAPI app with shared MCP host + claim store
- claims.py: POST /claims (extract → graph → recommendation),
  GET /claims, GET /claims/{id}, POST /claims/{id}/decision (human gate)
- main.py: mount claims router; register shared MCP host with its event
  loop so threadpool tool calls run on the host's loop (fixes deadlock)
- tools.py: drive shared-host calls via run_coroutine_threadsafe
- ignore runtime artifacts (claims store + audit log)
feat(api): claim lifecycle endpoints + shared-host fix
FastAPI service holds one long-lived MCP host (fixes per-call spin-up);
endpoints expose the claim lifecycle — submit, list, detail, decide.
The decision endpoint resumes the graph at the human gate (approve or
override) and writes the audit. React+Tailwind console: claim queue,
review detail (recommendation + evidence + cited precedents), and the
approve/override action. Container-ready for 6b deploy.
Closes #N, #N, #N
feat(api,ui): claim review console over the decision graph
One image that boots the app + its MCP servers
A dependency that rejects un-keyed write requests. Adds demo login for now
feat: Protect the expensive routes
Pre-compute and cache recommendation claims during demo setup so
recruiter browsing never triggers live LLM calls.

- Pre-seed recommendation claims in the claim index
- Serve cached recommendations instead of invoking the model
- Eliminate per-view AI costs during the demo
- Prevent API limit issues during recruiter browsing
- Add reset flow to refresh demo state for the next visitor
Remove duplicate json import, unused Path import, and split
semicolon-separated statements for E702.
feat(demo): pre-seed cached recommendations for zero-cost browsing
@AttiR
AttiR merged commit 49bc8a0 into main Jul 2, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant