Ir para o conteúdo

Roteie respostas do LLM para operações do Studio usando chamadas de função no Jitterbit Studio

Introdução

A chamada de função é uma capacidade do LLM onde, 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 um pedido do usuário, roteando uma mensagem sobre um pagamento ausente para uma operação de notificação de RH, por exemplo, enquanto roteia uma mensagem sobre um pedido de acesso a software para uma operação de provisionamento de TI.

Este guia cobre duas abordagens para implementar esse padrão:

  • Parte 1: Chamada de função formal: Defina esquemas de ferramentas em JSON, envie-os com o pedido do LLM via o conector HTTP v2, e receba uma resposta estruturada tool_calls. Um script extrai o nome da função e os argumentos, e então despacha para a operação correta. Essa abordagem produz uma saída estruturada e confiável 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, e então analise a resposta de texto do LLM para o nome da função selecionada e despache usando uma declaração Case. Essa abordagem não requer a criação de esquemas de ferramentas, mas depende do LLM seguir a instrução do prompt com precisão.

Este guia assume familiaridade com a atividade Prompt da OpenAI e o conector HTTP v2. Para detalhes de configuração, veja Use OpenAI para processar dados em uma operação do Studio e Chame 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:

  1. O LLM recebe a mensagem do usuário junto com uma descrição das operações disponíveis (a lista de ferramentas).
  2. O LLM seleciona a operação apropriada e retorna um nome de função (e na Parte 1, argumentos estruturados).
  3. 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:

flowchart LR A[Operação de Prompt LLM] -->|Em Caso de Sucesso| B[Operação de script Dispatcher] --> C[Operação de Destino]

A operação de Prompt LLM envia a mensagem do usuário para o modelo e armazena a resposta. A operação de 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 para essa função.

Variáveis globais transportam 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 de Conclusões de Chat da OpenAI 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 ferramentas

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 informa ao modelo quando chamar esta ferramenta: escreva 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 o RH, uma para notificar o 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

Escreva descrições de 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.

Passo 2: Incluir as ferramentas na solicitação LLM

Use uma atividade HTTP v2 POST para chamar o endpoint de Completions do Chat da OpenAI (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 o histórico da 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"
}

Definir 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, defina tool_choice como "required".

Para configuração de conexão e autenticação HTTP v2, consulte Chamar uma API REST usando o conector HTTP v2.

Passo 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 os argumentos e armazená-los como variáveis globais para uso nas operações de despachante e alvo.

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 ramo $function_name = "" lida com esse caso para que o script do despachante na próxima etapa possa direcioná-lo para uma operação de fallback.

Passo 4: Despachar para a operação alvo

Crie uma segunda operação, encadeada ao sucesso da operação de Prompt LLM. Esta operação contém uma única ferramenta de Script que lê function_name e chama a operação alvo 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 de forma síncrona. 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 conversas entre as interações, use Cloud Datastore para persistir o array de mensagens entre as execuções da operação. Se você enviar prompts através de um conector LLM nativo em vez de HTTP v2, os conectores OpenAI, Azure OpenAI e Amazon Bedrock podem reter o contexto do chat entre as operações para você em grupos de agentes na nuvem (com agentes privados retendo isso na memória).

Parte 2: Roteamento baseado em prompts

Essa abordagem incorpora a lista de operações disponíveis diretamente no prompt do sistema como texto simples, instruindo o modelo a responder com exatamente um nome de função e usa uma declaração Case para despachar. Nenhum JSON de esquema de ferramenta é necessário.

Etapa 1: Construir o manifesto da ferramenta

Use AddToDict para registrar cada operação disponível. Armazene a descrição e a lista de parâmetros opcionais 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 uma opção de fallback segura 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 construir uma lista em texto simples para incorporar no prompt 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 no prompt do sistema

No corpo da solicitação 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 de papel user separada para que o modelo tenha uma solicitação a ser roteada. 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 carrega a instrução de roteamento e o manifesto da ferramenta (tools_text); a mensagem do usuário carrega 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 de várias palavras ou formatadas. Teste o prompt com o modelo alvo antes de implantar.

Etapa 4: Extraia 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 quaisquer espaços em branco à frente ou atrás da resposta do modelo.

Etapa 5: Despachar para a operação alvo

Encadeie uma operação de despachante no sucesso da operação LLM Prompt, usando o mesmo padrão Case que a 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 final true captura qualquer resposta que não corresponda a um nome de função conhecido (por exemplo, se o modelo retornar uma frase em vez de uma única palavra-chave).

Verifique a integração

Verificando a Parte 1 (chamada de função formal)

  1. Implante e execute a operação LLM Prompt com uma mensagem do usuário que deve acionar uma ferramenta específica (por exemplo, uma mensagem sobre um problema de folha de pagamento para acionar notify_hr).

  2. No logs de operação, confirme que a entrada do log mostra Função selecionada: notify_hr (ou o nome da função esperado).

  3. Confirme que a operação do despachante foi executada e que a operação de destino correspondente (Notificar RH) foi concluída com sucesso.

  4. Envie uma mensagem que não deve acionar nenhuma ferramenta (por exemplo, uma saudação geral). Confirme que o log mostra Nenhuma chamada de função em resposta e que nenhuma operação de destino foi chamada inesperadamente.

  5. Se o modelo consistentemente selecionar a ferramenta errada, revise as descrições das ferramentas. Descrições que se sobrepõem ou carecem de especificidade fazem com que o modelo adivinhe incorretamente.

  6. Se JSONParser gerar um erro, confirme que choices[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 do prompt.

Verificando a Parte 2 (roteamento baseado em prompt)

  1. Implante e execute a operação LLM Prompt com uma mensagem que mapeie claramente para uma função disponível.

  2. No logs de operação, confirme que a entrada do log mostra Roteando para: seguida pelo nome da função esperado como uma única palavra.

  3. Confirme que a operação de destino correspondente foi executada e concluída com sucesso.

  4. Envie uma mensagem ambígua. Confirme que o log mostra Roteando para: unknown_route e que a operação de esclarecimento foi executada.

  5. Se o ramo final true for acionado inesperadamente, inspecione o valor bruto de choices[0].message.content no log. Uma resposta contendo texto extra (como "Eu chamaria: get_account_info") indica que a instrução do prompt do sistema precisa ser mais direta. Adicione um exemplo explícito ao prompt, como: Exemplo de resposta: get_account_info.