#复杂的AI业务如何拆解?从时序图到模块划分的领域驱动设计(DDD)实战
当AI项目从Demo走向生产最大的挑战往往不是模型精度而是业务逻辑的复杂度一、为什么AI项目越做越乱我见过不少AI项目初期用Jupyter Notebook跑通了一个高精度模型团队欢欣鼓舞地开始产品化。三个月后代码库变成了谁也看不懂的一团乱麻——意图识别、Prompt模板、外部API调用、业务规则判断、数据持久化全部揉在一起改一个功能要排查半天加一个新场景要复制粘贴一大段代码。症状很典型Prompt满天飞同样的业务规则在代码的不同位置用不同的Prompt重复实现逻辑散落各处一个订单退款流程的判断逻辑分散在Controller、Service、Agent节点和Prompt指令里改了不敢动不确定一个改动的波及范围因为没有人说得清整个业务流程的完整链路根本原因把AI能力当作“魔法黑盒”塞进传统分层架构忽视了AI应用本身也是一种复杂的业务系统需要被领域建模、被结构化拆解。解决方案的思路很清晰先用时序图把业务流程可视化再用领域驱动设计DDD把业务逻辑模块化。这套方法论在传统软件工程中已被验证有效而AI应用的复杂性恰恰让它更不可或缺。二、第一步用时序图把“黑盒”打开任何复杂系统设计的第一步都是把流程画出来。时序图Sequence Diagram是最合适的工具——它清晰展示了不同组件之间如何交互、谁调用谁、输入输出是什么。2.1 选一个真实的AI业务场景假设我们要开发一个**“智能订单助手”**用户可以通过自然语言完成三类操作商品咨询“这款耳机支持降噪吗”订单查询“帮我查一下我最近的订单状态”退款申请“我要退掉昨天买的那个键盘”这是一个典型的“多意图多Agent协作”场景。如果用传统方式代码里会是一堆if-else根据意图类型路由到不同的处理逻辑。这恰恰是最容易写乱的地方。2.2 绘制交互时序图先画出系统内部有哪些参与者以及它们之间的交互关系┌────────┐ ┌──────────┐ ┌─────────────┐ ┌─────────────┐ ┌──────────┐ │ 用户 │ │ API网关 │ │ 意图识别器 │ │ 各业务Agent │ │ 外部服务 │ └────┬───┘ └────┬─────┘ └──────┬──────┘ └──────┬──────┘ └────┬─────┘ │ │ │ │ │ │ 1. 输入自然语言 │ │ │ │────────────│ │ │ │ │ │ 2. 携带userId/sessionId │ │ │ │────────────────│ │ │ │ │ │ 3. 调用LLM判断意图 │ │ │ │ (商品咨询/订单查询/退款) │ │ │ │────────────────│ │ │ │ │ 4. 返回意图实体 │ │ │ │────────────────│ │ │ │ 5. 按意图路由 │ │ │ │ │────────────────│ │ │ │ │ │ │ │ │ │ 6. 调用对应Agent │ │ │ │ │─────────────────────────────────────│ │ │ │ │ │ 7. 查询数据库/调用外部API │ │ │ │────────────────│ │ │ │ │ 8. 返回结果 │ │ │ │ │────────────────│ │ 9. 返回最终回复 │ │ │ │────────────│ │ │ │这个时序图的价值在于明确了系统边界——哪些是外部调用方哪些是内部组件看清了调用链路——每个步骤的输入输出是什么暴露了拆分点——意图识别和具体业务执行可以拆成独立模块有了这张图我们就可以开始模块划分了。2.3 从时序图到模块边界观察时序图自然浮现出几个职责清晰的模块模块职责对应时序图中的角色意图识别模块理解用户输入判断意图类型和关键实体意图识别器商品咨询模块处理商品知识问答业务Agent商品订单查询模块查询订单状态和详情业务Agent订单退款处理模块执行退款流程含规则校验业务Agent退款这些模块之间的边界在时序图里也一目了然——它们通过“意图路由”这个中间环节解耦互不直接调用。这正是DDD中限界上下文Bounded Context的雏形。三、第二步用DDD把模块变成“可维护的代码”有了时序图建立的全局认知我们可以进入DDD的战术设计阶段把模块变成有清晰业务边界、可独立演化的代码单元。3.1 项目结构按限界上下文组织代码order-assistant/ ├── src/main/java/com/example/ │ ├── intent/ # 限界上下文意图识别 │ │ ├── domain/ # 领域层 │ │ │ ├── Intent.java # 聚合根意图 │ │ │ ├── IntentRepository.java │ │ │ └── IntentClassifier.java # 领域服务 │ │ ├── application/ # 应用层 │ │ │ └── IntentRecognitionService.java │ │ └── infrastructure/ # 基础设施层 │ │ └── LLMIntentClassifierImpl.java │ │ │ ├── product/ # 限界上下文商品咨询 │ │ ├── domain/ │ │ │ ├── ProductKnowledge.java │ │ │ └── ProductRepository.java │ │ └── application/ │ │ └── ProductConsultationService.java │ │ │ ├── order/ # 限界上下文订单查询 │ │ ├── domain/ │ │ │ ├── Order.java # 聚合根 │ │ │ └── OrderRepository.java │ │ └── application/ │ │ └── OrderQueryService.java │ │ │ ├── refund/ # 限界上下文退款处理 │ │ ├── domain/ │ │ │ ├── RefundOrder.java │ │ │ ├── RefundPolicy.java # 值对象 │ │ │ └── RefundRepository.java │ │ └── application/ │ │ └── RefundApplicationService.java │ │ │ └── orchestration/ # 编排层连接各上下文 │ ├── domain/ │ │ └── ConversationContext.java │ └── application/ │ └── OrderAssistantOrchestrator.java这种结构的关键在于每个限界上下文都有自己独立的领域层和应用层彼此通过编排层协调不直接依赖。3.2 领域层把业务规则写进代码DDD的核心原则是充血模型——业务逻辑封装在领域对象中而不是散落在Service层。对于AI业务来说这意味着Prompt策略是领域知识的一部分应该与业务规则放在一起**意图的“业务含义”**由领域对象表达而不是靠字符串匹配以Intent聚合根为例// intent/domain/Intent.javapublicclassIntent{privatefinalIntentIdid;privatefinalIntentTypetype;// CONSULTATION / QUERY / REFUNDprivatefinalStringrawInput;privatefinalMapString,Objectentities;// 提取的实体privatefinaldoubleconfidence;privateIntent(IntentIdid,IntentTypetype,StringrawInput,MapString,Objectentities,doubleconfidence){this.idid;this.typetype;this.rawInputrawInput;this.entitiesentities;this.confidenceconfidence;}// 工厂方法创建意图publicstaticIntentfromRawInput(Stringinput,IntentClassifierclassifier){ClassificationResultresultclassifier.classify(input);returnnewIntent(IntentId.generate(),result.getType(),input,result.getEntities(),result.getConfidence());}// 领域行为判断意图是否可信publicbooleanisConfident(){returnconfidence0.7;}// 领域行为获取必需的实体publicTTgetEntity(Stringkey,ClassTtype){if(!entities.containsKey(key)){thrownewMissingEntityException(缺少必需实体: key);}returntype.cast(entities.get(key));}// getters...}再看Order聚合根将订单的业务规则封装在领域对象内// order/domain/Order.javaEntityTable(nameorders)publicclassOrder{IdprivateStringorderNumber;privateStringcustomerId;privateOrderStatusstatus;privateMoneytotalAmount;privateLocalDateTimecreatedAt;// 领域行为取消订单publicvoidcancel(){if(status!OrderStatus.PAIDstatus!OrderStatus.CREATED){thrownewIllegalStateException(订单状态为 status无法取消);}this.statusOrderStatus.CANCELLED;// 发布领域事件DomainEventPublisher.publish(newOrderCancelledEvent(this.orderNumber));}// 领域行为确认退款资格publicbooleanisRefundable(){// 只有已支付且在7天内的订单可退款returnstatusOrderStatus.PAIDcreatedAt.isAfter(LocalDateTime.now().minusDays(7));}// getters/setters...}3.3 应用层协调领域对象完成用例应用层不包含业务逻辑只负责编排——从仓储取聚合根、调用领域方法、再存回去。以退款处理为例// refund/application/RefundApplicationService.javaServiceTransactionalRequiredArgsConstructorpublicclassRefundApplicationService{privatefinalOrderRepositoryorderRepository;privatefinalRefundRepositoryrefundRepository;privatefinalRefundPolicyrefundPolicy;publicRefundResultapplyRefund(StringorderNumber,Stringreason){// 1. 从仓储获取订单聚合根OrderorderorderRepository.findByOrderNumber(orderNumber).orElseThrow(()-newOrderNotFoundException(orderNumber));// 2. 调用聚合根的领域方法进行业务校验if(!order.isRefundable()){thrownewRefundNotAllowedException(该订单不具备退款资格);}// 3. 构建退款领域对象RefundOrderrefundOrderRefundOrder.create(order,reason,refundPolicy.calculateRefundAmount(order));// 4. 执行退款调用领域方法refundOrder.process();// 5. 持久化refundRepository.save(refundOrder);// 6. 发布领域事件DomainEventPublisher.publish(newRefundProcessedEvent(refundOrder));returnRefundResult.from(refundOrder);}}注意整个业务流程中业务规则都在领域层Order.isRefundable()、RefundOrder.process()应用层只是把“原材料”准备好、把“流程”串起来。3.4 基础设施层隔离技术细节基础设施层实现领域层定义的接口把技术细节LLM调用、数据库访问、外部API隔离出去。// intent/infrastructure/LLMIntentClassifierImpl.javaComponentRequiredArgsConstructorpublicclassLLMIntentClassifierImplimplementsIntentClassifier{privatefinalChatClientchatClient;privatestaticfinalStringPROMPT_TEMPLATE 你是一个意图识别专家。分析以下用户输入判断用户意图属于以下哪种类型 - CONSULTATION: 商品咨询询问商品功能、规格、价格等 - QUERY: 订单查询查询订单状态、物流等 - REFUND: 退款申请要求退货、退款 同时提取关键实体如商品名称、订单号。 用户输入%s 以JSON格式返回结果。 ;OverridepublicClassificationResultclassify(Stringinput){StringresponsechatClient.prompt().user(String.format(PROMPT_TEMPLATE,input)).call().content();// 解析LLM返回的JSONreturnparseClassificationResult(response);}}四、第三步用“编排层”把多Agent协作串起来对于多意图场景需要一个编排层Orchestration Layer来协调各限界上下文的协作。这里推荐使用工作流Graph/Workflow模式把业务流程表达为一张有向图。4.1 定义工作流状态// orchestration/domain/ConversationContext.javaDatapublicclassConversationContext{privateStringsessionId;privateStringuserId;privateStringuserInput;privateStringfinalReply;// 中间结果privateIntentintent;privateListOrderqueriedOrders;privateRefundOrderrefundOrder;// 流程控制privateStringcurrentStep;privateListStringexecutionPath;}4.2 构建状态图参考Spring AI Alibaba Graph模式// orchestration/infrastructure/AssistantGraphConfig.javaConfigurationpublicclassAssistantGraphConfig{BeanpublicStateGraphConversationContextorderAssistantGraph(EntryNodeentryNode,IntentRouterNodeintentRouterNode,ProductAgentNodeproductNode,OrderAgentNodeorderNode,RefundAgentNoderefundNode){StateGraphConversationContextgraphnewStateGraph();// 注册节点graph.addNode(entry,entryNode);graph.addNode(intent_router,intentRouterNode);graph.addNode(product_agent,productNode);graph.addNode(order_agent,orderNode);graph.addNode(refund_agent,refundNode);// 设置入口graph.setStart(entry);// 固定边graph.addEdge(entry,intent_router);// 条件边根据意图路由到不同Agentgraph.addConditionalEdges(intent_router,context-context.getIntent().getType().name(),Map.of(CONSULTATION,product_agent,QUERY,order_agent,REFUND,refund_agent,StateGraph.END,StateGraph.END));// Agent节点到结束graph.addEdge(product_agent,StateGraph.END);graph.addEdge(order_agent,StateGraph.END);graph.addEdge(refund_agent,StateGraph.END);returngraph;}}这种图结构的好处是业务流与代码结构一一对应。新增一个意图类型时只需添加一个节点和一条条件边不影响已有逻辑。4.3 各Agent节点实现以商品咨询为例// orchestration/infrastructure/nodes/ProductAgentNode.javaComponentRequiredArgsConstructorpublicclassProductAgentNodeimplementsNodeConversationContext{privatefinalProductConsultationServiceproductService;OverridepublicConversationContextapply(ConversationContextcontext){StringuserInputcontext.getUserInput();// 调用商品咨询限界上下文的应用服务StringreplyproductService.consult(userInput);context.setFinalReply(reply);context.setCurrentStep(product_agent);context.getExecutionPath().add(product_agent);returncontext;}}五、关键原则与避坑指南5.1 三条核心原则时序图先行代码后行任何新功能先画时序图再写代码保证团队对流程有一致理解限界上下文 限界Prompt每个上下文的Prompt策略独立维护互不干扰领域逻辑决不允许泄露到应用层像if (status PAID)这种判断必须写在聚合根内部5.2 常见陷阱陷阱症状解决方案贫血的聚合根所有业务逻辑都在Service层领域对象只是数据容器把业务方法移到聚合根内跨上下文直接调用Order上下文直接调用Refund上下文的方法通过领域事件异步解耦Prompt散落各处同样的Prompt在3个地方出现改一处忘两处把Prompt集中管理在对应上下文的配置类中时序图与代码脱节画完图就扔一边代码和图对不上把时序图作为设计文档Code Review时对照检查六、写在最后回到开头的问题为什么AI项目容易越做越乱因为AI能力的“魔法感”让团队忽视了它作为业务系统的本质。无论是意图识别、Prompt编排还是多Agent协作本质上都是业务逻辑——它们应该被建模、被组织、被封装而不是被“塞进”代码的缝隙里。时序图和DDD的组合拳解决的是认知负载问题时序图让团队看清流程全貌减少沟通偏差DDD的限界上下文把大问题拆成小问题每个团队/每个人负责一个边界清晰的模块充血模型让业务规则显式化新人看代码就能理解业务这套方法论不是AI专属但对于AI项目的复杂度来说它比任何时候都更必要。下次接到新需求时先画图、再分模块、最后写代码——让复杂业务变得可控从这两张图开始。

