Hướng dẫn: Gọi hàm bằng API Gemini


Xem trên ai.google.dev Chạy trong Google Colab Xem nguồn trên GitHub

Sử dụng lệnh gọi hàm để xác định các hàm tuỳ chỉnh và truyền các hàm đó đến Gemini. Mô hình này không trực tiếp gọi các hàm này mà tạo dữ liệu đầu ra có cấu trúc chỉ định tên hàm và các đối số đề xuất. Kết quả này cho phép gọi các API bên ngoài và sau đó, kết quả API thu được có thể được tích hợp lại vào mô hình, cho phép phản hồi truy vấn toàn diện hơn. Chức năng gọi hàm cho phép các LLM tương tác với thông tin theo thời gian thực và nhiều dịch vụ khác nhau, chẳng hạn như cơ sở dữ liệu, hệ thống quản lý quan hệ khách hàng và kho lưu trữ tài liệu, nhờ đó nâng cao khả năng đưa ra câu trả lời phù hợp và theo bối cảnh. Bạn có thể cung cấp cho mô hình Gemini nội dung mô tả về các hàm. Mô hình này có thể yêu cầu bạn gọi một hàm và gửi lại kết quả để giúp mô hình đó xử lý truy vấn của bạn.

Nếu bạn chưa xem, hãy xem phần Giới thiệu về tính năng gọi hàm để tìm hiểu thêm.

Thiết lập

Cài đặt SDK Python

SDK Python cho API Gemini nằm trong gói google-generativeai. Cài đặt phần phụ thuộc bằng pip:

pip install -U -q google-generativeai

Nhập gói

Nhập các gói cần thiết.

import pathlib
import textwrap
import time

import google.generativeai as genai

from IPython import display
from IPython.display import Markdown

def to_markdown(text):
  text = text.replace('•', '  *')
  return Markdown(textwrap.indent(text, '> ', predicate=lambda _: True))

Thiết lập khoá API

Để có thể sử dụng API Gemini, trước tiên, bạn phải có được khoá API. Nếu bạn chưa có khoá, hãy tạo khoá chỉ bằng một lần nhấp trong Google AI Studio.

Lấy khoá API

Trong Colab, hãy thêm khoá vào trình quản lý khoá bí mật trong mục "🔑" trên bảng điều khiển bên trái. Đặt tên cho API_KEY.

Sau khi bạn có khoá API, hãy truyền khoá đó vào SDK. Bạn có thể làm điều này theo hai cách:

  • Đặt khoá vào biến môi trường GOOGLE_API_KEY (SDK sẽ tự động nhận khoá từ đó).
  • Truyền khoá đến genai.configure(api_key=...)
try:
    # Used to securely store your API key
    from google.colab import userdata

    # Or use `os.getenv('API_KEY')` to fetch an environment variable.
    GOOGLE_API_KEY=userdata.get('GOOGLE_API_KEY')
except ImportError:
    import os
    GOOGLE_API_KEY = os.environ['GOOGLE_API_KEY']

genai.configure(api_key=GOOGLE_API_KEY)

Thông tin cơ bản về lệnh gọi hàm

Để sử dụng tính năng gọi hàm, hãy truyền danh sách hàm vào tham số tools khi tạo GenerativeModel. Mô hình này sử dụng chú giải tên hàm, chuỗi tài liệu, tham số và loại tham số để quyết định xem có cần hàm đó để trả lời câu lệnh chính xác nhất hay không.

def multiply(a:float, b:float):
    """returns a * b."""
    return a*b

model = genai.GenerativeModel(model_name='gemini-1.0-pro',
                              tools=[multiply])

model
genai.GenerativeModel(
    model_name='models/gemini-1.0-pro',
    generation_config={},
    safety_settings={},
    tools=<google.generativeai.types.content_types.FunctionLibrary object at 0x10e73fe90>,
)

