Запустіть Stanford STORM на кастомному OpenAI-сумісному ендпоінті.
Updated 2026-07-29
STORM будує кожну мовну модель як LitellmModel, а litellm приймає api_base. Впишіть https://api.apisrouter.com/v1 у спільний openai_kwargs, додайте префікс openai/ до id моделей — і всі п'ять слотів LM конвеєра статей маршрутизуються через один ендпоінт і один ключ.
Коротка відповідь: api_base в openai_kwargs, префікс openai/ на id.
LitellmModel в STORM зберігає будь-які kwargs, з якими ви його сконструювали, і об'єднує їх у кожен виклик litellm.completion(). Параметр api_base у litellm — це те, як ви спрямовуєте провайдера openai на інший хост, тож додавання api_base до словника openai_kwargs, який уже використовують власні приклади STORM, — це все перевизначення. Додайте префікс openai/ до кожного id моделі, щоб litellm говорив протоколом chat-completions до цієї бази, а рядок після скісної риски передається до шлюзу як є. Оскільки приклади будують один словник openai_kwargs і повторно використовують його для кожної моделі, один доданий ключ перенаправляє весь конвеєр. Жодних змін коду STORM, жодного форку; це стандартна поведінка knowledge_storm, накладена на задокументовану маршрутизацію 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)Як STORM ділить статтю на п'ять слотів LM.
STORM (stanford-oval на GitHub, приблизно 30 тис. зірок) пише звіти у стилі Вікіпедії з нуля: досліджує тему через симульовані розмови з кількох перспектив, будує план з того, що дізнався, генерує повну статтю розділ за розділом, а потім полірує її. STORMWikiLMConfigs показує цей конвеєр як п'ять незалежно налаштовуваних моделей: conv_simulator_lm і question_asker_lm ведуть дослідницькі розмови, outline_gen_lm структурує статтю, article_gen_lm пише її, а article_polish_lm робить фінальний прохід. Апстрим-README прямо говорить про економіку: симулятор розмови несе найбільший обсяг викликів, тому там рекомендується швидша модель, а для генерації статті — потужніша. Ця рекомендація передбачала вибір між моделями OpenAI; за мультивендорним ендпоінтом вона узагальнюється у щось корисніше. Кожен слот — це своя LitellmModel зі своїм рядком моделі, тож дослідницька балаканина може працювати на швидкому id DeepSeek, поки генерація плану й статті працює на Claude, а полірування — на будь-якій моделі, якій ви довіряєте щодо тону, усі автентифіковані тим самим ключем проти того самого api_base. Бік пошуку — окрема машинерія: раннер STORM приймає модуль RM (You.com, Bing та кілька інших пошукових бекендів) з власним API-ключем. Зміна того, куди вказують мовні моделі, не торкається того, як отримуються джерела.
Повне налаштування: п'ять слотів, один словник kwargs.
Робочий патерн віддзеркалює власні run-скрипти репозиторію: побудуйте спільні kwargs один раз, сконструюйте одну LitellmModel на роль і призначте їх через сеттери STORMWikiLMConfigs. api_key може мати будь-яку назву, яку ви оберете, оскільки ви передаєте його явно; приклад використовує власну змінну, щоб було зрозуміло, що це не credential облікового запису OpenAI. litellm також підтримує змінні середовища на рівні провайдера, а провайдер openai зчитує OPENAI_API_BASE, тож можливе перевизначення лише через середовище. Явний шлях kwargs усе одно варто віддавати перевагу: він видимий у коді, що створив конкретну статтю, переживає запуск на машині з іншим станом середовища й дозволяє винятки по окремому слоту, якщо ви колись захочете один етап на іншому ендпоінті.
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")Вибір моделей для кожного етапу конвеєра.
Ставтеся до п'яти сеттерів як до бюджетного важеля, а не шаблону. Апстрим-рекомендація вже каже розділяти швидкі й потужні моделі по етапах; мультивендорний ендпоінт просто розширює меню для кожного етапу. Змінюйте один слот за раз між прогонами на ту саму тему й порівнюйте виводи, з логом використання за ключем, що оцінює кожну конфігурацію.
- conv_simulator_lm і question_asker_lm — об'ємні етапи: багатоходові симульовані інтерв'ю з кількох перспектив на тему. deepseek-v4-flash чи інший швидкий id не дає дослідницькій фазі домінувати у витратах, а недосконала балаканина прийнятна, бо вона живить нотатки, а не прозу.
- article_gen_lm — флагманський слот. Він пише довгі, структуровані, цитовані розділи з накопиченого дослідження, що є роботою тривалої генерації, де claude-sonnet-4-6 чи gpt-5.5 явно перевершують менші id.
- outline_gen_lm — мало викликів з непропорційним впливом, та сама форма, що й слот планування: слабкий план обмежує статтю незалежно від того, наскільки хороший письменник. Це природне місце для тестування claude-opus-4-7.
- article_polish_lm переписує заради плавності й прибирає дублювання по всій зібраній статті, що виграє від id з довгим контекстом; gemini-3.1-pro-preview вартий бенчмаркінгу тут.
Оплата за фактом · нижче офіційних цін
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.
Голий id моделі маршрутизується за висновком, а не за вашим api_base. litellm зчитує префікс, щоб обрати провайдера, і безпрефіксний id Claude виводиться як нативний виклик Anthropic, який тоді хоче ANTHROPIC_API_KEY і повністю ігнорує ваш шлюз. Кожен id, спрямований на шлюз, має нести префікс openai/; префікс називає протокол, а не вендора. Один забутий слот. Кожна LitellmModel захоплює свої kwargs при побудові. Якщо чотири слоти діляться openai_kwargs, а п'ятий побудований окремо без api_base, цей слот тихо надсилає запит до типового постачальника й падає на автентифікації, а traceback називає етап конвеєра, а не рядок конфігурації. Побудуйте кожен слот з того самого словника, і цей клас багів зникає. Збої ретрівера, звинувачені в ендпоінті. Дослідницька фаза потребує робочого пошукового бекенда; недійсний чи вичерпаний ключ ретрівера (YDC_API_KEY, BING_SEARCH_API_KEY чи будь-який RM, який ви обрали) падає під час прогонів на етапі збору інформації. Ця фаза перемежовується з викликами LM, тож читайте traceback, щоб зрозуміти, який клієнт видав помилку, перш ніж чіпати конфігурацію LM. secrets.toml демо-версії — не конфігурація вашого скрипта. Streamlit-демо читає secrets.toml; програмні прогони читають те, що передає ваш скрипт. Редагування одного, поки працює інший, — класична невідповідність. max_tokens теж на кожен слот. Приклади STORM встановлюють малі ліміти на швидких слотах (500) і більші на генерації (3000). Спрямування слота на модель для довгого тексту без підняття його max_tokens тихо обрізає розділи, що виглядає як проблема якості моделі, а насправді число конфігурації.
Хто спрямовує STORM через шлюз.
- Команди, що генерують звіти знань в об'ємі (брифи, вікі-подібні внутрішні документи, огляди тем), де поділ на п'ять слотів робить налаштування вартості по етапах вартим реальних грошей.
- Дослідники, що вивчають композицію конвеєра: який етап виграє від сильнішої моделі — емпіричне питання, і один ендпоінт робить перелік комбінацій слот-модель тривіальним.
- Розробники, що запускають Claude чи Gemini у слотах письма стеку у формі OpenAI, не додаючи SDK вендора на кожну родину моделей.
- Будь-хто, хто запускає пакетні списки тем, де об'єм дослідницької фази множиться по темах, а лог використання стає книгою обліку вартості на тему.
- Розробники без доступу до білінгу певного постачальника. Доступ на основі поповнення без вимоги картки прибирає залежність від реєстрації в кожного провайдера.
Перевірте ендпоінт і налагодьте першу статтю.
Спочатку перелічіть моделі шлюзу: рядок після openai/ у кожному слоті має точно збігатися з обслуговуваним id. Збої першого прогону йдуть за порядком конвеєра. Помилка автентифікації, що називає Anthropic чи Google, означає, що безпрефіксний id маршрутизувався до нативного провайдера; додайте openai/. 401 від шлюзу означає, що api_key у ваших kwargs — не ключ шлюзу. Помилка model-not-found називає слот, чий id містить одруківку. Збої під час дослідницької фази, що згадують ваш пошуковий бекенд, — це облікові дані ретрівера, а не маршрутизація LM. А обрізані чи дивно короткі розділи статті зазвичай означають скупий max_tokens на слоті генерації, а не щось вище за конвеєром. Повний прогін STORM — це великий сплеск: симульовані розмови з кількох перспектив, потім план, генерація й полірування. Щойно один завершиться, консоль APIsRouter показує модель на запит, кількість токенів і витрати, що чітко мапиться на п'ять слотів і каже точно, який етап налаштувати наново перед наступною партією тем.
curl -s https://api.apisrouter.com/v1/models \
-H "Authorization: Bearer $APISROUTER_API_KEY" | head -50Поширені запитання
Як STORM підтримує кастомний OpenAI-сумісний ендпоінт?
Через litellm. STORM будує кожну LM як LitellmModel, яка об'єднує свої kwargs конструктора в кожен виклик litellm.completion(), а litellm приймає api_base для провайдера openai. Додайте api_base до словника openai_kwargs, і кожен слот, побудований з нього, маршрутизується до шлюзу.
Чому id моделей потребують префікса openai/?
litellm обирає провайдера за префіксом. openai/claude-sonnet-4-6 означає «говори протоколом chat-completions OpenAI до мого api_base з моделлю claude-sonnet-4-6». Без префікса litellm виводить вендора з назви і маршрутизує нативно, оминаючи ваш ендпоінт.
Чи можуть різні етапи STORM використовувати моделі різних вендорів?
Так. Кожен з п'яти слотів — незалежна LitellmModel, тож симулятор розмови може працювати на id DeepSeek, поки генерація статті працює на Claude, а полірування — на GPT, усе через той самий api_base і ключ. Апстрим уже рекомендує розділяти швидкі й потужні моделі по етапах.
Чи змінюється пошуковий ретрівер, коли я змінюю api_base?
Ні. Пошук працює через модуль RM, який ви передаєте до STORMWikiRunner (You.com, Bing та інші підтримувані бекенди) з власним ключем. Маршрутизація LM і отримання джерел — незалежні системи, що падають на різних фазах прогону.
Чи є шлях через змінні середовища замість kwargs?
litellm підтримує змінні на рівні провайдера, а провайдер openai зчитує OPENAI_API_BASE. Це працює, але явний kwarg api_base відтворюваніший: він подорожує зі скриптом, переживає машини з іншим станом середовища й дозволяє винятки по окремому слоту.
Скільки токенів споживає одна стаття STORM?
Домінує дослідницька фаза: багатоперспективні симульовані розмови множать виклики ще до того, як з'явиться перше слово статті, а потім генерація й полірування додають довгий вивід поверх. Повні прогони зазвичай сягають сотень тисяч токенів, і вигляд використання за ключем показує точний поділ по етапах.