Zum Inhalt springen

LLM-Antworten mithilfe von Funktionsaufrufen zu Studio-Operationen in Jitterbit Studio weiterleiten

Einführung

Funktionsaufrufe sind eine LLM-Funktion, bei der das Modell, anstatt freien Text zurückzugeben, eine strukturierte Auswahl darüber zurückgibt, welche Funktion aufgerufen werden soll und welche Argumente übergeben werden. In Studio bedeutet dies, dass das LLM die auszuführende Operation als Reaktion auf eine Benutzeranfrage auswählen kann – beispielsweise eine Nachricht über einen fehlenden Gehaltsscheck an eine HR-Benachrichtigungsoperation weiterleiten, während eine Nachricht über eine Softwarezugriffsanfrage an eine IT-Bereitstellungsoperation weitergeleitet wird.

Dieses Handbuch behandelt zwei Ansätze zur Implementierung dieses Musters:

  • Teil 1: Formale Funktionsaufrufe: Definiere Tool-Schemas in JSON, sende sie mit der LLM-Anfrage über den HTTP v2-Connector und erhalte eine strukturierte tool_calls-Antwort. Ein Skript extrahiert den Funktionsnamen und die Argumente und leitet dann an die richtige Operation weiter. Dieser Ansatz erzeugt zuverlässige, strukturierte Ausgaben und wird für den Produktionseinsatz empfohlen.
  • Teil 2: Prompt-basiertes Routing: Beschreibe verfügbare Operationen als Klartext im System-Prompt und parse dann die Textantwort des LLM auf den ausgewählten Funktionsnamen und leite ihn mithilfe einer Case-Anweisung weiter. Dieser Ansatz erfordert keine Tool-Schema-Erstellung, hängt aber davon ab, dass das LLM die Prompt-Anweisung genau befolgt.

Dieses Handbuch setzt Vertrautheit mit der OpenAI-Aktivität Prompt und dem HTTP v2-Connector voraus. Weitere Konfigurationsdetails findest du unter OpenAI verwenden, um Daten in einer Studio-Operation zu verarbeiten und Eine REST-API über den HTTP v2-Connector aufrufen.

Entwurfsmuster

Beide Ansätze verwenden den gleichen konzeptionellen Fluss und die gleiche Operationsstruktur:

  1. Das LLM empfängt die Nachricht des Benutzers zusammen mit einer Beschreibung der verfügbaren Operationen (der Tool-Liste).
  2. Das LLM wählt die entsprechende Operation aus und gibt einen Funktionsnamen zurück (und in Teil 1 strukturierte Argumente).
  3. Ein Studio-Skript extrahiert den Funktionsnamen und leitet die Ausführung an die entsprechende Operation weiter.

Die Operationskette folgt dieser Struktur:

%%{init: {"themeVariables": {"lineColor": "#6b7280", "edgeLabelBackground": "#f5f5f5"}}}%% flowchart LR A[LLM Prompt operation] -->|On Success| B[Dispatcher script operation] --> C[Target operation]

Die LLM Prompt-Operation sendet die Benutzernachricht an das Modell und speichert die Antwort. Die Dispatcher-Skript-Operation liest die Antwort, extrahiert den ausgewählten Funktionsnamen und ruft die entsprechende Operation mithilfe von RunOperation auf. Jede Zieloperation führt die tatsächliche Arbeit für diese Funktion durch.

Globale Variablen übertragen den extrahierten Funktionsnamen und die Argumente vom Dispatcher in jede Zieloperation.

Teil 1: Formale Funktionsaufrufe

Die OpenAI Chat Completions API akzeptiert ein tools-Array im Request-Body. Jeder Eintrag im Array definiert eine verfügbare Funktion: seinen Namen, eine Beschreibung, die das Modell verwendet, um zu entscheiden, wann es aufgerufen werden soll, und ein JSON-Schema-Objekt, das seine Parameter beschreibt. Wenn das Modell eine Funktion auswählt, gibt es ein tool_calls-Array in seiner Antwort zurück, anstatt message.content zu füllen.

Schritt 1: Tool-Schemas definieren

Jedes Tool-Schema ist ein JSON-Objekt mit drei Feldern: name, description und parameters.

name ist der Bezeichner, den dein Dispatcher-Skript prüft. description teilt dem Modell mit, wann dieses Tool aufgerufen werden soll: schreibe es als eine klare Aussage über den Zweck der Funktion. Das parameters-Objekt folgt den Konventionen des JSON Schema: liste jeden Parameter unter properties auf, setze seinen type und description und liste erforderliche Parameter unter required auf.

Beispiel-Schemas für zwei Tools (eine für HR-Benachrichtigung, eine für IT-Benachrichtigung):

