找回密码
 立即注册
首页 业界区 业界 Slickflow.NET 基于 AI 大模型实现智能客服多轮问答系统 ...

Slickflow.NET 基于 AI 大模型实现智能客服多轮问答系统

梁丘眉 8 小时前
一、概述与价值

1.1 系统简介

本文介绍基于 Slickflow.NET 工作流引擎与 AI 大模型 实现的 智能客服多轮问答系统。该系统由前端 aichatapp(基于 React 的单页应用,使用纯 JS + JSX 组件)与后端 aichatbackend(ASP.NET Core WebAPI)组成,核心能力包括:

  • 多轮对话:按会话与客户维度维护历史,支持上下文连续问答。
  • RAG 增强回答:结合向量知识库检索与大模型生成,回答准确、可追溯。
  • 客户信息自动提取与落库:从对话中由大模型抽取姓名、手机、微信、邮箱等,并写入 biz_customer,供后续 CRM 或运营使用。
  • 多行业支持:通过 industry / industry_id 区分不同业务线,知识库与客户数据均可按行业隔离。
智能问答的完整交互过程由 Slickflow 的「流程自动化运行」机制驱动:一次用户提问对应一次流程实例的启动与执行,流程内各节点(查询客户、加载历史、RAG 检索、LLM 生成、联系方式提取、保存会话等)按 BPMN 定义顺序自动执行,无需人工干预。这与传统人工审批流程「每步等人办理」形成鲜明对比,适合客服、导购、知识问答等自动化场景。
1.2 参考文档


  • Slickflow 与 AI 大模型应用实践(文生流程图、图片分类、RAG):
    .NET 开源工作流: Slickflow.NET 工作流引擎关于AI大模型的应用实践
  • Slickflow.NET 流程自动化运行技术指南(Workflow 代码定义、WorkflowExecutor、LocalMethod、RAG/LLM 节点):
    .NET 开源工作流:Slickflow 流程自动化运行技术指南
二、整体架构与流程自动化运行

2.1 一次问答的调用链


  • 前端 aichatapp:用户输入问题 → 调用 aichatbackend 的 POST /api/AiChatApp/GetChatMessage,传入 Message、SessionId、CustomerId、Industry 等。
  • 后端 AiChatMessageService:根据配置的流程 ID/版本,使用 WorkflowExecutor 启动流程,将 user_message、customer_id、session_id、industry_id 等写入流程变量,并调用 Run()。
  • 流程自动化执行:引擎按 BPMN 顺序依次执行「查询客户 → 查询会话历史 → RAG 检索并回答 → LLM 提取联系方式 → 解析并保存客户 → 保存会话记录」,无需人工参与。
  • 流式推送:RAG 节点可配置 isNotifyClient: true,通过 SSE 将生成中的内容推送到前端;流程结束后再推送 workflow_completed。
2.2 流程定义与节点概览

智能客服流程图如下图所示:
1.png

BPMN 定义(Process_RAG智能客服)节点顺序如下:
顺序节点名称类型作用简述1Start开始事件流程入口2接收客户的提问Task占位节点,实际用户输入由 API 写入变量 user_message3查询客户记录LocalService根据 customer_id 从 biz_customer 加载客户信息到变量 customer4查询会话历史记录LocalService根据 customer_id + session_id 从 biz_conversation 加载历史,组装为 chat_history5检索知识库, 并回答RAG ServiceTask向量检索 + 大模型生成,输出 ai_response,可 SSE 推送6大模型提取客户联系方式LLM ServiceTask从本轮对话中抽取联系方式,输出 JSON 到 contact_json7解析并保存客户联系数据LocalService解析 contact_json,写入/更新 biz_customer,并回写 customer / customer_id8保存会话记录LocalService将 user_message、ai_response 等写入 biz_conversation9End结束事件流程结束下文对大模型节点(RAG、LLM)的配置与调用方式、本地服务节点的入参/出参及代码实现做说明,便于开发人员上手与二次开发。
三、流程节点说明

3.1 大模型节点类型与提示词配置

流程中有两类 AI 节点,均在 BPMN 的 extensionElements 中通过 sf:aiServices 声明:

  • RAG 节点(sf:aiService type="RAG")

    • 作用:用用户问题做向量检索,将检索到的知识库片段与历史对话一起拼成 prompt,调用大模型生成回答。
    • 配置来源:引擎从表 ai_activity_config(或等效配置)中按流程 ID + 活动 ID 读取该节点的配置,包括:

      • SystemPrompt:系统角色与回答规范。
      • UserMessage:可选的固定示例或补充说明。
      • Temperature、MaxTokens:控制生成风格与长度。
      • RAG 相关:相似度阈值(如 rag_similarity_threshold)、检索条数(rag_search_count)、行业过滤(结合 industry_id)等。

    • 输出变量:本系统中 RAG 节点将大模型回复写入流程变量 ai_response;若配置了 isNotifyClient: true,则通过 SSE 推送到前端。

