Spaces:
Running
Running
| """Centralized LLM client factory. | |
| This module provides factory functions for creating LLM clients, | |
| ensuring consistent configuration and clear error messages. | |
| Why Magentic requires OpenAI: | |
| - Magentic agents use the @ai_function decorator for tool calling | |
| - This requires structured function calling protocol (tools, tool_choice) | |
| - OpenAI's API supports this natively | |
| - Anthropic/HuggingFace Inference APIs are text-in/text-out only | |
| """ | |
| from typing import TYPE_CHECKING, Any | |
| from src.utils.config import settings | |
| from src.utils.exceptions import ConfigurationError | |
| if TYPE_CHECKING: | |
| from agent_framework.openai import OpenAIChatClient | |
| def get_magentic_client() -> "OpenAIChatClient": | |
| """ | |
| Get the OpenAI client for Magentic agents. | |
| Magentic requires OpenAI because it uses function calling protocol: | |
| - @ai_function decorators define callable tools | |
| - LLM returns structured tool calls (not just text) | |
| - Requires OpenAI's tools/function_call API support | |
| Raises: | |
| ConfigurationError: If OPENAI_API_KEY is not set | |
| Returns: | |
| Configured OpenAIChatClient for Magentic agents | |
| """ | |
| # Import here to avoid requiring agent-framework for simple mode | |
| from agent_framework.openai import OpenAIChatClient | |
| api_key = settings.get_openai_api_key() | |
| return OpenAIChatClient( | |
| model_id=settings.openai_model, | |
| api_key=api_key, | |
| ) | |
| def get_pydantic_ai_model() -> Any: | |
| """ | |
| Get the appropriate model for pydantic-ai based on configuration. | |
| Uses the configured LLM_PROVIDER to select between OpenAI and Anthropic. | |
| This is used by simple mode components (JudgeHandler, etc.) | |
| Returns: | |
| Configured pydantic-ai model | |
| """ | |
| from pydantic_ai.models.anthropic import AnthropicModel | |
| from pydantic_ai.models.openai import OpenAIChatModel | |
| from pydantic_ai.providers.anthropic import AnthropicProvider | |
| from pydantic_ai.providers.openai import OpenAIProvider | |
| if settings.llm_provider == "openai": | |
| if not settings.openai_api_key: | |
| raise ConfigurationError("OPENAI_API_KEY not set for pydantic-ai") | |
| provider = OpenAIProvider(api_key=settings.openai_api_key) | |
| return OpenAIChatModel(settings.openai_model, provider=provider) | |
| if settings.llm_provider == "anthropic": | |
| if not settings.anthropic_api_key: | |
| raise ConfigurationError("ANTHROPIC_API_KEY not set for pydantic-ai") | |
| anthropic_provider = AnthropicProvider(api_key=settings.anthropic_api_key) | |
| return AnthropicModel(settings.anthropic_model, provider=anthropic_provider) | |
| raise ConfigurationError(f"Unknown LLM provider: {settings.llm_provider}") | |
| def check_magentic_requirements() -> None: | |
| """ | |
| Check if Magentic mode requirements are met. | |
| Raises: | |
| ConfigurationError: If requirements not met | |
| """ | |
| if not settings.has_openai_key: | |
| raise ConfigurationError( | |
| "Magentic mode requires OPENAI_API_KEY for function calling support. " | |
| "Anthropic and HuggingFace Inference do not support the structured " | |
| "function calling protocol that Magentic agents require. " | |
| "Use mode='simple' for other LLM providers." | |
| ) | |
| def check_simple_mode_requirements() -> None: | |
| """ | |
| Check if simple mode requirements are met. | |
| Simple mode supports both OpenAI and Anthropic. | |
| Raises: | |
| ConfigurationError: If no LLM API key is configured | |
| """ | |
| if not settings.has_any_llm_key: | |
| raise ConfigurationError( | |
| "No LLM API key configured. Set OPENAI_API_KEY or ANTHROPIC_API_KEY." | |
| ) | |