news 2026/9/8 13:41:44

AI Agent降本实战:五层技术栈与三种推理服务的成本优化指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI Agent降本实战:五层技术栈与三种推理服务的成本优化指南

上周有个朋友来找我,说他们公司花三个月做了一个AI Agent项目,演示效果特别好,结果一上生产,财务看到账单差点把他叫去谈话。原因很简单:Agent每执行一个稍微复杂的任务,可能要调用模型十几次,上下文越塞越大,账单数字肉眼可见地往上涨。这几乎是所有做AI Agent降本的人都会撞上的第一堵墙。

这篇文章我就结合自己实际操盘的经验,聊聊AI Agent降本这件事。我会从两个角度展开:一个是五层技术栈,帮你搞清楚成本到底产生在哪个环节;另一个是三种推理服务,也就是现在主流的云端API、自建推理、混合路由这三条路到底怎么选、怎么算账。适合正在做Agent落地的开发、架构、技术负责人,也适合准备Agent面试、想搞清楚成本模型的同学。

1. 先盘逻辑:AI Agent到底贵在哪

很多团队一上来就想着“换个便宜的模型”,结果换完效果崩了,又灰溜溜换回去。真正的问题在于,他们连钱花在哪了都没搞明白。想要降本,第一步不是改代码,而是把成本结构看清楚。

1.1 从一份账单说起:Agent“贵”的四个来源

传统ChatBot的成本基本等于“一次一问一答”的token费用,模型调用次数稳定,成本很好预测。但Agent完全不一样,它的成本来源至少包含四个部分。

第一是多轮调用的放大效应。一个Agent完成“帮用户查快递并生成投诉工单”这种任务,可能需要经过意图识别、工具调用、结果分析、回复生成好几轮。每一轮都是一次模型调用,而一次任务下来可能就是几千甚至上万token。如果业务里再做反思、纠错,调用次数会进一步膨胀。

第二是上下文窗口的持续膨胀。为了让模型记住前面发生了什么,Agent往往会把历史消息、工具返回结果、中间推理过程全部塞进上下文。尤其在长任务里,每多一轮,前面的内容都得重新传给模型。实测下来,一个20轮交互的Agent任务,输入token可能是单轮对话的20倍以上,但其中很多信息是重复的、冗余的。Prompt里每个字都是成本,这句话在Agent场景里体现得淋漓尽致。

第三是无效推理浪费。模型也不是每次都靠谱,工具调用格式错了、JSON解析失败、意图识别跑偏,都会导致重试。每一次重试都是白花花的token。更隐蔽的是,有些Agent框架默认会做多次“反思”或“自查”,你以为是在提升质量,实际上大部分场景根本不需要那么多次反思。

第四是算力资源的低利用率。如果走自建推理,GPU集群为了扛住峰值和SLA,往往要预留大量空转资源。而实时对话类的Agent任务,很多请求其实集中在工作时间段,闲时资源完全在烧钱。

这四个来源叠加在一起,才是Agent账单高的真相。“换个便宜模型”只能解决第二个来源的一部分,其他三个方面一点没动。

1.2 降本之前,先把成本结构画出来

个人经验是,做Agent降本,不要凭感觉拍脑袋,先干一件事:画一张成本结构图。

我习惯把Agent的成本拆成三层看。最底下一层是模型调用成本,包括输入token、输出token、缓存命中的价格差异,这是最直观的。中间一层是资源运营成本,自建推理的话要算GPU折旧、电费、运维人力,用云API的话要算API网关、日志存储、监控告警的费用。最上面一层是业务摩擦成本,这个最容易被忽略:因为Agent返回慢导致用户流失,因为回答质量差导致人工介入变多,因为链路不稳定导致返工……这些隐性成本往往比token费用更值得关注。

画完这张图你会发现,降本不等于“省token”。有时候多花一点token换更准的意图识别,反而能把人工介入成本压下来,整体更省钱。这就像做饭,不能只看食材花了多少钱,还得看浪费了多少、做砸了几次。

1.3 我的思路:让每一层都有明确的降本抓手

我的做法是沿着五层技术栈逐层排查,每一层都明确抛出降本抓手。