[
  {
    "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"]
      }
    }
  }
]

Tipp

Schreiben Sie Werkzeugbeschreibungen aus der Perspektive des Modells: Beschreiben Sie die Situation, in der das Modell diese Funktion aufrufen sollte, nicht die zugrunde liegende Operation. Vage Beschreibungen führen dazu, dass das Modell das falsche Werkzeug auswählt.

Schritt 2: Werkzeuge in die LLM-Anfrage einbeziehen

Nutzen Sie eine HTTP v2 POST-Aktivität, um den OpenAI Chat Completions-Endpoint (https://api.openai.com/v1/chat/completions) aufzurufen. Konstruieren Sie im Transformations-Text für den Anfrageteil die vollständige JSON-Anfrage als Zeichenfolge und ordnen Sie sie dem Body-Feld zu.

Ein beispielhafter Anfrage-Body mit einer Projektvariablen für den API-Schlüssel und globalen Variablen für die Benutzermeldung und den Verlauf der Konversation:

{
  "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"
}

Wenn tool_choice auf "auto" gesetzt ist, kann das Modell selbst entscheiden, ob es eine Funktion aufruft oder eine reine Textantwort zurückgibt. Um einen Funktionsaufruf zu erzwingen, setzen Sie tool_choice auf "required".

Informationen zur HTTP v2-Verbindung und zum Authentifizierungssetup finden Sie unter REST-API mithilfe des HTTP v2-Connectors aufrufen.

Schritt 3: tool_calls-Antwort analysieren

Wenn das Modell ein Werkzeug auswählt, enthält der Antwort-Body ein tool_calls-Array in choices[0].message. Fügen Sie einen Transformations-Skript-Knoten hinzu, um den Funktionsnamen und die Argumente zu extrahieren und als globale Variablen für die Verwendung im Verteiler und bei den Zieloperationen zu speichern.

Fügen Sie in der Transformation nach der HTTP v2-Aktivität einen Skript-Knoten auf Stammebene hinzu:

<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 konvertiert die arguments-Zeichenfolge (ein JSON-Objekt) in ein Wörterbuch. Die Schlüssel in args entsprechen den Parameternamen, die im Werkzeugschema definiert sind.

Hinweis

tool_calls fehlt in der Antwort, wenn das Modell reinen Text zurückgibt statt eine Funktion aufzurufen. Der $function_name = ""-Zweig verarbeitet diesen Fall, damit der Verteiler-Skript im nächsten Schritt ihn zu einer Fallback-Operation leiten kann.

Schritt 4: Zur Zieloperation verteilen

Erstellen Sie eine zweite Operation, die nach dem erfolgreichen Abschluss der LLM-Prompt-Operation verkettet ist. Diese Operation enthält ein einzelnes Skript-Werkzeug, das function_name liest und die entsprechende Zieloperation aufruft:

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 führt die Zieloperation synchron aus. Die in Schritt 3 gesetzten globalen Variablen (arg_email_body, arg_recipient_name usw.) sind innerhalb jeder Zieloperation verfügbar.

Tipp

Um den Konversationsverlauf zwischen einzelnen Durchläufen zu speichern, nutzen Sie Cloud Datastore, um das Messages-Array zwischen Operationsausführungen beizubehalten. Wenn Sie Eingabeaufforderungen über einen nativen LLM-Connector statt HTTP v2 senden und dieser Connector eine Einstellung für Chatverlauf über Operationen hinweg speichern bietet, kann dieser den Chatverlauf für Sie auf Cloud-Agentgruppen beibehalten, während private Agenten ihn automatisch im Speicher beibehalten.

Teil 2: Prompt-basiertes Routing

Dieser Ansatz bindet die Liste der verfügbaren Operationen direkt als Klartext in die Systemaufforderung ein, weist das Modell an, genau einen Funktionsnamen zu zurückzugeben, und nutzt eine Case-Anweisung zum Verteilen. Kein Tool-Schema-JSON erforderlich.

Schritt 1: Werkzeugmanifest erstellen

Nutzen Sie AddToDict, um jede verfügbare Operation zu registrieren. Speichern Sie die Beschreibung und optionale Parameterliste zusammen in einer einzelnen Zeichenfolge, getrennt durch ein |-Zeichen:

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

Fügen Sie einen unknown_route-Eintrag ein, damit das Modell einen sicheren Fallback hat, wenn die Absicht des Benutzers unklar ist.

Schritt 2: Das Manifest in Text konvertieren

Verwenden Sie GetKeys, um das Wörterbuch zu durchlaufen und eine einfache Textliste zu erstellen, die in die Systemaufforderung eingebettet wird:

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;

Schritt 3: Das Manifest in die Systemaufforderung einbeziehen

Fügen Sie im LLM-Anforderungstext tools_text in die Systemmeldung ein und weisen Sie das Modell an, genau einen Funktionsnamen zu beantworten. Beziehen Sie die Nachricht des Benutzers als separate Nachricht mit der Rolle user ein, damit das Modell eine Anforderung zum Weiterleiten hat. Die Systemanweisung muss explizit sein: Das Modell muss das erwartete Ausgabeformat kennen.

{
  "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"
    }
  ]
}

