Tool Use: das Modell fragt, das Programm handelt
Kurz gesagt: Tool Use lässt das Modell das Programm bitten, eine Funktion auszuführen, etwa den Status einer Bestellung nachzuschlagen, und aus dem Ergebnis statt aus dem Gedächtnis zu antworten.
Problem
Das Modell kennt deine Bestellungen nicht
Der Kunde fragt: „Wann kommt Bestellung 1042 an?“ Der Assistent fragt das Modell, ohne ihm die Daten zu geben:
FakeClient client = new FakeClient();String question = "Wann kommt Bestellung 1042 an?";List<Message> messages = List.of(new Message("user", List.of(new TextBlock(question))));Reply reply = client.create(SYSTEM, messages, List.of());System.out.println("Modell: " + textOf(reply));Order order = ORDERS.get("1042");System.out.println("Shop: " + order.status() + ", Lieferung " + order.eta());Modell: Bestellung 1042 kommt bis Freitag an.Shop: versandt, Lieferung 3. NovemberDas Modell sagt „bis Freitag“, und der Shop sagt 3. November. Es hat deine Datenbank nie gesehen. Es hat nur den Text, den du ihm geschickt hast, und es erfindet etwas Plausibles.
In der Lektion über den Prompt sind die Bestelldaten in die Vorlage gewandert. Das funktioniert, wenn du im Voraus weißt, welche Daten gebraucht werden. Aber der Kunde kann nach einer anderen Bestellung fragen, nach einer Rückgabe oder nach zwei Dingen auf einmal. Du kannst nicht den ganzen Shop in den Prompt packen: Der Kontext ist begrenzt, und jedes Wort kostet Geld.
Die Idee
Das Modell fragt, das Programm handelt
Du gibst dem Modell eine Liste von Tools. Jedes hat einen Namen, eine Beschreibung und ein Schema für seine Eingabe: dieselbe Art Schema wie in der Lektion über strukturierte Ausgabe. Jetzt kann das Modell auf zwei Arten antworten:
- Mit Text.
stop_reasonistend_turn, und das Gespräch ist zu Ende. - Mit einer Anfrage.
stop_reasonisttool_use, und die Antwort hat einentool_use-Block: eineid, den Namen des Tools und eine Eingabe, zum Beispiel{"order_id": "1042"}.
Bei einer Anfrage macht das Programm Folgendes:
- Es hängt die Antwort des Modells an den Verlauf an, mit der Rolle
assistant. - Es führt das Tool gegen seine eigenen Daten aus.
- Es gibt das Ergebnis als neue
user-Nachricht mit einemtool_result-Block zurück. Darin isttool_use_iddieselbeid, und bei einem Fehler istis_errorwahr. - Es fragt das Modell noch einmal, mit dem ganzen Verlauf.
Das ist die Tool-Schleife (Tool Use). Das Modell führt nichts aus und sieht die Datenbank nicht. Es sagt nur, was es braucht, und das Programm entscheidet, ob und wie es das tut. Darum lesen die Tools des Assistenten nur: den Status einer Bestellung, die Frist für eine Rückgabe.
Die Eingabe des Tools kommt vom Modell, also von außen. Das Programm prüft sie so, wie es ein Formular prüft.Sieh es dir an
Das Tool und die Blöcke
Das Tool, das das Modell verlangen kann. Die Beschreibung ist für das Modell: Daran entscheidet es, wann es das Tool aufruft.
static final List<Tool> TOOLS = List.of( new Tool("get_order_status", "Status und Lieferdatum einer Bestellung anhand ihrer Nummer.", List.of("order_id")));sealed sagt genau, welche:sealed interface Block permits TextBlock, ToolUse, ToolResult {}
record TextBlock(String text) implements Block {}
record ToolUse(String id, String name, Map<String, String> input) implements Block {}
record ToolResult(String toolUseId, String content, boolean isError) implements Block {}
record Message(String role, List<Block> content) {}
record Reply(List<Block> content, String stopReason, int inputTokens, int outputTokens) {}
record Tool(String name, String description, List<String> required) {}
record Order(String status, String eta, String returnBy) {}Das Programm führt aus, was verlangt wurde. Zuerst prüft es, ob es so ein Tool gibt und ob die Eingabe die nötigen Felder hat, dann schlägt es die Bestellung nach:
static ToolResult runTool(ToolUse use) { Tool tool = TOOLS.stream() .filter(t -> t.name().equals(use.name())) .findFirst().orElse(null); if (tool == null) { return new ToolResult(use.id(), "kein Tool " + use.name(), true); } for (String field : tool.required()) { if (!use.input().containsKey(field)) { return new ToolResult(use.id(), "fehlt " + field, true); } } String orderId = use.input().get("order_id"); Order order = ORDERS.get(orderId); if (order == null) { return new ToolResult(use.id(), "keine Bestellung " + orderId, true); } String text = orderId + " — " + order.status() + ", Lieferung " + order.eta(); return new ToolResult(use.id(), text, false);}Jeder Fehler ist ein Ergebnis mit is_error, keine Exception. Das Modell muss verstehen, was passiert ist, und entscheiden, was es dem Kunden sagt.
Sieh es dir an
Die Schleife
static void answer(FakeClient client, String question) { System.out.println("Frage: " + question); List<Message> messages = new ArrayList<>(); messages.add(new Message("user", List.of(new TextBlock(question)))); for (int call = 1; call <= MAX_CALLS; call++) { Reply reply = client.create(SYSTEM, messages, TOOLS); System.out.printf(" Aufruf %d (~%d Tokens): %s%n", call, reply.inputTokens(), reply.stopReason()); if (!reply.stopReason().equals("tool_use")) { System.out.println(" Antwort: " + textOf(reply)); return; } messages.add(new Message("assistant", reply.content())); List<Block> results = new ArrayList<>(); for (Block block : reply.content()) { if (block instanceof ToolUse use) { ToolResult result = runTool(use); String shown = (result.isError() ? "✗ " : "") + result.content(); System.out.printf(" %s %s → %s%n", use.id(), describe(use), shown); results.add(result); } } messages.add(new Message("user", results)); } System.out.println(" Stopp nach " + MAX_CALLS + " Aufrufen → zu einem Menschen");}static ToolResult runTool(ToolUse use) { Tool tool = TOOLS.stream() .filter(t -> t.name().equals(use.name())) .findFirst().orElse(null); if (tool == null) { return new ToolResult(use.id(), "kein Tool " + use.name(), true); } for (String field : tool.required()) { if (!use.input().containsKey(field)) { return new ToolResult(use.id(), "fehlt " + field, true); } } String orderId = use.input().get("order_id"); Order order = ORDERS.get(orderId); if (order == null) { return new ToolResult(use.id(), "keine Bestellung " + orderId, true); } String text = orderId + " — " + order.status() + ", Lieferung " + order.eta(); return new ToolResult(use.id(), text, false);}Schritt für Schritt, in Worten
- Die Frage ist die erste Nachricht. Sie geht zusammen mit der Liste der Tools an das Modell (~34 Tokens).
- Das Modell kennt den Status nicht. Es antwortet mit stop_reason tool_use: „Führe get_order_status mit order_id 1042 aus“.
- Das Programm behält die Antwort des Modells im Verlauf: Das Ergebnis braucht eine Anfrage, auf die es antwortet.
- Das Programm führt das Tool gegen seine eigenen Daten aus. Das Modell fasst den Shop nie an: Es hat nur gefragt.
- Das Ergebnis geht als user-Nachricht zurück: tool_result mit derselben id, call_1.
- Aufruf 2 schickt den ganzen Verlauf noch einmal: ~45 Tokens statt ~34.
- Jetzt hat das Modell die Daten und antwortet mit end_turn. Zwei Aufrufe an das Modell für eine Frage.
Die ganze Schleife. Zwei Hilfsfunktionen sagen, was das Modell verlangt hat und was der Text der Antwort ist:
static String describe(ToolUse use) { return use.name() + "(" + use.input().getOrDefault("order_id", "") + ")";}
static String textOf(Reply reply) { for (Block block : reply.content()) { if (block instanceof TextBlock t) { return t.text(); } } return "";}static void answer(FakeClient client, String question) { System.out.println("Frage: " + question); List<Message> messages = new ArrayList<>(); messages.add(new Message("user", List.of(new TextBlock(question)))); for (int call = 1; call <= MAX_CALLS; call++) { Reply reply = client.create(SYSTEM, messages, TOOLS); System.out.printf(" Aufruf %d (~%d Tokens): %s%n", call, reply.inputTokens(), reply.stopReason()); if (!reply.stopReason().equals("tool_use")) { System.out.println(" Antwort: " + textOf(reply)); return; } messages.add(new Message("assistant", reply.content())); List<Block> results = new ArrayList<>(); for (Block block : reply.content()) { if (block instanceof ToolUse use) { ToolResult result = runTool(use); String shown = (result.isError() ? "✗ " : "") + result.content(); System.out.printf(" %s %s → %s%n", use.id(), describe(use), shown); results.add(result); } } messages.add(new Message("user", results)); } System.out.println(" Stopp nach " + MAX_CALLS + " Aufrufen → zu einem Menschen");}FakeClient client = new FakeClient();answer(client, "Wann kommt Bestellung 1042 an?");Frage: Wann kommt Bestellung 1042 an? Aufruf 1 (~34 Tokens): tool_use call_1 get_order_status(1042) → 1042 — versandt, Lieferung 3. November Aufruf 2 (~45 Tokens): end_turn Antwort: Ich habe nachgesehen: 1042 — versandt, Lieferung 3. November.Eine Frage des Kunden macht zwei Aufrufe an das Modell. Der zweite schickt den ganzen Verlauf und ist größer: ~45 Tokens statt ~34.
Das Modell ist hier ein falscher Client, wie in den früheren Lektionen: Aus den Wörtern der Frage verlangt es die Tools, die es hat, und nach den Ergebnissen baut es daraus eine Antwort. Seine Regel steht unten unter „Genauer, für Neugierige“.
Probier es aus
Ergänze
Wann hält die Schleife an und gibt die Antwort aus? Was fehlt in der Prüfung?
if (!reply.stopReason().equals("")) {tool_use. Solange das Modell Tools verlangt, führt das Programm sie aus und fragt noch einmal. Jeder andere stop_reason (end_turn, aber auch max_tokens oder refusal) heißt, dass das Modell fertig ist.
Probier es aus
Ausgabe vorhersagen
Der Kunde bedankt sich nur. Was gibt answer aus?
FakeClient client = new FakeClient();answer(client, "Danke, das war alles.");Ein Aufruf. Das Modell hat ein Tool, muss es aber nicht benutzen: Bei „Danke“ gibt es nichts nachzuschlagen, also antwortet es direkt mit end_turn. Die Schleife führt nichts aus und endet bei der ersten Prüfung.
Die Idee
Wenn ein Tool fehlschlägt
Tools schlagen fehl: Die Nummer gibt es nicht, ein Feld fehlt, die Datenbank antwortet nicht. Das Programm wirft keine Exception und versteckt den Fehler nicht. Es gibt ihn als tool_result mit is_error an das Modell zurück, und das Modell entscheidet, was es sagt:
FakeClient client = new FakeClient();answer(client, "Wo ist Bestellung 9999?");answer(client, "Wo ist mein Paket?");Frage: Wo ist Bestellung 9999? Aufruf 1 (~33 Tokens): tool_use call_1 get_order_status(9999) → ✗ keine Bestellung 9999 Aufruf 2 (~40 Tokens): end_turn Antwort: Ich finde diese Bestellung nicht. Bitte prüfe die Nummer.Frage: Wo ist mein Paket? Aufruf 1 (~33 Tokens): tool_use call_2 get_order_status() → ✗ fehlt order_id Aufruf 2 (~38 Tokens): end_turn Antwort: Wie lautet deine Bestellnummer?- Bestellung 9999 gibt es nicht. Das Modell sagt es dem Kunden, statt einen Status zu erfinden.
- Die Frage hat keine Nummer. Das Modell hat das Tool trotzdem verlangt, aber ohne
order_id. Die Prüfung fängt das fehlende Feld ab, und das Modell fragt den Kunden nach der Nummer.
Manche Modelle hören nicht auf. Dieses rät die Nummer und verlangt eine nach der anderen:
FakeClient client = new FakeClient();answer(client, "Ich weiß die Nummer nicht mehr, es war ungefähr 1050.");Frage: Ich weiß die Nummer nicht mehr, es war ungefähr 1050. Aufruf 1 (~40 Tokens): tool_use call_1 get_order_status(1050) → ✗ keine Bestellung 1050 Aufruf 2 (~47 Tokens): tool_use call_2 get_order_status(1051) → ✗ keine Bestellung 1051 Aufruf 3 (~54 Tokens): tool_use call_3 get_order_status(1052) → ✗ keine Bestellung 1052 Aufruf 4 (~61 Tokens): tool_use call_4 get_order_status(1053) → ✗ keine Bestellung 1053 Stopp nach 4 Aufrufen → zu einem MenschenDarum hat die Schleife eine Grenze: höchstens 4 Aufrufe, dann geht das Gespräch an einen Menschen. Ohne die Grenze dreht sich das Programm, bis das Geld alle ist.
Probier es aus
Finde den Fehler
Ein Kollege schreibt ein kürzeres runTool. Das Programm schickt das Ergebnis, aber die API lehnt den zweiten Aufruf ab: Das tool_use hat keine Antwort. In welcher Zeile steckt der Fehler?
Wähle die Zeile mit dem Fehler.
Das Ergebnis ist an den Namen des Tools gebunden, nicht an die id der Anfrage. Die API sucht ein tool_result, dessen tool_use_id gleich der id jedes tool_use ist. Der Name ist nicht eindeutig: Zwei Blöcke können get_order_status für zwei Bestellungen verlangen. Nimm in der fehlerhaften Zeile use.id().
Die Idee
Bei dir ausführen
Dieses Programm gehört nicht zur Prüfung der Lektion: Du brauchst ein Konto bei einem Modellanbieter, einen Schlüssel und Geld für jeden Aufruf. Der Schlüssel steht in LLM_API_KEY, nie im Code. Anbieter liefern offizielle SDKs für Java, C#, Python und JavaScript mit derselben Form (Nachrichten, Rollen, Tokens, Tools); die genauen Namen der Klassen und Methoden stehen in der Doku des Anbieters. Hier siehst du, was für die Frage zu 1042 über das Netz geht. Die erste Anfrage trägt die Tools, und der Name des Modells ist ein Platzhalter:
{ "model": "<Name des Modells>", "max_tokens": 1024, "system": "Du bist der Support-Assistent eines Online-Shops. Frag bei Bestellungen die Tools.", "tools": [ { "name": "get_order_status", "description": "Status und Lieferdatum einer Bestellung anhand ihrer Nummer.", "input_schema": { "type": "object", "properties": {"order_id": {"type": "string"}}, "required": ["order_id"] } } ], "messages": [ { "role": "user", "content": "Wann kommt Bestellung 1042 an?" } ]}Die Antwort ist eine Anfrage nach einem Tool:
{ "content": [ { "type": "tool_use", "id": "call_1", "name": "get_order_status", "input": {"order_id": "1042"} } ], "stop_reason": "tool_use", "usage": {"input_tokens": 34, "output_tokens": 3}}Die zweite Anfrage trägt den ganzen Verlauf: die Frage, das tool_use des Modells und das tool_result des Programms mit derselben id:
{ "model": "<Name des Modells>", "max_tokens": 1024, "system": "Du bist der Support-Assistent eines Online-Shops. Frag bei Bestellungen die Tools.", "tools": [ { "name": "get_order_status", "description": "Status und Lieferdatum einer Bestellung anhand ihrer Nummer.", "input_schema": { "type": "object", "properties": {"order_id": {"type": "string"}}, "required": ["order_id"] } } ], "messages": [ { "role": "user", "content": "Wann kommt Bestellung 1042 an?" }, { "role": "assistant", "content": [ { "type": "tool_use", "id": "call_1", "name": "get_order_status", "input": {"order_id": "1042"} } ] }, { "role": "user", "content": [ { "type": "tool_result", "tool_use_id": "call_1", "content": "1042 — versandt, Lieferung 3. November" } ] } ]}{ "content": [ { "type": "text", "text": "Ich habe nachgesehen: 1042 — versandt, Lieferung 3. November." } ], "stop_reason": "end_turn", "usage": {"input_tokens": 45, "output_tokens": 12}}Bei einem Fehler hat das Ergebnis is_error:
{ "type": "tool_result", "tool_use_id": "call_1", "content": "keine Bestellung 9999", "is_error": true}Jede Anfrage geht mit dem Standard-HTTP-Client der Sprache raus, und die Schleife darum ist dieselbe wie in answer. Die Adresse ist ein Platzhalter:
// requestJson ist das JSON der Anfrage oben.// Der genaue Header für den Schlüssel steht in der Doku des Anbieters.HttpClient http = HttpClient.newHttpClient();HttpRequest request = HttpRequest.newBuilder(URI.create("https://<anbieter>/messages")) .header("Authorization", "Bearer " + System.getenv("LLM_API_KEY")) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(requestJson)) .build();HttpResponse<String> response = http.send(request, HttpResponse.BodyHandlers.ofString());System.out.println(response.body());Echte ids sind lange Zufallsstrings. Der falsche Client zählt sie einfach durch: call_1, call_2.
Die Idee
Wo es wehtut
- Ein Tool, das handelt, statt zu lesen. „Storniere die Bestellung“ oder „erstatte das Geld“ bekommt das Modell nicht ohne einen Menschen, der bestätigt. Das Modell kann die Bestellung verwechseln, und hier kostet ein Fehler Geld.
- Zu viele Tools. Jedes Tool ist eine Beschreibung, die bei jedem Aufruf mitgeschickt wird. Zwanzig Tools sind Hunderte Tokens und ein Modell, das öfter das falsche wählt.
- Vage Beschreibungen. Das Modell wählt nach der Beschreibung. „Liefert Daten“ sagt nichts. „Status und Lieferdatum einer Bestellung anhand ihrer Nummer“ sagt, wann man es braucht.
- Der Eingabe vertrauen.
order_idkommt vom Modell. Das Programm prüft, dass die Bestellung existiert und zu diesem Kunden gehört, bevor es etwas zeigt. Wenn ein Tool fremden Text liest (eine E-Mail, eine Webseite), kann dieser Text Anweisungen an das Modell enthalten. Dieser Angriff (Prompt Injection) hat im Modul über Agenten seine eigene Lektion. - Eine Schleife ohne Grenze. Jeder Aufruf schickt den ganzen Verlauf und kostet mehr als der vorherige. Wie viel genau, steht in der Lektion über Kosten und Geschwindigkeit. Ob der Assistent hundert Fragen richtig beantwortet, nicht nur eine, misst du mit einem Testset.
Genauer, für Neugierige
Warum die Antwort des Modells in den Verlauf kommt. Die API hat kein Gedächtnis. Beim zweiten Aufruf sieht das Modell nur, was du ihm schickst. Ein tool_result ohne ein tool_use davor ist eine Antwort ohne Frage, und die API lehnt es ab.
Zwei Tools in einem Aufruf. Das Modell kann mehrere Tools auf einmal verlangen. Das Programm führt alle aus und gibt alle Ergebnisse in einer user-Nachricht zurück, jedes mit seiner eigenen tool_use_id. So gibt es weniger Aufrufe an das Modell.
Eine Wahl erzwingen. Die API hat auch ein Feld tool_choice. Der Standard, auto, lässt das Modell entscheiden, ob es ein Tool benutzt. Neuere Modelle lassen sich nicht zu einem Tool zwingen, darum macht diese Lektion das nicht.
Der falsche Client von innen. Gibt es keine Tools, erfindet er ein Datum. Lautet die Frage „ungefähr 1050“, rät er Nummer für Nummer. Enthält die letzte Nachricht Ergebnisse, baut er daraus eine Antwort, und bei einem Fehler fragt er nach der Nummer oder sagt, dass er die Bestellung nicht findet. Sonst verlangt er das Tool nach der Nummer in der Frage: 1042 und 9999 für den Status, 1187 für eine Rückgabe. Die Tokens sind Wörter × 1,3, und die Beschreibungen der Tools werden bei jedem Aufruf mitgezählt.
// Steht anstelle des echten Modells: aufgezeichnete Antworten,// ohne Netz und jedes Mal dieselben.class FakeClient { static final String MADE_UP = "Bestellung 1042 kommt bis Freitag an."; static final String ASK_ID = "Wie lautet deine Bestellnummer?"; static final String NOT_FOUND = "Ich finde diese Bestellung nicht. Bitte prüfe die Nummer."; static final String THANKS = "Gern geschehen! Schreib uns, wenn du noch eine Frage hast."; private int lastId = 0;
Reply create(String system, List<Message> messages, List<Tool> tools) { String question = ((TextBlock) messages.get(0).content().get(0)).text(); List<Block> last = messages.get(messages.size() - 1).content(); List<Block> content = new ArrayList<>(); if (tools.isEmpty()) { content.add(new TextBlock(MADE_UP)); } else if (question.contains("ungefähr")) { // Rät die nächste Nummer, bis jemand es stoppt. int guess = 1050 + messages.size() / 2; ask(content, tools, "get_order_status", String.valueOf(guess)); } else if (last.get(0) instanceof ToolResult) { content.add(new TextBlock(afterResults(last))); } else { if (question.contains("1042")) { ask(content, tools, "get_order_status", "1042"); } if (question.contains("9999")) { ask(content, tools, "get_order_status", "9999"); } if (question.contains("1187")) { ask(content, tools, "get_return_window", "1187"); } if (question.contains("Paket")) { ask(content, tools, "get_order_status", null); } if (content.isEmpty()) { content.add(new TextBlock(THANKS)); } } int input = tokens(system); for (Tool t : tools) { input += tokens(t.name() + " " + t.description()); } for (Message m : messages) { for (Block b : m.content()) { input += tokens(words(b)); } } int output = 0; for (Block b : content) { output += tokens(words(b)); } String stop = content.get(0) instanceof ToolUse ? "tool_use" : "end_turn"; return new Reply(content, stop, input, output); }
private void ask(List<Block> content, List<Tool> tools, String name, String orderId) { if (tools.stream().noneMatch(t -> t.name().equals(name))) { return; } Map<String, String> input = orderId == null ? Map.of() : Map.of("order_id", orderId); lastId++; content.add(new ToolUse("call_" + lastId, name, input)); }
// Ein echtes Modell formuliert um; dieses hängt die Ergebnisse nur aneinander. private static String afterResults(List<Block> results) { List<String> parts = new ArrayList<>(); for (Block b : results) { ToolResult r = (ToolResult) b; if (r.isError()) { return r.content().contains("order_id") ? ASK_ID : NOT_FOUND; } parts.add(r.content()); } return "Ich habe nachgesehen: " + String.join("; ", parts) + "."; }
static String words(Block block) { return switch (block) { case TextBlock t -> t.text(); case ToolUse u -> u.name() + " " + String.join(" ", u.input().values()); case ToolResult r -> r.content(); }; }
// Grob: Wörter × 1,3, aufgerundet. static int tokens(String text) { String t = text.strip(); int words = t.isEmpty() ? 0 : t.split("\\s+").length; return (words * 13 + 9) / 10; }}sealed interface Block permits … sagt dem Compiler, dass es genau drei Blöcke gibt. Darum hat das switch in words kein default: Wenn du eine vierte Art Block hinzufügst, kompiliert der Code nicht, bis du sie behandelst. instanceof ToolUse use prüft die Art und gibt den Namen use in einem Zug.Übung
Die Rückgabefrist
Löse sie in deinem Editor.
Der Kunde fragt: „Wann kommt 1042 an, und bis wann kann ich 1187 zurückgeben?“ Jetzt hat das Modell nur get_order_status und beantwortet die Hälfte:
Frage: Wann kommt 1042 an, und bis wann kann ich 1187 zurückgeben? Aufruf 1 (~42 Tokens): tool_use call_1 get_order_status(1042) → 1042 — versandt, Lieferung 3. November Aufruf 2 (~53 Tokens): end_turn Antwort: Ich habe nachgesehen: 1042 — versandt, Lieferung 3. November.Füge ein zweites Tool get_return_window hinzu, mit der Beschreibung „Der letzte Tag, an dem eine Bestellung zurückgegeben werden kann, anhand ihrer Nummer.“ und der Eingabe order_id. Gib in runTool 1187 — Rückgabe bis … mit dem Rückgabefeld der Bestellung zurück. Das Modell verlangt beide Tools in einem Aufruf:
Frage: Wann kommt 1042 an, und bis wann kann ich 1187 zurückgeben? Aufruf 1 (~61 Tokens): tool_use call_1 get_order_status(1042) → 1042 — versandt, Lieferung 3. November call_2 get_return_window(1187) → 1187 — Rückgabe bis 9. November Aufruf 2 (~83 Tokens): end_turn Antwort: Ich habe nachgesehen: 1042 — versandt, Lieferung 3. November; 1187 — Rückgabe bis 9. November.Weitere Aufgaben
- Die Bestellung eines anderen. Gib jeder Bestellung den Kunden, dem sie gehört, und
answerden Kunden, der fragt.runToolgibt für die Bestellung eines anderen Kunden einen Fehler zurück. Was sagt das Modell dann? - Ein Token-Budget. Halte die Schleife auch an, wenn die Summe der Eingabe-Tokens 100 übersteigt. Bei welchem Aufruf hält die Frage „ungefähr 1050“ an?
Test
Teste dich
Verwandte Lektionen
Abschnitt „Verwandte Lektionen“- Baut auf: Die Grenzen des Modells · Ein Modell über eine API aufrufen · Der Prompt ist Code · Strukturierte Ausgabe: JSON nach einem Schema
- Geht weiter in: Der Agent-Loop: Plan, Aktion, Beobachtung · Prompt Injection: die E-Mail, die Befehle gibt · Guardrails: Prüfungen vor und nach dem Modell · Der Support-Assistent
- Aufgaben zum Thema: Anwendungen mit LLMs