บทแนะนำ: การเรียกฟังก์ชันด้วย Gemini API


ดูใน ai.google.dev เรียกใช้ใน Google Colab ดูซอร์สบน GitHub

ใช้การเรียกใช้ฟังก์ชันเพื่อกำหนดฟังก์ชันที่กำหนดเองและส่งไปยัง Gemini โมเดลจะไม่เรียกใช้ฟังก์ชันเหล่านี้โดยตรง แต่จะสร้างเอาต์พุต Structured Data ที่มีชื่อฟังก์ชันและอาร์กิวเมนต์ที่แนะนําแทน เอาต์พุตนี้ทำให้สามารถเรียกใช้ API ภายนอกได้ และหลังจากนั้นสามารถรวมเอาต์พุตของ API ที่ได้ลงในโมเดล ทำให้ได้รับคำตอบการค้นหาที่ครอบคลุมมากยิ่งขึ้น การเรียกใช้ฟังก์ชันช่วยให้ LLM สามารถโต้ตอบกับข้อมูลแบบเรียลไทม์และบริการต่างๆ เช่น ฐานข้อมูล ระบบการจัดการลูกค้าสัมพันธ์ และที่เก็บเอกสาร เพิ่มความสามารถในการให้คำตอบที่เกี่ยวข้องและอิงตามบริบท คุณระบุโมเดล Gemini พร้อมคำอธิบายฟังก์ชันได้ โมเดลอาจขอให้คุณเรียกฟังก์ชันและส่งผลลัพธ์กลับมาเพื่อช่วยให้โมเดลจัดการการค้นหาของคุณ

โปรดดูข้อมูลเพิ่มเติมในข้อมูลเบื้องต้นเกี่ยวกับการเรียกใช้ฟังก์ชัน หากยังไม่ได้ดำเนินการ

ตั้งค่า

ติดตั้ง Python SDK

Python SDK สำหรับ Gemini API อยู่ในแพ็กเกจ google-generativeai ติดตั้งทรัพยากร Dependency โดยใช้ PIP:

pip install -U -q google-generativeai

นำเข้าแพ็กเกจ

นำเข้าแพ็กเกจที่จำเป็น

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

ตั้งค่าคีย์ API

คุณต้องขอรับคีย์ API ก่อน จึงจะใช้ Gemini API ได้ หากยังไม่มี ให้สร้างคีย์ด้วยคลิกเดียวใน Google AI Studio

รับคีย์ API

ใน Colab ให้เพิ่มคีย์ลงในตัวจัดการข้อมูลลับใต้ "🔑" ในแผงด้านซ้าย ตั้งชื่อว่า API_KEY

เมื่อมีคีย์ API แล้ว ให้ส่งคีย์ดังกล่าวไปยัง SDK โดยสามารถทำได้สองวิธี:

  • ใส่คีย์ในตัวแปรสภาพแวดล้อม GOOGLE_API_KEY (SDK จะดึงคีย์จากที่นั่นโดยอัตโนมัติ)
  • ส่งกุญแจไปยัง 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)

ข้อมูลพื้นฐานเกี่ยวกับการเรียกใช้ฟังก์ชัน

หากต้องการใช้การเรียกฟังก์ชัน ให้ส่งรายการฟังก์ชันไปยังพารามิเตอร์ tools เมื่อสร้าง 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>,
)

ขอแนะนำให้ใช้การเรียกใช้ฟังก์ชันผ่านอินเทอร์เฟซการแชท เนื่องจากโดยปกติแล้วการเรียกใช้ฟังก์ชันจะแทรกอยู่ในการแชทแบบหลายมุมมอง ในขณะที่บันทึกการโต้ตอบกลับไปกลับมาระหว่างผู้ใช้และโมเดล ChatSession ของ Python SDK เป็นอินเทอร์เฟซที่ยอดเยี่ยมสำหรับแชท เพราะจะจัดการประวัติการสนทนาให้คุณ และการใช้พารามิเตอร์ enable_automatic_function_calling จะช่วยให้การเรียกใช้ฟังก์ชันง่ายขึ้นไปอีก

