【AI大模型应用开发】【项目实战】24.RAG智慧问答项目-(十二)融合MySQL的RAG系统之基于 FastAPI 的 FAQ 与知识库查询接口
目标:理解如何基于FastAPI构建高效的问答系统 API 接口掌握WebSocket 流式输出和HTTP 接口的实现,优化用户交互体验前后端交互、前端静态文件服务以及日常问候处理的集成一、开发完RAG系统以后,怎么对外提供服务?对外:调用链路: 前端 - 后端 - RAG系统功能:前端和后端是已有的业务系统,比如电商系统增加一个售后机器人:前端和后端改造代码, RAG系统从0到1开发职责划分:前端和后端对应的人员进行维护开发, AI工程师只负责做RAG系统RAG系统专门作为一个单独的系统对外服务,前端、后端从0到1开发,RAG系统也是从0到1职责划分:AI工程师负责做RAG系统, 也有可能兼职做后端(小团队甚至要做前端),后端仍然需要权限验证、登录等功能二、查询流程图app.py是对new_main.py的进一步优化,基于 FastAPI 框架构建了RESTful API和WebSocket 接口,集成了 RAG 系统 和 RAG 系统,支持流式输出、对话历史管理和日常问候处理,同时,通过静态文件服务支持前端页面交互,适用于项目场景下的实时问答系统下面是基于 FastAPI 的问答系统查询流程图,展示从前端请求到后端响应的处理逻辑三、流程说明1.请求接收:前端通过HTTP POST (/api/query)或WebSocket (/api/stream)发送查询请求,包含查询内容 (query)、学科过滤 (source_filter)和会话 ID (session_id)2.日常问候处理:检查查询是否为日常问候(如“你好”),若匹配则返回模板化回复3.BM25 搜索:使用BM25 算法搜索MySQL 知识库,设置相似度阈值 0.854.答案判断:若找到可靠答案(相似度 0.85),通过HTTP 一次性返回或WebSocket 流式返回若无可靠答案且需要 RAG,HTTP 接口提示使用 WebSocket,WebSocket 接口流式返回 RAG 答案若无需 RAG,返回“未找到答案”5.历史更新:将查询和答案存入 MySQL 的conversations表,保留最近 5 轮对话6.响应输出:HTTP 返回 JSON 格式响应,WebSocket 流式发送 JSON 数据(包含start、token、end或error类型)四、代码介绍下面是app.py的完整代码,包含逐行注释,详细解析功能与实现逻辑实现步骤,准备工作创建 FastAPI 应用并配置构建一个FastAPI对象配置跨域初始化RAG系统配置问答模板,定义日常问答模式定义请求和响应的数据结构,给核心query接口使用request: query,source_filter, session_idResponse: answer,is_streaming, session_id ,processing_timeis_streaming代表返回的结果是批式还是流式的,如果是批式的,前端直接获取answer。如果是流式的,需要前端去构建websocket通道,接收流式输出的内容挂载静态文件,重定向: / 到静态文件中的前端页面历史对话操作创建历史对话查询历史消息清除历史消息1.导入必备的工具包# 导入 FastAPI 相关模块,用于构建 API 和 WebSocket from fastapi import FastAPI, WebSocket, HTTPException, Query, Depends # 导入 FastAPI 响应类型,用于流式响应和文件服务 from fastapi.responses import StreamingResponse, FileResponse # 导入 CORS 中间件,支持跨域请求 from fastapi.middleware.cors import CORSMiddleware # 导入静态文件服务模块 # 给前端使用 from fastapi.staticfiles import StaticFiles # 导入 WebSocket 断开异常 from starlette.websockets import WebSocketDisconnect # 导入系统操作模块,用于文件目录管理 import os # 导入 Pydantic 模型,用于请求验证 from pydantic import BaseModel # 导入异步事件循环模块 import asyncio # 导入 JSON 处理模块 import json # 导入 UUID 模块,生成唯一会话 ID import uuid # 导入类型注解模块 from typing import Optional, List, Dict, Any # 导入时间模块,记录处理时间 import time # 导入正则表达式模块,用于匹配日常问候 import re # 导入优化后的问答系统 from new_main import IntegratedQASystem from base.logger import single_logger as logger2.创建 FastAPI 应用并配置创建 FastAPI 实例并配置 CORS和静态文件服务功能:初始化 FastAPI 应用,允许跨域请求,挂载静态文件目录关键点:CORS 配置在生产环境中需限制域名,静态文件服务支持前端页面# 创建 FastAPI 应用实例,设置标题和描述 app = FastAPI(title="问答系统API", description="集成MySQL和RAG的智能问答系统") # 配置 CORS 中间件,允许跨域请求 app.add_middleware( CORSMiddleware, allow_origins=["*"], # 允许所有来源(生产环境需限制) allow_credentials=True, # 允许凭证 allow_methods=["*"], # 允许所有 HTTP 方法 allow_headers=["*"], # 允许所有头部 ) # 创建静态文件目录(如果不存在) os.makedirs("static", exist_ok=True) # 创建全局问答系统实例 qa_system = IntegratedQASystem()3. 定义日常问候模式定义问候语正则匹配模式和回复功能:快速响应常见问候,提升用户体验关键点:使用正则表达式匹配,支持大小写无关匹配# 定义日常问候用语模式和回复 GREETING_PATTERNS = [ { "pattern": r"^(你好|您好|hi|hello)", # 匹配问候语 "response": "你好!我是小爱同学,专注于答疑解惑,很高兴为你服务!" }, { "pattern": r"^(你是谁|您是谁|你叫什么|你的名字|who are you)", # 匹配身份询问 "response": "我是小爱同学,你的智能助手,致力于提供 各方面 内容相关的解答!" }, { "pattern": r"^(在吗|在不在|有人吗)", # 匹配在线确认 "response": "我在!我是小爱同学,随时为你解答问题!" }, { "pattern": r"^(干嘛呢|你在干嘛|做什么)", # 匹配状态询问 "response": "我正在待命,随时为你解答 互联网 相关的问题!有什么我可以帮你的?" } ]4.定义请求和响应模型使用Pydantic定义请求和响应数据结构功能:规范 API 输入和输出格式,确保数据验证关键点:支持可选字段,方便扩展# 定义查询请求模型 # TODO 相当于java中的注解 @RequestBody class QueryRequest(BaseModel): # TODO @Param(param = "query", nullable = false) query: str # 查询内容,必填 # TODO @Param(param = "query", nullable = true) subject_filter: Optional[str] = None # 学科过滤,可选 session_id: Optional[str] = None # 会话 ID,可选 # 定义查询响应模型 # TODO 相当于java中的注解 @ResponseBody class QueryResponse(BaseModel): answer: str # 答案内容 # TODO 这个bool值的意思是告诉前端,将要接受流式输出,需要建立一个websocket通道 is_streaming: bool # 是否流式响应 session_id: str # 会话 ID processing_time: float # 处理时间5.挂载静态文件服务挂载静态文件目录并设置根路径功能:服务前端 HTML 文件,支持交互页面关键点:根路径重定向到index.html# 挂载静态文件目录,服务前端文件 # TODO app.mount("/static" - 127.0.0.1/static app.mount("/static", StaticFiles(directory="static"),) # 根路径重定向到 index.html # TODO 127.0.0.1/static/index.html - 127.0.0.1/ @app.get("/") async def read_root(): return FileResponse("static/index.html")6.创建新会话/api/create_session接口功能:生成新的唯一会话 ID关键点:使用 UUID 确保唯一性# 创建新会话接口 # TODO 类似于java中的@PostMapping @app.post("/api/create_session") async def create_session(): session_id = str(uuid.uuid4()) # 生成唯一会话 ID return {"session_id": session_id} # 返回会话 ID7.查询历史消息/api/history/{session_id}接口功能:获取指定会话的历史记录关键点:异常处理确保接口健壮性# 查询历史消息接口 # TODO restful api 规范 。比如某厂规范:internal-api.xxxx.com/{业务线: driver/passanger}/{二级:运营、打车}/xxxx # TODO 对外的api(openapi) : /api/v1/edu-rag/history/{session_id} @app.get("/api/history/{session_id}") async def get_history(session_id: str): try: # 获取指定会话的历史记录 history = qa_system.get_session_history(session_id) # 返回会话 ID 和历史记录 # TODO 规范操作:{"data": {"session_id": session_id, "history": history} ,"errno":0,"errmsg":报错信息, "log_id":日志编号} return {"session_id": session_id, "history": history} except Exception as e: # 抛出 HTTP 异常,包含错误信息 raise HTTPException(status_code=500, detail=f"获取历史记录失败: {str(e)}")8.清除历史消息/api/history/{session_id}接口功能:删除指定会话的所有历史记录关键点:返回操作状态,异常处理确保健壮性# 清除历史消息接口 @app.delete("/api/history/{session_id}") async def clear_history(session_id: str): # 清除指定会话的历史记录 success = qa_system.clear_session_history(session_id) if success: # 返回成功状态 return {"status": "success", "message": "历史记录已清除"} else: # 抛出 HTTP 异常 raise HTTPException(status_code=500, detail="清除历史记录失败")9.检查日常问候check_greeting函数功能:检查查询是否匹配日常问候,返回模板化回复关键点:正则匹配支持大小写无关,简化交互逻辑# 检查是否为日常问候用语并返回模板回复 def check_greeting(query: str) - Optional[str]: query_text = query.strip() # 去除首尾空格 for pattern_info in GREETING_PATTERNS: # 使用正则匹配,忽略大小写 if re.match(pattern_info["pattern"], query_text, re.IGNORECASE): return pattern_info["response"] # 返回匹配的回复 return None # 无匹配返回 None10.非流式查询接口/api/query接口功能:处理非流式查询,支持 MySQL 答案和日常问候,提示使用 WebSocket 获取 RAG 流式答案关键点:返回 JSON 格式响应,记录处理时间后端代码:# 非流式查询接口 @app.post("/api/query") async def query(request: QueryRequest): """ 用户输入的query,前端先去调用当前接口根据返回值的is_streaming字段决定是否输出答案,还是调用websocket接收流式输出 :param request: :return: """ start_time = time.time() # 记录开始时间 # 使用请求中的 session_id 或生成新 ID session_id = request.session_id or str(uuid.uuid4()) # 检查是否为日常问候 greeting_response = check_greeting(request.query) if greeting_response: # 返回问候回复 return { "answer": greeting_response, "is_streaming": False, "session_id": session_id, "processing_time": time.time() - start_time } # 执行 BM25 搜索 answer, need_rag = qa_system.faq.search(request.query, threshold=0.85) if need_rag: # 需要 RAG,提示使用 WebSocket return { "answer": "请使用WebSocket接口获取流式响应", "is_streaming": True, "session_id": session_id, "processing_time": time.time() - start_time } # 返回 MySQL 答案 return { "answer": answer, "is_streaming": False, "session_id": session_id, "processing_time": time.time() - start_time }前端调用代码:// 接收消息时 socket.onmessage = function(event) { const data = JSON.parse(event.data); switch (data.type) { case 'start': console.log('流式响应开始'); break; case 'token': // 追加 token 到内容 accumulatedContent += data.token; // 使用 marked.js 解析 Markdown 格式 contentElement.innerHTML = marked.parse(accumulatedContent); scrollToBottom(); break; case 'end': console.log('流式响应结束'); socket.close(); resolve(); break; case 'error': console.error('流式响应错误:', data.error);

