Rotear respostas de LLM para operações do Studio usando chamada de função no Jitterbit Studio
Introdução
A chamada de função é um recurso de LLM em que, em vez de retornar texto livre, o modelo retorna uma seleção estruturada de qual função chamar e quais argumentos passar. No Studio, isso significa que o LLM pode selecionar qual operação executar em resposta a uma solicitação do usuário, roteando uma mensagem sobre um salário não recebido para uma operação de notificação de RH, por exemplo, enquanto roteia uma mensagem sobre uma solicitação de acesso a software para uma operação de provisionamento de TI.
Este guia aborda duas abordagens para implementar esse padrão:
- Parte 1: Chamada de função formal: Defina esquemas de ferramentas em JSON, envie-os com a solicitação de LLM por meio do conector HTTP v2 e receba uma resposta estruturada de
tool_calls. Um script extrai o nome da função e os argumentos, depois encaminha para a operação correta. Esta abordagem produz saída confiável e estruturada e é recomendada para uso em produção. - Parte 2: Roteamento baseado em prompt: Descreva as operações disponíveis como texto simples no prompt do sistema, depois analise a resposta de texto do LLM para o nome da função selecionada e encaminhe usando uma instrução
Case. Esta abordagem não requer criação de esquema de ferramenta, mas depende do LLM seguir a instrução do prompt com precisão.
Este guia pressupõe familiaridade com a atividade Prompt do OpenAI e o conector HTTP v2. Para detalhes de configuração, consulte Usar OpenAI para processar dados em uma operação do Studio e Chamar uma API REST usando o conector HTTP v2.
Padrão de design
Ambas as abordagens compartilham o mesmo fluxo conceitual e estrutura de operação:
- O LLM recebe a mensagem do usuário junto com uma descrição das operações disponíveis (a lista de ferramentas).
- O LLM seleciona a operação apropriada e retorna um nome de função (e na Parte 1, argumentos estruturados).
- Um script do Studio extrai o nome da função e roteia a execução para a operação correspondente.
A cadeia de operações segue esta estrutura:
A operação LLM Prompt envia a mensagem do usuário para o modelo e armazena a resposta. A operação script Dispatcher lê a resposta, extrai o nome da função selecionada e chama a operação correspondente usando RunOperation. Cada operação de destino realiza o trabalho real dessa função.
Variáveis globais carregam o nome da função extraído e os argumentos do dispatcher para cada operação de destino.
Parte 1: Chamada de função formal
A API OpenAI Chat Completions aceita um array tools no corpo da solicitação. Cada entrada no array define uma função disponível: seu nome, uma descrição que o modelo usa para decidir quando chamá-la e um objeto JSON Schema descrevendo seus parâmetros. Quando o modelo seleciona uma função, ele retorna um array tool_calls em sua resposta em vez de preencher message.content.
Etapa 1: Definir os esquemas de ferramenta
Cada esquema de ferramenta é um objeto JSON com três campos: name, description e parameters.
O name é o identificador que seu script dispatcher verificará. A description diz ao modelo quando chamar essa ferramenta: escreva-a como uma declaração clara do propósito da função. O objeto parameters segue as convenções do JSON Schema: liste cada parâmetro sob properties, defina seu type e description e liste os parâmetros obrigatórios sob required.
Exemplos de esquemas para duas ferramentas (uma para notificar RH, outra para notificar TI):
[
{
"type": "function",
"function": {
"name": "notify_hr",
"description": "Send a message to the HR team, for example about onboarding, payroll, or leave requests.",
"parameters": {
"type": "object",
"properties": {
"email_body": {
"type": "string",
"description": "The full text of the message to send."
},
"recipient_name": {
"type": "string",
"description": "The name of the HR contact to address."
}
},
"required": ["email_body", "recipient_name"]
}
}
},
{
"type": "function",
"function": {
"name": "notify_it",
"description": "Send a message to the IT team, for example about software access, hardware, or account issues.",
"parameters": {
"type": "object",
"properties": {
"email_body": {
"type": "string",
"description": "The full text of the message to send."
},
"issue_type": {
"type": "string",
"description": "A short label for the type of issue, for example 'access request' or 'hardware fault'."
}
},
"required": ["email_body", "issue_type"]
}
}
}
]
Dica
Descreva as ferramentas do ponto de vista do modelo: descreva a situação em que o modelo deve chamar essa função, não o que a operação subjacente faz. Descrições vagas fazem com que o modelo selecione a ferramenta errada.
Etapa 2: Incluir as ferramentas na solicitação do LLM
Use uma atividade HTTP v2 POST para chamar o endpoint OpenAI Chat Completions (https://api.openai.com/v1/chat/completions). Na transformação do corpo da solicitação, construa a solicitação JSON completa como uma string e mapeie-a para o campo body.
Um corpo de solicitação representativo, usando uma variável de projeto para a chave da API e variáveis globais para a mensagem do usuário e histórico de conversa:
{
"model": "gpt-4",
"messages": [
{
"role": "system",
"content": "You are a helpful assistant. Use the available functions to handle the user's request."
},
{
"role": "user",
"content": "$user_message"
}
],
"tools": <tools array from Step 1>,
"tool_choice": "auto"
}
Configurar tool_choice como "auto" permite que o modelo decida se deve chamar uma função ou retornar uma resposta em texto simples. Para forçar uma chamada de função, configure tool_choice como "required".
Para configuração de conexão HTTP v2 e autenticação, consulte Chamar uma API REST usando o conector HTTP v2.
Etapa 3: Analisar a resposta tool_calls
Quando o modelo seleciona uma ferramenta, o corpo da resposta inclui um array tool_calls em choices[0].message. Adicione um nó de script de transformação para extrair o nome da função e argumentos e armazene-os como variáveis globais para uso no dispatcher e operações de destino.
Na transformação que segue a atividade HTTP v2, adicione um nó de script no nível raiz:
<trans>
// Check whether the model made a function call
toolCalls = Source.choices[0].message.tool_calls;
If(Length(toolCalls) > 0,
// Extract the function name and parse the arguments JSON string
$function_name = toolCalls[0].function.name;
args = JSONParser(toolCalls[0].function.arguments);
// Store individual arguments as global variables for downstream operations
$arg_email_body = args["email_body"];
$arg_recipient_name = args["recipient_name"];
$arg_issue_type = args["issue_type"];
WriteToOperationLog("Function selected: " + $function_name);
,
// No function call: model returned plain text
$function_name = "";
WriteToOperationLog("No function call in response");
);
</trans>
JSONParser converte a string arguments (um objeto JSON) em um dicionário. As chaves em args correspondem aos nomes dos parâmetros definidos no esquema da ferramenta.
Nota
tool_calls está ausente da resposta quando o modelo retorna texto simples em vez de chamar uma função. O branch $function_name = "" trata esse caso para que o script dispatcher na próxima etapa possa roteá-lo para uma operação alternativa.
Etapa 4: Distribuir para a operação de destino
Crie uma segunda operação, encadeada no sucesso da operação LLM Prompt. Esta operação contém uma única ferramenta Script que lê function_name e chama a operação de destino apropriada:
Case($function_name == "notify_hr",
RunOperation("<TAG>operation:Notify HR</TAG>");,
$function_name == "notify_it",
RunOperation("<TAG>operation:Notify IT</TAG>");,
true,
// Default case: unknown function name or plain text response
WriteToOperationLog("No matching function for: " + $function_name)
);
RunOperation executa a operação de destino sincronamente. As variáveis globais definidas na Etapa 3 (arg_email_body, arg_recipient_name, etc.) estão disponíveis dentro de cada operação de destino.
Dica
Para armazenar o histórico de conversa entre turnos, use Cloud Datastore para persistir o array de mensagens entre execuções de operação. Se enviar prompts por um conector LLM nativo em vez de HTTP v2, e esse conector oferecer uma configuração Store chat context across operations, ele pode reter o contexto de chat entre operações para você em grupos de agentes cloud, com agentes privados retendo-o na memória automaticamente.
Parte 2: Roteamento baseado em prompt
Esta abordagem incorpora a lista de operações disponíveis diretamente no prompt do sistema como texto simples, instrui o modelo a responder com exatamente um nome de função e usa uma instrução Case para distribuição. Nenhum JSON de esquema de ferramenta é necessário.
Etapa 1: Criar o manifesto de ferramentas
Use AddToDict para registrar cada operação disponível. Armazene a descrição e lista de parâmetros opcional juntas em uma única string, separadas por um caractere |:
AddToDict($tools_dict, "get_account_info",
"Retrieve account details for a customer.|(account_name)");
AddToDict($tools_dict, "create_ticket",
"Create a support ticket for a reported issue.|(subject,description)");
AddToDict($tools_dict, "send_notification",
"Send a notification message to a user.|(user_id,message)");
AddToDict($tools_dict, "unknown_route",
"Ask the user for clarification when the request is ambiguous.");
Inclua uma entrada unknown_route para que o modelo tenha um fallback seguro quando a intenção do usuário não estiver clara.
Etapa 2: Converter o manifesto em texto
Use GetKeys para iterar sobre o dicionário e criar uma lista em texto simples para incorporar na instrução do sistema:
toolText = "";
keys = GetKeys($tools_dict);
i = 0;
while(i < Length(keys),
key = keys[i];
entry = $tools_dict[key];
desc = Split(entry, "|")[0];
params = Split(entry, "|")[1];
toolText = toolText + "- " + key + ": " + desc;
If(Length(params) > 0,
toolText = toolText + " Parameters: " + params
);
toolText = toolText + "\n";
i++
);
$tools_text = toolText;
Etapa 3: Incluir o manifesto na instrução do sistema
No corpo da solicitação do LLM, insira tools_text na mensagem do sistema e instrua o modelo a responder com exatamente um nome de função. Inclua a mensagem do usuário como uma mensagem separada com função user para que o modelo tenha uma solicitação a rotear. A instrução do sistema deve ser explícita: o modelo precisa saber o formato de saída esperado.
{
"model": "gpt-4",
"messages": [
{
"role": "system",
"content": "You are a routing assistant. Based on the user's message, respond with exactly one function name from the list below. Do not include any explanation or other text.\n\nAvailable functions:\n$tools_text"
},
{
"role": "user",
"content": "$user_message"
}
]
}
A mensagem do sistema contém a instrução de roteamento e o manifesto de ferramentas (tools_text); a mensagem do usuário contém a solicitação real (user_message) que o modelo roteia.
Nota
O roteamento baseado em prompt depende do modelo seguir a instrução de formato de saída. Se o modelo retornar mais do que o nome da função, a chamada Trim na Etapa 4 remove espaços em branco ao redor, mas não pode corrigir respostas com múltiplas palavras ou formatadas. Teste o prompt com o modelo de destino antes de implementar.
Etapa 4: Extrair o nome da função da resposta
O modelo retorna o nome da função em choices[0].message.content. Adicione um nó de script na transformação após a atividade HTTP v2 para armazená-lo como uma variável global:
<trans>
$function_name = Trim(Source.choices[0].message.content);
WriteToOperationLog("Routing to: " + $function_name);
</trans>
Trim remove espaços em branco iniciais ou finais da resposta do modelo.
Etapa 5: Despachar para a operação de destino
Encadeie uma operação de dispatcher no sucesso da operação LLM Prompt, usando o mesmo padrão Case da Parte 1:
Case($function_name == "get_account_info",
RunOperation("<TAG>operation:Get Account Info</TAG>");,
$function_name == "create_ticket",
RunOperation("<TAG>operation:Create Ticket</TAG>");,
$function_name == "send_notification",
RunOperation("<TAG>operation:Send Notification</TAG>");,
$function_name == "unknown_route",
RunOperation("<TAG>operation:Ask For Clarification</TAG>");,
true,
WriteToOperationLog("Unrecognised function name: " + $function_name)
);
O ramo true final captura qualquer resposta que não corresponda a um nome de função conhecido (por exemplo, se o modelo retornar uma sentença em vez de uma única palavra-chave).
Verificar a integração
Verificar a Parte 1 (chamada de função formal)
-
Implante e execute a operação LLM Prompt com uma mensagem do usuário que deve disparar uma ferramenta específica (por exemplo, uma mensagem sobre um problema de folha de pagamento para disparar
notify_hr). -
Nos logs da operação, confirme que a entrada de log mostra
Function selected: notify_hr(ou o nome de função esperado). -
Confirme que a operação de dispatcher foi executada e que a operação de destino correspondente (
Notify HR) foi concluída com sucesso. -
Envie uma mensagem que não deve disparar nenhuma ferramenta (por exemplo, uma saudação geral). Confirme que o log mostra
No function call in responsee que nenhuma operação de destino foi chamada inesperadamente. -
Se o modelo selecionar consistentemente a ferramenta errada, revise as descrições da ferramenta. Descrições que se sobrepõem ou carecem de especificidade fazem o modelo adivinhar incorretamente.
-
Se
JSONParsergerar um erro, confirme quechoices[0].message.tool_calls[0].function.argumentsé uma string JSON válida na resposta bruta. Um campo de argumentos vazio ou malformado geralmente indica um problema de configuração do modelo ou prompt.
Verificar a Parte 2 (roteamento baseado em prompt)
-
Implante e execute a operação LLM Prompt com uma mensagem que corresponda claramente a uma função disponível.
-
Nos logs da operação, confirme que a entrada de log mostra
Routing to:seguido do nome de função esperado como uma única palavra. -
Confirme que a operação de destino correspondente foi executada e concluída com sucesso.
-
Envie uma mensagem ambígua. Confirme que o log mostra
Routing to: unknown_routee que a operação de esclarecimento foi executada. -
Se o último branch
truedispara inesperadamente, inspecione o valorchoices[0].message.contentbruto no log. Uma resposta contendo texto extra (como"I would call: get_account_info") indica que a instrução do prompt do sistema precisa ser mais diretiva. Adicione um exemplo explícito ao prompt, como:Example response: get_account_info.