Ejecuta el cerebro de RAG de Quivr sobre un endpoint personalizado compatible con OpenAI.
Updated 2026-07-29
El LLMEndpointConfig de quivr-core acepta un campo llm_base_url. Mantén el supplier como openai, configura llm_base_url a https://api.apisrouter.com/v1, pasa una clave, y cada brain.ask() genera su respuesta a través del gateway con cualquier id de modelo del catálogo.
Respuesta rápida: llm_base_url en LLMEndpointConfig.
El Quivr actual es quivr-core, una librería de RAG en Python, y su conexión con el LLM es explícita. LLMEndpointConfig lleva supplier (openai por defecto), model, llm_base_url y llm_api_key; LLMEndpoint.from_config() construye el cliente real a partir de esos campos, y para el supplier openai ese cliente es el ChatOpenAI de LangChain construido con tu base URL. Configura llm_base_url a https://api.apisrouter.com/v1, configura model a cualquier id del catálogo, y entrega el endpoint a tu Brain. La clave puede venir del campo de configuración o del entorno: cuando llm_api_key no está configurada, quivr-core la resuelve desde una variable de entorno nombrada según el supplier, que para el supplier openai es OPENAI_API_KEY. Ambas rutas son comportamiento upstream, legible en quivr_core/rag/entities/config.py y quivr_core/llm/llm_endpoint.py.
from quivr_core.llm import LLMEndpoint
from quivr_core.rag.entities.config import (
DefaultModelSuppliers, LLMEndpointConfig)
llm = LLMEndpoint.from_config(LLMEndpointConfig(
supplier=DefaultModelSuppliers.OPENAI,
model="claude-sonnet-4-6", # any catalog id
llm_base_url="https://api.apisrouter.com/v1",
llm_api_key=os.environ["APISROUTER_API_KEY"],
))Qué es Quivr ahora, y dónde se sitúa el slot de LLM.
Quivr (QuivrHQ en GitHub, unas 39K estrellas) empezó como una aplicación completa de segundo cerebro y pivotó hacia quivr-core: una librería de RAG con opinión propia que incrustas en tu propio producto. Le das archivos, los parsea y fragmenta, incrusta los fragmentos en un vector store (FAISS por defecto, PGVector soportado), y responde preguntas sobre ellos a través de un flujo de recuperación configurable. El objeto Brain es la unidad: Brain.from_files() ingiere, brain.ask() recupera y genera. La generación es el único paso que necesita un modelo de chat. El flujo de recuperación ensambla contexto de tus documentos, y el LLMEndpoint que pasaste escribe la respuesta fundamentada. Ese endpoint se construye una vez desde LLMEndpointConfig, así que la decisión de la base URL se toma en el momento de construcción y aplica a cada ask() en ese brain. Como ChatOpenAI reenvía el campo model como un string simple sobre /v1/chat/completions, el id puede ser Claude, DeepSeek, GPT o Gemini cuando el endpoint detrás de llm_base_url los sirve. Una nota honesta sobre el estado del proyecto: el repositorio ha estado callado desde mediados de 2025, así que trata a quivr-core como una librería estable en lugar de una que se mueve rápido. La superficie de configuración descrita aquí coincide con la última rama main, y la historia silenciosa significa que es improbable que cambie bajo tus pies; también significa que los tutoriales antiguos que describen la app full-stack retirada (archivos .env de backend, un frontend alojado) ya no coinciden con el código.
Configuración completa: un brain con un LLM enrutado por el gateway.
El patrón completo pasa el LLMEndpoint configurado a Brain.from_files. Todo lo demás sobre el brain (parseo, fragmentación, el almacén FAISS, el flujo de recuperación) es independiente del endpoint del LLM y mantiene sus valores por defecto. Presta atención al embedder. Si no pasas uno, quivr-core construye el OpenAIEmbeddings de LangChain con sus propios valores por defecto, que autentica con OPENAI_API_KEY y apunta al endpoint de OpenAI de fábrica. Ese es un cliente separado del LLM de chat: enrutar la generación a través del gateway no lo mueve. Pasa tu propio embedder (un wrapper local de sentence-transformers, o cualquier instancia de Embeddings de LangChain que configures) si no quieres que la mitad de embedding dependa de una cuenta de OpenAI.
import os
from quivr_core import Brain
from quivr_core.llm import LLMEndpoint
from quivr_core.rag.entities.config import (
DefaultModelSuppliers, LLMEndpointConfig)
llm = LLMEndpoint.from_config(LLMEndpointConfig(
supplier=DefaultModelSuppliers.OPENAI,
model="claude-sonnet-4-6",
llm_base_url="https://api.apisrouter.com/v1",
llm_api_key=os.environ["APISROUTER_API_KEY"],
max_output_tokens=2048,
temperature=0.3,
))
brain = Brain.from_files(
name="team-docs",
file_paths=["handbook.pdf", "runbook.md"],
llm=llm,
# embedder=... # separate component; see note above
)
print(brain.ask("What is the on-call escalation policy?").answer)Elegir un modelo de generación para respuestas de RAG.
Comparar candidatos es un cambio en tiempo de construcción: construye dos LLMEndpoints contra la misma base URL, dos brains sobre los mismos archivos, y diferencia las respuestas en un conjunto de preguntas fijo. El log de uso por clave tasa cada ejecución candidata, así que la calidad por token se mide en lugar de discutirse.
- La generación de RAG consume mucha entrada: los fragmentos recuperados dominan el prompt. El precio por token de entrada fija el coste de una respuesta, por lo que un id rápido a menudo reduce a la mitad la factura sin tocar la calidad de recuperación.
- claude-sonnet-4-6 es el valor por defecto fiable para respuestas fundamentadas que respetan el contexto recuperado y declinan de forma limpia cuando los documentos no contienen la respuesta.
- Los productos incrustados de alto volumen (el caso de uso declarado de Quivr) funcionan bien con claude-haiku-4-5-20251001, deepseek-v4-flash o gemini-3.5-flash para la mezcla cotidiana de preguntas.
- max_context_tokens en la misma configuración gobierna cuánto contexto recuperado empaqueta el pipeline; subirlo empareja naturalmente con ids de contexto largo y sube el gasto de entrada proporcionalmente.
- Los prefijos de modelo desconocidos recurren a un tokenizador genérico para presupuestar, que es cosmético; la petición en sí lleva tu id sin cambios al endpoint.
Pago por uso · por debajo del precio oficial
Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.
| Modelo | Precio oficial | Nuestro precio |
|---|---|---|
| Claude Sonnet 4.6 | $3.00 / $15.00 per M | $2.40 / $12.00 per M |
| Claude Haiku 4.5 20251001 | $1.00 / $5.00 per M | $0.80 / $4.00 per M |
| GPT-5.4 mini | $0.75 / $4.50 per M | $0.60 / $3.60 per M |
| DeepSeek V4 Flash | $0.14 / $0.28 per M | $0.10 / $0.30 per M |
| Gemini 3.5 Flash | $1.50 / $9.00 per M | $1.20 / $7.20 per M |
Correcciones a mitos comunes sobre Quivr.
Las guías en circulación describen superficies que Quivr ya no tiene, así que merece la pena decir qué hace realmente el código actual. quivr-core está respaldado por LangChain, no por LiteLLM. El enum supplier selecciona una clase de chat de LangChain, y openai se mapea a ChatOpenAI con tu llm_base_url. Si un tutorial te dice que configures un proxy de LiteLLM o un ajuste api_base dentro de Quivr, describe una arquitectura más antigua; el campo actual es llm_base_url en LLMEndpointConfig. La app full-stack está retirada. Las instrucciones sobre un .env de backend, configuración de Supabase, o un selector de modelo dentro de la app se refieren a la aplicación pre-pivote, que ya no es lo que distribuye el repositorio. La configuración ahora ocurre en tu código Python (o tu propia app alrededor de la librería). La variable de entorno de la clave se deriva del supplier. Para el supplier openai es OPENAI_API_KEY, incluso cuando el endpoint no es OpenAI. Si prefieres no sobrecargar ese nombre, pasa llm_api_key explícitamente en la configuración, que tiene precedencia y mantiene el entorno limpio. El embedder es separado. Enrutar la generación no mueve los embeddings; el embedder por defecto es OpenAIEmbeddings con sus propias credenciales. Decide las dos mitades de forma independiente, y reincrustar un almacén existente solo hace falta si cambias el propio modelo de embedding.
Quién enruta quivr-core a través de un gateway.
- Equipos de producto que incrustan RAG en sus apps y quieren que el modelo de generación sea un valor de configuración, no un compromiso de proveedor incrustado en la pila.
- Desarrolladores que ejecutan muchos brains en distintos niveles de calidad: una clave, un endpoint, id de modelo por brain.
- Equipos que quieren respuestas fundamentadas con calidad Claude detrás de una configuración con forma de OpenAI sin añadir un segundo SDK o cuenta de proveedor.
- Creadores que hacen benchmark de modelos de generación sobre un corpus fijo, donde cada candidato es un cambio de LLMEndpointConfig.
- Desarrolladores sin acceso a la facturación de un proveedor concreto. El acceso mediante recarga sin necesidad de tarjeta elimina la dependencia de registrarse en cada proveedor.
Verifica el endpoint y depura el primer ask().
Confirma que el gateway lista tu modelo antes de ingerir nada; el campo model debe coincidir exactamente con un id servido. Los fallos de primera ejecución son predecibles. Una advertencia de que la clave de API para el supplier openai no está configurada significa que ni llm_api_key ni OPENAI_API_KEY eran visibles cuando se construyó la configuración; la advertencia ocurre en la construcción, el fallo en el primer ask(). Un 401 significa que la clave resuelta no pertenece al endpoint en llm_base_url. Un error de modelo no encontrado es una errata de id contra /v1/models. Y un error de autenticación relacionado con embeddings durante Brain.from_files es el embedder por defecto separado pidiendo sus propias credenciales de OpenAI, algo que ningún ajuste de llm_base_url arreglará; pasa un embedder que controles. Una vez que las respuestas fluyen, la consola de APIsRouter muestra el modelo por petición, el recuento de tokens y el gasto. Para una librería que empaqueta fragmentos recuperados en cada prompt, el número de tokens por respuesta sobre tu corpus real es la cifra que debería guiar tu elección de modelo.
curl -s https://api.apisrouter.com/v1/models \
-H "Authorization: Bearer $APISROUTER_API_KEY" | head -50Preguntas frecuentes
¿Quivr admite una base URL personalizada compatible con OpenAI?
Sí. El LLMEndpointConfig de quivr-core tiene un campo llm_base_url, y para el supplier openai la librería construye el ChatOpenAI de LangChain contra esa URL. Configúralo al endpoint del gateway y pasa cualquier id de modelo del catálogo.
¿Quivr está basado en LiteLLM?
No en la base de código actual. quivr-core selecciona clases de chat de LangChain por supplier; el supplier openai usa ChatOpenAI con tu llm_base_url. Las guías que describen un api_base de LiteLLM dentro de Quivr se refieren a una arquitectura más antigua.
¿Puede brain.ask() responder con modelos de Claude o DeepSeek?
Sí. El campo model se reenvía como un string simple sobre /v1/chat/completions, así que claude-sonnet-4-6, deepseek-v4-flash, o cualquier otro id que sirva el endpoint funciona bajo el supplier openai.
¿Qué variable de entorno contiene la clave?
Cuando llm_api_key no está configurada en la configuración, quivr-core deriva la variable del nombre del supplier: OPENAI_API_KEY para el supplier openai. Una llm_api_key explícita en LLMEndpointConfig tiene precedencia y evita sobrecargar ese nombre.
¿llm_base_url mueve también los embeddings?
No. El embedder por defecto es un cliente OpenAIEmbeddings separado con sus propias credenciales y endpoint. Enruta la generación a través del gateway y pasa tu propio embedder si también quieres la mitad de embedding fuera de OpenAI.
¿Sigue manteniéndose el proyecto Quivr?
El repositorio ha estado callado desde mediados de 2025, así que trátalo como una librería estable en lugar de una activa. La superficie llm_base_url documentada aquí coincide con la última rama main, y la app full-stack pre-pivote que reemplazó está retirada.