LLM结构化判断实战:用Jev把模型决策做轻做快做便宜
LLM 应用做久了你会发现一个很尴尬的现实模型能写诗、能聊天、能编故事但一到帮我判断一下这个工单该分给哪个组这条评论是不是垃圾广告这封邮件要不要标紧急这种结构化决策场景就开始变得又慢又贵还不稳定。Jev 这个项目就是冲着这个痛点来的——它把 LLM 的判断能力压缩成又快又便宜的结构化决策让模型输出不再是自由发挥的小作文而是可以直接喂给下游系统的确定结果。我第一次接触这类需求是在一个内容审核的小项目里当时用最朴素的方式调模型每条数据都要几百毫秒、几分钱量一上来成本直接失控而且同样的输入偶尔给出不一样的答案下游逻辑根本没法写。后来才意识到问题不在于模型不够聪明而在于我们把判断这件事做得太重了。Jev 的思路正好相反把判断拆出来、做轻、做结构化让 LLM 只干它最擅长的那一小部分活。这篇文章我会从设计思路、核心机制、实操落地到踩坑排查完整讲一遍这套东西怎么用、为什么这么设计、以及实际跑起来要注意什么适合正在做 LLM 应用、被成本和延迟折磨的开发者参考。1. 为什么 LLM 判断需要结构化和便宜两件事一起做1.1 自由文本输出的三个隐性成本很多人做 LLM 判断的第一反应是写个 prompt请判断下面这段话属于哪一类并说明理由。然后解析模型返回的自然语言。这个做法在 demo 阶段没问题一上量就暴露三个成本。第一个是解析成本。模型返回我认为这条内容应该属于广告类因为它包含明显的促销词汇……你得写正则或者再调一次模型去抽取广告类这三个字。正则写不好就漏写太死就误伤维护起来是无底洞。第二个是token 成本。让模型说明理由意味着每次输出都要多几十上百个 token这些 token 你付了钱却只用来做展示下游系统根本不关心理由。第三个是不确定性成本。同样的输入模型这次说广告下次说疑似广告再下次说推广内容你的下游 if-else 根本没法穷举。这三个成本叠加起来就是为什么很多 LLM 判断类应用看起来能跑一算账就亏。Jev 要解决的核心就是把这三种成本同时压下去。1.2 结构化决策的本质把开放生成变成受限选择结构化决策的关键洞察是判断类任务本质上不是生成任务而是分类/选择任务。你不需要模型创作一个答案你只需要它从有限的选项里挑一个或者填几个固定的字段。一旦想通这一点优化方向就清晰了把输出空间从任意文本收缩到预定义的 schema。模型不再自由发挥而是在一个受约束的空间里做选择。这带来三个直接好处——输出可解析因为格式固定、token 可控因为不需要废话、结果稳定因为选项有限模型不容易跑偏。Jev 在这条路上做得比较彻底它不只是让你要求模型输出 JSON而是从调用方式、缓存、批处理等多个层面把结构化这件事做成了默认行为。下面我会逐层拆开讲。1.3 便宜和快从哪来三个可优化的杠杆要让 LLM 判断又快又便宜能动的杠杆其实就三个减少调用次数、减少单次 token、复用已有结果。减少调用次数靠的是批处理——把多条待判断数据打包成一次请求而不是一条一条调。减少单次 token 靠的是结构化输出——不让模型写理由、写解释只输出结果字段。复用已有结果靠的是缓存——相同或相似的输入直接命中缓存不重复花钱。Jev 的设计基本就是围绕这三个杠杆展开的。理解了这一点后面看它的具体机制就不会觉得零散因为每个设计都能对应到省调用省 token省重复中的某一个。2. Jev 的核心机制拆解它到底怎么把判断做轻2.1 结构化输出schema 约束下的确定性返回Jev 最核心的一层是结构化输出。你定义一个 schema比如情感倾向字段只能是 positive/negative/neutral 三选一置信度是 0 到 1 的浮点数模型就必须按这个格式返回。这不是靠 prompt 里写请务必返回 JSON这种软约束而是通过解析层和重试机制把格式错误挡在外面。为什么这点重要因为软约束的失败率在实际业务里高得吓人。我实测过纯靠 prompt 要求 JSON在复杂 schema 下失败率能到百分之十几尤其是字段一多、嵌套一深模型就开始漏字段、加注释、用中文引号。Jev 这类工具的价值就在于把这个失败率压到接近零让下游可以放心地直接json.loads。具体到实现层面通常有两种路子一种是调用模型时带上结构化输出参数很多模型 API 已经原生支持另一种是在拿到结果后做校验和自动重试。Jev 一般会两者结合——优先用原生结构化能力失败时用校验层兜底重试。这个组合的稳定性明显好于单用任何一种。2.2 批处理把 N 次调用压成 1 次批处理是省钱最直接的手段。假设你要判断 1000 条数据一条一条调就是 1000 次请求每次都有固定的系统 prompt 开销和网络往返。打包成批比如每批 20 条就变成 50 次请求系统 prompt 只付 50 次网络往返也少了一个数量级。但批处理有个坑批内某一条出错整批可能都受影响。所以好的批处理实现要能定位到具体是哪条出的问题并且支持部分成功。Jev 在这块的处理思路是把每条数据独立编号返回结果按编号对应某条失败不影响其他条失败的单独重试。另一个坑是批太大反而变慢。因为模型处理长输入本身就要时间批太大单次延迟会上去而且一旦失败重试成本高。实践中每批 10 到 30 条是比较舒服的区间具体要看单条数据的长度和模型的上下文窗口。2.3 缓存相同判断不重复花钱缓存这层经常被忽略但在判断类场景里命中率往往很高。比如内容审核很多重复内容、模板化内容会反复出现比如工单分类相似的描述会不断涌入。这些如果每次都重新调模型纯属浪费。Jev 的缓存通常基于输入的规范化哈希——把输入文本做标准化去空格、统一大小写、去掉无关标点后算哈希命中就直接返回上次的结果。这里有个细节要注意缓存 key 必须包含 schema 版本否则你改了 schema 之后旧缓存返回的字段结构对不上会出诡异 bug。我踩过这个坑改完 schema 忘了清缓存下游解析直接崩排查了半天才想起来是缓存的问题。2.4 模型选择不是越强越好而是够用就行判断类任务有个反直觉的结论很多判断根本不需要最强的模型。分类、打标、二选一这种任务小模型往往能做到和大模型接近的准确率但成本和延迟低一个数量级。Jev 的实践思路是分级——先用便宜的小模型跑对置信度低或者小模型拿不准的样本再升级到大模型复核。这样大部分流量走便宜通道只有少数难样本走贵通道整体成本大幅下降准确率还能保住。这个级联思路在业界已经比较成熟关键在于怎么定拿不准的阈值这个后面实操部分会讲。3. 从零搭一套结构化判断流程完整实操3.1 定义 schema先想清楚要判断什么一切从 schema 开始。schema 定义得好不好直接决定后面顺不顺。我的经验是字段越少越好类型越简单越好枚举值越明确越好。举个例子做一个评论审核判断schema 可以这样设计schema { type: object, properties: { category: { type: string, enum: [normal, spam, abuse, off_topic] }, confidence: { type: number, minimum: 0, maximum: 1 } }, required: [category, confidence] }注意几个设计要点。第一category用 enum 而不是自由字符串这样模型只能在四个选项里选不会给你造出第五个类别。第二confidence用数值而不是高/中/低这种模糊描述方便后面做阈值判断。第三required明确列出必填字段避免模型偷懒漏字段。提示不要在一个 schema 里塞太多字段。字段越多模型出错概率越高token 消耗也越大。如果确实需要判断多个维度考虑拆成多次调用或者多个 schema而不是堆在一个大 schema 里。3.2 构造 prompt把判断标准写清楚schema 定了接下来是 prompt。结构化判断的 prompt 和普通对话 prompt 不一样它要的是明确、无歧义、可执行。一个好的判断 prompt 通常包含三部分任务说明、判断标准、输出要求。任务说明一句话讲清楚要干什么判断标准把每个类别的边界讲清楚最好带一两个例子输出要求指明按 schema 返回。你是一个内容审核助手。请判断给定评论属于以下哪一类 - normal正常评论表达观点或交流 - spam垃圾广告包含推广链接或推销内容 - abuse辱骂、攻击性内容 - off_topic与主题完全无关的内容 判断标准 - 只要包含明显推销意图即使语气正常也归为 spam - 单纯的负面评价不算 abuse只有针对人的攻击才算 请按指定 JSON 格式返回不要输出任何额外文字。这里的关键是边界案例的说明。负面评价算不算 abuse这种模糊地带如果你不写清楚模型就会随机发挥导致结果不稳定。把边界写清楚是提升一致性的最有效手段。3.3 批处理实现打包、编号、解析批处理的核心是把多条数据组织成一次请求并且能正确对应回来。下面是一个简化的实现思路def batch_judge(items, batch_size20): results {} for i in range(0, len(items), batch_size): batch items[i:ibatch_size] # 给每条数据编号 numbered [ {id: idx, text: item} for idx, item in enumerate(batch) ] prompt build_batch_prompt(numbered) response call_llm(prompt, schemabatch_schema) # 按 id 对应回结果 for r in response[results]: results[i r[id]] r return results几个实操要点。第一编号一定要在批内唯一且能映射回全局上面用i r[id]做映射。第二批处理的 schema 是数组套对象比单条 schema 多一层要确保模型理解这个结构。第三解析时要处理缺项——模型偶尔会漏掉某条这时候要能识别出来并单独重试而不是默认给个错误结果。3.4 缓存层接入key 怎么设计缓存接入的位置很关键应该在调用模型之前。流程是输入 → 规范化 → 算 key → 查缓存 → 命中则返回未命中则调模型 → 写缓存。import hashlib import json def cache_key(text, schema_version): normalized text.strip().lower() raw f{schema_version}:{normalized} return hashlib.sha256(raw.encode()).hexdigest()注意schema_version一定要进 key。每次改 schema 就升版本号这样旧缓存自然失效不会污染新结果。这个细节看起来小但能省掉很多排查时间。3.5 级联判断小模型先跑大模型兜底级联的实现逻辑是小模型先判断如果置信度高于阈值就直接采纳低于阈值就交给大模型。def cascade_judge(text, threshold0.8): small_result call_small_model(text) if small_result[confidence] threshold: return small_result # 置信度不够升级到大模型 return call_large_model(text)阈值怎么定没有标准答案要靠数据调。我的做法是先跑一批标注好的样本看小模型在什么置信度区间准确率开始掉把阈值定在那个拐点上。通常 0.7 到 0.85 之间比较常见。阈值定太低难样本漏给大模型准确率受损定太高大部分样本都升级省不下钱。4. 实测数据与成本对比到底能省多少4.1 延迟对比批处理带来的数量级差异我在一个模拟项目里做过对比判断 1000 条短文本单条调用平均延迟约 400ms总耗时约 400 秒串行。改成每批 20 条后50 次请求单次延迟因为输入变长约 800ms总耗时约 40 秒。延迟降了一个数量级主要省在系统 prompt 的重复处理和网络往返上。如果再叠加缓存重复内容直接命中实际耗时还能再降。在内容审核这种重复率高的场景缓存命中率能到 30% 以上相当于三分之一的请求根本不花钱不花时间。4.2 成本对比token 层面的账成本这块结构化输出省的是废话 token。让模型写理由每次输出可能 100 token只输出结构化结果可能 20 token。单次看着不多乘以百万次调用就是几倍的差距。再叠加级联假设 80% 的样本小模型就能搞定小模型单价是大模型的十分之一那整体成本能降到原来的两成左右。这个账算下来对于量大且判断相对简单的场景优化空间非常可观。方案单次 token估相对成本相对延迟自由文本 理由1501.01.0结构化输出400.30.6结构化 批处理400.30.1结构化 批处理 缓存40命中不计0.20.07再叠加级联视分布0.1 左右0.05 左右注意上表是量级估算实际数字取决于你的数据分布、模型选择和缓存命中率不要当成精确值用。4.3 准确率有没有掉结构化会不会牺牲质量这是大家最关心的问题。我的实测结论是结构化输出本身几乎不损失准确率反而因为消除了格式噪声让结果更稳定。真正可能影响准确率的是级联——如果小模型判断错了且置信度还高就会漏过复核。所以级联的准确率取决于两个因素小模型本身的质量以及阈值定得合不合理。我的建议是级联上线前一定要用标注数据验证看整体准确率相比纯大模型掉了多少。如果掉得在可接受范围内比如 1 到 2 个百分点那省下的成本完全值得如果掉太多就调高阈值或者换更好的小模型。5. 常见问题与排查技巧实录5.1 模型不按 schema 返回怎么办这是最常见的问题。排查顺序是先看 schema 是不是太复杂字段太多、嵌套太深都会增加失败率再看 prompt 有没有明确要求按格式返回最后看用的模型是否原生支持结构化输出。如果都排查了还是失败就上校验重试层——解析失败时把错误信息拼回 prompt 再调一次通常第二次就能过。重试次数设 2 到 3 次足够再多说明 schema 本身有问题该简化了。5.2 批处理里某条结果错位了错位通常出在编号映射上。检查两点一是批内编号是否从 0 开始且连续二是返回结果里的 id 是否和输入对应。我遇到过模型把 id 理解成第几条而不是我给的编号导致映射错乱。解决办法是在 prompt 里明确说id 字段必须原样返回不要重新编号。5.3 缓存导致结果不更新前面提过八成是 schema 版本没进 key。另一个可能是输入规范化做得太激进把本该区分的内容归一成了同一个 key。比如把数字都去掉那价格 100和价格 200就撞了。规范化要适度只做无意义的标准化空格、大小写不要动语义相关的内容。5.4 级联阈值调不好阈值调不好表现为两种要么成本没降下来阈值太高要么准确率掉了阈值太低。解决办法是画一条曲线——横轴是阈值纵轴是准确率和成本找那个准确率还能接受、成本已经明显下降的点。这个点因业务而异审核类业务对准确率敏感阈值要高些推荐打标类业务容忍度高阈值可以低些。5.5 常见问题速查表现象可能原因排查方向解析失败率高schema 太复杂 / prompt 不明确简化 schema明确输出要求批处理结果错位编号映射错误检查 id 对应逻辑缓存不更新schema 版本未进 key把版本号加入缓存 key成本没降级联阈值太高下调阈值扩大便宜通道准确率下降级联阈值太低 / 小模型太弱上调阈值或换模型延迟反而变高批太大减小 batch_size6. 几个我踩过的坑和实操心得第一个坑是过度追求 schema 完整。我一开始总想把所有可能用到的字段都塞进 schema结果模型经常漏字段、格式出错。后来学乖了只保留下游真正要用的字段其他一律砍掉失败率立刻降下来。schema 是给机器用的不是给人看的够用就行。第二个坑是批处理没做部分失败处理。有次一批 20 条里有一条触发了内容策略整批返回失败20 条全部重试白白浪费。后来改成逐条校验只重试失败的那条效率高多了。批处理一定要假设批内会有个别失败做好隔离。第三个心得是缓存要定期清理和监控。缓存不是设了就完事要监控命中率和缓存大小。命中率太低说明 key 设计有问题或者数据本身重复率低这时候缓存意义不大缓存无限增长会占内存要设过期策略。我一般给缓存设个 TTL比如 7 天兼顾命中率和新鲜度。第四个心得是级联的阈值要随数据漂移调整。业务数据分布会变今天合适的阈值过两个月可能就不合适了。建议定期比如每月用新数据重新验证一次阈值别设完就不管。最后一个心得也是我觉得最重要的先跑通再优化别一上来就追求极致。我见过太多人一开始就想把批处理、缓存、级联全上齐结果调试成本极高还没上线就放弃了。正确的顺序是先单条结构化跑通确认准确率 OK再加批处理降延迟再加缓存降成本最后才上级联。每一步都验证过再往下走出问题也好定位。这套东西说到底不复杂核心就是把判断做轻这一个念头。想清楚哪些是必要的、哪些是可以省的然后一层层往下砍自然就快就便宜了。Jev 提供的正是这样一套把判断做轻的工具和思路剩下的就是结合你自己的业务数据去调那几个关键参数——阈值、批大小、缓存策略。这几个参数调好了效果立竿见影。

