Transformers documentation

Sử dụng công cụ

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.2).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Sử dụng công cụ

Các mô hình chat thường được huấn luyện với hỗ trợ “function-calling” hoặc “tool-use”. Công cụ là các hàm do người dùng cung cấp, mà mô hình có thể chọn gọi như một phần của phản hồi. Ví dụ, mô hình có thể truy cập công cụ máy tính để thực hiện các phép tính mà không cần phải thực hiện phép tính bên trong.

Hướng dẫn này sẽ minh họa cách định nghĩa các công cụ, cách truyền chúng cho một mô hình chat, và cách xử lý đầu ra của mô hình khi nó gọi một công cụ.

Truyền công cụ

Khi một model hỗ trợ tool-use, hãy truyền các functions vào tham số tools của apply_chat_template(). Các tools được truyền dưới dạng JSON schema hoặc các Python functions. Nếu bạn truyền các Python functions, các arguments, types của arguments và docstring của function sẽ được parse để tự động tạo ra JSON schema.

Mặc dù việc truyền các hàm Python rất tiện lợi, trình phân tích chỉ có thể xử lý docstring theo phong cách Google. Tham khảo các ví dụ bên dưới để biết cách định dạng một hàm sẵn sàng làm công cụ.

def get_current_temperature(location: str, unit: str):
    """
    Get the current temperature at a location.

    Args:
        location: The location to get the temperature for, in the format "City, Country"
        unit: The unit to return the temperature in. (choices: ["celsius", "fahrenheit"])
    """
    return 22.  # A real function should probably actually get the temperature!

def get_current_wind_speed(location: str):
    """
    Get the current wind speed in km/h at a given location.

    Args:
        location: The location to get the wind speed for, in the format "City, Country"
    """
    return 6.  # A real function should probably actually get the wind speed!

tools = [get_current_temperature, get_current_wind_speed]

Bạn có thể tùy chọn thêm khối Returns: vào docstring và kiểu trả về vào phần đầu của hàm, nhưng hầu hết các model sẽ không sử dụng thông tin này. Trình phân tích cũng sẽ bỏ qua mã thực tế bên trong hàm!

Điều thực sự quan trọng là tên hàm, tên các tham số, kiểu của các tham số và docstring mô tả mục đích của hàm cũng như mục đích của từng tham số. Những yếu tố này tạo nên “chữ ký” mà mô hình sẽ sử dụng để quyết định có gọi công cụ hay không.

Ví dụ về gọi công cụ

Tải một model và tokenizer hỗ trợ tool-use như NousResearch/Hermes-2-Pro-Llama-3-8B, nhưng bạn cũng có thể cân nhắc một model lớn hơn như Command-R và Mixtral-8x22B nếu phần cứng của bạn hỗ trợ.

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

checkpoint = "NousResearch/Hermes-2-Pro-Llama-3-8B"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForCausalLM.from_pretrained(checkpoint, dtype="auto", device_map="auto")

Tạo lịch sử trò chuyện.

messages = [
  {"role": "system", "content": "You are a bot that responds to weather queries. You should reply with the unit used in the queried location."},
  {"role": "user", "content": "Hey, what's the temperature in Paris right now?"}
]

Tiếp theo, truyền messages và một danh sách các công cụ vào apply_chat_template(). Tokenize cuộc trò chuyện và tạo phản hồi.

inputs = tokenizer.apply_chat_template(messages, tools=tools, add_generation_prompt=True, return_dict=True, return_tensors="pt")
outputs = model.generate(**inputs.to(model.device), max_new_tokens=128)
print(tokenizer.decode(outputs[0][len(inputs["input_ids"][0]):]))
<tool_call>
{"arguments": {"location": "Paris, France", "unit": "celsius"}, "name": "get_current_temperature"}
</tool_call><|im_end|>

Mô hình chat đã gọi công cụ get_current_temperature với các tham số chính xác từ docstring. Nó suy luận ra Pháp là vị trí dựa trên Paris, và rằng nên sử dụng Celsius cho đơn vị nhiệt độ.

Một model không thể tự gọi công cụ. Nó yêu cầu một cuộc gọi công cụ, và việc xử lý cuộc gọi đó, sau đó thêm nó cùng kết quả vào lịch sử chat là trách nhiệm của bạn. Đối với các model hỗ trợ response parsing, quá trình phân tích phản hồi sẽ được xử lý tự động, và bạn chỉ cần dùng parse_response() để trích xuất cuộc gọi công cụ. Đối với các model khác, bạn sẽ cần tự động dịch chuỗi đầu ra thành một dict cuộc gọi công cụ.

