LangChain 前端学习笔记:实现LLM的"记忆"能力

55 阅读13分钟

LangChain 前端学习笔记:实现LLM的"记忆"能力

在构建基于大语言模型的前端应用时,一个核心挑战是如何让LLM具备"记忆"能力,以实现连贯的多轮对话。传统LLM调用是无状态的,每次请求都独立处理,这在单次交互场景下是理想的,但在需要上下文连贯的对话系统中则成为主要障碍。本学习笔记将深入探讨LangChain框架中的Memory模块,展示如何在前端项目中实现LLM的记忆功能,包括对话历史记录的维护、状态管理机制以及不同记忆策略的适用场景。

一、LangChain框架概述

LangChain是一个用于构建大语言模型驱动应用程序的开源框架,它通过模块化设计简化了LLM应用的开发流程。LangChain的核心价值在于将不同组件(模型、提示模板、数据库、工具等)按顺序连接起来,形成一个可预测的、线性的工作流 。这种链式架构特别适合前端开发者,因为它提供了统一的API接口,允许快速切换不同LLM服务(如DeepSeek、OpenAI、通义千问等),同时通过Memory模块解决了多轮对话的记忆问题。

与传统的单次LLM调用不同,LangChain提供了一套完整的工具链,包括:

  • Models:封装各种LLM接口,提供统一调用方式
  • Prompts:管理提示模板,支持动态插入上下文信息
  • Chains:工作流编排,将多个组件连接成完整的处理流程
  • Memory:对话历史管理,实现LLM的"记忆"能力
  • Agents:智能体开发,让LLM能够自主选择工具完成任务

在前端应用中,LangChain的轻量化设计使其能够直接集成到浏览器或Deno环境中,无需依赖后端服务即可实现复杂AI功能。例如,通过LangChain.js库,前端开发者可以轻松创建带有记忆功能的对话链,为用户提供连贯的交互体验。

二、LLM的无状态特性与多轮会话需求矛盾

大语言模型(LLM)在本质上是无状态的,每次调用都只基于当前提供的输入生成响应。这种无状态设计虽然简化了模型调用流程,但在需要上下文连贯的多轮对话场景下造成了明显矛盾 。具体表现为:

// 直接调用LLM的无状态示例
import { ChatDeepSeek } from '@langchain/deepseek'

const model = new ChatDeepSeek({
    model: 'deepseek-chat',
    temperature: 0,
})

// 第一次调用
const res1 = await model.invoke('我叫张三')
console.log(res1.content) // 输出:"好的,张先生。有什么可以帮助您的?"

// 第二次调用
const res2 = await model.invoke('我叫什么名字')
console.log(res2.content) // 输出:"您还没有告诉我您的名字。"(无法记住前一次对话)

这种无状态行为在前端应用中尤为明显,因为用户期望与AI进行自然对话,而LLM的每次响应都应基于之前的交流内容。多轮会话需要模型能够理解并利用对话历史,而LLM本身并不具备这种能力,这就是我们需要LangChain Memory模块的原因。

LLM的无状态特性主要源于其技术实现方式:模型在生成过程中仅基于当前输入的token进行计算,缺乏显式的状态存储机制。虽然像ChatGPT这样的模型可以在同一会话接口内记录部分历史信息,但这种信息无法跨不同接口共享,也无法持久化存储。Prompting框架通过提供"Memory"系统,支持两种基本操作:读取和写入,从而为LLM添加记忆能力 。

三、Memory模块的实现原理

LangChain的Memory模块通过在Prompt模板中动态插入对话历史,让LLM能够基于上下文生成连贯的响应。其核心原理是将历史对话信息作为上下文传递给模型,使模型能够理解并参考之前的交流内容 。这一过程主要通过以下组件实现:

  1. Prompt模板:使用MessagesPlaceholder在Prompt中预留历史记录位置
  2. ChatMessageHistory:存储对话历史的具体实现,负责消息的添加和检索
  3. RunnableWithMessageHistory:封装组件,自动处理记忆的加载和存储

具体工作流程如下:

  • 当用户发起对话时,RunnableWithMessageHistory根据session_id加载对应的对话历史
  • 将历史记录通过history_messages_key插入到Prompt模板的{history}占位符中
  • 调用LLM生成响应
  • 将新消息(用户输入和LLM响应)通过save_context()方法保存到对话历史中

这种机制实现了对话历史的自动管理和传递,使前端开发者无需手动处理复杂的上下文拼接和存储逻辑 。以下是Memory模块在前端应用中的基本配置:

import {
    ChatDeepSeek,
    ChatPromptTemplate,
    MessagesPlaceholder
} from '@langchain/core'
import {
    InMemoryChatMessageHistory,
    RunnableWithMessageHistory
} from '@langchain/core/runnables'

// 1. 定义模型
const model = new ChatDeepSeek({
    model: 'deepseek-chat',
    temperature: 0,
})

// 2. 创建提示模板,包含历史占位符
const prompt = ChatPromptTemplate.fromMessages([
    ['system', '你是一个有记忆的助手,能够记住之前的对话内容'],
    new MessagesPlaceholder('history'), // 历史记录占位符
    ['human', '{input}'] // 当前用户输入
])

// 3. 创建链
const chain = prompt
    .pipe(model)

// 4. 配置记忆管理
const messageHistory = new InMemoryChatMessageHistory()

// 5. 创建带有记忆的可运行对象
const withMemoryChain = new RunnableWithMessageHistory({
   Runnable: chain,
   .getMessageHistory: () => messageHistory,
    inputMessagesKey: 'input',
    historyMessagesKey: 'history',
})

在这个配置中,RunnableWithMessageHistory包装了基础链,自动处理对话历史的加载和存储。每次调用withMemoryChain.invoke()时,它会从messageHistory中获取历史记录,将其插入到Prompt模板中,然后调用模型生成响应,并将新消息自动保存到历史记录中。

四、前端项目集成LangChain Memory的分步指南

在前端项目中集成LangChain的Memory功能,可以按照以下步骤进行:

步骤1:环境配置与依赖安装

首先,确保项目已经安装了必要的LangChain依赖。对于React项目,可以通过npm安装:

npm install @langchain/core @langchain/deepseek

如果使用Deno,可以通过导入URL直接获取:

import { ChatDeepSeek } from "https://deno.land/x@langchain/deepseek@1.0.0/mod.js"

步骤2:初始化Memory对象

根据应用需求选择合适的Memory实现。对于简单的单用户会话,可以使用InMemoryChatMessageHistory;对于需要持久化的场景,可以使用LSChatMessageHistory(基于localStorage) :

// 内存存储(会话期间有效)
import { InMemoryChatMessageHistory } from '@langchain/core/chat_history'

const messageHistory = new InMemoryChatMessageHistory()

// 本地存储(持久化,适合单用户)
import { LSChatMessageHistory } from '@langchain/core/chat_history'

const lsMessageHistory = new LSChatMessageHistory({
    key: 'my-conversation-history' // 存储在localStorage的键名
})

步骤3:创建带记忆的Prompt模板

使用ChatPromptTemplate创建包含历史占位符的Prompt模板:

import {
    ChatPromptTemplate,
    MessagesPlaceholder
} from '@langchain/core/prompts'

const prompt = ChatPromptTemplate.fromMessages([
    ['system', '你是一个有记忆的助手,能够记住之前的对话内容'],
    new MessagesPlaceholder('history'), // 历史记录占位符
    ['human', '{input}'] // 当前用户输入
])

系统提示词可以自定义,但需要明确告知LLM它应该参考历史对话内容。MessagesPlaceholder是关键组件,它会在每次调用时动态插入历史记录。

步骤4:构建并包装链

将Prompt模板与LLM模型连接成链,然后使用RunnableWithMessageHistory包装,添加记忆功能:

import { ChatDeepSeek } from '@langchain/deepseek'
import {
    RunnableWithMessageHistory
} from '@langchain/core/runnables'

// 1. 定义模型
const model = new ChatDeepSeek({
    model: 'deepseek-chat',
    temperature: 0,
})

// 2. 构建基础链
const chain = prompt
    .pipe(model)

// 3. 创建带有记忆的可运行对象
const withMemoryChain = new RunnableWithMessageHistory({
    Runnable: chain,
   .getMessageHistory: () => lsMessageHistory, // 使用本地存储
    inputMessagesKey: 'input',
    historyMessagesKey: 'history',
})

这里的关键是RunnableWithMessageHistory的配置参数:

  • Runnable:被包装的基础链
  • getMessageHistory:返回ChatMessageHistory对象的函数
  • inputMessagesKey:指定输入中的消息键(对应Prompt中的{input})
  • historyMessagesKey:指定历史消息的占位符键(对应Prompt中的{history})

步骤5:集成到前端UI

将记忆功能集成到前端UI组件中,例如React组件:

