基于LangChain4j的条件工作流:从规则预检到模型路由的Agent分支决策实践

做Agent设计模式这个系列做到第五篇,条件工作流算是我在真实项目里用得最多、也最容易翻车的部分。这期基于 LangChain4j 把“分支决策”这件事拆开聊:为什么简单的 if-else 不够用、怎么让模型自己决定走向哪个分支、以及循环和重试怎么落到代码里。适合那些已经能用 LangChain4j 跑通基础对话,想进一步把 Agent 流程设计成复杂业务系统的朋友。

1. 条件工作流到底解决什么问题

1.1 一个多场景助手的分支需求

先看一个很常见的场景:你要写一个客服助手,用户进来之后可能问天气、可能设置提醒、可能只是打个招呼。三个任务如果放在同一个系统提示词里,让一个模型接口直接回答,会出现两个典型问题:第一,提示词里要同时塞入不同业务的规则和输出要求,整体会变得很长,模型在长上下文中更容易忽略其中某一条;第二,不同任务可能需要调用不同的工具、返回不同的字段结构,强行在一个“万能助手”里做,代码会变成一堆 if-else 嵌套,而且每加一个业务都要重新调整提示词,测试成本翻倍。

条件工作流解决的就是这件事:把“用户进来之后到底走哪条处理链路”这个决策单独抽出来,先把意图分清楚,再让不同的小助手各管一段。你可以把整个流程想成公司前台:前台先问“办什么业务”,然后引导你去对应窗口,而不是所有人都挤在一个柜台后面处理所有问题。

1.2 条件工作流的核心是流程编排而不是分支语法

很多人一听到“条件工作流”,第一反应就是代码里的 switch、if-else。语法层面确实如此,但真正要设计的不是“怎么判断”,而是“在哪个环节判断、判断结果怎么影响后续流程”。

在 Agent 设计模式里,条件工作流通常出现在两个层次:

  • 业务规则层:根据输入内容、上下文状态、用户参数做判断,比如“消息里包含城市和时间就查天气”,这种判断不依赖模型,速度快、结果稳定。
  • 模型推导层:机器无法用规则覆盖所有表达,比如“明天会不会下雨”和“明天适合带伞吗”在表达上完全不同,但意图可能接近。这种语义判断需要让模型参与决策。

条件工作流的价值在于把这两层组合起来:先用规则拦截能明确判断的请求,再把模糊的请求交给模型路由,最后根据路由结果选择不同的执行分支。这里的“条件”可以是静态规则、模型输出、工具执行结果,甚至可以跨越多个节点形成一个循环,直到某个终止条件满足才退出。

与顺序工作流相比,条件工作流最大的变化是:执行路径不是预编译好的单选题,而是运行时依赖输入内容和中间结果动态生成的。这也意味着,你的代码一旦写成,就要面对“模型判断错了怎么办”的局面。

2. 条件工作流的实现路线怎么选

2.1 规则预检:先拦截,再问模型

我习惯在任何条件工作流的最前面加一道规则预检,而不是把所有判断都丢给模型。原因很简单:规则预检免费、确定、无延迟。比如用户消息里包含“天气”并且包含一个城市名,或者包含“提醒我”和时间短语,这些特征可以通过一个很小的正则表达式或者关键词表命中,根本不需要调用模型。

规则预检适合处理高频且表达相对固定的场景。它的缺点也明显:自然语言变化太多,完全靠规则覆盖所有情况不现实。比如用户说“今天出门穿什么?”,这句话里没有“天气”两个字,但本质上是天气查询。这时规则会漏掉,必须让模型介入。

所以我的设计原则是:规则预检负责“能确定的就确定”,模型路由负责“规则拿不准的再兜底”。两者结合,能在成本、延迟和准确率之间取得一个比较平衡的位置。

2.2 模型路由:让 LLM 决策意图

模型路由的核心思想是:把路由本身当成一个 Agent 任务,让模型输出一个结构化结果,然后用这个结果驱动代码分支。

常见的做法是让模型返回一个枚举值或一个 JSON 对象,比如{"action":"WEATHER_QUERY","reason":"用户询问明天天气"}。LangChain4j 里可以用接口方法和返回对象的方式让模型直接映射到 Java 类,省去手写 JSON 解析的麻烦。

模型路由的优势是覆盖面广、语义理解强,几乎不用维护规则表。但代价也很现实:每次路由多一次 LLM 调用,增加延迟和成本;如果返回格式不稳定,下游直接解析失败;如果枚举值太多、划分太细,模型也容易混淆。后面我会专门讲怎么避免这几个坑。

