Запустите paper-qa на кастомном OpenAI-совместимом эндпоинте.
Updated 2026-07-30
paper-qa настраивает свои модели через router-словари LiteLLM, а litellm_params принимает api_base. Укажите https://api.apisrouter.com/v1, передайте один ключ — и слоты answer, summary и agent смогут каждый запускать любую модель каталога над вашей собственной библиотекой статей.
Короткий ответ: router-словарь с api_base, переиспользуемый по каждому слоту.
Объект Settings в paper-qa принимает имя модели плюс опциональный router-конфиг LiteLLM на слот. Router-конфиг — это model_list, чьи litellm_params несут api_base и api_key, что тот же самый задокументированный паттерн, который README использует для локально размещённых OpenAI-совместимых серверов; шлюз — это просто тот же паттерн с публичным URL и реальным ключом. Задайте llm и summary_llm равными объявленному вами model_name, прикрепите конфиг к обоим слотам — и paper-qa маршрутизируется через шлюз. Строка модели внутри litellm_params сохраняет соглашение litellm о провайдере: openai/<id> говорит litellm говорить на chat-completions с вашим api_base, а id после слэша передаётся эндпоинту без изменений, так что id Claude, GPT, Gemini и GLM — все адресуемы одним и тем же словарём.
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,
),
)
]
)Где paper-qa тратит токены: три слота плюс эмбеддинги.
paper-qa (Future-House на GitHub, около 9K звёзд) выполняет retrieval-augmented ответы на вопросы по научным PDF с агентным циклом сверху: агент решает, когда искать в вашей библиотеке, собирает фрагменты доказательств, суммаризирует их релевантность и составляет ответ с цитатами. Это раскладывается на три независимо настраиваемых LLM-слота. summary_llm оценивает и сжимает доказательства по каждому извлечённому фрагменту, что делает его объёмным слотом. llm пишет финальный ответ из собранных доказательств — критичный для качества шаг. А agent_llm (внутри настроек агента) принимает решения о выборе инструмента, которые направляют цикл. Все три по умолчанию используют модель OpenAI, и у каждого есть соответствующее поле _config (llm_config, summary_llm_config, agent_llm_config), принимающее тот же router-словарь, так что один объект конфига шлюза можно прикрепить к каждому слоту, при этом имя модели по каждому слоту остаётся независимым. Обычное разделение — быстрый id суммаризирует доказательства, а топовый id пишет ответы, оба через один эндпоинт и ключ. Эмбеддинги — четвёртая нагрузка, и она намеренно отделена: настройка embedding (по умолчанию text-embedding-3-small) строит векторный индекс ваших статей. Перенос чат-слотов на шлюз не переносит эмбеддинги, и paper-qa поддерживает локальные sentence-transformers (префикс st-, через local extras), если вы хотите, чтобы индекс был полностью независим от любого удалённого эндпоинта.
Полная настройка: Settings с конфигами по каждому слоту.
Полный паттерн объявляет одну router-запись на каждую модель, которую вы хотите сделать адресуемой, и прикрепляет конфиги слот за слотом. Объявление двух записей, быстрой для суммаризации и сильной для ответов, держит всю настройку в одном словаре. Та же маршрутизация работает из CLI, поскольку pqa выставляет поверхность настроек, но путь через Python — воспроизводимый для исследовательского использования: объект Settings, который произвёл ответ, можно залогировать рядом с самим ответом.
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",
),
)Выбор моделей по каждому слоту.
Настраивайте с зафиксированным пайплайном доказательств: та же библиотека, те же вопросы, меняйте по одному слоту за раз. За одним эндпоинтом каждый кандидат — это строка model_name, а лог использования по ключу оценивает каждую конфигурацию на вопрос — это и есть та цифра, на которую лаборатория реально закладывает бюджет.
- summary_llm запускается один раз на каждый фрагмент доказательств, на каждый вопрос. На серьёзной библиотеке это подавляющее большинство вызовов, так что быстрый id (claude-haiku-4-5-20251001) задаёт минимальную стоимость для всей системы, при этом ему нужно только судить о релевантности, а не писать прозу.
- llm составляет ответ с цитатами из собранных доказательств. Именно здесь либо происходит, либо не происходит взвешенное, точное научное письмо; claude-sonnet-4-6 и gpt-5.5 — надёжные выборы, а слот делает мало вызовов на вопрос, так что премия ограничена.
- agent_llm направляет цикл: искать ли снова, собрать ли больше доказательств или ответить. Слабые решения здесь тратят токены везде остальном, что делает id среднего уровня или лучше экономичным выбором, несмотря на низкий объём слота.
- Id с длинным контекстом, вроде gemini-3.1-pro-preview, стоит протестировать в слоте answer, когда вопросы тянут доказательства сразу из многих статей.
Оплата по факту · дешевле официальных цен
Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.
| Модель | Официальная цена | Наша цена |
|---|---|---|
| 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 |
Сбои, специфичные именно для paper-qa.
Слот, оставленный на значении по умолчанию. Если задать llm и llm_config, но не summary_llm_config, суммаризация остаётся на дефолтной модели OpenAI, которая затем требует OPENAI_API_KEY и падает (или молча расщепляет вашу маршрутизацию на два эндпоинта, если такой ключ существует). У каждого слота своё поле _config; прикрепляйте словарь шлюза к каждому слоту, который собираетесь перенести, включая agent_llm_config. Имена, которые не совпадают. Settings.llm должен равняться какому-то model_name в model_list; litellm_params.model — это то, что реально уходит на провод. Не совпадёт внешнее имя — у router нет маршрута; опечатаетесь во внутреннем id — шлюз вернёт model-not-found. При отладке проверяйте эти две строки по отдельности, потому что они падают по-разному. Предположение, что эмбеддинги последуют сами. Слот embedding строит и запрашивает векторный индекс и имеет свой собственный дефолт и конфиг. Если у вас нет ключа OpenAI для дефолтного embedding, настройте embedding явно либо используйте локальные sentence-transformers через префикс st-. Перенастройка эмбеддингов позже также означает переиндексацию: векторы от разных моделей эмбеддинга не смешиваются. Отсутствующие лимиты генерации для длинных ответов. litellm_params принимает max_tokens на запись, и апстримные примеры для локального эндпоинта задают его намеренно. Слот answer без разумного лимита может обрезать длинные ответы с цитатами, что выглядит как слабость модели, но на деле — параметр. Обвинение маршрутизации в проблемах парсинга. Качество paper-qa зависит от парсинга PDF и разбиения на чанки прежде, чем какая-либо модель увидит текст. Если ответы ничего не цитируют на библиотеке, которая, как вы знаете, релевантна, проверьте шаг индексации; шлюз видит только то, что ему присылает retrieval.
Кто направляет paper-qa через шлюз.
- Исследовательские группы, прогоняющие QA по литературе над общими библиотеками, где использование по ключу превращает «сколько лаборатория тратит на вопрос» из догадки в отчёт.
- Команды, которым нужно научное письмо уровня Claude в слоте answer, при этом объём суммаризации остаётся на быстром id, один ключ на оба.
- Разработчики, встраивающие paper-qa во внутренние инструменты, заменяющие пачку секретов вендоров одним credential шлюза на окружение.
- Бенчмаркеры, сравнивающие модели answer на фиксированных пайплайнах доказательств, где каждый кандидат — это строка конфига, а не интеграция вендора.
- Разработчики без доступа к биллингу конкретного вендора. Доступ на основе пополнения без требования карты убирает зависимость от регистрации у каждого провайдера.
Проверьте эндпоинт и отладьте первый вопрос.
Убедитесь, что шлюз обслуживает id, которые вы объявили; строка litellm_params.model после openai/ должна точно совпадать с обслуживаемым id. Лестница сбоев на первом ask(): ошибка, требующая OPENAI_API_KEY, означает, что какой-то слот всё ещё на своей модели по умолчанию без прикреплённого конфига; найдите, какой из llm, summary_llm и agent_llm вы не перенесли. 401 от шлюза — это api_key внутри litellm_params. Ошибка router о неизвестной модели означает, что Settings.llm не совпадает ни с одним model_name из списка. Сбои во время индексации, а не ответа, указывают на настройку embedding или парсинг PDF, а не на маршрутизацию чата. Один вопрос раскрывается во множество вызовов summary плюс шаги агента плюс финальный ответ, так что после первого успешного прогона вид по запросу в консоли APIsRouter показывает разбивку по слотам в реальных токенах. Это та цифра, за которой стоит следить по мере роста библиотеки, потому что объём summary масштабируется с извлечёнными доказательствами, а не только с числом вопросов.
curl -s https://api.apisrouter.com/v1/models \
-H "Authorization: Bearer $APISROUTER_API_KEY" | head -50Частые вопросы
Как paper-qa поддерживает кастомный OpenAI-совместимый base URL?
Через свои router-конфиги LiteLLM: каждый из llm_config, summary_llm_config и agent_llm_config принимает model_list, чьи litellm_params включают api_base и api_key. Это тот же самый задокументированный паттерн, который paper-qa использует для локально размещённых OpenAI-совместимых серверов, только указывающий на URL шлюза.
Могут ли модели answer и summary быть от разных вендоров?
Да. Каждый слот сопоставляет имя модели со своим собственным конфигом, так что быстрый id Claude может суммаризировать доказательства, пока GPT-5.5 или Gemini пишет финальный ответ, всё через один api_base и один ключ. Объявите одну запись model_list на каждый id и ссылайтесь на них по слотам.
Нужно ли менять и модель embedding?
Нет, и обычно не стоит делать это тем же шагом. Настройка embedding независима от чат-слотов, а смена модели embedding делает недействительным ваш существующий векторный индекс. Если у вас нет ключа для дефолтного embedding, задайте embedding явно либо используйте локальные sentence-transformers с префиксом st-.
Что такое слот agent_llm и нужен ли ему тоже конфиг?
agent_llm, внутри AgentSettings, управляет выбором инструмента: когда искать, собирать доказательства или отвечать. По умолчанию он использует модель OpenAI, как и другие слоты, так что прикрепите agent_llm_config с тем же словарём шлюза, иначе он всё равно попытается маршрутизироваться к провайдеру по умолчанию.
Почему paper-qa всё ещё запрашивает OPENAI_API_KEY после моего переопределения?
Как минимум один слот всё ещё на своей модели по умолчанию без прикреплённого router-конфига. Проверьте llm, summary_llm и agent_llm плюс их поля _config; ошибка называет модель, которую пыталась вызвать система, что и указывает на пропущенный слот.
Работает ли это из CLI pqa так же, как из Python?
CLI выставляет ту же поверхность настроек, но для маршрутизации через шлюз практичнее путь через Python: router-словари неудобны как флаги командной строки, а объект Settings, залогированный рядом с результатами, делает исследовательские прогоны воспроизводимыми.