File size: 2,048 Bytes
aad7814
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Result models for a generated report."""

from __future__ import annotations

from pydantic import BaseModel, Field


class ReferenceSource(BaseModel):
    """Provenance for content mapped from an uploaded past report (REFERENCE tier)."""

    report_filename: str
    section_id: str = ""
    section_title: str = ""
    paragraph_index: int = 0
    tier: str = Field(default="reference", description="Always reference for user-facing attribution.")


class GeneratedSection(BaseModel):
    """One section of mapped output."""

    section_id: str
    title: str
    text: str = Field(default="")
    rating_value: str | None = Field(default=None)
    status: str = Field(
        default="OK",
        description="OK | empty | NO_RAG_MATCH | GROUNDING_REVIEW | UNASSIGNED",
    )
    notes: str = Field(default="", description="Diagnostic note for this section.")
    rag_sources: list[str] = Field(
        default_factory=list,
        description="Human-readable REFERENCE provenance strings.",
    )
    reference_sources: list[ReferenceSource] = Field(
        default_factory=list,
        description="Structured provenance from uploaded past reports only.",
    )
    grounding_passed: bool = Field(default=True)
    unmatched_observations: list[str] = Field(default_factory=list)
    shorthand_expanded: str | None = Field(
        default=None,
        description="Optional expanded shorthand for this section's notes.",
    )


class ReportResult(BaseModel):
    """Full generation result before DOCX assembly."""

    tenant_id: str
    schema_version: int
    property_type: str = Field(default="")
    tenure: str = Field(default="")
    sections: list[GeneratedSection] = Field(default_factory=list)
    unassigned_text: str = Field(default="")
    active_section_count: int = Field(
        default=0,
        description="Leaf subsections with notes and/or AI-selected photos.",
    )
    processed_section_count: int = Field(
        default=0,
        description="Leaf subsections actually processed in this run.",
    )