Bất kể cách tiếp cận bạn sử dụng, lời gọi công cụ phải nằm trong khóa tool_calls của một thông điệp assistant. Đây là API được khuyến nghị và nên được hỗ trợ bởi chat template của hầu hết các mô hình sử dụng công cụ.

Mặc dù tool_calls tương tự API của OpenAI, API của OpenAI lại sử dụng chuỗi JSON làm định dạng tool_calls của nó. Điều này có thể gây ra lỗi hoặc hành vi kỳ lạ của mô hình nếu được sử dụng trong Transformers, vốn kỳ vọng một dict.

tool_call = {"name": "get_current_temperature", "arguments": {"location": "Paris, France", "unit": "celsius"}}
messages.append({"role": "assistant", "tool_calls": [{"type": "function", "function": tool_call}]})

Thêm phản hồi của công cụ vào lịch sử trò chuyện với vai trò tool.

messages.append({"role": "tool", "content": "22"})  # Note that the returned content is always a string!

Cuối cùng, cho phép mô hình đọc phản hồi từ công cụ và trả lời cho người dùng.

inputs = tokenizer.apply_chat_template(messages, tools=tools, add_generation_prompt=True, return_dict=True, return_tensors="pt")
out = model.generate(**inputs.to(model.device), max_new_tokens=128)
print(tokenizer.decode(out[0][len(inputs["input_ids"][0]):]))
The temperature in Paris, France right now is 22°C.<|im_end|>

Mặc dù khóa trong thông điệp của trợ lý được gọi là tool_calls, trong hầu hết các trường hợp, các mô hình chỉ phát ra một lệnh gọi công cụ tại một thời điểm. Một số mô hình cũ hơn phát ra nhiều lệnh gọi công cụ cùng lúc, nhưng đây là một quy trình phức tạp hơn đáng kể, vì bạn cần xử lý nhiều phản hồi công cụ cùng một lúc và phân biệt chúng, thường là bằng cách sử dụng ID của lệnh gọi công cụ. Vui lòng tham khảo thẻ mô hình để xem chính xác định dạng mà mô hình mong đợi cho các lệnh gọi công cụ.

Sơ đồ JSON

Một cách khác để định nghĩa công cụ là bằng cách truyền vào một sơ đồ JSON.

Bạn cũng có thể gọi thủ công các hàm cấp thấp chuyển đổi các hàm Python sang JSON schema, sau đó kiểm tra hoặc chỉnh sửa các schema đã tạo. Điều này thường không cần thiết, nhưng hữu ích để hiểu cơ chế bên dưới. Nó đặc biệt quan trọng đối với những người tạo chat template cần truy cập JSON schema để render các định nghĩa công cụ.

Phương thức apply_chat_template() sử dụng hàm get_json_schema để chuyển đổi các callable Python sang JSON schema. Điều này bao gồm các phương thức: self và cls được coi là các đối số nhận ngầm và bị bỏ qua.

from transformers.utils import get_json_schema

def multiply(a: float, b: float):
    """
    A function that multiplies two numbers

    Args:
        a: The first number to multiply
        b: The second number to multiply
    """
    return a * b

schema = get_json_schema(multiply)
print(schema)
{
  "type": "function",
  "function": {
    "name": "multiply",
    "description": "A function that multiplies two numbers",
    "parameters": {
      "type": "object",
      "properties": {
        "a": {
          "type": "number",
          "description": "The first number to multiply"
        },
        "b": {
          "type": "number",
          "description": "The second number to multiply"
        }
      },
      "required": ["a", "b"]
    }
  }
}

Chúng tôi sẽ không đi vào chi tiết về chính JSON schema ở đây, vì nó đã được đánh giá rất tốt ở nơi khác. Tuy nhiên, chúng tôi sẽ đề cập rằng bạn có thể truyền các dict JSON schema vào tham số tools của apply_chat_template() thay vì các hàm Python:

# A simple function that takes no arguments
current_time = {
  "type": "function",
  "function": {
    "name": "current_time",
    "description": "Get the current local time as a string.",
    "parameters": {
      'type': 'object',
      'properties': {}
    }
  }
}

# A more complete function that takes two numerical arguments
multiply = {
  'type': 'function',
  'function': {
    'name': 'multiply',
    'description': 'A function that multiplies two numbers',
    'parameters': {
      'type': 'object',
      'properties': {
        'a': {
          'type': 'number',
          'description': 'The first number to multiply'
        },
        'b': {
          'type': 'number', 'description': 'The second number to multiply'
        }
      },
      'required': ['a', 'b']
    }
  }
}

model_input = tokenizer.apply_chat_template(
    messages,
    tools = [current_time, multiply]
)
Update on GitHub