Stanford STORM একটা কাস্টম OpenAI-compatible endpoint-এ চালান।

Updated 2026-07-29

STORM প্রতিটা language model একটা LitellmModel হিসেবে বানায়, এবং litellm api_base accept করে। আপনার shared openai_kwargs-এ https://api.apisrouter.com/v1 দিন, model id-কে openai/ দিয়ে prefix করুন, এবং article pipeline-এর পাঁচটা LM slot-ই এক endpoint এবং এক key দিয়ে route হয়।

দ্রুত উত্তর: openai_kwargs-এ api_base, id-তে openai/ prefix।

STORM-এর LitellmModel আপনি যে kwargs দিয়ে construct করেন তা store করে এবং প্রতিটা litellm.completion() call-এ merge করে। litellm-এর api_base parameter হলো কীভাবে আপনি openai provider-কে একটা ভিন্ন host-এ point করেন, তাই STORM-এর নিজস্ব example ইতিমধ্যে ব্যবহার করা openai_kwargs dict-এ api_base যোগ করাই পুরো override। প্রতিটা model id-কে openai/ দিয়ে prefix করুন যাতে litellm সেই base-এর সাথে chat-completions protocol বলে, এবং slash-এর পরের string gateway-তে pass through হয়। যেহেতু example একটা openai_kwargs dict বানায় এবং প্রতিটা model-এর জন্য এটা reuse করে, একটা যোগ করা key পুরো pipeline reroute করে দেয়। কোনো STORM code change না, fork না; এটা litellm-এর documented routing-এর উপর layered stock knowledge_storm behavior।

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)

STORM কীভাবে একটা article পাঁচটা LM slot জুড়ে split করে।

STORM (GitHub-এ stanford-oval, প্রায় 30K star) শুরু থেকে Wikipedia-style report লেখে: এটা simulated multi-perspective conversation দিয়ে একটা topic research করে, যা শিখেছে তা থেকে একটা outline বানায়, section ধরে ধরে পুরো article generate করে, এবং তারপর polish করে। STORMWikiLMConfigs সেই pipeline-কে পাঁচটা independently settable model হিসেবে expose করে: conv_simulator_lm এবং question_asker_lm research conversation চালায়, outline_gen_lm article structure করে, article_gen_lm এটা লেখে, এবং article_polish_lm final pass করে। Upstream README economics নিয়ে explicit: conversation simulator সবচেয়ে বেশি call volume চালায়, তাই এটা সেখানে একটা faster model এবং article generation-এর জন্য একটা more powerful model recommend করে। সেই guidance OpenAI model-এর মধ্যে বেছে নেওয়া ধরে নিয়েছিল; একটা multi-vendor endpoint-এর পেছনে এটা আরো useful কিছুতে generalize হয়। প্রতিটা slot তার নিজস্ব LitellmModel তার নিজস্ব model string সহ, তাই research chatter একটা fast DeepSeek id-তে চলতে পারে যখন outline এবং article generation Claude-এ চলে, এবং polish আপনি tone-এর জন্য যে model trust করেন তাতে, সবই একই key দিয়ে একই api_base-এর বিরুদ্ধে authenticated। Retrieval side আলাদা machinery: STORM-এর runner একটা RM module নেয় (You.com, Bing, এবং আরো কয়েকটা search backend) তার নিজস্ব API key সহ। Language model কোথায় point করছে তা পাল্টালে source কীভাবে fetch হয় তা touch হয় না।

সম্পূর্ণ সেটআপ: পাঁচটা slot, এক kwargs dict।

Working pattern repo-এর নিজস্ব run script mirror করে: shared kwargs একবার বানান, প্রতি role একটা LitellmModel construct করুন, এবং STORMWikiLMConfigs setter দিয়ে সেগুলো assign করুন। api_key যেকোনো নাম হতে পারে যেহেতু আপনি এটা explicitly পাস করেন; example তার নিজস্ব variable ব্যবহার করে স্পষ্ট করতে যে এটা কোনো OpenAI account credential না। litellm provider-level environment variable-ও honor করে, এবং openai provider OPENAI_API_BASE পড়ে, তাই একটা environment-only override সম্ভব। Explicit kwargs path তবুও পছন্দ করার যোগ্য: এটা যে code একটা নির্দিষ্ট article produce করেছে তাতে visible, এটা ভিন্ন environment state সহ একটা machine-এ চালানো টিকে থাকে, এবং প্রয়োজনে per-slot exception সম্ভব করে।

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")

প্রতি pipeline stage-এ model বেছে নেওয়া।

