Saltar al contenido

Rutea las respuestas de LLM a las operaciones de Studio utilizando llamadas a funciones en Jitterbit Studio

Introducción

La llamada a funciones es una capacidad de LLM donde, en lugar de devolver texto libre, el modelo devuelve una selección estructurada de qué función llamar y qué argumentos pasar. En Studio, esto significa que el LLM puede seleccionar qué operación ejecutar en respuesta a una solicitud del usuario, ruteando un mensaje sobre un cheque de pago faltante a una operación de notificación de recursos humanos, por ejemplo, mientras rutea un mensaje sobre una solicitud de acceso a software a una operación de aprovisionamiento de TI.

Esta guía cubre dos enfoques para implementar este patrón:

  • Parte 1: Llamada a funciones formal: Define esquemas de herramientas en JSON, envíalos con la solicitud de LLM a través del conector HTTP v2, y recibe una respuesta estructurada tool_calls. Un script extrae el nombre de la función y los argumentos, luego despacha a la operación correcta. Este enfoque produce una salida estructurada y confiable y se recomienda para uso en producción.
  • Parte 2: Ruteo basado en prompts: Describe las operaciones disponibles como texto simple en el prompt del sistema, luego analiza la respuesta de texto del LLM para el nombre de la función seleccionada y despacha utilizando una declaración Case. Este enfoque no requiere la creación de esquemas de herramientas, pero depende de que el LLM siga la instrucción del prompt con precisión.

Esta guía asume familiaridad con la actividad Prompt de OpenAI y el conector HTTP v2. Para detalles de configuración, consulta Usar OpenAI para procesar datos en una operación de Studio y Llamar a una API REST utilizando el conector HTTP v2.

Patrón de diseño

Ambos enfoques comparten el mismo flujo conceptual y estructura de operación:

  1. El LLM recibe el mensaje del usuario junto con una descripción de las operaciones disponibles (la lista de herramientas).
  2. El LLM selecciona la operación apropiada y devuelve un nombre de función (y en la Parte 1, argumentos estructurados).
  3. Un script de Studio extrae el nombre de la función y rutea la ejecución a la operación correspondiente.

La cadena de operación sigue esta estructura:

flowchart LR A[Operación de aviso LLM] -->|En caso de éxito| B[Operación de script de despachador] --> C[Operación objetivo]

La operación de aviso LLM envía el mensaje del usuario al modelo y almacena la respuesta. La operación de script de despachador lee la respuesta, extrae el nombre de la función seleccionada y llama a la operación correspondiente usando RunOperation. Cada operación objetivo realiza el trabajo real para esa función.

Las variables globales llevan el nombre de la función extraído y los argumentos del despachador a cada operación objetivo.

Parte 1: Llamada a funciones formal

La API de OpenAI Chat Completions acepta un array tools en el cuerpo de la solicitud. Cada entrada en el array define una función disponible: su nombre, una descripción que el modelo utiliza para decidir cuándo llamarla, y un objeto JSON Schema que describe sus parámetros. Cuando el modelo selecciona una función, devuelve un array tool_calls en su respuesta en lugar de llenar message.content.

Paso 1: Definir los esquemas de herramientas

Cada esquema de herramienta es un objeto JSON con tres campos: name, description y parameters.

El name es el identificador que su script de despachador verificará. La description le indica al modelo cuándo llamar a esta herramienta: escríbala como una declaración clara del propósito de la función. El objeto parameters sigue las convenciones de JSON Schema: enumere cada parámetro bajo properties, establezca su type y description, y enumere los parámetros requeridos bajo required.

Ejemplos de esquemas para dos herramientas (una para notificar a RRHH, una para notificar a 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"]
      }
    }
  }
]

Consejo

Escriba descripciones de herramientas desde la perspectiva del modelo: describa la situación en la que el modelo debería llamar a esta función, no lo que hace la operación subyacente. Descripciones vagas hacen que el modelo seleccione la herramienta incorrecta.

Paso 2: Incluir las herramientas en la solicitud LLM

