Draai paper-qa tegen een aangepast OpenAI-compatibel endpoint.

Updated 2026-07-30

paper-qa configureert zijn modellen via LiteLLM-router-dicts, en litellm_params accepteert api_base. Wijs hem naar https://api.apisrouter.com/v1, geef één sleutel door, en de answer-, summary- en agent-slots kunnen elk elk catalogusmodel draaien over je eigen paperbibliotheek.

Snel antwoord: een router-dict met api_base, hergebruikt per slot.

Het Settings-object van paper-qa neemt een modelnaam plus een optionele LiteLLM-routerconfig per slot. De routerconfig is een model_list wiens litellm_params api_base en api_key dragen, wat hetzelfde gedocumenteerde patroon is dat de README gebruikt voor lokaal gehoste OpenAI-compatibele servers; een gateway is simpelweg dat patroon met een publieke URL en een echte sleutel. Zet llm en summary_llm op de model_name die je hebt verklaard, koppel de config aan beide slots, en paper-qa routeert via de gateway. De model-string binnen litellm_params houdt de providerconventie van litellm aan: openai/<id> vertelt litellm om chat completions te spreken tegen je api_base, en het ID na de slash wordt doorgegeven aan het endpoint, dus Claude-, GPT-, Gemini- en GLM-ID's zijn allemaal aanspreekbaar met dezelfde dict.

gateway_config = dict(
    model_list=[
        dict(
            model_name="claude-sonnet-4-6",
            litellm_params=dict(
                model="openai/claude-sonnet-4-6",
                api_base="https://api.apisrouter.com/v1",
                api_key=os.getenv("APISROUTER_API_KEY"),
                temperature=0.1,
            ),
        )
    ]
)

Waar paper-qa tokens uitgeeft: drie slots plus embeddings.

paper-qa (Future-House op GitHub, ongeveer 9K sterren) doet retrieval-augmented question answering over wetenschappelijke PDF's met een agentic lus erbovenop: een agent beslist wanneer je bibliotheek te doorzoeken, verzamelt bewijsstukken, vat hun relevantie samen, en stelt een geciteerd antwoord samen. Dat mapt op drie apart configureerbare LLM-slots. summary_llm evalueert en condenseert bewijs per opgehaald stuk, wat het volumeslot maakt. llm schrijft het uiteindelijke antwoord uit het samengestelde bewijs, de kwaliteitskritieke stap. En agent_llm (binnen de agentinstellingen) neemt de tool-selectiebeslissingen die de lus sturen. Alle drie vallen standaard terug op een OpenAI-model, en elk heeft een bijpassend _config-veld (llm_config, summary_llm_config, agent_llm_config) dat dezelfde router-dict accepteert, dus één gatewayconfigobject kan aan elk slot worden gekoppeld terwijl de modelnaam per slot onafhankelijk blijft. Een gangbare splitsing is een snel ID dat bewijs samenvat en een frontier-ID dat antwoorden schrijft, beide via één endpoint en sleutel. Embeddings zijn de vierde workload en doelbewust apart: de embeddinginstelling (standaard text-embedding-3-small) bouwt de vectorindex van je papers. Chatslots naar een gateway verplaatsen verplaatst embeddings niet, en paper-qa ondersteunt lokale sentence-transformers (het voorvoegsel st-, via de local-extras) als je de index volledig onafhankelijk van elk extern endpoint wilt houden.

Volledige instelling: Settings met configs per slot.

Het volledige patroon verklaart één routervermelding per model dat je aanspreekbaar wilt en koppelt configs slot voor slot. Twee vermeldingen verklaren, een snelle voor samenvattingen en een sterke voor antwoorden, houdt de hele instelling in één dict. Dezelfde routering werkt vanuit de CLI, aangezien pqa het instellingenoppervlak blootstelt, maar het Python-pad is het reproduceerbare voor onderzoeksgebruik: het Settings-object dat een antwoord produceerde kan naast het antwoord zelf worden gelogd.

import os
from paperqa import Settings, ask
from paperqa.settings import AgentSettings

def entry(model_id, **params):
    return dict(
        model_name=model_id,
        litellm_params=dict(
            model=f"openai/{model_id}",
            api_base="https://api.apisrouter.com/v1",
            api_key=os.getenv("APISROUTER_API_KEY"),
            **params,
        ),
    )

gateway = dict(model_list=[
    entry("claude-sonnet-4-6", temperature=0.1),
    entry("claude-haiku-4-5-20251001", temperature=0.1),
])

