LlmService
Dual-provider LLM client (OpenAI + Anthropic chat-completions), translating each provider's tool-call wire format to and from a single OpenAI-shaped message array.
LlmService::__construct()
public function __construct(string $apiKey, string $model = 'gpt-4o', string $provider = 'openai', ?Psr\Log\LoggerInterface $logger = null, ?Psr\Http\Client\ClientInterface $httpClient = null, ?Psr\Http\Message\RequestFactoryInterface $requestFactory = null, ?Psr\Http\Message\StreamFactoryInterface $streamFactory = null, ?string $baseUrl = null, array $extraHeaders = [], ?Milpa\AiGateway\ChannelObserver $channelObserver = null):Parameters
| Name | Type | Description |
|---|---|---|
| $apiKey | string | |
| $model | string | |
| $provider | string | |
| $logger | ?Psr\Log\LoggerInterface | |
| $httpClient | ?Psr\Http\Client\ClientInterface | |
| $requestFactory | ?Psr\Http\Message\RequestFactoryInterface | |
| $streamFactory | ?Psr\Http\Message\StreamFactoryInterface | |
| $baseUrl | (string | null) | Dónde vive el modelo. `null` es el proveedor público — `api.openai.com` o `api.anthropic.com`— y cualquier otra cosa es un endpoint compatible: un Ollama en la LAN, un vLLM, un proxy corporativo. Sin esto, la única forma de probar el bucle del agente era gastarle tokens a un proveedor público, y la única forma de correrlo con datos que no pueden salir de la casa era no correrlo. |
| $extraHeaders | array<string, string> | Encabezados adicionales para cada llamada — un `Authorization: Basic …` cuando el endpoint local está detrás de auth básica, por ejemplo. Se aplican DESPUÉS de los propios, así que pueden reemplazar el `Authorization` del proveedor a propósito. |
| $channelObserver | ?Milpa\AiGateway\ChannelObserver |
LlmService::generateResponse()
public function generateResponse(string $prompt, array $tools = [], array $messages = [], int $maxTokens = 4096): arraySend a prompt (or a full message history) to the configured provider and return a single OpenAI-shaped assistant message, translating request and response tool-call formats to and from Anthropic's shape when needed.
Parameters
| Name | Type | Description |
|---|---|---|
| $prompt | string | |
| $tools | list<array<string, mixed>> | Tool summaries in MCP/OpenAI shape (`name`, `description`, `inputSchema`) |
| $messages | list<array<string, mixed>> | Full conversation so far; when empty, a single `user` message is built from `$prompt` |
| $maxTokens | int |
Returns
An OpenAI-shaped assistant message (`role`, `content`, and optionally `tool_calls`)