Spaces:
Sleeping
Sleeping
| """Agent — produces answers using the current skillbook of strategies. | |
| Uses PydanticAI for structured output validation with automatic retry | |
| and error feedback. | |
| """ | |
| from __future__ import annotations | |
| import logging | |
| from typing import Any, Optional, Union | |
| from pydantic_ai import Agent as PydanticAgent | |
| from pydantic_ai.settings import ModelSettings | |
| from ..core.context import SkillbookView | |
| from ..core.outputs import AgentOutput | |
| from ..core.skillbook import Skillbook | |
| from ..providers.pydantic_ai import resolve_model | |
| from .helpers import format_optional | |
| from .prompts import AGENT_PROMPT | |
| logger = logging.getLogger(__name__) | |
| class Agent: | |
| """Produces answers using the current skillbook of strategies. | |
| The Agent is one of three core ACE roles. It takes a question and | |
| uses the accumulated strategies in the skillbook to produce reasoned | |
| answers. | |
| Args: | |
| model: Model identifier string. Supports any LiteLLM model | |
| (e.g. ``"gpt-4o-mini"``, ``"openrouter/anthropic/claude-3.5-sonnet"``) | |
| or a PydanticAI-native identifier (e.g. ``"openai:gpt-4o"``). | |
| prompt_template: Custom prompt template (defaults to | |
| :data:`AGENT_PROMPT`). | |
| max_retries: Maximum retries for structured output validation. | |
| PydanticAI feeds validation errors back to the LLM on retry. | |
| model_settings: Optional PydanticAI ``ModelSettings`` for | |
| temperature, max_tokens, etc. | |
| Example:: | |
| agent = Agent("gpt-4o-mini") | |
| output = agent.generate( | |
| question="What is the capital of France?", | |
| context="Answer concisely", | |
| skillbook=skillbook, | |
| ) | |
| print(output.final_answer) # "Paris" | |
| """ | |
| def __init__( | |
| self, | |
| model: str, | |
| *, | |
| prompt_template: str = AGENT_PROMPT, | |
| max_retries: int = 3, | |
| model_settings: ModelSettings | None = None, | |
| ) -> None: | |
| self._prompt_template = prompt_template | |
| self._agent = PydanticAgent( | |
| resolve_model(model), | |
| output_type=AgentOutput, | |
| retries=max_retries, | |
| model_settings=model_settings, | |
| defer_model_check=True, | |
| ) | |
| def generate( | |
| self, | |
| *, | |
| question: str, | |
| context: Optional[str], | |
| skillbook: Union[SkillbookView, Skillbook], | |
| reflection: Optional[str] = None, | |
| **kwargs: Any, | |
| ) -> AgentOutput: | |
| """Generate an answer using skillbook strategies. | |
| This method signature matches :class:`AgentLike`. | |
| Args: | |
| question: The question to answer. | |
| context: Additional context or requirements. | |
| skillbook: Current skillbook (needs ``as_prompt``). | |
| reflection: Optional reflection from a previous attempt. | |
| **kwargs: Accepted for protocol compatibility but not forwarded. | |
| Returns: | |
| :class:`AgentOutput` with reasoning, final_answer, and | |
| cited skill_ids. | |
| """ | |
| prompt = self._prompt_template.format( | |
| skillbook=skillbook.as_prompt() or "(empty skillbook)", | |
| reflection=format_optional(reflection), | |
| question=question, | |
| context=format_optional(context), | |
| ) | |
| result = self._agent.run_sync(prompt) | |
| output = result.output | |
| output.raw = _extract_usage(result) | |
| return output | |
| def _extract_usage(result: Any) -> dict[str, Any]: | |
| """Extract usage metadata from a PydanticAI run result.""" | |
| usage = result.usage() | |
| return { | |
| "usage": { | |
| "prompt_tokens": usage.input_tokens or 0, | |
| "completion_tokens": usage.output_tokens or 0, | |
| "total_tokens": usage.total_tokens or 0, | |
| }, | |
| } | |