การส่งผ่านข้อมูลผ่านบริบท

ข้อมูลของนักพัฒนาแอปที่ทำงานร่วมกับ LLM อาจมีหมวดหมู่ต่างๆ ดังนี้

  • อินพุต: ข้อมูลที่เกี่ยวข้องโดยตรงเพื่อใช้เป็นแนวทางในการตอบกลับของ LLM สำหรับสายเรียกเข้าหนึ่งๆ ตัวอย่างของกรณีนี้คือข้อความที่ต้องสรุป
  • บริบทการสร้าง: ข้อมูลที่เกี่ยวข้องกับ LLM แต่ไม่ได้เจาะจงกับการโทร ตัวอย่างของข้อมูลนี้ ได้แก่ เวลาปัจจุบันหรือชื่อของผู้ใช้
  • บริบทการดําเนินการ: ข้อมูลที่สําคัญต่อโค้ดรอบๆ การเรียก LLM แต่ไม่ใช่สําหรับ LLM เอง ตัวอย่างของข้อมูลนี้ ได้แก่ โทเค็นการให้สิทธิ์ปัจจุบันของผู้ใช้

Genkit มีออบเจ็กต์ context ที่สอดคล้องกันซึ่งสามารถเผยแพร่บริบทการสร้างและการดำเนินการตลอดกระบวนการ บริบทนี้จะพร้อมใช้งานสําหรับการดำเนินการทั้งหมด รวมถึงขั้นตอน เครื่องมือ และพรอมต์

ระบบจะเผยแพร่บริบทไปยังการดำเนินการทั้งหมดที่เรียกภายในขอบเขตของการดำเนินการโดยอัตโนมัติ: บริบทที่ส่งไปยังโฟลว์จะพร้อมใช้งานสำหรับพรอมต์ที่ดำเนินการภายในโฟลว์ บริบทที่ส่งไปยังเมธอด generate() จะพร้อมใช้งานสำหรับเครื่องมือที่เรียกภายในลูปการสร้าง

เหตุใดบริบทจึงสำคัญ

แนวทางปฏิบัติแนะนำคือคุณควรให้ข้อมูลกับ LLM น้อยที่สุดเท่าที่จำเป็นเพื่อทำงานให้เสร็จสมบูรณ์ ซึ่งสำคัญอย่างยิ่งเนื่องจากเหตุผลหลายประการ ดังนี้

  • ยิ่ง LLM มีข้อมูลที่ไม่เกี่ยวข้องน้อยเท่าใด ก็ยิ่งมีแนวโน้มที่จะทํางานได้ดีเท่านั้น
  • หาก LLM ต้องส่งข้อมูล เช่น รหัสผู้ใช้หรือรหัสบัญชี ไปยังเครื่องมือต่างๆ ก็อาจถูกหลอกให้เปิดเผยข้อมูลได้

บริบทจะให้ช่องทางข้อมูลสํารองที่โค้ดของคุณสามารถใช้ได้ แต่ไม่จำเป็นต้องส่งไปยัง LLM ตัวอย่างเช่น คุณสามารถจํากัดการค้นหาของเครื่องมือให้อยู่ภายในขอบเขตที่ผู้ใช้ปัจจุบันมีสิทธิ์เข้าถึง

โครงสร้างบริบท

บริบทต้องเป็นออบเจ็กต์ แต่คุณเลือกพร็อพเพอร์ตี้ของออบเจ็กต์ได้ ในบางกรณี Genkit จะป้อนบริบทโดยอัตโนมัติ ตัวอย่างเช่น เมื่อใช้เซสชันถาวร ระบบจะเพิ่มพร็อพเพอร์ตี้ state ลงใน context โดยอัตโนมัติ

การใช้บริบทที่พบบ่อยที่สุดอย่างหนึ่งคือการเก็บข้อมูลเกี่ยวกับผู้ใช้ปัจจุบัน เราขอแนะนำให้เพิ่มบริบทการตรวจสอบสิทธิ์ในรูปแบบต่อไปนี้

{
  auth: {
    uid: "...", // the user's unique identifier
    token: {...}, // the decoded claims of a user's id token
    rawToken: "...", // the user's raw encoded id token
    // ...any other fields
  }
}