另外要注意,模型路由不只是用在大入口做意图分类,还可以用在流程中间。比如“根据当前工具的返回结果决定是否再做一次检索”,这就是循环条件的一种体现。

2.3 状态机与循环:处理更复杂的状态转移

条件工作流并不只有“一个入口 + 几个分支”这种形态。还有一种更复杂的形态是状态机:整个 Agent 会话会经历多个状态,每个状态都是一个独立的节点,在不同节点间根据条件转移。

比如一个售后工单助手,状态可能是收集问题 -> 确认诉求 -> 给方案 -> 回访结束。用户在“确认诉求”状态下输入的内容,处理方式和“收集问题”状态下完全不一样。这种场景如果只靠入口路由一次,无法解决,因为后续每一步都需要根据状态选择行为。

LangChain4j 本身没有专门的工作流引擎,但状态机的逻辑可以自己用 Java 代码维护:定义一个状态枚举,维护状态转移表,在每次接收用户输入时先判断当前状态,再路由到对应处理节点。循环也可以理解为一种特殊的状态机——“状态”在同一个节点反复执行,直到满足退出条件。

3. 基于 LangChain4j 实现一个条件工作流

3.1 依赖准备与模型接入

我使用的版本是 LangChain4j 1.x,依赖比较简单。如果你用 Maven,在pom.xml里加核心包和应用框架包即可:

<dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-core</artifactId> <version>1.0.0</version> </dependency>

模型接入我习惯写一个工厂方法,把具体模型服务的配置和环境变量绑在一起,这样切换模型服务时不用改业务代码。下面是示意:

