Saltar al contenido
# 🔌 Providers — Multi-proveedor en klaude-proxy ## 🤔 ¿Qué hago? ¿Cómo lo hago? ¿Y para qué lo hago? **Qué hago:** klaude-proxy soporta múltiples proveedores de LLM — Anthropic API y Ollama (modelos locales). El enrutamiento es transparente para el cliente: Klaus Code CLI (u cualquier cliente compatible con la Anthropic Messages API) simplemente especifica el modelo que quiere usar y el proxy lo dirige al backend correcto. **Cómo lo hago:** El campo `model` del request determina el proveedor. Si el modelo contiene `:` (convención de Ollama para tags), va a Ollama vía su endpoint OpenAI-compatible. Si es `claude-*` o está vacío, va a Anthropic. El adaptador de Ollama traduce el formato Anthropic ↔ OpenAI de forma transparente, por lo que el cliente siempre recibe respuestas en formato Anthropic. **Para qué lo hago:** Permite usar modelos locales especializados (`kdev:latest`, `kitil:latest`) sin coste por token, manteniendo la misma interfaz que Anthropic. La caché semántica funciona igual para ambos proveedores. --- ## 🗺️ Regla de routing | Campo `model` en el request | Provider | Modelo resuelto | | --- | --- | --- | | Vacío / `null` | Anthropic | `claude-haiku-4-5-20251001` | | `claude-haiku-4-5-20251001` | Anthropic | tal cual | | `claude-opus-4-8` | Anthropic | tal cual | | `kdev:latest` | Ollama | tal cual | | `kitil:latest` | Ollama | tal cual | | Cualquier string con `:` | Ollama | tal cual | La regla es simple: **si el modelo lleva `:` es Ollama; todo lo demás es Anthropic**. --- ## 🔄 Flujo de una petición ```mermaid flowchart TD C([Cliente\nKlaus Code CLI]) -->|POST /v1/messages| P[klaude-proxy] P --> R{router.py\nresolve_provider} R -->|model vacío| D[default_model\nclaude-haiku-4-5] R -->|model claude-*| A[Anthropic] R -->|model contiene :| O[Ollama] P --> CACHE{Caché\nQdrant} CACHE -->|HIT| RESP([Respuesta cacheada]) CACHE -->|MISS| R A -->|Anthropic format| P O -->|OpenAI format → traducción → Anthropic format| P P -->|Anthropic format| C P -->|Store si es end_turn| CACHE ``` --- ## ⚙️ Configuración ### Variables de entorno | Variable | Default | Descripción | | --- | --- | --- | | `ANTHROPIC_API_KEY` | `""` | API key de Anthropic. Opcional si solo usas Ollama. | | `OLLAMA_BASE_URL` | `http://localhost:11434` | URL base de Ollama (sin `/v1`). | | `OLLAMA_TIMEOUT_SECONDS` | `120` | Timeout en segundos para llamadas a Ollama. | | `DEFAULT_MODEL` | `claude-haiku-4-5-20251001` | Modelo usado cuando el cliente no especifica ninguno. | ### `.env` mínimo para Ollama-only ```env # No hace falta ANTHROPIC_API_KEY OLLAMA_BASE_URL=http://192.168.1.50:11434 DEFAULT_MODEL=kdev:latest ``` ### `.env` mínimo para Anthropic-only (configuración previa) ```env ANTHROPIC_API_KEY=sk-ant-... ``` ### `.env` para uso mixto ```env ANTHROPIC_API_KEY=sk-ant-... OLLAMA_BASE_URL=http://localhost:11434 DEFAULT_MODEL=claude-haiku-4-5-20251001 ``` --- ## 🤖 Modelos Ollama conocidos | Modelo | Propósito | | --- | --- | | `kdev:latest` | Desarrollo — código, refactoring, revisión | | `kitil:latest` | ITIL / operaciones — gestión de incidentes, cambios | Cualquier modelo disponible en tu instancia Ollama es válido: el proxy no valida la lista en tiempo de arranque. Si el modelo no existe, Ollama devolverá error 404 que el proxy propagará al cliente. --- ## 🔌 Adaptador Ollama (`proxy/ollama_client.py`) El adaptador usa el endpoint OpenAI-compatible de Ollama (`/v1/chat/completions`), disponible desde Ollama ≥ 0.1.24. ### Traducción request (Anthropic → OpenAI) ``` Anthropic: OpenAI (Ollama): { { "model": "kdev:latest", "model": "kdev:latest", "system": "Eres un experto", → "messages": [ "messages": [ {"role": "system", "content": "Eres un experto"}, {"role": "user", {"role": "user", "content": "¿Qué hace este código?"} "content": "¿Qué hace..."} ], ], "max_tokens": 4096 "max_tokens": 4096 } } ``` ### Traducción response (OpenAI → Anthropic) ``` OpenAI (Ollama): Anthropic: { { "choices": [{ "type": "message", "message": { "role": "assistant", "role": "assistant", → "content": [{"type": "text", "text": "..."}], "content": "La función hace..." "stop_reason": "end_turn", }, "usage": { "finish_reason": "stop" "input_tokens": 150, }], "output_tokens": 80 "usage": { } "prompt_tokens": 150, } "completion_tokens": 80 } } ``` --- ## 🔍 Identificar el provider en los logs El dashboard y los logs de contenedor muestran `provider=` en cada petición: ``` CACHE MISS hash=a1b2c3d4 stream=True model=kdev:latest provider=ollama FORWARD hash=a1b2c3d4 model=kdev:latest provider=ollama text=... RESPONSE hash=a1b2c3d4 in=150 out=80 model=kdev:latest source=ollama ``` El header de respuesta HTTP incluye `X-Provider: ollama` o `X-Provider: anthropic`. --- ## 🔗 Documentos relacionados - [proxy.md](proxy.md) — endpoints y configuración general - [cache.md](cache.md) — estrategia de caché semántica (válida para todos los providers) - [analytics.md](analytics.md) — tracking de costes (el campo `source` refleja el provider)