Stanford STORM auf einem custom OpenAI-kompatiblen Endpoint betreiben.
Updated 2026-07-29
STORM baut jedes Sprachmodell als LitellmModel, und litellm akzeptiert api_base. Trag https://api.apisrouter.com/v1 in dein geteiltes openai_kwargs ein, präfixiere Model-IDs mit openai/, und alle fünf LM-Slots der Artikel-Pipeline routen über einen Endpoint und einen Key.
Kurzantwort: api_base in openai_kwargs, openai/-Präfix auf IDs.
STORMs LitellmModel speichert, welche Kwargs auch immer du bei der Konstruktion übergibst, und mischt sie in jeden litellm.completion()-Call. litellms api_base-Parameter ist, wie du den openai-Provider auf einen anderen Host zeigst, also ist das Hinzufügen von api_base zum openai_kwargs-Dict, das STORMs eigene Beispiele schon nutzen, der ganze Override. Präfixiere jede Model-ID mit openai/, damit litellm das Chat-Completions-Protokoll gegen diese Base spricht, und der String nach dem Slash wird unverändert ans Gateway weitergereicht. Weil die Beispiele ein openai_kwargs-Dict bauen und für jedes Modell wiederverwenden, leitet ein hinzugefügter Key die gesamte Pipeline um. Keine STORM-Code-Änderungen, kein Fork; das ist Standard-knowledge_storm-Verhalten, das auf litellms dokumentiertem Routing aufsetzt.
openai_kwargs = {
"api_key": os.getenv("APISROUTER_API_KEY"),
"api_base": "https://api.apisrouter.com/v1",
"temperature": 1.0,
"top_p": 0.9,
}
fast = LitellmModel(model="openai/deepseek-v4-flash", max_tokens=500, **openai_kwargs)
strong = LitellmModel(model="openai/claude-sonnet-4-6", max_tokens=3000, **openai_kwargs)Wie STORM einen Artikel auf fünf LM-Slots aufteilt.
STORM (stanford-oval auf GitHub, rund 30.000 Stars) schreibt Wikipedia-artige Reports von Grund auf: es recherchiert ein Thema über simulierte Multi-Perspektiven-Konversationen, baut ein Outline aus dem Gelernten, generiert den vollständigen Artikel Abschnitt für Abschnitt, und poliert ihn dann. STORMWikiLMConfigs exponiert diese Pipeline als fünf unabhängig einstellbare Modelle: conv_simulator_lm und question_asker_lm treiben die Recherche-Konversationen, outline_gen_lm strukturiert den Artikel, article_gen_lm schreibt ihn, und article_polish_lm macht den finalen Durchgang. Das Upstream-README ist explizit über die Ökonomie: der Conversation-Simulator läuft mit dem höchsten Call-Volumen, also empfiehlt es dort ein schnelleres Modell und ein stärkeres für die Artikelgenerierung. Diese Empfehlung ging davon aus, zwischen OpenAI-Modellen zu wählen; hinter einem Multi-Vendor-Endpoint verallgemeinert sie sich zu etwas Nützlicherem. Jeder Slot ist sein eigenes LitellmModel mit eigenem model-String, sodass das Recherche-Geplauder auf einer schnellen DeepSeek-ID laufen kann, während Outline- und Artikelgenerierung auf Claude laufen, und Polish auf welchem Modell auch immer du für Ton vertraust, alles authentifiziert mit demselben Key gegen dieselbe api_base. Die Retrieval-Seite ist eine separate Maschinerie: STORMs Runner nimmt ein RM-Modul (You.com, Bing und mehrere andere Such-Backends) mit eigenem API-Key. Zu ändern, wohin die Sprachmodelle zeigen, berührt nicht, wie Quellen abgerufen werden.
Vollständiges Setup: fünf Slots, ein kwargs-Dict.
Das funktionierende Muster spiegelt die eigenen Run-Skripte des Repos: bau das geteilte kwargs einmal, konstruiere ein LitellmModel pro Rolle, und weise sie über die STORMWikiLMConfigs-Setter zu. Der api_key kann jeder Name sein, den du magst, da du ihn explizit übergibst; das Beispiel nutzt eine eigene Variable, um klarzustellen, dass dies kein OpenAI-Konto-Credential ist. litellm respektiert auch Provider-Level-Umgebungsvariablen, und der openai-Provider liest OPENAI_API_BASE, also ist ein reiner Umgebungs-Override möglich. Der explizite kwargs-Pfad bleibt trotzdem vorzuziehen: er ist im Code sichtbar, der einen bestimmten Artikel produziert hat, er überlebt, auf einem Rechner mit anderem Umgebungszustand ausgeführt zu werden, und er macht Per-Slot-Ausnahmen möglich, falls du je eine Stufe auf einem anderen Endpoint willst.
import os
from knowledge_storm import STORMWikiRunnerArguments, STORMWikiRunner, STORMWikiLMConfigs
from knowledge_storm.lm import LitellmModel
from knowledge_storm.rm import YouRM
openai_kwargs = {
"api_key": os.getenv("APISROUTER_API_KEY"),
"api_base": "https://api.apisrouter.com/v1",
"temperature": 1.0,
"top_p": 0.9,
}
fast = LitellmModel(model="openai/deepseek-v4-flash", max_tokens=500, **openai_kwargs)
strong = LitellmModel(model="openai/claude-sonnet-4-6", max_tokens=3000, **openai_kwargs)
lm_configs = STORMWikiLMConfigs()
lm_configs.set_conv_simulator_lm(fast)
lm_configs.set_question_asker_lm(fast)
lm_configs.set_outline_gen_lm(strong)
lm_configs.set_article_gen_lm(strong)
lm_configs.set_article_polish_lm(strong)
engine_args = STORMWikiRunnerArguments(output_dir="./results")
rm = YouRM(ydc_api_key=os.getenv("YDC_API_KEY"), k=engine_args.search_top_k)
runner = STORMWikiRunner(engine_args, lm_configs, rm)
runner.run(topic="Small modular reactors")Modelle pro Pipeline-Stufe wählen.
Behandle die fünf Setter als Budget-Regler, nicht als Boilerplate. Upstream-Guidance sagt bereits, schnelle und starke Modelle über Stufen zu splitten; ein Multi-Vendor-Endpoint erweitert nur das Menü pro Stufe. Ändere zwischen Runs am selben Thema einen Slot nach dem anderen und diffe die Outputs, mit dem Nutzungslog pro Key, das jede Konfiguration bepreist.
- conv_simulator_lm und question_asker_lm sind die Volumen-Stufen: mehrstufige simulierte Interviews über mehrere Perspektiven pro Thema. deepseek-v4-flash oder eine andere schnelle ID hält davon ab, dass die Recherche-Phase die Ausgaben dominiert, und unvollkommenes Geplauder ist tolerierbar, weil es Notizen füttert, keine Prosa.
- article_gen_lm ist der Flaggschiff-Slot. Er schreibt lange, strukturierte, zitierte Abschnitte aus akkumulierter Recherche, sustained-Generation-Arbeit, wo claude-sonnet-4-6 oder gpt-5.5 kleinere IDs sichtbar übertreffen.
- outline_gen_lm hat wenige Calls mit überproportionaler Hebelwirkung, dieselbe Form wie ein Planungs-Slot: ein schwaches Outline deckelt den Artikel, egal wie gut der Autor ist. Es ist der natürliche Ort, um claude-opus-4-7 zu testen.
- article_polish_lm schreibt für Fluss um und entfernt Redundanz über den zusammengesetzten Artikel, was von einer Long-Context-ID profitiert; gemini-3.1-pro-preview lohnt hier einen Benchmark.
Nutzungsbasiert · unter offiziellem Preis
Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.
| Modell | Offizieller Preis | Unser Preis |
|---|---|---|
| DeepSeek V4 Flash | $0.14 / $0.28 per M | $0.10 / $0.30 per M |
| Claude Sonnet 4.6 | $3.00 / $15.00 per M | $2.40 / $12.00 per M |
| Claude Opus 4.7 | $5.00 / $25.00 per M | $4.00 / $20.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 |
Die Fehlerbilder speziell für STORM.
Eine bloße Model-ID routet per Inferenz, nicht über deine api_base. litellm liest das Präfix, um einen Provider zu wählen, und eine präfixlose Claude-ID wird als nativer Anthropic-Call inferiert, der dann ANTHROPIC_API_KEY will und dein Gateway komplett ignoriert. Jede fürs Gateway bestimmte ID muss das openai/-Präfix tragen; das Präfix benennt das Protokoll, nicht den Vendor. Ein zurückgelassener Slot. Jedes LitellmModel erfasst seine kwargs bei der Konstruktion. Teilen sich vier Slots openai_kwargs und wurde ein fünfter ad hoc ohne api_base gebaut, postet dieser Slot still an den Vendor-Default und scheitert an Auth, und der Traceback nennt eine Pipeline-Stufe statt einer Config-Zeile. Bau jeden Slot aus demselben Dict, und diese Bug-Klasse verschwindet. Retriever-Fehler, die dem Endpoint angelastet werden. Die Recherche-Phase braucht ein funktionierendes Such-Backend; ein ungültiger oder aufgebrauchter Retriever-Key (YDC_API_KEY, BING_SEARCH_API_KEY oder welches RM auch immer du gewählt hast) scheitert während der Informationssammlung. Diese Phase verschachtelt sich mit LM-Calls, lies also im Traceback, welcher Client geworfen hat, bevor du die LM-Config anfasst. Die secrets.toml der Demo ist nicht die Config deines Skripts. Die Streamlit-Demo liest secrets.toml; programmatische Runs lesen, was auch immer dein Skript übergibt. Das eine zu bearbeiten, während das andere läuft, ist ein klassischer Mismatch. max_tokens ist auch pro Slot. STORMs Beispiele setzen kleine Limits auf den schnellen Slots (500) und größere auf der Generierung (3000). Einen Slot auf ein Long-Form-Modell zu zeigen, ohne sein max_tokens anzuheben, kürzt still Abschnitte, was wie ein Modell-Qualitätsproblem aussieht, aber eine Konfigurationszahl ist.
Wer STORM über ein Gateway routet.
- Teams, die Wissens-Reports in Volumen generieren (Briefings, wiki-artige interne Docs, Themen-Primer), wo der Fünf-Slot-Split Per-Stufen-Kostentuning echtes Geld wert macht.
- Forscher, die Pipeline-Komposition studieren: welche Stufe von einem stärkeren Modell profitiert, ist eine empirische Frage, und ein Endpoint macht das Raster aus Slot-Modell-Kombinationen trivial durchzuprobieren.
- Builder, die Claude oder Gemini in den Schreib-Slots eines OpenAI-förmigen Stacks laufen lassen, ohne ein Vendor-SDK pro Modellfamilie hinzuzufügen.
- Jeder, der Batch-Themenlisten betreibt, wo sich Recherche-Phasen-Volumen über Themen vervielfacht und das Nutzungslog zum Kosten-Ledger pro Thema wird.
- Entwickler ohne Zugang zum Billing eines bestimmten Vendors. Guthabenbasierter Zugang ohne Kartenpflicht entfernt die Sign-up-Abhängigkeit pro Provider.
Endpoint verifizieren und den ersten Artikel debuggen.
Liste zuerst die Modelle des Gateways: der String nach openai/ in jedem Slot muss exakt zu einer bedienten ID passen. First-Run-Fehler folgen der Pipeline-Reihenfolge. Ein Auth-Fehler, der Anthropic oder Google nennt, bedeutet, eine präfixlose ID wurde nativ zu einem Provider geroutet; füge openai/ hinzu. Ein 401 vom Gateway bedeutet, der api_key in deinem kwargs ist nicht der Gateway-Key. Ein model-not-found-Fehler nennt den Slot, dessen ID einen Tippfehler hat. Fehler während der Recherche-Phase, die dein Such-Backend erwähnen, sind Retriever-Credentials, kein LM-Routing. Und gekürzte oder seltsam kurze Artikelabschnitte liegen meist an einem knauserigen max_tokens auf dem Generierungs-Slot statt an irgendetwas Upstream. Ein voller STORM-Run ist ein großer Burst: simulierte Konversationen über Perspektiven, dann Outline, Generierung und Polish. Ist einer abgeschlossen, zeigt die APIsRouter-Konsole Modell, Token-Zahlen und Ausgaben pro Anfrage, was sauber auf die fünf Slots abbildet und dir exakt sagt, welche Stufe vor dem nächsten Themen-Batch nachjustiert werden sollte.
curl -s https://api.apisrouter.com/v1/models \
-H "Authorization: Bearer $APISROUTER_API_KEY" | head -50Häufige Fragen
Wie unterstützt STORM einen custom OpenAI-kompatiblen Endpoint?
Über litellm. STORM baut jedes LM als LitellmModel, das seine Konstruktor-Kwargs in jeden litellm.completion()-Call mischt, und litellm akzeptiert api_base für den openai-Provider. Füge api_base zum openai_kwargs-Dict hinzu, und jeder daraus gebaute Slot routet zum Gateway.
Warum brauchen Model-IDs das openai/-Präfix?
litellm wählt den Provider aus dem Präfix. openai/claude-sonnet-4-6 bedeutet „sprich das OpenAI-Chat-Completions-Protokoll gegen meine api_base mit model claude-sonnet-4-6". Ohne das Präfix inferiert litellm den Vendor aus dem Namen und routet nativ, vorbei an deinem Endpoint.
Können verschiedene STORM-Stufen Modelle unterschiedlicher Vendoren nutzen?
Ja. Jeder der fünf Slots ist ein unabhängiges LitellmModel, sodass der Conversation Simulator eine DeepSeek-ID laufen lassen kann, während Artikelgenerierung Claude und Polish GPT nutzt, alles über dieselbe api_base und denselben Key. Upstream empfiehlt bereits, schnelle und starke Modelle über Stufen zu splitten.
Ändert sich der Such-Retriever, wenn ich api_base ändere?
Nein. Retrieval läuft über das RM-Modul, das du an STORMWikiRunner übergibst (You.com, Bing und andere unterstützte Backends) mit eigenem Key. LM-Routing und Quellen-Retrieval sind unabhängige Systeme, die in unterschiedlichen Phasen eines Runs scheitern.
Gibt es statt kwargs einen Umgebungsvariablen-Pfad?
litellm respektiert Provider-Level-Variablen, und der openai-Provider liest OPENAI_API_BASE. Es funktioniert, aber das explizite api_base-Kwarg ist reproduzierbarer: es reist mit dem Skript, überlebt Rechner mit anderem Umgebungszustand, und erlaubt Per-Slot-Ausnahmen.
Wie viele Token verbraucht ein STORM-Artikel?
Die Recherche-Phase dominiert: mehrperspektivische simulierte Konversationen vervielfachen Calls, bevor auch nur ein Wort des Artikels existiert, dann fügen Generierung und Polish Long-Form-Output obendrauf. Volle Runs landen häufig im sechsstelligen Token-Bereich, und die Nutzungsansicht pro Key zeigt den exakten Per-Stufen-Split.