Skip to main content

Zep 云存储记忆

回忆、理解并从聊天历史中提取数据,打造个性化的 AI 体验。

Zep 是为 AI 助手应用提供的长期记忆服务。 使用 Zep,你可以让 AI 助手回忆过去的对话,无论这些对话多久以前发生, 同时还能减少幻觉、延迟和成本。

Zep 云存储的工作原理

Zep 持久化存储并回忆聊天历史,并从这些聊天历史中自动生成摘要和其他相关数据。 它还会对消息和摘要进行嵌入处理,使你能够搜索 Zep,从而获取过去对话中的相关上下文。 Zep 的所有这些操作都是异步执行的,以确保这些操作不会影响用户的聊天体验。 数据会持久化保存到数据库中,让你能够根据增长需求进行扩展。

Zep 还提供了一个简单易用的文档向量搜索抽象接口,称为文档集合(Document Collections)。 该功能旨在补充 Zep 核心的记忆功能,而不是作为通用的向量数据库。

Zep 让你在构建提示词时更加有目的性:

  • 自动添加最近的几条消息,消息数量可根据你的应用需求自定义;
  • 在上述消息之前,添加最近对话的摘要;
  • 从整个聊天会话中提取相关的上下文摘要或消息;
  • 或者从 Zep 文档集合中获取相关的业务数据。

Zep 云存储提供以下功能:

  • 事实提取:无需预先定义数据模式,即可从对话中自动构建事实表。
  • 对话分类:即时准确地对聊天对话进行分类。理解用户意图和情绪,对用户进行分组等。基于语义上下文进行链路路由,并触发事件。
  • 结构化数据提取:使用你定义的模式,快速从聊天对话中提取业务数据。了解你的助手下一步应该询问什么才能完成任务。

安装

注册 Zep 云存储 并创建一个项目。

按照 Zep 云存储 Typescript SDK 安装指南 安装并开始使用 Zep。

要使用 Zep 云存储记忆功能,你需要获取 Zep 云存储项目的 API 密钥。更多信息请参阅 Zep 云存储文档

:::提示 请参阅安装集成包的一般说明部分。 :::

npm install @getzep/zep-cloud @langchain/openai @langchain/community @langchain/core

ZepCloudChatMessageHistory + RunnableWithMessageHistory 的使用方式

import { ZepClient } from "@getzep/zep-cloud";
import {
ChatPromptTemplate,
MessagesPlaceholder,
} from "@langchain/core/prompts";
import { ConsoleCallbackHandler } from "@langchain/core/tracers/console";
import { ChatOpenAI } from "@langchain/openai";
import { RunnableWithMessageHistory } from "@langchain/core/runnables";
import { ZepCloudChatMessageHistory } from "@langchain/community/stores/message/zep_cloud";

// Your Zep Session ID.
const sessionId = "<Zep Session ID>";
const zepClient = new ZepClient({
// Your Zep Cloud Project API key https://help.getzep.com/projects
apiKey: "<Zep Api Key>",
});

const prompt = ChatPromptTemplate.fromMessages([
["system", "Answer the user's question below. Be polite and helpful:"],
new MessagesPlaceholder("history"),
["human", "{question}"],
]);

const chain = prompt
.pipe(
new ChatOpenAI({
temperature: 0.8,
model: "gpt-3.5-turbo-1106",
})
)
.withConfig({
callbacks: [new ConsoleCallbackHandler()],
});

const chainWithHistory = new RunnableWithMessageHistory({
runnable: chain,
getMessageHistory: (sessionId) =>
new ZepCloudChatMessageHistory({
client: zepClient,
sessionId,
memoryType: "perpetual",
}),
inputMessagesKey: "question",
historyMessagesKey: "history",
});

const result = await chainWithHistory.invoke(
{
question: "What did we talk about earlier?",
},
{
configurable: {
sessionId,
},
}
);

console.log("result", result);

API Reference:

ZepCloudChatMessageHistory + RunnableWithMessageHistory + ZepVectorStore(作为检索器)的使用方式

import { ZepClient } from "@getzep/zep-cloud";
import {
ChatPromptTemplate,
MessagesPlaceholder,
} from "@langchain/core/prompts";
import { ConsoleCallbackHandler } from "@langchain/core/tracers/console";
import { ChatOpenAI } from "@langchain/openai";
import { Document } from "@langchain/core/documents";
import {
RunnableLambda,
RunnableMap,
RunnablePassthrough,
RunnableWithMessageHistory,
} from "@langchain/core/runnables";
import { ZepCloudVectorStore } from "@langchain/community/vectorstores/zep_cloud";
import { StringOutputParser } from "@langchain/core/output_parsers";
import { ZepCloudChatMessageHistory } from "@langchain/community/stores/message/zep_cloud";

