本文将深入介绍如何在 FastAPI AI 聊天应用中实现用户历史消息功能,当用户切换助手,刷新页面时,都可以保留当前会话历史消息。
图片
本项目已经开源至 Github,项目地址:https://github.com/wayn111/fastapi-ai-chat-demo
温馨提示:本文全文约一万字,看完约需 15 分钟。
文章概述
重点讲解每个助手区分 sessionid、获取历史消息接口以及发送消息时携带上下文信息的核心技术实现。通过本教程,你将掌握构建智能聊天应用中消息持久化和上下文管理的关键技术。
核心功能
- 多助手会话隔离:每个 AI 助手(智能助手、AI 老师、编程专家)都有独立的会话历史
- 智能会话管理:自动生成和管理 sessionid,确保会话的唯一性和持久性
- 历史消息加载:快速加载和展示用户的历史对话记录
- 上下文传递:发送消息时自动携带历史上下文,保持对话连贯性
- 数据持久化:支持 Redis 和内存两种存储方式
技术栈
- 后端框架:FastAPI(高性能异步 Web 框架)
- 数据存储:Redis(主要)+ 内存存储(备用)
- 前端技术:原生 JavaScript + HTML5 + CSS3
- 数据格式:JSON(消息序列化和传输)
- 会话管理:UUID + 时间戳(会话 ID 生成)
核心架构设计
🏗️ 数据模型设计
在实现历史消息功能之前,我们需要设计合理的数据模型来存储和管理消息数据:
复制这个数据类定义了消息的基本结构,包含角色、内容、时间戳和可选的图片数据字段。
🔑 会话 ID 管理策略
会话 ID 是整个历史消息系统的核心,我们采用了前端生成、后端接收的管理策略:
前端会话 ID 生成逻辑:
复制后端键名管理:
复制前端生成唯一的会话 ID 并传递给后端,后端使用这个 ID 构建 Redis 键名来存储对话数据。
核心功能实现
🎯 功能一:每个助手区分 sessionid
前端实现:智能会话管理
在前端,我们为每个助手类型维护独立的 sessionid,实现真正的会话隔离:
复制这个函数负责切换助手时的会话管理,为每个助手类型维护独立的 sessionId,并从 localStorage 中获取或生成新的会话 ID。
后端实现:接收会话 ID 并管理数据
后端接收前端传来的会话 ID,通过 Redis 实现会话数据的持久化存储:
复制这个函数将消息保存到 Redis 或内存中,支持双重存储策略,并设置了消息数量限制和过期时间。
🔍 功能二:获取历史消息接口
后端 API 设计
我们设计了一个高效的历史消息获取接口:
复制前端历史消息加载
前端通过异步请求加载和渲染历史消息:
复制这个函数从后端获取指定助手的历史消息,并在前端进行渲染显示,支持文本和图片消息的完整展示。
💬 功能三:发送消息时携带上下文信息
后端流式对话实现
发送消息时,我们需要获取历史上下文并传递给 AI 模型:
1. 流式聊天接口
复制这个接口是流式聊天的入口点:
- 接收前端发送的 ChatRequest 对象,包含用户 ID、会话 ID、消息内容等
- 设置默认的 AI 角色为 "assistant",从请求中获取 AI 提供商和模型信息
- 验证 AI 角色是否在支持的角色列表中
- 返回 StreamingResponse 对象,设置 SSE(Server-Sent Events)相关的响应头
- 调用 generate_streaming_response 函数处理具体的流式响应逻辑
2. 流式响应生成函数
复制这个函数是流式响应的核心实现,主要包含以下步骤:
- 保存用户消息:将用户发送的消息(包括文本和图片)保存到 Redis 中
- 获取历史记录:根据用户 ID 和会话 ID 从 Redis 中获取完整的对话历史
- 构建系统提示:根据 AI 角色获取对应的系统提示词
- 构建消息列表:将历史消息转换为 AI 模型需要的格式
- 限制历史长度:只取最近的 N 条消息,避免上下文过长影响性能
- 调用 AI API:使用 AI 管理器调用指定提供商的流式 API
- 处理流式数据:逐块接收 AI 响应,实时推送给前端
- 数据过滤:从流式数据中提取纯文本内容,用于保存到数据库
- 实时推送:使用 yield 将数据块实时发送给前端
- 保存 AI 响应:将完整的 AI 回复保存到 Redis 中
- 发送结束信号:通知前端流式响应已完成
通过这种设计,实现了带有完整上下文的流式对话功能,用户可以看到 AI 的实时回复,同时所有对话记录都会被持久化保存。
总结
本教程通过前端会话 ID 管理、后端历史消息接口和流式对话上下文传递三个核心技术,实现了支持多助手切换和历史记录持久化的 AI 聊天应用。