Gọi công cụ

Gọi công cụ, còn gọi là gọi hàm, là một cách có cấu trúc để cung cấp Các LLM (mô hình ngôn ngữ lớn) có thể gửi yêu cầu về ứng dụng đã gọi nó. Bạn xác định các công cụ bạn muốn cung cấp cho mô hình và mô hình sẽ đưa ra yêu cầu của công cụ đến ứng dụng khi cần thiết để 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 rơi vào một số chủ đề:

Cấp cho một mô hình ngôn ngữ lớn (LLM) quyền truy cập vào thông tin mà mô hình này không được huấn luyện

  • Thông tin thường xuyên thay đổi, chẳng hạn như thực đơn hằng ngày của nhà hàng hoặc trạng thái kho hàng của cửa hàng.
  • Thông tin cụ thể về miền ứng dụng của bạn, chẳng hạn như thông tin sản phẩm.

Xin lưu ý sự trùng lặp với hoạt động tạo tăng cường truy xuất (RAG), cũng là một cách để cho phép một 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 hoặc thông tin liên quan nhất đến câu lệnh luôn mơ hồ. Bật mặt khác, nếu việc truy xuất thông tin mà LLM cần là một hàm đơn giản lệnh gọi hoặc tra cứu cơ sở dữ liệu, thì lệnh gọi công cụ sẽ phù hợp hơn.

Đưa tính tất định vào quy trình làm việc của một mô hình ngôn ngữ lớn (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 một 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 ứng dụng.

Thực hiện hành động khi do một mô hình ngôn ngữ lớn (LLM) khởi xướng

  • Bật và tắt đèn trong trợ lý gia đình sử dụng LLM
  • Đặt chỗ trước tại bàn trong một nhân viên hỗ trợ nhà hàng được LLM hỗ trợ

Trước khi bắt đầu

Nếu bạn muốn chạy các đoạn mã ví dụ 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ả 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 của Genkit.

Trang này thảo luận một trong các tính năng nâng cao của việc trừu tượng hoá mô hình Genkit và generate(), do đó, trước khi tìm hiểu sâu, 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 nên cũng đã quen thuộc với hệ thống của Genkit để xác định giản đồ đầu vào và đầu ra, Nội dung này sẽ được thảo luận trên trang Luồng.

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

Nhìn chung, đây là hoạt động tương tác thông thường để gọi công cụ với một mô hình ngôn ngữ lớn (LLM) sẽ có dạng như sau:

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

Để làm được điều này, bạn phải đáp ứng một số yêu cầu:

  • Mô hình phải được huấn luyện để đưa ra các yêu cầu về công cụ khi cần thiết để hoàn tất một . Hầu hết các mô hình lớn được cung cấp thông qua API web, chẳng hạn như Gemini và Meryl có thể làm được điều này, nhưng các mô hình nhỏ hơn và chuyên biệt hơn thường không thể làm được. Genkit sẽ báo lỗi nếu bạn cố cung cấp công cụ cho một mô hình không hỗ trợ cuộc trò chuyện.
  • Ứng dụng gọi phải cung cấp định nghĩa công cụ cho mô hình trong định dạng mà nó mong đợi.
  • Ứng dụng gọi phải nhắc mô hình tạo lệnh gọi công cụ các yêu cầu ở đị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ợ giao diện này. Mỗi trình bổ trợ mô hình đảm bảo rằng hai tiêu chí cuối cùng trong số các tiêu chí nêu trên được đáp ứng, và hàm generate() 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

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

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

Xác định công cụ

Dùng hàm defineTool() để viết định nghĩa công cụ:

const specialToolInputSchema = z.object({ meal: z.enum(["breakfast", "lunch", "dinner"]) });
const specialTool = defineTool(
  {
    name: "specialTool",
    description: "Retrieves today's special for the given meal",
    inputSchema: specialToolInputSchema,
    outputSchema: z.string(),
  },
  async ({ meal }): Promise<string> => {
    // Retrieve up-to-date information and return it. Here, we just return a
    // fixed value.
    return "Baked beans on toast";
  }
);

Cú pháp ở đây giống như cú pháp defineFlow(); Tuy nhiên, cả bốn các tham số name, description, inputSchemaoutputSchema là là bắt buộc. Khi viết định nghĩa về công cụ, hãy đặc biệt chú ý đến từ ngữ và mô tả của các tham số này vì chúng rất quan trọng đối với LLM sử dụng hiệu quả các công cụ sẵn có.

Thêm công cụ vào câu lệnh

Sau khi bạn xác định các công cụ của mình, hãy chỉ định chúng trong thông số tools của generate():

const llmResponse = await generate({
  model: gemini15Flash,
  prompt,
  tools: [specialTool],
});

Bạn có thể cung cấp nhiều công cụ; LLM sẽ gọi các công cụ này khi cần để hoàn tất lời nhắc.

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

Theo mặc định, Genkit nhiều lần gọi LLM cho đến khi mọi lệnh gọi công cụ đều được thực hiện đã được giải quyết. Nếu bạn muốn kiểm soát nhiều hơn đối với 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 tham số returnToolRequests thành true. Giờ đây, bạn có trách nhiệm đảm bảo tất cả các yêu cầu liên quan đến công cụ đều được thực hiện:

let generateOptions: GenerateOptions = {
  model: gemini15Flash,
  prompt,
  tools: [specialTool],
  returnToolRequests: true,
};
let llmResponse;
while (true) {
  llmResponse = await generate(generateOptions);
  const toolRequests = llmResponse.toolRequests();
  if (toolRequests.length < 1) {
    break;
  }
  const toolResponses: ToolResponsePart[] = await Promise.all(
    toolRequests.map(async (part) => {
      switch (part.toolRequest.name) {
        case "specialTool":
          return {
            toolResponse: {
              name: part.toolRequest.name,
              ref: part.toolRequest.ref,
              output: await specialTool(specialToolInputSchema.parse(part.toolRequest?.input)),
            },
          };
        default:
          throw Error('Tool not found');
        }
      }));
    generateOptions.history = llmResponse.toHistory();
    generateOptions.prompt = toolResponses;
}