从最底下的基础设施层开始,能不能换更划算的实例类型、能不能混部调度;到模型推理层,该做量化的做量化,该上缓存的上缓存;再到工具接口层,精简工具描述、聚合请求;然后是Agent编排层,压缩记忆、限制循环;最后是应用层,设计合理的降级体验。

听起来像废话?但实际执行下来,很少团队能每一层都做到位。大多数情况是,大家盯着模型调用的价格降了一点,却让上下文的冗余描述白白浪费了更多token。所以这篇文章的第二节,我会把每一层的降本抓手逐一展开,每一层都有能直接抄的作业。

2. 五层技术栈拆解:每一层都有钱可省

五层技术栈是我自己归纳的一个框架,不一定跟所有资料里的分层完全一致,但它足够覆盖Agent从底层到业务的全链路。这五层分别是:基础设施层、模型与推理层、工具与接口层、编排与智能体层、应用与交互层。

2.1 第一层:基础设施层

这一层是Agent运行的地基,主要涉及算力、存储、网络和GPU集群的管理。

先说算力。若用云端GPU,第一件事是搞清楚实例选型。很多团队为了保险,直接上最贵的卡,结果模型本身用不满,大量显存闲置。以部署开源模型为例,7B级别的模型用FP16加载大约需要14GB显存,一张24GB的卡足够跑起来。但是如果盲目上80GB的大卡,空转成本就白付了。实例类型上,优先考虑按量付费搭配抢占式实例,离线批处理任务可以大胆用抢占式,成本能降一半以上。

再说存储。Agent会产生大量日志、中间结果、会话历史。这些数据不是都要存热存储的。我们会话数据存7天用于排障,超过7天归档到对象存储,单月存储成本直接降了七成。

还有一点容易被忽略:网络带宽。Agent频繁调用外部API,来回传输JSON、图像、文档,流量费用累积起来很吓人。实操上,工具接口能传引用不传全文、能二进制压缩不传Base64,都能实实在在省钱。

这一层的核心原则是:不要为“可能的峰值”付费,而是要让资源跟着实际负载走。基础设施省下的钱可能不是大头,但它决定了你整体成本的天花板。

2.2 第二层:模型与推理层

这一层是绝大多数人盯着的地方,也是最容易做出成效的地方。

模型选型上,很多团队犯的错是“什么任务都用最强模型”。实际上,一个Agent内部不同环节对模型能力的要求完全不同。意图识别、实体抽取这类任务,一个参数量小得多的模型就足够了;只有最终生成复杂回复、做多步推理的时候,才需要拉出顶级模型。我习惯做一个“模型分级矩阵”,把Agent链路里的每个调用点标出来,分别指定不同档位的模型。简单任务用小模型,复杂任务用大模型,运行成本能降30%以上,效果几乎不受影响。

推理侧也有不少手段。量化是一个,把模型从FP16压到INT8甚至INT4,显存占用和推理延迟都会下降。不过量化不是无脑做的,要实测准确率跌幅。通常我会在评测集上跑一遍,如果主要指标不掉点,才敢上线。另一个是投机解码(Speculative Decoding),用一个小草稿模型先生成候选token,大模型并行验证,推理速度能提升两三倍,且生成质量几乎无损。这个在vLLM、SGLang这些推理框架里都有成熟实现,属于“不用白不用”的优化。

缓存方面,这是推理层省钱的王炸之一。Agent场景里有大量重复或相似的Prompt:系统提示词、工具描述、历史对话模板、常用问题前缀。开语义缓存之后,命中请求直接用缓存结果返回,不再走模型。我们团队实测在某客服Agent上,缓存命中率能做到35%到40%,相当于白赚了三成的模型调用成本。这类优化不改变效果,只改变钱花在哪,性价比极高。

还有一点要重视:Thermal throttling模型输出上限。Agent里的很多中间步骤不需要长回复,给模型设置合理的max_tokens上限,能避免模型“啰嗦”式地生成一堆没用的内容。很多人只关注输入token,忽略了输出token也烧钱,这里的浪费往往比你想象的严重。

2.3 第三层:工具与接口层

Agent区别于普通对话的关键,是它能调用工具。而工具调用这层,恰恰是隐性成本的重灾区。

