Created
September 21, 2024 12:29
-
-
Save mizchi/493c2439f53a7ee79b324d1f5fb07546 to your computer and use it in GitHub Desktop.
Vercel's ai sdk (claude-stream+tools) does not work with deno. Not compat?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// It does not work. | |
/* | |
$ deno run -A vai-claude-tools.ts | |
Certainly! I can help you get the current weather information for San Francisco. To do this, I'll use the weather function to retrieve the data. Let me make the call for you.error: Uncaught (in promise) AI_TypeValidationError: Type validation failed: Value: {"type":"content_block_start","index":1,"content_block":{"type":"tool_use","id":"toolu_01S1YL68SUTQiQhfMrF8ENNr","name":"weather","input":{}}}. | |
Error message: [ | |
{ | |
"received": "tool_use", | |
"code": "invalid_literal", | |
"expected": "text", | |
"path": [ | |
"content_block", | |
"type" | |
], | |
"message": "Invalid literal value, expected \"text\"" | |
}, | |
{ | |
"code": "invalid_type", | |
"expected": "string", | |
"received": "undefined", | |
"path": [ | |
"content_block", | |
"text" | |
], | |
"message": "Required" | |
} | |
] | |
at safeValidateTypes (file:///home/mizchi/clis/node_modules/.deno/@[email protected]/node_modules/@ai-sdk/provider-utils/dist/index.mjs:101:14) | |
at safeParseJSON (file:///home/mizchi/clis/node_modules/.deno/@[email protected]/node_modules/@ai-sdk/provider-utils/dist/index.mjs:144:12) | |
at Object.transform (file:///home/mizchi/clis/node_modules/.deno/@[email protected]/node_modules/@ai-sdk/provider-utils/dist/index.mjs:336:13) | |
at Module.invokeCallbackFunction (ext:deno_webidl/00_webidl.js:981:16) | |
at TransformStreamDefaultController.transformAlgorithm (ext:deno_web/06_streams.js:3789:14) | |
at transformStreamDefaultControllerPerformTransform (ext:deno_web/06_streams.js:4058:59) | |
at transformStreamDefaultSinkWriteAlgorithm (ext:deno_web/06_streams.js:4161:10) | |
at WritableStreamDefaultController.writeAlgorithm (ext:deno_web/06_streams.js:631:12) | |
at writableStreamDefaultControllerProcessWrite (ext:deno_web/06_streams.js:4485:55) | |
at writableStreamDefaultControllerAdvanceQueueIfNeeded (ext:deno_web/06_streams.js:4388:5) | |
Caused by: ZodError: [ | |
{ | |
"received": "tool_use", | |
"code": "invalid_literal", | |
"expected": "text", | |
"path": [ | |
"content_block", | |
"type" | |
], | |
"message": "Invalid literal value, expected \"text\"" | |
}, | |
{ | |
"code": "invalid_type", | |
"expected": "string", | |
"received": "undefined", | |
"path": [ | |
"content_block", | |
"text" | |
], | |
"message": "Required" | |
} | |
] | |
at Object.get error (file:///home/mizchi/clis/node_modules/.deno/[email protected]/node_modules/zod/lib/index.mjs:587:31) | |
at safeValidateTypes (file:///home/mizchi/clis/node_modules/.deno/@[email protected]/node_modules/@ai-sdk/provider-utils/dist/index.mjs:103:33) | |
at safeParseJSON (file:///home/mizchi/clis/node_modules/.deno/@[email protected]/node_modules/@ai-sdk/provider-utils/dist/index.mjs:144:12) | |
at Object.transform (file:///home/mizchi/clis/node_modules/.deno/@[email protected]/node_modules/@ai-sdk/provider-utils/dist/index.mjs:336:13) | |
at Module.invokeCallbackFunction (ext:deno_webidl/00_webidl.js:981:16) | |
at TransformStreamDefaultController.transformAlgorithm (ext:deno_web/06_streams.js:3789:14) | |
at transformStreamDefaultControllerPerformTransform (ext:deno_web/06_streams.js:4058:59) | |
at transformStreamDefaultSinkWriteAlgorithm (ext:deno_web/06_streams.js:4161:10) | |
at WritableStreamDefaultController.writeAlgorithm (ext:deno_web/06_streams.js:631:12) | |
at writableStreamDefaultControllerProcessWrite (ext:deno_web/06_streams.js:4485:55) | |
*/ | |
// for deno | |
import { anthropic } from "npm:@ai-sdk/[email protected]"; | |
import { streamText, tool } from "npm:[email protected]"; | |
import { z } from "npm:[email protected]"; | |
const _encoder = new TextEncoder(); | |
const write = (text: string) => { | |
Deno.stdout.write(_encoder.encode(text)); | |
}; | |
const { textStream } = await streamText({ | |
model: anthropic("claude-3-5-sonnet-20240620"), | |
tools: { | |
weather: tool({ | |
description: "Get the weather in a location", | |
// @ts-ignore no types for zod | |
parameters: z.object({ | |
location: z.string().describe("The location to get the weather for"), | |
}), | |
execute: async ({ location }) => { | |
// This is a fake implementation | |
return { | |
location, | |
temperature: 72 + Math.floor(Math.random() * 21) - 10, | |
}; | |
}, | |
}), | |
}, | |
onStepFinish({ text, toolCalls, toolResults, finishReason, usage }) { | |
console.log("[Step finished]", { | |
text, | |
toolCalls, | |
toolResults, | |
finishReason, | |
usage, | |
}); | |
// your own logic, e.g. for saving the chat history or recording usage | |
}, | |
// toolChoice: "required", | |
maxSteps: 5, | |
prompt: "What is the weather in San Francisco?", | |
// prompt: "Write a poem about embedding models.", | |
}); | |
for await (const textPart of textStream) { | |
write(textPart); | |
} | |
write("\n"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// It works. | |
/* | |
~/clis took 4s | |
$ nodets vai-claude-tools-node.ts | |
Certainly! I can help you get the current weather information for San Francisco. To do this, I'll use the weather function to retrieve the data. Let me make the call for you. | |
[Step finished] { | |
text: "Certainly! I can help you get the current weather information for San Francisco. To do this, I'll use the weather function to retrieve the data. Let me make the call for you.", | |
toolCalls: [ | |
{ | |
type: 'tool-call', | |
toolCallId: 'toolu_012ixXN18FDaUJrEHv7QiZ9i', | |
toolName: 'weather', | |
args: [Object] | |
} | |
], | |
toolResults: [ | |
{ | |
type: 'tool-result', | |
toolCallId: 'toolu_012ixXN18FDaUJrEHv7QiZ9i', | |
toolName: 'weather', | |
args: [Object], | |
result: [Object] | |
} | |
], | |
finishReason: 'tool-calls', | |
usage: { promptTokens: 400, completionTokens: 91, totalTokens: 491 } | |
} | |
Based on the information I've received, here's the current weather in San Francisco: | |
The temperature in San Francisco is 81°F (about 27°C). | |
This temperature suggests that it's quite warm in San Francisco right now. It's a pleasant, summery day, perfect for outdoor activities or enjoying the city. Remember to stay hydrated and use sun protection if you're planning to spend time outside. | |
Is there anything else you'd like to know about the weather in San Francisco or any other location? | |
[Step finished] { | |
text: '\n' + | |
'\n' + | |
"Based on the information I've received, here's the current weather in San Francisco:\n" + | |
'\n' + | |
'The temperature in San Francisco is 81°F (about 27°C).\n' + | |
'\n' + | |
"This temperature suggests that it's quite warm in San Francisco right now. It's a pleasant, summery day, perfect for outdoor activities or enjoying the city. Remember to stay hydrated and use sun protection if you're planning to spend time outside.\n" + | |
'\n' + | |
"Is there anything else you'd like to know about the weather in San Francisco or any other location?", | |
toolCalls: [], | |
toolResults: [], | |
finishReason: 'stop', | |
usage: { promptTokens: 512, completionTokens: 111, totalTokens: 623 } | |
} | |
*/ | |
// for node | |
import { anthropic } from "@ai-sdk/anthropic"; | |
import { streamText, tool } from "ai"; | |
import { z } from "zod"; | |
const _encoder = new TextEncoder(); | |
const write = (text: string) => { | |
// Deno.stdout.write(_encoder.encode(text)); | |
// for node | |
// @ts-ignore | |
process.stdout.write(_encoder.encode(text)); | |
}; | |
const { textStream } = await streamText({ | |
model: anthropic("claude-3-5-sonnet-20240620"), | |
tools: { | |
weather: tool({ | |
description: "Get the weather in a location", | |
// @ts-ignore no types for zod | |
parameters: z.object({ | |
location: z.string().describe("The location to get the weather for"), | |
}), | |
execute: async ({ location }) => { | |
// This is a fake implementation | |
return { | |
location, | |
temperature: 72 + Math.floor(Math.random() * 21) - 10, | |
}; | |
}, | |
}), | |
}, | |
onStepFinish({ text, toolCalls, toolResults, finishReason, usage }) { | |
write("\n"); | |
console.log("[Step finished]", { | |
text, | |
toolCalls, | |
toolResults, | |
finishReason, | |
usage, | |
}); | |
// your own logic, e.g. for saving the chat history or recording usage | |
}, | |
// toolChoice: "required", | |
maxSteps: 5, | |
prompt: "What is the weather in San Francisco?", | |
// prompt: "Write a poem about embedding models.", | |
}); | |
for await (const textPart of textStream) { | |
write(textPart); | |
} | |
write("\n"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment