从Codex源码到生产级AI Agent Runtime:工程化架构与核心模式解析
1. 从开源项目到生产系统一次工程思维的跃迁最近在社区里看到不少朋友在讨论如何基于 OpenAI 的 Codex 模型或者类似的大型语言模型LLM来构建自己的 AI Agent智能体。大家兴致勃勃地跑通了几个 Demo用 LangChain 或者 AutoGPT 搭了个架子让模型能调用工具、访问网络看起来挺像那么回事。但当我问起“这个系统能扛住多少 QPS每秒查询率”、“错误率是多少怎么监控和告警”、“一次对话的上下文管理成本有多高”时往往就陷入沉默了。这让我想起了几年前看 OpenAI Codex 早期开源代码比如 Codex 的论文和部分演示项目时的感受。那些代码清晰地展示了模型如何理解代码、如何补全是绝佳的研究范本。但如果你真想把那套逻辑搬到一个需要7x24小时稳定运行、服务成千上万用户的生产环境里你会发现中间隔着一道巨大的鸿沟。这道鸿沟就是工程化。“从 OpenAI Codex 源码看生产级 AI Agent Runtime 的工程模式”这个标题想探讨的正是这件事我们如何把那些惊艳的、充满研究色彩的 AI 能力封装成一个健壮、可靠、可维护的在线服务Codex 的源码是我们的“地图”它告诉我们目的地强大的代码生成能力和基本路径Transformer 架构、Prompt 工程但生产级 Runtime 则是我们要建造的“高速公路和交通管理系统”。这篇文章我就结合自己参与构建企业级 AI 应用的经验拆解一下这条从研究到生产的工程化之路看看那些成熟的团队都在用什么模式来解决实际问题。2. 剖析 Codex 源码理想化的单次交互与生产现实的差距要理解工程化的必要性我们得先回到起点看看典型的 Codex 风格源码或类似研究项目呈现出的世界是什么样子。虽然我们无法获得完整的、最新的 Codex 生产代码但从其论文、早期开源示例如 GitHub Copilot 的技术报告以及类似模型的实现中可以提炼出其核心交互模式。2.1 研究范本中的“完美”流程在一个典型的研究或演示项目中流程通常是线性的、纯净的输入构造接收一段自然语言描述或几行代码作为前缀Prompt。模型推理将构造好的 Prompt 送入预训练好的大型语言模型如 Codex。结果生成模型自回归地token by token生成代码补全内容。输出返回将生成的代码片段返回给用户。这个过程在 Jupyter Notebook 或者一个简单的 Python 脚本里跑得飞快也足够令人兴奋。它的核心假设是环境是干净的请求是独立的资源是无限的目标是验证能力。代码里可能充满了硬编码的参数、简单的错误处理甚至没有以及一次性的实验逻辑。2.2 生产环境抛出的“灵魂拷问”一旦把这个流程丢进生产环境每一个环节都会面临严峻挑战输入/输出I/O与上下文管理研究版Prompt 可能是内存中的一个字符串。上下文长度例如 2048 tokens固定简单截断或忽略。生产拷问用户输入可能来自 HTTP API、消息队列、WebSocket需要反序列化、验证、清洗。一次对话可能长达数十轮如何高效地管理、存储、检索和压缩历史上下文当对话轮次超过模型上下文窗口时是丢弃最早的历史还是进行智能摘要这个摘要本身也是模型调用如何保证其稳定性和成本模型服务与推理优化研究版直接调用openai.Completion.create()或类似的本地模型接口。生产拷问模型服务本身如何保证高可用是采用云服务商托管还是自建推理集群如何做负载均衡和弹性伸缩对于自建服务如何优化 GPU 利用率批处理、连续批处理 Continuous Batching如何实现低延迟的流式响应Streaming让用户能实时看到生成过程工具调用与外部集成研究版工具调用Function Calling可能用简单的if-else匹配函数名和参数然后同步执行。生产拷问工具可能是一个需要访问数据库的微服务、一个第三方 API有速率限制和认证、甚至是一个需要长时间运行的任务。如何管理这些工具的认证、超时、重试和错误处理如何保证工具调用的安全性防止任意代码执行工具执行是同步阻塞还是异步非阻塞如何将执行结果有效地重新整合到对话上下文中状态、记忆与持久化研究版对话状态保存在内存中进程重启就丢失。生产拷问用户可能从不同设备接入如何保证对话的连续性对话状态包括上下文、工具调用历史、用户偏好需要持久化到数据库如 Redis、PostgreSQL。这引入了状态管理的复杂性何时保存保存什么粒度如何设计数据模型以支持快速检索和更新可观测性与成本控制研究版打印日志到控制台成本是单次实验的 API 调用费。生产拷问我需要监控每秒请求量、平均响应延迟、Token 消耗分布、工具调用成功率、用户满意度。我需要设置告警当延迟飙升或错误率增加时能及时通知。同时我必须精确计量每次对话的成本按 Token 计费并可能需要对用户进行配额管理或计费。这些能力不会从研究代码中自然生长出来。看到这里你应该能感受到生产级 AI Agent Runtime 要解决的远不止是“让模型跑起来”。它本质上是一个复杂的分布式系统需要处理并发、状态、网络、容错、监控等一系列经典软件工程问题只不过它的核心业务逻辑由非确定性的 LLM 驱动。3. 核心架构模式构建健壮 AI Agent Runtime 的四大支柱面对上述挑战成熟的工程团队会采用一系列经过验证的架构模式。这些模式构成了生产级 Runtime 的骨架。3.1 分层与解耦清晰的责任边界这是最基础的工程原则。一个典型的 AI Agent Runtime 可以划分为以下几层接入层Gateway/API Layer负责协议适配HTTP/gRPC/WebSocket、认证鉴权、限流、请求路由和初步的输入验证。它屏蔽了外部协议的多样性为内部提供统一的请求对象。编排层Orchestration Layer这是 Runtime 的“大脑”。它接收标准化请求管理整个对话的生命周期。其核心职责包括对话状态管理从存储中加载或创建新的对话状态。上下文组装根据对话历史、系统指令、知识库检索结果等组装出送给模型的最终 Prompt。模型路由与调用决定使用哪个模型例如简单问题用小型廉价模型复杂代码生成用大型模型调用模型服务并处理响应。工具调度解析模型输出的工具调用请求安全地调用相应的工具执行器并等待结果。流式响应处理如果是流式响应需要处理 Token 的流式返回和组装。执行层Execution Layer一个专门执行“工具”的沙箱环境。它接收编排层的指令在受控的环境下执行代码、调用 API、查询数据库等并将执行结果成功或失败返回。安全性是这一层的重中之重通常需要严格的权限控制和资源隔离。数据与存储层Data Storage Layer对话存储使用 Redis缓存热数据、PostgreSQL 或 MongoDB持久化来存储对话状态、历史消息。向量数据库用于存储和检索知识库文档支持基于语义的上下文增强RAG。审计与日志所有关键操作用户输入、模型输出、工具调用、错误都需要结构化日志并送入如 Elasticsearch、Datadog 等可观测性平台。模型服务层Model Service Layer可以是托管的 OpenAI/Azure OpenAI API也可以是自建的推理服务器如使用 vLLM、TGI - Text Generation Inference。这一层专注于高效、稳定地提供模型推理能力。这种分层设计使得每个部分可以独立开发、部署和扩展。例如当工具调用逻辑变得复杂时可以强化执行层而不影响编排层。3.2 事件驱动与状态机管理复杂的异步流程AI Agent 的交互很少是简单的“一问一答”。它可能涉及多轮对话、多个工具的顺序或并行调用、等待外部异步回调等。用传统的同步调用链来编写这种逻辑会迅速变成“回调地狱”。事件驱动架构EDA和状态机State Machine是管理这种复杂性的利器。将对话视为一个状态机一个对话会话Session可以定义为一组状态如等待用户输入、生成思考中、等待工具执行、流式输出中、错误和触发状态转换的事件如用户消息到达、模型生成完成、工具执行成功/失败、流式结束。使用消息队列进行解耦编排层中的不同组件上下文组装器、模型调用器、工具调度器之间通过内部消息队列如 Redis Streams, Apache Kafka, RabbitMQ进行通信。当一个组件完成工作后它发布一个事件到队列触发下一个组件的工作。例如流程可能是用户发送消息事件UserMessageReceived状态从等待用户输入变为处理中。上下文组装器消费该事件组装 Prompt发布PromptReady事件。模型调用器消费PromptReady事件调用模型开始流式返回 Token并发布TokenGenerated事件给流式响应通道最后发布ModelResponseComplete事件。工具调度器检查模型响应如果包含工具调用则发布ToolInvocationRequested事件状态变为等待工具执行。执行层消费该事件执行工具发布ToolExecutionCompleted事件。编排层收到工具结果将其格式化为模型可读的格式重新组装上下文跳回步骤2形成循环直到模型输出最终答案状态变回等待用户输入。这种模式使得系统非常灵活易于添加新的处理环节如内容安全过滤、成本检查也便于实现重试、回退等容错逻辑。3.3 上下文管理与优化成本与效果的平衡术上下文管理是生产环境中资源消耗Token 数直接关联成本和效果模型记忆力的核心矛盾点。Codex 源码中简单的“滑动窗口”截断在生产中远远不够。高级上下文管理策略包括分层摘要Hierarchical Summarization不是简单丢弃旧消息而是定期例如每 10 轮对话使用一个更小、更便宜的模型如 GPT-3.5-turbo对过去的对话历史生成一个精简的摘要。然后将这个摘要作为“元记忆”放入后续对话的上下文开头。这样既保留了长期记忆又极大地节省了 Token。基于向量检索的动态上下文Retrieval-Augmented Context将长文档、知识库内容存储在向量数据库中。当用户提问时并不把所有相关知识都塞进 Prompt而是先进行向量相似度检索只选取最相关的几个片段插入上下文。这就是 RAG检索增强生成的核心它能突破模型上下文长度的限制处理超长文档。结构化状态存储除了保存原始的对话消息还可以提取并存储对话中的关键实体、决策点、用户偏好等结构化信息。这些结构化信息比原始文本更紧凑查询效率也更高可以在需要时快速注入上下文。工程实现上这需要一个独立的“上下文引擎”服务它负责维护对话的记忆池根据策略决定哪些信息以何种形式原始消息、摘要、结构化数据进入下一次模型调用的 Prompt。3.4 可观测性与韧性设计让系统变得“透明”和“打不死”这是研究代码和生产代码最本质的区别之一。一个黑盒的 AI 系统是运维的噩梦。全面的指标埋点业务指标会话数、活跃用户数、平均对话轮次。性能指标端到端延迟P50, P95, P99、模型推理延迟、工具调用延迟。质量与成本指标每次调用的输入/输出 Token 数、工具调用成功率、用户反馈点赞/点踩率、单次对话成本。模型相关指标不同模型的调用分布、各模型的错误码分布如 rate limit, context length exceeded。这些指标应使用 Prometheus 等工具收集并在 Grafana 上形成仪表盘。结构化日志与链路追踪Tracing每一个请求分配一个唯一的trace_id这个 ID 贯穿接入层、编排层、模型服务、工具调用的所有日志。使用 OpenTelemetry 这样的标准可以很好地实现这一点。当出现问题时你可以通过trace_id一键还原整个请求的完整生命周期快速定位是模型服务慢了还是某个工具 API 挂了。降级、熔断与重试降级当主模型如 GPT-4服务不稳定或成本过高时自动降级到备用模型如 GPT-3.5-Turbo或者关闭某些高成本功能如联网搜索。熔断如果某个工具 API 连续失败像电路熔断一样暂时停止对其的调用直接给用户返回“服务暂不可用”的友好提示而不是让用户长时间等待后超时。重试对于模型调用或工具调用中可能出现的瞬时错误如网络抖动、服务端过载实施有策略的重试如指数退避提高整体成功率。4. 实战中的工程取舍与经验之谈纸上谈兵终觉浅绝知此事要躬行。在设计 Runtime 时总会面临一些具体的工程抉择这里分享几点我的实战体会。4.1 自建推理 vs. 使用托管 API一个成本与控制的权衡托管 API如 OpenAI, Anthropic, 国内大模型平台优点上手极快无需操心 GPU 运维、模型部署、推理优化。全球分布式高可用性有保障。按需付费初期成本低。缺点数据隐私和安全需仔细评估服务条款。长期看Token 成本可能随着用量增长而变得高昂。定制化能力有限无法做深度的模型量化、裁剪、特定硬件优化。存在供应商锁定风险。适合创业公司、快速验证阶段、对数据出境无严格限制的业务、非核心辅助功能。自建推理集群优点数据完全私有安全性最高。长期大规模使用下硬件成本可能低于 API 调用费。可以进行极致的性能优化混合精度推理、量化、定制化模型。无供应商锁定。缺点工程复杂度陡增。需要专业的 MLops 团队负责模型部署、版本管理、GPU 资源调度、监控和故障恢复。前期固定投入高。适合大型企业、对数据安全有强制要求的行业金融、医疗、核心业务流量极大且稳定、需要高度定制化模型的场景。我的建议绝大多数团队应该从托管 API 开始快速验证业务逻辑和用户价值。当用量达到一定规模例如每月 API 费用超过几名高级工程师的年薪且对性能、成本、隐私有了更明确的要求后再考虑逐步迁移到自建或混合架构。可以使用像vLLM这样的开源推理服务器来降低自建难度。4.2 流式响应Streaming的实现细节流式响应对于提升用户体验至关重要。工程上需要注意协议选择HTTP 可使用 Server-Sent Events (SSE)WebSocket 则是全双工更佳选择。确保你的接入层和前端能支持。背压Backpressure处理模型生成 Token 的速度可能快于网络发送的速度。Runtime 需要妥善处理这种速度不匹配避免内存积压。通常异步框架如 Python 的asyncio能较好地处理。中间思考过程Chain-of-Thought的流式化如果 Agent 有“思考”步骤例如“我要先搜索天气再计算行程”可以考虑将这部分推理过程也以结构化的方式如特殊的标记流式输出给前端让用户感知 Agent 的“思考过程”体验更佳。错误处理如果在流式生成中途发生错误模型服务异常、网络中断需要有机制通知前端生成中断并可能提供部分已生成的结果。4.3 测试策略如何测试一个非确定性的系统测试 AI Agent 比测试传统软件困难得多因为模型的输出是非确定的。单元测试Unit Testing测试那些确定性的部分。例如测试你的 Prompt 模板组装逻辑是否正确测试你的工具参数解析器测试你的上下文摘要算法。集成测试Integration Testing用真实的模型服务可以是测试环境的廉价小模型测试端到端的流程。重点验证流程是否通畅工具调用是否能正确触发并整合结果。评估测试Evaluation Testing这是核心。你需要构建一个评估数据集包含一系列典型的用户查询和期望的“好回答”标准不一定是固定文本可以是规则如“必须调用某工具”、“回答中需包含某个信息点”。定期例如每天用这个数据集跑一遍你的 Agent自动化地评估其输出质量可以使用另一个 LLM 作为裁判即 LLM-as-a-Judge。监控评估分数的变化防止代码更新导致质量回退。混沌工程Chaos Engineering在生产环境的隔离部分模拟工具 API 延迟升高、模型服务返回错误等故障观察你的 Runtime 的降级、熔断、告警机制是否按预期工作。构建生产级 AI Agent Runtime 是一个充满挑战但也极具价值的工程实践。它要求我们不仅要对 AI 模型的能力有深刻理解更要具备扎实的分布式系统设计、软件工程和运维能力。从 Codex 那样优雅而单纯的研究代码出发走向一个能够承受真实世界复杂性和压力的生产系统这个过程本身就是一次从“算法思维”到“工程思维”的完整跃迁。希望这些模式和思考能为你构建自己的 AI 应用提供一些切实的参考。这条路没有银弹唯有在清晰的架构指导下结合业务实际不断迭代和打磨。

相关新闻

从静态指令到动态循环:构建自驱动AI智能体的核心原理与实践

从静态指令到动态循环:构建自驱动AI智能体的核心原理与实践

1. 从“保姆式”Prompt到“自驱动”Agent的范式转变最近在折腾AI应用开发的朋友,估计都经历过一个阶段:为了完成一个稍微复杂点的任务,比如分析一份数据报告并生成PPT,你得写一个巨长无比的Prompt。这个Prompt里,你得把…

2026/10/17 14:48:41 阅读更多 →
数据结构(5)二叉树的存储、创建与四种遍历算法

数据结构(5)二叉树的存储、创建与四种遍历算法

一、二叉树的基本概念二叉树(Binary Tree)是每个节点最多拥有两棵子树的树结构,通常子树被称作"左子树"和"右子树"。1.1 二叉树的递归定义二叉树是 n(n≥0)个节点的有限集合,该集合或者…

2026/10/17 14:49:32 阅读更多 →
显卡健康检测利器:memtest_vulkan显存稳定性测试全攻略

显卡健康检测利器:memtest_vulkan显存稳定性测试全攻略

显卡健康检测利器:memtest_vulkan显存稳定性测试全攻略 【免费下载链接】memtest_vulkan Vulkan compute tool for testing video memory stability 项目地址: https://gitcode.com/gh_mirrors/me/memtest_vulkan 在数字时代,显卡已成为计算机系统…