2.png


  • LLM 节点(sf:aiService type="LLM")

    • 作用:纯大模型调用,不做向量检索。本流程中用于「从当前对话中抽取客户联系方式」,输出结构化 JSON。
    • 配置:同样来自 ai_activity_config,可配置 SystemPrompt 要求输出 JSON 格式(如:只输出 name/mobile/phone_number/wechat/email 等字段,无则 null)。
    • 输出变量:本流程中 LLM 节点将抽取结果写入 contact_json,供下一节点「解析并保存客户联系数据」使用。

提示词设计建议:

  • RAG 节点:SystemPrompt 中明确「基于下方 Context 回答,若无法从 Context 得到答案则如实说明」,避免幻觉;可配合 UserMessage 做 few-shot。
  • LLM 联系方式提取:SystemPrompt 中约定 JSON Schema(字段名、类型),并强调「仅输出 JSON,不要多余解释」,便于后端反序列化。
3.2 本地服务节点调用方式与代码实现

所有本地服务节点均通过 BPMN 的 sf:services 声明为 methodType="LocalService",并指定 expression 为实现了 IExternalService 的类名,引擎在运行到该节点时通过反射创建实例并调用 Execute()。入参由 argus 列出流程变量名,引擎从 EventService(流程变量)中按名读取并注入;出参通过 EventService.SaveVariable 写回流程变量。
从继承关系上看,本系统中的本地服务类(如 CustomerLoadService 等)通常遵循如下结构:
  1. ┌────────────────────────────┐
  2. │          IExecutable       │  (引擎内部可执行接口)
  3. └──────────────▲─────────────┘
  4.                │
  5. ┌──────────────┴─────────────────────┐
  6. │     ExternalServiceBase            │       (抽象基类,封装 IEventService 注入)
  7. │  - IDictionary DynamicVariables    │
  8. │  - IEventService EventService      │
  9. │  - void Executable(IEventService)  │
  10. │  - abstract void Execute()         │
  11. └──────────────▲─────────────────────┘
  12.                │ 实现 IExternalService.Execute()
  13. ┌──────────────┴─────────────────────────────────────────────────────┐
  14. │ CustomerLoadService : ExternalServiceBase, IExternalService        │
  15. │ ConversationHistoryService : ExternalServiceBase, IExternalService │
  16. │ CustomerContactService : ExternalServiceBase, IExternalService     │
  17. │ ConversationService : ExternalServiceBase, IExternalService        │
  18. └────────────────────────────────────────────────────────────────────┘
复制代码

  • IExternalService:仅定义 void Execute(),表示“外部服务”统一入口。
  • ExternalServiceBase:实现了引擎内部的 IExecutable 接口,在 Executable(IEventService) 中注入 EventService 后调用抽象 Execute(),方便子类访问/读写流程变量。
  • 具体业务类:如 CustomerLoadService 等,统一继承 ExternalServiceBase 并实现 IExternalService,只需关注业务逻辑,使用 EventService.GetVariable/SaveVariable 就能完成与流程上下文的数据交互。
(1)查询客户记录 — CustomerLoadService


  • BPMN
  • 逻辑:从流程变量读取 customer_id,调用 SupabaseCustomerRepository.GetByIdAsync 查询 Supabase 表 biz_customer;若查到则将该客户实体序列化为 JSON 写入变量 customer,并确保 customer_id 与库中一致。
  • 用途:让后续 RAG/LLM 和「保存会话」等节点能拿到当前客户信息,避免重复询问已知信息;若无 customer_id 或查不到则跳过写变量。
(2)查询会话历史记录 — ConversationHistoryService


  • BPMN
  • 逻辑:用 customer_id + session_id 从 biz_conversation 查询最近若干条会话(如 40 条),按时间正序组装为 [{ "role": "user"|"assistant", "content": "..." }, ...],序列化后写入流程变量 chat_history
  • 用途:RAG/LLM 节点从 chat_history 读取多轮历史,实现多轮对话与上下文连贯。