import React, { useState, useEffect } from 'react'
import {
    LSChatMessageHistory,
    ChatPromptTemplate,
    MessagesPlaceholder
} from '@langchain/core'
import {
    ChatDeepSeek,
    RunnableWithMessageHistory
} from '@langchain/core/runnables'

function ChatComponent() {
    const [input, setInput] = useState('')
    const [messages, setMessages] = useState([])

    // 初始化本地存储的记忆
    const messageHistory = new LSChatMessageHistory({
        key: 'my-conversation-history'
    })

    // 构建带记忆的链
    const prompt = ChatPromptTemplate.fromMessages([
        ['system', '你是一个有记忆的助手,能够记住之前的对话内容'],
        new MessagesPlaceholder('history'),
        ['human', '{input}']
    ])

    const model = new ChatDeepSeek({
        model: 'deepseek-chat',
        temperature: 0,
    })

    const chain = prompt
        .pipe(model)

    const withMemoryChain = new RunnableWithMessageHistory({
        Runnable: chain,
       .getMessageHistory: () => messageHistory,
        inputMessagesKey: 'input',
        historyMessagesKey: 'history',
    })

    // 发送消息
    const handleSubmit = async (e) => {
        e.preventDefault()

        // 保存用户输入到历史记录
        messageHistory.add_messages([
            { role: 'user', content: input },
        ])

        // 调用链
        try {
            const response = await withMemoryChain.invoke({
                input: input,
            })

            // 更新消息列表
            setMessages(prev => [
                ...prev,
                { role: 'user', content: input },
                { role: 'assistant', content: response.content },
            ])

            // 清空输入框
            setInput('')
        } catch (error) {
            console.error('Error invoking chain:', error)
            // 显示错误信息
            setMessages(prev => [
                ...prev,
                { role: 'error', content: 'AI响应失败,请稍后再试' },
            ])
        }
    }

    useEffect(() => {
        // 加载历史记录
        const loadHistory = async () => {
            const history = await messageHistory.get_messages()
            setMessages(history)
        }

        loadHistory()
    }, [])

    return (
        <div className="chat-container">
            <div className="messages">
                {messages.map((msg, index) => (
                    <div
                        key={index}
                        className={`message ${msg.role === 'user' ? 'user' : 'assistant'}`}
                    >
                        <p>{msg.content}</p>
                    </div>
                ))}
            </div>

            <form onSubmit={handleSubmit} className="input-form">
                <input
                    type="text"
                    value={input}
                    onChange={(e) => setInput(e.target.value)}
                    placeholder="请输入消息..."
                />
                <button type="submit">发送</button>
            </form>
        </div>
    )
}

export default ChatComponent

这个React组件实现了完整的多轮对话功能:

  • 使用LSChatMessageHistory存储对话历史到localStorage
  • 通过useEffect在组件挂载时加载历史记录
  • 提交表单时调用带记忆的链
  • 自动将新消息添加到历史记录和UI显示

这种实现方式使前端开发者能够轻松构建具有记忆能力的对话应用,无需手动处理复杂的上下文拼接和存储逻辑

五、不同Memory策略的优缺点与适用场景

LangChain提供了多种Memory策略,每种策略在实现方式、性能和适用场景上都有所不同。以下是主要Memory策略的对比:

策略类型存储方式Token管理持久化多用户支持适用场景
InMemoryChatMessageHistory内存无自动限制会话期间有效通过session_id实现临时会话、单次对话
LSChatMessageHistorylocalStorage可配置浏览器持久化通过session_id实现单用户前端应用、需要持久化
FileChatMessageHistory文件系统可配置持久化通过文件名实现本地应用、命令行工具
SQLiteChatMessageHistory数据库可配置持久化原生支持多用户Web应用、需要结构化存储
SummaryMemory内存/存储自动压缩可选通过session_id实现长对话、需要减少token
VectorStoreRetrieverMemory向量数据库语义检索持久化原生支持大量历史数据、需要相关性检索

选择合适的Memory策略取决于应用的具体需求。例如,对于简单的单用户前端聊天应用,LSChatMessageHistory是最合适的,因为它提供了浏览器级别的持久化存储,同时不需要额外的服务器或数据库。对于需要处理大量历史数据或需要长期记忆的应用,可以考虑VectorStoreRetrieverMemory,它通过向量数据库存储历史记录,并在每次对话时检索最相关的上下文。

以下是几种常用Memory策略的详细说明:

1. LSChatMessageHistory(localStorage存储)