interface ChainInput {
question: string;
sessionId: string;
}

async function combineDocuments(docs: Document[], documentSeparator = "\n\n") {
const docStrings: string[] = await Promise.all(
docs.map((doc) => doc.pageContent)
);
return docStrings.join(documentSeparator);
}

// Your Zep Session ID.
const sessionId = "<Zep Session ID>";

const collectionName = "<Zep Collection Name>";

const zepClient = new ZepClient({
// Your Zep Cloud Project API key https://help.getzep.com/projects
apiKey: "<Zep Api Key>",
});

const vectorStore = await ZepCloudVectorStore.init({
client: zepClient,
collectionName,
});

const prompt = ChatPromptTemplate.fromMessages([
[
"system",
`Answer the question based only on the following context and conversation history: {context}`,
],
new MessagesPlaceholder("history"),
["human", "{question}"],
]);

const model = new ChatOpenAI({
temperature: 0.8,
model: "gpt-3.5-turbo-1106",
});
const retriever = vectorStore.asRetriever();
const searchQuery = new RunnableLambda({
func: async (input: any) => {
// You can use zep to synthesize a question based on the user input and session context.
// It can be useful because sometimes the user will type something like "yes" or "ok", which is not very useful for vector store retrieval.
const { question } = await zepClient.memory.synthesizeQuestion(
input.session_id
);
console.log("Synthesized question: ", question);
return question;
},
});
const retrieverLambda = new RunnableLambda({
func: async (question: string) => {
const response = await retriever.invoke(question);
return combineDocuments(response);
},
});
const setupAndRetrieval = RunnableMap.from({
context: searchQuery.pipe(retrieverLambda),
question: (x: any) => x.question,
history: (x: any) => x.history,
});
const outputParser = new StringOutputParser();

const ragChain = setupAndRetrieval.pipe(prompt).pipe(model).pipe(outputParser);

const invokeChain = (chainInput: ChainInput) => {
const chainWithHistory = new RunnableWithMessageHistory({
runnable: RunnablePassthrough.assign({
session_id: () => chainInput.sessionId,
}).pipe(ragChain),
getMessageHistory: (sessionId) =>
new ZepCloudChatMessageHistory({
client: zepClient,
sessionId,
memoryType: "perpetual",
}),
inputMessagesKey: "question",
historyMessagesKey: "history",
});

return chainWithHistory.invoke(
{ question: chainInput.question },
{
configurable: {
sessionId: chainInput.sessionId,
},
}
);
};

const chain = new RunnableLambda({
func: invokeChain,
}).withConfig({
callbacks: [new ConsoleCallbackHandler()],
});

const result = await chain.invoke({
question: "Project Gutenberg",
sessionId,
});

console.log("result", result);

API Reference:

Memory 使用方式

import { ChatOpenAI } from "@langchain/openai";
import { ConversationChain } from "langchain/chains";
import { ZepCloudMemory } from "@langchain/community/memory/zep_cloud";
import { randomUUID } from "crypto";

const sessionId = randomUUID(); // This should be unique for each user or each user's session.

const memory = new ZepCloudMemory({
sessionId,
// Your Zep Cloud Project API key https://help.getzep.com/projects
apiKey: "<Zep Api Key>",
});

const model = new ChatOpenAI({
modelName: "gpt-3.5-turbo",
temperature: 0,
});

const chain = new ConversationChain({ llm: model, memory });
console.log("Memory Keys:", memory.memoryKeys);

const res1 = await chain.invoke({ input: "Hi! I'm Jim." });
console.log({ res1 });
/*
{
res1: {
text: "Hello Jim! It's nice to meet you. My name is AI. How may I assist you today?"
}
}
*/

const res2 = await chain.invoke({ input: "What did I just say my name was?" });
console.log({ res2 });

/*
{
res1: {
text: "You said your name was Jim."
}
}
*/
console.log("Session ID: ", sessionId);
console.log("Memory: ", await memory.loadMemoryVariables({}));

API Reference:


Was this page helpful?


You can also leave detailed feedback on GitHub.