Ir para o conteúdo

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:

  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:

%%{init: {"themeVariables": {"lineColor": "#6b7280", "edgeLabelBackground": "#f5f5f5"}}}%% flowchart LR A[Operação LLM Prompt] -->|On Success| B[Operação script Dispatcher] --> C[Operação de destino]

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)

  1. 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).

  2. Nos logs da operação, confirme que a entrada de log mostra Function selected: notify_hr (ou o nome de função esperado).

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

  4. 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 response e que nenhuma operação de destino foi chamada inesperadamente.

  5. 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.

  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 prompt.

Verificar a Parte 2 (roteamento baseado em prompt)

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

  2. 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.

  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 Routing to: unknown_route e que a operação de esclarecimento foi executada.

  5. Se o último branch true dispara inesperadamente, inspecione o valor choices[0].message.content bruto 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.