这是最适合前端单用户应用的Memory策略,它将对话历史存储在浏览器的localStorage中:

import { LSChatMessageHistory } from '@langchain/core/chat_history'

const messageHistory = new LSChatMessageHistory({
    key: 'my-conversation-history', // 存储在localStorage的键名
    maxTokenLimit: 4096 // 可选:限制总token数
})

优点

  • 无需服务器或数据库
  • 数据在浏览器中持久化
  • 实现简单,适合前端单用户应用

缺点

  • 无法跨设备同步
  • 数据量受限于localStorage大小
  • 不支持多用户场景

2. SQLiteChatMessageHistory(数据库存储)

对于需要多用户支持或结构化存储的前端应用,可以使用SQLiteChatMessageHistory,它将对话历史存储在SQLite数据库中:

import { SQLiteChatMessageHistory } from '@langchain/core/chat_history'

const messageHistory = new SQLiteChatMessageHistory({
    dbPath: 'chat_history.db', // 数据库文件路径
    session_id: 'user-123' // 用户唯一标识
})

优点

  • 支持多用户隔离
  • 数据持久化且可跨会话使用
  • 支持复杂查询和管理

缺点

  • 需要处理数据库连接和路径
  • 增加系统复杂度
  • 在浏览器中使用时可能需要WebSQL或 indexedDB

3. SummaryMemory(对话摘要)

对于需要处理长对话的应用,可以使用SummaryMemory,它会自动将对话历史压缩为摘要:

import { SummaryMemory } from '@langchain/core/memories'

const memory = new SummaryMemory({
    memory_key: 'history',
    return messages: true
})

const withMemoryChain = new RunnableWithMessageHistory({
    Runnable: chain,
   .getMessageHistory: () => memory,
    inputMessagesKey: 'input',
    historyMessagesKey: 'history',
})

优点

  • 自动压缩历史信息,减少token消耗
  • 保持对话上下文的连贯性
  • 适合长对话场景

缺点

  • 摘要可能丢失细节信息
  • 增加额外计算开销
  • 需要额外配置

4. VectorStoreRetrieverMemory(向量检索增强)

对于需要处理大量历史数据或需要相关性检索的应用,可以使用VectorStoreRetrieverMemory,它结合向量数据库存储和检索历史记录:

import { VectorStoreRetrieverMemory } from '@langchain/core/memories'
import { FAISS } from '@langchain/core/stores'

// 初始化向量存储
const store = new FAISS()

// 创建检索增强的记忆
const memory = new VectorStoreRetrieverMemory({
    store: store,
    memory_key: 'history',
    return_messages: true,
    k: 3 // 检索最相关的3条记录
})

const withMemoryChain = new RunnableWithMessageHistory({
    Runnable: chain,
   .getMessageHistory: () => memory,
    inputMessagesKey: 'input',
    historyMessagesKey: 'history',
})

优点

  • 通过语义检索选择相关历史片段
  • 适合处理大量非结构化历史数据
  • 可结合RAG技术增强知识检索能力

缺点

  • 依赖向量数据库部署,增加系统复杂度
  • 检索延迟可能影响实时性
  • 需要额外处理向量存储

六、优化记忆功能的实践技巧

在前端项目中实现LLM记忆功能时,以下实践技巧可以帮助优化性能和用户体验:

1. 限制历史记录长度

为了避免token消耗过大,可以限制历史记录的长度。例如,使用ConversationalTokenBufferMemory基于token数动态截断历史:

import { conversationalTokenBufferMemory } from '@langchain/core/memories'

const memory = conversationalTokenBufferMemory({
    maxTokenLimit: 4096, // 最大token限制
    llm: model, // 用于计算token的模型
    return_messages: true
})

这种策略会在每次对话时自动计算token数,保留最新的对话内容,直到达到最大限制。这对于需要处理长对话但受限于模型上下文窗口的应用非常有用。

2. 使用会话ID隔离不同用户

在多用户场景中,确保每个用户的对话历史独立存储至关重要。可以通过session_id参数实现:

// 创建带会话ID的记忆
const messageHistory = new LSChatMessageHistory({
    key: `chat-history-${userId}`, // 使用用户ID作为键名
    maxTokenLimit: 4096
})

// 调用链时传递会话ID
const response = await withMemoryChain.invoke({
    input: input,
}, {
    configurable: {
        session_id: userId // 绑定用户ID
    }
})

通过会话ID可以确保不同用户之间的对话历史不会互相干扰,同时也能实现同一用户的跨会话记忆