answer = ask(
    "What is the evidence for LK-99 room-temperature superconductivity?",
    settings=Settings(
        llm="claude-sonnet-4-6",
        llm_config=gateway,
        summary_llm="claude-haiku-4-5-20251001",
        summary_llm_config=gateway,
        agent=AgentSettings(
            agent_llm="claude-sonnet-4-6",
            agent_llm_config=gateway,
        ),
        paper_directory="./papers",
    ),
)

Modellen kiezen per slot.

Tune met de bewijspijplijn vast: dezelfde bibliotheek, dezelfde vragen, wissel één slot per keer. Achter één endpoint is elke kandidaat een model_name-string, en het gebruikslogboek per sleutel prijst elke configuratie per vraag, wat het cijfer is dat een lab daadwerkelijk budgetteert.

  • summary_llm draait eenmaal per bewijsstuk, elke vraag. Op een serieuze bibliotheek is dit de overweldigende meerderheid van de aanroepen, dus een snel ID (claude-haiku-4-5-20251001) zet de kostenondergrens voor het hele systeem terwijl het alleen relevantie hoeft te beoordelen, geen proza te schrijven.
  • llm stelt het geciteerde antwoord samen uit verzameld bewijs. Hier gebeurt gehedgede, precieze wetenschappelijke schrijfstijl of niet; claude-sonnet-4-6 en gpt-5.5 zijn de betrouwbare keuzes, en het slot heeft weinig aanroepen per vraag dus de premie is begrensd.
  • agent_llm stuurt de lus: opnieuw zoeken, meer bewijs verzamelen, of antwoorden. Zwakke beslissingen hier verspillen tokens overal elders, wat een mid-tier of beter ID de economische keuze maakt ondanks het lage volume van het slot.
  • Langecontext-ID's zoals gemini-3.1-pro-preview zijn het waard om te testen als het answer-slot wanneer vragen bewijs uit veel papers tegelijk trekken.

Betaal naar gebruik · onder officiële prijzen

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

ModelOfficiële prijsOnze prijs
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.5$5.00 / $30.00 per M$4.00 / $24.00 per M
Gemini 3.1 Pro Preview$2.00 / $12.00 per M$1.60 / $9.60 per M
GLM-5.2$1.14 / $4.00 per M$1.10 / $4.00 per M

De faalmodi specifiek voor paper-qa.

Een slot achtergelaten op zijn standaard. llm en llm_config instellen maar niet summary_llm_config laat samenvatting op het standaard OpenAI-model, dat dan OPENAI_API_KEY eist en faalt (of stilletjes je routering over twee endpoints splitst als die sleutel bestaat). Elk slot heeft zijn eigen _config-veld; koppel de gateway-dict aan elk slot dat je van plan bent te verplaatsen, agent_llm_config inbegrepen. Namen die niet overeenkomen. Settings.llm moet gelijk zijn aan een model_name in de model_list; litellm_params.model is wat daadwerkelijk over de wire gaat. Mismatch de buitenste naam en de router heeft geen route; tikfout het binnenste ID en de gateway retourneert model-not-found. Controleer bij het debuggen de twee strings apart omdat ze anders falen. Embeddings waarvan wordt aangenomen dat ze volgen. Het embeddingslot bouwt en bevraagt de vectorindex en heeft zijn eigen standaard en config. Als je geen OpenAI-sleutel hebt voor de standaardembedding, configureer embedding expliciet, of gebruik lokale sentence-transformers via het voorvoegsel st-. Embeddings later herwijzen betekent ook herindexeren: vectoren van verschillende embeddingmodellen mixen niet. Ontbrekende generatielimieten voor lange antwoorden. litellm_params accepteert max_tokens per vermelding, en de lokale-endpointvoorbeelden upstream zetten het doelbewust. Een answer-slot zonder verstandige limiet kan lange geciteerde antwoorden afkappen, wat zich voordoet als modelzwakte maar een parameter is. Routering de schuld geven van parsingproblemen. De kwaliteit van paper-qa hangt af van PDF-parsing en chunking voordat enig model tekst ziet. Als antwoorden niets citeren op een bibliotheek waarvan je weet dat hij relevant is, inspecteer dan de indexeringsstap; de gateway ziet alleen wat retrieval hem stuurt.

