Aufruf einer OpenAI-Funktion in Next.js-API-Endpunkten
OpenAI-Funktionen in Next.js-API-Endpunkten aufrufen: Verbinden Sie Tools mit Server-Handlern, schreiben Sie präzise Beschreibungen der Tools und erfordern Sie Autorisierung für zerstörerische Aufrufe.
Quellen: Function Calling with Next.js and OpenAI: Letting AI Actually Do Things
Einfache Chat-Completionen können nur Text erzeugen. Funktionsaufrufe – auch als Tool-Nutzung bezeichnet – ermöglichen es einem Modell, auf der Grundlage des Benutzeranfrages tatsächliche Anwendungsaktionen wie das Abfragen einer Zeile, das Versenden von E-Mails oder das Aktualisieren eines Datensatzes anzufordern. Die nachstehende Anleitung integriert dieses Muster in eine Next.js-API-Route mit OpenAI.
Das Kernmuster
Beschreiben Sie den Modellen die verfügbaren Tools. Das Modell entscheidet, ob es eines davon aufrufen soll und welche Argumente übermittelt werden müssen. Der Anwendungscode führt den Handler aus und gibt ein Ergebnis zurück, das das Modell in eine Antwort umwandeln kann.
// app/api/chat/route.js
import OpenAI from 'openai';
const openai = new OpenAI();
const tools = [
{
type: 'function',
function: {
name: 'get_order_status',
description: "Get the status of a customer's order",
parameters: {
type: 'object',
properties: {
orderId: { type: 'string', description: 'The order ID' },
},
required: ['orderId'],
},
},
},
];export async function POST(request) {
const { messages } = await request.json(); const response = await openai.chat.completions.create({
model: 'gpt-4o-mini',
messages,
tools,
}); const toolCall = response.choices[0].message.tool_calls?.[0]; if (toolCall) {
const args = JSON.parse(toolCall.function.arguments);
const result = await getOrderStatus(args.orderId); // your real function // Send the result back so the model can respond in natural language
const followUp = await openai.chat.completions.create({
model: 'gpt-4o-mini',
messages: [
...messages,
response.choices[0].message,
{ role: 'tool', tool_call_id: toolCall.id, content: JSON.stringify(result) },
],
}); return Response.json({ reply: followUp.choices[0].message.content });
} return Response.json({ reply: response.choices[0].message.content });
}
Die eigentliche Funktion hinter dem Tool
async function getOrderStatus(orderId) {
const order = await db.order.findUnique({ where: { id: orderId } });
return order ? { status: order.status, eta: order.estimatedDelivery } : { error: 'Order not found' };
}
Der Handler ist gewöhnlicher Serverseitencod. Die Tool-Nutzung führt keine Magie aus; sie bietet dem Modell lediglich eine strukturierte Möglichkeit, den Server dazu aufzufordern, eine Funktion auszuführen.
Umgang mit mehreren Tools
const tools = [
{ type: 'function', function: { name: 'get_order_status', /* ... */ } },
{ type: 'function', function: { name: 'cancel_order', /* ... */ } },
{ type: 'function', function: { name: 'get_account_balance', /* ... */ } },
];
const toolHandlers = {
get_order_status: (args) => getOrderStatus(args.orderId),
cancel_order: (args) => cancelOrder(args.orderId),
get_account_balance: (args) => getAccountBalance(args.userId),
};// In your handler:
const handler = toolHandlers[toolCall.function.name];
const result = await handler(JSON.parse(toolCall.function.arguments));
Eine Handler-Karte ermöglicht eine sauberere Skalierung als eine wachsende if/else-Kette, wenn sich die Liste der Tools erweitert.
Kritisch: Lassen Sie niemals zu, dass das Modell ohne Bestätigung zerstörerische Aktionen ausführt
async function cancelOrder(orderId, userId) {
// Always verify the action against the actual authenticated user server-side —
// never trust that the model's tool call alone represents authorized intent
const order = await db.order.findUnique({ where: { id: orderId } });
if (order.userId !== userId) throw new Error('Unauthorized');
await db.order.update({ where: { id: orderId }, data: { status: 'cancelled' } });
}
Dass ein Modell beschließt, cancel_order aufzurufen, bedeutet nicht automatisch, dass der authentifizierte Benutzer diesen Auftrag stornieren darf. Der Handler muss bei jedem Aufruf erneut die Autorisierung überprüfen, genauso wie es ein normaler API-Endpunkt tun würde.
Häufiger Fehler: Unklare Funktion Beschreibungen
// Too vague — model may call this incorrectly or miss when it should
{ name: 'update', description: 'Updates something' }
// Specific enough for the model to use reliably
{ name: 'update_shipping_address', description: "Updates the shipping address for the customer's most recent unshipped order" }
Die Qualität der Werkzeugauswahl hängt von der Präzision der Beschreibungen ab. Unklare Namen und vage Beschreibungen führen zu fehlenden oder falschen Aufrufen; spezifische Namen sowie präzise Beschreibungen sorgen für zuverlässige Weiterleitungen.
Betrachten Sie die Argumente der Tools als unzuverlässige Eingaben. Überprüfen Sie Identifikatoren, lehnen Sie unerwartete Felder ab und halten Sie Nebeneffekte innerhalb von Transaktionen bei Änderungen an mehreren Tabellen. Das Protokollieren des Toolnamens, der Struktur der Argumente (nicht von Geheimnissen) sowie des Ergebnisses der Autorisierung erleichtert die Rekonstruktion von Produktionsstörungen, wenn ein Modell wiederholt das falsche Tool wählt.
Fazit
Die Aufrufung von Funktionen verwandelt eine Chat-Oberfläche in etwas, das handeln kann, doch die Absicht des Modells ist nur die Hälfte des Systems. Server-Handler benötigen weiterhin Autorisierungen auf Endpoint-Ebene, und genaue Beschreibungen der Tools sorgen dafür, dass diese Aktionen auf die richtige Aufgabe gerichtet bleiben und nicht zu Fehlern führen. Legen Sie Zeitlimits und Wiederholungsversuche für die Kommunikation mit dem Modell fest, damit ein blockiertes Tool-Loop den Pool der Route-Handler nicht erschöpfen kann.