ai.google.dev에서 보기 | Google Colab에서 실행 | GitHub에서 소스 보기 |
함수 호출을 사용하여 맞춤 함수를 정의하고 Gemini에 전달합니다. 모델은 이러한 함수를 직접 호출하지 않고 대신 함수 이름과 추천 인수를 지정하는 구조화된 데이터 출력을 생성합니다. 이 출력을 통해 외부 API를 호출할 수 있으며, 그 결과 생성된 API 출력을 모델에 다시 통합할 수 있어 더 포괄적인 쿼리 응답이 가능합니다. 함수 호출은 LLM이 실시간 정보 및 데이터베이스, 고객 관계 관리 시스템, 문서 저장소와 같은 다양한 서비스와 상호작용할 수 있도록 지원하여 관련성 있는 상황별 답변을 제공하는 능력을 강화합니다. Gemini 모델에 함수 설명을 제공할 수 있습니다. 모델이 쿼리를 처리할 수 있도록 함수를 호출하고 결과를 돌려보내도록 요청할 수 있습니다.
아직 확인하지 않았다면 함수 호출 소개를 확인하여 자세히 알아보세요.
설정
Python SDK 설치
Gemini API용 Python SDK는 google-generativeai
패키지에 포함되어 있습니다. 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 키 설정
Gemini API를 사용하려면 먼저 API 키를 가져와야 합니다. 아직 키가 없으면 Google AI Studio에서 클릭 한 번으로 키를 만듭니다.
Colab에서 왼쪽 패널의 'boot' 아래에 있는 보안 비밀 관리자에 키를 추가합니다. 이름을 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)
함수 호출의 기본사항
함수 호출을 사용하려면 GenerativeModel
를 만들 때 함수 목록을 tools
매개변수에 전달합니다. 모델은 함수 이름, docstring, 매개변수, 매개변수 유형 주석을 사용하여 프롬프트에 가장 잘 대답하는 함수가 필요한지 결정합니다.
def multiply(a:float, b:float):
"""returns a * b."""
return a*b
model = genai.GenerativeModel(model_name='gemini-1.5-flash',
tools=[multiply])
model
genai.GenerativeModel( model_name='models/gemini-1.5-flash', generation_config={}, safety_settings={}, tools=<google.generativeai.types.content_types.FunctionLibrary object at 0x10e73fe90>, )
채팅 인터페이스를 통해 함수 호출을 사용하는 것이 좋습니다. 이는 함수 호출이 사용자와 모델 간의 양방향 상호작용을 포착하므로 멀티턴 채팅에 자연스럽게 부합하기 때문입니다. Python SDK의 ChatSession
는 대화 기록을 처리하므로 채팅용으로 좋은 인터페이스이며 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 모델 간의 대화의 시간순 기록을 저장합니다. 대화의 각 차례는 다음 정보가 포함된 genai.protos.Content
객체로 표현됩니다.
- 역할: 콘텐츠의 출처가 '사용자'인지 '모델'인지 식별합니다.
- 부분: 메시지의 개별 구성요소를 나타내는
genai.protos.Part
객체의 목록입니다. 텍스트 전용 모델에서 이러한 부분은 다음과 같습니다.- 텍스트: 일반 문자 메시지입니다.
- 함수 호출 (
genai.protos.FunctionCall
): 제공된 인수로 특정 함수를 실행하기 위한 모델의 요청입니다. - 함수 응답 (
genai.protos.FunctionResponse
): 요청된 함수를 실행한 후 사용자가 반환한 결과입니다.
벙어리 장갑 계산을 사용한 이전 예에서 내역은 다음과 같은 순서를 보여줍니다.
- 사용자: 장갑의 총 개수를 묻습니다.
- 모델: 곱하기 함수가 유용한지 확인하고 사용자에게 FunctionCall 요청을 보냅니다.
- 사용자:
ChatSession
는enable_automatic_function_calling
가 설정되어 있어 자동으로 함수를 실행하고 계산된 결과와 함께FunctionResponse
를 반환합니다. - 모델: 함수의 출력을 사용하여 최종 답변을 작성하고 텍스트 응답으로 표시합니다.
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.'} --------------------------------------------------------------------------------
일반적으로 상태 다이어그램은 다음과 같습니다.
모델은 텍스트 응답을 반환하기 전에 여러 함수 호출로 응답할 수 있으며 함수 호출은 텍스트 응답 앞에 옵니다.
이 모든 작업은 자동으로 처리되지만 더 세부적으로 관리할 수 있는 방법은 다음과 같습니다.
- 기본
enable_automatic_function_calling=False
를 그대로 두고genai.protos.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-flash", 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 = [
genai.protos.Part(function_response=genai.protos.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
클라이언트 라이브러리는 하위 수준 유형에 대한 액세스를 제공하여 완전한 제어 기능을 제공합니다.
먼저 모델의 _tools
속성을 살펴보면 모델에 전달한 함수를 어떻게 설명하는지 확인할 수 있습니다.
def multiply(a:float, b:float):
"""returns a * b."""
return a*b
model = genai.GenerativeModel(model_name='gemini-1.5-flash',
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" } }]
이렇게 하면 API로 전송될 genai.protos.Tool
객체 목록이 반환됩니다. 출력된 형식이 익숙하지 않은 경우 Google protobuf 클래스이기 때문입니다. 각 genai.protos.Tool
(여기서는 1)에는 함수와 인수를 설명하는 genai.protos.FunctionDeclarations
목록이 포함됩니다.
다음은 genai.protos
클래스를 사용하여 작성된 동일한 곱셈 함수에 관한 선언입니다.
이러한 클래스는 API의 함수를 설명할 뿐이며 함수의 구현을 포함하지 않습니다. 따라서 자동 함수 호출에서는 이를 사용할 수 없지만 함수에 항상 구현이 필요하지는 않습니다.
calculator = genai.protos.Tool(
function_declarations=[
genai.protos.FunctionDeclaration(
name='multiply',
description="Returns the product of two numbers.",
parameters=genai.protos.Schema(
type=genai.protos.Type.OBJECT,
properties={
'a':genai.protos.Schema(type=genai.protos.Type.NUMBER),
'b':genai.protos.Schema(type=genai.protos.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']} }]}
genai.protos.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" } }
어느 쪽이든 genai.protos.Tool
표현 또는 도구 목록을
model = genai.GenerativeModel('gemini-1.5-flash', tools=calculator)
chat = model.start_chat()
response = chat.send_message(
f"What's 234551 X 325552 ?",
)
모델이 계산기의 multiply
함수를 호출하는 genai.protos.FunctionCall
를 반환하기 전과 같습니다.
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(
genai.protos.Content(
parts=[genai.protos.Part(
function_response = genai.protos.FunctionResponse(
name='multiply',
response={'result': result}))]))
요약
SDK에서 기본 함수 호출이 지원됩니다. 자연스러운 양방향 구조 때문에 채팅 모드를 사용하면 더 쉽게 관리할 수 있습니다. 텍스트 응답을 생성할 수 있도록 실제로 함수를 호출하고 결과를 모델로 다시 전송하는 일을 담당합니다.