SambaCloudのFunction calling (関数呼び出し) 機能を使うと、ユーザーの入力に応じて、モデルが実行すべき関数を選択・提案できるようになり、エージェントワークフローの構築に役立ちます。あらかじめ使用する関数またはツールの一覧を定義しておくことで、モデルにコンテキストを与え、必要な引数を適切に補完させることが可能になります。
Function callingの仕組み
Function callingを使うことで、リアルタイムデータや構造化出力に対応した柔軟なワークフローを構築でき、よりダイナミックかつ応答性の高いモデルの対話が実現します。
- ツールを含むクエリの送信:まず、JSON Schemaで定義された利用可能なツール群とともに、ユーザからのクエリを送信します。各関数のパラメータもスキーマで指定します。
- モデルによる処理と提案:モデルはクエリを解釈し、意図を判断した上で、通常の会話を返すか、function callingを提案するかを選択します。関数が呼び出される場合、定義されたスキーマに基づいて引数を補完します。
- モデルから応答を受信:モデルからの応答には、function callingの提案が含まれる場合があります。提供された引数を使って関数を実行し、その結果を再度モデルに返すことで対話を継続します。
対応モデル
- Meta-Llama-3.1-8B-Instruct
- Meta-Llama-3.1-405B-Instruct
- Meta-Llama-3.3-70B-Instruct
Meta社は、会話とツール呼び出しを組み合わせたアプリケーションには、Llama 70B-InstructまたはLlama 405B-Instructの使用を推奨しています。Llama 8B-Instructはツール呼び出しの定義を伴う会話を安定して保持できないため、ゼロショットのツール呼び出しなど限定的な用途に向いています。
使用例
以下の例では、function callingを使用するための各ステップを順に説明します。最後に、これらを通したend-to-endの実装例も紹介します。
ステップ1:関数スキーマの定義
まず、使用する関数のJSON Schemaを定義します。以下の要素を指定する必要があります。
- 関数名
- 関数の処理内容に関する説明
- 各パラメータの名前、データ型、および説明
{
"type": "function",
"function": {
"name": "solve_quadratic",
"description": "Solves a quadratic equation given coefficients a, b, and c.",
"parameters": {
"type": "object",
"properties": {
"a": {"type": "integer", "description": "Coefficient of the squared term"},
"b": {"type": "integer", "description": "Coefficient of the linear term"},
"c": {"type": "integer", "description": "Constant term"},
"root_type": {"type": "string", "description": "Type of roots to return: 'real' or 'all'"}
},
"required": ["a", "b", "c"]
}
}
}
ステップ2:リクエストにfunction callingを設定
SambaCloudにリクエストを送信する際、関数スキーマをtools
パラメータに含め、tool_choice
に以下のいずれかを指定します。
auto
:モデルが通常の応答とfunction callingを自動で選択。(デフォルト)
required
:モデルにfunction callingを強制。
- 特定の関数の呼び出しを強制するには、
tool_choice = {"type": "function", "function": {"name": "solve_quadratic"}}
を設定します。これにより、モデルは指定された関数のみを使用することが保証されます。
import openai
import cmath
import json
# Initialize the client with SN Cloud base URL and your API key
client = openai.OpenAI(
base_url="https://api.sambanova.ai/v1",
api_key="YOUR SAMBANOVA API KEY"
)
def solve_quadratic(a, b, c, root_type="real"):
"""
Solve a quadratic equation of the form ax^2 + bx + c = 0.
"""
discriminant = b**2 - 4*a*c
if root_type == "real":
if discriminant < 0:
return [] # No real roots
else:
root1 = (-b + discriminant**0.5) / (2 * a)
root2 = (-b - discriminant**0.5) / (2 * a)
return [root1, root2]
else:
root1 = (-b + cmath.sqrt(discriminant)) / (2 * a)
root2 = (-b - cmath.sqrt(discriminant)) / (2 * a)
return [
{"real": root1.real, "imag": root1.imag},
{"real": root2.real, "imag": root2.imag}
]
# Define user input and function schema
user_prompt = "Find all the roots of a quadratic equation given coefficients a = 3, b = -11, and c = -4."
messages = [
{
"role": "user",
"content": user_prompt,
}
]
tools = [
{
"type": "function",
"function": {
"name": "solve_quadratic",
"description": "Solves a quadratic equation given coefficients a, b, and c.",
"parameters": {
"type": "object",
"properties": {
"a": {"type": "integer", "description": "Coefficient of the squared term"},
"b": {"type": "integer", "description": "Coefficient of the linear term"},
"c": {"type": "integer", "description": "Constant term"},
"root_type": {"type": "string", "description": "Type of roots: 'real' or 'all'"}
},
"required": ["a", "b", "c"]
}
}
}
]
response = client.chat.completions.create(
model="Meta-Llama-3.3-70B-Instruct",
messages=messages,
tools=tools,
tool_choice="required"
)
print(response)
ステップ3:ツール呼び出しの処理
モデルがfunction callingを選択した場合、応答にtool_calls
フィールドが含まれます。この中からfunction callingの詳細を抽出し、指定されたパラメータを使って対応する関数を実行します。
response_message = response.choices[0].message
tool_calls = response_message.tool_calls
# If tool call is present
if tool_calls:
tool_call = tool_calls[0]
function_name = tool_call.function.name
arguments = tool_call.function.arguments
arguments = json.loads(arguments)
# Call the appropriate function with parsed arguments
if function_name == "solve_quadratic":
result = solve_quadratic(
a=arguments["a"],
b=arguments["b"],
c=arguments["c"],
root_type=arguments.get("root_type", "real")
)
print(result)
ステップ4:関数の実行結果をモデルに返す
計算結果が得られたら、会話を続けるか出力を確認するためにモデルに結果を返します。
# Convert result to JSON string format to return to model
function_response = json.dumps({"result": result})
# Provide the function response back to the model as a message
messages.append(
{
"tool_call_id": tool_call.id,
"role": "tool",
"name": function_name,
"content": function_response
}
)
# Second API call to incorporate the function result into conversation
second_response = client.chat.completions.create(
model="Meta-Llama-3.3-70B-Instruct",
messages=messages,
)
# print the final response from the model
print(second_response.choices[0].message.content)
ステップ5:最終出力の例
以下に出力例を示します。
The roots of the quadratic equation with coefficients a = 3, b = -11, and c = -4 are 4 and -1/3.
OpenAI互換性を使用したend-to-endの実装例
End-to-end example using OpenAI compatibility
import openai
import cmath
import json
# Define the OpenAI client
client = openai.OpenAI(
base_url="https://api.sambanova.ai/v1",
api_key="YOUR SAMBANOVA API KEY"
)
MODEL = 'Meta-Llama-3.3-70B-Instruct'
# Function to solve the quadratic equation
def solve_quadratic(a, b, c, root_type="real"):
"""
Solve a quadratic equation of the form ax^2 + bx + c = 0.
"""
discriminant = b**2 - 4*a*c
if root_type == "real":
if discriminant < 0:
return [] # No real roots
else:
root1 = (-b + discriminant**0.5) / (2 * a)
root2 = (-b - discriminant**0.5) / (2 * a)
return [root1, root2]
else:
root1 = (-b + cmath.sqrt(discriminant)) / (2 * a)
root2 = (-b - cmath.sqrt(discriminant)) / (2 * a)
return [
{"real": root1.real, "imag": root1.imag},
{"real": root2.real, "imag": root2.imag}
]
# Function to run conversation and provide tool result back to the model
def run_conversation(user_prompt):
# Initial conversation with user input
messages = [
{
"role": "system",
"content": "You are an assistant that can solve quadratic equations given coefficients a, b, and c."
},
{
"role": "user",
"content": user_prompt,
}
]
# Define the tool
tools = [
{
"type": "function",
"function": {
"name": "solve_quadratic",
"description": "Solve a quadratic equation given coefficients a, b, and c.",
"parameters": {
"type": "object",
"properties": {
"a": {"type": "integer", "description": "Coefficient of the squared term."},
"b": {"type": "integer", "description": "Coefficient of the linear term."},
"c": {"type": "integer", "description": "Constant term."},
"root_type": {"type": "string", "description": "Type of roots: 'real' or 'all'."}
},
"required": ["a", "b", "c"],
}
}
}
]
# First API call to get model's response
response = client.chat.completions.create(
model=MODEL,
messages=messages,
tools=tools,
tool_choice="auto",
max_tokens=500
)
response_message = response.choices[0].message
tool_calls = response_message.tool_calls
# If tool call is present
if tool_calls:
tool_call = tool_calls[0]
function_name = tool_call.function.name
arguments = tool_call.function.arguments
arguments = json.loads(arguments)
# Call the appropriate function with parsed arguments
if function_name == "solve_quadratic":
result = solve_quadratic(
a=arguments["a"],
b=arguments["b"],
c=arguments["c"],
root_type=arguments.get("root_type", "real")
)
# Convert result to JSON string format to return to model
function_response = json.dumps({"result": result})
# Provide the function response back to the model as a message
messages.append(
{
"tool_call_id": tool_call.id,
"role": "tool",
"name": function_name,
"content": function_response
}
)
# Second API call to incorporate the function result into conversation
second_response = client.chat.completions.create(
model=MODEL,
messages=messages,
max_tokens=500
)
# Return the final response from the model
return second_response.choices[0].message.content
# Example user prompt
user_prompt = "Find all the roots of a quadratic equation given coefficients a = 3, b = -11, and c = -4."
print(run_conversation(user_prompt))
JSONモード
リクエスト時にresponse_format
パラメータを json_object
に設定することで、モデルが有効なJSONを出力するように制御できます。
モデルが有効なJSONを生成できない場合、次のようなエラーが表示されます:Model did not output valid JSON。
import openai
# Define the OpenAI client
client = openai.OpenAI(
base_url="https://api.sambanova.ai/v1",
api_key="YOUR SAMBANOVA API KEY"
)
MODEL = 'Meta-Llama-3.3-70B-Instruct'
def run_conversation(user_prompt):
# Initial conversation with user input
messages = [
{
"role": "system",
"content": "Always provide the response in this JSON format: {\"country\": \"name\", \"capital\": \"xx\"}"
},
{
"role": "user",
"content": user_prompt,
}
]
# First API call to get model's response
response = client.chat.completions.create(
model=MODEL,
messages=messages,
max_tokens=500,
response_format = { "type": "json_object"},
# stream = True
)
response_message = response.choices[0].message
print(response_message)
run_conversation('what is the capital of Austria')
ChatCompletionMessage(content='{"country": "Austria", "capital": "Vienna"}', role='assistant', function_call=None, tool_calls=None)