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