পাঁচটা setter-কে boilerplate না, একটা budget dial হিসেবে treat করুন। Upstream guidance ইতিমধ্যে বলে stage জুড়ে fast এবং strong model split করতে; একটা multi-vendor endpoint শুধু per stage menu বড় করে। একই topic-এ run-এর মাঝে একবারে একটা slot পাল্টান এবং output diff করুন, per-key usage log প্রতিটা configuration price করে দেয়।

  • conv_simulator_lm এবং question_asker_lm হলো volume stage: প্রতি topic একাধিক perspective জুড়ে multi-turn simulated interview। deepseek-v4-flash বা অন্য একটা fast id research phase-কে spend-এ প্রাধান্য পাওয়া থেকে আটকায়, এবং অসম্পূর্ণ chatter সহনীয় কারণ এটা note feed করে, prose না।
  • article_gen_lm হলো flagship slot। এটা accumulated research থেকে লম্বা, structured, cited section লেখে, যা sustained-generation কাজ যেখানে claude-sonnet-4-6 বা gpt-5.5 ছোট id-র চেয়ে দৃশ্যত ভালো করে।
  • outline_gen_lm হলো কম call কিন্তু outsized leverage, একটা planning slot-এর একই shape: একটা দুর্বল outline লেখক যতই ভালো হোক না কেন article-কে cap করে দেয়। এখানে claude-opus-4-7 test করা natural জায়গা।
  • article_polish_lm assembled article জুড়ে flow-এর জন্য rewrite করে এবং duplication সরায়, যা একটা long-context id থেকে লাভবান হয়; gemini-3.1-pro-preview এখানে benchmark করার যোগ্য।

ব্যবহার অনুযায়ী পেমেন্ট · অফিশিয়াল মূল্যের নিচে

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

মডেলঅফিশিয়াল মূল্যআমাদের মূল্য
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

STORM-specific failure mode।

একটা bare model id inference দিয়ে route হয়, আপনার api_base দিয়ে না। litellm provider বেছে নিতে prefix পড়ে, এবং prefix ছাড়া একটা Claude id Anthropic-native call হিসেবে inferred হয়, যা তখন ANTHROPIC_API_KEY চায় এবং আপনার gateway সম্পূর্ণভাবে ignore করে। gateway-র দিকে যাওয়া প্রতিটা id-তে openai/ prefix থাকতে হবে; prefix protocol-এর নাম দেয়, vendor-এর না। একটা slot পিছনে রয়ে যাওয়া। প্রতিটা LitellmModel construction-এ তার kwargs capture করে। যদি চারটা slot openai_kwargs share করে এবং পঞ্চমটা api_base ছাড়া ad hoc বানানো হয়, সেই slot নীরবে vendor default-এ post করে এবং auth-এ fail করে, এবং traceback একটা config line-এর বদলে একটা pipeline stage নাম দেয়। একই dict থেকে প্রতিটা slot বানান এবং এই class-এর bug অদৃশ্য হয়ে যায়। Endpoint-কে দোষারোপ করা Retriever failure। Research phase-এর একটা working search backend দরকার; একটা invalid বা exhausted retriever key (YDC_API_KEY, BING_SEARCH_API_KEY, বা যে RM-ই বেছে নিয়েছেন) information gathering-এর সময় run fail করে। সেই phase LM call-এর সাথে interleave করে, তাই LM config touch করার আগে কোন client raise করেছে সেটার জন্য traceback পড়ুন। Demo-র secrets.toml আপনার script-এর config না। Streamlit demo secrets.toml পড়ে; programmatic run আপনার script যা পাস করে তাই পড়ে। একটা চালানোর সময় আরেকটা edit করা একটা classic mismatch। max_tokens per-slot-ও। STORM-এর example fast slot-এ ছোট limit (500) এবং generation-এ বড় (3000) সেট করে। এর max_tokens না বাড়িয়ে একটা slot-কে একটা long-form model-এ point করলে নীরবে section truncate হয়ে যায়, যা একটা model quality সমস্যার মতো দেখায় কিন্তু একটা config সংখ্যা।

