verl源码深度拆解:从环境搭建到核心链路与调试实战
简介面向希望在7天内快速上手verlVolcano Engine Reinforcement Learning for LLMs框架的开发者这份源码包提供了从单机部署到千万级参数模型训练全流程的完整代码与配置。包内共1058个文件以Python脚本578个、Shell脚本212个、YAML配置72个、Markdown文档67个为主同时包含大量Dockerfile、RST文档及JSON配置可支撑环境搭建、数据准备、PPO训练、性能调优和分布式部署等环节。压缩包整体仅2.64MB便于快速下载。已有142人学习适合具备一定Python与LLM基础、想要深入理解verl内部实现或直接复用训练配置的开发者。通过阅读源码和配套配置可以掌握verl的安装流程、命令行接口、模型并行策略以及生产级部署要点是系统学习火山引擎开源强化学习框架的高性价比资料。1. 七天吃透 verl 源码这份代码包到底值不值得一行行啃如果你也是那种拿到一个陌生软件包先不急着跑 demo而是想打开源码看看它到底怎么把请求送出去、又把结果接回来的开发者那 verl 这套「7天掌握」源码资源应该正对你胃口。它不只是一份能跑通的工程代码而是把一套完整的业务链路拆成了可读性很强的模块从配置加载、核心调度、上下位机通信到结果回传每一层都留有清晰的接入点和注释。网上很多软件包的源码要么过度抽象、要么绕开关键路径这套代码属于少数「顺着调用链读一遍就能建立全局观」的实战包。无论你是想快速接手一个现成项目还是打算基于它做二次开发这份资源都能帮你省下大量排查时间。当然源码不会替你思考但它的组织方式决定了你七天后是真正掌握还是只会在 README 里打转。2. 上手前先把骨架摸清环境准备与源码目录的一次性梳理2.1 环境依赖清单与版本对齐策略在打开任何代码文件之前我建议先花半小时把运行环境理清楚。很多开发者拿到陌生源码包后第一件事就是pip install一把梭结果装了一堆版本不匹配的依赖随后陷入玄学报错的泥潭。这套 verl 源码包在 README 里其实写明了推荐环境但实际运行时你会发现某些传递依赖的版本需要手动收紧否则会出现「代码逻辑没问题、但跑起来就翻车」的情况。我一般的做法是先创建一个独立的虚拟环境再按照 requirements.txt 安装。这里有一个容易被忽略的细节仓库根目录下通常会有多个 requirements 文件比如requirements/base.txt和requirements/dev.txt前者是运行时的最小依赖集后者额外包含了测试与调试工具。如果只想让核心链路跑起来只装 base 就够了装 dev 反而可能引入与本地 Python 版本冲突的包。创建环境时建议指定 Python 版本常见做法是用 pyenv 或 conda 管理多个版本pyenv install 3.10.11 pyenv virtualenv 3.10.11 verl-dev pyenv activate verl-dev python -m pip install --upgrade pip python -m pip install -r requirements/base.txt这里把 Python 版本锁在 3.10.x 是相对稳妥的选择。verl 源码中用到了一些新语法特性3.8 以下会直接语法报错而 3.11 以上部分依赖库的 wheel 可能还没跟上。3.10 是目前大多数第三方库兼容性最广的版本。如果你本机已经装了别的版本不必强改全局用虚拟环境隔离即可这也为后续反复折腾源码留好了后悔药。参数说明pyenv virtualenv创建的是基于指定 Python 版本的全新环境环境名称verl-dev可以随意改--upgrade pip是为了避免老版本 pip 在解析依赖时出现分歧。安装完成后可以用python -c import verl; print(verl.__file__)来确认包是否被正确装入当前环境这比看安装日志更直接。2.2 目录结构先看懂每个目录的边界再动手改代码环境就绪后下一步是通读源码目录。这套源码包的目录组织方式不算复杂但如果你不去梳理每个模块的边界很容易在阅读时迷失尤其是在跨模块调用频繁的部分。我习惯先用一条命令把目录树打出来再对照 README 的说明逐层理解。tree -L 2 -I __pycache__|*.pyc|.git|.venv|build|dist-L 2表示只显示两级目录避免一下子展开太多把思路带偏-I是排除干扰目录毕竟缓存文件和虚拟环境目录不属于源码阅读范围。执行后你大概会看到这样的结构根目录下分configs、core、interfaces、tests、examples几个一级目录。其中core是核心逻辑所在interfaces则负责与外部系统打交道examples里有可以直接跑通的完整示例脚本tests里是一些针对核心函数的单元测试。我在阅读这一类源码包时有个习惯不按目录顺序逐行读而是从入口脚本出发沿着一次完整的业务请求走一遍。这样能够快速确认数据是怎么从配置读进来、如何经过核心对象处理、最终又通过哪个接口发出去。相比静态地看每个文件这种「跟随调用链」的方式记忆点更深也更容易发现源码中真正关键的设计点。2.3 五分钟跑通最小示例用 examples 里的脚本验证环境目录结构有了基本概念之后别急着深挖每个文件先跑一个最小示例来验证刚才的环境是否正确。这套源码包里提供了几个可独立运行的脚本其中最短的一个只有几十行代码。以下是它的核心逻辑# examples/quickstart.py from verl.core import VerlEngine from verl.interfaces import SimpleOutput def main(): engine VerlEngine.from_config(configs/demo_config.yaml) payload {action: ping, params: {}} result engine.execute(payload) SimpleOutput.render(result) if __name__ __main__: main()这段代码做的事很直接从 YAML 配置文件里读取参数并构建引擎对象构造一个动作词典作为输入然后调用execute方法让整个链路跑一遍最后用工具类把结果打印出来。逻辑说明from_config是工厂方法负责把配置文件里的字段映射到引擎的初始化参数execute是核心入口它会串联起后续的调度、通信与回传流程SimpleOutput.render只是一个结果展示工具不影响业务逻辑。参数说明里你需要关注的是demo_config.yaml。这个文件里通常包含服务地址、超时时间、重试次数、日志级别等关键配置。第一次跑最小示例时我建议不要修改任何默认参数先让代码在「最原始的状态」下通过。如果这一关都过不去问题大概率出在环境依赖上而不是业务逻辑上。3. 核心链路拆解配置加载、调度执行与结果回传的完整闭环3.1 配置加载YAML 如何被映射成引擎参数最小示例跑通后下一步顺着调用链读源码会先碰到from_config背后的实现。这是很多源码包里都不会细讲的暗坑但 verl 的处理方式相当规范。它没有用一堆重复的os.getenv去手工拉参数而是定义了一个数据类把所有配置项集中管理再用一个加载器完成从 YAML 到对象的映射。# core/config.py from dataclasses import dataclass from typing import Optional import yaml dataclass class EngineConfig: host: str 127.0.0.1 port: int 8080 timeout: float 5.0 retry: int 3 log_level: str INFO adapter: Optional[str] None def load_config(path: str) - EngineConfig: with open(path, r, encodingutf-8) as f: raw yaml.safe_load(f) config EngineConfig(**{k: v for k, v in raw.items() if k in EngineConfig.__dataclass_fields__}) return config这段代码的精髓在于最后一行字典推导式只提取数据类中定义过的字段。这样做的好处是即使 YAML 文件里多了几个暂时用不到的配置项也不会触发TypeError。反过来如果 YAML 里漏了某个字段数据类默认值会自动兜底不会一启动就崩溃。实际工程里很多团队会直接把原始字典传给引擎然后在某个方法里用dict.get(host, 127.0.0.1)逐个取值。这种方式虽然灵活但代码会越来越散字段名一旦打错报错信息往往让人摸不着头脑。而数据类方案相当于把配置结构固化下来配合 IDE 的自动补全读代码和改代码都会轻松不少。关于port参数你可能会有一个疑问为什么默认是 8080而不是更常见的 80因为 80 端口通常需要管理员权限开发环境下很容易被系统服务占用。8080 是 HTTP 代理和调试服务常用端口选它作为默认值可以降低首次运行失败的几率。3.2 调度执行execute 方法里藏着的主流程execute是核心引擎的入口它的内部逻辑决定了整个链路的走向。在 verl 源码中这个方法并不会把所有事情都做完而是把任务逐层派发给各个子模块。这样设计的核心意图是让每个模块保持单一职责调度模块只管流程编排不关心底层通信细节通信模块只管收发数据不关心业务含义。# core/engine.py from .executor import TaskExecutor from .transport import TransportProxy class VerlEngine: def __init__(self, config): self.executor TaskExecutor(config.adapter) self.transport TransportProxy(config.host, config.port, config.timeout) def execute(self, payload: dict): task self.executor.normalize(payload) packed task.to_packet() response self.transport.send(packed) return self.executor.interpret(response)这里的关键点是normalize、to_packet、send、interpret四个步骤。normalize把外部传入的字典转换成内部统一的任务结构避免外部格式变化影响核心逻辑to_packet负责序列化将任务对象变成字节流send是真正的网络操作带超时控制interpret则把响应字节流重新解析成业务结果。这种设计的另一层好处是方便测试。你可以用一个假的transport对象替换真实的网络通信只测试normalize和interpret的打包与解包逻辑。许多人在读源码时容易忽略这一层抽象的意义直到需要单测才发现动不了手。3.3 通信与回传上下位机的协议细节与容错机制如果这个源码包的应用场景是让上位机控制端和某个下位机设备服务端交互那么TransportProxy这一段就值得重点关注。它不只是简单的 socket 收发还包含了粘包处理、心跳超时和自动重连等机制。# interfaces/transport.py import socket import struct class TransportProxy: def __init__(self, host, port, timeout5.0): self._addr (host, port) self._timeout timeout self._sock None def _ensure_connected(self): if self._sock is not None: return self._sock socket.create_connection(self._addr, timeoutself._timeout) def send(self, packet: bytes) - bytes: self._ensure_connected() header struct.pack(I, len(packet)) self._sock.sendall(header packet) resp_header self._recv_exact(4) (resp_len,) struct.unpack(I, resp_header) return self._recv_exact(resp_len)这段代码解决了一个非常经典的通信问题接收端如何知道一条完整消息在哪结束。做法是发送前先打包一个 4 字节的无符号整数作为包头里面记录后续业务数据的长度接收时先读包头得到长度再按长度读取剩余部分。_recv_exact是另一个辅助函数它循环调用recv直到读满指定字节数避免一次recv只收到半包就返回。参数说明I表示用大端字节序解析无符号整型网络协议中常见大端序所以这里不能省略struct.pack和struct.unpack是 Python 内置的二进制打包解包工具比手动拼接字节更不容易出错。如果你在二次开发时需要更换协议格式优先修改这里的打包逻辑而不要动上层任务结构。容错方面_ensure_connected会让连接在首次发送时建立并且不会在每次调用后立即关闭这样连续多次请求能复用同一条链路减少握手开销。超时参数self._timeout同时作用于连接建立和后续收发如果对端没有响应调用方会收到socket.timeout异常由上层TaskExecutor决定重试还是放弃。3.4 结果解析从字节流到业务对象的逆过程有打包就有解包interpret方法就是send返回字节流的逆过程。它通常从响应中先读取状态码再读取附加数据。状态码的作用是让业务层无需解析原始内容就能快速判断操作是否成功。# core/executor.py class TaskExecutor: def interpret(self, raw: bytes): status raw[0] if status 0x00: return {ok: True, data: raw[1:]} elif status 0xFF: raise ConnectionError(remote execution failed) else: return {ok: False, code: status, data: raw[1:]}这里第一字节作为状态标识是一个极简约定0x00表示成功0xFF表示远端执行出错其他值则保留给业务自定义异常。后面跟随的字节是真正的数据区。如果你的业务需要区分更多错误类型完全可以在第二字节再细分但为了保持兼容性第一字节的语义建议不要随意改动。从整个链路来看配置加载、调度执行、通信收发、结果解析这四个环节环环相扣。任何一个环节出了问题都不会直接告诉你「XX模块坏了」而是表现为上层调用报错。所以在排查问题时一定要从调用链的角度逐层定位而不是盯着某一个文件反复看。4. 避坑指南源码复现中最容易翻车的五个细节4.1 现象端口被系统服务占用启动报Address already in use现象执行示例脚本时网络层抛出OSError: [Errno 98] Address already in use。原因源码默认的通信端口是 8080而本机某些服务如开发代理、容器映射已经占用了这个端口导致 socket 绑定失败。解决修改demo_config.yaml中的port字段换一个不常用端口比如 18080 或 28080。如果换端口后依然报错用lsof -i :端口号或netstat -anp | grep 端口号找出占用进程确认它不是自己之前启动的残留进程后再决定是杀掉还是换端口。4.2 现象pip install时依赖解析冲突安装被迫中断现象安装 base 依赖时pip 提示某个传递依赖要求 Python 版本小于某个值而本机虚拟环境是 3.11。原因某些基础库比如二进制扩展类库在新版 Python 上还没有可用的 wheelpip 尝试从源码编译时失败。解决最省事的做法是退回 3.10 系列创建虚拟环境然后在安装时固定约束版本pip install -r requirements/base.txt --no-cache-dir。--no-cache-dir的作用是强制重新拉取包避免本地缓存的坏 wheel 干扰。如果问题依然存在可以尝试逐个安装依赖并定位具体是哪个包在搞事。4.3 现象读取本地配置文件成功但运行时参数没生效现象修改了 YAML 里某个字段的值程序输出结果却和修改前一致。原因demo_config.yaml里写的键名和EngineConfig数据类字段名不一致比如 YAML 写的是max_wait_time而数据类定义的是timeout。字段名拼不上时加载器会静默忽略该键我们以为改的是超时时间实际它根本没被读取。解决对照EngineConfig.__dataclass_fields__里逐个检查 YAML 键名。加载后还可以加一条调试输出print(engine.config)确认实际生效的配置值。这个方法看起来原始却能在配置项特别多时快速定位问题。4.4 现象结果解析出来全是乱码interpret抛 Unicode 错误现象interpret方法在解码响应时抛出UnicodeDecodeError。原因我们的代码里默认raw[1:]是文本数据但实际返回的是二进制内容或不同的字符编码。解决先不要立刻改代码在interpret里临时加一行日志print(raw.hex())把十六进制内容打出来确认对端到底发的是什么。然后根据实际情况决定是保留二进制原始数据还是在to_packet阶段写明编码格式让两端保持一致。4.5 现象示例能跑通但集成到自己的工程里就报ImportError现象在自己项目中from verl.core import VerlEngine时提示模块找不到。原因自己项目的工作目录不在 verl 仓库根目录下而模块导入依赖于项目根目录被加入sys.path; 或者用 IDE 直接打开了子文件导致根路径解析错误。解决在自己项目入口文件的最前面加入以下代码import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent))这句话把仓库根目录加入模块搜索路径之后再做导入就不会找不到包了。如果你用的是包管理工具也可以直接用pip install -e .把 verl 以可编辑模式安装进环境这样所有导入都不用手动处理路径。5. 最后一步用日志链路和状态码快速定位源码问题源码读到这个阶段你已经对 verl 的整体结构有了清晰认识。此时真正拉开差距的能力不是「能读懂代码」而是「在改出问题时能快速定位」。我最后分享一个自己一直在用的技巧把日志输出和状态码结合成一个快速排查链路这比单纯设断点调试高效很多。先说日志链路。verl 的from_config支持传入log_level参数默认是INFO。建议在实际排查时调到DEBUG这样引擎内部每个关键步骤都会输出提示比如配置加载完成、任务已经序列化、准备发送报文、收到响应等。开启方式有两种修改 YAML 文件里的log_level: DEBUG或者直接在实例化时传入config.log_level。我一般会选择改 YAML因为这样更接近真实部署环境。再说状态码链路。前面提到interpret方法用响应中的第一字节作为状态标识这是一个非常好的排查锚点。假如你发现某次操作不达预期第一步不是看业务日志而是先确认返回的状态码是0x00还是其他数字。状态码不是0x00说明问题大概率在远端服务或通信过程中而不在调用方状态码是0x00但结果不对说明问题出在你对返回数据的解释上。基于这两条线索我一般会把异常排查拆成三步走。第一步打开 DEBUG 日志看整个调用链走到了哪一步第二步看状态码确定异常范围是在远端还是在本端第三步在send调用前后加计时信息确认是不是超时重试导致的行为异常。有一次我在集成 verl 到自己的模拟项目 X 时任务总是执行失败但每次失败方式都不一样。一开始怀疑是调度逻辑问题后来打开 DEBUG 日志发现每次都在发送阶段失败再看状态码是0xFF说明远端根本没收到完整请求。顺藤摸瓜排查最后确认是我自己项目里另外一个工具把 socket 默认超时改掉了导致 verl 的代理层继承了一个过短的超时时间。从那以后我每次接入陌生代码包都会先确认全局网络参数有没有被别的组件改写过再开始调业务逻辑。如果你也想在七天内吃透这套源码建议给自己定一个验收标准不看任何注释能把configs/demo_config.yaml里的每个字段都改成自己理解的值并准确预测改动后对程序行为的影响。能做到这一点说明你已经不是在看代码而是在掌控代码。希望这篇拆解能帮你少走一些弯路也期待你踩到新坑时能想起用日志和状态码的组合把它快速揪出来。本文还有配套的精品资源点击获取

