Fai girare il cervello RAG di Quivr su un endpoint compatibile OpenAI personalizzato.

Updated 2026-07-29

LLMEndpointConfig di quivr-core accetta un campo llm_base_url. Mantieni il supplier come openai, imposta llm_base_url su https://api.apisrouter.com/v1, passa una chiave, e ogni brain.ask() genera la sua risposta attraverso il gateway con qualsiasi id di modello del catalogo.

Risposta rapida: llm_base_url in LLMEndpointConfig.

Quivr attuale è quivr-core, una libreria RAG in Python, e il suo collegamento LLM è esplicito. LLMEndpointConfig porta supplier (openai di default), model, llm_base_url e llm_api_key; LLMEndpoint.from_config() costruisce il client vero e proprio da questi campi, e per il supplier openai quel client è ChatOpenAI di LangChain costruito con la tua base URL. Imposta llm_base_url su https://api.apisrouter.com/v1, imposta model su qualsiasi id del catalogo, e passa l'endpoint al tuo Brain. La chiave può venire dal campo di configurazione o dall'ambiente: quando llm_api_key non è impostato, quivr-core la risolve da una variabile d'ambiente il cui nome deriva dal supplier, che per il supplier openai è OPENAI_API_KEY. Entrambi i percorsi sono comportamento upstream, leggibile in quivr_core/rag/entities/config.py e 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"],
))

Cos'è Quivr oggi, e dove si colloca lo slot LLM.

Quivr (QuivrHQ su GitHub, circa 39K stelle) è iniziato come applicazione completa da "secondo cervello" ed è passato a quivr-core: una libreria RAG opinionata che incorpori nel tuo stesso prodotto. Gli dai in pasto dei file, lei li analizza e li suddivide in chunk, incorpora i chunk in un vector store (FAISS di default, PGVector supportato), e risponde a domande su di essi tramite un flusso di recupero configurabile. L'oggetto Brain è l'unità: Brain.from_files() fa l'ingestione, brain.ask() recupera e genera. La generazione è l'unico passaggio che richiede un chat model. Il flusso di recupero assembla il contesto dai tuoi documenti, e l'LLMEndpoint che hai passato scrive la risposta ancorata alle fonti. Quell'endpoint viene costruito una sola volta da LLMEndpointConfig, quindi la decisione sulla base URL viene presa al momento della costruzione e si applica a ogni ask() su quel brain. Poiché ChatOpenAI inoltra il campo model come stringa semplice su /v1/chat/completions, l'id può essere Claude, DeepSeek, GPT o Gemini quando l'endpoint dietro llm_base_url li serve. Una nota onesta sullo stato del progetto: il repository è silenzioso dalla metà del 2025, quindi tratta quivr-core come una libreria stabile piuttosto che in rapida evoluzione. La superficie di configurazione descritta qui corrisponde all'ultimo branch main, e la storia silenziosa fa sì che sia improbabile che cambi sotto di te; significa anche che i vecchi tutorial che descrivono l'app full-stack ritirata (file .env di backend, un frontend ospitato) non corrispondono più al codice.

Configurazione completa: un brain con un LLM instradato tramite gateway.

Il pattern completo passa l'LLMEndpoint configurato a Brain.from_files. Tutto il resto del brain (parsing, chunking, lo store FAISS, il flusso di recupero) è indipendente dall'endpoint LLM e mantiene i suoi default. Fai attenzione all'embedder. Se non ne passi uno, quivr-core costruisce OpenAIEmbeddings di LangChain con i suoi default, che si autentica con OPENAI_API_KEY e punta all'endpoint OpenAI di serie. Quello è un client separato dall'LLM di chat: instradare la generazione attraverso il gateway non lo sposta. Passa il tuo embedder (un wrapper locale di sentence-transformers, o qualsiasi istanza Embeddings di LangChain che configuri tu) se non vuoi che la metà dedicata all'embedding dipenda da un account 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)

Scegliere un modello di generazione per le risposte RAG.

