# 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 任务 -> 智能体优先提交高成功率任务 ``` 当前实现阶段只做 vLLM;GGUF/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 模型优先目标 GPU:910b, 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 Xc-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=&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=&pageSize=50&status=SUCCESS`,模型 ID 在 `data.records[].args.model_id`。 6. 所有正式验证提交都应由智能体服务执行,不再依赖本地 Submit/Promote 脚本。