LLM ובחירת המיטב
מקבלים ממודל שפה JSON תקין עם client.llm, ועם client.reduce בוחרים את הטובה מבין הרבה תוצאות, עורכים ביניהן הצבעה, מאחדים או ממזגים אותן.
client.llm מבקש ממודל שפה פלט מובנה: שולחים פרומפט מערכת, קלט ו-JSON Schema, ומקבלים בחזרה אובייקט שתואם לסכמה. המשאב client.reduce מריץ בנפרד את שלב ה-Reduce, שבו הרבה תוצאות מתכנסות לתוצאה אחת: הוא בוחר את הטובה ביותר מביניהן, סופר אותן, עורך ביניהן הצבעה, מאחד טקסטים או ממזג JSON — מה שרכיב בחירת המיטב עושה בתהליך. קריאה למודל שפה בכל אחד מהשניים מחויבת לפי הטוקנים שהיא משתמשת בהם, בתעריף של המודל. ראו את הסעיף איך מחויבות קריאות LLM בדף קרדיטים.
מתודות
| מתודה | מה היא עושה |
|---|---|
llm.structured(input) | קבלת אובייקט תקין ממודל שפה, במסגרת בקשה אחת |
llm.structuredJob(input) | אותה קריאה, כמשימה שבודקים את הסטטוס שלה מדי כמה שניות |
reduce.run(input) | בחירה, ספירה, הצבעה, איחוד או מיזוג של הרבה קלטים לתוצאה אחת |
client.llm
פלט מובנה: שולחים את פרומפט המערכת ואת ה-JSON Schema שלכם, ומקבלים אובייקט שנבדק מול הסכמה. הפלטפורמה בוחרת את השירות שמריץ את המודל, כופה פלט JSON, בודקת אותו מול הסכמה שלכם ושולחת למודל בחזרה תשובות לא תקינות לפני שהיא מוותרת. הקריאה מחויבת בתור llm-structured, לפי הטוקנים שהיא השתמשה בהם, בתעריף של המודל בשירות שטיפל בה. קודם משוריינים קרדיטים, וכשהיתרה נמוכה מהשריון, המתודה זורקת InsufficientCreditsError. אחר כך הקריאה מחויבת לפי השימוש בפועל. על כשל שהספק חייב עליו משלמים לפי השימוש הזה. המודל Claude Fable 5 זמין. לאומדן מחיר של קריאה טיפוסית, העבירו את llmPriceKey("llm-structured", model) ל-credits.modelCosts().
llm.structured(input)
פונה למודל ומחכה לתשובה (POST /v1/llm/structured). קריאה יכולה להימשך כמה דקות, יותר מפסק הזמן של 60 שניות שהלקוח מגדיר כברירת מחדל. בשביל קריאה כזו, צרו את הלקוח עם ערך timeoutMs גדול יותר, או השתמשו ב-structuredJob().
structured<T>(input: LlmStructuredInput): Promise<{
jobId: string
output: T
usage: { inputTokens: number; outputTokens: number }
}>מאפיין
סוג
type Plan = { title: string; scenes: string[] }
const { output } = await client.llm.structured<Plan>({
system: "You write production plans for short films.",
input: "A rainy chase through Rome, 60 seconds.",
jsonSchema: {
type: "object",
properties: {
title: { type: "string" },
scenes: { type: "array", items: { type: "string" } },
},
required: ["title", "scenes"],
},
schemaName: "production_plan",
})
console.log(output.title, output.scenes.length)llm.structuredJob(input)
אותה קריאה, כמשימה (POST /v1/llm/structured/jobs). המתודה מחזירה jobId מיד; בדקו את סטטוס המשימה מדי כמה שניות עם client.jobs.getStatus(). משימה יכולה גם לבסס את הטיוטה על סרטון: הפלטפורמה מנתחת קודם את הסרטון, ואז מוסיפה את הניתוח לקלט שלכם.
structuredJob(input: LlmStructuredJobInput): Promise<{ jobId: string }>מאפיין
סוג
const { jobId } = await client.llm.structuredJob({
system: "You write production plans.",
input: "A rainy chase through Rome.",
jsonSchema: { type: "object", properties: { title: { type: "string" } }, required: ["title"] },
origin: "my-app",
label: "Rome chase",
})
// later, even from another session
const { data } = await client.jobs.getStatus(jobId)
if (data.status === "completed") {
console.log((data.output_data as { output: { title: string } }).output.title)
}
const { data: runs } = await client.jobs.list({ type: "llm-structured", origin: "my-app" })בזמן שהמשימה רצה, השדה output_data שלה כולל את stage: analyzing (בטיוטות מסרטון) או drafting. כשהמשימה מסתיימת, השדה output_data כולל את output, inputTokens ו-outputTokens, ובטיוטה מסרטון גם את analysisJobId ו-analysisCredits.
- בקשה עם
analysisJobIdנדחית עם 422 כשהמשימה לא שייכת לכם, לא קיימת או שהיא לא ניתוח וידאו שהסתיים. הקודים הםanalysis_not_found,not_analysis,analysis_failed,analysis_not_readyו-invalid_analysis. - מול פלטפורמה שהנתיב הזה לא קיים בה, המתודה זורקת
NotFoundError. - במופע באירוח עצמי שמעביר ל-Nodaro Cloud את הקריאות שלו למודלי שפה, הנתיב מחזיר
503 provider_unavailable. התייחסו לתשובה הזו כסימן שהיכולת לא זמינה במופע הזה, ולא כשגיאה חולפת.
client.reduce
reduce.run(input)
הופכת הרבה קלטים לתוצאה אחת. המתודה עובדת כמו כלי ה-MCP reduce וכמו רכיב בחירת המיטב.
run(input: ReduceInput): Promise<ReduceResult>מאפיין
סוג
| אסטרטגיה | strategyConfig | מה היא מחזירה |
|---|---|---|
pick-best-llm | { criteria, inputKind?, llmModel? }. הערך של inputKind הוא "text" או "image-url". השדה llmModel בוחר את מודל השופט. הקריאה של השופט מחויבת לפי טוקן, בתעריף של המודל הזה. | הקלט שמודל השפה קובע שהוא הטוב ביותר, עם המיקום שלו ועם הנימוק |
concat | { separator? }, שורה ריקה כברירת מחדל | כל הקלטים, מאוחדים לטקסט אחד |
first-non-empty | אין | הקלט הראשון שלא ריק |
count | אין | מספר הקלטים |
vote | { caseSensitive? }, false כברירת מחדל | הקלט שמופיע הכי הרבה פעמים. בתיקו, הראשון מנצח. |
merge-json | { strategy? }: "deep" (ברירת המחדל) או "shallow" | קלטי ה-JSON, ממוזגים לאובייקט אחד |
const result = await client.reduce.run({
strategyId: "pick-best-llm",
strategyConfig: { criteria: "The sharpest image with no artifacts", inputKind: "image-url" },
inputs: [url1, url2, url3, url4, url5],
})
console.log(result.output) // the chosen URL
console.log(result.meta.selectedIndex) // 0 to 4
console.log(result.meta.reasoning) // why the model chose itהתוצאה היא { jobId, output, meta }. השדה output הוא הערך שנבחר או שאוחד, כמחרוזת. ב-meta.summary תמיד יש ערך. האסטרטגיות pick-best-llm ו-vote מגדירות את meta.selectedIndex, והאסטרטגיה pick-best-llm מגדירה גם את meta.reasoning.
// Majority vote
const winner = await client.reduce.run({ strategyId: "vote", inputs: ["red", "blue", "red"] })
// Deep-merge JSON fragments
const merged = await client.reduce.run({
strategyId: "merge-json",
inputs: [JSON.stringify({ a: 1, nested: { x: 1 } }), JSON.stringify({ b: 2, nested: { y: 2 } })],
})
JSON.parse(merged.output) // { a: 1, b: 2, nested: { x: 1, y: 2 } }כשכל הקלטים ריקים או שיש בהם רק תווי רווח, הקריאה נכשלת עם שגיאת NodaroError שהסטטוס שלה הוא 400 וה-code שלה הוא no_valid_inputs. קרדיטים משוריינים כמו בכל יצירה, ולכן כשהיתרה לא מספיקה, המתודה זורקת InsufficientCreditsError.
שאלות נפוצות
איך מקבלים ממודל שפה JSON שתואם לסכמה שלכם?
קראו למתודה client.llm.structured עם פרומפט מערכת, קלט ואובייקט JSON Schema. הפלטפורמה כופה על המודל לענות במבנה הזה, בודקת את התשובה, מנסה שוב כשהתשובה לא תקינה ומחזירה את האובייקט המפוענח.
מתי כדאי להשתמש במתודה structuredJob במקום במתודה structured?
השתמשו במתודה structuredJob בקריאות ארוכות. המתודה structured מחכה לתשובה במסגרת בקשה אחת, וזה יכול להימשך דקות, יותר מפסק הזמן של 60 שניות שמוגדר כברירת מחדל. המתודה structuredJob מחזירה jobId מיד.
איך בוחרים את הטובה מבין כמה תמונות שנוצרו?
קראו למתודה client.reduce.run עם האסטרטגיה pick-best-llm, עם הקריטריונים שלכם ועם הערך image-url בשדה inputKind, והעבירו את כתובות התמונות בשדה inputs. התוצאה מציינת את הכתובת שנבחרה, את המיקום שלה בין הקלטים ואת הנימוק של המודל.
כמה עולה קריאת LLM עם פלט מובנה?
קריאת LLM עם פלט מובנה מחויבת לפי הטוקנים שהיא השתמשה בהם בפועל, בתעריף של המודל בשירות שטיפל בה. קודם משוריינים קרדיטים, ואחר כך הקריאה מחויבת לפי השימוש בפועל. המתודה client.credits.modelCosts עם המפתח llm-structured:<model> מחזירה אומדן של קריאה טיפוסית.
אילו אסטרטגיות של Reduce לא צריכות מודל שפה?
האסטרטגיות concat, first-non-empty, count, vote ו-merge-json רצות בלי מודל. רק האסטרטגיה pick-best-llm מבקשת ממודל שפה לשפוט.
דפים קשורים
בחירת המיטב
הרצת רכיבים
משימות והרצות
בוררים, ערכות ופרומפטים
עודכן לאחרונה