实现 AI 调度器真优先级队列 L0 抢占 L1/L2 + 多 provider 分流 #127
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
实现 AI 调度器真优先级队列(第三阶段)
第二阶段 #126 已闭环。第三阶段实现 #123 注释中明确留待后续的真优先级队列。
背景
queue_length恒为 0(asyncio 直接并发, 无排队)优先级定义
trigger按钮)验收标准(逐条可复现核验)
队列与状态
/ai/queue-status能真实反映排队长度 queue_length(不再恒为 0)抢占
多 provider 分流
回归
/ai/queue-statusHTTP 实测 code=0, active_count/queue_length 正确关联工单
关闭凭证要求
关闭前必须写
## 关闭凭证核验 (YYYY-MM-DD)评论, 逐条对应验收标准, 每条给出可复现核验方式(命令/路由/测试), 禁止"已测试通过"。关闭凭证核验 (2026-09-16)
第三阶段真优先级队列已实现并部署生产(
commit 723931c, release git-20260916160954, backend 容器健康)。验收标准逐条核验
backend/app/services/llm_scheduler.py_Gate(heap 按(level, seq)出队, holder 运行 / waiting 排队分离); 调用点挂级:ai.py::_runner→L2,generate_for_template后台→L0、admin→L1/ai/queue-status真实反映 queue_length(不再恒 0)python /tmp/sched_test_127b.py输出running_name=userA queue_length=1 queued=['userC'], 且 userA 释放后 userC 自动上位(FIFO)python /tmp/sched_test_127.py—— A(L2) 成为 holder 后 B(L0) 提交会抢占 A, 输出A 被抢占(进入 CancelledError 分支), 由ai_task_manager._run捕获 CancelledError 置"被更高优先级抢占可重试"。占用降级: 不复现"现场恢复"(获抢占即中断), 取"可重试"路径, 即满足"可恢复/可重试"_Gate(threading.Condition)任一时刻仅 1 holder=仅 1 个 LLM 调用在飞; 实测脚本两轮结束后running=0 queue_length=0, 无残留占用llm_client._call_multi_provider单请求内优先级遍历兜底(见下条)llm_client._call_multi_provider未改动, 仍按 priority 升序遍历、transient 降级下一 provider; 本工单调度层只对"一次 LLM 任务"排队/抢占, 不改 provider 兜底docker exec csctalon-backend ruff check app/services/llm_scheduler.py app/services/ai_report_worker.py app/services/ai_task_manager.py app/api/v1/ai.py app/api/v1/admin_ai.py→All checks passed!pytest -q tests/ -k ai --deselect tests/test_ai_assistant.py::test_llm_client_missing_base_url→ 全部通过(0 fail)。deselect 项为预存坏测试:test_llm_client_missing_base_url以无参llm_client._endpoint()断言 503, 但_endpoint(base_url)需必传参 —— 与本工单无关, main(eecc003) 上同样失败, 存量不追溯/ai/queue-statusHTTP 实测 code=0, active_count/queue_length 正确docker exec -w /app -e PYTHONPATH=/app csctalon-backend python /tmp/prod_check_127.py→{"code":0,...,"running_count":1,"running_level":0,"running_name":"ai_pregen:daily_general_morning","run_s":38,"queued":[],"timestamp":...}—— 真队列可见性齐全且可见 L0 后台预生成在飞结论
第三阶段核心(真优先队列 + L0 抢占 L1/L2 + queue_length 真实化)验收通过; 仅"每 provider 独立并发队列"一项以"单端点无收益"降级验收。后端代码已部署生产并经 HTTP 实测。
降级项补做凭证 (2026-09-16)
原降级验收项「每 provider 独立并发队列」已在 commit
0f4d7b1实现并部署生产(release git-20260916175115)。实现
_Gate改为_gates: dict[provider_code, _Gate](线程安全取/建)acquire(level, *, provider_code): 指定 provider 进该 provider 独立门闸; None 走 defaulttemplate.llm_provider_code; 用户实时 None → defaultqueue_status新增providers明细(每 provider 在飞/排队)可复现核验
python /tmp/verify_multi_provider.py: qwen+deepseek 同时跑 0.3s → 0.31s/ai/queue-status返回providers={"default":{"running":1,...}}pytest -k ai439 passedtest_llm_client_missing_base_url改_endpoint(""), 现通过#127 全部验收项(含原降级项)现已完成。