Skip to content

Commit 4f4c7f5

Browse files
authored
ai/core: anthropic tool call support (#1279)
1 parent 92fabdc commit 4f4c7f5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+409
-160
lines changed

.changeset/breezy-kangaroos-fly.md

Lines changed: 5 additions & 0 deletions

docs/pages/docs/ai-core/anthropic.mdx

Lines changed: 1 addition & 1 deletion
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { experimental_generateObject } from 'ai';
2+
import { anthropic } from 'ai/anthropic';
3+
import dotenv from 'dotenv';
4+
import { z } from 'zod';
5+
6+
dotenv.config();
7+
8+
async function main() {
9+
const result = await experimental_generateObject({
10+
model: anthropic.messages('claude-3-opus-20240229'),
11+
schema: z.object({
12+
recipe: z.object({
13+
name: z.string(),
14+
ingredients: z.array(
15+
z.object({
16+
name: z.string(),
17+
amount: z.string(),
18+
}),
19+
),
20+
steps: z.array(z.string()),
21+
}),
22+
}),
23+
prompt: 'Generate a lasagna recipe.',
24+
});
25+
26+
console.log(JSON.stringify(result.object, null, 2));
27+
console.log();
28+
console.log('Token usage:', result.usage);
29+
console.log('Finish reason:', result.finishReason);
30+
}
31+
32+
main().catch(console.error);

examples/ai-core/src/generate-object/mistral-json.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ async function main() {
2929
console.log(JSON.stringify(result.object, null, 2));
3030
}
3131

32-
main();
32+
main().catch(console.error);

examples/ai-core/src/generate-object/mistral-tool.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ async function main() {
2929
console.log(JSON.stringify(result.object, null, 2));
3030
}
3131

32-
main();
32+
main().catch(console.error);

examples/ai-core/src/generate-object/mistral.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ async function main() {
3131
console.log('Finish reason:', result.finishReason);
3232
}
3333

34-
main();
34+
main().catch(console.error);

examples/ai-core/src/generate-object/openai-json.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ async function main() {
2929
console.log(JSON.stringify(result.object, null, 2));
3030
}
3131

32-
main();
32+
main().catch(console.error);

examples/ai-core/src/generate-object/openai-tool.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@ async function main() {
3030
console.log(JSON.stringify(result.object, null, 2));
3131
}
3232

33-
main();
33+
main().catch(console.error);

examples/ai-core/src/generate-object/openai.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ async function main() {
3131
console.log('Finish reason:', result.finishReason);
3232
}
3333

34-
main();
34+
main().catch(console.error);
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { ExperimentalMessage, experimental_generateText } from 'ai';
2+
import { anthropic } from 'ai/anthropic';
3+
import dotenv from 'dotenv';
4+
import * as readline from 'node:readline/promises';
5+
import { weatherTool } from '../tools/weather-tool';
6+
7+
dotenv.config();
8+
9+
const terminal = readline.createInterface({
10+
input: process.stdin,
11+
output: process.stdout,
12+
});
13+
14+
const messages: ExperimentalMessage[] = [];
15+
16+
async function main() {
17+
let toolResponseAvailable = false;
18+
19+
while (true) {
20+
if (!toolResponseAvailable) {
21+
const userInput = await terminal.question('You: ');
22+
messages.push({ role: 'user', content: userInput });
23+
}
24+
25+
const { text, toolCalls, toolResults } = await experimental_generateText({
26+
model: anthropic.messages('claude-3-opus-20240229'),
27+
tools: { weatherTool },
28+
system: `You are a helpful, respectful and honest assistant.`,
29+
messages,
30+
});
31+
32+
toolResponseAvailable = false;
33+
34+
if (text) {
35+
process.stdout.write(`\nAssistant: ${text}`);
36+
}
37+
38+
for (const { toolName, args } of toolCalls) {
39+
process.stdout.write(
40+
`\nTool call: '${toolName}' ${JSON.stringify(args)}`,
41+
);
42+
}
43+
44+
for (const { toolName, result } of toolResults) {
45+
process.stdout.write(
46+
`\nTool response: '${toolName}' ${JSON.stringify(result)}`,
47+
);
48+
}
49+
50+
process.stdout.write('\n\n');
51+
52+
messages.push({
53+
role: 'assistant',
54+
content: [{ type: 'text', text }, ...(toolCalls ?? [])],
55+
});
56+
57+
if (toolResults.length > 0) {
58+
messages.push({ role: 'tool', content: toolResults });
59+
}
60+
61+
toolResponseAvailable = toolCalls.length > 0;
62+
}
63+
}
64+
65+
main().catch(console.error);

0 commit comments

Comments
 (0)