| """Pydantic schemas: the shared response contract. |
| |
| Every substantive answer ParaPilot returns is an ``AnswerEnvelope`` carrying |
| citations, a confidence score, the standing disclaimer, ``is_legal_information``, |
| and an escalation block — the SPEC §6 UPL/safety contract. |
| """ |
| from __future__ import annotations |
|
|
| from enum import Enum |
| from typing import List, Optional |
|
|
| from pydantic import BaseModel, Field |
|
|
|
|
| class AnswerKind(str, Enum): |
| """How an answer was produced.""" |
|
|
| GROUNDED = "grounded" |
| REFUSAL_SCOPE = "refusal_scope" |
| REFUSAL_ADVICE = "refusal_advice" |
| REFUSAL_LOW_CONFIDENCE = "refusal_low_confidence" |
|
|
|
|
| class Citation(BaseModel): |
| """A clickable pointer back to an authoritative source chunk.""" |
|
|
| marker: str = Field(..., description="Inline marker, e.g. '1'.") |
| source_id: str |
| chunk_id: str |
| title: str |
| url: str |
| publisher: str |
| retrieved: str |
| snippet: str = Field(..., description="Short supporting excerpt from the source.") |
|
|
|
|
| class Escalation(BaseModel): |
| """Where to get real legal help. Always present.""" |
|
|
| message: str = ( |
| "For advice about your specific situation, contact a licensed Illinois " |
| "attorney or legal aid." |
| ) |
| legal_aid_name: str = "Illinois Legal Aid Online (ILAO)" |
| legal_aid_url: str = "https://www.illinoislegalaid.org/get-legal-help" |
| lawyer_finder_name: str = "Illinois Lawyer Finder (ISBA)" |
| lawyer_finder_url: str = "https://www.isba.org/public/illinoislawyerfinder" |
|
|
|
|
| class AnswerEnvelope(BaseModel): |
| """The single response shape returned by the Ask endpoint.""" |
|
|
| kind: AnswerKind |
| question: str |
| answer: str |
| citations: List[Citation] = Field(default_factory=list) |
| confidence: float = Field(0.0, ge=0.0, le=1.0) |
| is_legal_information: bool = True |
| disclaimer: str |
| escalation: Escalation = Field(default_factory=Escalation) |
| provider: str = "stub" |
|
|
| @property |
| def is_refusal(self) -> bool: |
| return self.kind != AnswerKind.GROUNDED |
|
|
|
|
| class RetrievedChunk(BaseModel): |
| """A retrieval hit (internal).""" |
|
|
| source_id: str |
| chunk_id: str |
| title: str |
| url: str |
| publisher: str |
| retrieved: str |
| heading: str |
| text: str |
| score: float |
|
|