Source code for lalandre_rag.summaries.agent
"""PydanticAI agent for structured canonical summary generation."""
from __future__ import annotations
from collections.abc import Callable
from typing import Any
from lalandre_core.config import get_config
from lalandre_core.llm.structured import run_structured_agent
from pydantic import BaseModel, Field, field_validator
from pydantic_ai import Agent, ModelRetry
[docs]
class CanonicalSummaryOutput(BaseModel):
"""Structured summary output validated by PydanticAI."""
model_config = {"extra": "ignore"}
summary: str = Field(min_length=10)
output_validation_retries: int = Field(default=0, ge=0)
[docs]
@field_validator("summary", mode="before")
@classmethod
def clean_summary(cls, v: Any) -> str:
"""Normalize and validate the structured summary text."""
if isinstance(v, str) and v.strip():
return v.strip()
raise ValueError("Summary cannot be empty")
_SUMMARY_AGENT: Agent[Any, CanonicalSummaryOutput] = Agent(
output_type=CanonicalSummaryOutput,
instructions=(
"Tu résumes un acte juridique pour un panneau de bibliothèque documentaire.\n"
"4 à 6 phrases maximum. Ton factuel, sans citations, sans markdown, sans liste.\n"
"Décris l'objet du texte, sa portée et sa structure si visible.\n"
"N'invente aucun élément absent du contenu fourni."
),
output_retries=2,
defer_model_check=True,
)
@_SUMMARY_AGENT.output_validator
def _validate_summary(result: CanonicalSummaryOutput) -> CanonicalSummaryOutput:
min_chars = get_config().search.summary_min_chars
if len(result.summary) < min_chars:
raise ModelRetry(f"Le résumé est trop court (min {min_chars} caractères).")
return result
[docs]
def run_summary_agent(
*,
prompt: str,
generate_text: Callable[[str], str],
model_name: str,
) -> tuple[CanonicalSummaryOutput, int]:
"""Run the canonical summary agent and return validated output + retry count."""
return run_structured_agent(
agent=_SUMMARY_AGENT,
prompt=prompt,
llm_or_generate=generate_text,
model_name=model_name,
)