Como usar a chamada de funções com o Azure OpenAI nos modelos Microsoft Foundry

Se uma ou mais funções forem incluídas no seu pedido, o modelo determina 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, responde com um objeto JSON incluindo os argumentos para a função.

Os modelos formulam chamadas de API e estruturam as saídas de dados, tudo com base nas funções que especificas. É importante notar que, embora os modelos possam gerar estas chamadas, cabe-lhe a si executá-las, garantindo que mantém o controlo.

Num nível elevado, pode dividir o trabalho com funções em três etapas:

  1. Chama a API de completação de chat com as tuas funções e a entrada do utilizador
  2. Use a resposta do modelo para chamar a sua API ou função
  3. Chame novamente a API de completamento de chat, incluindo a resposta da sua função para obter uma resposta final

Pré-requisitos

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

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

Primeiro, demonstre uma chamada de função de brinquedo que pode verificar a hora em três locais codificados fixamente com uma única ferramenta/função definida. Adicionámos instruções print para ajudar a tornar a execução do 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 a usar uma implementação de modelo que suporta chamadas de função paralelas, poderíamos converter isto num exemplo de chamada de função paralela, alterando o array de mensagens para pedir a hora em múltiplos locais em vez de uma.

Para realizar a troca, altere 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 assim, e executar 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

Isto 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

Chamadas paralelas de função permitem realizar múltiplas chamadas de função em conjunto, possibilitando a execução e recuperação paralela dos resultados. Isto reduz o número de chamadas necessárias para a API e pode melhorar o desempenho global.

Por exemplo, na nossa aplicação de tempo simples, recuperámos múltiplos tempos simultaneamente. Isto resultou numa mensagem de conclusão do chat com três chamadas de função na matriz tool_calls, cada uma com um único id. Se quisesse responder a estas chamadas de função, adicionaria três novas mensagens à conversa, cada uma contendo o resultado de uma chamada de função, com uma tool_call_id referência ao id de tool_calls.

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

Nota

O comportamento padrão (tool_choice: "auto") é o modelo decidir por si próprio se deve chamar uma função e, em caso afirmativo, qual função chamar.

Chamada de funções paralelas com múltiplas funções

Agora demonstramos outro exemplo de função de brinquedo, desta vez com duas ferramentas/funções diferentes 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())

Produção

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, por isso precisas de adicionar lógica adicional ao teu código para conseguires lidar com erros. Para alguns casos de uso, pode ser necessário usar ajuste fino para melhorar o desempenho das chamadas de funções.

Engenharia rápida com funções

Quando defines uma função como parte do teu pedido, os detalhes são injetados na mensagem do sistema usando uma sintaxe específica em que o modelo foi treinado. Isto significa que as funções consomem tokens no seu prompt e que pode aplicar técnicas de engenharia de prompts para otimizar o desempenho das suas chamadas de função. O modelo utiliza o contexto completo do prompt para determinar se uma função deve ser chamada, incluindo a definição da função, a mensagem do sistema e as mensagens do utilizador.

Melhoria da qualidade e fiabilidade

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

Forneça mais detalhes na definição da sua função

É importante que forneça um significado description da função e descrições para qualquer parâmetro que possa não ser óbvio para o modelo. Por exemplo, na descrição do parâmetro location, poderia incluir detalhes extra 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)"
},
Forneça mais contexto na mensagem do sistema

A mensagem do sistema também pode ser usada para fornecer mais contexto ao modelo. Por exemplo, se tiver uma função chamada search_hotels , pode incluir uma mensagem do sistema como a seguinte para instruir o modelo a chamar a função quando um utilizador pede 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."}
Instrua o modelo a fazer perguntas de esclarecimento

Em alguns casos, deves instruir o modelo a fazer perguntas de esclarecimento para evitar fazer suposições sobre que valores usar com as funções. Por exemplo, com search_hotels gostaria que o modelo pedisse esclarecimentos se o pedido do utilizador não incluísse detalhes sobre location. Para instruir o modelo a fazer uma pergunta esclarecedora, pode incluir conteúdo como o exemplo seguinte na 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."}

Redução de erros

Outra área onde a engenharia de prompts pode ser valiosa é na redução de erros nas chamadas de funções. Os modelos são treinados para gerar chamadas de função que correspondem ao esquema que defines, mas produzem uma chamada de função que não corresponde ao esquema que definiste ou tenta chamar uma função que não incluiste.

Se descobrires que o modelo está a gerar chamadas de função que não foram fornecidas, tenta incluir uma frase na mensagem do sistema que diga "Only use the functions you have been provided with.".

Usar a chamada de função de forma responsável

Como em qualquer sistema de IA, usar chamadas de funções para integrar modelos de linguagem com outras ferramentas e sistemas apresenta riscos potenciais. É importante compreender os riscos que a invocação de funções pode apresentar e tomar medidas para garantir que utiliza as funcionalidades de forma responsável.

Aqui ficam algumas dicas para o ajudar a usar as funções de forma segura e protegida:

  • Validar Chamadas de Função: Verifique sempre as chamadas de função geradas pelo modelo. Isto inclui verificar os parâmetros, a função a ser chamada e garantir que a chamada está alinhada com a ação pretendida.
  • Use 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 podiam ser usados para instruir o modelo a escrever chamadas de função de uma forma diferente da que pretendias.
  • Siga o Princípio do Menor Privilégio: conceda apenas o acesso mínimo necessário para que a função deseje o seu trabalho. Isto reduz o impacto potencial se uma função for mal utilizada ou explorada. Por exemplo, se estiver a usar chamadas de função para consultar uma base de dados, deve dar à sua aplicação apenas acesso de leitura à base de dados. Também não deve depender apenas da exclusão de capacidades na definição de função como controlo de segurança.
  • Considere o Impacto no Mundo Real: Esteja atento ao impacto real das chamadas de função que planeia executar, especialmente aquelas que desencadeiam ações como executar código, atualizar bases de dados ou enviar notificações.
  • Implementar Passos de Confirmação do Utilizador: Particularmente para funções que realizam ações, recomendamos incluir um passo em que o utilizador confirma a ação antes da execução.

Para saber mais sobre as nossas recomendações sobre como utilizar Azure modelos OpenAI de forma responsável, consulte a visão Visão Geral das Práticas de IA Responsável para Azure modelos OpenAI.

Importante

Os parâmetros functions e function_call foram obsoletos com o lançamento da versão 2023-12-01-preview da API. O substituto para functions é o tools parâmetro. O substituto para function_call é o tool_choice parâmetro.

Suporte para chamadas de função

Chamada de função paralela

  • 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 função paralela foi adicionado pela primeira vez na versão da API 2023-12-01-preview

Chamada básica de funções com ferramentas

  • Todos os modelos que suportam a chamada de funções paralelas
  • 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 suportado com o3-mini e o1. Para mais informações, consulte o guia de modelos de raciocínio.

Importante

As descrições de ferramentas/funções estão atualmente limitadas a 1.024 caracteres com o Azure OpenAI. Atualizaremos este artigo se este limite for alterado.

Próximos passos