2026/10/17 14:54:10 阅读更多 →

最新新闻

SAP批处理实战:BDC与LSMW从录屏到物料账期批量更新的完整指南

SAP批处理实战:BDC与LSMW从录屏到物料账期批量更新的完整指南

简介:《SAP两种批处理工具使用方法详解(BDC&LSMW)》是一份面向SAP顾问、数据迁移及运维人员的实操型文档,重点解决批处理操作与历史数据导入中的效率问题。文档以SHDB录屏为线索,完整演示从创建记录、录制MMPV开账…

2026/10/17 23:50:47 阅读更多 →
riverpod_test鸿蒙适配指南:测试宿主设计与Provider生命周期治理

riverpod_test鸿蒙适配指南:测试宿主设计与Provider生命周期治理

我们团队年初接到一个鸿蒙化适配任务,业务代码一周跑通,测试库却卡了两周——尤其是 riverpod_test 这个库,一进鸿蒙侧的测试通道就各种异常。今天把整个适配过程和踩坑点整理出来,给同样在做 Flutter 鸿蒙化适配的团队一个参考。…

2026/10/17 23:50:47 阅读更多 →
长上下文注意力机制选型:GLA门控线性注意力与KDA增量注意力的对比

长上下文注意力机制选型:GLA门控线性注意力与KDA增量注意力的对比