先说工具描述。很多团队直接把工具接口的OpenAPI文档全量塞给模型,一份工具描述动辄几千字,而且是每一轮调用都带上。模型每读一次,这些token就要付一次钱。解决办法是精简工具描述:只保留模型需要知道的部分,删掉内部字段、过长的枚举说明、无关的鉴权细节。我们做过一次“工具描述瘦身”,把六个工具的平均描述从2000多token压到600多token,链路总token下降非常明显,而且工具调用准确率没有下降,因为关键信息反而更突出了。

再说工具调用结果的处理。有的工具会返回很大的JSON,Agent拿到后直接把全部内容塞回上下文,下一轮对话还得继续带着,成本就在那里浪费。正确做法是在工具返回层做一次裁剪,把大JSON里只保留任务所需的关键字段,其余丢弃;如果工具支持按需字段查询,优先用筛选参数而不是全量拉取。

接口层还需要管理重试策略。Agent调用外部API失败时,默认的重试机制往往是指数退避重试三次。但如果上游接口本来就不稳定,每次重试都会拉长Agent的执行时间,同时因为超时导致上下文继续保留,进一步增加后续调用成本。我的建议是:给不同类型的接口设置不同的重试上限,对非关键接口第一次失败就直接降级返回,不要死磕。

2.4 第四层:编排与智能体层

这层是Agent的灵魂,也是成本炸弹最密集的地方。

先说规划与循环。Agent为了完成一个目标,会不断“思考—行动—观察”。这个循环如果不加限制,理论上可以无限跑下去,token就跟着无限烧。我的做法是给每个任务设置明确的最大步数限制,比如6步内必须收敛,超过就主动结束并转人工。同时给Agent链路加一个“预算熔断器”:比如单个任务消耗token超过预设阈值,立刻降级到最简回复模式。这听起来很简单,但实际落地能兜住大量极端情况。

然后是记忆管理。Agent保持长期记忆的常规做法是把所有历史记录塞进系统提示词,这是最贵也最傻的做法。合理的设计是“分层记忆”:短期记忆保留最近几轮对话原文,中期记忆用摘要压缩成几百字,长期记忆则从向量库里按需检索。这样每次请求真正带进Prompt的,只有当前最关键的信息,其余都放外面。我们做过对比,同一批Agent任务,用上分层记忆后输入token平均下降50%以上,而任务成功率基本持平。

还有一点是“Skill”复用。如果Agent每次执行相同子任务都要从头规划,等于重复掏钱。把这些高频子任务沉淀成工具或编排模板,让Agent直接调用,比让Agent每次现场推理要省得多。我见过有团队把“产品信息查询”这种高频动作做成了工具,Agent就不需要每次理解一遍产品库的schema,成本降得立竿见影。

2.5 第五层:应用与交互层

真正上线之后,应用层的策略同样影响成本。只是这一层优化的不是单个请求,而是整体流量的成本结构。

首先是体验降级设计。不是所有用户请求都需要完整Agent能力。我的做法是做一个前置分流:简单问题直接走一个轻量级Bot,复杂问题才升级到完整Agent。很多客服场景里,80%的问题是重复的常规咨询,根本没有必要动用大型模型。这个前置分流做得好,整体模型调用成本能直接降一半以上,而用户体验几乎不感知。

其次是异步化。很多Agent任务不是实时交互型的,比如批量生成摘要、定时汇总报告、后台数据清洗。这些任务用同步推理会占用实时资源,成本高且影响在线服务稳定性。把它们改成异步队列、离线批处理,用便宜的低峰时段或抢占式实例执行,成本可能是实时的三分之一。

最后是结果复用。Agent生成的答案、摘要、分析结果,如果有一定复用价值,可以存起来建一个结果缓存。后续相似请求直接返回历史结果,不再重跑链路。这特别适合那些“问题相同但用户不同”的场景,比如政策解读、产品FAQ、常见参数查询。这一层的收益往往最直观,因为很多请求完全绕过了模型。

3. 三种推理服务怎么选:算清这笔账再动手

技术栈聊完,回到一个更现实的问题:模型推理服务到底用哪种方式落地?我把它总结为三种:云端大模型API、自建推理服务、混合路由推理。

3.1 三种推理服务的成本模型对比

