RD-Agent 日志卡顿 3 步修复指南:让 Web UI 从白屏到秒开
【免费下载链接】RD-AgentResearch and development (R&D) is crucial for the enhancement of industrial productivity, especially in the AI era, where the core aspects of R&D are mainly focused on data and models. We are committed to automating these high-value generic R&D processes through R&D-Agent, which lets AI drive>项目地址: https://gitcode.com/GitHub_Trending/rd/RD-Agent
RD-Agent 日志卡顿是它 Web UI 目前最容易碰上的问题:日志面板刷屏、页面卡死,或者点一次 "All Loops" 后长时间白屏没反应。这类卡顿的根源不在你的浏览器,而在日志显示链路的渲染、传输、配置三处。读 2 分钟原理,照 3 个步骤动手改,再用一张对比表验收,全程大约 10 分钟。改完你拿到的,是一个能实时盯日志、页面不僵死的界面。
本文代码以仓库当前主分支为准,本地没有的话用git clone https://gitcode.com/GitHub_Trending/rd/RD-Agent获取。
上图是日志页面顶部会展示的流程:Idea 到 Experiment 再到 Feedback 的每个阶段,都对应一段日志输出。理解这张图,后面看日志卡在哪就顺了。
卡在哪:显示链路上的 3 个薄弱点
先别急着改代码,机制讲清楚只要三点:
- 渲染端:Web UI 基于 Streamlit(一个用 Python 直接写网页的框架)搭建,每条日志都走
st.code()生成一个独立 code 块(见rdagent/log/ui/web.py的StWindow.consume_msg)。DOM 节点随日志条数线性增长,浏览器重排开销随之暴涨,滚动开始发滞。 - 传输端:日志读取是同步阻塞的。
rdagent/log/ui/app.py里的get_msgs_until()在循环里不停调next(),"All Loops" 按钮相当于"把整份日志读完整齐才出第一屏",页面只能干等白屏。 - 配置端:消息结构
Message(rdagent/log/base.py)本身带 level 级别字段,但界面默认不按级别过滤,只把 llm_messages 和 str 两类当噪音排除,大量调试内容原样进入渲染。
分步实操:先减量,再提速
第 1 步:日志级别怎么调——先把无效输出挡在门外
做什么:让渲染之前先过一道过滤,把总量降下来。
怎么做:两处入手。
- 日志页面侧边栏打开 Config 面板,在 "excluded log tags / excluded log types" 多选框里勾掉明确无用的内容。注意
debug_tpl、debug_llm在should_display()里已被硬编码排除,重复添加没有效果。 - 长期方案:扩展
rdagent/log/conf.py的LogSettings。它带LOG_环境变量前缀,可以加一个默认级别或待排除标签列表,再在FileStorage.iter_msg()(rdagent/log/storage.py,负责从磁盘读日志文件的类)加载 pkl 日志文件时应用过滤。
怎么验证:打开页面后展开 Debug Info 面板,看 "message id" 计数——和改动前比明显下降,这步才算生效。
做完这一步,进入页面的日志量应该肉眼可见地变少。如果还有上千条,说明瓶颈转移到了渲染端。
第 2 步:改造 StWindow——别再一条日志一个 code 块
做什么:把"每来一条就新增一个 DOM 节点"改成"固定窗口覆盖渲染",页面上永远只有固定数量的日志可见。
怎么做:重写rdagent/log/ui/web.py的StWindow。核心是维护一个有上限的本地缓存,并用container.empty()复用同一个容器,每次都清空重画,而不是追加。
# rdagent/log/ui/web.py:StWindow 改为"固定窗口 + 容器复用" class StWindow: def __init__(self, container): self.container, self.cache = container, [] # 新增:本地缓存 def consume_msg(self, msg): self.cache = (self.cache + [msg])[-50:] # 改:只保留最近 50 条 box = self.container.empty() # 改:复用容器,不再每条追加新块 with box: for m in self.cache: st.code(f"{m.level} | {m.content}")怎么验证:F12 打开开发者工具,数一下日志区域的 code 块节点。日志再多,节点数也稳定在一百五左右,不再是几千。
渲染端被管住后,页面不会再被日志总量拖垮,但点 "All Loops" 后那段白屏还在——那是传输端的问题。
第 3 步:流式推送怎么改——首屏不再等全量日志
做什么:把"同步等全部读完"改成"分块读、边读边出",有余力再改异步推送。
怎么做:rdagent/log/ui/app.py的症结是get_msgs_until()的 while 循环一口气跑到底,而 "All Loops" 传入的停止条件永远不触发。最小改动是给每次读取加个上限:
# rdagent/log/ui/app.py:get_msgs_until 改成"每次最多读 N 条" def get_msgs_until(end_func=lambda _: True, limit=200): read = 0 while read < limit: # 改:单次限量,首屏快速出 try: msg = next(state.fs) except StopIteration: break # 原有 should_display 过滤与统计逻辑保持不变 read += 1想要更彻底,就改成推送模式:前端订阅一个流(SSE 或 WebSocket),后端每读出一条就发一条。
怎么验证:点 "All Loops" 后,首屏约 2 秒内出现,之后的日志逐批续上,而不是卡半天后一次性跳到末尾。
改完什么样:前后对比
| 指标 | 优化前 | 优化后 |
|---|---|---|
| 点 "All Loops" 后首屏 | 分钟级,同步等全量读完 | 约 2 秒,之后分批更新 |
| 日志区 DOM 节点 | 1 条日志 = 1 个 code 块,5000 条约 5000 个 | 恒定约 150 个(只留最近 50 条) |
| 内存占用走势 | 随日志条数线性上涨 | 缓存封顶,不再随条数增长 |
| 可承载日志量 | 上千条开始明显卡 | 可支撑提升一个数量级 |
"优化后"一列是完成第 2、3 步后的目标值,请以你机器上 F12 的 Performance 面板和 message id 计数实测为准。
改完出现 X 怎么办:3 个高频坑
⚠️ 改完之后最容易踩的三处,各给一句解法:
- 翻不回旧日志了→ 上限只作用于屏幕,历史仍在本地日志目录(
LOG_SETTINGS.trace_path),需要回溯时直接用FileStorage按 tag 过滤打开,别依赖前端缓存。 - "Next Loop" 停错了位置→ 停止条件(
end_func参数)是这个函数的灵魂,改造只改"单次读多少",别动"读到哪停"。 - 加了标签,面板没变化→ 多半加的是已被硬编码排除的 tag,或页面上根本不出现的 tag;先对照 Debug Info 里实际打出来的 tag 再加。
三步做完,日志链路在读取、传输、渲染三侧都瘦了身,RD-Agent 日志卡顿基本到头了。如果还想继续要空间,下一步是把日志传输做成真流式:rdagent/log/ui/storage.py的WebStorage已经在用 HTTP POST 把消息推给 UI 服务,把它扩成常驻通道、前端边到边订阅即可。开发规范可以参考docs/development.rst。
【免费下载链接】RD-AgentResearch and development (R&D) is crucial for the enhancement of industrial productivity, especially in the AI era, where the core aspects of R&D are mainly focused on data and models. We are committed to automating these high-value generic R&D processes through R&D-Agent, which lets AI drive>项目地址: https://gitcode.com/GitHub_Trending/rd/RD-Agent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考