Microsoft Foundry モデルで Azure OpenAI で関数呼び出しを使用する方法

要求に 1 つ以上の関数が含まれている場合、モデルはプロンプトのコンテキストに基づいて関数を呼び出す必要があるかどうかを判断します。 モデルは、関数を呼び出す必要があると判断すると、関数の引数を含む JSON オブジェクトで応答します。

モデルは、指定した関数に基づいて、API 呼び出しと構造化データ出力を作成します。 モデルではこれらの呼び出しを生成できますが、それらを実行して制御を維持する必要があることに注意することが重要です。

大まかに言うと、関数の操作を次の 3 つの手順に分けることができます。

  1. 関数とユーザーの入力を基にチャット補完 API を呼び出す
  2. モデルの応答を使用して API または関数を呼び出す
  3. 関数からの応答を含め、チャット完了 API をもう一度呼び出して最終的な応答を取得する

前提 条件

  • デプロイされた Azure OpenAI モデル
  • Microsoft Entra ID認証の場合:
    • 構成されたカスタム サブドメイン。 詳細については、「 カスタム サブドメイン名」を参照してください。
    • パッケージ: pip install openai azure-identity

単一のツール/関数呼び出しの例

最初に、1 つのツール/関数が定義された 3 つのハードコードされた場所で時刻を確認できるおもちゃの関数呼び出しを示します。 コードの実行を容易にするために、print ステートメントを追加しました。

import os
import json
from openai import OpenAI
from datetime import datetime
from zoneinfo import ZoneInfo
from azure.identity import DefaultAzureCredential, get_bearer_token_provider

token_provider = get_bearer_token_provider(
    DefaultAzureCredential(), "https://ai.azure.com/.default"
)

client = OpenAI(  
  base_url = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",  
  api_key=token_provider,
)

# Define the deployment you want to use for your chat completions API calls

deployment_name = "<YOUR_DEPLOYMENT_NAME_HERE>"

# Simplified timezone data
TIMEZONE_DATA = {
    "tokyo": "Asia/Tokyo",
    "san francisco": "America/Los_Angeles",
    "paris": "Europe/Paris"
}

def get_current_time(location):
    """Get the current time for a given location"""
    print(f"get_current_time called with location: {location}")  
    location_lower = location.lower()
    
    for key, timezone in TIMEZONE_DATA.items():
        if key in location_lower:
            print(f"Timezone found for {key}")  
            current_time = datetime.now(ZoneInfo(timezone)).strftime("%I:%M %p")
            return json.dumps({
                "location": location,
                "current_time": current_time
            })
    
    print(f"No timezone data found for {location_lower}")  
    return json.dumps({"location": location, "current_time": "unknown"})

def run_conversation():
    # Initial user message
    messages = [{"role": "user", "content": "What's the current time in San Francisco"}] # Single function call
    #messages = [{"role": "user", "content": "What's the current time in San Francisco, Tokyo, and Paris?"}] # Parallel function call with a single tool/function defined

    # Define the function for the model
    tools = [
        {
            "type": "function",
            "function": {
                "name": "get_current_time",
                "description": "Get the current time in a given location",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "The city name, e.g. San Francisco",
                        },
                    },
                    "required": ["location"],
                },
            }
        }
    ]

    # First API call: Ask the model to use the function
    response = client.chat.completions.create(
        model=deployment_name,
        messages=messages,
        tools=tools,
        tool_choice="auto",
    )

    # Process the model's response
    response_message = response.choices[0].message
    messages.append(response_message)

    print("Model's response:")  
    print(response_message)  

    # Handle function calls
    if response_message.tool_calls:
        for tool_call in response_message.tool_calls:
            if tool_call.function.name == "get_current_time":
                function_args = json.loads(tool_call.function.arguments)
                print(f"Function arguments: {function_args}")  
                time_response = get_current_time(
                    location=function_args.get("location")
                )
                messages.append({
                    "tool_call_id": tool_call.id,
                    "role": "tool",
                    "name": "get_current_time",
                    "content": time_response,
                })
    else:
        print("No tool calls were made by the model.")  

    # Second API call: Get the final response from the model
    final_response = client.chat.completions.create(
        model=deployment_name,
        messages=messages,
    )

    return final_response.choices[0].message.content

# Run the conversation and print the result
print(run_conversation())

出力:

