Feat/math validation agent (#6012)

Co-authored-by: James Brunton <[email protected]>
Co-authored-by: EthanHealy01 <[email protected]>
This commit is contained in:
ConnorYoh
2026-04-17 10:36:45 +01:00
committed by GitHub
co-authored by James Brunton EthanHealy01
parent 688f7f2013
commit de8c483054
49 changed files with 3726 additions and 17 deletions
+4
View File
@@ -8,10 +8,12 @@ from pydantic_ai import Agent
from pydantic_ai.models.instrumented import InstrumentationSettings
from stirling.agents import ExecutionPlanningAgent, OrchestratorAgent, PdfEditAgent, PdfQuestionAgent, UserSpecAgent
from stirling.agents.ledger import MathAuditorAgent
from stirling.api.middleware import UserIdMiddleware
from stirling.api.routes import (
agent_draft_router,
execution_router,
ledger_router,
orchestrator_router,
pdf_edit_router,
pdf_question_router,
@@ -40,6 +42,7 @@ async def lifespan(fast_api: FastAPI):
fast_api.state.pdf_question_agent = PdfQuestionAgent(runtime)
fast_api.state.user_spec_agent = UserSpecAgent(runtime)
fast_api.state.execution_planning_agent = ExecutionPlanningAgent(runtime)
fast_api.state.math_auditor_agent = MathAuditorAgent(runtime)
tracer_provider = setup_posthog_tracking(settings)
if tracer_provider:
Agent.instrument_all(InstrumentationSettings(tracer_provider=tracer_provider))
@@ -55,6 +58,7 @@ app.include_router(pdf_edit_router)
app.include_router(pdf_question_router)
app.include_router(agent_draft_router)
app.include_router(execution_router)
app.include_router(ledger_router)
@app.get("/health", response_model=HealthResponse)
+5
View File
@@ -3,6 +3,7 @@ from __future__ import annotations
from fastapi import Request
from stirling.agents import ExecutionPlanningAgent, OrchestratorAgent, PdfEditAgent, PdfQuestionAgent, UserSpecAgent
from stirling.agents.ledger import MathAuditorAgent
from stirling.services import AppRuntime
@@ -28,3 +29,7 @@ def get_user_spec_agent(request: Request) -> UserSpecAgent:
def get_execution_planning_agent(request: Request) -> ExecutionPlanningAgent:
return request.app.state.execution_planning_agent
def get_math_auditor_agent(request: Request) -> MathAuditorAgent:
return request.app.state.math_auditor_agent
@@ -1,5 +1,6 @@
from .agent_drafts import router as agent_draft_router
from .execution import router as execution_router
from .ledger import router as ledger_router
from .orchestrator import router as orchestrator_router
from .pdf_edit import router as pdf_edit_router
from .pdf_questions import router as pdf_question_router
@@ -7,6 +8,7 @@ from .pdf_questions import router as pdf_question_router
__all__ = [
"agent_draft_router",
"execution_router",
"ledger_router",
"orchestrator_router",
"pdf_edit_router",
"pdf_question_router",
+60
View File
@@ -0,0 +1,60 @@
"""
Math Auditor Agent (mathAuditorAgent) — FastAPI routes.
Two internal endpoints, called only by the Java MathAuditorOrchestrator:
POST /api/v1/ai/math-auditor-agent/examine
Java sends a FolioManifest (cheap page classification).
Python returns a Requisition (what Java must extract).
POST /api/v1/ai/math-auditor-agent/deliberate
Java sends Evidence (fulfilled extraction results).
Python returns a Verdict directly.
"""
from __future__ import annotations
import logging
from decimal import Decimal, InvalidOperation
from typing import Annotated
from fastapi import APIRouter, Depends, HTTPException, Query
from stirling.agents.ledger import MathAuditorAgent
from stirling.api.dependencies import get_math_auditor_agent
from stirling.contracts.ledger import (
Evidence,
FolioManifest,
Requisition,
Verdict,
)
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/v1/ai/math-auditor-agent", tags=["math-auditor-agent"])
@router.post("/examine", response_model=Requisition)
async def examine_endpoint(
manifest: FolioManifest,
agent: Annotated[MathAuditorAgent, Depends(get_math_auditor_agent)],
) -> Requisition:
"""Round 1: Java presents a FolioManifest; Python declares its Requisition."""
return await agent.examine(manifest)
@router.post("/deliberate", response_model=Verdict)
async def deliberate_endpoint(
evidence: Evidence,
agent: Annotated[MathAuditorAgent, Depends(get_math_auditor_agent)],
tolerance: str = Query(default="0.01"),
) -> Verdict:
"""Round 2: Java presents fulfilled Evidence; Python returns a Verdict."""
try:
tol = Decimal(tolerance)
if tol < 0:
raise HTTPException(status_code=400, detail="tolerance must be non-negative")
except InvalidOperation:
raise HTTPException(status_code=400, detail=f"Invalid tolerance value: {tolerance!r}")
return await agent.audit(evidence, tol)