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

1""" 

2Period / quarter-end inference. 

3 

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. 

7 

8Value extraction is deliberately out of scope for this module. 

9""" 

10 

11from __future__ import annotations 

12 

13from datetime import date 

14from typing import Optional 

15 

16from loguru import logger 

17from pydantic import BaseModel, Field 

18 

19from quber.agents import AgentFactory 

20from quber.agents.factory import ModelProvider 

21 

22PERIOD_PROMPT = """\ 

23You are reading a financial-document table fragment to infer the 

24reporting period it covers. 

25 

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) 

32 

33Do not guess. If the table fragment does not state the period 

34unambiguously, return nulls for the fields you cannot fill. 

35""" 

36 

37 

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) 

43 

44 

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 ) 

58 

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()