Wie routeert paper-qa via een gateway.

  • Onderzoeksgroepen die literatuur-QA draaien over gedeelde bibliotheken, waar gebruik per sleutel "wat besteedt het lab per vraag" verandert van gissen naar een rapport.
  • Teams die Claude-kwaliteit wetenschappelijk schrijven willen in het answer-slot terwijl het samenvattingsvolume op een snel ID blijft, één sleutel voor beide.
  • Bouwers die paper-qa inbedden in interne tools, die een bundel leverancierssecrets vervangen door één gatewaycredential per omgeving.
  • Benchmarkers die answer-modellen vergelijken op vaste bewijspijplijnen, waar elke kandidaat een configstring is in plaats van een leveranciersintegratie.
  • Developers zonder toegang tot de facturering van een bepaalde leverancier. Toegang op basis van opwaarderen zonder kaartvereiste verwijdert de aanmeldingsafhankelijkheid per provider.

Verifieer het endpoint en debug de eerste vraag.

Bevestig dat de gateway de ID's bedient die je hebt verklaard; de litellm_params.model-string na openai/ moet exact overeenkomen met een bediend ID. De faalladder op een eerste ask(): een fout die OPENAI_API_KEY eist betekent dat een slot nog op zijn standaardmodel staat zonder gekoppelde config; zoek uit welke van llm, summary_llm en agent_llm je niet hebt verplaatst. Een 401 van de gateway is de api_key binnen litellm_params. Een routerfout over een onbekend model betekent dat Settings.llm niet overeenkomt met een model_name in de lijst. Fouten tijdens indexering in plaats van beantwoording wijzen naar de embeddinginstelling of PDF-parsing, niet naar chatroutering. Eén vraag waaiert uit in veel samenvattingsaanroepen plus agentstappen plus het uiteindelijke antwoord, dus na de eerste geslaagde run toont de weergave per verzoek van de APIsRouter-console de slotsplitsing in echte tokens. Dat is het cijfer om in de gaten te houden naarmate de bibliotheek groeit, omdat samenvattingsvolume schaalt met opgehaald bewijs, niet alleen met vraagaantal.

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

Veelgestelde vragen

Hoe ondersteunt paper-qa een aangepaste OpenAI-compatibele base URL?

Via zijn LiteLLM-routerconfigs: elk van llm_config, summary_llm_config en agent_llm_config accepteert een model_list wiens litellm_params api_base en api_key bevatten. Dit is hetzelfde gedocumenteerde patroon dat paper-qa gebruikt voor lokaal gehoste OpenAI-compatibele servers, nu gewezen naar een gateway-URL.

Kunnen het answer- en summary-model van verschillende leveranciers komen?

Ja. Elk slot koppelt een modelnaam aan zijn eigen config, dus een snel Claude-ID kan bewijs samenvatten terwijl GPT-5.5 of Gemini het uiteindelijke antwoord schrijft, allemaal via één api_base en één sleutel. Verklaar één model_list-vermelding per ID en verwijs ernaar per slot.

Moet ik ook het embeddingmodel wijzigen?

Nee, en meestal moet je dat niet in dezelfde stap doen. De embeddinginstelling is onafhankelijk van de chatslots, en het wisselen van embeddingmodellen maakt je bestaande vectorindex ongeldig. Als je geen sleutel hebt voor de standaardembedding, zet embedding expliciet of gebruik lokale sentence-transformers met het voorvoegsel st-.

Wat is het agent_llm-slot en heeft het de config ook nodig?

agent_llm, binnen AgentSettings, stuurt toolselectie: wanneer te zoeken, bewijs te verzamelen, of te antwoorden. Het valt standaard terug op een OpenAI-model zoals de andere slots, dus koppel agent_llm_config met dezelfde gateway-dict of het probeert nog steeds naar de standaardprovider te routeren.

Waarom vraagt paper-qa nog steeds om OPENAI_API_KEY na mijn override?

Ten minste één slot staat nog op zijn standaardmodel zonder gekoppelde routerconfig. Controleer llm, summary_llm en agent_llm plus hun _config-velden; de fout noemt het model dat het probeerde aan te roepen, wat het gemiste slot identificeert.

Werkt dit ook vanuit de pqa-CLI, net als Python?

De CLI stelt hetzelfde instellingenoppervlak bloot, maar voor gatewayroutering is het Python-pad het praktische: router-dicts zijn onhandig als commandoregelflags, en een Settings-object gelogd naast resultaten maakt onderzoeksruns reproduceerbaar.