paper-qa را در برابر یک endpoint سفارشی سازگار با OpenAI اجرا کنید.

Updated 2026-07-30

paper-qa مدل‌های خود را از طریق dict های router برابر LiteLLM پیکربندی می‌کند، و litellm_params مقدار api_base را می‌پذیرد. آن را به https://api.apisrouter.com/v1 اشاره دهید، یک کلید پاس دهید، و اسلات‌های answer، summary، و agent هرکدام می‌توانند هر مدل کاتالوگی را روی کتابخانه مقاله خود شما اجرا کنند.

پاسخ سریع: یک dict router با api_base، دوباره‌استفاده‌شده به ازای هر اسلات.

شیء Settings در paper-qa یک نام مدل به‌علاوه یک config اختیاری از router برابر LiteLLM به ازای هر اسلات می‌گیرد. config router یک model_list است که litellm_params آن api_base و api_key حمل می‌کند، که همان الگوی مستندشده‌ای است که README برای سرورهای محلی سازگار با OpenAI استفاده می‌کند؛ یک gateway به‌سادگی همان الگو با یک URL عمومی و یک کلید واقعی است. llm و summary_llm را روی model_name ای که اعلام کرده‌اید تنظیم کنید، config را به هر دو اسلات ضمیمه کنید، و paper-qa از طریق gateway مسیردهی می‌شود. رشته مدل داخل litellm_params قرارداد provider مربوط به litellm را نگه می‌دارد: openai/<id> به litellm می‌گوید chat-completions را با api_base شما صحبت کند، و id بعد از اسلش به endpoint فوروارد می‌شود، پس id های Claude، GPT، Gemini، و GLM همه با همان dict قابل‌آدرس‌دهی‌اند.

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 token خرج می‌کند: سه اسلات به‌علاوه embedding ها.

paper-qa (Future-House در GitHub، حدود ۹ هزار ستاره) پاسخ‌دهی به سؤال مبتنی‌بر-retrieval روی PDF های علمی را با یک حلقه agentic روی آن انجام می‌دهد: یک agent تصمیم می‌گیرد کی کتابخانه شما را جست‌وجو کند، قطعات شاهد را جمع می‌کند، ارتباط آن‌ها را خلاصه می‌کند، و یک پاسخ استنادشده می‌سازد. آن روی سه اسلات LLM جداگانه قابل‌پیکربندی نگاشت می‌شود. summary_llm شواهد را به ازای هر قطعه بازیابی‌شده ارزیابی و فشرده می‌کند، که آن را اسلات حجمی می‌کند. llm پاسخ نهایی را از شواهد مونتاژشده می‌نویسد، گام کیفیت-حیاتی. و agent_llm (داخل تنظیمات agent) تصمیم‌های انتخاب-tool را می‌سازد که حلقه را هدایت می‌کنند. هر سه به یک مدل OpenAI پیش‌فرض می‌شوند، و هرکدام یک فیلد _config متطابق (llm_config، summary_llm_config، agent_llm_config) دارند که همان dict router را می‌پذیرد، پس یک شیء config gateway می‌تواند به هر اسلات ضمیمه شود در حالی که نام مدل به ازای هر اسلات مستقل می‌ماند. یک تفکیک رایج یک id سریع است که شواهد را خلاصه می‌کند و یک id frontier که پاسخ‌ها را می‌نویسد، هر دو از طریق یک endpoint و کلید. embedding ها workload چهارم و عمداً جدا هستند: تنظیم embedding (پیش‌فرض text-embedding-3-small) index vector مقالات شما را می‌سازد. جابه‌جایی اسلات‌های چت به یک gateway embedding ها را جابه‌جا نمی‌کند، و paper-qa از sentence-transformers محلی (پیشوند st-، از طریق local extras) پشتیبانی می‌کند اگر می‌خواهید index کاملاً مستقل از هر endpoint دوردست باشد.

راه‌اندازی کامل: Settings با config های هر-اسلات.

الگوی کامل یک ورودی router به ازای هر مدلی که می‌خواهید قابل‌آدرس‌دهی باشد اعلام می‌کند و config ها را اسلات به اسلات ضمیمه می‌کند. اعلام دو ورودی، یکی سریع برای خلاصه‌ها و یکی قوی برای پاسخ‌ها، کل راه‌اندازی را در یک dict نگه می‌دارد. همان مسیردهی از CLI کار می‌کند، چون pqa سطح تنظیمات را افشا می‌کند، اما مسیر پایتون بازتولیدپذیر برای استفاده پژوهشی است: شیء 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",
    ),
)

انتخاب مدل‌ها به ازای هر اسلات.

