| | """final_verdict node — synthesize compliance analysis + optional peer review into structured verdict."""
|
| | from __future__ import annotations
|
| |
|
| | from datetime import datetime
|
| |
|
| | from google import genai
|
| | from google.genai import types
|
| |
|
| | from config import GOOGLE_API_KEY, VERDICT_MODEL
|
| | from state import AgentMessage, ComplianceState
|
| |
|
| |
|
| | def final_verdict(state: ComplianceState) -> dict:
|
| | """Produce the final compliance verdict, synthesizing all evidence."""
|
| | question = state["question"]
|
| | compliance_analysis = state.get("compliance_analysis", "")
|
| | reviewer_analysis = state.get("reviewer_analysis", "")
|
| | code_report = state.get("code_report", "")
|
| | enable_consensus = state.get("enable_consensus", False)
|
| |
|
| |
|
| | if not enable_consensus or not reviewer_analysis:
|
| | verdict_msg = AgentMessage(
|
| | timestamp=datetime.now().strftime("%H:%M:%S"),
|
| | agent="compliance_analyst",
|
| | action="verdict",
|
| | summary="Final compliance verdict issued.",
|
| | detail=compliance_analysis[:1000],
|
| | evidence_refs=[],
|
| | )
|
| | return {
|
| | "final_verdict": compliance_analysis,
|
| | "discussion_log": [verdict_msg],
|
| | "status_message": ["Final verdict ready."],
|
| | }
|
| |
|
| |
|
| | client = genai.Client(api_key=GOOGLE_API_KEY)
|
| |
|
| | synthesis_prompt = f"""\
|
| | You are producing a FINAL COMPLIANCE VERDICT for a NYC building code review.
|
| |
|
| | USER QUESTION: {question}
|
| |
|
| | CODE REQUIREMENTS (from legal research):
|
| | {code_report[:3000]}
|
| |
|
| | ANALYST A (Gemini) compliance findings:
|
| | {compliance_analysis}
|
| |
|
| | ANALYST B (GPT) peer review:
|
| | {reviewer_analysis}
|
| |
|
| | YOUR TASK:
|
| | 1. If both analysts AGREE on compliance status: produce a confident, unified verdict.
|
| | 2. If they PARTIALLY AGREE: produce the verdict based on agreed points, and explicitly \
|
| | note areas of disagreement with evidence from both sides.
|
| | 3. If they DISAGREE: present both interpretations, explain the discrepancy, and state \
|
| | which determination appears better supported by the evidence.
|
| |
|
| | OUTPUT FORMAT:
|
| |
|
| | ### Compliance Verdict
|
| | **Status:** Compliant | Non-Compliant | Partially Compliant | Unverifiable
|
| |
|
| | ### Legal Basis
|
| | For each code requirement checked:
|
| | - **[Code Type] SS[Section] — [Title]**
|
| | - Requirement: [specific measurable requirement]
|
| | - Drawing Evidence: [what was observed]
|
| | - Determination: [compliant/non-compliant/unverifiable]
|
| |
|
| | ### Key Findings
|
| | - Bullet points of the most important compliance determinations
|
| |
|
| | ### Analyst Consensus
|
| | - Agreement/disagreement between Gemini and GPT analysts
|
| | - Resolution of any conflicts
|
| |
|
| | ### Limitations
|
| | - What could not be verified and why
|
| | - Recommended follow-up actions
|
| |
|
| | Always cite BOTH code sections AND image crop labels for every factual claim.
|
| | """
|
| |
|
| | response = client.models.generate_content(
|
| | model=VERDICT_MODEL,
|
| | contents=[synthesis_prompt],
|
| | )
|
| |
|
| | verdict_text = response.text
|
| |
|
| | verdict_msg = AgentMessage(
|
| | timestamp=datetime.now().strftime("%H:%M:%S"),
|
| | agent="compliance_analyst",
|
| | action="verdict",
|
| | summary="Final synthesized compliance verdict issued.",
|
| | detail=verdict_text[:1000],
|
| | evidence_refs=[],
|
| | )
|
| |
|
| | return {
|
| | "final_verdict": verdict_text,
|
| | "discussion_log": [verdict_msg],
|
| | "status_message": ["Final synthesized verdict ready."],
|
| | }
|
| |
|