agentscope-ai / agentscope-ai/QwenPaw

[Bug]: 仅启用 console 渠道时启动仍需 30-45 秒 —— _load_builtin_channels() 无条件导入全部 18 个渠道模块(lark_oapi 单个包约 18.5 秒)

Open
#7,367 2 comments 0 reactions 1 assignee Claimed by @hongxicheng View on GitHub
bug
Dominant language
TypeScript
Stars
35k
Forks
3.1k
Avg merge
1d 13h
Merged PRs (30d)
228

Description

**正文:**

## QwenPaw 版本

2.1.0(reme-ai 0.4.1.5)

## 问题描述

**只启用 `console` 一个渠道**时,服务启动仍要 30-45 秒。根因:每次进程启动时,第一次调用 `get_channel_registry()`(发生在 workspace 启动期间的 `ChannelManager.from_config()` 中)会**无条件 import 全部 18 个内置渠道模块**,其中包括大量根本不会被使用的重型第三方 SDK。

在 Windows 11 + pip 默认全量依赖的环境下实测:

- `lark_oapi`(飞书 SDK):**10727 个 .py 文件、48.8 MB,冷 import 约 18.5 秒**
- `aibot`:2.4 秒
- `telegram`、`slack_bolt`:各约 0.5 秒
- 其余渠道模块:合计数秒

因此 `channel_manager` 这个 workspace 服务在隔离复现中占了 **`Workspace.start()` 总耗时 35 秒里的 32 秒**。

单机一周内的启动耗时趋势(来自 `~/.qwenpaw/qwenpaw.log` 的 `Background startup completed in ...`):

| 日期 | 启动耗时 | 备注 |
| ----------------------- | ------------ | ------------------------------ |
| 08-22(lark-oapi 安装前) | 9.7s / 12.8s | |
| 08-22 18:26 | — | 安装 `lark-oapi` 1.7.3 |
| 08-24 | 11-22s | |
| 08-25 ~ 08-28 | 33-46s | 每次启动都有稳定的 35-39s 空档 |

## 受影响组件

- [x] Core / Backend(app、agents、config、providers、utils、local_models)
- [x] Channels(DingTalk、Feishu、QQ、Discord、iMessage 等)

## 环境

- **QwenPaw 版本:** 2.1.0
- **操作系统:** Windows 11(AMD64)
- **安装方式:** pip
- **Python 版本:** 3.12

## 复现步骤

1. `pip install qwenpaw`(会装上全部渠道 SDK,包括 `lark-oapi`、`aibot`/`wecom-aibot-python-sdk` 等)
2. 只配置 `console` 渠道(`channels.console.enabled = true`,其余渠道全部禁用)
3. 运行 `qwenpaw app`
4. 观察到 `Background startup completed in ~35-45s`,且日志中 `Initializing ReMe Application` 与 `Console channel started` 之间存在约 35-39 秒的完全空档

## 实际 vs 预期

- **实际:** 启动约 45 秒;`channel_manager` 服务约 32 秒(逐 service 计时:`local_workspace` 0.01s、`session` 0.00s、`chat_manager` 0.00s、`driver_manager` 0.30s、`memory_manager` 1.30s、**`channel_manager` 32.21s**、`cron_manager` 0.01s)
- **预期:** 只 import 实际启用的渠道;启动约 10-15 秒

## 日志 / 截图

```
09:28:49 | Server ready in 2.423s (background startup follows)
09:28:50 | Starting workspace: default
09:28:50 | Starting workspace: <第二个 agent>
09:28:51 | Initializing ReMe Application v0.4.1.5
09:28:51 | WARNING: memory_manager failed to start for <第二个 agent>: No active model configured.
[ 约 39 秒完全无日志输出 ]
09:29:30 | Console channel started
09:29:31 | Workspace started successfully: default
09:29:32 | Background startup completed in 45.250s
```

隔离复现(把 workspace 目录复制到临时路径,在独立进程中跑 `Workspace.start()`,对 `ServiceManager._start_service` 打点):

```
service local_workspace = 0.01s
service session = 0.00s
service chat_manager = 0.00s
service driver_manager = 0.30s
service memory_manager = 1.30s
service channel_manager = 32.21s <-- 时间全部消耗在第一条渠道日志之前
service cron_manager = 0.01s
workspace.start() TOTAL = 35.02s
```

冷 import 耗时(全新进程;.pyc 已全量存在;Defender 实时防护已关闭——纯 import 机制成本):

```
lark_oapi 18.46s (10727 个 .py 文件)
aibot 2.40s
telegram 0.50s
slack_bolt 0.57s
dingtalk_stream 0.04s
paho.mqtt 0.01s
```

## 补充说明

- `QWENPAW_ENABLED_CHANNELS` / `QWENPAW_DISABLED_CHANNELS` 环境变量**救不了**:`get_available_channels()`(config/utils.py)自己就先调用了 `get_channel_registry()`,完整 import 发生在任何过滤之前。
- `qwenpaw/app/channels/__init__.py` 已经对 `ChannelManager` 做了懒加载,注释写明是 *"to avoid pulling feishu/lark_oapi on CLI"*,但注册表(`qwenpaw/app/channels/registry.py` 的 `_load_builtin_channels()`)在 server 路径上仍然全量 import。
- **已有一个可用的本地补丁**(已应用到 site-packages 并验证):只急切 import 必需的 `console` 渠道,其余 17 个渠道包一层懒代理,首次属性访问时才 import 真实模块并缓存结果。已验证:import 注册表后 `sys.modules` 中不再出现 `lark_oapi`;`registry["feishu"].from_config` 首次使用时能正确解析出真实的 `FeishuChannel`(一次性 21.8 秒,只在渠道真正被启用/使用时才付出)。打补丁后启动预期 ≈ 10-15 秒。
- 上游 PR 需要处理的一个行为变化:急切加载时,某个渠道依赖缺失会在注册表构建阶段被静默跳过;懒加载后,import 错误会在该渠道首次使用时才暴露。`ChannelManager.from_config` 中 `inspect.signature(ch_cls.from_config)` 这行位于包装实例化的 `try:` 之前——应挪进 `try` 内,让依赖损坏的渠道退化为现有的 "skipping: ..." 告警,而不是直接中断 workspace 启动。
-

Image

Contributor guide

Open the contributing guide

Research direction

Start with qwenpaw/app/channels/registry.py and _load_builtin_channels(), then trace get_available_channels() in config/utils.py and ChannelManager.from_config. Reproduce the console-only startup and verify that unused channel SDKs are not imported, while a missing channel dependency still produces the existing “skipping” warning instead of aborting workspace startup.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.