Utiliza una actividad POST de HTTP v2 para llamar al endpoint de OpenAI Chat Completions (https://api.openai.com/v1/chat/completions). En la transformación del cuerpo de la solicitud, construye la solicitud JSON completa como una cadena y mapea esto al campo del cuerpo.

Un cuerpo de solicitud representativo, utilizando una variable de proyecto para la clave de API y variables globales para el mensaje del usuario y el historial de la conversación:

{
  "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 a "auto" permite que el modelo decida si llamar a una función o devolver una respuesta en texto plano. Para forzar una llamada a función, establece tool_choice a "required".

Para la configuración de conexión y autenticación de HTTP v2, consulta Llamar a una API REST utilizando el conector HTTP v2.

Paso 3: Analizar la respuesta de tool_calls

Cuando el modelo selecciona una herramienta, el cuerpo de la respuesta incluye un array tool_calls en choices[0].message. Agrega un nodo de script de transformación para extraer el nombre de la función y los argumentos y almacenarlos como variables globales para su uso en el despachador y las operaciones de destino.

En la transformación que sigue a la actividad HTTP v2, agrega un nodo de script en el nivel raíz:

<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 convierte la cadena arguments (un objeto JSON) en un diccionario. Las claves en args corresponden a los nombres de los parámetros definidos en el esquema de la herramienta.

Nota

tool_calls está ausente de la respuesta cuando el modelo devuelve texto plano en lugar de llamar a una función. La rama $function_name = "" maneja este caso para que el script del despachador en el siguiente paso pueda dirigirlo a una operación de respaldo.

Paso 4: Despachar a la operación de destino

Crea una segunda operación, encadenada al éxito de la operación de LLM Prompt. Esta operación contiene una única herramienta de Script que lee function_name y llama a la operación de destino apropiada:

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 ejecuta la operación objetivo de manera sincrónica. Las variables globales establecidas en el Paso 3 (arg_email_body, arg_recipient_name, etc.) están disponibles dentro de cada operación objetivo.

Consejo

Para almacenar el historial de conversación entre turnos, utiliza Cloud Datastore para persistir el arreglo de mensajes a través de las ejecuciones de la operación. Si envías solicitudes a través de un conector LLM nativo en lugar de HTTP v2, los conectores de OpenAI, Azure OpenAI y Amazon Bedrock pueden retener el contexto de chat entre operaciones por ti en grupos de agentes en la nube (con agentes privados reteniéndolo en memoria).

Parte 2: Enrutamiento basado en prompts

Este enfoque incrusta la lista de operaciones disponibles directamente en el prompt del sistema como texto plano, instruye al modelo a responder con exactamente un nombre de función y utiliza una Case para despachar. No se requiere JSON de esquema de herramienta.

Paso 1: Construir el manifiesto de la herramienta

Utiliza AddToDict para registrar cada operación disponible. Almacena la descripción y la lista de parámetros opcionales juntas en una sola cadena, separadas por un carácter |:

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.");

Incluye una entrada unknown_route para que el modelo tenga una opción de respaldo segura cuando la intención del usuario no esté clara.

Paso 2: Convertir el manifiesto a texto

Utiliza GetKeys para iterar sobre el diccionario y construir una lista en texto plano para incrustar en el prompt del 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;

Paso 3: Incluir el manifiesto en el prompt del sistema

En el cuerpo de la solicitud LLM, inserta tools_text en el mensaje del sistema e instruye al modelo para que responda con exactamente un nombre de función. Incluye el mensaje del usuario como un mensaje de rol user separado para que el modelo tenga una solicitud a la que dirigir. La instrucción del sistema debe ser explícita: el modelo necesita conocer el formato de salida 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"
    }
  ]
}

El mensaje del sistema lleva la instrucción de enrutamiento y el manifiesto de herramientas (tools_text); el mensaje del usuario lleva la solicitud real (user_message) que el modelo enrutará.

Nota

El enrutamiento basado en prompts depende de que el modelo siga la instrucción de formato de salida. Si el modelo devuelve más que el nombre de la función, la llamada Trim en el Paso 4 elimina los espacios en blanco circundantes, pero no puede corregir respuestas de varias palabras o formateadas. Prueba el prompt con el modelo objetivo antes de implementar.

Paso 4: Extraer el nombre de la función de la respuesta

El modelo devuelve el nombre de la función en choices[0].message.content. Agrega un nodo de script en la transformación después de la actividad HTTP v2 para almacenarlo como una variable global:

<trans>
$function_name = Trim(Source.choices[0].message.content);
WriteToOperationLog("Routing to: " + $function_name);
</trans>

Trim elimina cualquier espacio en blanco al principio o al final de la respuesta del modelo.

Paso 5: Despachar a la operación objetivo

Encadena una operación de despachador en el éxito de la operación LLM Prompt, utilizando el mismo patrón de Case que la 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)
);

La rama final true captura cualquier respuesta que no coincida con un nombre de función conocido (por ejemplo, si el modelo devuelve una oración en lugar de una sola palabra clave).

Verificar la integración

Verificando Parte 1 (llamada formal a la función)

  1. Implementa y ejecuta la operación LLM Prompt con un mensaje de usuario que debería activar una herramienta específica (por ejemplo, un mensaje sobre un problema de nómina para activar notify_hr).

  2. En los registros de operaciones, confirma que la entrada del registro muestra Function selected: notify_hr (o el nombre de función esperado).

  3. Confirma que la operación del despachador se ejecutó y que la operación de destino correspondiente (Notify HR) se completó con éxito.

  4. Envía un mensaje que no debería activar ninguna herramienta (por ejemplo, un saludo general). Confirma que el registro muestra No function call in response y que no se llamó a ninguna operación de destino inesperadamente.

  5. Si el modelo selecciona constantemente la herramienta incorrecta, revisa las descripciones de las herramientas. Descripciones que se superponen o carecen de especificidad hacen que el modelo adivine incorrectamente.

  6. Si JSONParser genera un error, confirma que choices[0].message.tool_calls[0].function.arguments es una cadena JSON válida en la respuesta sin procesar. Un campo de argumentos vacío o mal formado indica típicamente un problema de configuración del modelo o del aviso.

Verificando Parte 2 (enrutamiento basado en avisos)

  1. Despliega y ejecuta la operación LLM Prompt con un mensaje que se mapee claramente a una función disponible.

  2. En los registros de operaciones, confirma que la entrada del registro muestra Routing to: seguido del nombre de función esperado como una sola palabra.

  3. Confirma que la operación de destino correspondiente se ejecutó y completó con éxito.

  4. Envía un mensaje ambiguo. Confirma que el registro muestra Routing to: unknown_route y que la operación de aclaración se ejecutó.

  5. Si la rama final true se activa inesperadamente, inspecciona el valor sin procesar de choices[0].message.content en el registro. Una respuesta que contenga texto adicional (como "I would call: get_account_info") indica que la instrucción del aviso del sistema necesita ser más directa. Agrega un ejemplo explícito al aviso, como: Example response: get_account_info.