การเรียกใช้เครื่องมือ

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

โดยทั่วไปแล้ว Use Case ของการเรียกใช้เครื่องมือจะแบ่งออกเป็น 2-3 ธีม ดังนี้

การให้ LLM เข้าถึงข้อมูลที่ไม่ได้ใช้ฝึก

  • ข้อมูลที่มีการเปลี่ยนแปลงบ่อยครั้ง เช่น ราคาหุ้นหรือสภาพอากาศปัจจุบัน
  • ข้อมูลเฉพาะสำหรับโดเมนแอป เช่น ข้อมูลผลิตภัณฑ์หรือโปรไฟล์ผู้ใช้

โปรดทราบว่ามีบางส่วนที่ทับซ้อนกับการสร้างที่เพิ่มการดึงข้อมูล (RAG) ซึ่งเป็นวิธีให้ LLM ผสานรวมข้อมูลข้อเท็จจริงไว้ในการสร้างด้วย RAG เป็นโซลูชันที่หนักกว่าซึ่งเหมาะสําหรับกรณีที่คุณมีข้อมูลจํานวนมากหรือข้อมูลที่เกี่ยวข้องกับพรอมต์มากที่สุดมีความคลุมเครือ ในทางกลับกัน หากการเรียกฟังก์ชันหรือการค้นหาฐานข้อมูลเป็นสิ่งจําเป็นเพียงอย่างเดียวในการดึงข้อมูลที่ LLM ต้องการ การเรียกใช้เครื่องมือจะเหมาะสมกว่า

การนําระดับการกําหนดลงในเวิร์กโฟลว์ LLM

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

การดำเนินการเมื่อ LLM เริ่มต้น

  • การเปิดและปิดไฟในบ้านที่ทำงานด้วย LLM
  • การจองโต๊ะในตัวแทนร้านอาหารที่ทำงานด้วย LLM

ก่อนเริ่มต้น

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

หน้านี้กล่าวถึงฟีเจอร์ขั้นสูงอย่างหนึ่งของการแยกแยะโมเดล Genkit ดังนั้นก่อนลงลึก คุณควรทำความคุ้นเคยกับเนื้อหาในหน้าการสร้างเนื้อหาด้วยโมเดล AI นอกจากนี้ คุณควรทำความคุ้นเคยกับระบบของ Genkit ในการกําหนดสคีมาอินพุตและเอาต์พุต ซึ่งจะกล่าวถึงในหน้าเวิร์กโฟลว์

ภาพรวมของการเรียกใช้เครื่องมือ

โดยทั่วไปแล้ว การโต้ตอบแบบเรียกใช้เครื่องมือกับ LLM จะมีลักษณะดังนี้

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

ฟีเจอร์นี้ใช้ได้ก็ต่อเมื่อมีคุณสมบัติตรงตามข้อกำหนดต่อไปนี้

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

การโทรหาเครื่องมือด้วย Genkit

Genkit มีอินเทอร์เฟซเดียวสําหรับการเรียกใช้เครื่องมือกับโมเดลที่รองรับ ปลั๊กอินรูปแบบแต่ละรายการต้องเป็นไปตามเกณฑ์ 2 ข้อสุดท้ายที่กล่าวถึงในส่วนก่อนหน้า และฟังก์ชัน genkit.Generate() จะทําลูปการเรียกใช้เครื่องมือที่อธิบายไว้ก่อนหน้านี้โดยอัตโนมัติ

การรองรับโมเดล

การรองรับการเรียกใช้เครื่องมือจะขึ้นอยู่กับรุ่น API ของรุ่น และปลั๊กอิน Genkit โปรดดูเอกสารประกอบที่เกี่ยวข้องเพื่อพิจารณาว่าระบบมีแนวโน้มที่จะรองรับการเรียกใช้เครื่องมือหรือไม่ นอกจากนี้

  • Genkit จะแสดงข้อผิดพลาดหากคุณพยายามใส่เครื่องมือในโมเดลที่ไม่รองรับ
  • หากปลั๊กอินส่งออกข้อมูลอ้างอิงรูปแบบ ModelInfo.Supports.Tools พร็อพเพอร์ตี้จะระบุว่ารองรับการเรียกใช้เครื่องมือหรือไม่

เครื่องมือกำหนด

