הריצו את paper-qa מול endpoint תואם OpenAI מותאם אישית.

Updated 2026-07-30

paper-qa מגדיר את המודלים שלו דרך dicts של router מסוג LiteLLM, ו-litellm_params מקבל api_base. הפנו אותו אל https://api.apisrouter.com/v1, העבירו מפתח אחד, וסלוטי התשובה, הסיכום, וה-agent יכולים כל אחד להריץ כל מודל קטלוג על ספריית המאמרים שלכם.

תשובה מהירה: dict של router עם api_base, בשימוש חוזר לכל סלוט.

אובייקט ה-Settings של paper-qa לוקח שם מודל בתוספת הגדרת router אופציונלית של LiteLLM לכל סלוט. הגדרת ה-router היא model_list שה-litellm_params שלו נושאים api_base ו-api_key, שזה בדיוק הדפוס המתועד שה-README משתמש בו עבור שרתים תואמי-OpenAI מתארחים מקומית; gateway הוא פשוט הדפוס הזה עם URL ציבורי ומפתח אמיתי. הגדירו את llm ואת summary_llm ל-model_name שהכרזתם, צרפו את ההגדרה לשני הסלוטים, ו-paper-qa מנתב דרך ה-gateway. מחרוזת המודל בתוך litellm_params שומרת את מוסכמת הספק של litellm: openai/<id> אומר ל-litellm לדבר chat-completions אל ה-api_base שלכם, וה-id אחרי הסלאש מועבר אל ה-endpoint, כך ש-ids של 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 מוציא טוקנים: שלושה סלוטים בתוספת embeddings.

paper-qa (Future-House ב-GitHub, כ-9K כוכבים) עושה מענה-לשאלות מבוסס-אחזור על PDFs מדעיים עם לולאת agent מעליו: agent מחליט מתי לחפש בספרייה שלכם, אוסף קטעי ראיה, מסכם את הרלוונטיות שלהם, ומרכיב תשובה עם ציטוטים. זה ממופה לשלושה סלוטי LLM ניתנים להגדרה בנפרד. summary_llm מעריך ומצמצם ראיה לכל קטע שאוחזר, מה שהופך אותו לסלוט הנפח. llm כותב את התשובה הסופית מהראיה שהורכבה, השלב הקריטי-לאיכות. ו-agent_llm (בתוך הגדרות ה-agent) מקבל את החלטות בחירת-הכלים שמכוונות את הלולאה. כל השלושה כברירת מחדל הם מודל OpenAI, ולכל אחד יש שדה _config תואם (llm_config, summary_llm_config, agent_llm_config) שמקבל את אותו dict של router, כך שאובייקט הגדרת gateway אחד יכול להיות מצורף לכל סלוט בעוד שם המודל לכל סלוט נשאר עצמאי. פיצול נפוץ הוא id מהיר שמסכם ראיה ו-id מהחזית שכותב תשובות, שניהם דרך endpoint ומפתח אחד. Embeddings הם עומס העבודה הרביעי ונפרדים במכוון: הגדרת ה-embedding (ברירת מחדל text-embedding-3-small) בונה את אינדקס הווקטורים של המאמרים שלכם. הזזת סלוטי הצ'אט אל gateway לא מזיזה embeddings, ו-paper-qa תומך ב-sentence-transformers מקומיים (הקידומת st-, דרך התוספים המקומיים) אם אתם רוצים שהאינדקס יהיה עצמאי לגמרי מכל endpoint מרוחק.

הגדרה מלאה: Settings עם הגדרות לכל-סלוט.

הדפוס המלא מכריז רשומת router אחת לכל מודל שאתם רוצים ניתן-לכתובת ומצרף הגדרות סלוט אחר סלוט. הכרזת שתי רשומות, אחת מהירה לסיכומים ואחת חזקה לתשובות, שומרת את כל ההגדרה ב-dict אחד. אותו ניתוב עובד מה-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",
    ),
)

בחירת מודלים לכל סלוט.

כווננו עם צינור הראיה קבוע: אותה ספרייה, אותן שאלות, החליפו סלוט אחד בכל פעם. מאחורי endpoint אחד כל מועמד הוא מחרוזת model_name, ולוג השימוש לפי מפתח מתמחר כל הגדרה לכל שאלה, וזה המספר שמעבדה באמת מתקצבת.

  • summary_llm רץ פעם אחת לכל קטע ראיה, בכל שאלה. על ספרייה רצינית זה הרוב המכריע של הקריאות, אז id מהיר (claude-haiku-4-5-20251001) קובע את רצפת העלות עבור המערכת כולה תוך שהוא צריך רק לשפוט רלוונטיות, לא לכתוב פרוזה.
  • llm מרכיב את התשובה עם הציטוטים מהראיה שהורכבה. כאן כתיבה מדעית מגובה ומדויקת קורית או לא; claude-sonnet-4-6 ו-gpt-5.5 הן הבחירות האמינות, והסלוט הוא מעט קריאות לכל שאלה אז הפרמיה מוגבלת.
  • agent_llm מכוון את הלולאה: האם לחפש שוב, לאסוף עוד ראיה, או לענות. החלטות חלשות כאן מבזבזות טוקנים בכל מקום אחר, מה שהופך id בשכבה-בינונית או טוב יותר לבחירה הכלכלית למרות הנפח הנמוך של הסלוט.
  • ids בהקשר-ארוך כמו 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.