先上结论:三者不是替代关系,更多是互补关系。选型的核心是算清自己的业务属于什么成本模型。

对比维度云端大模型API自建推理服务混合路由推理
初期投入几乎为零,充值即用高,GPU采购或包年中等,初期建议先跑云端
单位token成本较高,不同档位差异大满载时低,空转时极高按需路由,整体趋向最低
弹性伸缩极好,自动扩缩困难,需预留容量结合云端弹性,伸缩灵活
运维复杂度低,平台全托管高,需要监控、调优、容灾中等,路由层有一定复杂度
数据合规需评估数据出域风险数据不出域,可控核心数据调度到自建,可控
适合场景起步验证、波动大的流量稳定高并发、私有化要求高成本敏感、场景复杂度高的长期业务

3.2 场景一:云端大模型API

如果团队刚起步,或者业务流量还处于验证期,直接用云端大模型API是最稳妥的。

这类服务的优势是弹性极好,请求量波动再大也不用操心扩容。而且现在各大云厂商API的价格已经打得比较低了,不同档位的模型差价很大。实践上有两个省钱技巧:一是把“输入缓存”用起来,很多平台提供Prompt缓存功能,命中缓存的价格通常只有非缓存价格的十分之一左右;二是尽量用批量API处理非实时任务,不少平台对批量任务有折扣。

但云端API的坑也很明显:费用不可控。Agent本身调用次数多,如果不做预算熔断,账单很容易超预期。我们在第一次上线时就吃过这个亏,后来加了每日限额和异常告警,才把失控风险摁住。另外,数据出域问题在很多行业是红线,如果你的业务对数据合规非常敏感,云端API可能根本上不了线。

3.3 场景二:自建推理服务

当业务量稳定了,自建推理服务的账就开始变得划算。

我通常把自建推理服务分两种形态:一种是用开源模型自建,另一种是拿开源模型做路由层的“主力模型”。后者其实更推荐。用vLLM或SGLang部署一个7B或14B的开源模型,处理高并发的简单任务、意图分类、信息抽取,成本能做到云端API的几分之一甚至十分之一。而最高难度的生成任务,仍然走云端API保效果。

自建推理最大的风险是GPU利用率上不去。Agent场景很多是实时对话,来一个请求就要一次响应,并发低时GPU大量空转。解决办法有几个方向:把多个模型的推理服务混部到同一批GPU上,错峰互补;把离线批处理任务调度到低峰时段填闲;用小batch聚合在线和离线任务。还有一点,部署时一定要做显存管理,像vLLM的continuous batching能大幅提升吞吐,建议直接用。自建服务如果利用率能跑上50%,成本优势就会非常明显;如果长期低于20%,要么调整混部策略,要么回到云端API可能更划算。

3.4 场景三:混合路由推理

这是我现在最推荐的方案,也是大流量Agent业务的主流打法。

核心思路是:在模型层前面放一个路由网关,根据任务复杂度、模型成本、当前负载,把每个请求动态调度到最合适的推理服务上。简单请求走自建小模型,复杂请求走大模型API,失败再降级。再配合语义缓存、结果复用、异步批处理,形成一套组合拳。

路由规则不是一次设定的,而是随着数据积累不断调整。比如我们在路由层设计了“成本-质量”双指标监控:每周统计每个路由目标的调用量、平均token成本、任务成功率、用户满意度。如果发现某类任务在小模型上成功率持续偏低,就把这类任务上调到大模型;如果发现某类任务在大模型上的成功率和低成本模型没差别,就下调。这是一个持续调优的过程,但事事积累下来,节省非常可观。

混合路由的落地有一定技术门槛:你需要一个统一的Agent框架来承接模型调用的抽象,需要可观测性建设来追踪每一条请求的路径和成本。但如果你的业务规模已经到了月调用百万次以上,这个投入是值得的。

4. 实操过程:一套完整降本方案的长这样

聊了这么多理论,说一段我自己实际做过的案例。一个知识库客服Agent项目,线上跑了三个月,当时的主要痛点是:模型调用费用高企,平均每用户会话成本居高不下,财务已经要求优化。我带团队做了一轮系统的降本改造,整个过程大概花了两周。