Bạn nên sử dụng các lệnh gọi hàm thông qua giao diện trò chuyện. Nguyên nhân là do các lệnh gọi hàm vốn phù hợp với cuộc trò chuyện nhiều lượt vì chúng thể hiện hoạt động tương tác qua lại giữa người dùng và mô hình. ChatSession của SDK Python là một giao diện tuyệt vời dành cho cuộc trò chuyện vì giao diện này xử lý nhật ký trò chuyện cho bạn, đồng thời việc sử dụng tham số enable_automatic_function_calling giúp đơn giản hoá việc gọi hàm hơn nữa:

chat = model.start_chat(enable_automatic_function_calling=True)

Khi bật tính năng gọi hàm tự động, chat.send_message sẽ tự động gọi hàm của bạn nếu mô hình yêu cầu.

Có vẻ như ứng dụng này chỉ trả về một phản hồi bằng văn bản chứa câu trả lời chính xác:

response = chat.send_message('I have 57 cats, each owns 44 mittens, how many mittens is that in total?')
response.text
'The total number of mittens is 2508.'
57*44
2508

Kiểm tra nhật ký trò chuyện để xem luồng cuộc trò chuyện và cách các lệnh gọi hàm được tích hợp vào đó.

Thuộc tính ChatSession.history lưu trữ bản ghi theo trình tự thời gian của cuộc trò chuyện giữa người dùng và mô hình Gemini. Mỗi lượt trong cuộc trò chuyện được biểu thị bằng một đối tượng glm.Content, chứa các thông tin sau:

  • Vai trò: Xác định xem nội dung bắt nguồn từ "người dùng" hay "mô hình".
  • Phần: Danh sách các đối tượng glm.Part đại diện cho các thành phần riêng lẻ của thông báo. Với mô hình chỉ văn bản, các phần sau có thể là:
    • Văn bản: Tin nhắn văn bản thuần tuý.
    • Lệnh gọi hàm (glm.FunctionCall): Yêu cầu từ mô hình để thực thi một hàm cụ thể với các đối số đã cho.
    • Phản hồi của hàm (glm.FunctionResponse): Kết quả mà người dùng trả về sau khi thực thi hàm được yêu cầu.

Trong ví dụ trước về cách tính găng tay, nhật ký cho thấy trình tự sau đây:

  1. Người dùng: Đặt câu hỏi về tổng số găng tay.
  2. Mô hình: Xác định rằng hàm nhân là hữu ích và gửi yêu cầu FunctionCall cho người dùng.
  3. Người dùng: ChatSession tự động thực thi hàm (do bạn đang đặt enable_automatic_function_calling) và gửi lại một FunctionResponse kèm theo kết quả đã tính.
  4. Mô hình: Sử dụng kết quả của hàm để tạo câu trả lời cuối cùng và trình bày câu trả lời đó dưới dạng phản hồi bằng văn bản.
for content in chat.history:
    part = content.parts[0]
    print(content.role, "->", type(part).to_dict(part))
    print('-'*80)
user -> {'text': 'I have 57 cats, each owns 44 mittens, how many mittens is that in total?'}
--------------------------------------------------------------------------------
model -> {'function_call': {'name': 'multiply', 'args': {'a': 57.0, 'b': 44.0} } }
--------------------------------------------------------------------------------
user -> {'function_response': {'name': 'multiply', 'response': {'result': 2508.0} } }
--------------------------------------------------------------------------------
model -> {'text': 'The total number of mittens is 2508.'}
--------------------------------------------------------------------------------

Nhìn chung, sơ đồ trạng thái là:

Mô hình luôn có thể trả lời bằng văn bản hoặc dùng FunctionCall. Nếu mô hình gửi một FunctionCall, người dùng phải trả lời bằng một FunctionResponse

Mô hình này có thể phản hồi bằng nhiều lệnh gọi hàm trước khi trả về phản hồi bằng văn bản, còn các lệnh gọi hàm thì trước phản hồi bằng văn bản.