相关新闻

WebSocket消息推送架构:私发与广播的集群路由设计实践

WebSocket消息推送架构:私发与广播的集群路由设计实践

做Web实时消息推送这几年,我最大的感受是:广播很容易,人人都会;私发才是真正考验设计功底的地方。很多人以为私发就是“给某个session发一条消息”,做出来之后一上集群就凉了,session在A机器,消…

2026/10/14 5:45:16 阅读更多 →
Furion内置定时任务完全指南:从ITask接口到分布式任务调度避坑实战

Furion内置定时任务完全指南:从ITask接口到分布式任务调度避坑实战

简介:面向.NET开发者的Furion内置定时任务学习示例,围绕任务定义、调度、持久化与配置展开,适合正在学习Furion或需要在项目中快速接入后台任务调度的读者。压缩包共12个文件,大小仅9KB,包含7个C#源码、3个JSON配置文件…

2026/10/14 5:45:16 阅读更多 →
LLM应用开发中的数据格式全解析:从JSONL到ChatML的实战指南

LLM应用开发中的数据格式全解析:从JSONL到ChatML的实战指南

1. 为什么数据格式是LLM应用的第一道坎做LLM应用开发这几年,我踩过最多的坑不是模型选型,也不是提示词设计,而是数据格式。听起来很基础对吧?但实际情况是,我见过太多项目在原型阶段跑得挺欢,一到接入真实数…