相关新闻

多动作并行异步DDPG:选矿浮选智能决策模型工程化实践

多动作并行异步DDPG:选矿浮选智能决策模型工程化实践

简介:本资源是一篇发表于《控制与决策》2022年第8期的学术论文PDF,面向自动化、智能优化与流程工业领域的研究生、科研人员及工程技术人员,聚焦选矿过程运行指标的动态决策难题。针对传统深度确定性策略梯度(DDPG)算法…

2026/10/18 14:09:21 阅读更多 →
UVM验证环境自动生成工具:一键生成testbench与组件代码

UVM验证环境自动生成工具:一键生成testbench与组件代码

简介:这是一款面向数字芯片验证工程师的UVM环境自动化构建工具,专为降低SystemVerilog验证平台搭建门槛而设计,尤其适合初/中级验证人员及需快速迭代验证场景的团队。资源包共78个文件,含14个核心UVM SystemVerilog源码&#xff0…

2026/10/18 14:09:21 阅读更多 →
AI 接进办公文档后,为什么还是会读错?从结构保真到结果复核的实现链路

AI 接进办公文档后,为什么还是会读错?从结构保真到结果复核的实现链路

办公 AI 的常见误差,往往从模型看到文档之前就开始了:表格中的列名丢了,批注混进正文了,脚注里的限制条件被截断了。等模型接到一段看似完整的文本,它可能已经失去了判断业务含义所需的关系。 因此,可靠的…