מודלמחיר רשמיהמחיר שלנו
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 ונכשל (או מפצל בשקט את הניתוב שלכם על פני שני endpoints אם המפתח הזה קיים). לכל סלוט יש שדה _config משלו; צרפו את ה-dict של ה-gateway לכל סלוט שאתם מתכוונים להזיז, כולל agent_llm_config. שמות שלא מיושרים. Settings.llm חייב להיות שווה ל-model_name ב-model_list; litellm_params.model הוא מה שבאמת הולך לתקשורת. אי-התאמה בשם החיצוני והראוטר אין לו route; טעות הקלדה ב-id הפנימי וה-gateway מחזיר model-not-found. כשמבצעים דיבוג, בדקו את שתי המחרוזות בנפרד מכיוון שהן נכשלות באופנים שונים. הנחת המשך של embeddings. סלוט ה-embedding בונה ושואל את אינדקס הווקטורים ויש לו ברירת מחדל והגדרה משלו. אם אין לכם מפתח OpenAI עבור ה-embedding ברירת המחדל, הגדירו embedding במפורש, או השתמשו ב-sentence-transformers מקומיים דרך הקידומת st-. הפניית embeddings מחדש מאוחר יותר גם אומרת אינדוקס מחדש: וקטורים ממודלי embedding שונים לא מתערבבים. מגבלות ייצור חסרות לתשובות ארוכות. litellm_params מקבל max_tokens לכל רשומה, ודוגמאות ה-endpoint המקומי ב-upstream מגדירות אותו במכוון. סלוט תשובה בלי מגבלה הגיונית יכול לגזום תשובות ארוכות עם ציטוטים, מה שמציג כחולשת מודל אבל הוא פרמטר. האשמת הניתוב בבעיות ניתוח. האיכות של paper-qa תלויה בניתוח PDF וחלוקה לפני שמודל כלשהו רואה טקסט. אם תשובות לא מצטטות כלום על ספרייה שאתם יודעים שרלוונטית, בדקו את שלב האינדוקס; ה-gateway רואה רק מה שהאחזור שולח לו.

מי מנתב את paper-qa דרך gateway.

  • קבוצות מחקר שמריצות שאלות-ותשובות על ספרות על ספריות משותפות, שם שימוש-לפי-מפתח הופך את "כמה המעבדה מוציאה לכל שאלה" מניחוש לדוח.
  • צוותים שרוצים כתיבה מדעית באיכות Claude בסלוט התשובה תוך שמירה על נפח הסיכום על id מהיר, מפתח אחד לשניהם.
  • בונים שמטמיעים את paper-qa בכלים פנימיים, מחליפים חבילת סודות ספק במפתח gateway אחד לכל סביבה.
  • בודקי benchmark שמשווים מודלי תשובה על צינורות ראיה קבועים, שם כל מועמד הוא מחרוזת הגדרה ולא אינטגרציית ספק.
  • מפתחים ללא גישה לחיוב של ספק נתון. גישה מבוססת-הטענה בלי דרישת כרטיס מסירה את התלות בהרשמה לכל ספק.

אמתו את ה-endpoint ובצעו דיבוג לשאלה הראשונה.

אשרו שה-gateway משרת את ה-ids שהכרזתם; מחרוזת litellm_params.model אחרי openai/ חייבת להתאים בדיוק ל-id מוגש. סולם הכשלים ב-ask() ראשון: שגיאה שדורשת OPENAI_API_KEY אומרת שסלוט כלשהו עדיין על מודל ברירת המחדל שלו בלי הגדרה מצורפת; מצאו איזה מבין llm, summary_llm, ו-agent_llm לא הזזתם. 401 מה-gateway הוא ה-api_key בתוך litellm_params. שגיאת router על מודל לא-מוכר אומרת ש-Settings.llm לא תואם שום model_name ברשימה. כשלים במהלך אינדוקס במקום מענה מצביעים על הגדרת ה-embedding או ניתוח PDF, לא ניתוב הצ'אט. שאלה אחת מתפצלת להרבה קריאות סיכום בתוספת צעדי agent בתוספת התשובה הסופית, אז אחרי ההרצה המוצלחת הראשונה, התצוגה לכל-בקשה של קונסולת APIsRouter מציגה את פיצול הסלוט בטוקנים אמיתיים. זה המספר לצפות בו ככל שהספרייה גדלה, מכיוון שנפח הסיכום נמדד לפי ראיה שאוחזרה, לא רק לפי מספר השאלות.

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

שאלות נפוצות

איך paper-qa תומך ב-base URL תואם OpenAI מותאם אישית?

דרך הגדרות ה-router מסוג LiteLLM שלו: כל אחד מ-llm_config, summary_llm_config, ו-agent_llm_config מקבל model_list שה-litellm_params שלו כוללים api_base ו-api_key. זה בדיוק הדפוס המתועד ש-paper-qa משתמש בו עבור שרתים תואמי-OpenAI מתארחים מקומית, מכוון ל-URL של gateway במקום.

האם מודלי התשובה והסיכום יכולים להגיע מספקים שונים?

כן. כל סלוט מזווג שם מודל עם הגדרה משלו, כך ש-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 עם אותו dict של gateway אחרת הוא עדיין ינסה לנתב אל הספק ברירת המחדל.

למה paper-qa עדיין מבקש OPENAI_API_KEY אחרי הדריסה שלי?

לפחות סלוט אחד עדיין על מודל ברירת המחדל שלו בלי הגדרת router מצורפת. בדקו את llm, summary_llm, ו-agent_llm בתוספת שדות ה-_config שלהם; השגיאה נוקבת במודל שהיא ניסתה לקרוא לו, מה שמזהה את הסלוט שפספסתם.

האם זה עובד גם מ-CLI בשם pqa כמו מ-Python?

ה-CLI חושף את אותו שטח הגדרות, אבל לניתוב gateway נתיב ה-Python הוא המעשי: dicts של router מסורבלים כדגלי שורת-פקודה, ואובייקט Settings שנרשם ביומן לצד תוצאות הופך הרצות מחקר לבנות-שחזור.