Gọi công cụ

Lệnh gọi công cụ (còn gọi là lệnh gọi hàm) là một cách có cấu trúc để cho phép LLM đưa ra yêu cầu trả về cho ứng dụng đã gọi lệnh gọi đó. Bạn xác định các công cụ mà bạn muốn cung cấp cho mô hình và mô hình sẽ đưa ra các yêu cầu về công cụ cho ứng dụng của bạn nếu cần để thực hiện các lời nhắc mà bạn đưa ra.

Các trường hợp sử dụng lệnh gọi công cụ thường thuộc một số chủ đề:

Cấp cho LLM quyền truy cập vào thông tin mà LLM không được huấn luyện

  • Thông tin thay đổi thường xuyên, chẳng hạn như giá cổ phiếu hoặc thời tiết hiện tại.
  • Thông tin dành riêng cho miền ứng dụng của bạn, chẳng hạn như thông tin sản phẩm hoặc hồ sơ người dùng.

Lưu ý sự trùng lặp với tạo dữ liệu tăng cường truy xuất (RAG). Đây cũng là một cách để cho phép LLM tích hợp thông tin thực tế vào các thế hệ của nó. RAG là một giải pháp nặng hơn, phù hợp nhất khi bạn có một lượng lớn thông tin hoặc thông tin phù hợp nhất với câu lệnh không rõ ràng. Mặt khác, nếu lệnh gọi hàm hoặc tra cứu cơ sở dữ liệu là tất cả những gì cần thiết để truy xuất thông tin mà LLM cần, thì lệnh gọi công cụ sẽ phù hợp hơn.

Giới thiệu một mức độ xác định vào quy trình công việc LLM

  • Thực hiện các phép tính mà LLM không thể tự hoàn tất một cách đáng tin cậy.
  • Buộc LLM tạo văn bản nguyên văn trong một số trường hợp nhất định, chẳng hạn như khi trả lời câu hỏi về điều khoản dịch vụ của một ứng dụng.

Thực hiện một hành động khi được LLM khởi tạo

  • Bật và tắt đèn trong trợ lý nhà sử dụng LLM
  • Đặt chỗ bàn trong một tác nhân nhà hàng sử dụng LLM

Trước khi bắt đầu

Nếu bạn muốn chạy các ví dụ về mã trên trang này, trước tiên, hãy hoàn thành các bước trong hướng dẫn Bắt đầu. Tất cả các ví dụ đều giả định rằng bạn đã thiết lập một dự án có cài đặt các phần phụ thuộc Genkit.

Trang này thảo luận về một trong những tính năng nâng cao của tính năng trừu tượng mô hình Genkit. Vì vậy, trước khi đi sâu vào vấn đề, bạn nên làm quen với nội dung trên trang Tạo nội dung bằng mô hình AI. Bạn cũng nên làm quen với hệ thống của Genkit để xác định giản đồ đầu vào và đầu ra. Hệ thống này được thảo luận trên trang Flows (Luồng).

Tổng quan về lệnh gọi công cụ

Ở cấp độ cao, đây là cách tương tác gọi công cụ thông thường với LLM:

  1. Ứng dụng gọi sẽ đưa ra yêu cầu cho LLM và cũng đưa vào lời nhắc danh sách các công cụ mà LLM có thể sử dụng để tạo phản hồi.
  2. LLM tạo một phản hồi hoàn chỉnh hoặc tạo một yêu cầu gọi công cụ ở định dạng cụ thể.
  3. Nếu phương thức gọi nhận được phản hồi đầy đủ, yêu cầu sẽ được thực hiện và hoạt động tương tác sẽ kết thúc; nhưng nếu phương thức gọi nhận được lệnh gọi công cụ, thì phương thức gọi đó sẽ thực hiện bất kỳ logic nào phù hợp và gửi một yêu cầu mới đến LLM chứa lời nhắc ban đầu hoặc một số biến thể của lời nhắc đó cũng như kết quả của lệnh gọi công cụ.
  4. LLM xử lý lời nhắc mới như trong Bước 2.

Để tính năng này hoạt động, bạn phải đáp ứng một số yêu cầu:

  • Mô hình phải được huấn luyện để tạo yêu cầu công cụ khi cần thiết để hoàn tất một câu lệnh. Hầu hết các mô hình lớn hơn được cung cấp thông qua API web như Gemini có thể thực hiện việc này, nhưng các mô hình nhỏ hơn và chuyên biệt hơn thường không thể. Genkit sẽ gửi lỗi nếu bạn cố gắng cung cấp công cụ cho một mô hình không hỗ trợ công cụ đó.
  • Ứng dụng gọi phải cung cấp định nghĩa công cụ cho mô hình ở định dạng mà ứng dụng đó mong đợi.
  • Ứng dụng gọi phải nhắc mô hình tạo các yêu cầu gọi công cụ ở định dạng mà ứng dụng mong đợi.

Gọi công cụ bằng Genkit

Genkit cung cấp một giao diện duy nhất để gọi công cụ với các mô hình hỗ trợ công cụ đó. Mỗi trình bổ trợ mô hình đảm bảo đáp ứng hai tiêu chí cuối cùng được đề cập trong phần trước và hàm genkit.Generate() sẽ tự động thực hiện vòng lặp gọi công cụ được mô tả trước đó.

Hỗ trợ mô hình

Tính năng hỗ trợ gọi công cụ phụ thuộc vào mô hình, API mô hình và trình bổ trợ Genkit. Tham khảo tài liệu có liên quan để xác định xem tính năng gọi công cụ có được hỗ trợ hay không. Ngoài ra:

  • Genkit sẽ báo lỗi nếu bạn cố gắng cung cấp công cụ cho một mô hình không hỗ trợ công cụ đó.
  • Nếu trình bổ trợ xuất các tệp tham chiếu mô hình, thì thuộc tính ModelInfo.Supports.Tools sẽ cho biết liệu trình bổ trợ có hỗ trợ tính năng gọi công cụ hay không.

Xác định công cụ

Sử dụng hàm genkit.DefineTool() để viết định nghĩa công cụ:

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);
        })
}

Cú pháp ở đây giống hệt như cú pháp genkit.DefineFlow(); tuy nhiên, bạn phải viết nội dung mô tả. Hãy đặc biệt chú ý đến cách diễn đạt và tính mô tả của nội dung mô tả vì điều này rất quan trọng để LLM quyết định sử dụng nội dung mô tả một cách phù hợp.

Sử dụng công cụ

Thêm các công cụ đã xác định vào câu lệnh để tạo nội dung.

Tạo

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"}),
)

Tệp lời nhắc

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

What is the weather in {{location}}?

Sau đó, bạn có thể thực thi lời nhắc trong mã của mình như sau:

// 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 sẽ tự động xử lý lệnh gọi công cụ nếu LLM cần sử dụng công cụ getWeather để trả lời lời nhắc.

Xử lý rõ ràng các lệnh gọi công cụ

Nếu bạn muốn toàn quyền kiểm soát vòng lặp gọi công cụ này, chẳng hạn như để áp dụng logic phức tạp hơn, hãy đặt tuỳ chọn WithReturnToolRequests() thành true. Giờ đây, bạn có trách nhiệm đảm bảo tất cả các yêu cầu về công cụ đều được thực hiện:

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)
}