AI Eval — Providers nativos Anthropic y OpenAI
Resumen
Commit 3ad21cc (2026-04-27, @Esquembri) amplía la herramienta AI Eval del workspace CreaRack para soportar llamadas nativas a Anthropic y OpenAI, eliminando la dependencia de OpenRouter para los modelos Claude y GPT. El cambio toca dos archivos: el handler CF Workers (run.ts) y el panel React (AiEvalPanel.tsx), con +217/-15 LOC totales — dentro de la Regla 21 (≤ 400 LOC por feature).
Contexto previo
Antes de este commit, AI Eval soportaba:
| Provider | Integración |
|---|---|
| Gemini | Nativa (Google AI SDK) |
| OpenRouter | Gateway genérico (Claude, Llama, Qwen vía proxy) |
Los modelos Claude se invocaban a través de OpenRouter como anthropic/claude-haiku-4.5, con el overhead de latencia y markup de precio (~5 %) del gateway.
Cambios introducidos
Backend — functions/api/tools/ai-eval/run.ts
Tipo Candidate.provider
// Antes
provider: 'gemini' | 'openrouter'
// Después
provider: 'gemini' | 'anthropic' | 'openai' | 'openrouter'
RunBody.api_keys
// Antes
api_keys: { gemini?: string; openrouter?: string }
// Después
api_keys: { gemini?: string; anthropic?: string; openai?: string; openrouter?: string }
Nueva función callAnthropic
- Endpoint:
https://api.anthropic.com/v1/messages - Header obligatorio:
anthropic-version: 2023-06-01 - Autenticación:
x-api-key - Soporte vision (image base64 via
source.type: 'base64') - Soporte
system_instructioncomo camposystemde nivel superior - Usage:
input_tokens/output_tokens
Nueva función callOpenAI
- Endpoint:
https://api.openai.com/v1/chat/completions - Autenticación:
Authorization: Bearer - Usa
max_completion_tokens(compatible GPT-4o → GPT-5+; backward-compatible) - Guard o-series (reasoning): detecta modelos
o\dcon regex y omitetemperature(los modelos de razonamiento no aceptan ese parámetro) - Soporte
response_format: json_objectcuandoc.response_json === true - Soporte vision via
image_urlcon data URI base64 - Usage:
prompt_tokens/completion_tokens
Enrutador runCell
El switch de providers se extiende con guards explícitos:
if (c.provider === 'anthropic') {
if (!keys.anthropic) return { answer: '', latency_ms: 0, error: 'Falta API key de Anthropic' };
return callAnthropic(keys.anthropic, c.model, ec);
}
if (c.provider === 'openai') {
if (!keys.openai) return { answer: '', latency_ms: 0, error: 'Falta API key de OpenAI' };
return callOpenAI(keys.openai, c.model, ec);
}
Frontend — src/components/tools/AiEvalPanel.tsx
13 presets totales
| Grupo | Modelos |
|---|---|
| Google Gemini (3) | Gemini 3 Flash, Gemini 3.1 Flash-Lite, Gemini 2.5 Flash |
| Anthropic Claude (3) | Opus 4.7, Sonnet 4.6, Haiku 4.5 |
| OpenAI (4) | GPT-5.5, GPT-5.4, GPT-5.4 mini, GPT-5.4 nano |
| OpenRouter (3) | Qwen 2.5 72B, Llama 3.3 70B, DeepSeek R1 |
Los modelos Claude vía OpenRouter (
anthropic/claude-haiku-4.5) se mantienen enMODEL_PRICINGpor compatibilidad con runs históricos, pero los presets apuntan ahora al provider nativo.
MODEL_PRICING — Tarifas abril 2026 (USD / 1M tokens)
| Modelo | Input | Output |
|---|---|---|
| claude-opus-4-7 | $5.00 | $25.00 |
| claude-sonnet-4-6 | $3.00 | $15.00 |
| claude-haiku-4-5 | $1.00 | $5.00 |
| gpt-5.5 | $5.00 | $30.00 |
| gpt-5.4 | $2.50 | $15.00 |
| gpt-5.4-mini | $0.75 | $4.50 |
| gpt-5.4-nano | $0.20 | $1.25 |
| deepseek/deepseek-r1 (OR) | $0.55 | $2.19 |
Fuente: Anthropic docs + catálogo OpenRouter (verificados 2026-04-27). Actualizar cuando los providers cambien tarifas.
State y validación
keysstate ampliado a 4 campos:{ gemini, anthropic, openai, openrouter }canRunvalida que si un provider está en uso, su key no esté vacía- Inputs de API key aparecen condicionalmente (solo si el provider está en la selección activa), usando
providersInUse.has('anthropic')etc. CustomModelInputdropdown ahora lista los 4 providers
Arquitectura multi-provider
AiEvalPanel.tsx
└─ POST /api/tools/ai-eval/run
└─ runCell(candidate, evalCase, keys)
├─ provider='gemini' → callGemini(...)
├─ provider='anthropic' → callAnthropic(...) ← NUEVO
├─ provider='openai' → callOpenAI(...) ← NUEVO
└─ provider='openrouter' → callOpenRouter(...)
Cada función devuelve CellResult: { answer, latency_ms, tokens_in?, tokens_out?, error? }, permitiendo al panel calcular coste estimado con MODEL_PRICING.
Detalles de implementación notables
Guard o-series (OpenAI reasoning)
Los modelos o1, o3, o4-mini, etc. de OpenAI no aceptan el parámetro temperature. El código detecta el patrón con:
const isReasoning = /^o\d/i.test(model);
if (!isReasoning && c.temperature !== undefined) {
body.temperature = c.temperature;
}
Vision multi-provider
| Provider | Formato imagen |
|---|---|
| Anthropic | { type: 'image', source: { type: 'base64', media_type: 'image/png', data: b64 } } |
| OpenAI | { type: 'image_url', image_url: { url: 'data:image/png;base64,...' } } |
| Gemini | Formato SDK propio (ya existente) |
Compatibilidad de tokens
Anthropic → usage.input_tokens / usage.output_tokens
OpenAI → usage.prompt_tokens / usage.completion_tokens
Ambos se mapean a los campos estándar CellResult.tokens_in / tokens_out.
Impacto y consideraciones
- Sin breaking changes: el tipo
RunBody.api_keyssolo añade campos opcionales. - Coste por defecto: usuarios que no provean la key de Anthropic/OpenAI simplemente no pueden seleccionar esos providers (la UI bloquea
canRun). - OpenRouter como fallback: sigue disponible para modelos sin provider nativo (Qwen, Llama, DeepSeek).
- Regla 21 respetada: +217 LOC en 2 archivos (< 400 LOC).
Véase también
- [[entity—workspace—handler—ai-eval-run]]
- [[concept—ai—multi-provider-eval]]