(3)解析并保存客户联系数据 — CustomerContactService


  • BPMN
  • 逻辑

    • 从流程变量读取 contact_json(由上一步 LLM 节点输出的 JSON 字符串)。
    • 反序列化为联系人 DTO(name、mobile、phone_number、wechat、email)。
    • 若有任意一个联系字段非空,则:

      • 若流程中已有 customer_id,则按该 ID 查询 biz_customer,存在则更新、不存在则插入并沿用该 ID;
      • 若无 customer_id,则按 wechat/phone 查重,有则更新、无则插入并生成新 customer_id。

    • 将 industry_id 从流程变量写入客户实体(便于按行业筛选客户列表)。
    • 把保存后的客户实体序列化写入变量 customer,并写回 customer_id
    • 可选:将本轮收集到的联系信息摘要追加到 chat_history 一条 system 消息,便于后续轮次中模型「已知哪些联系方式已收集」。

(4)保存会话记录 — ConversationService


  • BPMN
  • 逻辑:从流程变量读取 user_message、ai_response、customer_id(或从 customer JSON 中解析)、session_id、industry_id,构造 BizConversationEntity 并调用 SupabaseConversationRepository.InsertAsync 写入表 biz_conversation
  • 用途:持久化每一轮问答,供下一轮「查询会话历史记录」和运营/分析使用。
以上四类服务的调用方式统一为:引擎在流程运行时根据 BPMN 中 expression 反射得到服务类,注入 IEventService(访问流程变量与流程实例 ID),然后执行 Execute();无需在代码中显式注册,只要程序集被加载即可。
四、知识库与向量检索

4.1 向量知识库简介与可选数据库

系统使用向量知识库实现 RAG:将业务文档切成片段,通过嵌入模型转为高维向量并存储;用户提问时先将问题向量化,再在向量库中做相似度检索,将检索到的片段作为上下文交给大模型生成回答。

  • 本系统:使用 Supabase(基于 PostgreSQL + pgvector 扩展)存储向量与业务表,RAG 检索通过 Supabase 的 RPC 函数 biz_match_documents_optimized 完成。
  • 可替代方案:若希望替换为其他向量库,只需实现与当前 SupabaseRagService.MatchDocumentsOptimizedAsync 语义一致的接口(输入:查询向量、阈值、条数、可选 industry_id;输出:文档 id、content、metadata、similarity),并在 RAG 消息构建处注入该实现即可。常见选择包括:

    • MilvusQdrantWeaviatePinecone 等专用向量库;
    • Elasticsearch 等支持 dense vector 的搜索引擎;
    • 其他支持向量索引的云数据库(如部分云厂商的 PostgreSQL + pgvector)。

4.2 知识库记录的生成与嵌入模型


  • 知识库表:本系统使用表 biz_documents(及可选 biz_document_usage_log 记录每次 RAG 命中的文档),字段通常包括:id、content、metadata、embedding(向量)、industry_id 等。
  • 记录生成

    • 将原始文档(如产品说明、FAQ)按段落或固定长度切分为片段。
    • 对每个片段调用嵌入 API 得到向量,写入 embedding 列。
    • 若有行业维度,则写入 industry_id,便于检索时按行业过滤。

  • 嵌入模型:本系统支持千问(Qwen)text-embedding-v4 等模型,通过 QWen3EmbeddingGenerator 调用阿里云 DashScope 兼容的 Embedding API;向量维度与模型配置一致(如 1536 维)。也可配置为 OpenAI 兼容的 Embedding API(如 text-embedding-3-small),由 EmbeddingGenUtility 或对应实现类完成调用。
  • 入库与更新:可通过控制台脚本或管理后台批量导入/更新文档并重新生成 embedding;需保证与检索时使用的嵌入模型与维度一致。
4.3 相似度计算与检索逻辑(算法层面)


  • 相似度度量:Supabase(pgvector)使用 余弦距离 运算符 :(1 - (embedding  query_embedding)) 即为余弦相似度,取值约 [0,1],越大越相似。
  • 检索逻辑(与 biz_match_documents_optimized 对应):

    • 输入:用户问题的向量 query_embedding、高/低相似度阈值(如 0.8 / 0.6)、高/低阈值各取几条(如 5/3)、可选 filter_industry_id。
    • 在 biz_documents 中筛选:embedding 非空、相似度 ≥ 低阈值,且当 filter_industry_id 非空时只保留该行业。
    • 按余弦距离升序排序(即相似度从高到低),取前 match_count_high 条返回,供 RAG 拼入 Context。

  • 业务含义:高阈值保证强相关文档优先;低阈值与条数用于在相关文档不足时适当放宽,避免无上下文可用的情形。
五、客户联系方式提取规则与生成

