-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Brace/anthropic tools #4978
Brace/anthropic tools #4978
Changes from 5 commits
d1eab3c
076b69a
56aede7
fef15c8
baef838
7d0b267
18bbfea
1396b1d
38a8fcb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import { ChatAnthropic } from "@langchain/anthropic"; | ||
import { ChatPromptTemplate } from "@langchain/core/prompts"; | ||
import { z } from "zod"; | ||
import { zodToJsonSchema } from "zod-to-json-schema"; | ||
|
||
const calculatorSchema = z.object({ | ||
operation: z | ||
.enum(["add", "subtract", "multiply", "divide", "average"]) | ||
.describe("The type of operation to execute."), | ||
numbers: z.array(z.number()).describe("The numbers to operate on."), | ||
}); | ||
|
||
const weatherSchema = z | ||
.object({ | ||
location: z.string().describe("The name of city to get the weather for."), | ||
}) | ||
.describe( | ||
"Get the weather of a specific location and return the temperature in Celsius." | ||
); | ||
|
||
const tools = [ | ||
{ | ||
name: "calculator", | ||
description: "A simple calculator tool.", | ||
input_schema: zodToJsonSchema(calculatorSchema), | ||
}, | ||
{ | ||
name: "get_weather", | ||
description: "Get the weather of a location", | ||
input_schema: zodToJsonSchema(weatherSchema), | ||
}, | ||
]; | ||
|
||
const model = new ChatAnthropic({ | ||
anthropicApiKey: process.env.ANTHROPIC_API_KEY, | ||
modelName: "claude-3-opus-20240229", | ||
}).bind({ | ||
tools, | ||
}); | ||
|
||
const prompt = ChatPromptTemplate.fromMessages([ | ||
[ | ||
"system", | ||
"You are a helpful assistant who always uses tools to ensure you provide accurate, up to date information.", | ||
], | ||
["human", "{input}"], | ||
]); | ||
|
||
// Chain your prompt and model together | ||
const chain = prompt.pipe(model); | ||
|
||
const response = await chain.invoke({ | ||
input: | ||
"What is the current weather in new york, and san francisco? Also, what is the average of these numbers: 2273,7192,272,92737?", | ||
}); | ||
console.log(JSON.stringify(response, null, 2)); | ||
/* | ||
{ | ||
"kwargs": { | ||
"content": "<thinking>\nTo answer this query, there are two relevant tools:\n\n1. get_weather - This can be used to get the current weather for New York and San Francisco. It requires a \"location\" parameter. Since the user provided \"new york\" and \"san francisco\" as locations, we have the necessary information to call this tool twice - once for each city.\n\n2. calculator - This can be used to calculate the average of the provided numbers. It requires a \"numbers\" parameter which is an array of numbers, and an \"operation\" parameter. The user provided the numbers \"2273,7192,272,92737\" which we can split into an array, and they asked for the \"average\", so we have the necessary information to call this tool.\n\nSince we have the required parameters for both relevant tools, we can proceed with the function calls.\n</thinking>", | ||
"additional_kwargs": { | ||
"id": "msg_013AgVS83LU6fWRHbykfvbYS", | ||
"type": "message", | ||
"role": "assistant", | ||
"model": "claude-3-opus-20240229", | ||
"stop_reason": "tool_use", | ||
"usage": { | ||
"input_tokens": 714, | ||
"output_tokens": 336 | ||
}, | ||
"tool_calls": [ | ||
{ | ||
"id": "toolu_01NHY2v7kZx8WqAvGzBuCu4h", | ||
"type": "function", | ||
"function": { | ||
"arguments": "{\"location\":\"new york\"}", | ||
"name": "get_weather" | ||
} | ||
}, | ||
{ | ||
"id": "toolu_01PVCofvgkbnD4NfWfvXdsPC", | ||
"type": "function", | ||
"function": { | ||
"arguments": "{\"location\":\"san francisco\"}", | ||
"name": "get_weather" | ||
} | ||
}, | ||
{ | ||
"id": "toolu_019AVVNUyCYnvsVdpkGKVDdv", | ||
"type": "function", | ||
"function": { | ||
"arguments": "{\"operation\":\"average\",\"numbers\":[2273,7192,272,92737]}", | ||
"name": "calculator" | ||
} | ||
} | ||
] | ||
}, | ||
} | ||
} | ||
*/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { ChatAnthropic } from "@langchain/anthropic"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hey there! I've reviewed the code and noticed that the added code explicitly accesses an environment variable via |
||
import { ChatPromptTemplate } from "@langchain/core/prompts"; | ||
import { z } from "zod"; | ||
import { zodToJsonSchema } from "zod-to-json-schema"; | ||
|
||
const calculatorSchema = z.object({ | ||
operation: z | ||
.enum(["add", "subtract", "multiply", "divide"]) | ||
.describe("The type of operation to execute."), | ||
number1: z.number().describe("The first number to operate on."), | ||
number2: z.number().describe("The second number to operate on."), | ||
}); | ||
|
||
const tool = { | ||
name: "calculator", | ||
description: "A simple calculator tool", | ||
input_schema: zodToJsonSchema(calculatorSchema), | ||
}; | ||
|
||
const model = new ChatAnthropic({ | ||
anthropicApiKey: process.env.ANTHROPIC_API_KEY, | ||
modelName: "claude-3-haiku-20240307", | ||
}).bind({ | ||
tools: [tool], | ||
}); | ||
|
||
const prompt = ChatPromptTemplate.fromMessages([ | ||
[ | ||
"system", | ||
"You are a helpful assistant who always needs to use a calculator.", | ||
], | ||
["human", "{input}"], | ||
]); | ||
|
||
// Chain your prompt and model together | ||
const chain = prompt.pipe(model); | ||
|
||
const response = await chain.invoke({ | ||
input: "What is 2 + 2?", | ||
}); | ||
console.log(JSON.stringify(response, null, 2)); | ||
/* | ||
{ | ||
"kwargs": { | ||
"content": "Okay, let's calculate that using the calculator tool:", | ||
"additional_kwargs": { | ||
"id": "msg_01YcT1KFV8qH7xG6T6C4EpGq", | ||
"role": "assistant", | ||
"model": "claude-3-haiku-20240307", | ||
"tool_calls": [ | ||
{ | ||
"id": "toolu_01UiqGsTTH45MUveRQfzf7KH", | ||
"type": "function", | ||
"function": { | ||
"arguments": "{\"number1\":2,\"number2\":2,\"operation\":\"add\"}", | ||
"name": "calculator" | ||
} | ||
} | ||
] | ||
}, | ||
"response_metadata": {} | ||
} | ||
} | ||
*/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { ChatAnthropic } from "@langchain/anthropic"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hey team, just a heads up that I've flagged the latest change in the PR for review. It explicitly accesses the |
||
import { ChatPromptTemplate } from "@langchain/core/prompts"; | ||
import { z } from "zod"; | ||
|
||
const calculatorSchema = z | ||
.object({ | ||
operation: z | ||
.enum(["add", "subtract", "multiply", "divide"]) | ||
.describe("The type of operation to execute."), | ||
number1: z.number().describe("The first number to operate on."), | ||
number2: z.number().describe("The second number to operate on."), | ||
}) | ||
.describe("A simple calculator tool"); | ||
|
||
const model = new ChatAnthropic({ | ||
anthropicApiKey: process.env.ANTHROPIC_API_KEY, | ||
modelName: "claude-3-haiku-20240307", | ||
}); | ||
|
||
// Pass the schema and tool name to the withStructuredOutput method | ||
const modelWithTool = model.withStructuredOutput(calculatorSchema); | ||
|
||
const prompt = ChatPromptTemplate.fromMessages([ | ||
[ | ||
"system", | ||
"You are a helpful assistant who always needs to use a calculator.", | ||
], | ||
["human", "{input}"], | ||
]); | ||
|
||
// Chain your prompt and model together | ||
const chain = prompt.pipe(modelWithTool); | ||
|
||
const response = await chain.invoke({ | ||
input: "What is 2 + 2?", | ||
}); | ||
console.log(response); | ||
/* | ||
{ operation: 'add', number1: 2, number2: 2 } | ||
*/ | ||
|
||
/** | ||
* You can supply a "name" field to give the LLM additional context | ||
* around what you are trying to generate. You can also pass | ||
* 'includeRaw' to get the raw message back from the model too. | ||
*/ | ||
const includeRawModel = model.withStructuredOutput(calculatorSchema, { | ||
name: "calculator", | ||
includeRaw: true, | ||
}); | ||
const includeRawChain = prompt.pipe(includeRawModel); | ||
|
||
const includeRawResponse = await includeRawChain.invoke({ | ||
input: "What is 2 + 2?", | ||
}); | ||
console.log(JSON.stringify(includeRawResponse, null, 2)); | ||
/* | ||
{ | ||
"raw": { | ||
"kwargs": { | ||
"content": "Okay, let me use the calculator tool to find the result of 2 + 2:", | ||
"additional_kwargs": { | ||
"id": "msg_01HYwRhJoeqwr5LkSCHHks5t", | ||
"type": "message", | ||
"role": "assistant", | ||
"model": "claude-3-haiku-20240307", | ||
"usage": { | ||
"input_tokens": 458, | ||
"output_tokens": 109 | ||
}, | ||
"tool_calls": [ | ||
{ | ||
"id": "toolu_01LDJpdtEQrq6pXSqSgEHErC", | ||
"type": "function", | ||
"function": { | ||
"arguments": "{\"number1\":2,\"number2\":2,\"operation\":\"add\"}", | ||
"name": "calculator" | ||
} | ||
} | ||
] | ||
}, | ||
} | ||
}, | ||
"parsed": { | ||
"operation": "add", | ||
"number1": 2, | ||
"number2": 2 | ||
} | ||
} | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey there! 👋 I've flagged this PR for your review because it adds code that explicitly accesses an environment variable using
process.env
. Please take a look and ensure that the handling of environment variables aligns with best practices. Let me know if you need any further assistance with this!