با pipeline شاهد ثابت تنظیم کنید: همان کتابخانه، همان سؤالات، یک اسلات را در هر بار عوض کنید. پشت یک endpoint هر کاندید یک رشته model_name است، و usage log هر-کلید هر پیکربندی را به ازای هر سؤال قیمت‌گذاری می‌کند، که همان عددی است که یک آزمایشگاه واقعاً روی آن بودجه می‌بندد.

  • summary_llm یک‌بار به ازای هر قطعه شاهد، هر سؤال اجرا می‌شود. روی یک کتابخانه جدی این اکثریت قاطع فراخوانی‌ها است، پس یک id سریع (claude-haiku-4-5-20251001) کف هزینه کل سیستم را تنظیم می‌کند در حالی که فقط باید ارتباط را قضاوت کند، نه نثر بنویسد.
  • llm پاسخ استنادشده را از شواهد مونتاژشده می‌سازد. اینجا جایی است که نوشتار علمی محتاطانه و دقیق یا اتفاق می‌افتد یا نه؛ claude-sonnet-4-6 و gpt-5.5 انتخاب‌های قابل‌اتکا هستند، و اسلات چند فراخوانی به ازای هر سؤال است پس صرف premium محدود است.
  • agent_llm حلقه را هدایت می‌کند: آیا دوباره جست‌وجو کند، شواهد بیشتری جمع کند، یا پاسخ دهد. تصمیم‌های ضعیف اینجا token ها را در همه‌جای دیگر هدر می‌دهند، که یک id mid-tier یا بهتر را با وجود حجم پایین اسلات انتخاب اقتصادی می‌کند.
  • id های long-context مثل 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 می‌خواهد و شکست می‌خورد (یا بی‌صدا مسیردهی شما را در سرتاسر دو endpoint تقسیم می‌کند اگر آن کلید وجود داشته باشد). هر اسلات فیلد _config خودش را دارد؛ dict gateway را به هر اسلاتی که قصد جابه‌جایی آن را دارید ضمیمه کنید، شامل agent_llm_config. نام‌هایی که هم‌تراز نیستند. Settings.llm باید برابر یک model_name در model_list باشد؛ litellm_params.model آن چیزی است که واقعاً به wire می‌رود. نام بیرونی را نامتطابق کنید و router مسیری ندارد؛ id درونی را غلط‌تایپی کنید و gateway model-not-found برمی‌گرداند. هنگام دیباگ، دو رشته را جداگانه چک کنید چون به‌شکل متفاوتی شکست می‌خورند. فرض‌شده embedding ها دنبال می‌کنند. اسلات embedding index vector را می‌سازد و پرس‌وجو می‌کند و پیش‌فرض و config خودش را دارد. اگر یک کلید OpenAI برای embedding پیش‌فرض ندارید، embedding را صریح پیکربندی کنید، یا از sentence-transformers محلی از طریق پیشوند st- استفاده کنید. اشاره‌دادن مجدد embedding ها بعداً همچنین یعنی re-index کردن: vector های مدل‌های embedding متفاوت با هم مخلوط نمی‌شوند. محدودیت‌های تولید گم‌شده برای پاسخ‌های بلند. litellm_params مقدار max_tokens را به ازای هر ورودی می‌پذیرد، و مثال‌های endpoint-محلی در upstream آن را عمداً تنظیم می‌کنند. یک اسلات answer بدون یک محدودیت معقول می‌تواند پاسخ‌های استنادشده بلند را کوتاه کند، که مثل ضعف مدل ارائه می‌شود اما یک پارامتر است. مقصر‌دانستن مسیردهی برای مسائل parsing. کیفیت paper-qa به parsing و chunking PDF قبل از اینکه هر مدلی متن را ببیند بستگی دارد. اگر پاسخ‌ها روی یک کتابخانه که می‌دانید مرتبط است هیچ‌چیز استناد نمی‌کنند، گام indexing را بازرسی کنید؛ gateway فقط چیزی را می‌بیند که retrieval به آن می‌فرستد.

چه کسانی paper-qa را از طریق یک gateway مسیردهی می‌کنند.

  • گروه‌های پژوهشی که QA ادبیات را روی کتابخانه‌های مشترک اجرا می‌کنند، جایی که usage هر-کلید «آزمایشگاه به ازای هر سؤال چقدر خرج می‌کند» را از یک حدس به یک گزارش تبدیل می‌کند.
  • تیم‌هایی که نوشتار علمی با کیفیت Claude را در اسلات answer می‌خواهند در حالی که حجم خلاصه‌سازی را روی یک id سریع نگه می‌دارند، یک کلید برای هر دو.
  • سازندگانی که paper-qa را در ابزارهای داخلی embed می‌کنند، جایگزین‌کردن یک بسته secret های vendor با یک credential gateway به ازای هر محیط.
  • benchmark‌کنندگانی که مدل‌های answer را روی pipeline های شاهد ثابت مقایسه می‌کنند، جایی که هر کاندید یک رشته config است نه یک integration vendor.
  • توسعه‌دهندگان بدون دسترسی به صورت‌حساب یک vendor خاص. دسترسی مبتنی بر شارژ بدون الزام کارت وابستگی ثبت‌نام هر-provider را حذف می‌کند.