Model's response:
ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_pOsKdUlqvdyttYB67MOj434b', function=Function(arguments='{"location":"San Francisco"}', name='get_current_time'), type='function')])
Function arguments: {'location': 'San Francisco'}
get_current_time called with location: San Francisco
Timezone found for san francisco
The current time in San Francisco is 09:24 AM.

並列関数呼び出しをサポートするモデル デプロイを使用している場合は、メッセージ配列を変更して、1 つではなく複数の場所で時刻を要求することで、これを並列関数呼び出しの例に変換できます。

これを行うには、次の 2 行のコメントを入れ替えます。

    messages = [{"role": "user", "content": "What's the current time in San Francisco"}] # Single function call
    #messages = [{"role": "user", "content": "What's the current time in San Francisco, Tokyo, and Paris?"}] # Parallel function call with a single tool/function defined

次のように表示し、コードをもう一度実行します。

    #messages = [{"role": "user", "content": "What's the current time in San Francisco"}] # Single function call
    messages = [{"role": "user", "content": "What's the current time in San Francisco, Tokyo, and Paris?"}] # Parallel function call with a single tool/function defined

これにより、次の出力が生成されます。

出力:

Model's response:
ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_IjcAVz9JOv5BXwUx1jd076C1', function=Function(arguments='{"location": "San Francisco"}', name='get_current_time'), type='function'), ChatCompletionMessageToolCall(id='call_XIPQYTCtKIaNCCPTdvwjkaSN', function=Function(arguments='{"location": "Tokyo"}', name='get_current_time'), type='function'), ChatCompletionMessageToolCall(id='call_OHIB5aJzO8HGqanmsdzfytvp', function=Function(arguments='{"location": "Paris"}', name='get_current_time'), type='function')])
Function arguments: {'location': 'San Francisco'}
get_current_time called with location: San Francisco
Timezone found for san francisco
Function arguments: {'location': 'Tokyo'}
get_current_time called with location: Tokyo
Timezone found for tokyo
Function arguments: {'location': 'Paris'}
get_current_time called with location: Paris
Timezone found for paris
As of now, the current times are:

- **San Francisco:** 11:15 AM
- **Tokyo:** 03:15 AM (next day)
- **Paris:** 08:15 PM

並列関数呼び出しを使用すると、複数の関数呼び出しを同時に実行できるため、結果の並列実行と取得が可能になります。 これにより、API に対する呼び出しの数が減り、全体的なパフォーマンスが向上します。

たとえば、単純なタイム アプリでは、同時に複数回取得しました。 その結果、 tool_calls 配列に 3 つの関数呼び出しが含まれるチャット完了メッセージが生成され、それぞれが一意の idを持つ結果になります。 これらの関数呼び出しに応答する場合は、3 つの新しいメッセージを会話に追加します。それぞれに 1 つの関数呼び出しの結果が含まれており、tool_call_idからidを参照するtool_callsが含まれます。

モデルで特定の関数を強制的に呼び出すには、 tool_choice を名前付きツール オブジェクト (例: tool_choice={"type": "function", "function": {"name": "get_current_time"}}) に設定します。 ユーザー向けのメッセージを強制的に送信するには、 tool_choice="none"設定します。

メモ

既定の動作 (tool_choice: "auto") は、モデルが関数を呼び出す必要があるかどうか、その場合に呼び出す関数を独自に決定することです。

複数の関数を使用した並列関数呼び出し

次に、2 つの異なるツール/関数を定義して、今度は別のおもちゃ関数呼び出し例を示します。

import os
import json
from openai import OpenAI
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
from azure.identity import DefaultAzureCredential, get_bearer_token_provider

token_provider = get_bearer_token_provider(
    DefaultAzureCredential(), "https://ai.azure.com/.default"
)

client = OpenAI(  
  base_url = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",  
  api_key=token_provider,
)

# Provide the model deployment name you want to use for this example

deployment_name = "YOUR_DEPLOYMENT_NAME_HERE" 

# Simplified weather data
WEATHER_DATA = {
    "tokyo": {"temperature": "10", "unit": "celsius"},
    "san francisco": {"temperature": "72", "unit": "fahrenheit"},
    "paris": {"temperature": "22", "unit": "celsius"}
}