Die Systemmeldung enthält die Weiterleitungsanweisung und das Tool-Manifest (tools_text); die Benutzermeldung enthält die eigentliche Anforderung (user_message), die das Modell weiterleitet.

Hinweis

Prompt-basiertes Routing hängt davon ab, dass das Modell die Anweisung zum Ausgabeformat befolgt. Wenn das Modell mehr als den Funktionsnamen zurückgibt, entfernt der Trim-Aufruf in Schritt 4 umgebende Leerzeichen, kann aber mehrteilige oder formatierte Antworten nicht korrigieren. Testen Sie die Aufforderung mit dem Zielmodell vor der Bereitstellung.

Schritt 4: Den Funktionsnamen aus der Antwort extrahieren

Das Modell gibt den Funktionsnamen in choices[0].message.content zurück. Fügen Sie einen Skriptknoten in der Transformation nach der HTTP v2-Aktivität hinzu, um ihn als globale Variable zu speichern:

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

Trim entfernt führende oder nachfolgende Leerzeichen aus der Antwort des Modells.

Schritt 5: Zur Zieloperation weiterleiten

Verketten Sie eine Dispatcher-Operation nach erfolgreichem Abschluss der LLM Prompt-Operation, wobei Sie das gleiche Case-Muster wie in Teil 1 verwenden:

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

Der letzte true-Branch erfasst alle Antworten, die nicht mit einem bekannten Funktionsnamen übereinstimmen (z. B. wenn das Modell einen Satz anstelle eines einzelnen Schlüsselworts zurückgibt).

Integration überprüfen

Teil 1 überprüfen (formales Function Calling)

  1. Stellen Sie bereit und führen Sie aus die LLM Prompt-Operation mit einer Benutzermeldung aus, die ein bestimmtes Tool auslösen sollte (z. B. eine Nachricht über ein Gehaltsabrechnung-Problem, um notify_hr auszulösen).

  2. In den Operationsprotokollen bestätigen Sie, dass der Protokolleintrag Function selected: notify_hr anzeigt (oder den erwarteten Funktionsnamen).

  3. Bestätigen Sie, dass die Dispatcher-Operation ausgeführt wurde und dass die entsprechende Zieloperation (Notify HR) erfolgreich abgeschlossen wurde.

  4. Senden Sie eine Nachricht, die kein Tool auslösen sollte (z. B. eine allgemeine Begrüßung). Bestätigen Sie, dass das Protokoll No function call in response anzeigt und dass keine Zieloperation unerwartet aufgerufen wurde.

  5. Wenn das Modell konsistent das falsche Tool auswählt, überprüfen Sie die Tool-Beschreibungen. Beschreibungen, die sich überlappen oder keine Spezifität aufweisen, führen dazu, dass das Modell falsch rät.

  6. Wenn JSONParser einen Fehler auslöst, bestätigen Sie, dass choices[0].message.tool_calls[0].function.arguments eine gültige JSON-Zeichenkette in der Rohantwort ist. Ein leeres oder fehlerhaft formatiertes Argumentfeld weist normalerweise auf ein Modell- oder Prompt-Konfigurationsproblem hin.

Teil 2 überprüfen (Prompt-basiertes Routing)

  1. Stellen Sie bereit und führen Sie aus die LLM Prompt-Operation mit einer Nachricht aus, die klar einer verfügbaren Funktion zugeordnet ist.

  2. In den Operationsprotokollen bestätigen Sie, dass der Protokolleintrag Routing to: gefolgt vom erwarteten Funktionsnamen als einzelnes Wort anzeigt.

  3. Bestätigen Sie, dass die entsprechende Zieloperation ausgeführt wurde und erfolgreich abgeschlossen wurde.

  4. Sende eine mehrdeutige Nachricht. Bestätige, dass das Log Routing to: unknown_route anzeigt und dass die Klärungsoperation ausgeführt wurde.

  5. Falls der finale true-Branch unerwartet ausgelöst wird, überprüfe den rohen choices[0].message.content-Wert im Log. Eine Antwort mit zusätzlichem Text (wie "I would call: get_account_info") deutet darauf hin, dass die Systemaufforderung direktiver sein muss. Füge ein explizites Beispiel zur Aufforderung hinzu, wie: Example response: get_account_info.