dify/dify-agent/src/dify_agent/runtime/agent_factory.py

49 lines
2.0 KiB
Python

"""Pydantic AI agent construction for models supplied by Agenton layers.
The run request carries model/provider selection in the layer graph. This helper
keeps Agent construction details out of ``AgentRunRunner`` while accepting an
already resolved Pydantic AI model from the configured model layer. Tool values
arriving here are already transformed by Agenton's
``PYDANTIC_AI_TRANSFORMERS`` preset, while Dify system prompts are rendered into
temporary ``message_history`` before the call reaches this helper. The caller
also passes the already resolved ``output_type`` so legacy text output and the
optional JSON Schema output layer share the same ``Agent`` construction path.
"""
from collections.abc import Sequence
from typing import Any, cast
from pydantic_ai import Agent
from pydantic_ai.messages import UserContent
from pydantic_ai.models import Model
from pydantic_ai.output import OutputSpec
from agenton.layers.types import PydanticAITool
def create_agent(
model: Model[Any],
*,
tools: Sequence[PydanticAITool[object]],
output_type: OutputSpec[object] = str,
) -> Agent[None, object]:
"""Create the pydantic-ai agent for one run.
``output_type`` is resolved by the runtime after entering the Agenton run so
validation and execution both honor the same optional structured output
contract. For structured output runs the type inside ``output_type`` already
carries the Pydantic hooks needed for schema exposure and runtime validation,
so agent construction does not need to register a separate validator.
"""
return cast(Agent[None, object], Agent(model, output_type=output_type, tools=tools))
def normalize_user_input(user_prompts: Sequence[UserContent]) -> str | Sequence[UserContent]:
"""Return the pydantic-ai run input while preserving multi-part prompts."""
if len(user_prompts) == 1 and isinstance(user_prompts[0], str):
return user_prompts[0]
return list(user_prompts)
__all__ = ["create_agent", "normalize_user_input"]