4.1 从监控到建模:先把成本数据跑出来

改造前第一周,我们没动任何代码,先把成本数据完整跑了出来。

具体做法是,在Agent框架里加了一层请求日志,把每次模型调用的链路、模型名、输入token数、输出token数、耗时、任务类型、最终是否成功全部记录下来。然后按任务类型聚合,算出每类任务的“千次任务成本”作为基准值。这一步很多人会跳过去,直接凭感觉优化,结果改完不知道效果是好是坏。我们做完之后发现,成本分布极其不均:大约20%的任务类型贡献了70%的token消耗,而这20%里大部分是“数据查询+报告生成”这类高频任务。

随后当我们画出成本热力图后,心里就有数了。优先优化的目标不是降所有任务的成本,而是集中打穿这20%的高频高耗任务。

4.2 典型优化动作:分层打补丁

第二周开始动手,我们沿着五层技术栈逐层打补丁。

第一件事是给Agent加了预算熔断和最大步数限制。在此之前,一个任务最多能跑20多轮模型调用,不少是因为工具调用失败后反复重试。加了限制之后,平均调用轮数从约19轮压到约7轮,效果不但没变差,反而因为减少了无效循环,用户等待时间也缩短了。

第二件事是精简Prompt和工具描述。我们把系统提示词从一份3000多字的“完整说明书”改成了一份800字的“要点卡”,把每个工具的描述压缩到只保留核心参数,并统一了输出格式要求。改完之后,任务成功率和工具调用准确率反而有小幅提升,原因是信息冗余少了,模型更容易抓住重点。

第三件事是引入语义缓存。我们把用户问题的Embedding向量存起来,相似度超过阈值的直接走缓存答案。因为客服场景中常见问题重复率很高,这个改动上线后,缓存命中率直接干到了30%以上。对于命中缓存的请求,模型调用费用为零,整个成本曲线的下降非常明显。

第四件事是模型分级路由。我们把意图识别和实体抽取这类任务切到自建的小模型上,只有最终生成完整答案时才调用大模型。这一步单独节省了20%以上的token费用。我们还在中间加了一个兜底逻辑:如果小模型输出的置信度低,才升级到大模型,防止一刀切降级损伤体验。

4.3 实测收益:一次优化的完整记录

两周改造结束后,我们用同样的业务流量做了A/B对比。

改造后,平均每千次Agent任务消耗的token量下降了55%以上,综合推理服务费用(含自建GPU成本与云端API费用)下降了约45%。同时,用户侧的满意度指标没有明显回落,平均响应时间反而因为减少无效调用而缩短了。

要注意的是,这个收益不是某个单一改动带来的,而是分层优化的结果。监控建模解决了“不知道该改哪”的问题,顶层优化解决了“怎么改不伤效果”的问题,最后模型分级保证了长期稳定性。整个过程中最大的心得是:降本不能追求一步到位,而是要做成持续迭代的工程

5. 常见问题与排查技巧实录

做Agent降本过程中,我们踩过不少坑,这里整理几个典型的,供大家参考。

5.1 我踩过的坑

坑一:只换便宜模型,不调Prompt。有段时间我们为了省钱,直接把主导Agent的大模型换成了低价档小模型,结果工具调用格式频繁出错、意图识别开始跑偏,用户反馈明显变差。后来才知道,小模型对复杂指令的遵循能力有限,换个模型必须配套调整Prompt格式和工具描述,尽量用更短、更明确的指令,而不是把给大模型写的那套原样搬过去。

坑二:缓存Key设计不合理。最开始做语义缓存时,我们把用户ID拼进了缓存Key,导致同一个问题在不同用户之间无法命中,缓存命中率只有不到5%。后来改成以归一化后的问题文本和意图类别作为缓存键,命中率才涨上去。这里提醒一句,缓存Key要剔除跟问题本身无关的变量,比如时间戳、用户ID、会话ID。

坑三:自建GPU利用率长期上不去。有一段时间我们自建服务的GPU利用率一直在10%左右,算上折旧和电费,比直接调云端API还贵。排查下来核心原因是实时对话请求并发太低、batch又小,导致GPU大部分时间在空转。后来我们把离线任务(如摘要生成、批量分类)调度到低峰时段,同时开启了vLLM的连续批处理,利用率才慢慢爬到40%以上。如果利用率连续两周上不了30%,我建议直接停掉自建,切回云端API,别跟空转的GPU较劲。