5.1 提取规则


  • 数据来源:当前轮次用户输入与 AI 回复(以及可选的历史摘要),由 LLM 节点在单次调用中完成「理解 + 抽取」。
  • 输出格式:LLM 节点按 SystemPrompt 约定输出 JSON,例如:
    { "name": "张三", "mobile": "13800138000", "phone_number": null, "wechat": "wxid_xxx", "email": "zhangsan@example.com" }
    未识别到的字段可为 null 或省略。
  • 去重与更新

    • 若流程中已带 customer_id(如前端传入),则优先按该 ID 在 biz_customer 中查找,存在则更新该客户,不存在则插入并沿用该 ID,保证同一会话/同一浏览器始终对应同一客户 ID。
    • 若未带 customer_id,则由 CustomerContactService 按 wechat 或 phone 在 biz_customer 中查重;有则更新,无则插入并生成新的 customer_id(如 cust-{guid})。

  • 行业:从流程变量 industry_id 写入客户实体,便于按行业筛选客户列表(与 aichatapp 多行业主页一致)。
5.2 生成流程简述


  • 用户在前端输入问题(可能包含姓名、电话、微信等)。
  • 流程执行到 RAG 节点,先返回知识库增强的回复(ai_response)。
  • 紧接着 LLM 节点读取当前轮(及可选历史)的 user/assistant 内容,按提示词要求输出 contact_json
  • CustomerContactService 解析 contact_json,写入或更新 biz_customer,并回写 customer / customer_id 到流程变量;可选地将「本轮已收集联系信息」摘要追加到 chat_history。
  • 下一轮「查询客户记录」与「查询会话历史记录」会带上最新 customer_id 与历史,RAG/LLM 即可避免重复询问已收集的信息。
六、开发与版本获取


  • 新增行业:在 biz_industry 中增加记录;前端 aichatapp 通过 ?industry=xxx 区分;后端将 industry 解析为 industry_id 写入流程变量,RAG 与客户数据即可按行业隔离。
  • 更换向量库:实现与 MatchDocumentsOptimizedAsync 同语义的检索接口,并在 RAG 消息构建处切换实现;嵌入模型与维度需与知识库一致。
  • 调整 RAG/LLM 行为:修改 ai_activity_config 中对应活动 ID 的 SystemPrompt、Temperature、RAG 阈值与条数等即可,无需改代码。
  • 新增本地服务节点:实现 IExternalService,在 BPMN 中通过 sf:services 的 expression 指定类名,argus 列出所需流程变量名即可。
6.1 示例访问入口

当前示例项目在 aichatapp 中预置了多个行业入口,便于演示“同一套智能客服引擎,面向不同行业知识库与客户数据”的效果。典型访问地址(以本地开发环境为例)如下:

  • 电动汽车新能源客服(ev):https://demo.slickflow.com/aichatapp/?industry=ev
  • 青少年心理咨询中心(psychology):https://demo.slickflow.com/aichatapp/?industry=psychology
  • 医美咨询中心(medical_beauty):https://demo.slickflow.com/aichatapp/?industry=medical_beauty
  • 宠物托管服务中心(pet_hosting):https://demo.slickflow.com/aichatapp/?industry=pet_hosting
(如需在本地或自有环境部署,可将上述域名替换为实际部署地址,保留 ?industry=xxx 参数形式不变。)
3.png

6.2 微信小程序端示例

4.png

6.3 源码获取与版本说明


  • 解决方案与完整源代码
    本智能客服多轮问答系统(包含流程定义、Slickflow.AI、aichatapp、aichatbackend 等)作为示例项目,随 Slickflow.NET 旗舰版 一同提供。
  • Slickflow 研发团队可以给客户提供定制化解决方案,目前Slickflow引擎产品具备大模型开发的实战能力,源代码完全开源,是.NET生态平台的优秀开源产品,值得客户信赖。
  • 欢迎通过 Slickflow 官方渠道咨询旗舰版授权与技术支持,获取最新版本的解决方案源码、部署文档和技术开发资料。

七、小结

Slickflow.NET 基于 流程自动化运行AI 大模型(RAG + LLM)能力,将「接收提问 → 查客户/历史 → 知识库检索与回答 → 联系方式提取与落库 → 保存会话」串成一条可配置、可扩展的 BPMN 流程。aichatapp + aichatbackend 实现了多轮问答、多行业与客户维度的会话与客户管理;通过 BPMN 与配置即可调整提示词与检索策略,便于开发人员上手和二次开发。
参考资料

  • Slickflow.NET 工作流引擎关于AI大模型的应用实践
  • Slickflow 流程自动化运行技术指南

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册