3. 结合RAG技术增强知识记忆

对于需要长期记忆或特定领域知识的应用,可以结合RAG(检索增强生成)技术:

import { VectorStoreRetrieverMemory } from '@langchain/core/memories'
import { FAISS } from '@langchain/core/stores'
import {Embeddings} from '@langchain/core'

// 初始化向量存储
const embeddings = new OpenAIEmbeddings()
const store = new FAISS(embeddings)

// 创建检索增强的记忆
const memory = new VectorStoreRetrieverMemory({
    store: store,
    memory_key: 'history',
    return_messages: true,
    k: 3 // 检索最相关的3条记录
})

// 构建带记忆的链
const withMemoryChain = new RunnableWithMessageHistory({
    Runnable: chain,
   .getMessageHistory: () => memory,
    inputMessagesKey: 'input',
    historyMessagesKey: 'history',
})

RAG技术通过向量数据库存储和检索相关信息,可以显著增强LLM的记忆能力,尤其适合需要长期记忆或特定领域知识的应用

4. 实现对话历史的可视化

在前端应用中,实现对话历史的可视化可以提升用户体验。可以通过React或Vue组件展示消息列表:

// React对话历史组件
function MessageList({ messages }) {
    return (
        <div className="messages">
            {messages.map((msg, index) => (
                <div
                    key={index}
                    className={`message ${msg.role === 'user' ? 'user' : 'assistant'}`}
                >
                    <p>{msg.content}</p>
                </div>
            ))}
        </div>
    )
}

// Vue对话历史组件
<template>
    <div class="messages">
        <div v-for="(msg, index) in messages" :key="index"
             class=`message ${msg.role === 'user' ? 'user' : 'assistant'}`}>
            <p>{{ msg.content }}</p>
        </div>
    </div>
</template>

通过可视化对话历史,用户可以清晰地看到之前的交流内容,增强对话的连贯性和可追溯性

七、实际应用案例分析

案例1:个性化客服助手

一个实际应用场景是构建带有记忆功能的个性化客服助手,能够记住用户的偏好和历史问题:

import { LSChatMessageHistory } from '@langchain/core/chat_history'
import { RunnableWithMessageHistory } from '@langchain/core/runnables'
import { ChatPromptTemplate, MessagesPlaceholder } from '@langchain/core/prompts'
import { ChatDeepSeek } from '@langchain/deepseek'

// 1. 定义记忆
const messageHistory = new LSChatMessageHistory({
    key: `customer-service history`,
    maxTokenLimit: 4096
})

// 2. 创建提示模板
const prompt = ChatPromptTemplate.fromMessages([
    ['system', '你是一个客服助手,能够记住之前的对话内容,提供个性化服务'],
    new MessagesPlaceholder('history'),
    ['human', '{input}']
])

// 3. 定义模型
const model = new ChatDeepSeek({
    model: 'deepseek-chat',
    temperature: 0.3,
})

// 4. 构建链
const chain = prompt
    .pipe(model)

// 5. 创建带记忆的可运行对象
const withMemoryChain = new RunnableWithMessageHistory({
    Runnable: chain,
   .getMessageHistory: () => messageHistory,
    inputMessagesKey: 'input',
    historyMessagesKey: 'history',
})

这个案例展示了如何通过记忆功能为客服助手添加个性化服务能力,提高用户体验和满意度

案例2:多轮问答教育应用

另一个应用场景是教育领域的多轮问答应用,能够记住学生的知识掌握情况并提供针对性指导:

import { LSChatMessageHistory } from '@langchain/core/chat_history'
import { RunnableWithMessageHistory } from '@langchain/core/runnables'
import { ChatPromptTemplate, MessagesPlaceholder } from '@langchain/core/prompts'
import { ChatDeepSeek } from '@langchain/deepseek'

// 1. 定义记忆
const messageHistory = new LSChatMessageHistory({
    key: `learning-path history`,
    maxTokenLimit: 8192
})

// 2. 创建提示模板
const prompt = ChatPromptTemplate.fromMessages([
    ['system', '你是一个学习助手,能够记住之前的对话内容,提供个性化学习路径'],
    new MessagesPlaceholder('history'),
    ['human', '{input}']
])

// 3. 定义模型
const model = new ChatDeepSeek({
    model: 'deepseek-chat',
    temperature: 0.5,
})

// 4. 构建链
const chain = prompt
    .pipe(model)