5.2 问题速查表

问题现象可能原因排查方向与解法
模型调用费用异常飙升Agent死循环或重试过多查看调用日志的轮数与失败率,试着设置最大步数和预算熔断
上下文太长导致账单变大历史记录和工具结果全量保留用分层记忆、摘要压缩、在工具返回层做字段裁剪
引入缓存后命中率很低缓存Key含用户ID、时间戳等变量对问题做归一化处理,用意图+归一化文本做签名
自建GPU成本比云端API还高并发低、batch小、利用率不足混部离线任务、打包连续批处理、监控2周利用率再决策
换了小模型后工具调用总出错Prompt和工具描述未适配小模型精简指令、拆分工具描述、增加输出格式校验与重试
降级体验导致用户投诉路由策略一刀切降级做置信度兜底,低置信度升级到高配模型而不是直接降级
日志和监控本身成本高全量日志存热存储热存储只保留一周,归档到对象存储,按需拉取分析

最后再说几个实操心得。Agent降本没有银弹,任何一个“单点大招”都很难带来持久收益。真正有效的做法是把五层技术栈当成一条流水线,每一层都保持“可观测、可优化、可回滚”的状态。我第一次做降本时也幻想过一劳永逸的方案,后来发现成本优化本身就是Agent产品的长期能力之一,它跟用户体验优化一样,需要持续迭代。

“2026年Agent的成本还会继续降”这句话,与其说是趋势预测,不如说是必然——因为模型层面有开源模型的迭代,推理层面有更高效的引擎,产品层面大家都在把Agent能力做得更精简。但对我们这些做落地的人来说,不管底层怎么变,五层技术栈的成本视角、三种推理服务的选型思路、以及在每一层抠成本的执行方法,这些能力是永远有用的。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 13:38:18

嵌入式UI开发新范式:RUI Studio声明式框架实战与性能优化

我不想再堆一个“新框架介绍”式的文章。RUI Studio 这个项目,我盯了有一阵子,因为在嵌入式界面开发这条路上,它确实把很多旧习惯和旧流程彻底改了。它不是简单的换了个工具链,而是从设计思想上就把“UI”从“画出来再烧进去”变成…

作者头像 李华
网站建设 2026/9/8 13:36:40

LSSVM在MATLAB中的实现与调参实战:从原理到应用

简介:基于MATLAB的LSSVM(最小二乘支持向量机)实现程序包,面向需要在分类、回归等场景中快速建模的科研工程师与学生,可解决从算法理论到代码落地之间的衔接问题。包内共72个文件,以70个m函数/脚本为主&…

作者头像 李华
网站建设 2026/9/8 13:35:12

全民健身解决方案系统开发实战:从架构设计到部署全流程指南

全民健身解决方案系统开发实战:从架构设计到部署全流程指南 一、全民健身解决方案系统开发的核心功能模块 全民健身解决方案系统是面向体育场馆、健身机构、社区体育管理者的一站式数字化平台。系统核心是打通用户端、运营端与管理端的数据链路,实现场地…

作者头像 李华
网站建设 2026/9/8 13:34:58

一键切换Claude Code API配置:cc-switch 安装与实战指南

说实话,Claude Code 用到现在,最让我崩溃的不是 Agent 能力不行,也不是上下文不够长,而是来回改配置这件事。今天用官方 Anthropic API,明天想接一下第三方兼容网关,后天又想切到本地 Ollama 跑一下模型&am…

作者头像 李华
网站建设 2026/9/8 13:33:25

软件测试转AI:先补数学还是先刷项目?实战路线解析

入行十几年,大部分时间都在跟测试、自动化、质量管理打交道,这几年肉眼可见的一个趋势是:AI 已经不是概念,而是开始渗透到研发链条的每一个环节。我身边不少做软件测试的朋友,包括带过的团队成员,都在问同一…

作者头像 李华
网站建设 2026/9/8 13:32:03

Java Socket文件传输实战:协议设计、断点续传与性能优化

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

作者头像 李华