长上下文大模型这两年卷得厉害,注意力机制早就不是那个 QKV 打天下的年代了。我最近在调一个百万 token 级别的超长上下文模型时,把两种被反复提到的注意力变体翻来覆去做了不少对比实验:一个是 Gated Linear Attention,也就是 GL…

2026/10/17 23:50:46 阅读更多 →
kd-tree与三角剖分如何改进ICP:点云配准实战解析

kd-tree与三角剖分如何改进ICP:点云配准实战解析

简介:面向点云配准学习者的 MATLAB 实现资料,基于改进 ICP 算法,将 kd-tree、指派问题与 delaunay 三角剖分相结合,用于提升二维点云配准的精度与速度,适合计算机视觉、三维几何处理方向的学生及相关算法初学者。资料源…

2026/10/17 23:50:46 阅读更多 →
计算机博弈入门:从博弈树搜索算法到棋类AI程序实战

计算机博弈入门:从博弈树搜索算法到棋类AI程序实战

简介:一份聚焦计算机博弈竞赛的辅导课件,源自东北大学机器博弈研究室教学讲稿,面向参赛学生、算法爱好者及研究者。内容从棋类介绍与分类切入,系统讲解中国象棋、国际象棋、围棋、五子棋、六子棋及民间棋类规则,进而覆…

2026/10/17 23:50:46 阅读更多 →
《人工智能基础》【工具篇17】:OpenClaw十大必装技能推荐与TaoToken统一接入实践

《人工智能基础》【工具篇17】:OpenClaw十大必装技能推荐与TaoToken统一接入实践

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

2026/10/17 23:49:46 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 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/16 21:54:38 阅读更多 →
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/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练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/16 14:23:36 阅读更多 →