相关新闻

Arduino Leonardo做的双旋钮+十四键音游控制器,即插即用支持多平台

Arduino Leonardo做的双旋钮+十四键音游控制器,即插即用支持多平台

本文还有配套的精品资源,点击获取 简介:用Arduino Leonardo打造的音乐游戏专用外设,自带两个带按压功能的高精度旋转编码器和十四颗独立按键,所有输入都可自由映射。设备通过标准HID协议通信,Windows/macOS/Linux系…

2026/7/24 7:28:17 阅读更多 →
基于SpringBoot的社区优选商城(Java+SpringBoot+MySQL)| 计算机毕业设计 附源码论文PPT

基于SpringBoot的社区优选商城(Java+SpringBoot+MySQL)| 计算机毕业设计 附源码论文PPT

本项目为计算机本科毕业设计,采用 Java Spring Boot 作为后端框架,Vue.js 作为前端框架,数据库使用 MySQL。系统涵盖用户管理、商家管理、商品管理、订单管理、客服聊天管理、论坛管理、商品资讯管理、购物车等八大功能模块。配套材料包括论…

2026/7/24 4:11:45 阅读更多 →
皮肤癌良恶性图像二分类数据集:含训练验证划分、类别映射文件与一键可视化脚本

皮肤癌良恶性图像二分类数据集:含训练验证划分、类别映射文件与一键可视化脚本

