Como usar a chamada de função com Azure OpenAI nos modelos da Microsoft Foundry

Se uma ou mais funções forem incluídas em sua solicitação, o modelo determinará se alguma das funções deve ser chamada com base no contexto do prompt. Quando o modelo determina que uma função deve ser chamada, ela responde com um objeto JSON, incluindo os argumentos para a função.

Os modelos formulam chamadas de API e saídas de dados de estrutura, tudo com base nas funções especificadas. É importante observar que, embora os modelos possam gerar essas chamadas, cabe a você executá-las, garantindo que você permaneça no controle.

Em um alto nível, você pode dividir o trabalho com funções em três etapas:

  1. Chamar a API de conclusões de chat com suas funções e a entrada do usuário
  2. Use a resposta do modelo para chamar sua API ou função
  3. Invoque novamente a API de finalização de chat, incluindo a resposta da sua função para obter uma resposta final

Pré-requisitos

  • Um modelo OpenAI do Azure implantado
  • Para autenticação Microsoft Entra ID:

Exemplo de chamada de ferramenta/função única

Primeiro, demonstre uma chamada de função de exemplo que pode verificar a hora em três locais pré-definidos com uma função ou ferramenta única. Adicionamos instruções impressas para ajudar a tornar a execução de código mais fácil de seguir:

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

Saída:

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.

Se estivermos usando uma implantação de modelo que dê suporte a chamadas de função paralela, poderemos convertê-la em um exemplo de chamada de função paralela alterando a matriz de mensagens para solicitar o tempo em vários locais em vez de um.

Para fazer essa troca, troque os comentários nestas duas linhas:

    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

Para que fique com esta aparência, execute o código novamente:

    #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

Isso gera a seguinte saída:

Saída:

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

As chamadas de função paralela permitem que você execute várias chamadas de função em conjunto, permitindo a execução paralela e a recuperação de resultados. Isso reduz o número de chamadas à API que precisam ser feitas e podem melhorar o desempenho geral.

Por exemplo, em nosso aplicativo de tempo simples, recuperamos várias vezes ao mesmo tempo. Isso resultou em uma mensagem de conclusão de chat com três chamadas de função na tool_calls matriz, cada uma com um id único. Se você quisesse responder a essas chamadas de função, adicionaria três novas mensagens à conversa, cada uma contendo o resultado de uma chamada de função, com uma referência tool_call_id ao id de tool_calls.

Para forçar o modelo a chamar uma função específica, defina tool_choice como um objeto de ferramenta nomeado, por exemplo: tool_choice={"type": "function", "function": {"name": "get_current_time"}}. Para forçar uma mensagem voltada para o usuário, defina tool_choice="none".

Nota

O comportamento padrão (tool_choice: "auto") é que o modelo decida por conta própria se deve chamar uma função e, se for o caso, qual função chamar.

Chamada de função paralela com várias funções

Agora, demonstramos outro exemplo de chamada de função de brinquedo, com duas funções/ferramentas diferentes desta vez definidas.

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

Saída

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?

Importante

A resposta JSON pode nem sempre ser válida, portanto, você precisa adicionar lógica adicional ao código para poder lidar com erros. Para alguns casos de uso, talvez você precise usar o ajuste fino para melhorar o desempenho de chamada de função.

Engenharia de prompt com funções

Quando você define uma função como parte de sua solicitação, os detalhes são injetados na mensagem do sistema usando a sintaxe específica na qual o modelo foi treinado. Isso significa que as funções consomem tokens em seu prompt e que você pode aplicar técnicas de engenharia de prompt para otimizar o desempenho de suas chamadas de função. O modelo usa o contexto completo do prompt para determinar se uma função deve ser chamada, incluindo a definição de função, a mensagem do sistema e as mensagens do usuário.

Melhorando a qualidade e a confiabilidade

Se o modelo não estiver chamando sua função quando ou como você espera, há algumas coisas que você pode tentar para melhorar a qualidade.

Forneça mais detalhes em sua definição de função

É importante que você forneça um significado description da função e forneça descrições para qualquer parâmetro que possa não ser óbvio para o modelo. Por exemplo, na descrição do parâmetro location, você pode incluir detalhes extras e exemplos sobre o formato da localização.