2026/10/14 5:45:16 阅读更多 →

最新新闻

Flutter跨平台开发实战:从环境搭建到架构优化的完整指南

Flutter跨平台开发实战:从环境搭建到架构优化的完整指南

简介:这份PDF资料面向跨平台移动应用开发的初学者,以及有编程基础但尚未接触Flutter的开发者,系统讲解Flutter从环境搭建到项目实战的完整路径。内容涵盖Flutter自绘引擎、AOT编译与热重载等核心优势,Windows与macOS下的SDK安装和…

2026/10/14 6:19:25 阅读更多 →
Agent稳定性工程化:Harness机制设计与落地实践

Agent稳定性工程化:Harness机制设计与落地实践

1. 从“能跑”到“跑得稳”:Agent 稳定性问题的工程化破局思路做 Agent 开发的人大概都有过这种体验:Demo 阶段一切丝滑,一旦放到真实业务里跑上几百上千次,各种稀奇古怪的失败就开始冒出来。同一个输入,今天返回正常结…

2026/10/14 6:19:25 阅读更多 →
EMC Symmetrix DMX操作手册:企业级存储现场作业指南

EMC Symmetrix DMX操作手册:企业级存储现场作业指南

简介:本资源是EMC Symmetrix DMX系列企业级存储系统的官方级操作手册,面向存储运维工程师、系统集成人员及维保技术人员,聚焦DMX设备日常巡检、硬件故障定位与现场处置等核心运维场景。手册覆盖DMX 800/1000/2000/3000全型号架构图示&#xf…