本文还有配套的精品资源,点击获取 简介:专为皮肤癌二分类任务准备的医学图像数据集,包含2637张训练图和660张测试图,按良性、恶性两类独立存放于train/test子目录中,开箱即用,无需重命名或移动文件。所有…

2026/7/24 2:11:06 阅读更多 →

最新新闻

嵌入式I2C总线DMA触发机制详解与寄存器配置实战

嵌入式I2C总线DMA触发机制详解与寄存器配置实战

1. I2C DMA触发机制深度解析 在嵌入式系统开发中,I2C总线因其简洁的两线制(SCL和SDA)和主从架构,被广泛应用于连接各类传感器、EEPROM和显示模块。然而,当需要处理大量数据时,传统的轮询或中断方式会大量占…

2026/7/24 8:17:44 阅读更多 →
Metasploit与Wireshark联动安装与实战:从环境搭建到流量分析

Metasploit与Wireshark联动安装与实战:从环境搭建到流量分析

1. 项目概述:为什么需要Metasploit与Wireshark这对“黄金搭档”? 如果你对网络安全、渗透测试或者仅仅是好奇网络流量背后的秘密感兴趣,那么Metasploit和Wireshark这两个名字你一定不陌生。它们就像是网络世界里的“矛”与“盾”,…

2026/7/24 8:17:44 阅读更多 →
YOLOv8目标检测中Focal EIoU损失函数的原理与实践