ใช้ฟังก์ชัน genkit.DefineTool() เพื่อเขียนคำจำกัดความของเครื่องมือ

import (
    "context"
    "log"

    "github.com/firebase/genkit/go/ai"
    "github.com/firebase/genkit/go/genkit"
    "github.com/firebase/genkit/go/plugins/googlegenai"
)

func main() {
    ctx := context.Background()

    g, err := genkit.Init(ctx,
        genkit.WithPlugins(&googlegenai.GoogleAI{}),
        genkit.WithDefaultModel("googleai/gemini-2.0-flash"),
    )
    if err != nil {
      log.Fatal(err)
    }

    getWeatherTool := genkit.DefineTool(
        g, "getWeather", "Gets the current weather in a given location",
        func(ctx *ai.ToolContext, location string) (string, error) {
            // Here, we would typically make an API call or database query. For this
            // example, we just return a fixed value.
            return fmt.Sprintf("The current weather in %s is 63°F and sunny.", location);
        })
}

ไวยากรณ์ที่นี่เหมือนกับไวยากรณ์ genkit.DefineFlow() แต่คุณต้องเขียนคำอธิบาย โปรดใช้คำที่สื่อความหมายและอธิบายได้ดี เนื่องจากคำอธิบายนี้มีความสำคัญต่อ LLM ในการตัดสินใจใช้คำอธิบายอย่างเหมาะสม

การใช้เครื่องมือ

ใส่เครื่องมือที่กําหนดไว้ในพรอมต์เพื่อสร้างเนื้อหา

สร้าง

resp, err := genkit.Generate(ctx, g,
    ai.WithPrompt("What is the weather in San Francisco?"),
    ai.WithTools(getWeatherTool),
)

DefinePrompt

weatherPrompt, err := genkit.DefinePrompt(g, "weatherPrompt",
    ai.WithPrompt("What is the weather in {{location}}?"),
    ai.WithTools(getWeatherTool),
)
if err != nil {
    log.Fatal(err)
}

resp, err := weatherPrompt.Execute(ctx,
    with.Input(map[string]any{"location": "San Francisco"}),
)

ไฟล์พรอมต์

---
system: "Answer questions using the tools you have."
tools: [getWeather]
input:
  schema:
    location: string
---

What is the weather in {{location}}?

จากนั้นเรียกใช้พรอมต์ในโค้ดของคุณดังนี้

// Assuming prompt file named weatherPrompt.prompt exists in ./prompts dir.
weatherPrompt := genkit.LookupPrompt("weatherPrompt")
if weatherPrompt == nil {
    log.Fatal("no prompt named 'weatherPrompt' found")
}

resp, err := weatherPrompt.Execute(ctx,
    ai.WithInput(map[string]any{"location": "San Francisco"}),
)

Genkit จะจัดการการเรียกใช้เครื่องมือโดยอัตโนมัติหาก LLM ต้องใช้เครื่องมือ getWeather เพื่อตอบกลับพรอมต์

การจัดการการเรียกใช้เครื่องมืออย่างชัดแจ้ง

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

getWeatherTool := genkit.DefineTool(
    g, "getWeather", "Gets the current weather in a given location",
    func(ctx *ai.ToolContext, location string) (string, error) {
        // Tool implementation...
    })

resp, err := genkit.Generate(ctx, g,
    ai.WithPrompt("What is the weather in San Francisco?"),
    ai.WithTools(getWeatherTool),
    ai.WithReturnToolRequests(true),
)
if err != nil {
    log.Fatal(err)
}

parts := []*Part{}
for _, req := range resp.ToolRequests() {
    tool := genkit.LookupTool(g, req.Name)
    if tool == nil {
        log.Fatalf("tool %q not found", req.Name)
    }

    output, err := tool.RunRaw(ctx, req.Input)
    if err != nil {
        log.Fatalf("tool %q execution failed: %v", err)
    }

    parts = append(parts,
        ai.NewToolResponsePart(&ai.ToolResponse{
            Name:   req.Name,
            Ref:    req.Ref,
            Output: output,
        }))
}

resp, err = genkit.Generate(ctx, g,
    ai.WithMessages(resp.History()..., NewMessage(ai.RoleTool, nil, parts...)),
)
if err != nil {
    log.Fatal(err)
}