如何将运行时值传递给工具
本指南假定您已熟悉以下概念:
本指南使用具有原生工具调用功能的模型。 您可以查看支持工具调用的所有模型列表。
您可能需要将仅在运行时才知道的值绑定到某个工具。例如,工具的逻辑可能需要使用发起请求的用户 ID。
大多数情况下,这些值不应由 LLM 控制。实际上,允许 LLM 控制用户 ID 可能会导致安全风险。
相反,LLM 应该仅控制那些设计上应由 LLM 控制的工具参数,而其他参数(如用户 ID)应由应用程序逻辑固定。
Pick your chat model:
- Groq
- OpenAI
- Anthropic
- Google Gemini
- FireworksAI
- MistralAI
- VertexAI
Install dependencies
- npm
- yarn
- pnpm
npm i @langchain/groq
yarn add @langchain/groq
pnpm add @langchain/groq
Add environment variables
GROQ_API_KEY=your-api-key
Instantiate the model
import { ChatGroq } from "@langchain/groq";
const llm = new ChatGroq({
model: "llama-3.3-70b-versatile",
temperature: 0
});
Install dependencies
- npm
- yarn
- pnpm
npm i @langchain/openai
yarn add @langchain/openai
pnpm add @langchain/openai
Add environment variables
OPENAI_API_KEY=your-api-key
Instantiate the model
import { ChatOpenAI } from "@langchain/openai";
const llm = new ChatOpenAI({
model: "gpt-4o-mini",
temperature: 0
});
Install dependencies
- npm
- yarn
- pnpm
npm i @langchain/anthropic
yarn add @langchain/anthropic
pnpm add @langchain/anthropic
Add environment variables
ANTHROPIC_API_KEY=your-api-key
Instantiate the model
import { ChatAnthropic } from "@langchain/anthropic";
const llm = new ChatAnthropic({
model: "claude-3-5-sonnet-20240620",
temperature: 0
});
Install dependencies
- npm
- yarn
- pnpm
npm i @langchain/google-genai
yarn add @langchain/google-genai
pnpm add @langchain/google-genai
Add environment variables
GOOGLE_API_KEY=your-api-key
Instantiate the model
import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
const llm = new ChatGoogleGenerativeAI({
model: "gemini-2.0-flash",
temperature: 0
});
Install dependencies
- npm
- yarn
- pnpm
npm i @langchain/community
yarn add @langchain/community
pnpm add @langchain/community
Add environment variables
FIREWORKS_API_KEY=your-api-key
Instantiate the model
import { ChatFireworks } from "@langchain/community/chat_models/fireworks";
const llm = new ChatFireworks({
model: "accounts/fireworks/models/llama-v3p1-70b-instruct",
temperature: 0
});
Install dependencies
- npm
- yarn
- pnpm
npm i @langchain/mistralai
yarn add @langchain/mistralai
pnpm add @langchain/mistralai
Add environment variables
MISTRAL_API_KEY=your-api-key
Instantiate the model
import { ChatMistralAI } from "@langchain/mistralai";
const llm = new ChatMistralAI({
model: "mistral-large-latest",
temperature: 0
});
Install dependencies
- npm
- yarn
- pnpm
npm i @langchain/google-vertexai
yarn add @langchain/google-vertexai
pnpm add @langchain/google-vertexai
Add environment variables
GOOGLE_APPLICATION_CREDENTIALS=credentials.json
Instantiate the model
import { ChatVertexAI } from "@langchain/google-vertexai";
const llm = new ChatVertexAI({
model: "gemini-1.5-flash",
temperature: 0
});
使用上下文变量
此功能是在 @langchain/core>=0.3.10 中添加的。如果您在项目中单独使用 LangSmith SDK,我们也建议升级到 langsmith>=0.1.65。请确保您的软件包已更新。
它还需要 async_hooks 支持,在所有环境中并非都支持此功能。
解决此问题的一种方法是使用上下文变量。上下文变量是一个强大的功能,允许您在应用程序的更高级别设置值,然后在从该级别调用的子 runnable(例如工具)中访问它们。
它们的工作方式超出了传统的范围规则,因此您无需直接引用已声明的变量即可访问其值。
下面,我们声明了一个工具,该工具根据名为 userId 的上下文变量更新中心
userToPets 状态。请注意,此 userId 不属于工具的 schema 或输入:
import { z } from "zod";
import { tool } from "@langchain/core/tools";
import { getContextVariable } from "@langchain/core/context";
let userToPets: Record<string, string[]> = {};
const updateFavoritePets = tool(
async (input) => {
const userId = getContextVariable("userId");
if (userId === undefined) {
throw new Error(
`No "userId" found in current context. Remember to call "setContextVariable('userId', value)";`
);
}
userToPets[userId] = input.pets;
return "update_favorite_pets called.";
},
{
name: "update_favorite_pets",
description: "add to the list of favorite pets.",
schema: z.object({
pets: z.array(z.string()),
}),
}
);
如果在更高层级设置上下文变量之前调用上述工具,userId 将会是
undefined:
await updateFavoritePets.invoke({ pets: ["cat", "dog"] });
Error: No "userId" found in current context. Remember to call "setContextVariable('userId', value)";
at updateFavoritePets.name (evalmachine.<anonymous>:14:15)
at /Users/jacoblee/langchain/langchainjs/langchain-core/dist/tools/index.cjs:329:33
at AsyncLocalStorage.run (node:async_hooks:346:14)
at AsyncLocalStorageProvider.runWithConfig (/Users/jacoblee/langchain/langchainjs/langchain-core/dist/singletons/index.cjs:58:24)
at /Users/jacoblee/langchain/langchainjs/langchain-core/dist/tools/index.cjs:325:68
at new Promise (<anonymous>)
at DynamicStructuredTool.func (/Users/jacoblee/langchain/langchainjs/langchain-core/dist/tools/index.cjs:321:20)
at DynamicStructuredTool._call (/Users/jacoblee/langchain/langchainjs/langchain-core/dist/tools/index.cjs:283:21)
at DynamicStructuredTool.call (/Users/jacoblee/langchain/langchainjs/langchain-core/dist/tools/index.cjs:111:33)
at async evalmachine.<anonymous>:3:22
相反,请设置一个上下文变量,作为调用工具的位置的父级:
import { setContextVariable } from "@langchain/core/context";
import { BaseChatModel } from "@langchain/core/language_models/chat_models";
import { RunnableLambda } from "@langchain/core/runnables";
const handleRunTimeRequestRunnable = RunnableLambda.from(
async (params: { userId: string; query: string; llm: BaseChatModel }) => {
const { userId, query, llm } = params;
if (!llm.bindTools) {
throw new Error("Language model does not support tools.");
}
// Set a context variable accessible to any child runnables called within this one.
// You can also set context variables at top level that act as globals.
setContextVariable("userId", userId);
const tools = [updateFavoritePets];
const llmWithTools = llm.bindTools(tools);
const modelResponse = await llmWithTools.invoke(query);
// For simplicity, skip checking the tool call's name field and assume
// that the model is calling the "updateFavoritePets" tool
if (modelResponse.tool_calls.length > 0) {
return updateFavoritePets.invoke(modelResponse.tool_calls[0]);
} else {
return "No tool invoked.";
}
}
);
当我们的方法调用工具时,你将看到工具正确访问了先前设置的 userId
上下文变量,并成功运行:
await handleRunTimeRequestRunnable.invoke({
userId: "brace",
query: "my favorite animals are cats and parrots.",
llm: llm,
});
ToolMessage {
"content": "update_favorite_pets called.",
"name": "update_favorite_pets",
"additional_kwargs": {},
"response_metadata": {},
"tool_call_id": "call_vsD2DbSpDquOtmFlOtbUME6h"
}
并且还更新了 userToPets 对象,添加了一个与我们传入的 userId(即
"brace")匹配的键:
console.log(userToPets);
{ brace: [ 'cats', 'parrots' ] }
没有上下文变量的情况下
如果你使用的是较早版本的 core,或者所处的环境不支持
async_hooks,你可以使用以下设计模式,在运行时动态创建工具,并将其绑定到相应的值。
其思路是在请求时动态创建工具,并将其绑定到相应的信息。例如, 这些信息可以是从请求本身解析出的用户 ID。
import { z } from "zod";
import { tool } from "@langchain/core/tools";
userToPets = {};
function generateToolsForUser(userId: string) {
const updateFavoritePets = tool(
async (input) => {
userToPets[userId] = input.pets;
return "update_favorite_pets called.";
},
{
name: "update_favorite_pets",
description: "add to the list of favorite pets.",
schema: z.object({
pets: z.array(z.string()),
}),
}
);
// You can declare and return additional tools as well:
return [updateFavoritePets];
}
验证工具是否正常工作
const [updatePets] = generateToolsForUser("cobb");
await updatePets.invoke({ pets: ["tiger", "wolf"] });
console.log(userToPets);
{ cobb: [ 'tiger', 'wolf' ] }
import { BaseChatModel } from "@langchain/core/language_models/chat_models";
async function handleRunTimeRequest(
userId: string,
query: string,
llm: BaseChatModel
): Promise<any> {
if (!llm.bindTools) {
throw new Error("Language model does not support tools.");
}
const tools = generateToolsForUser(userId);
const llmWithTools = llm.bindTools(tools);
return llmWithTools.invoke(query);
}
这段代码将允许 LLM 调用工具,但 LLM并不知道存在用户 ID这一事实。你可以看到,user_id
并不在 LLM 生成的参数列表中:
const aiMessage = await handleRunTimeRequest(
"cobb",
"my favorite pets are tigers and wolves.",
llm
);
console.log(aiMessage.tool_calls[0]);
{
name: 'update_favorite_pets',
args: { pets: [ 'tigers', 'wolves' ] },
type: 'tool_call',
id: 'call_FBF4D51SkVK2clsLOQHX6wTv'
}
:::提示 点击 这里 查看上述运行的 LangSmith 跟踪。 :::
:::提示 聊天模型仅输出调用工具的请求。它们不会实际调用底层工具。
如需了解如何调用工具,请参阅 如何使用模型调用工具。 :::