前端 AI 对话历史存储与上下文回溯方案设计
在当前的大模型应用浪潮中,很多前端开发者切入 AI 领域的第一步往往是封装一个 ChatGPT 般的对话界面。起初,我们可能只是简单地将用户输入和 AI 回复 Push 到一个数组中,并在页面上渲染。然而,随着应用场景的深入,这种'玩具级'的架构很快就会面临严峻挑战。
背景:被忽视的'记忆'成本
很多前端同学在开发 AI 应用时,最容易踩的坑就是'只顾眼前交互,忽视持久化与上下文管理'。
痛点主要体现在三个方面:
- 数据脆弱性:用户不小心刷新页面,长达几十轮的深度对话瞬间灰飞烟灭。这种体验在 Web 端是致命的,用户无法接受自己的'思考过程'因误操作而丢失。
- 上下文窗口限制:大模型都有 Token 限制(如 GPT-3.5 的 4k,GPT-4 的 8k/32k)。如果前端只是无脑累加历史记录发给后端,很快就会报错
context_length_exceeded。前端必须具备'上下文回溯'与'裁剪'的能力。 - 多会话管理:现代 AI 应用往往是多会话并行的(类似 ChatGPT 左侧列表)。如何高效索引、切换、存储多个会话的历史记录,对前端的数据结构设计提出了要求。
这不仅是存储问题,更是架构设计问题。我们需要在前端构建一套轻量级但健壮的'记忆管理系统'。
核心内容:分层存储与滑动窗口策略
针对上述痛点,理性的解决方案应当包含两个核心维度:存储介质的选择与上下文窗口的管理策略。
1. 存储介质:IndexedDB 优于 localStorage
虽然 localStorage 简单易用,但在 AI 对话场景下,它并不合适。AI 对话产生的数据量增长迅速,且单条消息可能包含大段的代码或 Markdown 文本。localStorage 有 5MB 的大小限制,且是同步操作,容易阻塞 UI 线程。
推荐方案:IndexedDB。
IndexedDB 容量大(通常几百 MB 以上),支持异步操作,非常适合存储非结构化的对话数据。我们可以设计一张 conversations 表,以 sessionId 为主键,存储整个对话树。
2. 上下文管理:滑动窗口与摘要回溯
前端不能把所有历史记录都塞给 API。我们需要实现一个滑动窗口机制。
- 窗口大小:设定一个阈值(如最近 10 轮对话)。
- 系统提示词保留:System Prompt 必须始终保留在上下文头部。
- 远期记忆裁剪:超过窗口期的对话,前端可以选择截断,或者调用单独的 API 生成摘要,将摘要作为一条新的 Message 塞入上下文。
下面我们通过代码实战来落地这套方案。
实战代码:构建前端记忆管理器
我们将使用 TypeScript 定义一个 HistoryManager 类,结合 IndexedDB(模拟逻辑,实际生产推荐使用 Dexie.js 等库封装)和滑动窗口算法。
1. 数据模型定义
首先,明确我们的数据结构。不仅仅是消息数组,还要包含会话元信息。
// 定义单条消息结构
interface Message {
id: string;
role: 'user' | 'assistant' | 'system';
: ;
: ;
}
{
: ;
: ;
: [];
: ;
: ;
}

