Initial commit
This commit is contained in:
189
references/function-calling-patterns.md
Normal file
189
references/function-calling-patterns.md
Normal file
@@ -0,0 +1,189 @@
|
||||
# Function Calling Patterns
|
||||
|
||||
**Last Updated**: 2025-10-25
|
||||
|
||||
Advanced patterns for implementing function calling (tool calling) with OpenAI's Chat Completions API.
|
||||
|
||||
---
|
||||
|
||||
## Basic Pattern
|
||||
|
||||
```typescript
|
||||
const tools = [
|
||||
{
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'get_weather',
|
||||
description: 'Get current weather for a location',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
location: { type: 'string', description: 'City name' },
|
||||
unit: { type: 'string', enum: ['celsius', 'fahrenheit'] },
|
||||
},
|
||||
required: ['location'],
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Advanced Patterns
|
||||
|
||||
### 1. Parallel Tool Calls
|
||||
|
||||
The model can call multiple tools simultaneously:
|
||||
|
||||
```typescript
|
||||
const completion = await openai.chat.completions.create({
|
||||
model: 'gpt-5',
|
||||
messages: [
|
||||
{ role: 'user', content: 'What is the weather in SF and NYC?' }
|
||||
],
|
||||
tools: tools,
|
||||
});
|
||||
|
||||
// Model may return multiple tool_calls
|
||||
const toolCalls = completion.choices[0].message.tool_calls;
|
||||
|
||||
// Execute all in parallel
|
||||
const results = await Promise.all(
|
||||
toolCalls.map(call => executeFunction(call.function.name, call.function.arguments))
|
||||
);
|
||||
```
|
||||
|
||||
### 2. Dynamic Tool Generation
|
||||
|
||||
Generate tools based on runtime context:
|
||||
|
||||
```typescript
|
||||
function generateTools(database: Database) {
|
||||
const tables = database.getTables();
|
||||
|
||||
return tables.map(table => ({
|
||||
type: 'function',
|
||||
function: {
|
||||
name: `query_${table.name}`,
|
||||
description: `Query the ${table.name} table`,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: table.columns.reduce((acc, col) => ({
|
||||
...acc,
|
||||
[col.name]: { type: col.type, description: col.description },
|
||||
}), {}),
|
||||
},
|
||||
},
|
||||
}));
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Tool Chaining
|
||||
|
||||
Chain tool results:
|
||||
|
||||
```typescript
|
||||
async function chatWithToolChaining(userMessage: string) {
|
||||
let messages = [{ role: 'user', content: userMessage }];
|
||||
|
||||
while (true) {
|
||||
const completion = await openai.chat.completions.create({
|
||||
model: 'gpt-5',
|
||||
messages,
|
||||
tools,
|
||||
});
|
||||
|
||||
const message = completion.choices[0].message;
|
||||
messages.push(message);
|
||||
|
||||
if (!message.tool_calls) {
|
||||
return message.content; // Final answer
|
||||
}
|
||||
|
||||
// Execute tool calls and add results
|
||||
for (const toolCall of message.tool_calls) {
|
||||
const result = await executeFunction(
|
||||
toolCall.function.name,
|
||||
toolCall.function.arguments
|
||||
);
|
||||
|
||||
messages.push({
|
||||
role: 'tool',
|
||||
tool_call_id: toolCall.id,
|
||||
content: JSON.stringify(result),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Error Handling in Tools
|
||||
|
||||
```typescript
|
||||
async function executeFunction(name: string, argsString: string) {
|
||||
try {
|
||||
const args = JSON.parse(argsString);
|
||||
|
||||
switch (name) {
|
||||
case 'get_weather':
|
||||
return await getWeather(args.location, args.unit);
|
||||
|
||||
default:
|
||||
return { error: `Unknown function: ${name}` };
|
||||
}
|
||||
} catch (error: any) {
|
||||
return { error: error.message };
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Streaming with Tools
|
||||
|
||||
```typescript
|
||||
const stream = await openai.chat.completions.create({
|
||||
model: 'gpt-5',
|
||||
messages,
|
||||
tools,
|
||||
stream: true,
|
||||
});
|
||||
|
||||
for await (const chunk of stream) {
|
||||
const delta = chunk.choices[0]?.delta;
|
||||
|
||||
// Check for tool calls in streaming
|
||||
if (delta?.tool_calls) {
|
||||
// Accumulate tool call data
|
||||
console.log('Tool call chunk:', delta.tool_calls);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
✅ **Schema Design**:
|
||||
- Provide clear descriptions for each parameter
|
||||
- Use enum when options are limited
|
||||
- Mark required vs optional parameters
|
||||
|
||||
✅ **Error Handling**:
|
||||
- Return structured error objects
|
||||
- Don't throw exceptions from tool functions
|
||||
- Let the model handle error recovery
|
||||
|
||||
✅ **Performance**:
|
||||
- Execute independent tool calls in parallel
|
||||
- Cache tool results when appropriate
|
||||
- Limit recursion depth to avoid infinite loops
|
||||
|
||||
❌ **Don't**:
|
||||
- Expose sensitive internal functions
|
||||
- Allow unlimited recursion
|
||||
- Skip parameter validation
|
||||
- Return unstructured error messages
|
||||
|
||||
---
|
||||
|
||||
**See Also**: Official Function Calling Guide (https://platform.openai.com/docs/guides/function-calling)
|
||||
Reference in New Issue
Block a user