2026/10/18 14:09:21 阅读更多 →

最新新闻

Reflector 7.4.1.179 绿色注册版部署指南:插件集成与避坑实践

Reflector 7.4.1.179 绿色注册版部署指南:插件集成与避坑实践

简介:这是一份面向.NET开发者的反编译工具整合包,主角是经典的.NET Reflector 7.4.1.179绿色注册版,并真正集成了FileDisassembler与FileGenerator两款广受好评的插件,解决原版只能逐个查看方法、无法批量导出源码的痛点。包内共2…

2026/10/18 14:58:53 阅读更多 →
Vue权限控制实战:路由、菜单与按钮级权限完整链路

Vue权限控制实战:路由、菜单与按钮级权限完整链路

简介:这份资源面向正在开发后台管理系统的Vue前端开发者,聚焦权限控制这一核心场景,帮助解决不同角色用户只能访问被授权功能的问题。内容围绕两种主流限制方式展开:一是路由不可见,借助Vue Router的meta字段存储权限列…

2026/10/18 14:58:53 阅读更多 →
建筑施工安全技术资料如何变成项目台账?链路拆解与归档实操

建筑施工安全技术资料如何变成项目台账?链路拆解与归档实操

简介:建筑施工安全技术资料是现场安全管理的底账,而非应付检查的废纸。其核心原理是把方案、交底、检查、验收、整改五个环节串成管理链路,再按塔吊、基坑、临电等对象建立检索维度,形成“链路对象”的矩阵台账。通过统一编号、逐…