// 5. 创建带记忆的可运行对象
const withMemoryChain = new RunnableWithMessageHistory({
    Runnable: chain,
   .getMessageHistory: () => messageHistory,
    inputMessagesKey: 'input',
    historyMessagesKey: 'history',
})

这个案例展示了如何通过记忆功能构建教育领域的个性化学习助手,根据学生的历史互动提供更有针对性的指导

八、常见问题与解决方案

问题1:对话历史超过模型上下文限制

解决方案:使用ConversationalTokenBufferMemorySummaryMemory策略,自动限制历史记录的token数量或压缩历史信息 :

import { conversationalTokenBufferMemory } from '@langchain/core/memories'

const memory = conversationalTokenBufferMemory({
    maxTokenLimit: 4096, // 最大token限制
    llm: model, // 用于计算token的模型
    return_messages: true
})

问题2:多用户场景下的对话历史混淆

解决方案:使用会话ID参数隔离不同用户的历史记录 :

// 创建带会话ID的记忆
const messageHistory = new LSChatMessageHistory({
    key: `chat-history-${userId}`, // 使用用户ID作为键名
    maxTokenLimit: 4096
})

// 调用链时传递会话ID
const response = await withMemoryChain.invoke({
    input: input,
}, {
    configurable: {
        session_id: userId // 绑定用户ID
    }
})

问题3:浏览器环境下的数据持久化

解决方案:使用LSChatMessageHistoryIndexedDBChatMessageHistory实现浏览器级别的持久化存储 :

import { LSChatMessageHistory } from '@langchain/core/chat_history'

const messageHistory = new LSChatMessageHistory({
    key: 'my-conversation-history',
    maxTokenLimit: 4096
})

问题4:对话历史的初始化与清理

解决方案:使用clear()方法清理对话历史,或在特定条件下初始化新的会话 :

// 清理当前会话的历史
await messageHistory.clear()

// 初始化新会话(通过新会话ID)
const newMessageHistory = new LSChatMessageHistory({
    key: `chat-history-${newUserId}`,
    maxTokenLimit: 4096
})

九、未来发展趋势与展望

随着大语言模型技术的不断发展,LLM的记忆能力也在持续改进。未来,我们可以期待以下发展趋势:

1. 更高效的记忆压缩技术

递归摘要等技术将使对话历史压缩更加高效 ,保留关键信息的同时大幅减少token消耗。例如,通过自动识别对话中的关键实体和关系,生成更精炼的摘要。

2. 跨平台记忆同步

未来的Memory策略可能会支持跨设备、跨平台的记忆同步,使用户能够在不同设备上继续之前的对话。这可能通过云存储或区块链技术实现,确保数据的安全性和一致性。

3. 混合记忆策略

结合多种记忆策略的混合方案将成为主流,例如同时使用短期内存(InMemoryChatMessageHistory)和长期存储(VectorStoreRetrieverMemory),根据对话的重要性和时效性动态管理记忆。

4. 更智能的上下文检索

未来的检索增强记忆(RAG)技术将更加智能,能够根据对话的上下文和意图动态调整检索参数,返回更相关的历史信息。这可能通过强化学习等技术实现,使检索过程更加自适应。

十、总结与最佳实践

通过LangChain的Memory模块,前端开发者可以轻松实现LLM的记忆能力,解决无状态模型与多轮会话需求之间的矛盾 。在实际应用中,应根据具体需求选择合适的Memory策略:

  • 对于简单的单用户前端应用,推荐使用LSChatMessageHistory,它提供了浏览器级别的持久化存储,实现简单且无需额外基础设施。
  • 对于需要多用户支持的Web应用,可以考虑SQLiteChatMessageHistory或结合会话ID的LSChatMessageHistory
  • 对于需要处理长对话的应用,建议使用ConversationalTokenBufferMemorySummaryMemory策略,自动限制历史记录的token数量。
  • 对于需要长期记忆或特定领域知识的应用,可以考虑结合RAG技术的VectorStoreRetrieverMemory策略 。

最佳实践是将Memory模块与前端UI组件紧密结合,实现对话历史的可视化和交互,同时通过会话ID参数确保不同用户之间的记忆隔离。对于需要处理大量历史数据的应用,可以考虑使用递归摘要等技术优化记忆管理,减少token消耗并提高响应速度。

通过合理配置和优化,LangChain的Memory模块可以使前端应用中的LLM具备强大的记忆能力,提供更加自然、连贯的对话体验,满足各种复杂场景的需求。