public class ModelFactory { public static ChatLanguageModel createChatModel() { String baseUrl = System.getenv("MODEL_BASE_URL"); String apiKey = System.getenv("MODEL_API_KEY"); String modelName = System.getenv("MODEL_NAME"); // 这里使用兼容主流协议的消息模型实现,具体厂商类放在基础设施层 return ChatLanguageModel.builder() .baseUrl(baseUrl) .apiKey(apiKey) .modelName(modelName) .build(); } }

依赖注入或者单例管理都可以,核心是业务代码只面对ChatLanguageModel接口,不会因为底层模型变动而跟着改动。

3.2 定义路由结果与分支动作

路由结果最好用一个枚举加一个数据类来表达。枚举控制分支走向,数据类可以携带模型给出的理由,便于日志排查。

public enum WorkflowAction { WEATHER_QUERY, REMINDER_SET, GREETING, UNKNOWN } public class WorkflowDecision { private WorkflowAction action; private String reason; public WorkflowAction getAction() { return action; } public void setAction(WorkflowAction action) { this.action = action; } public String getReason() { return reason; } public void setReason(String reason) { this.reason = reason; } }

枚举数量一定要克制。我见过有人把路由枚举拆成二十多个分支,结果模型经常分错。一般情况下,一个大入口的顶层路由控制在五到七个动作以内会比较稳。如果业务确实很多,可以考虑先粗分再细分,用多级路由。

3.3 编写路由接口及分支 Agent

LangChain4j 的AiServices可以让我们通过接口定义 Agent,非常直观。我先定义一个路由接口:

public interface DecisionRouter { @SystemMessage(""" 你是任务路由引擎。根据用户消息判断意图,只输出JSON格式。 可选动作:WEATHER_QUERY、REMINDER_SET、GREETING、UNKNOWN。 JSON格式:{"action":"动作枚举","reason":"选择理由"} 不要输出其他文字。 """) WorkflowDecision route(@UserMessage String userMessage); }

这里让返回类型直接是WorkflowDecision,LangChain4j 会尝试把模型输出解析成 Java 对象。返回类型设计成 POJO,比返回一个字符串再手工解析省事得多。

接下来定义分支 Agent,也就是真正干活的小助手:

public interface WeatherAgent { @SystemMessage("你是天气问答助手,负责根据用户问题提供简洁的天气建议。") String handle(@UserMessage String userMessage); } public interface ReminderAgent { @SystemMessage("你是提醒助手,负责把用户请求整理成提醒信息并确认。") String handle(@UserMessage String userMessage); }

这样设计的好处是每个分支的提示词互相独立,互不干扰。后续改天气助手的提示词,完全不会影响提醒助手。

3.4 主流程编排代码实现

有了路由接口和分支 Agent,就可以写主流程了。我把整个流程放在一个类里,叫ConditionalWorkflow。入口方法先做规则预检,再走模型路由,最后分发到具体分支。

public class ConditionalWorkflow { private final DecisionRouter router; private final WeatherAgent weatherAgent; private final ReminderAgent reminderAgent; public ConditionalWorkflow(ChatLanguageModel model) { this.router = AiServices.builder(DecisionRouter.class) .chatLanguageModel(model) .build(); this.weatherAgent = AiServices.builder(WeatherAgent.class) .chatLanguageModel(model) .build(); this.reminderAgent = AiServices.builder(ReminderAgent.class) .chatLanguageModel(model) .build(); } public String execute(String userMessage) { // 第一步:规则预检,能确定的直接分流 WorkflowAction preAction = PreRule.match(userMessage); if (preAction != null) { return dispatch(preAction, userMessage); } // 第二步:模型路由 WorkflowDecision decision = router.route(userMessage); WorkflowAction action = decision.getAction(); if (action == null || action == WorkflowAction.UNKNOWN) { return fallback(userMessage); } return dispatch(action, userMessage); } private String dispatch(WorkflowAction action, String userMessage) { switch (action) { case WEATHER_QUERY: return weatherAgent.handle(userMessage); case REMINDER_SET: return reminderAgent.handle(userMessage); case GREETING: return greetingReply(userMessage); default: return fallback(userMessage); } } private String greetingReply(String userMessage) { return "你好,有需要随时告诉我。"; } private String fallback(String userMessage) { return "抱歉,我还没有完全理解你的需求,可以换个说法试试。"; } }

这段代码最关键的是把“判断”和“执行”拆开。execute方法里没有业务判断逻辑,它只知道“决定完了就分发”;真正的判断逻辑分散在规则预检和模型路由里。这样后续加一个新分支,只需要新增一个枚举值、一个分支接口、一个 case 分支,改动集中且可控。

PreRule.match是我抽出来的规则预检工具,内部就是关键词和正则,这里不展开。实际项目中我建议把它做成可配置的规则表,而不是硬编码在代码里。

3.5 循环重试与终态控制

条件工作流中还有一个高频场景:循环。比如“生成方案 -> 自动评估 -> 不合格则重写”,直到评估通过或者达到最大次数。这个循环本质上也是条件判断驱动的,只不过判断对象是模型输出结果。

我用一个简化例子说明:写一段文案,然后用评测模型打一个合格/不合格标记,循环三次。

public interface WriterAgent { String write(@UserMessage String instruction); } public interface JudgeAgent { @SystemMessage("你是质检员,判断文案是否符合要求,只输出JSON:{\"passed\":true,\"reason\":\"...\"}") JudgeResult evaluate(@UserMessage String instructionAndText); } public static class JudgeResult { private boolean passed; private String reason; // getters/setters }

循环流程:

public String generateWithQualityCheck(String instruction) { String answer = null; for (int i = 0; i < 3; i++) { answer = writerAgent.write(instruction); JudgeResult result = judgeAgent.evaluate("需求:" + instruction + "\n文案:" + answer); if (result.isPassed()) { return answer; } System.out.println("第" + (i + 1) + "次未通过,原因:" + result.getReason()); } return answer; }

这里有两个必须注意的点。第一,必须有最大迭代次数,否则模型一直不合格就会无限循环,既浪费 token 又拖垮服务。第二,最后一次循环即使不合格也应返回结果,不要返回空字符串。业务上“拿一个不够完美的结果”比“什么都没有”更好兜底。

4. 实操中值得注意的细节与排查经验

4.1 不要让模型输出“自由格式”的意图

我第一次做模型路由时,直接在系统提示词里写“请先判断用户的意图,然后给出回答”,把路由和回答混在一个接口里。结果模型输出一大堆解释文本,我很难稳定地拿到意图字段。

后来改成“路由专用接口只输出 JSON”,情况立刻稳定了很多。LangChain4j 在把模型输出映射到 POJO 时,要求模型输出尽量贴近目标结构。你在系统提示词里给一个两个范例,效果会更好。

还有一点:WorkflowDecision里的reason字段不要省略,它不影响分支逻辑,但能让排查问题的人立刻看到模型为什么选了这条路。没有reason,出问题时只能瞎猜。

4.2 路由 Prompt 越短,越不容易翻车

路由接口的系统提示词不需要写太多业务背景。它只需要知道“有哪些动作可选、各自代表什么含义、输出成什么格式”。写多了反而容易让模型花更多 token 去理解无关上下文。

我给路由提示词定过三条原则:

  • 动作枚举必须在提示词里原样列出,并且说明一定是 JSON 字段值。
  • 枚举不超过七个,否则模型混淆率明显上升。
  • 每个动作配一个极简解释,但不要贴大段示例数据。

如果你的路由需求确实复杂,不要硬塞到一段提示词里。拆成多级路由,先用一个粗粒度接口判断大类,再在各自分支里用更细的提示词判断小类,整体准确率通常更高。

4.3 排查条件工作流问题的日志套路

条件工作流出问题时,最难的是不知道在哪一环断的。我现在的习惯是给每个关键节点加结构化日志,至少记录四个信息:用户输入原文、路由决策、决策理由、分支执行耗时。

实际日志长这样:

input=明天上海有雨吗 preRule=null decision=WEATHER_QUERY reason=用户询问天气情况 branch=weatherAgent costMs=842

有了这类日志,定位问题就快很多。如果预检命中了但结果不对,说明规则写太宽;如果预检没命中,模型路由选错,那就去看 reason;如果分支输出不对,问题往往在对应 Agent 的提示词而不是路由。

这条经验帮我省过很多次时间,建议你把日志从一开始就埋好,不要等上线后出问题再补。

4.4 常见问题速查表

现象可能原因解决思路
模型路由返回中文而非枚举系统提示词约束不够强强化“只输出 JSON”和枚举取值,给一个输出范例
分支 Agent 回答跑题路由正确但分支提示词与任务不匹配检查对应分支 Agent 的系统提示词
JSON 解析频繁失败模型输出中混入了多余文本改用接口返回 POJO;增加一次重试解析
循环不结束缺少最大迭代次数或退出条件增加计数器,最多迭代 N 次后返回当前结果
路由枚举太多,准确率下降顶层分支划分过细拆成多级路由,或把枚举数量控制在七个以内
条件工作流整体响应变慢每次路由都额外调用一次模型前面加规则预检,能确定的请求不走模型路由
模型选错动作但 reason 正确提示词语义模糊调整动作解释,增加 positive/negative few-shot 示例

一个关于条件粒度的小经验

这个系列写到现在,我个人最大的体会是:条件工作流的复杂度和模型能力成反比。模型能力越强,越可以用更粗的粒度让它自己决策;模型能力弱,就越需要把条件写显式,多依赖规则预检和状态机兜底。另外,不管条件工作流设计得多漂亮,一定要给每个分支留一个容错出口。我见过太多次因为模型在某个分支上输出异常,导致整条链路崩掉的情况。后续如果想继续扩展,可以顺着这个条件路由的思路,把缓存、超时、熔断这些稳定性策略加进来,那又是另一个主题了。

相关新闻

智能体路由设计:从规则到语义的落地实践与避坑指南

智能体路由设计:从规则到语义的落地实践与避坑指南

做了几年智能体应用&#xff0c;我越来越觉得路由&#xff08;Routing&#xff09;是整套系统里最容易被低估&#xff0c;却又最能决定上限的模块。智能体开发里所谓的路由&#xff0c;就是让系统在合适的时机、把合适的请求送到合适的处理方手里——无论是选大模型、选工具&am…

2026/10/21 5:43:16 阅读更多 →
游戏UI环形布局:动态参数化控件环绕实现方案

游戏UI环形布局:动态参数化控件环绕实现方案

1. 项目概述&#xff1a;为什么一个“UI控件环绕”能成为游戏客户端开发中的高频需求“UI控件环绕特效”这八个字&#xff0c;听上去像美术同学随口提的一句需求&#xff0c;但在我过去十年参与的二十多个中大型游戏客户端项目里&#xff0c;它几乎出现在每一轮版本评审会上——…

2026/10/21 5:42:16 阅读更多 →
AI智能体进阶五级法则:从失控到工程化的实战指南

AI智能体进阶五级法则:从失控到工程化的实战指南

破题&#xff1a;如果你不崩溃&#xff0c;说明你还没做AI智能体做了两年多AI智能体落地&#xff0c;我最大的感受是&#xff1a;每个号称“AI应用研发专家”的人&#xff0c;职业生涯大概都逃不过一次体面尽失的崩溃。不是测试不通过的崩溃&#xff0c;是那种线上用户疯狂反馈…

2026/10/21 5:42:16 阅读更多 →

最新新闻

企业微信H5授权登录全攻略:从OAuth流程到access_token缓存实战

企业微信H5授权登录全攻略:从OAuth流程到access_token缓存实战

1. 认清本质&#xff1a;企业微信H5授权到底在干嘛很多初接触企业微信H5开发的童鞋&#xff0c;一上来就盯着那些API文档和参数名死磕&#xff0c;结果把企业微信授权登录完全理解成了传统的账号密码登录。这玩意儿跟微信公众平台的网页授权是一脉相承的思路&#xff0c;但又多…

2026/10/21 6:24:34 阅读更多 →
K8S NFS动态供给实战:StorageClass与Provisioner部署指南

K8S NFS动态供给实战:StorageClass与Provisioner部署指南

1. 为什么要在 K8S 里折腾 NFS 动态供给1.1 从一次存储告警说起事情的起因很简单&#xff1a;某天凌晨收到一条告警&#xff0c;某个有状态服务的 Pod 因为 PVC 一直处于 Pending 状态起不来&#xff0c;业务直接中断。排查下来发现&#xff0c;之前团队用的是静态 PV 的方式—…

2026/10/21 6:24:34 阅读更多 →
HarmonyOS接入AGC认证服务:邮箱验证码登录完整实现与踩坑记录

HarmonyOS接入AGC认证服务:邮箱验证码登录完整实现与踩坑记录

如果你的App需要一套“用户输入邮箱、收到六位验证码、填入即登录”的流程&#xff0c;用华为AGC的认证服务来落地&#xff0c;能省掉自己搭邮件服务和找回密码逻辑的不少功夫。我最近接HarmonyOS端需求&#xff0c;就是用AGC的认证服务来做邮箱验证码登录&#xff0c;本以为照…

2026/10/21 6:24:34 阅读更多 →
技能管理框架实践:从能力数据化到团队协作与个人成长

技能管理框架实践:从能力数据化到团队协作与个人成长

1. 别被“skills”这个名字骗了&#xff1a;它到底是个什么东西我第一次看到“skills”这个项目名的时候&#xff0c;第一反应是“这不就是个技能列表吗”。但真正把项目完整跑起来之后&#xff0c;我才发现自己错得离谱。它既不是一份简历上的技能清单&#xff0c;也不是某个系…

2026/10/21 6:24:34 阅读更多 →
友盟分享SDK 6.4.6_custom接入指南:Android多平台分享集成与避坑

友盟分享SDK 6.4.6_custom接入指南:Android多平台分享集成与避坑

简介&#xff1a;友盟分享安卓社交软件开发工具包定制版&#xff0c;面向需要为应用添加分享能力的移动开发者&#xff0c;它整合了微信、QQ、微博等国内主流社交平台及Facebook、Twitter等海外渠道&#xff0c;通过统一接口即可完成多平台分享调用&#xff0c;省去分别对接各个…

2026/10/21 6:24:34 阅读更多 →
自动驾驶入门课程导论:知识体系、学习路径与工具链全解析

自动驾驶入门课程导论:知识体系、学习路径与工具链全解析

1. 从"欢迎"两个字里读出这门课的野心很多人看到"欢迎来到课程"这种标题&#xff0c;第一反应是划走——这不就是个开场白吗&#xff0c;有什么好讲的。但我做了这么多年技术内容&#xff0c;越来越觉得一门课的第一节"欢迎课"其实是最能暴露设计…

2026/10/21 6:23:34 阅读更多 →

日新闻

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

这段时间硬件圈和AI圈都在传一个事&#xff1a;AMD锐龙AI Max PRO 400系列把最高192GB统一内存搬进了PC形态的产品里&#xff0c;按宣传口径&#xff0c;本地跑320B参数的大家伙不再是纸面概念。我第一反应倒不是“内存真大”&#xff0c;而是这话背后的含金量——它把过去只能…

2026/10/21 0:00:11 阅读更多 →
AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

1. 从“封号重开”这个行为说起&#xff1a;用户到底在追求什么“封号重开”这四个字&#xff0c;放在任何产品语境里都带着一股决绝的味道。一个账号从零开始积累使用记录、调教偏好、沉淀工作流&#xff0c;背后是大量的时间和精力成本。正常情况下&#xff0c;没有人愿意主动…

2026/10/21 0:00:11 阅读更多 →
ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

1. 为什么在ROS里硬刚YOLOv3不是“炫技”&#xff0c;而是工程落地的必经之路我第一次在某高校机器人实验室看到那台搭载Jetson TX2的移动底盘原地打转、反复识别错垃圾桶时&#xff0c;就意识到&#xff1a;单纯跑通darknet_ros demo和真正让YOLOv3在ROS里“干活”&#xff0c…

2026/10/21 0:00:11 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/21 4:27:17 阅读更多 →

月新闻

我发现了一个新思路:用 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/20 10:02:08 阅读更多 →
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/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练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/20 9:50:45 阅读更多 →