# Simplified timezone data
TIMEZONE_DATA = {
    "tokyo": "Asia/Tokyo",
    "san francisco": "America/Los_Angeles",
    "paris": "Europe/Paris"
}

def get_current_weather(location, unit=None):
    """Get the current weather for a given location"""
    location_lower = location.lower()
    print(f"get_current_weather called with location: {location}, unit: {unit}")  
    
    for key in WEATHER_DATA:
        if key in location_lower:
            print(f"Weather data found for {key}")  
            weather = WEATHER_DATA[key]
            return json.dumps({
                "location": location,
                "temperature": weather["temperature"],
                "unit": unit if unit else weather["unit"]
            })
    
    print(f"No weather data found for {location_lower}")  
    return json.dumps({"location": location, "temperature": "unknown"})

def get_current_time(location):
    """Get the current time for a given location"""
    print(f"get_current_time called with location: {location}")  
    location_lower = location.lower()
    
    for key, timezone in TIMEZONE_DATA.items():
        if key in location_lower:
            print(f"Timezone found for {key}")  
            current_time = datetime.now(ZoneInfo(timezone)).strftime("%I:%M %p")
            return json.dumps({
                "location": location,
                "current_time": current_time
            })
    
    print(f"No timezone data found for {location_lower}")  
    return json.dumps({"location": location, "current_time": "unknown"})

def run_conversation():
    # Initial user message
    messages = [{"role": "user", "content": "What's the weather and current time in San Francisco, Tokyo, and Paris?"}]

    # Define the functions for the model
    tools = [
        {
            "type": "function",
            "function": {
                "name": "get_current_weather",
                "description": "Get the current weather in a given location",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "The city name, e.g. San Francisco",
                        },
                        "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
                    },
                    "required": ["location"],
                },
            }
        },
        {
            "type": "function",
            "function": {
                "name": "get_current_time",
                "description": "Get the current time in a given location",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "The city name, e.g. San Francisco",
                        },
                    },
                    "required": ["location"],
                },
            }
        }
    ]

    # First API call: Ask the model to use the functions
    response = client.chat.completions.create(
        model=deployment_name,
        messages=messages,
        tools=tools,
        tool_choice="auto",
    )

    # Process the model's response
    response_message = response.choices[0].message
    messages.append(response_message)

    print("Model's response:")  
    print(response_message)  

    # Handle function calls
    if response_message.tool_calls:
        for tool_call in response_message.tool_calls:
            function_name = tool_call.function.name
            function_args = json.loads(tool_call.function.arguments)
            print(f"Function call: {function_name}")  
            print(f"Function arguments: {function_args}")  
            
            if function_name == "get_current_weather":
                function_response = get_current_weather(
                    location=function_args.get("location"),
                    unit=function_args.get("unit")
                )
            elif function_name == "get_current_time":
                function_response = get_current_time(
                    location=function_args.get("location")
                )
            else:
                function_response = json.dumps({"error": "Unknown function"})
            
            messages.append({
                "tool_call_id": tool_call.id,
                "role": "tool",
                "name": function_name,
                "content": function_response,
            })
    else:
        print("No tool calls were made by the model.")  

    # Second API call: Get the final response from the model
    final_response = client.chat.completions.create(
        model=deployment_name,
        messages=messages,
    )

    return final_response.choices[0].message.content

# Run the conversation and print the result
print(run_conversation())

出力