2026/10/14 6:19:25 阅读更多 →
短视频背景音乐版权如何合规解决?可商用音乐素材平台盘点

短视频背景音乐版权如何合规解决?可商用音乐素材平台盘点

在短视频与商业内容爆发式增长的今天,背景音乐的版权合规已成为创作者和企业必须正视的核心问题。未经授权使用音乐不仅可能导致视频下架、账号限流,还可能引发法律纠纷与经济损失。选择正规可商用音乐素材平台,是保障内容安全、提升创作效率…

2026/10/14 6:19:25 阅读更多 →
豆包优化公司哪家好?AI搜索推荐优化找谁做

豆包优化公司哪家好?AI搜索推荐优化找谁做

越来越多用户开始用豆包这类AI助手查资料、做决策。QuestMobile数据显示,2026年6月豆包月活跃用户已达到约3.82亿。对企业来说,品牌能否在AI回答中被提及、被推荐,直接影响新客户对品牌的初步印象。“豆包优化公司哪家好、AI搜索推荐优化找谁…

2026/10/14 6:19:25 阅读更多 →
Hive文件存储格式深度解析:从TextFile到ORC的选型与优化

Hive文件存储格式深度解析:从TextFile到ORC的选型与优化

1. 为什么文件存储格式值得单独拎出来讲做数据仓库这行的人,绕不开Hive。而一旦你开始认真用Hive处理稍微上点规模的数据,迟早会撞上一个问题:同样的SQL,为什么别人跑几分钟,我跑半小时?排除掉数据倾斜、资…

2026/10/14 6:18:25 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 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/13 22:01:27 阅读更多 →
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/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练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/12 18:11:17 阅读更多 →