Patakbuhin ang Stanford STORM sa isang custom OpenAI-compatible endpoint.
Updated 2026-07-30
Binubuo ng STORM ang bawat language model bilang isang LitellmModel, at tinatanggap ng litellm ang api_base. Ilagay ang https://api.apisrouter.com/v1 sa shared openai_kwargs mo, i-prefix ang mga model id ng openai/, at ire-ruta ng lahat ng limang LM slot ng article pipeline ang trapiko sa isang endpoint at isang key.
Mabilisang sagot: api_base sa openai_kwargs, openai/ prefix sa mga id.
Iniimbak ng LitellmModel ng STORM kung anumang mga kwargs ang ibinuo mo dito at pinagsasama ang mga ito sa bawat tawag ng litellm.completion(). Ang api_base parameter ng litellm ang paraan para ituro ang openai provider sa ibang host, kaya ang pagdadagdag ng api_base sa openai_kwargs dict na ginagamit na ng sariling mga halimbawa ng STORM ang buong override. I-prefix ang bawat model id ng openai/ para makipag-usap ang litellm sa chat-completions protocol sa base na iyon, at ang string pagkatapos ng slash ay ipinapasa sa gateway. Dahil bumubuo ang mga halimbawa ng isang openai_kwargs dict at ginagamit ito ulit para sa bawat model, isang idinagdag na key ang nagre-ruta sa buong pipeline. Walang pagbabago sa STORM code, walang fork; ito ay stock na behavior ng knowledge_storm na nakapatong sa naka-document na routing ng litellm.
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)Paano hinahati ng STORM ang isang artikulo sa limang LM slot.
Ang STORM (stanford-oval sa GitHub, humigit-kumulang 30K stars) ay nagsusulat ng mga report na estilong Wikipedia mula sa wala: sinasaliksik nito ang isang paksa sa pamamagitan ng mga simulated na usapan mula sa maraming perspektibo, bumubuo ng balangkas mula sa natutunan nito, gumagawa ng buong artikulo per seksyon, at pagkatapos ay nililinis ito. Inilalantad ng STORMWikiLMConfigs ang pipeline na iyon bilang limang model na independiyenteng maitatakda: pinapatakbo ng conv_simulator_lm at question_asker_lm ang mga usapan sa pananaliksik, iniaayos ng outline_gen_lm ang artikulo, isinusulat ito ng article_gen_lm, at ginagawa ng article_polish_lm ang huling pass. Malinaw ang upstream README tungkol sa ekonomiya: pinakamataas ang call volume ng conversation simulator, kaya inirerekomenda nito ang isang mas mabilis na model doon at isang mas malakas na model para sa article generation. Ipinagpalagay ng payo na iyon ang pagpili sa pagitan ng mga model ng OpenAI; sa likod ng isang multi-vendor na endpoint, nage-generalize ito sa isang bagay na mas kapaki-pakinabang. Sariling LitellmModel ang bawat slot na may sariling model string, kaya maaaring tumakbo ang research chatter sa isang mabilis na id ng DeepSeek habang tumatakbo sa Claude ang outline at article generation, at sa anumang model na pinagkakatiwalaan mo para sa tono ang polish, lahat pinapatunayan ng parehong key laban sa parehong api_base. Hiwalay na makinarya ang panig ng retrieval: kinukuha ng runner ng STORM ang isang RM module (You.com, Bing, at ilang ibang search backend) na may sariling API key. Hindi nahihipo ng pagbabago sa itinuturo ng mga language model kung paano kinukuha ang mga source.
Buong setup: limang slot, isang kwargs dict.
Sinasalamin ng gumaganang pattern ang sariling mga run script ng repo: buuin ang shared kwargs nang isang beses, bumuo ng isang LitellmModel per role, at i-assign ang mga ito sa pamamagitan ng mga setter ng STORMWikiLMConfigs. Maaaring anumang pangalan ang api_key dahil tahasan mo itong ipinapasa; gumagamit ang halimbawa ng sarili nitong variable para linawin na hindi ito isang credential ng OpenAI account. Iginagalang din ng litellm ang mga environment variable sa antas ng provider, at binabasa ng openai provider ang OPENAI_API_BASE, kaya posible ang isang environment-only na override. Mananatiling mas mainam pumili ang tahasang path ng kwargs: nakikita ito sa code na gumawa ng isang partikular na artikulo, nakakaligtas ito sa isang makinang may ibang environment state, at pinapayagan nito ang mga eksepsiyon per slot kung gusto mo balang araw na iba ang endpoint ng isang stage.
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")Pagpili ng mga model per pipeline stage.
Ituring ang limang setter bilang dial ng budget, hindi boilerplate. Sinasabi na ng upstream guidance na paghatiin ang mabilis at malakas na mga model sa mga stage; ang isang multi-vendor na endpoint ay pinapalawak lamang ang menu per stage. Palitan ang isang slot sa isang pagkakataon sa pagitan ng mga run sa parehong paksa at i-diff ang mga output, na may per-key usage log na nagpepresyo sa bawat configuration.
- Ang conv_simulator_lm at question_asker_lm ang mga volume stage: multi-turn na simulated na panayam sa maraming perspektibo per paksa. Pinapanatili ng deepseek-v4-flash o ibang mabilis na id na hindi naghahari ang research phase sa gastos, at katanggap-tanggap ang di-perpektong chatter dahil nagpapakain ito ng mga tala, hindi prosa.
- Ang flagship na slot ang article_gen_lm. Isinusulat nito ang mahaba, structured, may citation na mga seksyon mula sa naipong pananaliksik, na sustained-generation na trabaho kung saan halatang nangunguna ang claude-sonnet-4-6 o gpt-5.5 sa mas maliliit na id.
- Kaunting tawag pero malaking leverage ang outline_gen_lm, kaparehong hugis ng isang planning slot: hinahangganan ng isang mahinang balangkas ang artikulo gaano man kagaling ang manunulat. Ito ang natural na lugar para subukan ang claude-opus-4-7.
- Muling isinusulat ng article_polish_lm ang daloy at inaalis ang duplikasyon sa buong naipong artikulo, na nakikinabang sa isang long-context na id; sulit i-benchmark dito ang gemini-3.1-pro-preview.
Pay-as-you-go · mas mababa sa opisyal na presyo
Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.
| Model | Opisyal na Presyo | Aming Presyo |
|---|---|---|
| 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 |
Ang mga failure mode na specific sa STORM.
Niruruta ng inference, hindi ng api_base mo, ang isang bare na model id. Binabasa ng litellm ang prefix para pumili ng provider, at ang isang Claude id na walang prefix ay nakikita bilang isang tawag na native sa Anthropic, na humihiling pagkatapos ng ANTHROPIC_API_KEY at binabalewala ang gateway mo nang lubusan. Dapat magdala ng openai/ prefix ang bawat id na papunta sa gateway; ang prefix ang nagbibigay-pangalan sa protocol, hindi sa vendor. Isang slot na naiwan. Kinukuha ng bawat LitellmModel ang mga kwargs nito sa oras ng construction. Kung apat na slot ang nagbabahagi ng openai_kwargs at ang ikalimang ginawa nang ad hoc nang walang api_base, tahimik na nagpo-post ang slot na iyon sa default ng vendor at nabibigo sa auth, at ang traceback ay pinapangalanan ang isang stage ng pipeline sa halip na isang linya ng config. Buuin ang bawat slot mula sa parehong dict at nawawala ang uring ito ng bug. Sinisisi ang endpoint sa mga kabiguan ng retriever. Nangangailangan ang research phase ng isang gumaganang search backend; kapag invalid o naubos na ang retriever key (YDC_API_KEY, BING_SEARCH_API_KEY, o kahit anong RM na pinili mo), nabibigo ang mga run sa panahon ng pagkolekta ng impormasyon. Nagsasalubong ang yugtong iyon sa mga tawag sa LM, kaya basahin ang traceback kung aling client ang nagbanggit bago hipuin ang LM config. Hindi ang config ng script mo ang secrets.toml ng demo. Binabasa ng Streamlit demo ang secrets.toml; binabasa ng mga programmatic na run kung anumang ipinapasa ng script mo. Klasikong hindi pagkakatugma ang pag-edit sa isa habang pinapatakbo ang isa. Per-slot din ang max_tokens. Itinatakda ng mga halimbawa ng STORM ang maliliit na limitasyon sa mabilis na slots (500) at mas malaki sa generation (3000). Ang pagturo ng isang slot sa isang long-form na model nang hindi itinataas ang max_tokens nito ay tahimik na nagti-trim ng mga seksyon, na tila problema sa kalidad ng model pero isa lamang numero sa config.
Sino ang nagru-route ng STORM sa pamamagitan ng isang gateway.
- Mga team na gumagawa ng knowledge reports sa volume (briefs, wiki-style na internal docs, topic primers), kung saan ginagawang karapat-dapat sa tunay na pera ang paghahati sa limang slot para sa per-stage na cost tuning.
- Mga mananaliksik na nag-aaral ng komposisyon ng pipeline: empirical na tanong kung aling stage ang nakikinabang sa isang mas malakas na model, at ginagawang madali ng isang endpoint na i-enumerate ang grid ng mga kombinasyon ng slot at model.
- Mga builder na nagpapatakbo ng Claude o Gemini sa mga writing slot ng isang OpenAI-shaped na stack, nang hindi nagdaragdag ng vendor SDK per model family.
- Sinuman na nagpapatakbo ng batch na listahan ng paksa, kung saan pinaparami ng volume ng research phase ang bawat paksa at nagiging per-topic na cost ledger ang usage log.
- Mga developer na walang access sa billing ng isang partikular na vendor. Ang top-up based na access na walang kailangang card ay inaalis ang per-provider na sign-up dependency.
I-verify ang endpoint at i-debug ang unang artikulo.
Ilista muna ang mga model ng gateway: dapat eksaktong tumugma ang string pagkatapos ng openai/ sa bawat slot sa isang si-serve na id. Sumusunod sa order ng pipeline ang mga kabiguan sa unang run. Nangangahulugan ang isang auth error na binabanggit ang Anthropic o Google na niruta ang isang id na walang prefix patungo sa isang native na provider; idagdag ang openai/. Nangangahulugan ang isang 401 mula sa gateway na hindi gateway key ang api_key sa kwargs mo. Nagbibigay ng pangalan sa slot na may typo ang id ng isang model-not-found na error. Nangangahulugan ang mga kabiguan sa panahon ng research phase na binabanggit ang search backend mo na credentials ito ng retriever, hindi routing ng LM. At karaniwang nangangahulugan ang mga naputol o kakaibang maiikling seksyon ng artikulo na kuripot ang max_tokens sa generation slot sa halip na anumang bagay sa itaas. Malaking burst ang isang buong run ng STORM: simulated na usapan sa maraming perspektibo, pagkatapos ang balangkas, generation, at polish. Kapag natapos na ang isa, ipinapakita ng APIsRouter console ang per-request na model, token counts, at gastos, na malinaw na nakakabit sa limang slot at sinasabi sa iyo kung aling stage ang dapat mo unang i-tune ulit bago ang susunod na batch ng mga paksa.
curl -s https://api.apisrouter.com/v1/models \
-H "Authorization: Bearer $APISROUTER_API_KEY" | head -50Mga madalas itanong
Paano sinusuportahan ng STORM ang isang custom OpenAI-compatible endpoint?
Sa pamamagitan ng litellm. Binubuo ng STORM ang bawat LM bilang isang LitellmModel, na pinagsasama ang mga constructor kwargs nito sa bawat tawag ng litellm.completion(), at tinatanggap ng litellm ang api_base para sa openai provider. Idagdag ang api_base sa openai_kwargs dict at ire-ruta sa gateway ang bawat slot na binuo mula rito.
Bakit kailangan ng mga model id ng openai/ prefix?
Pinipili ng litellm ang provider mula sa prefix. Ang ibig sabihin ng openai/claude-sonnet-4-6 ay "magsalita ng OpenAI chat-completions protocol sa api_base ko gamit ang model claude-sonnet-4-6". Kung wala ang prefix, ini-infer ng litellm ang vendor mula sa pangalan at niruta ito nang native, na dumadaan sa labas ng endpoint mo.
Maaari bang gumamit ang magkaibang stage ng STORM ng mga model ng magkaibang vendor?
Oo. Independiyenteng LitellmModel ang bawat isa sa limang slot, kaya maaaring tumakbo ang conversation simulator sa isang id ng DeepSeek habang tumatakbo sa Claude ang article generation at sa GPT ang polish, lahat sa pamamagitan ng parehong api_base at key. Inirerekomenda na ng upstream ang paghahati ng mabilis at malakas na mga model sa mga stage.
Nagbabago ba ang search retriever kapag binago ko ang api_base?
Hindi. Tumatakbo ang retrieval sa pamamagitan ng RM module na ipinapasa mo sa STORMWikiRunner (You.com, Bing, at iba pang sinusuportahang backend) gamit ang sarili nitong key. Independiyenteng sistema ang LM routing at source retrieval na nabibigo sa iba't ibang yugto ng isang run.
May environment-variable na path ba sa halip na kwargs?
Iginagalang ng litellm ang mga variable sa antas ng provider, at binabasa ng openai provider ang OPENAI_API_BASE. Gumagana ito, pero mas reproducible ang tahasang api_base kwarg: naglalakbay ito kasama ng script, nakakaligtas sa mga makinang may ibang environment state, at pinapayagan ang mga eksepsiyon per slot.
Ilang token ang gastos ng isang artikulo ng STORM?
Naghahari ang research phase: pinaparami ng multi-perspective na simulated na mga usapan ang mga tawag bago pa man may isang salita ng artikulo, pagkatapos ay nagdadagdag ng long-form na output ang generation at polish. Karaniwang tumatama sa daan-daang libong token ang mga buong run, at ipinapakita ng per-key usage view ang eksaktong hati per stage.