YOLOv8目标检测中Focal EIoU损失函数的原理与实践

1. 项目背景与核心价值 在目标检测领域,YOLOv8作为当前最先进的实时检测框架之一,其性能表现很大程度上依赖于损失函数的设计。传统IoU系列损失函数(如CIoU、DIoU)虽然已经取得不错效果,但在处理极端长宽比目标或密集小…

2026/7/24 8:17:44 阅读更多 →
大模型实战:六大高价值应用场景与落地指南

大模型实战:六大高价值应用场景与落地指南

1. 大模型实战的价值与挑战大模型技术正在深刻改变各行各业的工作方式。根据实际项目经验,合理应用大模型确实可以在特定场景下减少80%以上的重复性工作。但实现这一目标需要克服三个关键挑战:场景选择:不是所有工作都适合用大模型优化&#…

2026/7/24 8:17:44 阅读更多 →
海外华人网购痛点攻克:独立站跨境包裹合并转运系统实践分享

海外华人网购痛点攻克:独立站跨境包裹合并转运系统实践分享

随着反向海淘行业持续升温,海外华人、留学生、驻外工作人群已成为国内国货消费的核心主力群体。从中式零食、调味食材、国风文创,到适配国内标准的小家电、家居用品,海量高性价比国货通过反向海淘流向全球各地。但相较于成熟的正向跨境电商&a…

2026/7/24 8:17:44 阅读更多 →
深入解析UCD90320 PMBus制造商特定命令:故障管理与系统监控实战

深入解析UCD90320 PMBus制造商特定命令:故障管理与系统监控实战

1. 项目概述:深入UCD90320的PMBus“后花园” 在数字电源管理的世界里,PMBus协议就像一本通用词典,它定义了如何读取电压、电流、温度,以及如何开关电源轨。但当你面对像TI UCD90320这样功能强大的序列发生器与系统健康控制器时&am…

2026/7/24 8:16:44 阅读更多 →

日新闻

用Highcharts 创建可拖拽三维散点立方体3D图表

用Highcharts 创建可拖拽三维散点立方体3D图表

该案例基于Highcharts scatter3d 三维散点图实现空间立方体散点可视化,核心特色:三维 X/Y/Z 三轴空间,所有散点分布在 0~10 立方体空间内;散点使用径向渐变实现立体 3D 圆球质感;支持鼠标 / 触屏拖拽画布,…

2026/7/24 0:00:29 阅读更多 →
AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口 AppCertDlls 位于 HKLM\System\CurrentControlSet\Control\Session Manager\AppCertDlls。本文的程序功能是只读列出这个键在 64 位和 32 位注册表视图中的全部值,并显示每条值的来源、名称、类型和可安全显示的数…

2026/7/24 0:00:29 阅读更多 →
我的编程之路:第一篇博客

我的编程之路:第一篇博客

大家好,我是一名编程初学者,同时这也是我编程学习之路上的第一篇博客。在这里,我想要向大家介绍我的一些想法和规划。a.自我介绍我是一个刚刚接触编程的新手,目前在学习c语言,我对编程世界充满了强烈的好奇。当然&…

2026/7/24 0:00:29 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/24 3:59:20 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/24 1:23:39 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 17:49:47 阅读更多 →

月新闻