#CSDN博客-智能客服RAG实战
基于 Milvus Ollama(BGE-M3) DeepSeek 的智能客服 RAG 实战一、项目背景在社保、医保、就业等公共服务领域每天都有大量群众拨打热线咨询相似问题。传统人工客服成本高、效率低而基于关键词匹配的机器人又难以理解用户的真实意图。本项目基于RAGRetrieval-Augmented Generation检索增强生成架构搭建了一套智能客服系统实现用户问题语义理解非关键词匹配从知识库中精准检索相关问答基于 LLM 生成自然语言回答自动推荐相关问题引导用户继续咨询支持语音输入和语音播报二、整体架构用户(语音/文本输入) │ ▼ ┌─────────────┐ │ Flask服务 │ ← HTTPS部署 │ (后端API) │ └──────┬──────┘ │ ▼ ┌──────────────────┐ ┌──────────────────┐ │ Ollama本地服务 │ │ Milvus向量数据库 │ │ (bge-m3 向量化) │────▶│ (知识库语义检索) │ └──────────────────┘ └────────┬─────────┘ │ Top-20 相似问答 ▼ ┌──────────────────┐ │ DeepSeek API │ │ (LLM推理生成回答) │ └────────┬─────────┘ │ ▼ 回答 推荐问题 (SSE流式 / 普通返回)三、技术栈组件技术选型说明Embedding模型Ollama bge-m3本地部署免费支持中英文混合向量数据库Milvus开源高性能支持COSINE相似度大语言模型DeepSeek API (deepseek-chat)推理能力强性价比高后端服务Flask flask_cors轻量级支持HTTPS前端HTML JS jQuery支持语音输入(讯飞) Markdown渲染四、环境准备4.1 安装 Ollama 并拉取模型# 安装Ollama参考官方文档 https://ollama.com# 拉取中文Embedding模型ollama pull bge-m3验证模型是否可用curlhttp://localhost:11434/api/embeddings-d{ model: bge-m3:latest, prompt: 社保缴费年限不够怎么办 }返回结果中包含embedding字段即为成功。4.2 部署 Milvus推荐使用 Docker 部署# 下载docker-compose.ymlwgethttps://github.com/milvus-io/milvus/releases/download/v2.4.0/milvus-standalone-docker-compose.yml-Odocker-compose.yml# 启动dockercompose up-d4.3 安装Python依赖pipinstallflask flask-cors pymilvus requests chardet五、知识库构建5.1 创建Milvus集合frompymilvusimport(MilvusClient,FieldSchema,CollectionSchema,DataType)clientMilvusClient(urihttp://your_milvus_host:19530,tokenyour_token,db_namedefault)fields[FieldSchema(nameuid,dtypeDataType.INT64,is_primaryTrue,auto_idFalse,max_length100),FieldSchema(nameQuestion,dtypeDataType.VARCHAR,max_length5000),FieldSchema(nameAnswer,dtypeDataType.VARCHAR,max_length5000),FieldSchema(nameVector,dtypeDataType.FLOAT_VECTOR,dim1024),]schemaCollectionSchema(fields,社保知识库向量存储)client.create_collection(collection_nameSI_knowledge,schemaschema,dimension1024)注意bge-m3 模型输出的向量维度为1024创建集合时dim必须一致。5.2 创建向量索引defcreate_index(client:MilvusClient,collection_name:str):index_paraclient.prepare_index_params()index_para.add_index(field_nameVector,index_typeIVF_FLAT,metric_typeCOSINE,params{nlist:1024})client.create_index(collection_namecollection_name,index_paramsindex_para)5.3 导入知识库数据将业务问答数据向量化并存入Milvus。核心逻辑先检索是否已存在语义相似的问答去重再插入新数据。defvectorize_text(text):urlhttp://localhost:11434/api/embeddingsheaders{Content-Type:application/json,Accept:application/json}data{model:bge-m3:latest,prompt:text}responserequests.post(url,jsondata,headersheaders)ifresponse.status_code200:returnresponse.json().get(embedding,[])returnNonedefimport_knowledge(client,question,answer,uid):vectorvectorize_text(question)# 去重先检索是否存在语义高度相似的问题search_params{metric_type:COSINE,params:{radius:0.87}}resclient.search(collection_nameSI_knowledge,data[vector],limit10,output_fields[uid,Question],search_paramssearch_params)iflen(res[0])0:print(f已存在相似问题:{res[0][0][entity][Question]})return# 插入新数据data{uid:uid,Question:question,Answer:answer,Vector:vector}client.insert(collection_nameSI_knowledge,datadata)print(f插入成功: uid{uid})六、核心服务实现6.1 Flask服务主框架fromflaskimportFlask,request,render_template,Response,stream_with_contextfrompymilvusimportMilvusClientfromflask_corsimportCORSimportrequests,json,time appFlask(__name__)CORS(app)# Milvus连接配置clientMilvusClient(uriyour_milvus_host:19530,tokenyour_token,db_namedefault)# DeepSeek API配置DEEPSEEK_URLhttps://api.deepseek.com/chat/completionsDEEPSEEK_API_KEYos.environ.get(DEEPSEEK_API_KEY)# 建议使用环境变量headers{Content-Type:application/json,Accept:application/json,Authorization:fBearer{DEEPSEEK_API_KEY}}# 向量检索参数search_params{metric_type:COSINE,params:{radius:0.5}}6.2 本地Embedding向量化defvectorize_text(text):调用本地Ollama的bge-m3模型进行文本向量化urlhttp://localhost:11434/api/embeddingsheaders{Content-Type:application/json,Accept:application/json}data{model:bge-m3:latest,prompt:text}responserequests.post(url,jsondata,headersheaders)ifresponse.status_code200:returnresponse.json().get(embedding,[])returnNone为什么用本地Ollama做Embedding免费调用无API费用数据不出内网安全可控bge-m3 对中文语义理解效果优秀6.3 普通问答接口同步返回app.route(/getAnser,methods[GET])defget_answer():questionrequest.args.get(q)# 1. 问题向量化vectorvectorize_text(question)# 2. Milvus语义检索获取Top-20相关问答resclient.search(collection_nameSI_knowledge,data[vector],limit20,output_fields[uid,Question,Answer],search_paramssearch_params)# 3. 构建DeepSeek的请求data{model:deepseek-chat,messages:[],stream:False,temperature:0.3,max_tokens:8192}# 用户问题带Prompt约束data[messages].append({role:user,content:(question只能使用提供的上下文进行逻辑推理不要提示根据提供的上下文。回答问题后推荐相关的3个问题且不含回答及序号且答案与推荐的问题之间用separate分开且问题的答案在前面)})# 将检索到的知识库答案作为System上下文注入foriteminres[0]:data[messages].append({role:system,content:item[entity][Answer]})# 4. 调用DeepSeek生成回答start_timetime.time()responserequests.post(DEEPSEEK_URL,jsondata,headersheaders)print(f耗时:{time.time()-start_time:.2f}s)ifresponse.status_code200:resultresponse.json()contentresult[choices][0][message][content]# 5. 解析回答和推荐问题answer,recommendparse_answer_and_recommend(content)returnanswerseparaterecommendreturn6.4 流式问答接口SSE实时返回defsafe_decode(byte_data:bytes,encodingutf-8)-str:兼容多种编码格式的字节解码try:encodingrequests.compat.chardet.detect(byte_data)[encoding]returnbyte_data.decode(encoding)exceptUnicodeDecodeError:returnbyte_data.decode(encoding,errorsreplace)app.route(/getAnserStream,methods[GET])defget_answer_stream():questionrequest.args.get(q)# 1. 向量化 检索同上vectorvectorize_text(question)resclient.search(collection_nameSI_knowledge,data[vector],limit20,output_fields[uid,Question,Answer],search_paramssearch_params)# 2. 构建请求streamTruedata{model:deepseek-chat,messages:[],stream:True,temperature:0.3,max_tokens:8192}data[messages].append({role:user,content:(question只能使用提供的上下文进行逻辑推理不要提示根据提供的上下文如果发现是问了多个问题拆分问题。回答问题后从上下文中推荐相关的3个问题且不含回答及序号且答案与推荐的问题之间用separate分开且问题的答案在前面)})foriteminres[0]:data[messages].append({role:system,content:f问:{item[entity][Question]}?答:{item[entity][Answer]}})# 3. 流式调用DeepSeekresponserequests.post(DEEPSEEK_URL,jsondata,headersheaders,streamTrue)ifresponse.status_code200:defgenerate():forlineinresponse.iter_lines():ifline:textsafe_decode(line).replace(data: ,)try:chunkjson.loads(text)contentchunk[choices][0][delta][content]yieldcontentexceptException:passreturnResponse(stream_with_context(generate()),mimetypetext/plain)return6.5 解析回答和推荐问题defparse_answer_and_recommend(raw_content:str):从LLM输出中分离答案和推荐问题# 处理DeepSeek-R1的思考标记char_think\u25b8positionraw_content.find(char_think)startposition8ifposition0else0contentraw_content[start:]# 分离答案和推荐问题sepseparatesep_poscontent.find(sep)ifsep_pos0:answercontent[:sep_pos]recommend_textcontent[sep_poslen(sep):]# 清洗推荐问题文本linesrecommend_text.split(\n)cleaned[]forlineinlines:fornoisein[相关推荐问题,相关问题推荐,推荐相关问题,*,:,]:lineline.replace(noise,)iflen(line)4:cleaned.append(line)recommendseparate.join(cleaned)returnanswer,recommendreturncontent,七、前端集成7.1 流式请求与Markdown渲染functionaskllm(question){varallResult;fetch(/getAnserStream?qencodeURIComponent(question)).then(response{constreaderresponse.body.getReader();constdecodernewTextDecoder();functionreadChunk(){returnreader.read().then(({done,value}){if(done){// 流结束解析推荐问题constsepIndexallResult.indexOf(separate);constanswerallResult.slice(0,sepIndex);// 使用marked.js渲染Markdowndocument.getElementById(result).innerHTMLmarked(allResult.substring(0,sepIndex));// 解析并渲染推荐问题...return;}consttextdecoder.decode(value);allResulttext;document.getElementById(result).innerHTMLtext;readChunk();});}readChunk();});}7.2 语音输入讯飞语音识别前端集成了讯飞实时语音转写iat用户可以通过点击麦克风按钮直接语音提问语音识别结果自动发送给后端进行问答。7.3 语音播报讯飞TTS回答生成完成后自动调用讯飞TTS进行语音播报实现完整的语音交互闭环。八、HTTPS部署if__name____main__:app.run(host0.0.0.0,port443,ssl_context(path/to/server.crt,path/to/server.key))生产环境建议使用 Nginx 反向代理 Let’s Encrypt 证书而非直接在Flask中启用HTTPS。九、关键技术细节9.1 Prompt工程本项目的Prompt设计核心思路用户问题 约束条件 → 要求LLM 1. 只能使用提供的上下文推理防止幻觉 2. 不提示根据提供的上下文更自然 3. 拆分多问题场景 4. 输出答案 推荐问题用特殊分隔符分隔将检索到的知识库答案以system角色注入格式为问:xxx?答:xxx让LLM理解上下文结构。9.2 相似度阈值调优参数值说明radius0.5检索阈值越高越严格limit20检索返回条数metric_typeCOSINE余弦相似度temperature0.3LLM温度值偏低以保持准确知识库去重时使用radius0.87确保高语义相似的问题不会重复入库。9.3 选择bge-m3的原因中英文混合支持bge-m3 多语言效果好维度适中1024维Milvus检索效率高本地部署零成本通过Ollama本地运行无需API调用十、效果展示用户提问示例用户: “职工缴费年限不够怎么办”系统回答:从知识库检索到Top-20相关问题及答案DeepSeek基于上下文生成结构化回答自动推荐3个相关问题如养老保险缴费标准是什么、灵活就业人员如何参保等十一、优化方向Prompt输出结构化当前使用separate分隔符解析推荐问题可改为JSON格式输出更稳定Rerank重排序在Milvus检索后增加Rerank模型如bge-reranker提升Top-K准确率对话历史管理当前为单轮对话可增加session管理实现多轮上下文缓存层高频问题可加Redis缓存减少重复的Embedding和LLM调用知识库更新机制定时从业务系统同步最新问答数据十二、总结本项目通过Ollama本地Embedding Milvus向量检索 DeepSeek推理的RAG架构实现了零Embedding API成本的语义检索基于知识库的准确回答减少幻觉流式输出 语音交互的良好用户体验整套方案技术栈开源、部署简单适合政府、企业等有私有知识库的智能客服场景。相关技术文档Milvus官方文档https://milvus.io/docsOllama官方文档https://ollama.comDeepSeek API文档https://platform.deepseek.com/api-docsbge-m3模型https://huggingface.co/BAAI/bge-m3
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2499826.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!