Model's response:
ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_djHAeQP0DFEVZ2qptrO0CYC4', function=Function(arguments='{"location": "San Francisco", "unit": "celsius"}', name='get_current_weather'), type='function'), ChatCompletionMessageToolCall(id='call_q2f1HPKKUUj81yUa3ITLOZFs', function=Function(arguments='{"location": "Tokyo", "unit": "celsius"}', name='get_current_weather'), type='function'), ChatCompletionMessageToolCall(id='call_6TEY5Imtr17PaB4UhWDaPxiX', function=Function(arguments='{"location": "Paris", "unit": "celsius"}', name='get_current_weather'), type='function'), ChatCompletionMessageToolCall(id='call_vpzJ3jElpKZXA9abdbVMoauu', function=Function(arguments='{"location": "San Francisco"}', name='get_current_time'), type='function'), ChatCompletionMessageToolCall(id='call_1ag0MCIsEjlwbpAqIXJbZcQj', function=Function(arguments='{"location": "Tokyo"}', name='get_current_time'), type='function'), ChatCompletionMessageToolCall(id='call_ukOu3kfYOZR8lpxGRpdkhhdD', function=Function(arguments='{"location": "Paris"}', name='get_current_time'), type='function')])
Function call: get_current_weather
Function arguments: {'location': 'San Francisco', 'unit': 'celsius'}
get_current_weather called with location: San Francisco, unit: celsius
Weather data found for san francisco
Function call: get_current_weather
Function arguments: {'location': 'Tokyo', 'unit': 'celsius'}
get_current_weather called with location: Tokyo, unit: celsius
Weather data found for tokyo
Function call: get_current_weather
Function arguments: {'location': 'Paris', 'unit': 'celsius'}
get_current_weather called with location: Paris, unit: celsius
Weather data found for paris
Function call: get_current_time
Function arguments: {'location': 'San Francisco'}
get_current_time called with location: San Francisco
Timezone found for san francisco
Function call: get_current_time
Function arguments: {'location': 'Tokyo'}
get_current_time called with location: Tokyo
Timezone found for tokyo
Function call: get_current_time
Function arguments: {'location': 'Paris'}
get_current_time called with location: Paris
Timezone found for paris
Here's the current information for the three cities:

### San Francisco
- **Time:** 09:13 AM
- **Weather:** 72°C (quite warm!)

### Tokyo
- **Time:** 01:13 AM (next day)
- **Weather:** 10°C

### Paris
- **Time:** 06:13 PM
- **Weather:** 22°C

Is there anything else you need?

重要

JSON 応答が常に有効であるとは限らないため、エラーを処理できるようにするには、コードにロジックを追加する必要があります。 一部のユース ケースでは、 関数呼び出しのパフォーマンスを向上させるために微調整を使用する必要がある場合があります。

関数によるプロンプトエンジニアリング

要求の一部として関数を定義すると、モデルがトレーニングされた特定の構文を使用して、詳細がシステム メッセージに挿入されます。 つまり、関数はプロンプトでトークンを使用し、プロンプト エンジニアリング手法を適用して関数呼び出しのパフォーマンスを最適化できます。 モデルでは、プロンプトの完全なコンテキストを使用して、関数定義、システム メッセージ、ユーザー メッセージなど、関数を呼び出す必要があるかどうかを判断します。

品質と信頼性の向上

モデルが期待したタイミングまたは方法で関数を呼び出さない場合は、品質の向上を試みることができます。

関数定義に詳細を指定する

関数の意味のある description を指定し、モデルにとって明白ではない可能性があるパラメーターの説明を提供することが重要です。 たとえば、 location パラメーターの説明には、場所の形式に関する追加の詳細と例を含めることができます。

"location": {
    "type": "string",
    "description": "The location of the hotel. The location should include the city and the state's abbreviation (i.e. Seattle, WA or Miami, FL)"
},
システム メッセージでより多くのコンテキストを提供する

システム メッセージを使用して、モデルにより多くのコンテキストを提供することもできます。 たとえば、 search_hotels という名前の関数がある場合は、次のようなシステム メッセージを含めて、ユーザーがホテルを見つける際に関数を呼び出すようにモデルに指示できます。

{"role": "system", "content": "You're an AI assistant designed to help users search for hotels. When a user asks for help finding a hotel, you should call the search_hotels function."}
明確な質問をするようにモデルに指示する

場合によっては、関数で使用する値について想定しないように、明確な質問をするようにモデルに指示する必要があります。 たとえば、 search_hotels では、ユーザー要求に locationの詳細が含まれていない場合に、モデルに明確化を求める必要があります。 明確な質問をするようにモデルに指示するには、次の例のようなコンテンツをシステム メッセージに含めることができます。

{"role": "system", "content": "Don't make assumptions about what values to use with functions. Ask for clarification if a user request is ambiguous."}

エラーの削減

プロンプト エンジニアリングが価値のあるもう 1 つの領域は、関数呼び出しのエラーを減らすことです。 モデルは、定義したスキーマに一致する関数呼び出しを生成するようにトレーニングされていますが、定義したスキーマと一致しない関数呼び出しを生成するか、含めなかった関数を呼び出そうとします。

モデルが指定されていない関数呼び出しを生成している場合は、 "Only use the functions you have been provided with."という文をシステム メッセージに含めてみてください。

責任を持って関数呼び出しを使用する

