Files
vllm_agent_strategy/STRATEGY_DESIGN.md
2026-07-21 16:04:18 +08:00

574 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# vLLM/未来 GGUF 智能体提交策略设计
## 1. 背景和目标
当前目标不是“尽量多下载模型”,而是“尽量多产生验证成功的提交”。现在只有智能体提交的任务才会触发验证,因此本地脚本主要用于理解接口和策略,最终提交逻辑应在智能体服务中执行。
旧流程大致是:
```text
fetchModel_db.py -> Download_db.py -> Submit_db.py / Promote_db.py
```
主要问题:
1. `Download_db.py` 以下载为主线,下载池满时会阻塞,导致后续模型无法继续扫描。
2. `Promote_db.py` 思路正确,但候选来源过窄,只依赖本地 `downloaded` 表。
3. `Submit_db.py / Promote_db.py` 使用模型级 `in_db` 状态,不适合按 `model_id + gpu_type` 最大化 2000 个任务额度。
4. 页面上的“批量模型悬赏”没有直接给模型 ID只提示目标算力因此不能直接爬出模型任务。
新版策略应该是:
```text
手动设置悬赏/目标算力
-> 爬 ModelHub 已入库模型
-> 找出目标算力未适配的模型
-> 按模型类型选择 vLLM 或未来 GGUF/llamacpp 路线
-> 生成 model_id + gpu_type 任务
-> 智能体优先提交高成功率任务
```
当前实现阶段只做 vLLMGGUF/llamacpp 先在文档里明确策略,后续再实现。
---
## 2. 总体优先级
推荐优先级如下:
```text
P0: 手动配置的悬赏目标算力 + ModelHub 已入库 + 目标算力未适配的模型
P1: 普通目标算力未适配的已入库模型
P2: admin/tools/model-download 页面中别人已经下载成功的模型
P3: 自己下载 HuggingFace 新模型
```
其中 P0/P1 是 Promote 思路的升级版:模型已经在平台存在,说明至少已经被验证/入库过;如果某个目标算力还没有适配成功,就提交到该目标算力。
P2 只能说明模型文件已成功下载,不一定说明模型已验证成功,因此优先级低于已入库未适配模型。
P3 自己下载风险最高、成本最高,放最后。
---
## 3. Step 1目标算力手动配置
无需自动爬取 `https://modelhub.org.cn/#/adaptation-model` 页面里的“批量模型悬赏”。原因:
1. 页面没有直接给模型 ID。
2. 手动看一眼目标算力更快、更稳定。
3. 自动爬页面还要解析 hash route / XHR维护成本高。
建议通过环境变量或配置文件手动指定目标算力。
### 3.1 建议配置
```text
TARGET_MACHINE_NAMES=MTT S4000,Hygon K100,Kunlunxin P800,Biren 166M
TARGET_TASK_LEVEL=文本生成
```
同时需要维护一张页面展示名到提交 GPU alias 的映射表。
示例:
```python
MACHINE_TO_GPU_ALIAS = {
"MTT S4000": "s4000",
"Hygon K100": "k100",
"Kunlunxin P800": "p800",
"Biren 166M": "biren166m",
"Ascend 910B": "910b",
"Iluvatar BI100": "bi100",
"Iluvatar BI150": "bi150",
"MetaX C500": "c500",
"Iluvatar MRV100": "mrv100",
"Cambricon MLU370-X4": "mlu370-x4",
"Cambricon MLU370-X8": "mlu370-x8",
}
```
这张表需要根据 `/api/computility/models/list/page/vo` 返回的 `machines[].machineName` 实际值校准。
---
## 4. Step 2爬 ModelHub 已入库模型
参考 `D:\4paradigm\fetch_not_adapted_models.py`
使用接口:
```text
POST https://modelhub.org.cn/api/computility/models/list/page/vo
```
请求示例:
```json
{
"current": 1,
"pageSize": 100,
"searchText": ""
}
```
返回里重点字段:
```text
modelId
machines[].machineName
taskLevelChineseName
taskLevelsInfo.taskLevelChineseName
```
扫描逻辑:
1. 分页拉取平台已入库模型。
2. 只保留文本生成模型:
```python
model_task = (
model.get("taskLevelChineseName")
or model.get("taskLevelsInfo", {}).get("taskLevelChineseName")
or ""
)
if "文本生成" not in model_task:
skip
```
3. 读取已适配算力:
```python
machines = model.get("machines", [])
adapted_machines = [m.get("machineName") for m in machines if m.get("machineName")]
```
4. 对每个手动配置的目标算力,如果目标算力不在 `adapted_machines` 中,则生成候选任务。
```text
model_id + target_gpu_alias
```
---
## 5. Step 3 / Step 4区分 vLLM 模型和 GGUF 模型
这里需要纠正之前的“直接过滤 GGUF”策略。
当前阶段只实现 vLLM所以 GGUF 先不提交,但不能简单认为 GGUF 没用。GGUF 模型应该走 llamacpp而且根据经验成功率更高的芯片是
```text
910b
s4000
```
因此模型类型判断应该是:
```text
如果 model_id 或相关权重文件包含 gguf
标记为 engine=llamacpp_candidate
当前 vLLM-only 阶段不提交
后续 GGUF 优先提交到 910b、s4000
否则:
标记为 engine=vllm
当前阶段可提交
```
### 5.1 当前 vLLM-only 阶段
当前阶段策略:
```text
非 GGUF 模型:进入 vLLM 任务队列
GGUF 模型:写入候选表,但 status=skipped_gguf 或 engine=llamacpp_candidate不提交
```
不要把 GGUF 完全丢弃,避免后续 GGUF/llamacpp 优化时还要重新爬。
### 5.2 未来 GGUF/llamacpp 阶段
后续实现 GGUF 后,策略应为:
```text
GGUF 模型优先目标 GPU910b, s4000
框架llamacpp
权重文件:需要具体 .gguf 文件名
```
可以参考旧文件:
- `D:\4paradigm\fetchModel2_gguf.py`
- `D:\4paradigm\run_llamacpp.py`
- `D:\4paradigm\Utils_db.py` 中的 `choose_llamacpp_config()`
GGUF 任务粒度未来应是:
```text
model_id + weight_file + gpu_type + engine=llamacpp
```
而不是只用 `model_id + gpu_type`
---
## 6. Step 5别人已下载成功模型来源
别人已下载成功的模型可以从页面:
```text
https://modelhub.org.cn/admin/tools/model-download
```
页面中选择:
```text
状态 = 成功
pageSize = 50
```
可以看到类似:
```text
Aimiliya0011/lora_409
```
这类模型说明文件已经在平台下载成功,可以作为 P2 候选。
### 6.1 已确认接口
页面背后的接口已确认:
```text
GET https://modelhub.org.cn/adminApi/async/task/model-download-task
```
查询参数:
```text
current=1
pageSize=50
status=SUCCESS
```
示例:
```text
https://modelhub.org.cn/adminApi/async/task/model-download-task?current=1&pageSize=50&status=SUCCESS
```
该接口需要认证请求头。直接在浏览器地址栏打开通常会返回 401
```json
{"code":401,"data":null,"message":"请提供有效的JWT Token或Xc-Token"}
```
代码里需要像旧版 `Utils_db.py` 一样携带:
```text
Authorization: Bearer <AUTH_TOKEN>
Xc-Token: <AUTH_TOKEN>
Content-Type: application/json
```
Response 结构示例:
```json
{
"code": 0,
"data": {
"records": [
{
"id": "3464438",
"name": "DOWNLOAD_MODEL",
"args": {
"hf_token": "hf_***gE",
"storage_type": "juicefs",
"user_email": "adminProxy@4paradigm.com",
"user_id": 82,
"source": "HuggingFace",
"model_id": "bryn107/llama3-8b-indonesian-legal-bot"
}
}
]
}
}
```
关键字段:
```text
records 路径: data.records
model_id 路径: records[].args.model_id
source 路径: records[].args.source
任务 id 路径: records[].id
```
注意字段名是 `args.model_id`,不是顶层 `modelId`
分页停止条件:
```text
优先使用 data.total 判断是否结束;
如果没有 total则 records 为空或 len(records) < pageSize 时结束。
```
### 6.2 source 规范化
接口返回的来源可能是页面展示值,例如:
```text
HuggingFace
ModelScope
```
新版内部建议规范化为旧脚本使用的枚举:
```python
SOURCE_MAP = {
"HuggingFace": "HUGGING_FACE",
"ModelScope": "MODEL_SCOPE",
}
```
### 6.3 爬取后处理
爬到别人已下载成功模型后:
```text
origin=downloaded_success_page
priority=20
known_downloaded_by_others=1
```
然后根据模型类型:
```text
非 GGUF -> engine=vllm进入 vLLM 候选
GGUF -> engine=llamacpp_candidate当前阶段暂存不提交
```
注意:别人已下载成功不代表已验证成功,所以优先级低于 ModelHub 已入库未适配模型。
---
## 7. 下载策略
自己下载仍然保留,但只作为最后补充。
规则:
```text
MAX_SELF_DOWNLOADS=8
```
即每个人后台同时下载的模型最多 8 个。
旧问题是:下载池满时 `Download_db.py` 会 sleep导致后面的模型无法继续扫描。
新版规则:
```text
下载池满,只停止创建新的自下载任务;不停止:
- 爬 ModelHub 已入库模型
- 爬别人下载成功模型
- 提交 bounty/promote 任务
- 扫描后续候选
```
遇到下载相关返回:
```text
code=0 -> 自己创建下载任务active_self_slot +1
code=40000 -> 别人/已有任务正在下载,不占自己的 8 个槽,后续轮询
code=60004 -> 已下载过,查状态,成功则进入提交候选
code=60005 -> 自己下载池满,当前任务 backoff不全局 sleep
```
---
## 8. 提交策略
所有正式提交都应由智能体服务执行。
任务粒度:
```text
vLLM: model_id + gpu_type + engine=vllm
llamacpp: model_id + weight_file + gpu_type + engine=llamacpp # 未来
```
每人最多 2000 个任务,建议保守按 materialized task 数量控制,避免超量。
提交返回处理参考 `Utils_db.submit()`
```text
code=0 && message=ok -> submitted
code=40000 && message 包含 正在验证中 -> conflict / running
code=60007 -> 当前 task/gpu queue_full_backoff
其他 -> failed 或短 backoff
```
关键原则:
```text
任何一个 GPU 队列满,都不能让整个策略 sleep。
只给当前 task 或当前 gpu_type 设置 backoff然后继续提交其他 GPU / 其他模型。
```
---
## 9. 推荐新版候选来源和状态
### 9.1 candidate origin
```text
bounty_target_not_adapted # 手动目标算力 + 已入库模型 + 目标算力未适配
normal_target_not_adapted # 普通目标算力未适配
model_download_success_page # admin/tools/model-download 状态成功页面
hf_self_download_seed # HuggingFace 新模型自下载候选
manual_seed # 手动补充
```
### 9.2 engine 类型
```text
vllm
llamacpp_candidate
llamacpp # 未来正式实现
```
### 9.3 task status
```text
pending
ready_to_submit
waiting_download
submitted
conflict
queue_full_backoff
failed
skipped_gguf
skipped_unsupported_gpu
budget_blocked
```
---
## 10. 当前代码需要如何调整
当前 `vllm_agent_strategy` 已经实现了 seed fallback 和 vLLM 调度骨架,但需要根据本设计做以下调整。
### 10.1 新增 target-not-adapted crawler
新增模块:
```text
app/clients/modelhub.py
list_modelhub_models(page, page_size, search_text="")
fetch_not_adapted_models(machine_name, task_level="文本生成")
```
或者单独:
```text
app/crawlers/not_adapted.py
```
功能:
```text
读取 TARGET_MACHINE_NAMES
分页调用 /api/computility/models/list/page/vo
筛选文本生成
按 machines 判断目标算力未适配
区分 GGUF / 非 GGUF
写入 candidates
```
### 10.2 新增 machine mapping
新增:
```text
app/domain/machines.py
```
包含:
```python
MACHINE_TO_GPU_ALIAS = {...}
```
### 10.3 调整 GGUF 处理
当前 vLLM-only 阶段:
```text
GGUF 不提交,但写入 candidates/tasks 或 gguf_candidates 表
状态为 skipped_gguf / llamacpp_candidate
```
后续 GGUF 实现时,只处理:
```text
gpu_alias in [910b, s4000]
engine=llamacpp
```
### 10.4 新增 model-download success crawler
新增模块:
```text
app/crawlers/download_success.py
```
接口已确认:
```text
GET /adminApi/async/task/model-download-task?current=<page>&pageSize=50&status=SUCCESS
```
功能:
```text
携带 Authorization / Xc-Token 认证头
按 current/pageSize/status=SUCCESS 分页
从 data.records[].args.model_id 提取 model_id
从 data.records[].args.source 提取 source 并规范化
区分 GGUF / 非 GGUF
写入 P2 candidates
```
推荐在 `app/clients/modelhub.py` 增加:
```text
list_success_download_tasks(current, page_size)
fetch_success_downloaded_models(page_size=50, max_pages=None)
```
---
## 11. 推荐实施顺序
1. 先不要自动爬 adaptation-model 页面目标算力,改为手动配置 `TARGET_MACHINE_NAMES`
2. 实现 `fetch_not_adapted_models.py` 的逻辑到新版智能体目录。
3. 新增 machineName -> gpu_alias 映射。
4. 增加 GGUF 识别:当前 vLLM-only 阶段不提交 GGUF但保留候选。
5. 把 P0 任务来源从 `manual_bounty seed` 改为 `bounty_target_not_adapted crawler`
6. 保留 manual seed 作为兜底。
7. 基于已确认的 `/adminApi/async/task/model-download-task?status=SUCCESS` 接口,实现别人下载成功模型爬取。
8. 最后再考虑 GGUF/llamacpp优先 910b 和 s4000。
---
## 12. 当前最重要的结论
1. 不需要爬取“批量模型悬赏”的目标算力,手动配置更快更稳。
2. 真正有价值的是用手动目标算力去爬 ModelHub 已入库模型,筛选“目标算力未适配”的模型。
3. GGUF 不能简单丢弃;当前 vLLM 阶段跳过提交,但应保留给未来 llamacpp。
4. GGUF/llamacpp 后续优先跑 910b 和 s4000。
5. 别人已下载成功页面是 P2 候选来源,接口已确认为 `GET /adminApi/async/task/model-download-task?current=<page>&pageSize=50&status=SUCCESS`,模型 ID 在 `data.records[].args.model_id`
6. 所有正式验证提交都应由智能体服务执行,不再依赖本地 Submit/Promote 脚本。