Mặc dù tất cả đều được xử lý tự động, nhưng nếu cần kiểm soát nhiều hơn, bạn có thể:

  • Giữ nguyên enable_automatic_function_calling=False mặc định và tự xử lý các câu trả lời glm.FunctionCall.
  • Hoặc sử dụng GenerativeModel.generate_content, nơi bạn cũng cần quản lý nhật ký trò chuyện.

Gọi hàm song song

Ngoài lệnh gọi hàm cơ bản được mô tả ở trên, bạn cũng có thể gọi nhiều hàm cùng một lúc. Phần này trình bày một ví dụ về cách bạn có thể sử dụng lệnh gọi hàm song song.

Xác định các công cụ.

def power_disco_ball(power: bool) -> bool:
    """Powers the spinning disco ball."""
    print(f"Disco ball is {'spinning!' if power else 'stopped.'}")
    return True


def start_music(energetic: bool, loud: bool, bpm: int) -> str:
    """Play some music matching the specified parameters.

    Args:
      energetic: Whether the music is energetic or not.
      loud: Whether the music is loud or not.
      bpm: The beats per minute of the music.

    Returns: The name of the song being played.
    """
    print(f"Starting music! {energetic=} {loud=}, {bpm=}")
    return "Never gonna give you up."


def dim_lights(brightness: float) -> bool:
    """Dim the lights.

    Args:
      brightness: The brightness of the lights, 0.0 is off, 1.0 is full.
    """
    print(f"Lights are now set to {brightness:.0%}")
    return True

Bây giờ, hãy gọi mô hình kèm theo hướng dẫn có thể sử dụng mọi công cụ đã chỉ định.

# Set the model up with tools.
house_fns = [power_disco_ball, start_music, dim_lights]

model = genai.GenerativeModel(model_name="gemini-1.5-pro-latest", tools=house_fns)

# Call the API.
chat = model.start_chat()
response = chat.send_message("Turn this place into a party!")

# Print out each of the function calls requested from this single call.
for part in response.parts:
    if fn := part.function_call:
        args = ", ".join(f"{key}={val}" for key, val in fn.args.items())
        print(f"{fn.name}({args})")
power_disco_ball(power=True)
start_music(energetic=True, loud=True, bpm=120.0)
dim_lights(brightness=0.3)

Mỗi kết quả được in phản ánh một lệnh gọi hàm duy nhất mà mô hình đã yêu cầu. Để gửi lại kết quả, hãy thêm các câu trả lời theo đúng thứ tự mà chúng được yêu cầu.

# Simulate the responses from the specified tools.
responses = {
    "power_disco_ball": True,
    "start_music": "Never gonna give you up.",
    "dim_lights": True,
}

# Build the response parts.
response_parts = [
    glm.Part(function_response=glm.FunctionResponse(name=fn, response={"result": val}))
    for fn, val in responses.items()
]

response = chat.send_message(response_parts)
print(response.text)
Let's get this party started! I've turned on the disco ball, started playing some upbeat music, and dimmed the lights. 🎶✨  Get ready to dance! 🕺💃

(Không bắt buộc) Quyền truy cập cấp thấp

Không phải trường hợp nào bạn cũng có thể trích xuất tự động giản đồ từ các hàm python. Ví dụ: API này không xử lý các trường hợp mà bạn mô tả các trường của một đối tượng từ điển lồng nhau, nhưng API có hỗ trợ việc này. API này có thể mô tả bất kỳ loại nào sau đây:

