Skip to main content

Firestore 聊天记录

¥Firestore Chat Memory

为了在聊天会话中实现更长期的持久化,你可以将支持聊天内存类(如 BufferMemory)的默认内存 chatHistory 替换为 Firestore。

¥For longer-term persistence across chat sessions, you can swap out the default in-memory chatHistory that backs chat memory classes like BufferMemory for a firestore.

设置

¥Setup

首先,在你的项目中安装 Firebase 管理包:

¥First, install the Firebase admin package in your project:

npm install firebase-admin
npm install @langchain/openai @langchain/community @langchain/core

从你的 Firebase 项目中访问 Project Settings 页面,然后选择“Service accounts”选项卡。

¥Visit the Project Settings page from your Firebase project and select the Service accounts tab.

Service accounts 选项卡中,点击 Firebase Admin SDK 部分内的 Generate new private key 按钮,下载包含服务账户凭据的 JSON 文件。

¥Inside the Service accounts tab, click the Generate new private key button inside the Firebase Admin SDK section to download a JSON file containing your service account's credentials.

使用下载的 JSON 文件,将 projectIdprivateKeyclientEmail 传递给 FirestoreChatMessageHistory 类的 config 对象,如下所示:

¥Using the downloaded JSON file, pass in the projectId, privateKey, and clientEmail to the config object of the FirestoreChatMessageHistory class, like shown below:

import { FirestoreChatMessageHistory } from "@langchain/community/stores/message/firestore";
import admin from "firebase-admin";

const messageHistory = new FirestoreChatMessageHistory({
collections: ["chats"],
docs: ["user-id"],
sessionId: "user-id",
userId: "a@example.com",
config: {
projectId: "YOUR-PROJECT-ID",
credential: admin.credential.cert({
projectId: "YOUR-PROJECT-ID",
privateKey:
"-----BEGIN PRIVATE KEY-----\nCHANGE-ME\n-----END PRIVATE KEY-----\n",
clientEmail: "CHANGE-ME@CHANGE-ME-TOO.iam.gserviceaccount.com",
}),
},
});

这里,collections 字段应与数据库中 collections 的名称和顺序匹配。docs 也是如此,它应该与数据库中 docs 的名称和顺序匹配。

¥Here, the collections field should match the names and ordering of the collections in your database. The same goes for docs, it should match the names and ordering of the docs in your database.

用法

¥Usage

import { BufferMemory } from "langchain/memory";
import { FirestoreChatMessageHistory } from "@langchain/community/stores/message/firestore";
import { ChatOpenAI } from "@langchain/openai";
import { ConversationChain } from "langchain/chains";
import admin from "firebase-admin";

const memory = new BufferMemory({
chatHistory: new FirestoreChatMessageHistory({
collections: ["langchain"],
docs: ["lc-example"],
sessionId: "lc-example-id",
userId: "a@example.com",
config: {
projectId: "YOUR-PROJECT-ID",
credential: admin.credential.cert({
projectId: "YOUR-PROJECT-ID",
privateKey:
"-----BEGIN PRIVATE KEY-----\nnCHANGE-ME\n-----END PRIVATE KEY-----\n",
clientEmail: "CHANGE-ME@CHANGE-ME-TOO.iam.gserviceaccount.com",
}),
},
}),
});

const model = new ChatOpenAI();
const chain = new ConversationChain({ llm: model, memory });

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." } }
*/

API Reference:

嵌套集合

¥Nested Collections

FirestoreChatMessageHistory 类支持嵌套集合和动态集合/文档名称。

¥The FirestoreChatMessageHistory class supports nested collections, and dynamic collection/doc names.

以下示例展示了如何在具有以下结构的数据库中添加和检索消息:

¥The example below shows how to add and retrieve messages from a database with the following structure:

/chats/{chat-id}/bots/{bot-id}/messages/{message-id}
import { BufferMemory } from "langchain/memory";
import { FirestoreChatMessageHistory } from "@langchain/community/stores/message/firestore";
import { ChatOpenAI } from "@langchain/openai";
import { ConversationChain } from "langchain/chains";
import admin from "firebase-admin";

const memory = new BufferMemory({
chatHistory: new FirestoreChatMessageHistory({
collections: ["chats", "bots"],
docs: ["chat-id", "bot-id"],
sessionId: "user-id",
userId: "a@example.com",
config: {
projectId: "YOUR-PROJECT-ID",
credential: admin.credential.cert({
projectId: "YOUR-PROJECT-ID",
privateKey:
"-----BEGIN PRIVATE KEY-----\nnCHANGE-ME\n-----END PRIVATE KEY-----\n",
clientEmail: "CHANGE-ME@CHANGE-ME-TOO.iam.gserviceaccount.com",
}),
},
}),
});

const model = new ChatOpenAI();
const chain = new ConversationChain({ llm: model, memory });

const res1 = await chain.invoke({ input: "Hi! I'm Jim." });
console.log({ res1 });
/*
{ res1: { response: 'Hello Jim! How can I assist you today?' } }
*/

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

/*
{ res2: { response: 'You just said that your name is Jim.' } }
*/

API Reference:

Firestore 规则

¥Firestore Rules

如果你的集合名称为 "chathistory,",你可以按如下方式配置 Firestore 规则。

¥If your collection name is "chathistory," you can configure Firestore rules as follows.

      match /chathistory/{sessionId} {
allow read: if request.auth.uid == resource.data.createdBy;
allow write: if request.auth.uid == request.resource.data.createdBy;
}
match /chathistory/{sessionId}/messages/{messageId} {
allow read: if request.auth.uid == resource.data.createdBy;
allow write: if request.auth.uid == request.resource.data.createdBy;
}