
1. 项目背景与核心价值最近在做一个很有意思的项目——基于RAG技术的健康知识问答系统。这个项目的初衷很简单现在大语言模型虽然很火但在专业领域比如医疗健康经常会出现一本正经胡说八道的情况。想象一下如果你问AI感冒了吃什么药好它可能会给你推荐一些根本没经过验证的偏方这显然很危险。RAG检索增强生成技术正好能解决这个问题。它的核心思路是先从一个可靠的数据库里找到相关答案再让AI基于这些真实资料来回答。就像一个有经验的医生先查医学文献再给你建议而不是凭记忆随口说。我选择的技术栈是前端Vue3 Element Plus现代前端框架响应式体验好后端FlaskPython轻量级框架适合快速开发API向量数据库Chroma轻量级适合本地部署大模型通过Ollama本地运行数据不出内网隐私有保障框架LangChain专门为AI应用设计的编排工具2. 系统架构设计2.1 整体架构解析这个系统采用经典的前后端分离设计用户浏览器 ←HTTP→ Vue3前端 ←REST API→ Flask后端 ←gRPC→ Ollama服务 ↓ ChromaDB前端用Vue3的单页面应用(SPA)设计主要考虑三点Element Plus组件库成熟能快速搭建管理界面Composition API写起来更灵活Vite构建速度快开发体验好后端选择Flask而不是Django因为更轻量适合API服务与LangChain的Python生态配合更好我们的业务逻辑不复杂不需要Django的全套功能2.2 核心数据流当用户提出一个问题时系统内部的处理流程是这样的前端通过axios发送问题到Flask的/api/ask接口Flask服务用Ollama的embedding模型把问题转成向量去Chroma数据库里找最相似的文档片段把问题和找到的文档一起发给大模型大模型生成回答后原路返回给用户关键点在于AI的回答不是凭空想象的而是基于我们提前准备好的权威健康知识库。3. 关键技术实现细节3.1 文档处理流水线知识库的构建是整个系统的基石。我们设计了一个自动化处理流水线def process_document(file): # 1. 文本提取支持PDF/DOCX/TXT text extract_text(file) # 2. 文本分块重要 chunks split_text(text, chunk_size1000, chunk_overlap200) # 3. 向量化 embeddings ollama.embed(chunks) # 4. 存入数据库 chroma_db.add(embeddings, metadata{file_name: file.name})这里有几个关键参数需要注意chunk_size1000每个文本块约1000字符chunk_overlap200块之间重叠200字符防止断句实际测试发现这样的配置在准确率和性能间取得了平衡踩坑记录最初用固定行数分块结果经常把表格数据切碎。后来改用语义分块识别段落边界效果才好起来。3.2 RAG问答链实现核心的问答服务代码其实很简洁这要归功于LangChain的优秀设计# 初始化组件 llm ChatOllama(modelqwen3:8b) retriever chroma_db.as_retriever(k3) # 取最相关的3个文档 # 构建处理链 rag_chain ( {context: retriever | format_docs, question: RunnablePassthrough()} | prompt | llm | StrOutputParser() ) # 使用示例 answer rag_chain.invoke(糖尿病患者可以吃哪些水果)几个技术细节k3经过测试3个相关片段足够生成准确回答再多反而可能引入噪声temperature0.3让AI的回答更保守可靠特别设计了系统提示词强制AI必须基于提供的资料回答3.3 前端交互设计为了让用户体验更好我们做了这些优化问答界面分成三栏左侧知识库目录树中间问答对话框右侧参考文档展示消息气泡显示来源template div v-for(msg, index) in messages :keyindex div classmessage :class{ ai-message: msg.isAI } {{ msg.content }} div v-ifmsg.sources classsources 参考来源{{ msg.sources.join(, ) }} /div /div /div /template添加了加载状态指示器避免用户以为卡顿4. 部署与性能优化4.1 本地开发环境配置建议用conda创建隔离环境conda create -n rag-health python3.10 conda activate rag-health pip install -r requirements.txt关键依赖版本langchain0.1.0flask3.0.0chromadb0.4.0ollama0.1.04.2 生产环境部署我们用Docker compose编排了三个服务version: 3 services: web: build: ./web ports: [5000:5000] ollama: image: ollama/ollama ports: [11434:11434] chroma: image: chromadb/chroma ports: [8000:8000]性能调优经验Ollama服务分配了4GB内存模型是8B参数的qwen3Chroma配置了持久化存储Flask启用gunicorn多workergunicorn -w 4 -b :5000 app:app4.3 缓存策略为了减少重复计算我们实现了两级缓存问题向量缓存避免相同问题重复embedding回答结果缓存TTL 1小时from flask_caching import Cache cache Cache(config{CACHE_TYPE: SimpleCache}) cache.memoize(timeout3600) def get_embedding(text): return ollama.embed(text)5. 实际应用中的经验总结5.1 知识库建设心得数据质量比数量重要我们精选了200份三甲医院发布的健康指南效果比网上抓取的10000篇文章更好文档预处理很关键一定要去除页眉页脚表格内容要特殊处理非文本内容如图片需要人工补全描述定期更新机制我们设置了每月自动检查文档更新并重新生成向量5.2 常见问题排查遇到过的典型问题及解决方案问题现象可能原因解决方法回答与文档无关chunk切分不合理调整chunk_size或改用语义分块响应速度慢Ollama负载高增加模型服务内存或换更小模型找不到相关文档嵌入模型不匹配确保embedding和问答用同一模型5.3 效果评估指标我们设计了三个维度的评估准确率人工抽查100个问题对比标准答案响应时间平均控制在3秒内用户满意度通过前端点赞/点踩收集反馈实测结果常见健康问题准确率达92%专业医学问题准确率约75%平均响应时间2.8秒6. 扩展方向这个基础框架其实可以应用到很多领域法律咨询接入法律法规数据库教育辅导基于教材内容回答问题企业客服结合产品手册和常见问题最近我们在尝试添加多轮对话支持实验更大的70B参数模型实现PDF文档内直接高亮答案出处整个项目最让我惊喜的是LangChain的表现——它真的让RAG系统的开发变得非常简单。如果你也想尝试类似项目我的建议是先从一个小而精的知识库开始把质量把控好再逐步扩展规模