刚开始接触 Jev 的时候我也被“不写文本”这个描述搞得有点懵。做了几年提示词工程大家默认的共识都是 prompt 越长越详细越好怎么到了 Jev 这里反而不让写文本了后来在 Codex 这类 Agent 环境里跑了几轮我才回过味来Jev 并不是不让你表达需求而是换了一种表达方式——把“告诉模型怎么做”变成了“让模型在给定的选项中做决策”。这个转变本质上就是从“生成式提示词”转向“类型化决策”。这篇文章我想把这个思路彻底拆开聊。不管你是刚接触 Jev 的小白还是已经在 Agent 开发里摸爬滚打的老手只要能理解“类型化决策”这四个字背后的设计逻辑你就能少走很多弯路。我会从原理讲到实操最后把踩过的坑也一并列出来照着做基本就能在自己的项目里落地。1. 先搞懂“不写文本”到底在说什么1.1 传统提示词工程的瓶颈在哪里传统提示词工程的核心是“写”。写角色设定、写任务描述、写步骤清单、写约束条件恨不得把所有可能性都塞进那几段文字里。这种方式在单轮对话、简单任务上确实有效可一旦进入 Agent 场景问题就暴露出来了。首先是输出不稳定。同样一段 prompt模型每次给的结果措辞不同、结构不同甚至执行路径都可能跑偏。你写“如果测试失败请尝试修复”模型可能真的去改代码也可能只是把错误信息复述一遍还可能直接给出一个完全不相关的建议。文本描述得再详细模型理解时仍然存在歧义空间。其次是上下文浪费。Agent 场景里每一轮工具调用都要消耗 token长文本 prompt 会占用大量上下文窗口。更糟糕的是这些文本往往只是“指令”并不是“信息”。模型需要的是当前仓库状态、函数签名、错误日志这类硬数据而不是一大段“你是一个优秀的软件工程师”式的角色扮演。还有一点很难受不可编程。文本 prompt 没法被程序解析、校验、分支。你想根据模型输出做自动化处理就得靠正则或字符串匹配去猜它的意图这在工程上是极其脆弱的。我见过太多团队在解析 LLM 输出时写出一堆 hack 代码最后维护成本比写 prompt 本身还高。1.2 Jev 的“不写文本”本质是决策优先Jev 的思路完全反过来。它不要求用户写“怎么做”而是要求用户定义“有哪些选择”。模型要做的事情不再是生成一段自由文本而是在一个预先定义好的决策空间里做出选择。举个例子传统 prompt 会让你写如果测试失败了分析失败原因然后决定是修改代码、补充日志还是上报人工。Jev 式的做法则是定义一个决策结构{ decision_point: test_failure_handler, available_actions: [modify_implementation, add_logging, escalate_to_human], context_required: [test_output, failure_bucket, recent_changes] }模型收到的是这个结构化定义和必要上下文输出的是一个决策枚举值附带少量结构化参数。没有大段解释没有多余修辞只有干净利落的“我选择做什么”。这个转变的本质是把模型从“答题者”变成“选择题作答者”。问答题可以自由发挥全凭模型心情选择题则框架清晰答错了你知道它错在哪一步答对了你知道它为什么对。这种确定性在 Agent 里就是生命线。用生活化的类比来说传统 prompt 是让实习生“根据你的理解去处理这件事”类型化决策是给实习生一张工单选择表问题属于 A 类就走 A 流程属于 B 类就走 B 流程。看起来少了些“智能感”但实际跑起来稳定性完全不在一个量级。2. 类型化决策的核心方法论2.1 把任务拆成决策树而不是步骤清单类型化决策的第一步是重新理解任务结构。大部分人写 prompt 时习惯列步骤先做 A再做 B然后 C。这在确定性流程里没问题但 Agent 的任务往往存在大量分支预设步骤根本覆盖不全。决策树的思路是用来拆的每个节点代表一个“需要判断的情况”每个分支代表一种“可执行的动作”。根节点是任务的入口子节点是不同情境下的决策点叶子节点是具体动作。以“修复测试失败”为例根决策测试失败了失败类型是什么编译错误 / 断言失败 / 超时 / 环境问题编译错误分支是引入的 API 变了还是语法错误断言失败分支是期望值不对还是实现逻辑有 bug超时分支是算法复杂度问题还是外部依赖阻塞每个叶子节点对应一个具体动作修改调用代码、改实现、加超时处理、上报人工。这个拆法跟传统步骤清单的最大区别在于决策树是“分支导向”的每个分支点都要求模型做一次类型化判断步骤清单是“顺序导向”的模型经常在第一步卡住之后就不知道怎么办了。实操建议拆决策树时最多拆到三层深度超过三层的分支要么合并要么拆成独立的子决策流程。决策树太深模型判断的准确率会下降调试起来也费劲。我见过好的实践是把树控制在“根决策 一级分支 叶子动作”的结构清晰又好维护。2.2 用类型定义约束输出空间这是“类型化”三个字的核心。所谓类型就是给模型的输出加上一道硬约束让它只能在限定范围内选择而不是自由发挥。常用的类型约束手段有三种第一种是枚举类型。适用于“情况已经被前人总结过”的场景。比如代码变更类型可以定义为[feature, bugfix, refactor, docs, test]。模型只能输出其中一个值不允许发明新的。枚举最大的价值是让输出变成可解析的固定值程序拿到之后可以直接走 switch 分支。第二种是结构体类型。适用于“决策需要附带参数”的场景。比如模型选择“修改实现”那它需要同时给出修改的目标文件、修改的思路、风险评估等字段。结构体定义了完整的数据契约比让模型自由写一段说明更可靠。第三种是条件依赖类型。适用于“不同决策对应不同参数”的场景。比如模型选择“上报人工”那不需要修改文件字段但需要上报原因模型选择“修改代码”那不需要上报原因但需要文件路径。条件依赖可以通过 JSON Schema 的oneOf或if-then-else来表达让模型只在当前决策对应的分支里填参数。这里有个很容易忽略的点所谓“不写文本”不是指模型输出里完全没有文本而是指“决策本身不依赖文本表达”。模型仍然可以用结构化字段里的reason字段写一句简短理由但程序逻辑只依赖枚举值和结构字段不依赖那段理由。把理由当作文档留给人看而不是当作文本留给程序解析。这个区分很重要。2.3 上下文工程配合类型化决策类型化决策再完美也需要信息支撑。模型做判断的依据不是 schema 本身而是当时拿到的上下文。这里要区分两类上下文指令型上下文和信息型上下文。指令型上下文描述的是“怎么做”比如角色设定、禁止事项。这类内容在 Jev 体系里要尽量少因为决策空间已经定义清楚了重复强调“你要做一个谨慎的工程师”没有意义反而稀释注意力。信息型上下文描述的是“现状是什么”比如当前仓库文件结构、最近一次提交的 diff、测试失败的具体日志、相关函数的签名。这些才是模型做决策真正需要的输入。实际操作中我建议把信息型上下文按“决策相关性”做筛选。一个常见的错误是为了保险把整个仓库的文件内容全塞进上下文结果模型被海量无关信息淹没决策质量反而下降。正确做法是先确定当前决策需要哪些信息再把相关信息组装成固定格式的上下文块最后连同决策 schema 一起交给模型。还有个边界问题值得单独说系统提示词和 Skill Agent 在 Jev 体系里扮演什么角色。我的理解是这样系统提示词负责“全局不变原则”比如安全规范、输出格式底线Skill Agent 负责“某一类任务的领域知识”比如“如何分析内存泄漏”这类专业流程而 Jev 负责“当前这一步做什么选择”。三者是分层关系Jev 是最靠近具体动作的一层。如果全局规则频繁变化那是系统提示词没设计好如果决策点反复出现相同分支那是应该把它抽象成 Skill如果单个决策动作本身很复杂那是 Jev 的决策粒度需要调整。这三个层次不要混在一起写。3. 实操落地Jev 式决策在 Agent 里怎么跑3.1 一个可复用的决策框架模板理论说完了来看点能直接用的东西。我把自己在项目里沉淀的决策框架模板分享出来它分成三层决策定义、执行循环、记录回放。决策定义层负责维护所有决策点及其类型约束。推荐用 JSON Schema 统一描述这样既能喂给模型又能做程序校验。下面是一个我常用的模板结构{ schema_version: 1.0, decision_points: [ { id: error_triage, description: 对报错信息进行分流, input_context: [error_log, code_snapshot], output_schema: { type: object, properties: { bucket: { type: string, enum: [syntax, runtime, logic, infra, unknown] }, confidence: { type: number, minimum: 0, maximum: 1 }, suggested_action: { type: string, enum: [fix_now, add_diagnostics, escalate] }, reason: { type: string, maxLength: 200 } }, required: [bucket, confidence, suggested_action] } } ] }这个 Schema 的精髓在于suggested_action和bucket都是枚举程序可以拿到结果后直接做映射处理reason字段虽然是个字符串但只是给人看的不参与程序逻辑。执行循环层是 Agent 主循环的改造。传统 Agent 循环是“拿任务 - 生成文本 - 提取意图 - 调工具”Jev 式循环变成“拿决策定义 - 收集上下文 - 模型选决策 - 程序分发动作”。区别在于意图提取这一步被类型化决策替代了模型输出直接就是一个可执行的动作标识。记录回放层是很多人忽视但特别重要的部分。每次决策都应该记录当前上下文摘要、模型选择的动作、置信度、最终执行结果。这套数据积累下来你就能分析出哪些决策点模型经常选错、哪些上下文字段对决策帮助最大、哪些枚举值从来没人选中。这些都是后续优化决策定义的重要依据。3.2 示例从测试失败到修复方案的完整决策流说个具体的例子。假设我在一个 Python 项目里跑测试测试挂了我想让 Jev 帮我分流这个失败。传统提示词我可能会写测试失败了请分析下面的错误日志告诉我问题出在哪里并给出修复建议 [粘贴日志]Jev 式做法完全不同。先生成一个决策点定义把失败场景的选项都列出来{ decision: test_failure_triage, context: { test_name: test_user_creation, error_message: TypeError: create_user() missing 1 required positional argument: email, recent_diff: - user create_user(name, password)\n user create_user(name, password, email), file_path: tests/test_auth.py }, choices: [ { id: missing_arg, action: repair_call_site, params: { target_files: [tests/test_auth.py] } }, { id: wrong_signature, action: update_function_def, params: { target_files: [auth/service.py] } }, { id: test_bug, action: fix_test_setup, params: { target_files: [tests/test_auth.py] } }, { id: schema_drift, action: escalate, params: { reason: 接口签名与实际调用不一致需要人工确认 } } ] }模型拿到这个决策定义和上下文之后输出{ choice_id: wrong_signature, confidence: 0.87, evidence: 调用处传了三个参数但函数定义只包含两个参数 }程序拿到choice_id之后直接分发到update_function_def这个工具把它当成一个普通函数调用处理。整个过程没有正则匹配没有文本意图猜测完全结构化。这个流程的关键价值在于可回滚、可审计。如果这次修复把别的测试搞挂了回放记录时能明确看到“模型当时判断是 wrong_signature置信度 0.87”是判断错了还是执行错了一眼就能定位。3.3 在 Codex 这类 Agent 环境中怎么接入 Jev既然热词里提到了 Jev 在 Codex 中使用这里单独说一下接入思路。Codex 本身是一个编码 Agent执行循环已经内置我们需要做的是把类型化决策嵌入到它的工具调用链路里。我的做法是写一个独立的 router 工具。Agent 在执行过程中遇到需要判断的情况时不再自己拍脑袋而是调用jev_router这个工具。jev_router接收当前上下文和决策定义返回类型化决策结果再由 Codex 根据决策结果调用后续工具。伪代码大概是这样的def jev_router(context: dict, decision_schema: dict) - dict: prompt build_decision_prompt(context, decision_schema) response jev_model.complete(prompt, response_formatjson) validated validate_decision(response, decision_schema) return validated关键点在于response_formatjson和后续的validate_decision。前者从模型端约束输出格式后者在程序端做二次校验。哪怕模型偶尔抽风输出了 schema 之外的值校验层也能拦截下来不会让坏数据流到执行层。网络热词里提到“jev密钥”这个其实就是 API key跟其他模型服务的用法一致。申请密钥、配置到环境变量然后通过 SDK 或 HTTP 调用。需要注意的一点是Jev 这种决策型模型的调用频次通常比传统生成型模型高得多因为每个决策点都要单独调一次。如果你的 Agent 跑一个大任务可能会产生几十甚至上百次决策调用密钥的权限配置和额度监控要做好。另外热词里还反映了不少人在问“Jev 模型开源吗”。从我目前掌握的信息来看Jev 是以闭源 API 服务方式提供的但这不影响我们借鉴它的方法论。哪怕你完全不用 Jev 这个具体模型只要理解了类型化决策的设计思路用 GPT-4 或任何一个大模型都能复现同样的效果。方法论是通用的模型只是载体。4. 常见问题与排查技巧实录4.1 决策项太少模型总是硬凑选项这是我会遇到的第一个坑。决策定义里选项给少了模型面对一个不在预设分类里的情况会硬塞一个相近选项导致后续动作完全跑偏。比如你定义了错误类型只有[syntax, runtime]模型遇到一个逻辑错误Logic Error大概率会往runtime上归类因为它没有别的可选。后续处理逻辑就会按运行时异常去排查方向全错。解决办法是两点一是增加unknown或other兜底选项让模型有“不确定”的出口二是在兜底选项的逻辑里默认走“上报人工”或“收集更多信息后重试”而不是自动选择一个危险动作。这个兜底设计不是偷懒它是类型化决策体系里的安全气囊。判断兜底选项设计得好不好有个简单的检查方式统计一段时间内unknown被选中的比例。如果经常高于 5%说明你的决策分类没有覆盖真实场景需要回去补充枚举值如果几乎从来没被选中可能分类粒度太粗模型把所有情况都归到了具体选项里兜底形同虚设。4.2 决策类型过死灵活场景跑不动跟上面的问题相反这个坑是分支定义太死板模型明明可以处理复杂情况却被 schema 限制住了。常见症状是模型对同一个问题给出了合理但不在枚举里的动作你为了适配它只能不断往 schema 里加枚举值越加越多最后整个决策定义膨胀到几十个选项模型反而更不知道选哪个了。这个问题的本质是“决策粒度”和“灵活性”的平衡没有找好。我的经验是决策点只负责“选方向”不负责“定细节”。方向的枚举值控制在 5 到 7 个以内细节交给工具执行时再展开。比如fix_now这个动作它可以代表“修复未找到的问题”但具体怎么修是改实现还是改测试由执行工具内部再去判断不要让决策层背负所有分支。还有一个保险做法是给每个决策点设定一个“推荐拒识”逻辑。当模型输出的置信度低于某个阈值时不直接执行而是返回给上层人工确认或重新收集上下文后再次决策。这个逻辑用对了比调什么 prompt 都管用。4.3 决策结果和实际执行的偏差怎么排查类型化决策的模型端准确率不一定比传统 prompt 高多少它真正的优势是“可排查”。因为每一步决策都被记录成结构化数据一旦执行结果与预期不符我们可以直接回放模型选了什么、上下文是什么、置信度多高、执行器做了什么。排查顺序一般是三步先看决策结果本身是否合理。如果模型选错了那是决策定义或上下文的问题。再看执行器是否按决策结果执行。有时候模型选择“修改 A 文件”但执行器因为路径解析问题改了 B 文件这就是工程 bug跟模型无关。最后看上下文数据是否可靠。如果塞给模型的 diff 是过期的、或日志被截断了一半模型基于错误信息做的判断自然不能信。这里要特别提醒一点上下文采集的“新鲜度”是个隐蔽的坑。很多 Agent 框架里上下文是异步预取的如果某个文件在预取之后被修改了模型拿到的就是旧信息。我遇到过排查了半天的“模型判断错误”最后发现是 Agent 上下文缓冲失效。所以要在执行循环里给上下文块打上时间戳执行前做一次校验。4.4 上下文太长与决策信息不足的平衡最后一个高频问题类型化决策到底该给模型多少上下文给太少模型看不清全貌给太多关键信号被淹没还会浪费大量 token。我的经验做法是“三级裁剪”。第一级是原始信息全量保留但不直接喂给模型。第二级是从原始信息里提取决策关键字段比如错误行号、函数名、最近变更文件。第三级是把关键字段格式化成结构化的“决策简报”再和决策 schema 一起送进模型。用一个例子说明。原始错误日志可能有一百行里面绝大多数是无关堆栈。裁剪之后只保留错误类型、出错文件、出错函数、相邻上下文代码段。模型需要判断的是“这是语法问题还是逻辑问题”给它堆栈全貌反而分散注意力。如果预算允许还可以给模型加一个“信息请求”动作让它在自己觉得信息不足时主动申请额外上下文。这个动作天然适合 Jev 的类型化设计——它本身就是决策点之一。把这个动作加进枚举后模型就不再蒙着头做决定而是会把“我不知道”变成一次明确的工具调用。我在实际使用中的体会是Jev 这类“不写文本”的决策范式最难的其实不是技术实现而是思维转换。你得接受“模型不需要理解全局才能做好局部”这个观点。每个决策点只关注当前情况选一个动作执行观察结果再进入下一个决策点。这样组装出来的 Agent 行为可能没有那种“一口气写出一个完整方案”的惊艳感但可靠性和可维护性完全是另一个层次。最后再分享一个小技巧把你定义好的决策点和枚举值当作代码接口来维护每次都做 schema 版本控制。模型输出的决策结构跟着 schema 版本走程序解析时也要做版本兼容处理。这套体系跑久了之后你会发现提示词工程的“工程”二字在 Jev 这里终于落回到了真正的工程范式上。
企业数字化 ERP 产品动态
相关推荐
SSM状态空间模型工程实践:从线性复杂度到混合架构落地 状态空间模型(State Space Model,SSM)从控制论的教科书里走出来,到成为 LLM 圈子里真正能打的正规军,也就这两三年的事。Mamba 带火的那一阵,"线性复杂度""固定大小隐状态"刷遍各个技术… · 2026/11/3 20:58:16
TTF字体在上位机开发中的优化与应用 1. TTF技术在上位机开发中的核心价值 TTF(TrueType Font)作为数字字体领域的行业标准,在上位机人机界面开发中扮演着关键角色。不同于普通办公软件,工业级上位机对字体有着特殊要求:需要在高分辨率、低光照甚至震动环境… · 2026/11/3 20:58:16
Vue3+Element Plus解决el-table分页序号闪烁问题 1. 问题现象与背景分析 在Vue3 Element Plus开发环境中,使用el-table组件时经常会遇到一个典型问题:当表格启用分页功能并设置type"index"显示行序号时,在切换分页的瞬间会出现序号闪烁或跳跃现象。具体表现为: 从第1… · 2026/11/3 20:58:16
Hadoop参数传递实战:Configuration对象与分布式缓存详解 1. Hadoop参数传递概述在Hadoop生态系统中,参数传递是开发过程中最基础也最关键的环节之一。作为一名长期使用Hadoop进行大数据处理的开发者,我深刻体会到参数传递方式的选择直接影响着作业的灵活性、可维护性和执行效率。Hadoop参数传递的本质是将配置信… · 2026/11/3 21:47:50
从8位到16位:运算器实验中的进位链设计与避坑指南 简介:这份实验报告面向计算机组成原理课程的学习者与实验备考学生,聚焦运算器硬件实现这一核心难点,帮助读者理清从串行加减到先行进位加法的设计脉络。内容围绕8位可控加减法器、4位快速加法器与16位快速加法器三个实验展开,涵盖… · 2026/11/3 21:47:50
分布式系统唯一ID生成方案对比与实践指南 1. 项目概述:唯一标识号的意义与应用场景在软件开发和系统设计中,唯一标识号(Unique Identifier)就像每个人的身份证号码,是区分和识别数据实体的核心机制。我处理过的分布式系统中,标识冲突导致的脏数据问… · 2026/11/3 21:47:50
什么是Buzz?从技术杂音到传播热词的跨领域解析 我无法基于当前输入生成符合要求的博文。原因在于:您提供的输入内容中,项目标题仅为“buzz”,且后续未提供任何有效信息——没有项目正文(原始描述)没有关键词列表(当前显示为空)没有摘要描述&a… · 2026/11/3 21:47:50
SSD1322驱动开发实战:从GDDRAM寻址到电源时序的避坑指南 简介:SSD1322数据手册面向OLED/PLED显示驱动开发工程师、嵌入式硬件设计者及电子类学生,提供Solomon Systech公司480128点阵高功率段/公共驱动器控制器的完整技术资料,可解决芯片选型、寄存器配置与硬件调试中缺乏权威依据的问题。资源包共1个… · 2026/11/3 21:47:50
MT62xx功能机源码开发实战:编译仿真、烧写校准与MMI移植 简介:围绕MTK6225、6226、6223、6235、6253系列手机开发平台整理的光盘配套使用手册,面向准备进入手机与嵌入式行业的在校学生、初级硬件与驱动工程师,也适合想了解功能机时代MTK方案全貌的技术爱好者。文档先交代平台定位与行业背景… · 2026/11/3 21:46:49
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46
STM32F411RE与MAX14431实现SPI隔离:工业现场抗共模干扰实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
ESP32+大模型AI硬件开发:从Demo到产品的8个工程问题 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
基于MAX14431BAEE+与PIC18F85J10的SPI隔离方案设计与实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46