尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

基于DeepSeek和RAGFlow的智能项目推荐客服系统架构设计与部署实践

基于DeepSeek和RAGFlow的智能项目推荐客服系统架构设计与部署实践 背景痛点传统客服系统的项目推荐之困在项目咨询或服务推荐的场景下传统的客服系统常常显得力不从心。这类系统大多基于关键词匹配或预设的规则树其局限性非常明显。首先最头疼的是“冷启动”问题。当用户提出一个全新的、系统知识库中从未出现过的项目需求时基于规则的引擎要么返回“抱歉我无法理解您的问题”要么给出一个完全不相关的推荐用户体验瞬间跌至谷底。其次语义理解的偏差是另一个硬伤。比如用户问“有没有适合小团队、能快速上手的协作工具”传统系统可能只会机械地匹配“团队”、“协作”、“工具”这几个关键词然后推出一堆重型项目管理软件而忽略了“小团队”和“快速上手”这两个核心约束。这种偏差源于系统缺乏对上下文和用户意图的深层理解。此外这类系统的知识更新成本高昂。每当有新的项目或服务上线都需要技术人员手动编写和更新大量的匹配规则不仅响应慢还容易出错。面对日益增长和变化的用户需求这种僵化的模式越来越难以为继。正是这些痛点促使我们去寻找更智能、更灵活的解决方案。我们希望系统不仅能“听懂”用户的话还能从海量的、动态更新的项目库中精准地找到最符合用户当下需求的选项。技术选型为什么是DeepSeek与RAGFlow面对上述挑战我们选择了DeepSeek大模型与RAGFlow框架的组合。这个选择是经过深思熟虑和对比验证的。1. 大模型选型DeepSeek的优势在中文场景下我们对比了多个主流的大语言模型。DeepSeek脱颖而出主要基于以下几点考量出色的中文理解与生成能力DeepSeek在中文语料上进行了深度训练对中文的语义、语境和文化背景有更好的把握这在处理中文项目描述和用户咨询时至关重要。优秀的指令遵循Instruction Following能力对于客服推荐场景我们需要模型严格按照我们设定的格式和逻辑来组织回复DeepSeek在这方面的表现非常稳定。性价比与可用性相较于一些闭源的商业模型DeepSeek提供了性能优异且成本更可控的API服务这对于需要处理大量并发请求的客服系统来说是一个关键优势。2. 检索框架选型RAGFlow vs. 传统方案传统的检索增强生成RAG方案通常需要开发者自行搭建向量数据库如Milvus, Pinecone、设计文档切分与向量化流程、并处理复杂的检索逻辑。这带来了较高的开发和维护门槛。RAGFlow框架则将这些复杂性封装起来提供了开箱即用的解决方案其核心优势在于动态数据更新这是传统RAG方案的一大痛点。RAGFlow支持对知识库文档进行增量更新和实时索引新的项目信息可以近乎实时地被纳入检索范围无需重建整个索引完美解决了知识更新延迟的问题。混合检索Hybrid Search能力RAGFlow不仅支持基于向量相似度的语义检索还融合了基于关键词如BM25的稀疏检索。这种混合模式能有效结合语义匹配的“广度”和关键词匹配的“精度”尤其在处理包含特定名称、型号或专业术语的查询时效果显著优于单一的向量检索。简化的部署与管理它提供了直观的管理界面和API大大降低了从文档处理到检索服务上线的整个流程复杂度。下图展示了我们技术栈的核心构成系统架构设计我们的智能项目推荐客服系统采用分层架构设计确保各模块职责清晰、易于扩展和维护。1. 整体分层架构系统主要分为三层接入层、推理层和数据层。接入层作为系统的门面负责接收来自Web、App或API客户端的用户请求。它主要处理协议转换、请求路由、基础的输入验证和用户会话管理。我们使用Nginx作为反向代理和负载均衡器后接基于Python Flask/FastAPI构建的API网关负责JWT鉴权、限流和请求分发。推理层这是系统的“大脑”也是核心所在。它接收来自接入层的用户Query并执行智能推荐的核心流程。该层进一步细分为几个关键服务Query理解服务利用DeepSeek模型对原始用户问题进行意图识别、实体抽取和查询改写将口语化表达转化为更适合检索的结构化查询。检索服务基于RAGFlow构建。接收优化后的查询从其管理的向量知识库中执行混合检索召回一组相关的候选项目文档片段。提示工程与生成服务将检索到的文档片段与原始查询、对话历史如果有结合通过精心设计的Prompt模板提交给DeepSeek生成模型让其生成自然、准确、个性化的推荐回复。结果精排服务对生成模型返回的多个候选回复或检索到的多个项目根据相关性、置信度、业务规则如优先级、热度进行重新排序选出最优结果。数据层为系统提供持久化存储和知识支撑。包括向量知识库由RAGFlow管理存储所有项目的向量化表示和原始文本片段。关系型数据库存储用户信息、对话历史、日志、系统配置等结构化数据。缓存Redis缓存高频查询的推荐结果、会话状态以大幅降低响应延迟和模型调用开销。各层之间通过定义良好的RESTful API或gRPC接口进行通信实现了松耦合。2. 核心算法流程当用户发起一次咨询时系统内部会经历一个精密的处理流水线Query理解用户输入“我想找个做微信小程序的公司预算不高”。Query理解服务会解析出意图为“寻找服务商”实体为“微信小程序”约束条件为“预算有限”。可能将查询改写为“性价比高的微信小程序开发服务商推荐”。向量检索改写后的查询被送入RAGFlow检索服务。RAGFlow利用其混合检索能力同时计算查询与知识库中项目描述的语义相似度向量匹配和关键词匹配度综合两者得分召回Top-K个最相关的项目片段例如“A公司专注轻量级小程序开发入门套餐价优...”、“B团队擅长社交类小程序提供灵活报价方案...”。提示工程生成服务将这些片段、原始查询、以及要求模型扮演“专业项目顾问”的指令组合成一个结构化的Prompt发送给DeepSeek生成模型。Prompt模板会明确要求模型基于提供的片段进行回答避免虚构信息。结果精排DeepSeek返回的回复可能是对多个项目的介绍。精排服务会根据项目本身的评分、与用户预算的匹配度、历史合作成功率等业务指标对回复中的项目推荐顺序进行微调最终生成并返回给用户“根据您的需求这里有几个高性价比的微信小程序开发选择1. A公司... 2. B团队...”。代码实现关键环节下面通过几个核心代码片段来具体展示如何将上述架构落地。1. 使用DeepSeek API构建Embedding服务虽然RAGFlow内部集成了向量化能力但在某些需要自定义或单独使用嵌入向量的场景下我们直接调用DeepSeek的Embedding API。import requests import json from typing import List class DeepSeekEmbedder: def __init__(self, api_key: str, base_url: str https://api.deepseek.com): self.api_key api_key self.base_url base_url self.headers { Authorization: fBearer {api_key}, Content-Type: application/json } def get_embedding(self, text: str, model: str deepseek-embedding) - List[float]: 调用DeepSeek Embedding API将单条文本转换为向量。 Args: text: 需要向量化的文本。 model: 使用的嵌入模型名称。 Returns: 文本对应的向量列表。 payload { input: text, model: model } try: response requests.post( f{self.base_url}/embeddings, headersself.headers, jsonpayload, timeout10 ) response.raise_for_status() result response.json() # 假设API返回结构为 {data: [{embedding: [...]}]} return result[data][0][embedding] except requests.exceptions.RequestException as e: # 在实际生产中这里应加入更完善的错误处理和日志记录 print(f获取嵌入向量失败: {e}) # 降级策略返回零向量或触发缓存/备用模型 return [0.0] * 768 # 假设维度为768 def batch_get_embeddings(self, texts: List[str]) - List[List[float]]: 批量获取嵌入向量提高效率。 注意需要检查DeepSeek API是否支持批量调用此处为示例逻辑。 embeddings [] for text in texts: # 实际批量调用可能通过API的batch参数实现 emb self.get_embedding(text) embeddings.append(emb) return embeddings # 使用示例 if __name__ __main__: embedder DeepSeekEmbedder(api_keyyour_deepseek_api_key_here) sample_text 微信小程序开发性价比高 vector embedder.get_embedding(sample_text) print(f文本向量维度: {len(vector)})2. 集成RAGFlow进行检索增强这里展示如何调用部署好的RAGFlow服务来完成检索。import requests from typing import Dict, Any, List class RAGFlowClient: def __init__(self, ragflow_api_endpoint: str, api_key: str): self.endpoint ragflow_api_endpoint.rstrip(/) self.headers { Authorization: fBearer {api_key}, Content-Type: application/json } def hybrid_search(self, query: str, top_k: int 5, filter_conditions: Dict[str, Any] None) - List[Dict]: 执行混合检索。 Args: query: 用户查询文本。 top_k: 返回最相关结果的数量。 filter_conditions: 可选的过滤条件如按项目类别、时间筛选。 Returns: 包含检索结果和元数据的列表。 payload { query: query, top_k: top_k, search_method: hybrid, # 指定使用混合检索 } if filter_conditions: payload[filter] filter_conditions try: response requests.post( f{self.endpoint}/retrieve, headersself.headers, jsonpayload, timeout15 ) response.raise_for_status() data response.json() # 假设RAGFlow返回格式为 {results: [{content:..., score:..., metadata:...}, ...]} return data.get(results, []) except requests.exceptions.RequestException as e: print(fRAGFlow检索失败: {e}) # 触发降级逻辑例如返回基于关键词的简单检索结果 return self._fallback_search(query, top_k) def _fallback_search(self, query: str, top_k: int) - List[Dict]: 降级检索策略当RAGFlow服务不可用时使用。 例如可以查询关系型数据库中的关键词索引。 # 实现简单的本地关键词匹配逻辑或调用备用服务 # 此处返回空列表作为示例 print(触发降级检索策略) return [] # 使用示例 if __name__ __main__: client RAGFlowClient( ragflow_api_endpointhttp://your-ragflow-server:port/api, api_keyyour_ragflow_api_key ) results client.hybrid_search(寻找AI图像生成项目, top_k3) for i, res in enumerate(results): print(f结果 {i1}: 分数{res.get(score, 0):.3f}) print(f内容: {res.get(content, )[:200]}...) # 预览前200字符 print(- * 50)3. 推荐结果的后处理与精排逻辑检索和生成的结果需要经过后处理才能最终呈现给用户。from typing import List, Dict, Any import numpy as np class RecommendationPostProcessor: def __init__(self, business_rules: Dict[str, Any]): 初始化后处理器载入业务规则。 Args: business_rules: 包含业务权重的配置如项目热度权重、价格匹配权重等。 self.business_rules business_rules def rerank_with_business_logic(self, candidates: List[Dict], user_context: Dict[str, Any] None) - List[Dict]: 根据业务规则和用户上下文对候选项目进行重新排序。 Args: candidates: 来自检索或生成的候选项目列表每个项目应包含至少score(相关性分)、metadata。 user_context: 用户上下文如预算范围、历史偏好。 Returns: 重新排序后的项目列表。 if not candidates: return [] reranked_items [] for item in candidates: final_score item.get(score, 0.0) metadata item.get(metadata, {}) # 1. 业务规则加分项 # 例如热门项目加分 if metadata.get(is_hot, False): final_score self.business_rules.get(hot_project_bonus, 0.1) # 价格匹配度加分 (假设用户上下文中有预算) if user_context and user_budget in user_context: project_price metadata.get(price, float(inf)) budget user_context[user_budget] # 简单的价格匹配逻辑价格低于或接近预算则加分 if project_price budget * 1.2: # 允许20%上浮 price_match_ratio max(0, 1 - (project_price - budget) / budget) if budget 0 else 0 final_score price_match_ratio * self.business_rules.get(price_match_weight, 0.15) # 2. 惩罚项 # 例如差评率过高惩罚 bad_review_rate metadata.get(bad_review_rate, 0) if bad_review_rate 0.3: # 差评率超过30% final_score - self.business_rules.get(high_bad_review_penalty, 0.2) reranked_items.append({ **item, final_score: final_score # 添加最终综合得分 }) # 按最终得分降序排序 reranked_items.sort(keylambda x: x[final_score], reverseTrue) return reranked_items def format_response_for_user(self, reranked_items: List[Dict], query: str) - str: 将精排后的项目列表格式化为面向用户的自然语言回复。 Args: reranked_items: 精排后的项目列表。 query: 原始用户查询。 Returns: 格式化后的回复文本。 if not reranked_items: return 抱歉暂时没有找到完全符合您要求的项目。您可以尝试调整搜索条件或联系人工客服获取更多帮助。 response_lines [f根据您“{query}”的需求为您推荐以下项目\n] for idx, item in enumerate(reranked_items[:5]): # 最多展示5个 meta item.get(metadata, {}) name meta.get(project_name, 未知项目) brief item.get(content, )[:100] ... # 截取摘要 tag 热门 if meta.get(is_hot) else response_lines.append(f{idx1}. **{name}** {tag}) response_lines.append(f {brief}) response_lines.append() # 空行分隔 response_lines.append(您对哪个项目更感兴趣呢我可以为您提供更详细的信息。) return \n.join(response_lines) # 使用示例 if __name__ __main__: business_rules { hot_project_bonus: 0.1, price_match_weight: 0.15, high_bad_review_penalty: 0.2 } processor RecommendationPostProcessor(business_rules) # 模拟候选项目 mock_candidates [ {score: 0.85, content: A公司提供AI绘画小程序定制..., metadata: {project_name: AI绘画小程序, price: 50000, is_hot: True}}, {score: 0.78, content: B团队擅长企业官网开发..., metadata: {project_name: 企业官网, price: 30000, bad_review_rate: 0.4}}, ] user_ctx {user_budget: 40000} reranked processor.rerank_with_business_logic(mock_candidates, user_ctx) final_response processor.format_response_for_user(reranked, 做个小程序) print(final_response)生产环境部署与考量将这样一个AI系统投入生产除了功能实现还需要在性能、安全、可靠性上下足功夫。1. 性能测试与优化在系统上线前我们进行了全面的压力测试。使用Locust模拟不同并发用户数下的请求关键指标如下单节点基准性能在4核8G的容器配置下端到端处理一个典型查询包含检索、生成、后处理的平均延迟P95约为1.8秒其中大模型生成耗时占大头。纯检索不调用生成模型的延迟可控制在300毫秒以内。并发能力随着并发用户数QPS从10提升到50系统响应时间逐渐增加。在QPS30时P95延迟约为2.5秒仍处于可接受范围。当QPS超过40由于模型API调用成为瓶颈延迟上升明显。优化措施结果缓存对高频、通用的查询如“推荐热门项目”结果进行短期缓存如5分钟命中缓存时延迟可降至50毫秒以下。异步处理对于非实时性要求极高的场景将生成任务放入消息队列异步处理并通过WebSocket或轮询通知用户。模型蒸馏与量化考虑在边缘场景使用更小、更快的蒸馏模型进行初步意图识别或简单问答减轻主模型压力。2. 安全防护策略AI系统的输入输出必须经过严格把关。接入层安全JWT鉴权所有API请求必须携带有效的JWT令牌令牌中可包含用户角色、权限等信息网关负责验证。速率限制基于IP和用户ID实施API调用频率限制防止恶意爬取和DDoS攻击。输入过滤与清洗对用户输入的文本进行敏感词过滤、SQL注入和脚本注入检查。对输入长度进行限制防止超长文本攻击。输出审核与对齐后处理审核在将模型生成的回复返回给用户前通过一个轻量级的规则引擎或分类模型进行二次审核过滤掉包含不当言论、政治敏感或商业机密泄露风险的内容。提示工程约束在给模型的Prompt中明确加入“拒绝回答与项目推荐无关的问题”、“不评论任何实体或个人”等指令从源头引导模型行为。3. 容灾与降级设计任何依赖外部API如DeepSeek的服务都必须有降级方案。模型服务降级断路器模式Circuit Breaker当连续调用DeepSeek API失败次数达到阈值时断路器“跳闸”短时间内直接拒绝请求快速失败避免系统资源被拖垮。之后进入半开状态试探。备用模型当主生成模型不可用时自动切换至本地部署的、能力稍弱但稳定的开源小模型如Qwen2.5-7B或直接返回基于检索结果的模板化回复。缓存回退策略当检索服务RAGFlow暂时不可用时系统可以回退到查询关系型数据库中预构建的关键词-项目索引虽然效果打折但保证了基本服务可用。对于登录用户可以尝试从其历史对话和偏好中提取推荐实现个性化降级。实践避坑指南在开发和部署过程中我们踩过一些坑也总结出一些经验。1. 缓解大模型“幻觉”问题的三种实践方法大模型有时会“一本正经地胡说八道”生成与检索内容无关或事实错误的信息。我们通过以下组合拳来缓解强化检索内容在Prompt中的权重和指示在Prompt中明确指令如“请严格依据以下提供的资料进行回答如果资料中没有相关信息请直接说‘根据现有资料我无法回答这个问题’”并将检索到的文档片段放在Prompt中显眼的位置如使用context.../context标签包裹。引入“引用溯源”机制要求模型在生成答案时指明其依据的是哪一段资料。这不仅能增加可信度也便于事后验证和调试。我们在后处理中会尝试解析模型的回答将提到的信息点与检索出的文档块进行关联验证。结果置信度评估与过滤训练一个简单的分类器或者利用模型自身生成答案时的logits概率对生成回复的置信度进行评估。对于置信度过低的回答不直接返回给用户而是触发人工审核或转接人工客服流程。2. Kubernetes部署资源配额配置建议在K8s中部署AI应用资源请求requests和限制limits的设置至关重要。API网关/Web服务这类无状态服务CPU请求可设为100m-250m内存256Mi-512Mi。限制可以设为请求的1.5-2倍。采用HPA水平Pod自动伸缩基于CPU利用率如70%进行扩缩容。模型推理服务如果本地部署这是资源消耗大户。以部署一个7B参数量的量化模型为例建议内存请求至少为8GiCPU2核。需要密切关注GPU显存如果使用GPU例如8Gi。务必设置内存限制防止OOM内存溢出导致Pod不断重启。RAGFlow/向量数据库服务内存消耗与索引数据量强相关。建议内存请求为预估索引内存占用的1.5倍。例如1百万条向量的索引可能占用2-3GB内存则请求可设为4Gi。数据持久化卷PVC的大小也要提前规划好。Redis缓存根据缓存数据量设置内存。建议使用maxmemory-policy配置为allkeys-lru等策略防止内存打满。3. 对话状态管理的常见错误模式在多轮对话的客服场景中状态管理容易出错。错误1状态全存服务端导致扩展性差。将所有对话历史、中间结果都塞进服务器的内存或数据库会话对象中当用户量大时服务器压力巨大。正确做法采用无状态设计。将必要的对话上下文如最近几轮QA经过精简后作为参数附加在每次请求中可加密或存储于分布式缓存如Redis中通过一个会话ID来关联。错误2上下文窗口滥用。盲目地将整个漫长的对话历史都喂给模型导致token数超限、成本激增且模型可能因信息过载而表现下降。正确做法实现智能的上下文窗口管理。只保留最近N轮对话并对更早的历史进行摘要Summary将摘要而非全文放入上下文。RAGFlow等框架通常也支持基于当前查询从历史对话中检索最相关的片段而非全部送入。错误3状态丢失后体验割裂。用户短暂离开后回来会话状态丢失需要从头开始。正确做法实现会话的持久化与恢复。将会话状态定期持久化到数据库并为用户提供“继续上次对话”的入口。同时设置合理的会话过期时间如30分钟无活动后过期平衡体验与资源占用。结语与未来思考通过将DeepSeek大模型的强大理解与生成能力与RAGFlow框架的高效、动态检索能力相结合我们成功构建了一个能够精准理解用户意图、并从海量项目中智能匹配推荐的客服系统。这套架构不仅显著提升了推荐准确率和用户体验也因其模块化设计而具备了良好的可维护性和扩展性。回顾整个实践过程从技术选型、架构设计到生产部署我们深刻体会到构建一个可靠的AI应用不仅仅是调用API那么简单它需要前后端工程、算法、运维安全的紧密协作尤其是在性能优化、安全防护和容灾降级等方面需要投入大量的工程设计。最后我们也在持续思考如何让这个系统变得更好。这里抛出两个开放性问题或许也是我们和读者可以共同探索的方向如何更动态地评估和优化检索质量目前我们主要通过人工抽查和A/B测试来评估检索结果的相关性。能否设计一种在线学习机制根据用户对推荐结果的点击、咨询深度等隐式反馈自动调整RAGFlow中混合检索的权重语义vs关键词甚至动态优化向量模型的微调在多轮复杂对话中如何更精准地管理对话目标与状态当前的状态管理更多是基于历史语句的堆叠。当用户需求在对话中逐渐演变或细化时例如从“找开发团队”细化到“找有电商经验的小程序开发团队”系统能否自动识别这种“对话目标的转移”并主动调整检索策略和生成策略以实现更连贯、更智能的渐进式推荐技术的道路没有终点期待与各位开发者同行继续交流与探索。
返回列表