2026/10/18 14:58:53 阅读更多 →
YOLOv8骨干替换EfficientNetV2:均质架构提升小目标检测与推理性能

YOLOv8骨干替换EfficientNetV2:均质架构提升小目标检测与推理性能

1. 改造动机与方案选型1.1 YOLOv8原有骨干的瓶颈在哪里动手换主干之前,我先把YOLOv8原生CSPDarknet53的短板列了一遍。YOLOv8默认的backbone在COCO这类通用检测任务上确实够用,但一旦碰到分辨率高、小目标密集或纹理细节要求高的场景,它的问题…

2026/10/18 14:58:53 阅读更多 →
STM32F407 DCMI图像采集丢帧错位的硬件时序真相

STM32F407 DCMI图像采集丢帧错位的硬件时序真相

简介:本资源是一份基于STM32F407微控制器的高速并行12位ADC与DCMI数字摄像头接口协同开发实践方案,面向嵌入式初学者及图像采集方向进阶开发者,解决模拟信号高速采样与图像数据流同步传输的核心工程问题,适用于工业检测、智能视觉…

2026/10/18 14:58:53 阅读更多 →
《华为团队工作法》华为人才管理和薪酬激励:构建四位一体点燃员工热情的激励体系

《华为团队工作法》华为人才管理和薪酬激励:构建四位一体点燃员工热情的激励体系

本 115 页 PPT 适配企业人才管理、薪酬激励、干部管理类咨询方案与 HR 培训课件编制。基于华为人才管理体系核心实践,系统拆解人才选配、评估、干部任用、人才成长、文化锻造、薪酬激励、全面激励、健康成长八大模块。涵盖 STAR 行为面试、人才搭配四宫格、绩效能力…

2026/10/18 14:57:52 阅读更多 →

日新闻

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

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

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

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

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

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

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

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

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

2026/10/18 0:00:55 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 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/18 0:55:02 阅读更多 →
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/18 12:16:16 阅读更多 →