דילוג לתוכן
תיעוד Nodaro
תיעודמדריך הרכיביםמודליםתבניותסוכני AI (MCP)מפתחיםאירוח עצמימחקרהשוואות
SDK ל-TypeScript

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 מבקשת ממודל שפה לשפוט.

עודכן לאחרונה

בדף הזה