ออบเจ็กต์บริบทสามารถจัดเก็บข้อมูลที่คุณอาจจำเป็นต้องทราบที่อื่นในขั้นตอนการดำเนินการ

ใช้บริบทในการดําเนินการ

หากต้องการใช้บริบทภายในการดำเนินการ คุณสามารถเข้าถึงตัวช่วยบริบทที่ระบุไว้ในคําจํากัดความของฟังก์ชันโดยอัตโนมัติ ดังนี้

น้ำไหล

const summarizeHistory = ai.defineFlow({
  name: 'summarizeMessages',
  inputSchema: z.object({friendUid: z.string()}),
  outputSchema: z.string();
}, async ({friendUid}, {context}) => {
  if (!context.auth?.uid) throw new Error("Must supply auth context.");
  const messages = await listMessagesBetween(friendUid, context.auth.uid);
  const {text} = await ai.generate({
    prompt:
      `Summarize the content of these messages: ${JSON.stringify(messages)}`,
  });
  return text;
});

เครื่องมือ

const searchNotes = ai.defineTool({
  name: 'searchNotes',
  description: "search the current user's notes for info",
  inputSchema: z.object({query: z.string()}),
  outputSchmea: z.array(NoteSchema);
}, async ({query}, {context}) => {
  if (!context.auth?.uid) throw new Error("Must be called by a signed-in user.");
  return searchUserNotes(context.auth.uid, query);
});

ไฟล์พรอมต์

เมื่อใช้เทมเพลต Dotprompt ระบบจะแสดงบริบทพร้อมคำนำหน้าตัวแปร @ เช่น วัตถุบริบทของ {auth: {name: 'Michael'}} สามารถเข้าถึงได้ในเทมเพลตพรอมต์ดังนี้

---
input:
  schema:
    pirateStyle?: boolean
---

{{#if pirateStyle}}
Avast, {{@auth.name}}, how be ye today?
{{else}}
Hello, {{@auth.name}}, how are you today?
{{/if}}

ระบุบริบทที่รันไทม์

หากต้องการระบุบริบทให้กับการดําเนินการ ให้ส่งออบเจ็กต์บริบทเป็นตัวเลือกเมื่อเรียกใช้การดําเนินการ

โฟลว์

const summarizeHistory = ai.defineFlow(/* ... */);

const summary = await summarizeHistory(friend.uid, {context: {auth: currentUser}});

รุ่น

const {text} = await ai.generate({
  prompt: "Find references to ocelots in my notes.",
  // the context will propagate to tool calls
  tools: [searchNotes],
  context: {auth: currentUser},
});

พรอมต์

const helloPrompt = ai.prompt('sayHello');
helloPrompt({pirateStyle: true}, {context: {auth: currentUser}});

การนำไปใช้งานบริบทและการลบล้าง

โดยค่าเริ่มต้น เมื่อคุณระบุบริบท ระบบจะนำไปเผยแพร่ไปยังการดำเนินการทั้งหมดที่เรียกใช้อันเป็นผลมาจากการเรียกครั้งแรกโดยอัตโนมัติ หากการเรียกใช้โฟลว์เรียกใช้โฟลว์อื่นๆ หรือเครื่องมือเรียกใช้เครื่องมืออื่นๆ ระบบจะแสดงบริบทเดียวกัน

หากต้องการลบล้างบริบทภายในการดําเนินการ ให้ส่งออบเจ็กต์บริบทอื่นเพื่อแทนที่ออบเจ็กต์ที่มีอยู่ ดังนี้

const otherFlow = ai.defineFlow(/* ... */);

const myFlow = ai.defineFlow({
  // ...
}, (input, {context}) => {
  // override the existing context completely
  otherFlow({/*...*/}, {context: {newContext: true}});
  // or selectively override
  otherFlow({/*...*/}, {context: {...context, updatedContext: true}});
}); 

เมื่อมีการแทนที่บริบท ระบบจะนำไปเผยแพร่ด้วยวิธีเดียวกัน ในตัวอย่างนี้ การดำเนินการใดๆ ที่ otherFlow เรียกใช้ระหว่างการดำเนินการจะรับค่าคอนテキストที่ลบล้าง