কারা একটা gateway দিয়ে STORM route করে।

  • Team যারা volume-এ knowledge report generate করে (brief, wiki-style internal doc, topic primer), যেখানে পাঁচ-slot split per-stage cost tuning-কে real টাকা worth করে।
  • Researcher যারা pipeline composition study করছে: কোন stage একটা stronger model থেকে লাভবান হয় তা একটা empirical প্রশ্ন, এবং এক endpoint slot-model combination-এর grid enumerate করা trivial বানায়।
  • Builder যারা প্রতি model family-তে একটা vendor SDK যোগ না করে একটা OpenAI-shaped stack-এর writing slot-এ Claude বা Gemini চালাচ্ছে।
  • যে কেউ batch topic list চালাচ্ছে, যেখানে research-phase volume topic জুড়ে গুণ হয় এবং usage log per-topic cost ledger হয়ে যায়।
  • Developer যাদের কোনো নির্দিষ্ট vendor-এর billing-এ access নেই। কোনো card requirement ছাড়া Top-up based access per-provider sign-up dependency সরিয়ে দেয়।

Endpoint verify করুন এবং প্রথম article debug করুন।

প্রথমে gateway-এর model list করুন: প্রতিটা slot-এ openai/-এর পরের string অবশ্যই একটা served id-র সাথে exactly মিলতে হবে। First-run failure pipeline order অনুসরণ করে। Anthropic বা Google নাম দেওয়া একটা auth error মানে একটা prefix-ছাড়া id একটা native provider-এ route হয়েছে; openai/ যোগ করুন। gateway থেকে একটা 401 মানে আপনার kwargs-এর api_key gateway key না। একটা model-not-found error সেই slot নাম দেয় যার id-তে একটা typo আছে। Research phase-এর সময় failure যা আপনার search backend উল্লেখ করে তা retriever credential, LM routing না। এবং truncated বা অদ্ভুত ছোট article section সাধারণত upstream-এর কিছুর বদলে generation slot-এ একটা কৃপণ max_tokens। একটা পূর্ণ STORM run একটা বড় burst: perspective জুড়ে simulated conversation, তারপর outline, generation, এবং polish। একবার একটা complete হলে, APIsRouter console per-request model, token count, এবং spend দেখায়, যা পাঁচটা slot-এর উপর পরিষ্কারভাবে map করে এবং পরের batch topic-এর আগে ঠিক কোন stage retune করতে হবে তা বলে দেয়।

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

সাধারণ প্রশ্ন

STORM কীভাবে একটা কাস্টম OpenAI-compatible endpoint সাপোর্ট করে?

litellm-এর মাধ্যমে। STORM প্রতিটা LM একটা LitellmModel হিসেবে বানায়, যা এর constructor kwargs প্রতিটা litellm.completion() call-এ merge করে, এবং litellm openai provider-এর জন্য api_base accept করে। openai_kwargs dict-এ api_base যোগ করুন এবং এর থেকে বানানো প্রতিটা slot gateway-তে route হবে।

Model id-তে কেন openai/ prefix দরকার?

litellm prefix থেকে provider বেছে নেয়। openai/claude-sonnet-4-6 মানে "claude-sonnet-4-6 model দিয়ে আমার api_base-এ OpenAI chat-completions protocol বলো"। Prefix ছাড়া, litellm নাম থেকে vendor infer করে এবং natively route করে, আপনার endpoint bypass করে।

STORM-এর ভিন্ন stage কি ভিন্ন vendor-এর model ব্যবহার করতে পারে?

হ্যাঁ। পাঁচটা slot-এর প্রতিটা একটা independent LitellmModel, তাই conversation simulator একটা DeepSeek id চালাতে পারে যখন article generation Claude চালায় এবং polish GPT চালায়, সবই একই api_base এবং key দিয়ে। Upstream ইতিমধ্যে stage জুড়ে fast এবং strong model split করার পরামর্শ দেয়।

api_base পাল্টালে কি search retriever পাল্টায়?

না। Retrieval STORMWikiRunner-কে পাস করা RM module দিয়ে চলে (You.com, Bing, এবং অন্য supported backend) তার নিজস্ব key সহ। LM routing এবং source retrieval independent system যা একটা run-এর ভিন্ন phase-এ fail করে।

kwargs-এর বদলে একটা environment-variable path আছে?

litellm provider-level variable honor করে, এবং openai provider OPENAI_API_BASE পড়ে। এটা কাজ করে, কিন্তু explicit api_base kwarg বেশি reproducible: এটা script-এর সাথে ভ্রমণ করে, ভিন্ন environment state সহ machine-এ টিকে থাকে, এবং per-slot exception অনুমতি দেয়।

একটা STORM article কত token খরচ করে?

Research phase-ই প্রাধান্য পায়: multi-perspective simulated conversation article-এর একটা শব্দও লেখার আগে call গুণ করে, তারপর generation এবং polish লম্বা output যোগ করে। পূর্ণ run সাধারণত কয়েক লক্ষ token-এ পৌঁছায়, এবং per-key usage view exact per-stage split দেখায়।