他の AI システムと同様に、関数呼び出しを使用して言語モデルを他のツールやシステムと統合すると、潜在的なリスクが生じます。 関数呼び出しが提示する可能性があるリスクを理解し、機能を責任を持って使用するための対策を講じていることが重要です。

関数を安全かつ安全に使用するのに役立つヒントをいくつか次に示します。

  • 関数呼び出しの検証: モデルによって生成された関数呼び出しを常に確認します。 これには、パラメーター、呼び出される関数の確認、呼び出しが目的のアクションと一致していることを確認する機能が含まれます。
  • 信頼できるデータとツールを使用する: 信頼できるソースと検証済みのソースからのデータのみを使用します。 関数の出力内の信頼されていないデータを使用して、意図した方法以外の方法で関数呼び出しを記述するようにモデルに指示できます。
  • 最小限の特権の原則に従う: 関数がジョブを実行するために必要な最小限のアクセス権のみを付与します。 これにより、関数が誤用または悪用された場合の潜在的な影響が軽減されます。 たとえば、関数呼び出しを使用してデータベースのクエリを実行する場合は、アプリケーションにデータベースへの読み取り専用アクセス権のみを付与する必要があります。 また、セキュリティコントロールとして関数定義の機能を除外することだけに依存しないでください。
  • 実世界の影響を考慮する: 実行する予定の関数呼び出しが、特にコードの実行、データベースの更新、通知の送信といったアクションをトリガーする場合、その実際の影響に注意してください。
  • ユーザー確認ステップの実装: 特にアクションを実行する関数の場合は、実行前にユーザーがアクションを確認するステップを含めてお勧めします。

Azure OpenAI モデルを責任を持って使用する方法に関する推奨事項の詳細については、 OpenAI モデルの責任ある AI Azure プラクティスの概要を参照してください。

重要

functions および function_call パラメーターは、2023-12-01-preview バージョンの API のリリースで非推奨になりました。 functionsの置換は、tools パラメーターです。 function_callの置換は、tool_choice パラメーターです。

関数呼び出しのサポート

並列関数呼び出し

  • gpt-4 (2024-04-09)
  • gpt-4o (2024-05-13)
  • gpt-4o (2024-08-06)
  • gpt-4o (2024-11-20)
  • gpt-4o-mini (2024-07-18)
  • gpt-4.1 (2025-04-14)
  • gpt-4.1-mini (2025-04-14)
  • gpt-5 (2025-08-07)
  • gpt-5-mini (2025-08-07)
  • gpt-5-nano (2025-08-07)
  • gpt-5-codex (2025-09-11)
  • gpt-5.1 (2025-11-13)
  • gpt-5.1-chat (2025-11-13)
  • gpt-5.1-codex (2025-11-13)
  • gpt-5.1-codex-mini (2025-11-13)
  • gpt-5.1-codex-max (2025-12-04)
  • gpt-5.2 (2025-12-11)
  • gpt-5.2-chat (2025-12-11)
  • gpt-5.2-codex (2026-01-14)
  • gpt-5.2-chat (2026-02-10)
  • gpt-5.3-codex (2026-02-24)
  • gpt-5.3-chat (2026-03-03)
  • gpt-5.4 (2026-03-05)
  • gpt-5.4 (2026-03-05)
  • gpt-5.4-mini (2026-03-17)
  • gpt-5.4-nano (2026-03-17)
  • gpt-5.5 (2026-04-24)

並列関数のサポートは、API バージョン 2023-12-01-preview で最初に追加されました

ツールを使用した基本的な関数呼び出し

  • 並列関数呼び出しをサポートするすべてのモデル
  • gpt-5.4-pro (2026-03-05)
  • gpt-5-pro (2025-10-06)
  • codex-mini (2025-05-16)
  • o3-pro (2025-06-10)
  • o4-mini (2025-04-16)
  • o3 (2025-04-16)
  • gpt-4.1-nano (2025-04-14)
  • o3-mini (2025-01-31)
  • o1 (2024-12-17)

メモ

tool_choice パラメーターは、o3-minio1でサポートされるようになりました。 詳細については、 推論モデルガイドを参照してください。

重要

現在、ツール/関数の説明は、Azure OpenAI では 1,024 文字に制限されています。 この制限が変更された場合は、この記事を更新します。

次の手順