chat = model.start_chat(enable_automatic_function_calling=True)

เมื่อเปิดใช้การเรียกใช้ฟังก์ชันอัตโนมัติ chat.send_message จะเรียกใช้ฟังก์ชันของคุณโดยอัตโนมัติหากโมเดลขอให้ดำเนินการ

ดูเหมือนว่าจะส่งข้อความตอบกลับที่มีคำตอบที่ถูกต้อง:

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

ตรวจสอบประวัติการแชทเพื่อดูความต่อเนื่องของการสนทนาและการผสานรวมการเรียกใช้ฟังก์ชันภายในการสนทนา

พร็อพเพอร์ตี้ ChatSession.history จะเก็บบันทึกการสนทนาระหว่างผู้ใช้กับโมเดล Gemini ตามลำดับเวลา การสนทนาแต่ละครั้งจะแทนด้วยออบเจ็กต์ glm.Content ซึ่งมีข้อมูลต่อไปนี้

  • บทบาท: ระบุว่าเนื้อหามีที่มาจาก "ผู้ใช้" หรือ "โมเดล"
  • ส่วน: รายการออบเจ็กต์ glm.Part ที่แสดงคอมโพเนนต์แต่ละรายการของข้อความ เมื่อใช้โมเดลข้อความเท่านั้น ส่วนเหล่านี้อาจมีลักษณะดังนี้
    • ข้อความ: ข้อความธรรมดา
    • การเรียกใช้ฟังก์ชัน (glm.FunctionCall): คำขอจากโมเดลเพื่อเรียกใช้ฟังก์ชันที่เฉพาะเจาะจงด้วยอาร์กิวเมนต์ที่ระบุ
    • การตอบสนองของฟังก์ชัน (glm.FunctionResponse): ผลลัพธ์ที่ผู้ใช้แสดงหลังจากเรียกใช้ฟังก์ชันที่ขอ

ในตัวอย่างก่อนหน้านี้ที่มีการคำนวณถุงมือ ประวัติจะแสดงลำดับต่อไปนี้

  1. ผู้ใช้: ถามคำถามเกี่ยวกับจำนวนถุงมือทั้งหมด
  2. โมเดล: ระบุว่าฟังก์ชันการคูณมีประโยชน์ และส่งคำขอ FunctionCall ไปยังผู้ใช้
  3. ผู้ใช้: ChatSession จะเรียกใช้ฟังก์ชันโดยอัตโนมัติ (เนื่องจากมีการตั้งค่า enable_automatic_function_calling) และส่งกลับ FunctionResponse พร้อมผลลัพธ์ที่คำนวณแล้ว
  4. โมเดล: ใช้เอาต์พุตของฟังก์ชันเพื่อร่างคำตอบสุดท้ายและนำเสนอเป็นคำตอบข้อความ
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.'}
--------------------------------------------------------------------------------

โดยทั่วไปแผนภาพสถานะจะเป็นดังนี้

โมเดลสามารถตอบกลับด้วยข้อความหรือ FunctionCall ได้เสมอ หากโมเดลส่ง FunctionCall ผู้ใช้ต้องตอบกลับด้วย FunctionResponse

โมเดลจะตอบสนองด้วยการเรียกฟังก์ชันหลายรายการก่อนส่งคืนข้อความตอบกลับ และการเรียกใช้ฟังก์ชันจะมาก่อนข้อความตอบกลับ

แม้ว่าทั้งหมดนี้จะได้รับการจัดการโดยอัตโนมัติ แต่หากต้องการการควบคุมที่มากขึ้น คุณก็สามารถทำดังนี้

  • ปล่อยค่าเริ่มต้น enable_automatic_function_calling=False ไว้และประมวลผลคำตอบ glm.FunctionCall ด้วยตนเอง
  • หรือใช้ GenerativeModel.generate_content ซึ่งคุณต้องจัดการประวัติการแชทด้วย

การเรียกฟังก์ชันคู่ขนาน