"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)"
},
Fornecer mais contexto na mensagem do sistema

A mensagem do sistema também pode ser usada para fornecer mais contexto ao modelo. Por exemplo, se você tiver uma função chamada search_hotels , poderá incluir uma mensagem do sistema como a seguinte para instruir o modelo a chamar a função quando um usuário pedir ajuda para encontrar um hotel.

{"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."}
Instruir o modelo a fazer perguntas esclarecedoras

Em alguns casos, você deseja instruir o modelo a fazer perguntas esclarecedoras para evitar fazer suposições sobre quais valores usar com funções. Por exemplo, com search_hotels, você gostaria que o modelo solicitasse esclarecimentos se a solicitação do usuário não incluísse detalhes sobre location. Para instruir o modelo a fazer uma pergunta esclarecedora, você pode incluir conteúdo como o próximo exemplo em sua mensagem do sistema.

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

Reduzindo erros

Outra área em que a engenharia de prompt pode ser valiosa está em reduzir os erros nas chamadas de funções. Os modelos são treinados para gerar chamadas de função correspondentes ao esquema que você define, mas os modelos produzem uma chamada de função que não corresponde ao esquema definido ou tentam chamar uma função que você não incluiu.

Se você descobrir que o modelo está gerando chamadas de função que não foram fornecidas, tente incluir uma frase na mensagem do sistema que diz "Only use the functions you have been provided with.".

Usando a chamada de função com responsabilidade

Como qualquer sistema de IA, o uso da chamada de função para integrar modelos de linguagem a outras ferramentas e sistemas apresenta riscos potenciais. É importante entender os riscos que a chamada de função pode apresentar e tomar medidas para garantir que você use os recursos com responsabilidade.

Aqui estão algumas dicas para ajudá-lo a usar funções de forma segura e protegida:

  • Validar chamadas de função: sempre verifique as chamadas de função geradas pelo modelo. Isso inclui verificar os parâmetros, a função que está sendo chamada e garantir que a chamada se alinhe com a ação pretendida.
  • Usar dados e ferramentas confiáveis: use apenas dados de fontes confiáveis e verificadas. Dados não confiáveis na saída de uma função podem ser usados para instruir o modelo a gravar chamadas de função de uma maneira diferente da pretendida.
  • Siga o Princípio do Privilégio Mínimo: conceda apenas o acesso mínimo necessário para que a função execute seu trabalho. Isso reduz o impacto potencial se uma função for mal utilizada ou explorada. Por exemplo, se você estiver usando chamadas de função para consultar um banco de dados, só deverá conceder ao seu aplicativo acesso somente leitura ao banco de dados. Você também não deve depender apenas da limitação de recursos na definição de função como medida de segurança.
  • Considere o Impacto no Mundo Real: esteja ciente do impacto real das chamadas de função que você planeja executar, especialmente aquelas que desencadeiam ações como executar código, atualizar bancos de dados ou enviar notificações.
  • Implementar etapas de confirmação do usuário: especialmente para funções que executam ações, recomendamos incluir uma etapa em que o usuário confirme a ação antes da execução.

Para saber mais sobre nossas recomendações sobre como usar Azure modelos OpenAI com responsabilidade, consulte o Overview das práticas de IA responsável para modelos Azure OpenAI.

Importante

Os parâmetros functions e function_call foram preteridos com a versão do 2023-12-01-preview da API. A substituição para functions é o parâmetro tools. A substituição para function_call é o parâmetro tool_choice.

Suporte à chamada de função

Execução paralela de funções

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

O suporte para a função paralela foi adicionado pela primeira vez na versão da API 2023-12-01-preview

Chamada de função básica com ferramentas

  • Todos os modelos que dão suporte à chamada de função paralela
  • 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)

Nota

O tool_choice parâmetro agora tem suporte com o3-mini e o1. Para obter mais informações, consulte o guia de modelos de raciocínio.

Importante

No momento, as descrições de ferramenta/função estão limitadas a 1.024 caracteres com Azure OpenAI. Atualizaremos este artigo se esse limite for alterado.

Próximas etapas