AllowedType = (int | float | bool | str | list['AllowedType'] | dict[str, AllowedType]

Thư viện ứng dụng google.ai.generativelanguage cung cấp quyền truy cập vào các loại cấp thấp để bạn có toàn quyền kiểm soát.

import google.ai.generativelanguage as glm

Xem nhanh trước bên trong thuộc tính _tools của mô hình, bạn có thể thấy cách thuộc tính đó mô tả(các) hàm mà bạn đã truyền vào mô hình:

def multiply(a:float, b:float):
    """returns a * b."""
    return a*b

model = genai.GenerativeModel(model_name='gemini-1.0-pro',
                             tools=[multiply])

model._tools.to_proto()
[function_declarations {
   name: "multiply"
   description: "returns a * b."
   parameters {
     type_: OBJECT
     properties {
       key: "b"
       value {
         type_: NUMBER
       }
     }
     properties {
       key: "a"
       value {
         type_: NUMBER
       }
     }
     required: "a"
     required: "b"
   }
 }]

Thao tác này sẽ trả về danh sách các đối tượng glm.Tool sẽ được gửi đến API. Nếu bạn không quen thuộc với định dạng in, thì đó là do đây là các lớp protobuf của Google. Mỗi glm.Tool (1 trong trường hợp này) chứa một danh sách glm.FunctionDeclarations giúp mô tả một hàm và các đối số của hàm đó.

Dưới đây là phần khai báo cho cùng một hàm nhân được viết bằng các lớp glm.

Lưu ý rằng các lớp này chỉ mô tả chức năng cho API, chứ không bao gồm việc triển khai hàm. Vì vậy, việc sử dụng hàm này không hiệu quả với tính năng gọi hàm tự động, nhưng các hàm không phải lúc nào cũng cần triển khai.

calculator = glm.Tool(
    function_declarations=[
      glm.FunctionDeclaration(
        name='multiply',
        description="Returns the product of two numbers.",
        parameters=glm.Schema(
            type=glm.Type.OBJECT,
            properties={
                'a':glm.Schema(type=glm.Type.NUMBER),
                'b':glm.Schema(type=glm.Type.NUMBER)
            },
            required=['a','b']
        )
      )
    ])

Tương đương, bạn có thể mô tả đây là một đối tượng tương thích với JSON:

calculator = {'function_declarations': [
      {'name': 'multiply',
       'description': 'Returns the product of two numbers.',
       'parameters': {'type_': 'OBJECT',
       'properties': {
         'a': {'type_': 'NUMBER'},
         'b': {'type_': 'NUMBER'} },
       'required': ['a', 'b']} }]}
glm.Tool(calculator)
function_declarations {
  name: "multiply"
  description: "Returns the product of two numbers."
  parameters {
    type_: OBJECT
    properties {
      key: "b"
      value {
        type_: NUMBER
      }
    }
    properties {
      key: "a"
      value {
        type_: NUMBER
      }
    }
    required: "a"
    required: "b"
  }
}

Dù bằng cách nào, bạn cũng truyền bản trình bày của glm.Tool hoặc danh sách công cụ để

model = genai.GenerativeModel('gemini-pro', tools=calculator)
chat = model.start_chat()

response = chat.send_message(
    f"What's 234551 X 325552 ?",
)

Giống như trước khi mô hình này trả về glm.FunctionCall gọi hàm multiply của máy tính:

response.candidates
[index: 0
content {
  parts {
    function_call {
      name: "multiply"
      args {
        fields {
          key: "b"
          value {
            number_value: 325552
          }
        }
        fields {
          key: "a"
          value {
            number_value: 234551
          }
        }
      }
    }
  }
  role: "model"
}
finish_reason: STOP
]

Tự thực thi hàm:

fc = response.candidates[0].content.parts[0].function_call
assert fc.name == 'multiply'

result = fc.args['a'] * fc.args['b']
result
76358547152.0

Gửi kết quả đến mô hình để tiếp tục cuộc trò chuyện:

response = chat.send_message(
    glm.Content(
    parts=[glm.Part(
        function_response = glm.FunctionResponse(
          name='multiply',
          response={'result': result}))]))

Tóm tắt

SDK hỗ trợ tính năng gọi hàm cơ bản. Hãy nhớ rằng sẽ dễ quản lý hơn bằng cách sử dụng chế độ trò chuyện do có cấu trúc qua lại tự nhiên. Bạn sẽ chịu trách nhiệm gọi các hàm và gửi kết quả trở lại mô hình để có thể tạo phản hồi bằng văn bản.