API Gemini: Gọi hàm bằng Python

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

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.

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)

Kiến thức cơ bản về hàm

Bạn có thể truyền danh sách hàm đến đối số tools khi tạo genai.GenerativeModel.

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 tính năng gọi hàm thông qua giao diện trò chuyện. Lý do chính là FunctionCalls phù hợp với cấu trúc nhiều lượt của cuộc trò chuyện.

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

Nếu nhìn vào ChatSession.history, bạn có thể thấy trình tự các sự kiện:

  1. Bạn đã gửi câu hỏi.
  2. Mô hình đó đã trả lời bằng một glm.FunctionCall.
  3. genai.ChatSession đã thực thi hàm cục bộ và gửi lại mô hình glm.FunctionResponse.
  4. Mô hình này sử dụng kết quả đầu ra của hàm trong câu trả lời.
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.

[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 có thể mô tả bất kỳ loại sau:

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.