| """analysis/signals.py — shared signal types for the Analyst Edge layer. |
| |
| These Pydantic models carry deterministically-computed evidence (verbatim |
| before/after text, counts, deltas) from the analysis modules to the LangGraph |
| agent and synthesis node. The LLM explains; the code supplies the figures. |
| """ |
| from __future__ import annotations |
|
|
| from typing import Literal, Optional |
| from pydantic import BaseModel, ConfigDict, Field |
|
|
|
|
| class QuarterDelta(BaseModel): |
| """A verbatim text change detected between two consecutive filing periods.""" |
| model_config = ConfigDict(extra="ignore") |
|
|
| kind: Literal[ |
| "risk_added", |
| "risk_removed", |
| "risk_reworded", |
| "guidance_language_shift", |
| "term_frequency", |
| "kpi_dropped", |
| |
| "tone_trend", |
| "topic_arc", |
| "recurring_evasion", |
| "topic_fade", |
| ] = Field(description="Type of delta detected.") |
|
|
| period_from: str = Field(description="Prior filing period, e.g. 'Q42025'.") |
| period_to: str = Field(description="Current filing period, e.g. 'Q12026'.") |
|
|
| before_text: str = Field( |
| default="", |
| description="Verbatim fragment from the prior period. Empty for risk_added.", |
| ) |
| after_text: str = Field( |
| default="", |
| description="Verbatim fragment from the current period. Empty for risk_removed.", |
| ) |
|
|
| computed_metric: str = Field( |
| default="", |
| description="A computed summary, e.g. '2→8 occurrences (+300%)' for term_frequency.", |
| ) |
|
|
| source: Literal["10-K", "10-Q", "transcript"] = Field( |
| default="10-Q", |
| description="Filing type the delta was detected in.", |
| ) |
|
|
| significance: Literal["HIGH", "MEDIUM", "LOW"] = Field( |
| default="MEDIUM", |
| description="Computed significance: HIGH for new risks or large frequency swings, etc.", |
| ) |
|
|
| term: str = Field( |
| default="", |
| description="The term or risk label being tracked (for term_frequency / kpi_dropped).", |
| ) |
|
|