概述
LangChain 代理使用 LangGraph 持久化 来实现长期记忆。这是一个较为高级的主题,需要具备 LangGraph 相关知识才能使用。记忆存储
LangGraph 将长期记忆以 JSON 文档的形式存储在 存储库 中。 每段记忆都组织在一个自定义的namespace(类似于文件夹)和一个唯一的 key(类似于文件名)下。命名空间通常包含用户或组织 ID 或其他便于组织信息的标签。
这种结构支持记忆的层次化组织。然后通过内容过滤器支持跨命名空间的搜索。
Copy
import { InMemoryStore } from "@langchain/langgraph";
const embed = (texts: string[]): number[][] => {
// Replace with an actual embedding function or LangChain embeddings object
return texts.map(() => [1.0, 2.0]);
};
// InMemoryStore saves data to an in-memory dictionary. Use a DB-backed store in production use.
const store = new InMemoryStore({ index: { embed, dims: 2 } });
const userId = "my-user";
const applicationContext = "chitchat";
const namespace = [userId, applicationContext];
await store.put(
namespace,
"a-memory",
{
rules: [
"User likes short, direct language",
"User only speaks English & TypeScript",
],
"my-key": "my-value",
}
);
// get the "memory" by ID
const item = await store.get(namespace, "a-memory");
// search for "memories" within this namespace, filtering on content equivalence, sorted by vector similarity
const items = await store.search(
namespace,
{
filter: { "my-key": "my-value" },
query: "language preferences"
}
);
在工具中读取长期记忆
一个代理可以用来查找用户信息的工具
Copy
import * as z from "zod";
import { createAgent, tool } from "langchain";
import { InMemoryStore, type Runtime } from "@langchain/langgraph";
// InMemoryStore saves data to an in-memory dictionary. Use a DB-backed store in production.
const store = new InMemoryStore();
const contextSchema = z.object({
userId: z.string(),
});
// Write sample data to the store using the put method
await store.put(
["users"], // Namespace to group related data together (users namespace for user data)
"user_123", // Key within the namespace (user ID as key)
{
name: "John Smith",
language: "English",
} // Data to store for the given user
);
const getUserInfo = tool(
// Look up user info.
async (_, runtime: Runtime<z.infer<typeof contextSchema>>) => {
// Access the store - same as that provided to `createAgent`
const userId = runtime.context?.userId;
if (!userId) {
throw new Error("userId is required");
}
// Retrieve data from store - returns StoreValue object with value and metadata
const userInfo = await runtime.store.get(["users"], userId);
return userInfo?.value ? JSON.stringify(userInfo.value) : "Unknown user";
},
{
name: "getUserInfo",
description: "Look up user info by userId from the store.",
schema: z.object({}),
}
);
const agent = createAgent({
model: "openai:gpt-4o-mini",
tools: [getUserInfo],
contextSchema,
// Pass store to agent - enables agent to access store when running tools
store,
});
// Run the agent
const result = await agent.invoke(
{ messages: [{ role: "user", "content: "look up user information" }] },
{ context: { userId: "user_123" } }
);
console.log(result.messages.at(-1)?.content);
/**
* Outputs:
* User Information:
* - Name: John Smith
* - Language: English
*/
从工具写入长期记忆
一个更新用户信息的工具示例
Copy
import * as z from "zod";
import { tool, createAgent, type AgentRuntime } from "langchain";
import { InMemoryStore, type Runtime } from "@langchain/langgraph";
// InMemoryStore saves data to an in-memory dictionary. Use a DB-backed store in production.
const store = new InMemoryStore();
const contextSchema = z.object({
userId: z.string(),
});
// Schema defines the structure of user information for the LLM
const UserInfo = z.object({
name: z.string(),
});
// Tool that allows agent to update user information (useful for chat applications)
const saveUserInfo = tool(
async (userInfo: z.infer<typeof UserInfo>, runtime: Runtime<z.infer<typeof contextSchema>>) => {
const userId = runtime.context?.userId;
if (!userId) {
throw new Error("userId is required");
}
// Store data in the store (namespace, key, data)
await runtime.store.put(["users"], userId, userInfo);
return "Successfully saved user info.";
},
{
name: "save_user_info",
description: "Save user info",
schema: UserInfo,
}
);
const agent = createAgent({
model: "openai:gpt-4o-mini",
tools: [saveUserInfo],
contextSchema,
store,
});
// Run the agent
await agent.invoke(
{ messages: [{ role: "user", "content": "My name is John Smith" }] },
// userId passed in context to identify whose information is being updated
{ context: { userId: "user_123" } }
);
// You can access the store directly to get the value
const result = await store.get(["users"], "user_123");
console.log(result?.value); // Output: { name: "John Smith" }
Connect these docs programmatically to Claude, VSCode, and more via MCP for real-time answers.