相关新闻

00110

00110

101010

2026/10/25 14:15:47 阅读更多 →
Abaqus PythonReaderPro

Abaqus PythonReaderPro

PythonReader Pro ABAQUS CAE 实时 Python 命令流监控阅读器 💾 下载 最新版本 v2.1 | 📥 下载 Windows x64 版 解压即可运行,无需安装 .NET 运行时。历史版本请见 Releases。 简介 PythonReader Pro 是一款专为 ABAQUS CAE 用户设计的实时…

2026/10/25 7:45:54 阅读更多 →
Hy-Embodied-RxBrain-1.0社区与支持:如何参与贡献与获取帮助

Hy-Embodied-RxBrain-1.0社区与支持:如何参与贡献与获取帮助

Hy-Embodied-RxBrain-1.0社区与支持:如何参与贡献与获取帮助 【免费下载链接】Hy-Embodied-RxBrain-1.0 项目地址: https://ai.gitcode.com/tencent_hunyuan/Hy-Embodied-RxBrain-1.0 Hy-Embodied-RxBrain-1.0是腾讯混元团队开发的具身认知基础模型&#xf…

2026/10/26 8:57:20 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/26 12:00:21 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/27 4:06:49 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/26 4:52:12 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/26 12:00:21 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/27 6:20:47 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/27 4:06:50 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/26 12:00:19 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/25 13:21:54 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/26 8:34:37 阅读更多 →