Confrontare i candidati è un cambiamento al momento della costruzione: costruisci due LLMEndpoint contro la stessa base URL, due brain sugli stessi file, e confronta le risposte su un set di domande fisso. Il log di utilizzo per chiave mette un prezzo a ogni esecuzione candidata, così la qualità per token si misura invece di discuterla.

  • La generazione RAG è ad alto consumo di input: i chunk recuperati dominano il prompt. Il prezzo per token di input determina il costo di una risposta, il che è il motivo per cui un id veloce spesso dimezza il conto senza toccare la qualità del recupero.
  • claude-sonnet-4-6 è la scelta predefinita affidabile per risposte ancorate che rispettano il contesto recuperato e rifiutano in modo pulito quando i documenti non contengono la risposta.
  • I prodotti embedded ad alto volume (il caso d'uso dichiarato di Quivr) funzionano bene con claude-haiku-4-5-20251001, deepseek-v4-flash o gemini-3.5-flash per il mix di domande quotidiane.
  • max_context_tokens nella stessa configurazione governa quanto contesto recuperato il pipeline impacchetta; alzarlo si abbina naturalmente a id a contesto lungo e alza proporzionalmente la spesa in input.
  • I prefissi di modello sconosciuti tornano a un tokenizer generico per il budgeting, il che è puramente cosmetico; la richiesta stessa porta il tuo id invariato all'endpoint.

Pagamento a consumo · sotto i prezzi ufficiali

Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.

ModelloPrezzo ufficialeIl nostro prezzo
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

Correzioni al folklore comune su Quivr.

Le guide in circolazione descrivono superfici che Quivr non ha più, quindi vale la pena affermare cosa fa davvero il codice attuale. quivr-core è basato su LangChain, non su LiteLLM. L'enum supplier seleziona una classe di chat di LangChain, e openai mappa su ChatOpenAI con il tuo llm_base_url. Se un tutorial ti dice di configurare un proxy LiteLLM o un'impostazione api_base dentro Quivr, descrive un'architettura più vecchia; il campo attuale è llm_base_url su LLMEndpointConfig. L'app full-stack è ritirata. Le istruzioni su un .env di backend, un setup Supabase o un selettore di modello in-app si riferiscono all'applicazione pre-pivot, che non è più ciò che il repository distribuisce. La configurazione ora avviene nel tuo codice Python (o nella tua app costruita attorno alla libreria). La variabile d'ambiente della chiave è derivata dal supplier. Per il supplier openai è OPENAI_API_KEY, anche quando l'endpoint non è OpenAI. Se preferisci non sovraccaricare quel nome, passa llm_api_key esplicitamente nella configurazione, che ha la precedenza e mantiene pulito l'ambiente. L'embedder è separato. Instradare la generazione non sposta gli embedding; l'embedder di default è OpenAIEmbeddings con le proprie credenziali. Decidi le due metà in modo indipendente, e ri-incorporare uno store esistente serve solo se cambi il modello di embedding stesso.

Chi instrada quivr-core tramite un gateway.

  • Team di prodotto che incorporano RAG nelle loro app e vogliono che il modello di generazione sia un valore di configurazione, non un impegno verso un fornitore incorporato nello stack.
  • Sviluppatori che eseguono molti brain a livelli di qualità diversi: una chiave, un endpoint, un id di modello per brain.
  • Team che vogliono risposte ancorate di qualità Claude dietro una configurazione a forma OpenAI senza aggiungere un secondo SDK o account fornitore.
  • Builder che fanno benchmark dei modelli di generazione su un corpus fisso, dove ogni candidato è un cambiamento di LLMEndpointConfig.
  • Sviluppatori senza accesso alla fatturazione di un dato fornitore. L'accesso basato su ricarica senza obbligo di carta rimuove la dipendenza dalla registrazione per provider.

Verifica l'endpoint e fai debug del primo ask().

Conferma che il gateway elenchi il tuo modello prima di fare ingestione di qualsiasi cosa; il campo model deve corrispondere esattamente a un id servito. I fallimenti al primo avvio sono prevedibili. Un avviso che la chiave API per il supplier openai non è impostata significa che né llm_api_key né OPENAI_API_KEY erano visibili quando la configurazione è stata costruita; l'avviso avviene alla costruzione, il fallimento al primo ask(). Un 401 significa che la chiave risolta non appartiene all'endpoint in llm_base_url. Un errore modello-non-trovato è un errore di battitura nell'id rispetto a /v1/models. E un errore di autenticazione legato all'embedding durante Brain.from_files è il separato embedder di default che chiede le proprie credenziali OpenAI, cosa che nessuna impostazione llm_base_url risolverà; passa un embedder che controlli tu. Una volta che le risposte scorrono, la console di APIsRouter mostra il modello per richiesta, i conteggi dei token e la spesa. Per una libreria che impacchetta chunk recuperati in ogni prompt, il numero di token per risposta sul tuo corpus reale è la cifra che dovrebbe guidare la tua scelta di modello.

curl -s https://api.apisrouter.com/v1/models \
  -H "Authorization: Bearer $APISROUTER_API_KEY" | head -50

Domande frequenti

Quivr supporta una base URL personalizzata compatibile OpenAI?

Sì. LLMEndpointConfig di quivr-core ha un campo llm_base_url, e per il supplier openai la libreria costruisce ChatOpenAI di LangChain contro quell'URL. Impostalo sull'endpoint del gateway e passa qualsiasi id di modello del catalogo.

Quivr è basato su LiteLLM?

Non nel codebase attuale. quivr-core seleziona le classi di chat di LangChain per supplier; il supplier openai usa ChatOpenAI con il tuo llm_base_url. Le guide che descrivono un api_base LiteLLM dentro Quivr si riferiscono a un'architettura più vecchia.

brain.ask() può rispondere con modelli Claude o DeepSeek?

Sì. Il campo model viene inoltrato come stringa semplice su /v1/chat/completions, quindi claude-sonnet-4-6, deepseek-v4-flash, o qualsiasi altro id servito dall'endpoint funziona sotto il supplier openai.

Quale variabile d'ambiente contiene la chiave?

Quando llm_api_key non è impostato nella configurazione, quivr-core deriva la variabile dal nome del supplier: OPENAI_API_KEY per il supplier openai. Un llm_api_key esplicito in LLMEndpointConfig ha la precedenza ed evita di sovraccaricare quel nome.

llm_base_url sposta anche gli embedding?

No. L'embedder di default è un client OpenAIEmbeddings separato con le proprie credenziali ed endpoint. Instrada la generazione attraverso il gateway e passa il tuo embedder se vuoi che anche la metà dedicata all'embedding sia fuori da OpenAI.

Il progetto Quivr è ancora mantenuto?

Il repository è silenzioso dalla metà del 2025, quindi trattalo come una libreria stabile piuttosto che attiva. La superficie llm_base_url documentata qui corrisponde all'ultimo branch main, e l'app full-stack pre-pivot che ha sostituito è ritirata.