Coverage for src / quber / processors / period.py: 0%
24 statements
« prev ^ index » next coverage.py v7.14.0, created at 2026-09-23 22:14 -0400
« prev ^ index » next coverage.py v7.14.0, created at 2026-09-23 22:14 -0400
1"""
2Period / quarter-end inference.
4Asks an LLM to read a table fragment and infer the reporting period it
5covers (period end date plus the label as printed). Uses pydantic-ai so
6it sits alongside the existing inference processor.
8Value extraction is deliberately out of scope for this module.
9"""
11from __future__ import annotations
13from datetime import date
14from typing import Optional
16from loguru import logger
17from pydantic import BaseModel, Field
19from quber.agents import AgentFactory
20from quber.agents.factory import ModelProvider
22PERIOD_PROMPT = """\
23You are reading a financial-document table fragment to infer the
24reporting period it covers.
26Return a JSON object with:
27- period_end (ISO date YYYY-MM-DD, or null if unknown)
28- period_label (free-text label as it appears in the source, e.g.
29 "Q1 FY25", "For the 3 Months Ended September 30, 2025")
30- fiscal_quarter (1-4, or null)
31- fiscal_year (e.g. 2025, or null)
33Do not guess. If the table fragment does not state the period
34unambiguously, return nulls for the fields you cannot fill.
35"""
38class PeriodInference(BaseModel):
39 period_end: Optional[date] = Field(default=None)
40 period_label: Optional[str] = Field(default=None)
41 fiscal_quarter: Optional[int] = Field(default=None, ge=1, le=4)
42 fiscal_year: Optional[int] = Field(default=None)
45class PeriodInferenceProcessor:
46 def __init__(
47 self,
48 provider: Optional[ModelProvider] = None,
49 model: Optional[str] = None,
50 ) -> None:
51 factory = AgentFactory(enable_logfire=False)
52 self.agent = factory.create_agent(
53 output_type=PeriodInference,
54 system_prompt=PERIOD_PROMPT,
55 provider=provider,
56 model=model,
57 )
59 async def infer(self, fragment: str) -> PeriodInference:
60 try:
61 result = await self.agent.run(fragment)
62 return result.output
63 except Exception as exc:
64 logger.warning("PeriodInferenceProcessor failed: {exc}", exc=exc)
65 return PeriodInference()