endpoint را تأیید کنید و اولین سؤال را عیب‌یابی کنید.

تأیید کنید gateway id هایی که اعلام کرده‌اید را سرویس می‌دهد؛ رشته litellm_params.model بعد از openai/ باید دقیقاً با یک id سرویس‌داده‌شده مطابقت داشته باشد. نردبان شکست روی یک ask() اول: خطایی که OPENAI_API_KEY می‌خواهد یعنی برخی اسلات هنوز روی مدل پیش‌فرض خودش است بدون config ضمیمه‌شده؛ پیدا کنید کدام‌یک از llm، summary_llm، و agent_llm را جابه‌جا نکرده‌اید. یک ۴۰۱ از gateway همان api_key داخل litellm_params است. یک خطای router درباره یک مدل ناشناخته یعنی Settings.llm با هیچ model_name ای در فهرست مطابقت ندارد. شکست‌ها در طول indexing به‌جای answering به تنظیم embedding یا PDF parsing اشاره دارند، نه مسیردهی چت. یک سؤال به بسیاری فراخوانی summary به‌علاوه گام‌های agent به‌علاوه پاسخ نهایی شاخه می‌شود، پس بعد از اولین اجرای موفق، نمای هر-درخواست کنسول APIsRouter تفکیک اسلات را در token واقعی نشان می‌دهد. آن عددی است که باید در حین رشد کتابخانه تماشا کرد، چون حجم summary با شواهد بازیابی‌شده مقیاس می‌گیرد، نه فقط با شمارش سؤال.

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

پرسش‌های پرتکرار

چطور paper-qa از یک base URL سفارشی سازگار با OpenAI پشتیبانی می‌کند؟

از طریق config های router برابر LiteLLM: هرکدام از llm_config، summary_llm_config، و agent_llm_config یک model_list می‌پذیرد که litellm_params آن api_base و api_key را شامل می‌شود. این همان الگوی مستندشده‌ای است که paper-qa برای سرورهای محلی سازگار با OpenAI استفاده می‌کند، به‌جای آن به یک URL gateway اشاره‌کرده.

آیا مدل‌های answer و summary می‌توانند از vendor های متفاوت باشند؟

بله. هر اسلات یک نام مدل را با config خودش جفت می‌کند، پس یک id سریع Claude می‌تواند شواهد را خلاصه کند در حالی که GPT-5.5 یا Gemini پاسخ نهایی را می‌نویسد، همه از طریق یک api_base و یک کلید. یک ورودی model_list به ازای هر id اعلام کنید و به آن‌ها به ازای هر اسلات ارجاع دهید.

آیا باید مدل embedding را هم تغییر دهم؟

خیر، و معمولاً نباید در همان گام این کار را بکنید. تنظیم embedding مستقل از اسلات‌های چت است، و عوض‌کردن مدل‌های embedding index vector موجود شما را باطل می‌کند. اگر یک کلید برای embedding پیش‌فرض ندارید، embedding را صریح تنظیم کنید یا از sentence-transformers محلی با پیشوند st- استفاده کنید.

اسلات agent_llm چیست و آیا آن هم به config نیاز دارد؟

agent_llm، داخل AgentSettings، انتخاب tool را هدایت می‌کند: کی جست‌وجو کند، شواهد جمع کند، یا پاسخ دهد. مثل اسلات‌های دیگر به یک مدل OpenAI پیش‌فرض می‌شود، پس agent_llm_config را با همان dict gateway ضمیمه کنید وگرنه همچنان تلاش می‌کند به provider پیش‌فرض مسیردهی شود.

چرا paper-qa بعد از override من همچنان OPENAI_API_KEY می‌خواهد؟

حداقل یک اسلات هنوز روی مدل پیش‌فرض خودش است بدون config router ضمیمه‌شده. llm، summary_llm، و agent_llm به‌علاوه فیلدهای _config آن‌ها را چک کنید؛ خطا مدلی که تلاش کرده فراخوانی کند را نام می‌برد، که اسلاتی که از دست داده‌اید را شناسایی می‌کند.

آیا این هم از CLI پی‌کیوای و هم از پایتون کار می‌کند؟

CLI همان سطح تنظیمات را افشا می‌کند، اما برای مسیردهی gateway مسیر پایتون عملی است: dict های router به‌عنوان flag های خط فرمان دست‌وپاگیرند، و یک شیء Settings ثبت‌شده کنار نتایج اجراهای پژوهش را بازتولیدپذیر می‌کند.