นอกจากการเรียกฟังก์ชันพื้นฐานที่อธิบายไว้ข้างต้นแล้ว คุณยังสามารถเรียกหลายฟังก์ชันในคราวเดียวได้อีกด้วย ส่วนนี้จะแสดงตัวอย่างวิธีเรียกใช้ฟังก์ชันพร้อมกัน

กำหนดเครื่องมือ

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

ทีนี้เรียกโมเดลด้วยคำสั่งที่อาจใช้เครื่องมือที่ระบุทั้งหมด

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

ผลลัพธ์ที่พิมพ์แต่ละรายการจะแสดงการเรียกใช้ฟังก์ชันเดียวที่โมเดลได้ขอ หากต้องการส่งผลลัพธ์กลับมา ให้ใส่คำตอบในลำดับเดียวกันกับที่ขอ

# 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! 🕺💃

(ไม่บังคับ) สิทธิ์เข้าถึงระดับต่ำ

การดึงสคีมาอัตโนมัติจากฟังก์ชัน Python ใช้งานไม่ได้ในทุกกรณี เช่น โปรโตคอลนี้ไม่รองรับกรณีที่คุณอธิบายช่องของออบเจ็กต์พจนานุกรมที่ซ้อนกัน แต่ API รองรับการดำเนินการนี้ API อธิบายประเภทต่อไปนี้ได้

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

ไลบรารีของไคลเอ็นต์ google.ai.generativelanguage จะให้สิทธิ์เข้าถึงประเภทระดับต่ำเพื่อให้คุณควบคุมได้เต็มที่

import google.ai.generativelanguage as glm

ดูครั้งแรกภายในแอตทริบิวต์ _tools ของโมเดล คุณจะเห็นว่าโมเดลอธิบายฟังก์ชันที่คุณส่งไปยังโมเดลได้อย่างไร

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"
   }
 }]

การดำเนินการนี้จะแสดงรายการออบเจ็กต์ glm.Tool รายการที่จะส่งไปที่ API หากรูปแบบที่พิมพ์ไม่คุ้นตา นั่นอาจเป็นเพราะชั้นเรียนเหล่านี้คือคลาส Protobuf ของ Google glm.Tool แต่ละรายการ (ในกรณีนี้ 1 รายการ) ประกอบด้วยรายการ glm.FunctionDeclarations ซึ่งอธิบายฟังก์ชันและอาร์กิวเมนต์

ต่อไปนี้เป็นการประกาศสำหรับฟังก์ชันการคูณเดียวกันที่เขียนโดยใช้คลาส glm

โปรดทราบว่าคลาสเหล่านี้เป็นเพียงการอธิบายฟังก์ชันของ API เท่านั้น โดยไม่มีการติดตั้งใช้งาน ดังนั้น การใช้ฟังก์ชันนี้จึงไม่สามารถใช้กับการเรียกใช้ฟังก์ชันอัตโนมัติ แต่ฟังก์ชันไม่จำเป็นต้องติดตั้งเสมอไป

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']
        )
      )
    ])

คุณสามารถอธิบายได้ว่ารายการนี้เป็นออบเจ็กต์ที่เข้ากันได้กับ 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"
  }
}

แต่ไม่ว่าจะเลือกแบบไหน คุณจะส่งผ่านตัวแทนกลุ่ม glm.Tool หรือรายชื่อเครื่องมือเพื่อ

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

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

เช่นเดียวกับก่อนที่โมเดลจะแสดงผล glm.FunctionCall ที่จะเรียกใช้ฟังก์ชัน multiply ของเครื่องคำนวณ

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
]

ดำเนินการฟังก์ชันด้วยตัวเอง

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

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

ส่งผลลัพธ์ไปยังโมเดลเพื่อสนทนาต่อ

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

สรุป

SDK รองรับการเรียกฟังก์ชันพื้นฐาน อย่าลืมว่าการใช้โหมดแชทจะจัดการได้ง่ายกว่า เนื่องจากมีโครงสร้างการสื่อสารกลับไปกลับมาตามปกติ คุณต้องรับผิดชอบในการเรียกใช้ฟังก์ชันและส่งผลลัพธ์กลับไปยังโมเดลเพื่อให้สามารถสร้างข้อความตอบกลับได้