Define numeric swarm acceptance gates
Add a concrete 0-100 swarmness/compliance score, local large-scale stress, and 3000 TPM budget acceptance so the repo can say when it is a swarm by measured criteria instead of prose alone. Constraint: user required Chinese docs, explicit scenarios, parameters, formulas, pass/fail lines, and git upload. Rejected: prose-only PASS reports | they did not answer whether the system is a swarm with a concrete score. Confidence: high Scope-risk: moderate Directive: keep production runtime claims separate from local minimal swarm acceptance scores. Tested: py_compile swarm_minimal examples tests; unittest discover -s tests 45 tests; run_swarm_compliance_score.py; run_tpm_budget_acceptance.py; run_academic_standard_evaluation.py; git diff --check; docs/script secret-pattern scan. Not-tested: live S07 and production Kubernetes/NewAPI provider-rate-limit stress were not rerun in this upload step. Co-authored-by: OmX <omx@oh-my-codex.dev>
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
|
||||
主要报告入口都放在 `docs/`,完整索引见 `docs/README.md`:
|
||||
|
||||
- `docs/AGENT_SWARM_INDICATOR_TEST_MATRIX.zh-CN.md`:所有 Agent / 蜂群指标的统一测试矩阵,说明每个指标的设计场景和成功阈值。
|
||||
- `docs/AGENT_SWARM_QUALITY_STANDARD.zh-CN.md`:Agent / 蜂群 Agent 质量标准、测试标准来源、S07 外部 GitHub 代码任务分配和接手机制。
|
||||
- `docs/SWARM_CHARACTERISTICS_ACCEPTANCE_STANDARD.zh-CN.md`:蜂群六特征验收指标、公式、场景和当前结论。
|
||||
- `docs/ACADEMIC_STANDARD_TEST_REPORT.zh-CN.md`:S01-S10 测试场景、测试过程、测试结果、算法清单和马尔可夫过程判定。
|
||||
@@ -85,6 +86,9 @@ python3 -B -m py_compile swarm_minimal/*.py examples/*.py tests/*.py
|
||||
python3 -B -m unittest discover -s tests
|
||||
python3 -u -B examples/run_next_boundary_acceptance.py
|
||||
python3 -u -B examples/run_swarm_characteristics_acceptance.py
|
||||
python3 -u -B examples/run_large_scale_stress_acceptance.py
|
||||
python3 -u -B examples/run_tpm_budget_acceptance.py
|
||||
python3 -u -B examples/run_swarm_compliance_score.py
|
||||
python3 -u -B examples/run_academic_standard_evaluation.py
|
||||
```
|
||||
|
||||
@@ -92,6 +96,14 @@ python3 -u -B examples/run_academic_standard_evaluation.py
|
||||
|
||||
`run_swarm_characteristics_acceptance.py` 是 S10 的独立验收入口,专门验证蜂群六特征:去中心化、自组织、涌现性、鲁棒性、可扩展性、隐式协作。
|
||||
|
||||
`run_large_scale_stress_acceptance.py` 是 L01 的独立验收入口,默认使用本机全部逻辑 CPU 做本地多进程压力测试。本轮最大性能实测为 8 逻辑核、128 Agent、131072 任务、46.9689 秒完成、失败 0、重复 claim 0。
|
||||
|
||||
`run_tpm_budget_acceptance.py` 是 L02 的独立验收入口,按 `3000 TPM` 模型吞吐预算做本地确定性调度验收。本轮实测为 8 个 Agent、60 个模型预算任务、每任务 50 token、总需求 3000 token、单分钟窗口最大 3000 token、预算利用率 100%、失败 0、重复 claim 0。
|
||||
|
||||
`run_swarm_compliance_score.py` 是蜂群性数值评分入口,输出 `swarmness_score` 和 `minimal_compliance_score`。当前本地最小蜂群评分为 `100/100`,等级为“极强本地最小蜂群合规”;该分数不等同于生产级 Kubernetes runtime 认证。
|
||||
|
||||
指标成功值以 `docs/AGENT_SWARM_INDICATOR_TEST_MATRIX.zh-CN.md` 为准。最小闭环必须同时满足:A01-A09 全部通过、S01-S10 全部通过、F01-F06 六特征全部通过;其中 S07 live 场景必须 14 项检查全部 PASS,S10 必须 6 个蜂群特征场景全部 PASS。若声明本机压力和模型预算量级也通过,还必须同时满足 L01 与 L02。
|
||||
|
||||
完整 live 标准矩阵需要本机被忽略的 `.env` 中提供 Azure PostgreSQL、Redis、Blob 和 NewAPI 测试凭据:
|
||||
|
||||
```bash
|
||||
@@ -184,8 +196,14 @@ python3 -B examples/run_azure_demo.py
|
||||
- `tests/test_newapi_agnet.py`:NewAPI Agnet 的 mock 测试。
|
||||
- `tests/test_markov_process_properties.py`:马尔可夫式状态转移判定测试。
|
||||
- `tests/test_swarm_characteristics_acceptance.py`:蜂群六特征验收测试。
|
||||
- `tests/test_acceptance_scoring.py`:蜂群性数值评分和硬上限测试。
|
||||
- `tests/test_tpm_budget_acceptance.py`:L02 3000 TPM 模型预算调度测试。
|
||||
- `examples/run_next_boundary_acceptance.py`:S09 下一阶段边界最小验收入口,覆盖并发自主 claim、候选融合和互相质询。
|
||||
- `examples/run_swarm_characteristics_acceptance.py`:S10 蜂群六特征验收入口。
|
||||
- `examples/run_large_scale_stress_acceptance.py`:L01 本机最大性能压力验收入口。
|
||||
- `examples/run_tpm_budget_acceptance.py`:L02 3000 TPM 模型预算调度验收入口。
|
||||
- `examples/run_swarm_compliance_score.py`:蜂群性数值评分入口。
|
||||
- `examples/run_academic_standard_evaluation.py`:学术化标准测试汇总入口。
|
||||
- `docs/ACADEMIC_STANDARD_TEST_REPORT.zh-CN.md`:标准来源、测试过程、结果、算法和马尔可夫过程结论。
|
||||
- `docs/AGENT_SWARM_INDICATOR_TEST_MATRIX.zh-CN.md`:指标、测试场景、成功阈值和证据入口的统一矩阵。
|
||||
- `docs/AGENT_SWARM_QUALITY_STANDARD.zh-CN.md`:Agent / 蜂群 Agent 质量标准、S07 任务分配、模型接手机制和当前结论。
|
||||
|
||||
@@ -12,13 +12,15 @@
|
||||
本文是 Heicode / Manager / Agnet 平台 10 天生产级联调计划,不是当前 `fengqun` 仓库的已完成清单。当前仓库已经完成并验收的是 `swarm-minimal` 的最小可验收闭环:
|
||||
|
||||
- AQS / SW-AQS v1 标准矩阵已扩展为 S01-S10,并把去中心化、自组织、涌现性、鲁棒性、可扩展性、隐式协作作为 S10 一级验收指标。
|
||||
- 本地单元测试 41 项已通过,学术化本地门禁 A01-A07 已通过。
|
||||
- 本地单元测试 45 项已通过,学术化本地门禁 A01-A09 已通过。
|
||||
- S07 已使用外部 GitHub 复杂代码项目 `fastapi/fastapi` 的 live 场景,通过 Azure PostgreSQL、Redis、Blob 和 NewAPI 形成真实证据。
|
||||
- S09 已补齐 3/5/7 Agent 并发自主 claim、候选融合输出、反驳-修正-再投票共识的最小代码验收。
|
||||
- S10 已补齐蜂群六特征的本地最小代码验收。
|
||||
|
||||
仍属于本文后续平台落地范围的内容包括:Manager / Agnet 平台统一接口、人类审批主线、真实 Kubernetes worker runtime、生产级扩缩容压测、Redis Stream 消费驱动的动态任务图、生产权限和监控体系。后续实施时不能把本仓库的本地最小闭环验收直接等同于完整生产平台交付。
|
||||
|
||||
当前仓库指标测试的统一阈值见 `AGENT_SWARM_INDICATOR_TEST_MATRIX.zh-CN.md`。本计划后续所有验收记录都应沿用“指标、场景、成功值、证据入口”四列格式,不能只写“已验证”。
|
||||
|
||||
## 1. 交付目标
|
||||
|
||||
10 天结束时,团队必须交付一个可以最小验证的 Agnet 受控蜂群闭环。
|
||||
@@ -233,6 +235,16 @@
|
||||
- 高危审批证据。
|
||||
- 事件、日志、用量、审计证据。
|
||||
- 无明文长期密钥证据。
|
||||
|
||||
最终验收的最小成功值:
|
||||
|
||||
| 指标组 | 成功值 |
|
||||
|---|---|
|
||||
| 当前 `swarm-minimal` 复验 | A01-A09、S01-S10、F01-F06 全部 PASS |
|
||||
| Manager / Agnet 平台接口 | 创建、查询、停止、回调、artifact、审批接口均有至少一次真实环境调用证据 |
|
||||
| Runtime 扩缩容 | 真实 worker runtime 下重复 `3/5/7` 扩缩容场景,仍满足无重复 claim、失败为 0 或可恢复 |
|
||||
| 审批与安全 | 高危动作 100% 进入审批;长期明文密钥泄露次数为 `0` |
|
||||
| 可观测性 | run、task、event、artifact、usage、audit、日志和指标均可按 `correlation_id` 查询 |
|
||||
- 失败恢复证据。
|
||||
|
||||
## 5. 每日同步机制
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
本文后续仍要完成的是把这些能力接入 Manager / Agnet API、真实 worker runtime、审批、审计、生产资源和人类可见状态面板。阅读本文时应把它理解为生产级联调分工,而不是当前仓库最小闭环是否完成的判定依据。
|
||||
|
||||
当前最小原型指标的设计场景和成功阈值见 `AGENT_SWARM_INDICATOR_TEST_MATRIX.zh-CN.md`。接口联调阶段也必须按同一口径记录:每项指标写清测试场景、成功值和证据入口。
|
||||
|
||||
## 1. 成员 A: Heicode / Manager 对接负责人
|
||||
|
||||
### 1.1 目标
|
||||
@@ -444,3 +446,13 @@ C 不把“Pod Running”当完成,必须证明业务链路可以运行。
|
||||
- 每个 artifact 都能追溯到 Swarm Run 和 Task。
|
||||
- 每条日志都能通过 `correlation_id` 关联。
|
||||
- 任何接口响应和日志都不能出现长期明文密钥。
|
||||
|
||||
接口联调成功值:
|
||||
|
||||
| 指标 | 成功值 |
|
||||
|---|---|
|
||||
| 接口调用证据 | 每个创建、查询、停止、回调、artifact、审批接口至少 1 次真实环境调用成功 |
|
||||
| 幂等 | 重复创建和重复回调不产生重复 Swarm、重复事件或重复 artifact |
|
||||
| 状态一致性 | Manager、Agnet Runtime、数据库状态可用同一 `correlation_id` 对齐 |
|
||||
| 安全 | 长期明文密钥泄露次数为 `0`;未授权资源访问必须失败并写审计 |
|
||||
| 蜂群能力复用 | 接入后仍能复验 A01-A09、S01-S10、F01-F06,不能因平台化丢失现有指标 |
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
|
||||
本文描述的是平台级最小验证与验收流程,覆盖 Heicode、Manager、Agnet 平台、Azure、密钥保管器和 CodeGW 的完整受控闭环。当前 `fengqun` 仓库已经完成的是其中的 `swarm-minimal` 行为验收层:
|
||||
|
||||
- 本地静态与单元门禁已通过:`py_compile` 和 41 项 unittest。
|
||||
- 学术化本地门禁已通过:A01-A07。
|
||||
- 本地静态与单元门禁已通过:`py_compile` 和 45 项 unittest。
|
||||
- 学术化本地门禁已通过:A01-A09。
|
||||
- 完整标准矩阵已扩展为:S01-S10。
|
||||
- S07 live 外部代码场景已通过:固定 `fastapi/fastapi` commit、7 个任务、14 项检查、2 轮质量共识、无失败检查。
|
||||
- S09 下一阶段边界已通过:3/5/7 并发 claim、候选融合、互相质询共识。
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
因此,当前仓库可以判定为“最小化闭环已完成并可验收”。但本文中涉及的 Manager 启动入口、审批页面、Agnet 平台 API、AKS worker runtime、密钥保管器和 CodeGW 归因仍属于生产级平台验证,不应被当前仓库的本地验收结果自动覆盖。
|
||||
|
||||
当前仓库所有指标的设计场景和成功阈值以 `AGENT_SWARM_INDICATOR_TEST_MATRIX.zh-CN.md` 为准。本文的“可观测”只表示生产平台需要采集这些指标,不自动等于当前最小原型已完成生产级指标。
|
||||
|
||||
## 1. 最小验证结论先行
|
||||
|
||||
最小验证不是证明“有 3 个 Agent”,也不是证明“有一个 workflow 跑完”。
|
||||
@@ -354,14 +356,14 @@ Manager 展示:
|
||||
|
||||
| 指标 | 验收标准 |
|
||||
|---|---|
|
||||
| Swarm 创建耗时 | 可观测 |
|
||||
| 任务等待时间 | 可观测 |
|
||||
| 任务执行时间 | 可观测 |
|
||||
| handoff 次数 | 可观测 |
|
||||
| 失败次数 | 可观测 |
|
||||
| 重试次数 | 可观测 |
|
||||
| 审批等待时间 | 可观测 |
|
||||
| 模型用量 | 可归因到用户或任务 |
|
||||
| Swarm 创建耗时 | 可观测;生产平台需记录 start/end timestamp;当前最小原型不把耗时作为 PASS 阈值 |
|
||||
| 任务等待时间 | 可观测;生产平台需记录 task created 到 claimed;当前最小原型以 claim 是否正确为主 |
|
||||
| 任务执行时间 | 可观测;生产平台需记录 claimed 到 done/failed;当前最小原型不设 SLA |
|
||||
| handoff 次数 | 可观测;当前 S07 成功值为 7 个 STEP、7 条 chain edge |
|
||||
| 失败次数 | 可观测;当前故障注入成功值为 `failed_tasks >= 1` 且 run 仍 `converged` |
|
||||
| 重试次数 | 可观测;当前 fallback 场景成功值为 bad model 失败后至少一次 retry/fallback 并由 good model 接手 |
|
||||
| 审批等待时间 | 可观测;属于生产级 Manager / Heicode 验收,不属于当前本地原型 PASS 阈值 |
|
||||
| 模型用量 | 可归因到用户或任务;当前 S07 成功值为 3 个 discovered distinct 模型参与 7 步链路 |
|
||||
|
||||
## 8. Day 10 最终验收清单
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 学术化标准测试报告
|
||||
|
||||
**对象**: `swarm-minimal` 最小蜂群原型
|
||||
**日期**: 2026-05-16
|
||||
**范围**: 本地确定性测试、蜂群六特征验收、传统 Agnet 对比、多轮共识、并发扩缩容、候选融合、互相质询、模型 I/O 报告审计、马尔可夫过程适配性判断
|
||||
**日期**: 2026-05-17
|
||||
**范围**: 本地确定性测试、蜂群六特征验收、传统 Agnet 对比、多轮共识、并发扩缩容、候选融合、互相质询、本机最大性能、3000 TPM 模型预算、模型 I/O 报告审计、马尔可夫过程适配性判断
|
||||
|
||||
## 1. 已实现的场景测试
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
| S08 | 模型 I/O 报告审计 | 验证报告包含场景、输入、输出、接手证据,且无明显真实密钥样式 | `tests/test_model_io_report_audit.py` |
|
||||
| S09 | 下一阶段边界最小验收 | 验证 SW-AQS-16 的 3/5/7 并发自主 claim、候选融合输出、反驳-修正-再投票共识 | `examples/run_next_boundary_acceptance.py` |
|
||||
| S10 | 蜂群六特征验收 | 验证去中心化、自组织、涌现性、鲁棒性、可扩展性、隐式协作六个一级指标 | `examples/run_swarm_characteristics_acceptance.py` |
|
||||
| L01 | 本机最大性能压力验收 | 使用本机全部逻辑 CPU 做本地多进程大规模任务 claim、执行和收敛压力测试 | `examples/run_large_scale_stress_acceptance.py` |
|
||||
| L02 | 3000 TPM 模型预算验收 | 在本地虚拟 token ledger 中验证 3000 TPM 量级下的并发 claim、预算预留、窗口不超额和收敛 | `examples/run_tpm_budget_acceptance.py` |
|
||||
| F01-F06 | 蜂群一级特征 | 把蜂群判定固定为六个核心特征,而不是泛泛的“多 Agent 能跑” | `tests/test_swarm_characteristics_acceptance.py` |
|
||||
| B01 | 单 Agnet 故障隔离 | 一个 Agnet 崩溃不导致整体失败 | `tests/test_swarm_behavior_academic.py` |
|
||||
| B02 | 群体涌现 | 多个弱局部信号通过共享状态聚合成更强整体结果 | `tests/test_swarm_behavior_academic.py` |
|
||||
@@ -26,6 +28,47 @@
|
||||
| C01-C04 | 传统 Agnet 对比 | 和单路线/FIFO/无共享状态/无上下文 handoff 的基线比较 | `examples/run_swarm_vs_traditional_benchmark.py` |
|
||||
| M01-M03 | 马尔可夫过程适配性 | 判断当前实现是马尔可夫式状态机,但不是严格 MDP | `tests/test_markov_process_properties.py` |
|
||||
|
||||
### 1.1 场景成功值总览
|
||||
|
||||
完整阈值见 `AGENT_SWARM_INDICATOR_TEST_MATRIX.zh-CN.md`。本报告中的 PASS 必须按下表判定:
|
||||
|
||||
| ID | 设计场景 | 成功值 |
|
||||
| --- | --- | --- |
|
||||
| S01 | 编译所有 Python 模块 | 退出码 `0`,无语法错误 |
|
||||
| S02 | 运行全部单元与确定性测试 | 当前 45 项测试全部通过,失败数 `0` |
|
||||
| S03 | 连续推理链路 marker 检查 | 7/7 STEP 输出包含当前 marker 和 previous marker;断链样例必须失败 |
|
||||
| S04 | MVP 依赖边界 | “必须依赖 NATS/Cosmos”必须被判为 false |
|
||||
| S05 | 最终收敛评分与质量门 | 拒答/角色边界输出分数为 `0.12`;最终 STEP-07 质量通过后 score 为 `1.0` |
|
||||
| S06 | 失败注入 | 失败任务 status 为 `failed`,错误可查,失败信息素 `<0`,其他任务仍完成 |
|
||||
| S07 | live 外部 FastAPI 代码链 | 7 个任务完成;14 项检查全 PASS;`accepted_score >= 0.75`;共识轮数 `>=2` |
|
||||
| S08 | 模型 I/O 报告审计 | 场景、输入、输出、交接证据存在;明显密钥样式命中数 `0` |
|
||||
| S09 | 并发 claim、候选融合、互相质询 | 3 项检查全 PASS;`3/5/7` Agent 均无重复 claim;融合过滤低分噪声;质询共识至少 2 轮 |
|
||||
| S10 | 蜂群六特征 | F01-F06 全部 PASS;任一特征失败则 S10 失败 |
|
||||
| L01 | 本机最大性能压力 | 默认使用全部逻辑 CPU;本轮最大性能实测 128 Agent、131072 任务、失败 `0`、重复 claim `0`、8 个分片全部收敛 |
|
||||
| L02 | 3000 TPM 模型预算 | 8 个 Agent、60 个预算任务、每任务 50 token、总需求 3000 token;单分钟窗口 token `<=3000`;利用率 `1.0`;失败和重复 claim 都为 `0` |
|
||||
|
||||
### 1.2 验收合理性与反推闭环结论
|
||||
|
||||
本轮验收设计不是从已有测试反推“看起来通过”,而是先定义最终主张,再反推必要条件:
|
||||
|
||||
```text
|
||||
最终主张: 当前仓库满足最小蜂群 Agent 验收
|
||||
必要条件: AQS 单 Agent 可靠 + SW-AQS 多 Agent 协作 + F01-F06 蜂群特征 + S07 外部代码 live 链路 + S08 安全审计
|
||||
测试标准: 每个必要条件都必须有场景、阈值和失败判定
|
||||
```
|
||||
|
||||
合理性判定:
|
||||
|
||||
| 检查项 | 是否满足 | 理由 |
|
||||
| --- | --- | --- |
|
||||
| 指标是否对应目标 | 是 | AQS 覆盖单 Agent 输出,SW-AQS 覆盖蜂群协作,F01-F06 覆盖六个蜂群特征 |
|
||||
| 场景是否能反驳结论 | 是 | 任何一个六特征、S07 14 项检查、S08 审计或 S09 三项边界失败,都会让对应结论失败 |
|
||||
| 阈值是否明确 | 是 | 使用 `Q >= 0.72`、`duplicate_claims=0`、`round_count>=2`、`accepted_score>=0.75` 等明确值 |
|
||||
| 是否避免自证 | 基本满足 | S07 使用外部 `fastapi/fastapi` 固定 commit,不拿本仓库源码当被测代码 |
|
||||
| 是否覆盖生产级平台 | 否 | Kubernetes worker、Manager / Agnet API、人类审批、长期压测和生产监控仍未纳入当前闭环 |
|
||||
|
||||
结论:在 `swarm-minimal` 最小原型范围内,验收设计和反推测试标准是逻辑闭环;在生产级无中心分布式 runtime 范围内,还不是闭环。
|
||||
|
||||
## 2. 测试标准来源
|
||||
|
||||
本项目没有使用“某一个 Agnet 认证标准”,因为行业目前还没有统一答案。当前采用 `AGENT_SWARM_QUALITY_STANDARD.zh-CN.md` 中定义的 AQS / SW-AQS v1:以行业 Agent 风险框架为参考,配置本项目自己的 Agent 和蜂群 Agent 质量标准。
|
||||
@@ -39,8 +82,11 @@
|
||||
| MITRE ATLAS | AI 攻击/误用视角下的失败、越权、诱导和异常场景 |
|
||||
| OpenTelemetry | Agent 过程的 traces、metrics、logs、events 和 artifact 证据 |
|
||||
| LangGraph handoff 参考 | `transfer_to_<agent>`、active-agent 路由和上下文传递语义 |
|
||||
| 蜂群六特征归纳标准 | 去中心化、自组织、涌现性、鲁棒性、可扩展性、隐式协作 |
|
||||
| Markov property 定义 | 给定当前状态后,未来状态不再依赖历史路径 |
|
||||
| RFC 2697 token bucket / rate policing | L02 3000 TPM 虚拟 ledger 的限流思想来源 |
|
||||
| OpenAI rate limit 文档 | 使用 TPM/RPM 作为模型供应商吞吐预算维度的参考 |
|
||||
| Stigmergy / Ant System | 信息素、环境痕迹、隐式协作和分布式强化的理论来源 |
|
||||
| Swarm Intelligence 体系 | 去中心化、自组织、涌现性、鲁棒性、可扩展性、隐式协作的概念来源 |
|
||||
| Puterman MDP | Markov process / MDP 的严格边界,用来说明当前只是工程马尔可夫式状态机 |
|
||||
|
||||
`py_compile` 和 `unittest` 只作为证据采集工具,不作为最终质量标准本身。完整链接在 `swarm_minimal/academic_evaluation.py` 的 `ACADEMIC_STANDARD_SOURCES` 中维护。
|
||||
|
||||
@@ -72,7 +118,7 @@ S07 需要本地被 git 忽略的 `.env`,其中包含 Azure PostgreSQL、Redis
|
||||
| 命令 | 本轮结果 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `python3 -B -m py_compile swarm_minimal/*.py examples/*.py tests/*.py` | PASS | 无输出,表示所有模块编译通过 |
|
||||
| `python3 -B -m unittest discover -s tests` | PASS | 41 个测试通过 |
|
||||
| `python3 -B -m unittest discover -s tests` | PASS | 45 个测试通过 |
|
||||
| `python3 -B -m unittest tests.test_markov_process_properties` | PASS | 3 个马尔可夫适配性测试通过 |
|
||||
| `python3 -B -m unittest tests.test_model_io_report_audit` | PASS | 2 个模型 I/O 报告审计测试通过 |
|
||||
| `python3 -u -B examples/run_swarm_behavior_acceptance.py` | PASS | B01-B04 全部通过 |
|
||||
@@ -80,7 +126,10 @@ S07 需要本地被 git 忽略的 `.env`,其中包含 Azure PostgreSQL、Redis
|
||||
| `python3 -u -B examples/run_consensus_convergence_acceptance.py` | PASS | 2 轮收敛,接受 `lease_based_pg_queue` |
|
||||
| `python3 -u -B examples/run_next_boundary_acceptance.py` | PASS | S09 三项检查通过:3/5/7 并发 claim、候选融合、反驳-修正-再投票 |
|
||||
| `python3 -u -B examples/run_swarm_characteristics_acceptance.py` | PASS | S10 六特征全部通过:去中心化、自组织、涌现性、鲁棒性、可扩展性、隐式协作 |
|
||||
| `python3 -u -B examples/run_academic_standard_evaluation.py` | PASS | A01-A07 本地学术化门禁全部通过,检测到 `examples/.env` 可用于 live 测试 |
|
||||
| `SWARM_STRESS_AGENTS_PER_PROCESS=16 SWARM_STRESS_TASKS_PER_PROCESS=16384 SWARM_STRESS_CPU_CYCLES=128 python3 -u -B examples/run_large_scale_stress_acceptance.py` | PASS | L01 本机最大性能压力通过:8 逻辑核、8 进程、128 Agent、131072 任务、46.9689 秒、吞吐 2790.61 tasks/s、失败 0、重复 claim 0 |
|
||||
| `python3 -u -B examples/run_tpm_budget_acceptance.py` | PASS | L02 3000 TPM 模型预算通过:8 Agent、60 个任务、3000 token 单窗口打满、预算利用率 1.0、失败 0、重复 claim 0 |
|
||||
| `python3 -u -B examples/run_swarm_compliance_score.py` | PASS | 蜂群性数值评分通过:`swarmness_score=100/100`,`minimal_compliance_score=100/100`,等级为“极强本地最小蜂群合规” |
|
||||
| `python3 -u -B examples/run_academic_standard_evaluation.py` | PASS | A01-A09 本地学术化门禁全部通过,检测到 `examples/.env` 可用于 live 测试 |
|
||||
| `python3 -u -B examples/run_standard_scenario_acceptance.py` | PASS | S01-S10 全部通过;S07 外部 FastAPI 代码场景完成 7 个 live 任务,14 个检查无失败,S08/S09/S10 通过 |
|
||||
|
||||
最新 S07 外部 GitHub live 证据:
|
||||
@@ -108,16 +157,16 @@ S07 需要本地被 git 忽略的 `.env`,其中包含 Azure PostgreSQL、Redis
|
||||
|
||||
| 门禁 | 当前结论 |
|
||||
| --- | --- |
|
||||
| 本地学术化门禁 A01-A07 | 可通过 |
|
||||
| 本地学术化门禁 A01-A09 | 可通过 |
|
||||
| 标准矩阵 S01-S10 | 已通过 |
|
||||
| 标准矩阵 S07 live 外部 GitHub 代码推理 | 已通过 |
|
||||
| 标准矩阵 S08 模型 I/O 报告审计 | 已通过 |
|
||||
| 标准矩阵 S09 下一阶段边界最小验收 | 已通过 |
|
||||
| 标准矩阵 S10 蜂群六特征验收 | 已通过 |
|
||||
| 最小化标准化验收 | 已满足 |
|
||||
| 生产级完整交付 | 未声称完成,仍需真实 Kubernetes runtime、平台 API、审批和生产压测 |
|
||||
| 生产级完整交付 | 未声称完成,仍需真实 Kubernetes runtime、平台 API、审批、真实模型限流和生产压测 |
|
||||
|
||||
结论:当前项目已经具备可执行的标准化测试,且本地确定性蜂群行为测试、真实 Azure/NewAPI live 集成测试、S09 下一阶段边界最小验收、S10 蜂群六特征验收均已通过。该结论限定在本仓库定义的最小蜂群标准矩阵内,不等同于真实 Kubernetes runtime 的大规模生产压测或第三方认证。
|
||||
结论:当前项目已经具备可执行的标准化测试,且本地确定性蜂群行为测试、真实 Azure/NewAPI live 集成测试、S09 下一阶段边界最小验收、S10 蜂群六特征验收、L01 本机最大性能压力和 L02 3000 TPM 模型预算验收均已通过。该结论限定在本仓库定义的最小蜂群标准矩阵内,不等同于真实 Kubernetes runtime 的大规模生产压测、真实模型供应商限流认证或第三方认证。
|
||||
|
||||
## 6. 算法清单
|
||||
|
||||
@@ -137,12 +186,14 @@ S07 需要本地被 git 忽略的 `.env`,其中包含 Azure PostgreSQL、Redis
|
||||
| 蜂群六特征验收 | `examples/run_swarm_characteristics_acceptance.py` | 把去中心化、自组织、涌现性、鲁棒性、可扩展性和隐式协作作为一级验收门 |
|
||||
| 动态模型发现 | `discover_newapi_models` | 从 NewAPI 兼容端点发现模型 |
|
||||
| 去重模型选择 | `select_distinct_models` | 多 Agnet 测试时选择不同模型 |
|
||||
| 虚拟 TPM 预算账本 | `TokenMinuteLedger` | 多 Agent 并发任务先预留模型 token,保证任意模拟分钟不超过目标 TPM |
|
||||
| 加权蜂群合规评分 | `score_items` | F01-F06 占 60 分,S07/S08/S09 占 25 分,L01/L02 占 15 分,并使用硬上限防止核心蜂群特征失败时被外围证据补分 |
|
||||
|
||||
## 7. 马尔可夫过程结论
|
||||
|
||||
当前实现满足“工程意义上的马尔可夫式状态机”:
|
||||
|
||||
- 如果把 `tasks`、`pheromones`、`shared_state`、`observations`、agent policy 和共识轮次一起视为完整当前状态,则下一步 claim、score 更新和收敛选择只依赖当前状态。
|
||||
- 如果把 `tasks`、`pheromones`、`shared_state`、`observations`、agent policy、共识轮次和 TPM 预算账本一起视为完整当前状态,则下一步 claim、score 更新、预算预留和收敛选择只依赖当前状态。
|
||||
- 新增测试 `tests/test_markov_process_properties.py` 验证了等价当前任务/信息素状态下,不同历史路径会得到相同 claim 与 score 更新。
|
||||
|
||||
但它不满足严格数学意义的 Markov process / Markov Decision Process:
|
||||
|
||||
@@ -0,0 +1,523 @@
|
||||
# Agent / 蜂群指标测试验收矩阵
|
||||
|
||||
**对象**: `swarm-minimal` 最小蜂群原型
|
||||
**日期**: 2026-05-17
|
||||
**定位**: 本文件是当前仓库所有 Agent / 蜂群指标测试的统一口径。其他文档只做解释或报告,指标阈值以本文件为准。
|
||||
|
||||
## 1. 指标设立方法
|
||||
|
||||
本项目不把“代码能跑”当成 Agent 质量标准。指标按下面流程设立:
|
||||
|
||||
1. 先确定 Agent 或蜂群特征,例如任务理解、交接、去中心化、自组织、涌现性。
|
||||
2. 把抽象特征转换成可观察状态,例如 task status、claim event、shared_state、pheromone、artifact、consensus round。
|
||||
3. 为每个指标设计一个可复现实验场景,明确输入、Agent 数量、任务数量、模型链路或候选集合。
|
||||
4. 给每个指标设置成功阈值。阈值必须是布尔、数量、分数、集合或顺序条件,不能只写“效果不错”。
|
||||
5. 指标通过必须有命令、测试文件或 live run 证据。
|
||||
|
||||
总体通过公式:
|
||||
|
||||
```text
|
||||
MINIMAL_AGENT_SWARM_PASS =
|
||||
AQS_PASS
|
||||
∧ SW_AQS_PASS
|
||||
∧ S01_to_S10_PASS
|
||||
∧ F01_to_F06_PASS
|
||||
```
|
||||
|
||||
其中任何一个一级门失败,当前仓库都不能声称满足“最小蜂群 Agent 验收”。
|
||||
|
||||
如果要声称“本机大规模压力也通过”,还必须额外满足:
|
||||
|
||||
```text
|
||||
LOCAL_LARGE_SCALE_PASS =
|
||||
MINIMAL_AGENT_SWARM_PASS
|
||||
∧ L01_local_max_performance_stress_pass
|
||||
```
|
||||
|
||||
如果要声称“3000 TPM 模型预算量级也通过”,还必须额外满足:
|
||||
|
||||
```text
|
||||
LOCAL_TPM_BUDGET_PASS =
|
||||
MINIMAL_AGENT_SWARM_PASS
|
||||
∧ L02_3000_tpm_budget_acceptance_pass
|
||||
```
|
||||
|
||||
## 2. 验收合理性设计
|
||||
|
||||
验收指标是否合理,按五个约束判断:
|
||||
|
||||
| 约束 | 设计要求 | 本项目落点 |
|
||||
| --- | --- | --- |
|
||||
| 特征对齐 | 指标必须直接对应 Agent 或蜂群特征,不能只对应普通软件工程质量 | AQS 对应单 Agent 能力;SW-AQS 对应多 Agent 协作;F01-F06 对应六个蜂群特征 |
|
||||
| 可观察 | 指标必须能落到 task、claim event、shared_state、pheromone、artifact、report、consensus round 等证据 | 每项指标都有命令、测试文件或 live run 证据入口 |
|
||||
| 可反驳 | 指标必须有失败条件,不能只写正向叙述 | 例如任一 F01-F06 失败则 S10 失败;S07 14 项检查任一失败则 live 标准失败 |
|
||||
| 有阈值 | 指标必须能写成数字、布尔、集合或顺序条件 | 例如 `Q >= 0.72`、`duplicate_claims = 0`、`round_count >= 2`、`event_delta >= 22` |
|
||||
| 不自证 | 关键场景不能只用本仓库证明自己正确 | S07 使用外部 GitHub 项目 `fastapi/fastapi` 固定 commit;S08 再审计报告和密钥样式 |
|
||||
|
||||
因此,这套验收的合理性不是来自“我认为合理”,而是来自:
|
||||
|
||||
```text
|
||||
抽象特征
|
||||
-> 可观察证据
|
||||
-> 可执行场景
|
||||
-> 明确阈值
|
||||
-> 失败可反驳
|
||||
-> 报告可审计
|
||||
```
|
||||
|
||||
## 2.1 来源边界:引用算法、引用文章与项目自定义
|
||||
|
||||
这套指标不是“前无古人后无来者”的自创理论。它由三层组成:
|
||||
|
||||
| 层级 | 来源 | 本项目如何使用 | 是否项目自定义 |
|
||||
| --- | --- | --- | --- |
|
||||
| 模型限流 / TPM | RFC 2697 token bucket / rate policing;OpenAI rate limit 文档中的 RPM / TPM 维度 | L02 使用虚拟 token ledger,验证多 Agent 并发时不会冲破 `3000 TPM` | `3000` 来自本轮用户给定量级;`50 token × 60 task` 是为了刚好打满 3000 token 窗口的工程验收参数 |
|
||||
| 信息素 / 隐式协作 | Stigmergy;Dorigo 等 1996 Ant System | 用 `pheromone` 和 shared state 表示环境痕迹,Agent 不直接互发消息也能被环境影响 | 具体字段名、分数阈值、测试任务数是项目自定义 |
|
||||
| 蜂群六特征 | Bonabeau / Dorigo / Theraulaz 的 Swarm Intelligence 体系 | 把去中心化、自组织、涌现性、鲁棒性、可扩展性、隐式协作设为一级门 | 六特征组合为本项目验收口径,但每个特征不是自创概念 |
|
||||
| 马尔可夫边界 | Puterman MDP;Sutton / Barto 强化学习中对 state/action/reward/transition 的定义 | 只声明“工程意义上的马尔可夫式状态机”,不声明严格 MDP | 当前非概率核、非策略优化,因此不强行套严格 MDP |
|
||||
| Agent 风险与可观测性 | NIST AI RMF / AI 600-1、OWASP LLM / Agentic Skills、MITRE ATLAS、OpenTelemetry | 把拒答、偏题、泄密、工具边界、run/task/event/artifact 证据变成门禁 | 具体通过阈值按本仓库最小闭环目标配置 |
|
||||
| Handoff | LangGraph handoff 参考 | 用 active agent、previous summary、chain edge 表示接手 | 交接字段和报告格式是项目自定义 |
|
||||
|
||||
核心结论:
|
||||
|
||||
```text
|
||||
理论来源不是自创;
|
||||
验收矩阵是项目配置;
|
||||
阈值是为了让“最小蜂群 Agent 是否通过”可执行、可反驳、可复验。
|
||||
```
|
||||
|
||||
关键引用:
|
||||
|
||||
- RFC 2697, A Single Rate Three Color Marker: `https://www.rfc-editor.org/rfc/rfc2697.html`
|
||||
- OpenAI API rate limits: `https://platform.openai.com/docs/guides/rate-limits`
|
||||
- Stigmergy: from mathematical modelling to control: `https://pmc.ncbi.nlm.nih.gov/articles/PMC11371424/`
|
||||
- Dorigo, Maniezzo, Colorni, Ant System: Optimization by a Colony of Cooperating Agents, 1996: `https://iridia.ulb.ac.be/~mdorigo/Published_papers/All_Dorigo_papers/DorManCol1996tsmcb.pdf`
|
||||
- Bonabeau, Dorigo, Theraulaz, Swarm Intelligence: From Natural to Artificial Systems, 1999: `https://academic.oup.com/book/40811`
|
||||
- Puterman, Markov Decision Processes, 1994: `https://books.google.com/books/about/Markov_Decision_Processes.html?id=tsiiQgAACAAJ`
|
||||
- NIST AI RMF: `https://www.nist.gov/itl/ai-risk-management-framework`
|
||||
- NIST AI 600-1: `https://doi.org/10.6028/NIST.AI.600-1`
|
||||
- OWASP LLM Top 10: `https://owasp.org/www-project-top-10-for-large-language-model-applications/`
|
||||
- MITRE ATLAS: `https://atlas.mitre.org/`
|
||||
- OpenTelemetry: `https://opentelemetry.io/docs/`
|
||||
- LangGraph handoff: `https://reference.langchain.com/python/langgraph-swarm/handoff/create_handoff_tool`
|
||||
|
||||
## 3. 反推测试标准的逻辑闭环
|
||||
|
||||
反推方式是从最终结论倒推必要条件,再把必要条件变成测试:
|
||||
|
||||
```text
|
||||
目标结论: 当前仓库满足最小蜂群 Agent 验收
|
||||
|
||||
必要条件:
|
||||
1. 单 Agent 输出可靠
|
||||
2. 多 Agent 协作成立
|
||||
3. 蜂群六特征成立
|
||||
4. 外部复杂代码任务链路成立
|
||||
5. 失败、拒答、偏题和泄密风险不能直接通过
|
||||
|
||||
反推测试:
|
||||
必要条件 -> 可观察指标 -> 场景输入 -> 成功阈值 -> 证据入口
|
||||
```
|
||||
|
||||
闭环表:
|
||||
|
||||
| 结论主张 | 反推必要条件 | 测试场景 | 成功阈值 | 失败后结论 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| “Agent 能承接任务” | 当前输出必须包含当前任务和上一步信息 | S07 STEP-01 到 STEP-07 | 7/7 输出有 own marker 和 previous marker | 不能声称上下文承接通过 |
|
||||
| “输出质量可控” | 拒答、角色拒绝、偏题不能混入最终结果 | 质量门和 fallback 场景 | `Q >= 0.72`;风险输出分 `0.12`;触发 retry/fallback | 不能声称 Agent 质量门通过 |
|
||||
| “不是本仓库自证” | 需要外部复杂代码目标 | S07 `fastapi/fastapi` 固定 commit | 14 项 live checks 全 PASS;外部文件引用 `>=5` | 不能声称 live 外部代码验收通过 |
|
||||
| “蜂群不是多 Agent 堆叠” | 六个蜂群特征都要可观察 | S10 F01-F06 | 6 项全部 PASS | 不能声称蜂群特征通过 |
|
||||
| “能容错” | 单 Agent 失败不能导致整体失败 | F04 / B01 / S06 | `failed_tasks >= 1` 且 run 仍 `converged` | 不能声称鲁棒性通过 |
|
||||
| “能扩缩容” | Agent 数变化不能改变架构或产生重复 claim | S09 / F05 的 `3/5/7` 场景 | 每个 `n` 完成 `2n` 任务,失败 `0`,重复 claim `0` | 不能声称可扩展性通过 |
|
||||
| “能收敛而非碰巧最高分” | 需要质量门、候选融合和多轮共识 | S07 / S09 | S07 共识 `round_count >= 2`;S09 融合过滤低分噪声;质询先不收敛再收敛 | 不能声称收敛机制充分 |
|
||||
| “可审计且安全” | 报告能说明输入输出交接且不泄密 | S08 模型 I/O 报告审计 | 场景、输入、输出、交接证据存在;密钥样式命中数 `0` | 不能声称人类审计友好或安全 |
|
||||
|
||||
闭环判定:
|
||||
|
||||
```text
|
||||
在 swarm-minimal 本地最小原型范围内:
|
||||
目标 -> 指标 -> 场景 -> 阈值 -> 证据 -> 结论
|
||||
是逻辑闭环。
|
||||
|
||||
在生产级无中心分布式 runtime 范围内:
|
||||
还不是闭环。
|
||||
```
|
||||
|
||||
原因是当前测试已经能反驳“最小蜂群 Agent 验收”这个结论,但还不能反驳“生产级蜂群平台验收”这个更大结论。生产级闭环还需要真实 Kubernetes worker、Manager / Agnet API、人类审批、长期运行、真实扩缩容压测和生产监控。
|
||||
|
||||
## 3.1 蜂群性数值评分模型
|
||||
|
||||
为了避免“是不是蜂群”只停留在口头判断,本仓库新增 `SWARM_COMPLIANCE_SCORE`。它分成两个数值:
|
||||
|
||||
| 分数 | 含义 | 当前值 |
|
||||
| --- | --- | --- |
|
||||
| `swarmness_score` | 只判断六个核心蜂群特征是否成立 | `100 / 100` |
|
||||
| `minimal_compliance_score` | 判断是否达到本仓库最小蜂群 Agent 验收 | `100 / 100` |
|
||||
|
||||
权重设计:
|
||||
|
||||
| 组 | 权重 | 指标 | 为什么这样设 |
|
||||
| --- | --- | --- | --- |
|
||||
| 核心蜂群性 | 60 | F01-F06,每项 10 分 | “是不是蜂群”必须先看六特征,不能让工程外围项冲高分 |
|
||||
| Agent / 审计 / 收敛支撑 | 25 | S07 10 分、S08 5 分、S09 10 分 | 证明不是多个 Agent 各跑各的,而是有外部复杂任务、输入输出审计、融合和质询共识 |
|
||||
| 规模和预算 | 15 | L01 7 分、L02 8 分 | 证明在本机大规模任务和 3000 TPM 模型预算下仍稳定 |
|
||||
|
||||
评分公式:
|
||||
|
||||
```text
|
||||
swarmness_score =
|
||||
100 × (Σ passed(F01..F06) × 10) / 60
|
||||
```
|
||||
|
||||
```text
|
||||
minimal_compliance_score =
|
||||
Σ weight_i × pass_i
|
||||
```
|
||||
|
||||
其中:
|
||||
|
||||
```text
|
||||
pass_i ∈ {0, 1}
|
||||
Σ weight_i = 100
|
||||
```
|
||||
|
||||
当前代入:
|
||||
|
||||
```text
|
||||
swarmness_score =
|
||||
100 × (10+10+10+10+10+10) / 60
|
||||
= 100
|
||||
```
|
||||
|
||||
```text
|
||||
minimal_compliance_score =
|
||||
F01..F06(60)
|
||||
+ S07(10)
|
||||
+ S08(5)
|
||||
+ S09(10)
|
||||
+ L01(7)
|
||||
+ L02(8)
|
||||
= 100
|
||||
```
|
||||
|
||||
分级线:
|
||||
|
||||
| 分数区间 | 判定 |
|
||||
| --- | --- |
|
||||
| `< 60` | 不满足蜂群 |
|
||||
| `60-74` | 部分蜂群,不可验收 |
|
||||
| `75-84` | 最小可验收蜂群 |
|
||||
| `85-94` | 合规蜂群原型 |
|
||||
| `>= 95` 且无硬上限 | 极强本地最小蜂群合规 |
|
||||
|
||||
硬上限规则:
|
||||
|
||||
| 失败条件 | 上限 | 解释 |
|
||||
| --- | --- | --- |
|
||||
| F01-F06 任一核心蜂群特征失败 | 最高 `59` | 核心特征缺失时不能通过外围工程项补分 |
|
||||
| S07/S08/S09 任一支撑证据缺失 | 最高 `84` | 可以是最小蜂群,但不能声称完整合规原型 |
|
||||
| L01/L02 任一规模或预算证据缺失 | 最高 `94` | 可以合规,但不能声称“极强本地最小蜂群合规” |
|
||||
|
||||
因此,当前结论不是“看起来像蜂群”,而是:
|
||||
|
||||
```text
|
||||
swarmness_score = 100 / 100
|
||||
minimal_compliance_score = 100 / 100
|
||||
tier = 极强本地最小蜂群合规
|
||||
production_certification = false
|
||||
```
|
||||
|
||||
边界:这个分数只证明本仓库定义的本地最小蜂群标准,不证明生产级 Kubernetes runtime、跨机器真实调度、人类审批和长期监控已经完成。
|
||||
|
||||
证据入口:
|
||||
|
||||
```bash
|
||||
python3 -u -B examples/run_swarm_compliance_score.py
|
||||
```
|
||||
|
||||
## 4. 总门槛
|
||||
|
||||
| 门槛 | 测试场景 | 成功值 |
|
||||
| --- | --- | --- |
|
||||
| A01 静态编译 | 编译 `swarm_minimal/*.py`、`examples/*.py`、`tests/*.py` | 退出码 `0`,无语法错误 |
|
||||
| A02 单元与确定性场景 | `python3 -B -m unittest discover -s tests` | 当前 45 项测试全部通过,失败数 `0` |
|
||||
| A03 蜂群行为 | B01-B04:故障隔离、涌现、信息素、handoff | 4 个场景全部 PASS |
|
||||
| A04 传统基线对比 | 蜂群 vs 单路线/FIFO/无共享状态/无 handoff | 蜂群总归一化分高于传统基线;当前 `0.9175 > 0.1958` |
|
||||
| A05 多轮共识 | 候选 `lease_based_pg_queue` 的加权投票 | `converged=true`,`round_count >= 2` |
|
||||
| A06 下一阶段边界 | S09 三项:3/5/7 claim、候选融合、互相质询 | 3 项全部 PASS |
|
||||
| A07 六特征 | S10 六项蜂群一级特征 | 6 项全部 PASS |
|
||||
| A08 模型预算 | L02 3000 TPM 调度验收 | 3000 token 单窗口不超额;预算利用率 `1.0`;失败和重复 claim 都为 `0` |
|
||||
| A09 蜂群性数值 | 加权评分和硬上限 | `swarmness_score=100`;`minimal_compliance_score=100`;核心特征任一失败时最高 `59` |
|
||||
| S07 live 外部代码 | `fastapi/fastapi` 固定 commit 的 7 步 Agnet 链 | 14 项检查全部 PASS,失败数 `0` |
|
||||
| S08 模型 I/O 审计 | 审计 `MODEL_AGNET_IO_REPORT.zh-CN.md` | 场景、输入、输出、交接证据存在,密钥样式命中数 `0` |
|
||||
| S09 边界能力 | 扩缩容、融合、质询 | 3 项全部 PASS |
|
||||
| S10 六特征 | F01-F06 | 6 项全部 PASS |
|
||||
| L01 本机最大性能压力 | 使用本机检测到的全部逻辑 CPU 跑多进程大规模 swarm stress | 默认 `worker_processes = logical_cpus`;完成任务数等于目标任务数;失败 `0`;重复 claim `0`;所有分片收敛 |
|
||||
| L02 3000 TPM 模型预算 | 8 个 Agent 并发领取模型预算任务,共享虚拟 TPM ledger | `target_tpm = 3000`;单个模拟分钟 token 使用量 `<=3000`;总预留 token `=3000`;预算利用率 `=1.0`;失败 `0`;重复 claim `0` |
|
||||
|
||||
## 5. S10 蜂群六特征指标
|
||||
|
||||
S10 是当前蜂群指标的主门。它不接受“多 Agent 能跑”这种宽泛结论,只接受下面六项都达标。
|
||||
|
||||
| ID | 指标 | 设计场景 | 成功值 |
|
||||
| --- | --- | --- | --- |
|
||||
| F01 | 去中心化 | 4 个 Agent 自主领取 8 个 `autonomous` 任务;每个 Agent 只基于共享任务池和本地 task 输入决策 | `participating_agents >= 4`;`duplicate_claims = 0`;`control_keys = 0`;`decision_records = task_count = 8` |
|
||||
| F02 | 自组织 | 5 个局部信号 `api:0.31`、`docs:0.22`、`api:0.29`、`tests:0.18`、`api:0.27` 写入 shared_state,初始不预置全局分类 | `no_preseeded_global_plan=true`;`local_interaction_count >= 5`;`dominant_cluster = api`;`cluster:api:count = 3`;`cluster:api:score > cluster:docs:score` |
|
||||
| F03 | 涌现性 | 4 个局部候选信号:`alpha:0.31`、`beta:0.33`、`beta:0.34`、`gamma:0.45`;单个 `gamma` 局部信号最高,但 `beta` 群体累计更高 | `candidate:beta:score = 0.67`;`accepted_candidate = beta`;`accepted_score > max(local_signal_i) = 0.45` |
|
||||
| F04 | 鲁棒性 | 3 个 route 任务,其中 1 个 Agent 故意抛错,2 个 backup Agent 正常完成 | `failed_tasks = 1`;`completed_tasks >= 2`;`negative_observation_exists=true`;`run_status = converged` |
|
||||
| F05 | 可扩展性 | 分别用 `3/5/7` 个 Agent 跑同一 shared task pool 架构,每个 Agent 对应 2 个任务 | 对每个 `n ∈ {3,5,7}`:`completed_tasks = 2n`;`failed_tasks = 0`;`duplicate_claims = 0`;`participating_agents = n`;所有 task 状态为 `done` |
|
||||
| F06 | 隐式协作 | 3 个 `stigmergy` 任务预置信息素:high `0.9`、medium `0.4`、low `0.1`;Agent 不互发消息,只读写环境痕迹 | `direct_message_keys = 0`;`environment:trail` 存在;`first_claim = high-signal`;`final_pheromone_high > final_pheromone_medium` |
|
||||
|
||||
S10 成功公式:
|
||||
|
||||
```text
|
||||
S10_PASS =
|
||||
F01_pass
|
||||
∧ F02_pass
|
||||
∧ F03_pass
|
||||
∧ F04_pass
|
||||
∧ F05_pass
|
||||
∧ F06_pass
|
||||
```
|
||||
|
||||
证据入口:
|
||||
|
||||
```bash
|
||||
python3 -B -m unittest tests.test_swarm_characteristics_acceptance
|
||||
python3 -u -B examples/run_swarm_characteristics_acceptance.py
|
||||
```
|
||||
|
||||
## 6. S09 下一阶段边界指标
|
||||
|
||||
| ID | 指标 | 设计场景 | 成功值 |
|
||||
| --- | --- | --- | --- |
|
||||
| S09-1 | SW-AQS-16 并发自主 claim | `3/5/7` 个 Agent 分别领取 `2n` 个 stress 任务 | 对每个 `n`:`converged=true`;`completed_tasks=2n`;`failed_tasks=0`;`duplicate_claims=0`;`participating_agents=n` |
|
||||
| S09-2 | 候选融合 | 三个候选:quality `0.91`、coverage `0.86`、noise `0.2`;融合阈值 `min_score=0.5` | `source_candidate_ids=("quality","coverage")`;融合文本包含所有 expected terms;不包含 `低分噪声` |
|
||||
| S09-3 | 互相质询共识 | 3 个 QuestioningAgent 执行 challenge、revise、vote;参数 `threshold=0.7`、`min_margin=0.2`、`max_rounds=3`、`evaporation=0.85` | `converged=true`;`accepted_candidate=approve_fused_candidate`;`round_count>=2`;第一轮不收敛;最后一轮收敛;每轮都有 challenges 和 revisions |
|
||||
|
||||
证据入口:
|
||||
|
||||
```bash
|
||||
python3 -u -B examples/run_next_boundary_acceptance.py
|
||||
```
|
||||
|
||||
## 7. L01 本机最大性能压力指标
|
||||
|
||||
L01 用来回答“这台电脑本地最大性能下,当前最小蜂群 claim / 执行 / 收敛是否仍稳定”。它默认使用 `os.cpu_count()` 检测到的全部逻辑 CPU,并用多进程分片压测,避免只在单线程里假并发。
|
||||
|
||||
| 指标 | 设计场景 | 成功值 |
|
||||
| --- | --- | --- |
|
||||
| CPU 使用范围 | 默认读取本机逻辑 CPU 数 | `worker_processes = logical_cpus`,本机当前为 `8` |
|
||||
| 大规模任务量 | 每个进程跑一个独立 swarm 分片 | 默认 `tasks_per_process = 2048`;本轮重压测提升到 `16384` |
|
||||
| Agent 规模 | 每个进程多个 Agent 共享 task pool | 默认每进程 `8` 个 Agent;本轮重压测提升到 `16`,总计 `128` 个 Agent |
|
||||
| CPU-bound 工作 | 每个任务执行 deterministic checksum | 默认 `64` 轮;本轮重压测为 `128` 轮 |
|
||||
| 正确性 | 所有任务必须完成 | `completed_tasks = total_tasks` |
|
||||
| 容错安全 | 本地压力下不允许任务失败 | `failed_tasks = 0` |
|
||||
| claim 安全 | 本地压力下不允许重复领取 | `duplicate_claims = 0` |
|
||||
| 参与度 | 所有 Agent 至少参与一次 | `participating_agents = total_agents` |
|
||||
| 收敛 | 每个进程分片都必须收敛 | `converged_shards = worker_processes` |
|
||||
|
||||
本轮最大性能实测结果:
|
||||
|
||||
```text
|
||||
logical_cpus = 8
|
||||
worker_processes = 8
|
||||
agents_per_process = 16
|
||||
total_agents = 128
|
||||
tasks_per_process = 16384
|
||||
total_tasks = 131072
|
||||
cpu_cycles_per_task = 128
|
||||
duration_seconds = 46.9689
|
||||
tasks_per_second = 2790.61
|
||||
failed_tasks = 0
|
||||
duplicate_claims = 0
|
||||
converged_shards = 8
|
||||
```
|
||||
|
||||
证据入口:
|
||||
|
||||
```bash
|
||||
python3 -u -B examples/run_large_scale_stress_acceptance.py
|
||||
```
|
||||
|
||||
本轮最大性能命令:
|
||||
|
||||
```bash
|
||||
SWARM_STRESS_AGENTS_PER_PROCESS=16 \
|
||||
SWARM_STRESS_TASKS_PER_PROCESS=16384 \
|
||||
SWARM_STRESS_CPU_CYCLES=128 \
|
||||
python3 -u -B examples/run_large_scale_stress_acceptance.py
|
||||
```
|
||||
|
||||
边界:L01 是本机内存版最大性能压力验收,不等同于生产 Kubernetes runtime、跨机器网络、真实 Redis Stream 消费或长期稳定性压测。
|
||||
|
||||
## 8. L02 3000 TPM 模型预算指标
|
||||
|
||||
L02 用来回答“如果模型侧只给 3000 TPM,当前蜂群是否能在共享任务池里按预算调度,而不是并发冲过额度”。它不调用真实模型供应商,使用本地确定性的虚拟 token ledger,避免把验收建立在外部网络抖动或真实 key 泄露上。
|
||||
|
||||
参数来源:
|
||||
|
||||
| 参数 | 值 | 来源 / 解释 |
|
||||
| --- | --- | --- |
|
||||
| `target_tpm` | `3000` | 本轮用户指定的模型吞吐量级,等价于每分钟最多 3000 token 的预算 |
|
||||
| `tokens_per_task` | `50` | 本地确定性测试的单位模型任务成本;不是声称真实业务任务都只有 50 token |
|
||||
| `task_count` | `60` | `3000 / 50 = 60`,刚好打满一个 3000 token 窗口,用来验收满载不超额 |
|
||||
| `agent_count` | `8` | 默认 `min(8, logical_cpus)`;本机当前为 8 个逻辑 CPU,所以使用 8 个预算 Agent |
|
||||
| `simulated_minutes` | `1` | `ceil(total_token_demand / target_tpm) = ceil(3000 / 3000) = 1` |
|
||||
|
||||
补充单元测试还覆盖 61 个任务的 rollover 场景:第 61 个 50-token 任务会排入第二个模拟分钟,因此窗口分布必须是 `{0: 3000, 1: 50}`,用来证明不是简单把所有任务硬塞进同一窗口。
|
||||
|
||||
| 指标 | 设计场景 | 成功值 |
|
||||
| --- | --- | --- |
|
||||
| TPM 预算 | 目标模型吞吐预算固定为 `3000 TPM` | `target_tpm = 3000` |
|
||||
| 任务规模 | 60 个模型预算任务,每个任务 50 token | `task_count = 60`;`tokens_per_task = 50`;`total_reserved_tokens = 3000` |
|
||||
| Agent 规模 | 默认读取本机逻辑 CPU,上限 8 个预算 Agent | 本机当前 `agent_count = 8`,且 8 个 Agent 都至少参与一次 |
|
||||
| 预算窗口 | 每次任务执行必须先向共享 ledger 预留 token | 任意模拟分钟 `tokens <= 3000`;`over_budget_windows = {}` |
|
||||
| 预算利用率 | 默认总需求正好打满一个 3000 token 窗口 | `budget_utilization = 1.0` |
|
||||
| 正确性 | 所有预算任务完成 | `completed_tasks = 60`;`all_tasks_done = true` |
|
||||
| 容错安全 | 预算调度下不允许任务失败 | `failed_tasks = 0` |
|
||||
| claim 安全 | 并发预算调度下不允许重复领取 | `duplicate_claims = 0` |
|
||||
| 收敛 | 预算任务完成后写入收敛结果 | `converged = true` |
|
||||
|
||||
L02 成功公式:
|
||||
|
||||
```text
|
||||
L02_PASS =
|
||||
target_tpm = 3000
|
||||
∧ max(tokens_by_minute) <= 3000
|
||||
∧ total_reserved_tokens = task_count * tokens_per_task = 3000
|
||||
∧ budget_utilization = 1.0
|
||||
∧ completed_tasks = task_count
|
||||
∧ failed_tasks = 0
|
||||
∧ duplicate_claims = 0
|
||||
∧ participating_agents = agent_count
|
||||
∧ converged = true
|
||||
```
|
||||
|
||||
本轮 3000 TPM 实测结果:
|
||||
|
||||
```text
|
||||
target_tpm = 3000
|
||||
agent_count = 8
|
||||
task_count = 60
|
||||
tokens_per_task = 50
|
||||
total_reserved_tokens = 3000
|
||||
simulated_minutes = 1
|
||||
max_tokens_in_any_minute = 3000
|
||||
budget_utilization = 1.0
|
||||
failed_tasks = 0
|
||||
duplicate_claims = 0
|
||||
participating_agents = 8
|
||||
```
|
||||
|
||||
证据入口:
|
||||
|
||||
```bash
|
||||
python3 -u -B examples/run_tpm_budget_acceptance.py
|
||||
python3 -B -m unittest tests.test_tpm_budget_acceptance
|
||||
```
|
||||
|
||||
边界:L02 是本地模型预算调度验收,不等同于真实供应商的 live 限流压测。真实供应商限流还需要在 NewAPI 网关侧记录请求 token、返回 token、429 重试和费用归因。
|
||||
|
||||
## 9. S07 live 外部代码 Agent 链指标
|
||||
|
||||
S07 的任务不是测试本仓库,而是让 7 个连续 Agnet 阶段审查外部复杂 GitHub 项目:
|
||||
|
||||
```text
|
||||
目标项目: fastapi/fastapi
|
||||
固定 commit: ecace740f3eaccb1aba152cf1de79477095c56f4
|
||||
任务主题: 响应序列化与 OpenAPI 依赖链审查
|
||||
```
|
||||
|
||||
| 指标 | 设计场景 | 成功值 |
|
||||
| --- | --- | --- |
|
||||
| 模型发现 | 从 NewAPI 兼容模型列表选择模型 | `len(discovered_models) >= 3`;`len(set(selected_models)) = 3`;selected 是 discovered 子集 |
|
||||
| 7 步链路 | STEP-01 到 STEP-07 连续推理 | PostgreSQL 中 `task_rows = 7`;全部 `status=done` |
|
||||
| marker 与前序承接 | 每步输出必须包含当前 STEP 和 previous marker | 7/7 输出满足 `own_marker` 和 `previous_marker` |
|
||||
| 输出质量门 | 每步输出按质量检查项得分 | `Q >= 0.72` 且关键项全通过 |
|
||||
| shared_state 交接 | 每步写 summary、cursor、edge | `cursor=STEP-07`;`summary_count=7`;7 条 edge 都存在 |
|
||||
| 信息素证据 | PostgreSQL 与 Redis 都记录正反馈 | 每个任务 `P_task_pg > 0` 且 `P_task_redis > 0` |
|
||||
| 收敛状态 | run 完成并写入收敛结果 | `run_status=converged` |
|
||||
| artifact 证据 | Blob 中存在结果工件 | `blob_artifact_exists=true` |
|
||||
| 收敛分 | 最终结果可接受 | `completed_tasks=7`;`accepted_score >= 0.75` |
|
||||
| 事件流 | Redis Stream 记录 claim/done/converged 等事件 | `event_delta >= 3 * task_count + 1`,当前任务数为 7,因此至少 22 |
|
||||
| 外部代码材料 | 输出必须包含外部 FastAPI 代码审查信息 | 包含不变量、反例、修正、验收、复杂度或 `O(`,并包含 FastAPI 代码语义 |
|
||||
| 多轮质量共识 | 三类审查 Agnet 对最终链路投票 | `converged=true`;`accepted_candidate=accept_external_chain`;`round_count>=2`;参数 `threshold=0.7`、`min_margin=0.25` |
|
||||
| 文件引用 | 最终输出必须落到外部仓库文件 | `count_referenced_files(final_output) >= 5` |
|
||||
| 不固定模型 | 不能把 `NEWAPI_MODEL` 当成唯一固定模型 | 输出必须说明模型发现 / discover,并拒绝固定单模型 |
|
||||
| 不测试本仓库 | 不能把 `swarm_minimal`、`examples` 当成被测代码 | 输出含 `fastapi/fastapi` 和固定 commit;引用外部文件数 `>=5`;本仓库目标漂移为 false |
|
||||
|
||||
证据入口:
|
||||
|
||||
```bash
|
||||
python3 -u -B examples/run_standard_scenario_acceptance.py
|
||||
```
|
||||
|
||||
## 10. 通用 Agent 指标 AQS
|
||||
|
||||
| ID | 指标 | 设计场景 | 成功值 |
|
||||
| --- | --- | --- | --- |
|
||||
| AQS-01 | 任务理解 | S07 每个 Agnet 被分配一个明确 STEP 子任务 | 7/7 输出回应当前 STEP,不泛泛聊天 |
|
||||
| AQS-02 | 指令遵循 | 输出必须包含 marker、约束、文件路径、验收命令或风险项 | `quality_pass=true`,且缺失关键项数量为 `0` |
|
||||
| AQS-03 | 上下文忠实 | 除 STEP-01 外,每步承接上一步 marker 和 summary | 7/7 输出包含 previous marker;shared_state 有 7 条 edge |
|
||||
| AQS-04 | 可验证输出 | 输出能被规则检查,而不是只有主观结论 | S03/S05/S07 相关检查全部 PASS |
|
||||
| AQS-05 | 模型选择可控 | 不依赖固定 `NEWAPI_MODEL` | discovered 模型数 `>=3`,selected distinct 模型数 `=3` |
|
||||
| AQS-06 | 工具/资源边界 | MVP 不把 NATS/Cosmos 变成必需依赖 | 依赖边界测试中“必须依赖 NATS/Cosmos”的文本必须被判 false |
|
||||
| AQS-07 | 敏感信息保护 | 审计 Markdown、报告和配置摘要 | 明显密钥样式命中数 `0`;配置输出只允许 redacted 或占位符 |
|
||||
| AQS-08 | 可观测性 | S07 写入 run_id、task、score、event、artifact | PostgreSQL、Redis、Blob 证据全部存在 |
|
||||
| AQS-09 | 错误可解释 | 故障注入任务失败 | failed task 有 error;负信息素 `<0`;其他任务继续完成 |
|
||||
| AQS-10 | 交接准备度 | 每个 Agnet 输出给下一步 summary / risk / next action | STEP-01 到 STEP-06 均能被下一步读取并继续 |
|
||||
| AQS-11 | 外部依赖真实性 | live 连接 Azure PostgreSQL、Redis、Blob、NewAPI | S07 完整矩阵 PASS;无 `.env` 时不能声称 full standard PASS |
|
||||
| AQS-12 | 人类审计友好 | 生成并审计模型 I/O 报告 | 场景、任务、输入、输出、交接证据存在;审计测试 2 项 PASS |
|
||||
| AQS-13 | 输出质量恢复 | 故意让 bad model 先输出拒答/角色边界文本 | bad output 分数为 `0.12`;触发 retry/fallback;最终 `used_model=good-model` |
|
||||
|
||||
## 11. 蜂群 Agent 指标 SW-AQS
|
||||
|
||||
| ID | 指标 | 设计场景 | 成功值 |
|
||||
| --- | --- | --- | --- |
|
||||
| SW-AQS-01 | 多角色能力 | S07 3 个不同模型、7 个连续步骤 | selected distinct 模型数 `=3`;chain step 数 `=7` |
|
||||
| SW-AQS-02 | 共享任务池 | Agent 从统一 task pool claim | task_rows `=7` 或 S09/S10 场景任务数全部进入同一 store |
|
||||
| SW-AQS-03 | 局部感知 | Agent 输入包含当前任务和前序 summary | 每步 prompt 带 task input;STEP-02 到 STEP-07 带 previous summary |
|
||||
| SW-AQS-04 | 自主 claim / 去中心化 | S10 F01 | `participating_agents>=4`;`duplicate_claims=0`;`control_keys=0` |
|
||||
| SW-AQS-05 | 信息素 / 分数 | 成功加分,失败扣分 | 成功任务 `P_t>0`;失败任务 `P_t<0` |
|
||||
| SW-AQS-06 | 隐式协作 | S10 F06 | `message:*` 键数量 `0`;依靠 pheromone 和 shared_state trail 协作 |
|
||||
| SW-AQS-07 | handoff 连续性 | B04 与 S07 chain edge | active agent、目标 agent、payload、edge 均保留 |
|
||||
| SW-AQS-08 | 广播 / 事件 | Redis Stream 记录事件 | S07 `event_delta >= 22` |
|
||||
| SW-AQS-09 | 收敛条件 | 不只看跑完,还看分数、状态、artifact、质量门、共识 | S07 14 项 checks 全 PASS |
|
||||
| SW-AQS-10 | 鲁棒性 | S10 F04 / B01 / S06 | 单 Agent 失败时 `failed_tasks>=1`,但 run 仍 `converged` |
|
||||
| SW-AQS-11 | 涌现性 | S10 F03 / B02 | 群体累计分大于任一局部信号,最终候选来自群体聚合 |
|
||||
| SW-AQS-12 | 传统基线对比 | C01-C04 | swarm score 高于 traditional score;当前 ratio `4.69` |
|
||||
| SW-AQS-13 | live 外部闭环 | S07 | Azure + NewAPI + 外部 GitHub 代码场景 PASS |
|
||||
| SW-AQS-14 | 马尔可夫式状态 | M01-M03 | 等价当前状态下 claim 与 score 更新一致;但不声明严格 MDP |
|
||||
| SW-AQS-15 | 多轮质询共识 | S07/S09 | `round_count>=2`,第一轮可不收敛,后续达成接受 |
|
||||
| SW-AQS-16 | 扩缩容与并发 | S09/S10 F05 | `3/5/7` Agent 下完成 `2n` 任务,失败和重复 claim 都为 `0` |
|
||||
| SW-AQS-17 | 候选融合 | S09-2 | `min_score=0.5` 过滤低分噪声,保留多个高分候选来源 |
|
||||
| SW-AQS-18 | 本机大规模压力 | L01 | 8 逻辑核满核压测,128 Agent / 131072 任务,失败 `0`、重复 claim `0`、全部收敛 |
|
||||
| SW-AQS-19 | 模型预算调度 | L02 | 3000 TPM 窗口内 60 个预算任务全部完成;单分钟 token 不超额;预算利用率 `1.0`;失败和重复 claim 都为 `0` |
|
||||
|
||||
## 12. 不通过判定
|
||||
|
||||
出现以下任一情况,不能判定通过:
|
||||
|
||||
- 六特征任一项失败。
|
||||
- S07 14 项 live 检查任一失败。
|
||||
- 模型输出拒答、角色拒绝、偏题或漂移到本仓库后,没有触发扣分、重试或 fallback。
|
||||
- 报告、日志或 Markdown 中出现真实长期密钥、连接串或未脱敏密码。
|
||||
- claim 出现重复领取,或者单个 Agent 失败导致整体不能收敛。
|
||||
- 只展示最高分候选,但没有候选融合或多轮共识证据。
|
||||
- 缺少 `.env` 时仍声称完整 S07 live 标准矩阵已通过。
|
||||
- L01 压测中出现任务失败、重复 claim、分片未收敛或参与 Agent 数不足时,不能声称本机大规模压力通过。
|
||||
- L02 中任意模拟分钟 token 超过 `3000`,或者总需求没有被完整预留,不能声称 3000 TPM 量级通过。
|
||||
|
||||
## 13. 当前结论
|
||||
|
||||
按本文件定义的最小验收口径,当前仓库已经达到最小 Agent / 蜂群 Agent 闭环:
|
||||
|
||||
- A01-A09 通过。
|
||||
- S01-S10 通过。
|
||||
- F01-F06 通过。
|
||||
- L01 本机最大性能压力通过:8 逻辑核、128 Agent、131072 任务、失败 0、重复 claim 0。
|
||||
- L02 3000 TPM 模型预算验收通过:8 Agent、60 个任务、3000 token 单窗口打满、失败 0、重复 claim 0。
|
||||
- S07 live 外部 GitHub 代码场景通过,最新 run_id 为 `9c7ccc6087c1435694a52efb12c32301`。
|
||||
|
||||
边界:这不是生产级无中心分布式 runtime 认证。真实 Kubernetes worker、Manager / Agnet API、人类审批、生产监控和长期运行压测仍属于下一阶段。
|
||||
@@ -14,6 +14,8 @@
|
||||
- 多个 Agent 是否能通过共享环境、信息素、handoff 和收敛机制形成蜂群行为。
|
||||
- Agent 运行过程是否能被审计、复现、拒绝越权、避免明文密钥泄露。
|
||||
|
||||
所有指标的设计场景和成功阈值统一维护在 `AGENT_SWARM_INDICATOR_TEST_MATRIX.zh-CN.md`。本文定义质量项;凡是本文出现的 AQS、SW-AQS、S07、S09、S10 指标,都必须能在该矩阵中找到“场景 + 成功值 + 证据入口”。
|
||||
|
||||
## 2. 行业参考来源
|
||||
|
||||
当前行业没有统一的“Agent 质量认证”。本项目采用“行业参考 + 本项目配置标准”的方式:
|
||||
@@ -47,6 +49,16 @@
|
||||
| AQS-12 人类审计友好 | 最终报告必须能回答:任务、输入、输出、接手、结果、未满足项 | S08 + `MODEL_AGNET_IO_REPORT.zh-CN.md` 和本文件 |
|
||||
| AQS-13 输出质量恢复 | 拒答、角色拒绝、偏题或目标漂移必须被扣分,并触发重试或 fallback 模型接手 | S07 `all_outputs_pass_quality_gate` + fallback 单元测试 |
|
||||
|
||||
### 3.1 AQS 场景和成功值摘要
|
||||
|
||||
| 指标组 | 设计场景 | 成功值 |
|
||||
| --- | --- | --- |
|
||||
| 任务理解 / 指令遵循 / 上下文忠实 | S07 外部 FastAPI 代码链路,STEP-01 到 STEP-07 连续承接 | 7/7 输出包含当前 STEP、previous marker、外部仓库和固定 commit;质量分 `Q >= 0.72` 且关键项全通过 |
|
||||
| 模型选择可控 | NewAPI 模型发现后选择多模型 Agnet | `len(discovered_models) >= 3`;`len(set(selected_models)) = 3`;不固定单一 `NEWAPI_MODEL` |
|
||||
| 资源边界 / 敏感信息保护 | 依赖边界测试、Markdown/报告密钥样式审计 | NATS/Cosmos 不能成为 MVP 必需依赖;明显密钥样式命中数 `0` |
|
||||
| 可观测性 / 可验证输出 | PostgreSQL、Redis、Blob、shared_state、event stream 证据 | task rows、pheromone、cursor、edge、artifact、event delta 均存在;S07 14 项 checks 全 PASS |
|
||||
| 输出质量恢复 | bad model 先产生拒答或角色边界输出 | 风险输出分数固定为 `0.12`;触发 retry/fallback;最终输出带 `used_model=good-model` |
|
||||
|
||||
## 4. 蜂群六特征一级验收指标
|
||||
|
||||
蜂群 Agent 的主验收指标调整为六个一级特征。它们不是补充说明,而是 S10 的直接验收标准。
|
||||
@@ -76,6 +88,17 @@ SWARM_PASS =
|
||||
|
||||
完整细节见 `SWARM_CHARACTERISTICS_ACCEPTANCE_STANDARD.zh-CN.md`。
|
||||
|
||||
六特征成功值摘要:
|
||||
|
||||
| 特征 | 成功值 |
|
||||
| --- | --- |
|
||||
| 去中心化 | `participating_agents >= 4`、`duplicate_claims = 0`、`control_keys = 0`、`decision_records = task_count` |
|
||||
| 自组织 | 初始不预置全局结果;`local_interaction_count >= 5`;`dominant_cluster = argmax(cluster_score)` |
|
||||
| 涌现性 | `global_score(candidate_group) > max(local_signal_i)`,最终接受聚合胜出候选 |
|
||||
| 鲁棒性 | `failed_tasks >= 1`、`completed_tasks >= 2`、存在负反馈、run 仍 `converged` |
|
||||
| 可扩展性 | `3/5/7` Agent 下均满足 `completed_tasks = 2n`、`failed_tasks = 0`、`duplicate_claims = 0` |
|
||||
| 隐式协作 | `direct_message_keys = 0`,通过 pheromone 和 shared_state trail 协调,最高信息素任务优先 claim |
|
||||
|
||||
## 5. 蜂群 Agent 质量标准 SW-AQS
|
||||
|
||||
| ID | 蜂群质量项 | 合格标准 | 当前证据 / 缺口 |
|
||||
@@ -97,6 +120,21 @@ SWARM_PASS =
|
||||
| SW-AQS-15 多轮质询共识 | 最终接受结果必须经过交接连续性、输出质量、最终收敛审查,并支持反驳、修正、再投票 | S07 `multi_round_quality_consensus_accepts_chain` + S09 `question_revise_revote_consensus` |
|
||||
| SW-AQS-16 扩缩容与并发 / 可扩展性 | 3/5/7 Agent 并发自主 claim 下仍稳定,新增或移除 Agent 不改变架构 | S10 F05 + S09 `sw_aqs_16_scaled_autonomous_claim_3_5_7` |
|
||||
| SW-AQS-17 候选融合 | 可把多个有效候选输出去重融合,而不是只能接受单个最高分文本 | S09 `candidate_fusion_output` |
|
||||
| SW-AQS-18 本机大规模压力 | 使用本机全部逻辑 CPU 做多进程大规模 claim、执行和收敛压力测试 | L01:8 逻辑核、128 Agent、131072 任务、失败 0、重复 claim 0 |
|
||||
| SW-AQS-19 模型预算调度 | 多 Agent 并发执行时必须遵守模型侧 TPM 预算,不能把所有请求一拥而上 | L02:3000 TPM、8 Agent、60 个任务、单窗口 token 不超额、预算利用率 1.0 |
|
||||
|
||||
### 5.1 SW-AQS 场景和成功值摘要
|
||||
|
||||
| 指标组 | 设计场景 | 成功值 |
|
||||
| --- | --- | --- |
|
||||
| 多角色与共享任务池 | S07 3 模型、7 步外部代码链;S09/S10 本地 shared task pool | selected distinct 模型数 `=3`;chain step 数 `=7`;任务均来自同一 task pool |
|
||||
| 自主 claim 与扩缩容 | S09/S10 使用 `3/5/7` Agent 领取 `2n` 任务 | 每个规模下 `completed_tasks=2n`、`failed_tasks=0`、`duplicate_claims=0`、`participating_agents=n` |
|
||||
| 蜂群性数值评分 | F01-F06 占 60 分,S07/S08/S09 占 25 分,L01/L02 占 15 分 | 当前 `swarmness_score=100/100`,`minimal_compliance_score=100/100`,F01-F06 任一失败时最高 `59` |
|
||||
| 本机最大性能压力 | L01 使用本机 8 逻辑核跑 8 进程、128 Agent、131072 任务 | `completed_tasks=131072`、`failed_tasks=0`、`duplicate_claims=0`、`converged_shards=8` |
|
||||
| 3000 TPM 模型预算 | L02 使用 8 Agent 领取 60 个模型预算任务,每个任务 50 token | `total_reserved_tokens=3000`、`max_tokens_in_any_minute=3000`、`budget_utilization=1.0`、`failed_tasks=0`、`duplicate_claims=0` |
|
||||
| 信息素和隐式协作 | 成功任务加分、失败任务扣分;F06 用 `0.9/0.4/0.1` 信息素控制顺序 | 成功 `P_t>0`;失败 `P_t<0`;F06 首个 claim 为 `high-signal` 且无 `message:*` 键 |
|
||||
| 收敛和共识 | S07 质量共识、S09 反驳-修正-再投票 | S07 14 项 checks 全 PASS;共识 `round_count>=2`;S09 第一轮不收敛、最后一轮收敛 |
|
||||
| 候选融合 | `quality=0.91`、`coverage=0.86`、`noise=0.2` | `min_score=0.5`;保留 quality/coverage;过滤 noise |
|
||||
|
||||
## 6. S07 live 测试任务定义
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
这份说明只从 Agnet 的输入、输出、交接和收敛角度解释当前框架逻辑,不展开源码,不写命令,不贴实现代码。
|
||||
|
||||
指标测试的统一阈值见 `AGENT_SWARM_INDICATOR_TEST_MATRIX.zh-CN.md`。本文件描述输入输出链路如何工作;“到多少值算成功”以该矩阵和 `SCORING_AND_ACCEPTANCE_FORMULAS.zh-CN.md` 为准。
|
||||
|
||||
## 一句话逻辑
|
||||
|
||||
当前框架不是让一个模型一次性回答完整问题,而是把一个复杂目标拆成连续的 Agnet 输入。每个 Agnet 接收“当前任务输入”和“上一位 Agnet 的输出摘要”,生成自己的输出,再把这个输出变成下一位 Agnet 的输入条件。最后,框架先做输出质量门和多轮质量共识,再根据评分选择最终可接受输出作为收敛结果。
|
||||
@@ -70,6 +72,8 @@
|
||||
|
||||
第五步,对输出进行评分。评分偏向连续性、目标一致性、可交接性和最终可验收性。输出偏题、拒答或只声明能力边界时,会被重罚,不能靠普通高分混进最终结果。
|
||||
|
||||
当前输入输出链的关键成功值是:每个 Agnet 输出质量分 `Q >= 0.72` 且关键项全通过;STEP-01 到 STEP-07 共 7 个任务全部完成;最终接受分 `accepted_score >= 0.75`;质量共识至少 2 轮;任一模型拒答、角色拒绝、偏题或漂移到本仓库时,风险输出分固定降为 `0.12` 并触发重试或 fallback。
|
||||
|
||||
第六步,如果输出不合格,框架先进行同模型重试;仍不合格时,切换到 fallback 模型接手当前步骤。只有通过质量门的输出才会成为下一步摘要。
|
||||
|
||||
第七步,把每一步输出沉淀成共享状态、观测记录和评分记录。这样最终报告可以追溯“谁接了什么输入、谁输出了什么、谁把结论交给了下一步”。
|
||||
|
||||
@@ -19,6 +19,18 @@
|
||||
| LangGraph handoff | 参考 active-agent 和 `transfer_to_<agent>` 式交接语义 |
|
||||
| 蜂群六特征归纳标准 | 约束去中心化、自组织、涌现性、鲁棒性、可扩展性和隐式协作 |
|
||||
|
||||
## 指标落地方式
|
||||
|
||||
行业框架只提供方向,不直接给本项目可执行阈值。因此本项目把框架要求落成 `AGENT_SWARM_INDICATOR_TEST_MATRIX.zh-CN.md` 中的可测指标:
|
||||
|
||||
| 来源方向 | 本项目指标 | 设计场景 | 成功值 |
|
||||
| --- | --- | --- | --- |
|
||||
| NIST 风险可度量 | AQS-01 到 AQS-13 | S07 外部 FastAPI 代码链、质量门、fallback、报告审计 | 7/7 STEP 可承接;质量 `Q >= 0.72`;明显密钥样式命中数 `0` |
|
||||
| OWASP 工具与密钥边界 | AQS-06 / AQS-07 | 依赖边界测试、Markdown/报告密钥样式扫描 | NATS/Cosmos 不能成为必需依赖;报告不输出真实长期密钥 |
|
||||
| OpenTelemetry 可观测 | AQS-08 / SW-AQS-08 | PostgreSQL task、Redis event、Blob artifact、shared_state edge | S07 14 项 checks 全 PASS;event delta 至少 `3*7+1=22` |
|
||||
| LangGraph handoff | AQS-03 / SW-AQS-07 | STEP 链路和 active-agent handoff | 7/7 输出包含 previous marker;handoff payload 保留 |
|
||||
| 蜂群六特征 | F01-F06 / S10 | 本地六特征验收 | 6 项全部 PASS,任一失败则 S10 失败 |
|
||||
|
||||
## 最小通过条件
|
||||
|
||||
本项目当前最小通过条件不是“代码质量通过”,而是:
|
||||
|
||||
@@ -8,16 +8,36 @@
|
||||
| 项 | 当前证据 |
|
||||
| --- | --- |
|
||||
| 本地静态门 | `py_compile swarm_minimal/*.py examples/*.py tests/*.py` 通过 |
|
||||
| 单元与确定性场景 | `unittest discover -s tests` 通过,当前为 41 项测试 |
|
||||
| 学术化本地门禁 | `run_academic_standard_evaluation.py` 覆盖 A01-A07 |
|
||||
| 单元与确定性场景 | `unittest discover -s tests` 通过,当前为 45 项测试 |
|
||||
| 学术化本地门禁 | `run_academic_standard_evaluation.py` 覆盖 A01-A09 |
|
||||
| 完整标准矩阵 | `run_standard_scenario_acceptance.py` 覆盖 S01-S10 |
|
||||
| live 外部代码场景 | S07 对 `fastapi/fastapi` 固定 commit 跑通 7 步 Agnet 链 |
|
||||
| 蜂群六特征 | S10 覆盖去中心化、自组织、涌现性、鲁棒性、可扩展性、隐式协作 |
|
||||
| 蜂群性数值 | `swarmness_score=100/100`,`minimal_compliance_score=100/100` |
|
||||
| 本机最大性能压力 | L01 使用 8 逻辑核、128 Agent、131072 任务完成本地大规模压力验收 |
|
||||
| 3000 TPM 模型预算 | L02 使用 8 个 Agent、60 个预算任务打满 3000 token 单分钟窗口,且不超额 |
|
||||
| 质量门 | 拒答、角色拒绝、偏题、本仓库漂移、交接断裂会被扣分和补救 |
|
||||
| fallback 补救 | 当前模型输出不合格时先重试,再切换 fallback 模型接手当前步骤 |
|
||||
| 多轮质量共识 | S07 已有交接连续性、输出质量、最终收敛三类审查 Agnet 的 2 轮共识 |
|
||||
| 马尔可夫式状态机 | 给定完整任务、信息素、共享状态、观测和 agent policy,工程转移由当前状态决定 |
|
||||
|
||||
## 最小闭环成功阈值
|
||||
|
||||
详细指标矩阵见 `AGENT_SWARM_INDICATOR_TEST_MATRIX.zh-CN.md`。当前“最小闭环已完成”只在下面阈值同时满足时成立:
|
||||
|
||||
| 指标组 | 成功值 |
|
||||
| --- | --- |
|
||||
| 本地门禁 | `py_compile` 退出码 `0`;`unittest discover` 当前 45 项全部通过 |
|
||||
| 学术化门禁 | A01-A09 全部 PASS |
|
||||
| 完整标准矩阵 | S01-S10 全部 PASS |
|
||||
| S07 live 外部代码链 | 7 个任务完成、14 项检查全 PASS、失败检查数 `0`、质量共识轮数 `>=2` |
|
||||
| S09 三项边界 | 3/5/7 Agent 并发 claim 无重复领取;候选融合过滤低分噪声;互相质询至少 2 轮后接受 |
|
||||
| S10 六特征 | 去中心化、自组织、涌现性、鲁棒性、可扩展性、隐式协作六项全部 PASS |
|
||||
| 蜂群性评分 | `swarmness_score>=75` 才能声称最小蜂群成立;当前 `100`;F01-F06 任一失败时总分最高 `59` |
|
||||
| L01 本机压力 | `completed_tasks=131072`、`failed_tasks=0`、`duplicate_claims=0`、`participating_agents=128`、`converged_shards=8` |
|
||||
| L02 3000 TPM | `target_tpm=3000`、`total_reserved_tokens=3000`、`max_tokens_in_any_minute=3000`、`budget_utilization=1.0`、`failed_tasks=0`、`duplicate_claims=0` |
|
||||
| 密钥安全 | Markdown / 报告中明显密钥样式命中数 `0` |
|
||||
|
||||
## 已补的三项边界
|
||||
|
||||
| 优先级 | 原缺口 | 已补最小实现 | 验收标准 |
|
||||
@@ -52,12 +72,18 @@
|
||||
5. `scalability_three_five_seven_agents_same_architecture`
|
||||
6. `implicit_collaboration_by_environment`
|
||||
|
||||
本轮新增 L01 / L02,专门把本机规模和模型预算量级纳入验收:
|
||||
|
||||
1. `local_large_scale_stress`: 使用本机 8 逻辑核、128 Agent、131072 任务验证本地大规模 claim / 执行 / 收敛稳定性。
|
||||
2. `local_3000_tpm_budget`: 使用 8 个 Agent、60 个预算任务、每任务 50 token,验证 3000 TPM 窗口内不超额且利用率打满。
|
||||
|
||||
## 仍不是生产级完整交付的部分
|
||||
|
||||
当前补齐的是本地确定性、最小代码级验收。以下仍属于更大范围平台阶段:
|
||||
|
||||
- Manager / Agnet 平台统一接口、人类审批主线、权限、预算和审计全链路。
|
||||
- 真实 Kubernetes runtime 的 3/5/7 worker 扩缩容压测。
|
||||
- 真实 NewAPI / 模型供应商侧 3000 TPM live 限流、429 重试、费用归因和长期运行曲线。
|
||||
- Redis Stream 事件被其他 Agent 实时消费并影响下一步任务图。
|
||||
- 自动创建补充 Agnet / 动态任务图,而不是只在当前候选上质询和修正。
|
||||
- 收敛速度、Agent 利用率、响应时间、信息素分布等生产监控指标。
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
报告解释 S07 外部 GitHub 代码场景:被测项目是什么、本仓库做了什么测试工作、不同 Agnet 如何接手,以及最终如何收敛。
|
||||
报告不展示 `.env` 或任何密钥;模型原始输出保存在 PostgreSQL,本页只给中文审计摘要和必要证据前缀,避免纯英文原文淹没测试结论。
|
||||
|
||||
本报告只记录 S07 live run 的输入输出证据。所有指标的设计场景、成功阈值和总体 PASS 口径见 `AGENT_SWARM_INDICATOR_TEST_MATRIX.zh-CN.md`;分数公式见 `SCORING_AND_ACCEPTANCE_FORMULAS.zh-CN.md`。
|
||||
|
||||
## 场景说明:FastAPI 是什么项目
|
||||
|
||||
- 被测项目:`fastapi/fastapi`,固定 commit `ecace740f3eaccb1aba152cf1de79477095c56f4`。
|
||||
|
||||
+8
-6
@@ -3,18 +3,20 @@
|
||||
## 当前阅读顺序
|
||||
|
||||
1. 先读 `MINIMAL_CLOSED_LOOP_STATUS.zh-CN.md`,确认当前仓库已完成的最小闭环、已补齐的三项边界和仍不是生产级完整交付的部分。
|
||||
2. 再读 `SWARM_CHARACTERISTICS_ACCEPTANCE_STANDARD.zh-CN.md`,确认去中心化、自组织、涌现性、鲁棒性、可扩展性、隐式协作这六个一级验收指标。
|
||||
3. 再读 `AGENT_SWARM_QUALITY_STANDARD.zh-CN.md` 和 `ACADEMIC_STANDARD_TEST_REPORT.zh-CN.md`,确认测试标准来自哪里、S01-S10 如何验收、测试结果是什么。
|
||||
4. 需要看分数如何计算、如何判定通过时,读 `SCORING_AND_ACCEPTANCE_FORMULAS.zh-CN.md`。
|
||||
5. 需要看真实模型 / Agnet 输入输出时,读 `MODEL_AGNET_IO_REPORT.zh-CN.md`。
|
||||
6. 需要看不带代码的框架逻辑、交接和收敛过程时,读 `AGNET_FRAMEWORK_INPUT_OUTPUT_LOGIC.zh-CN.md`。
|
||||
7. `agnet-swarm-design-principles.md`、`01-ten-day-delivery-plan.md`、`02-person-task-interface-matrix.md`、`03-minimal-validation-and-acceptance.md` 是生产级平台落地路线图,不应被误读成当前仓库已完成完整 Heicode / Manager / Agnet 平台集成。
|
||||
2. 再读 `AGENT_SWARM_INDICATOR_TEST_MATRIX.zh-CN.md`,确认每个指标的设计场景、输入、成功阈值和证据入口。
|
||||
3. 再读 `SCORING_AND_ACCEPTANCE_FORMULAS.zh-CN.md`,确认蜂群性数值评分、硬上限、分数等级和公式。
|
||||
4. 再读 `SWARM_CHARACTERISTICS_ACCEPTANCE_STANDARD.zh-CN.md`,确认去中心化、自组织、涌现性、鲁棒性、可扩展性、隐式协作这六个一级验收指标。
|
||||
5. 再读 `AGENT_SWARM_QUALITY_STANDARD.zh-CN.md` 和 `ACADEMIC_STANDARD_TEST_REPORT.zh-CN.md`,确认测试标准来自哪里、S01-S10 如何验收、测试结果是什么。
|
||||
6. 需要看真实模型 / Agnet 输入输出时,读 `MODEL_AGNET_IO_REPORT.zh-CN.md`。
|
||||
7. 需要看不带代码的框架逻辑、交接和收敛过程时,读 `AGNET_FRAMEWORK_INPUT_OUTPUT_LOGIC.zh-CN.md`。
|
||||
8. `agnet-swarm-design-principles.md`、`01-ten-day-delivery-plan.md`、`02-person-task-interface-matrix.md`、`03-minimal-validation-and-acceptance.md` 是生产级平台落地路线图,不应被误读成当前仓库已完成完整 Heicode / Manager / Agnet 平台集成。
|
||||
|
||||
当前结论:`fengqun` 仓库已经达到本仓库定义的最小化闭环验收;它不是生产级完整交付。生产级差距主要在真实 Kubernetes worker runtime、Manager / Agnet API、人类审批主线、生产权限和平台监控。
|
||||
|
||||
## Agent / 蜂群 Agent 测试
|
||||
|
||||
- `AGENT_SWARM_QUALITY_STANDARD.zh-CN.md`:AQS / SW-AQS v1 主标准,说明 Agent 和蜂群 Agent 的质量项、S07 任务分配、模型交接和当前结论。
|
||||
- `AGENT_SWARM_INDICATOR_TEST_MATRIX.zh-CN.md`:指标测试统一矩阵,逐项列出设计场景、输入、成功阈值、证据入口、验收合理性、反推闭环判定、蜂群性数值评分、L01 本机最大性能压力结果和 L02 3000 TPM 模型预算结果。
|
||||
- `SWARM_CHARACTERISTICS_ACCEPTANCE_STANDARD.zh-CN.md`:蜂群六特征验收指标、公式、场景和当前结论。
|
||||
- `ACADEMIC_STANDARD_TEST_REPORT.zh-CN.md`:S01-S10 测试场景、测试过程、测试结果、算法清单和马尔可夫过程判定。
|
||||
- `SCORING_AND_ACCEPTANCE_FORMULAS.zh-CN.md`:分数实现、公式、变量含义、S07/S09/S10 和最小闭环通过判定。
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 分数实现与验收判定公式
|
||||
|
||||
**对象**: `swarm-minimal` 最小蜂群原型
|
||||
**日期**: 2026-05-16
|
||||
**范围**: 任务分数、输出质量分、信息素分数、候选融合分数、多轮共识分数、S07/S09/S10 验收判定
|
||||
**日期**: 2026-05-17
|
||||
**范围**: 任务分数、输出质量分、信息素分数、候选融合分数、多轮共识分数、L01 本机压力、L02 3000 TPM、S07/S09/S10 验收判定
|
||||
|
||||
## 1. 分数层级
|
||||
|
||||
@@ -19,6 +19,23 @@
|
||||
|
||||
因此,最终不是“一个高分就通过”,而是“质量门、分数门、状态证据、artifact 证据、共识门同时通过”。
|
||||
|
||||
所有指标的设计场景和成功阈值统一见 `AGENT_SWARM_INDICATOR_TEST_MATRIX.zh-CN.md`。本文件只解释“分数如何算”和“公式如何判定”,不再用自然语言替代阈值。
|
||||
|
||||
## 1.1 指标成功值速查
|
||||
|
||||
| 指标组 | 成功值 |
|
||||
| --- | --- |
|
||||
| 输出质量 | `Q >= 0.72` 且 critical checks 全通过 |
|
||||
| 风险输出 | 拒答、角色边界、偏题或质量失败时 `task.score = 0.12` |
|
||||
| 最终 STEP-07 | 质量通过后 `task.score = 1.0` |
|
||||
| S07 live 收敛 | 7 个任务完成、14 项 checks 全 PASS、`accepted_score >= 0.75`、共识 `round_count >= 2` |
|
||||
| S09 候选融合 | `min_score = 0.5`,低分噪声必须被过滤 |
|
||||
| S09/S07 共识 | S07 `threshold=0.7,min_margin=0.25`;S09 `threshold=0.7,min_margin=0.2` |
|
||||
| S10 六特征 | F01-F06 全部为 true |
|
||||
| L01 本机压力 | 128 Agent、131072 任务,失败 `0`,重复 claim `0` |
|
||||
| L02 3000 TPM | 单分钟 token `<=3000`,总预留 token `=3000`,预算利用率 `1.0` |
|
||||
| 蜂群性数值 | `swarmness_score >= 75` 才能说最小蜂群成立;当前为 `100` |
|
||||
|
||||
## 2. 输出质量原始分
|
||||
|
||||
每个质量检查项记为:
|
||||
@@ -347,8 +364,6 @@ questioning_consensus_pass =
|
||||
∧ every_round_has_revisions
|
||||
```
|
||||
|
||||
## 10. 总体验收公式
|
||||
|
||||
## 10. S10 蜂群六特征通过公式
|
||||
|
||||
S10 把蜂群判定收敛为六个一级指标:
|
||||
@@ -421,7 +436,129 @@ implicit_collaboration_pass =
|
||||
∧ final_pheromone_high > final_pheromone_medium
|
||||
```
|
||||
|
||||
## 11. 总体验收公式
|
||||
## 11. L01 / L02 本机规模和模型预算公式
|
||||
|
||||
L01 本机最大性能压力通过条件:
|
||||
|
||||
```text
|
||||
L01_PASS =
|
||||
worker_processes = logical_cpus
|
||||
∧ completed_tasks = total_tasks
|
||||
∧ failed_tasks = 0
|
||||
∧ duplicate_claims = ∅
|
||||
∧ participating_agents = total_agents
|
||||
∧ converged_shards = worker_processes
|
||||
```
|
||||
|
||||
L02 3000 TPM 预算通过条件:
|
||||
|
||||
```text
|
||||
tokens_by_minute_m = 第 m 个模拟分钟窗口内预留 token 总量
|
||||
```
|
||||
|
||||
```text
|
||||
L02_PASS =
|
||||
target_tpm = 3000
|
||||
∧ max_m(tokens_by_minute_m) <= 3000
|
||||
∧ total_reserved_tokens = task_count × tokens_per_task = 3000
|
||||
∧ budget_utilization = total_reserved_tokens / (simulated_minutes × target_tpm) = 1.0
|
||||
∧ completed_tasks = task_count
|
||||
∧ failed_tasks = 0
|
||||
∧ duplicate_claims = ∅
|
||||
∧ participating_agents = agent_count
|
||||
∧ converged = true
|
||||
```
|
||||
|
||||
解释:
|
||||
|
||||
- L01 验证本机并发 claim / 执行 / 收敛在大任务量下不崩。
|
||||
- L02 验证模型预算调度不会因为多 Agent 并发而冲破 3000 TPM;调度思想参考 token bucket / rate policing,项目中实现为离散分钟窗口 ledger。
|
||||
- L02 使用本地虚拟 ledger,不调用真实模型供应商;真实 live 限流仍需要 NewAPI 网关的请求 token、返回 token、429 和费用归因证据。
|
||||
|
||||
L02 参数换算:
|
||||
|
||||
```text
|
||||
target_tpm = 3000
|
||||
tokens_per_task = 50
|
||||
task_count = target_tpm / tokens_per_task = 60
|
||||
total_token_demand = task_count × tokens_per_task = 3000
|
||||
simulated_minutes = ceil(total_token_demand / target_tpm) = 1
|
||||
budget_utilization = total_reserved_tokens / (simulated_minutes × target_tpm) = 1.0
|
||||
```
|
||||
|
||||
## 12. 蜂群性数值评分公式
|
||||
|
||||
核心蜂群性只看 F01-F06:
|
||||
|
||||
```text
|
||||
swarmness_score =
|
||||
100 × (10F01 + 10F02 + 10F03 + 10F04 + 10F05 + 10F06) / 60
|
||||
```
|
||||
|
||||
其中:
|
||||
|
||||
```text
|
||||
F_i ∈ {0, 1}
|
||||
```
|
||||
|
||||
最小合规评分:
|
||||
|
||||
```text
|
||||
minimal_compliance_score =
|
||||
10F01 + 10F02 + 10F03 + 10F04 + 10F05 + 10F06
|
||||
+ 10S07
|
||||
+ 5S08
|
||||
+ 10S09
|
||||
+ 7L01
|
||||
+ 8L02
|
||||
```
|
||||
|
||||
总权重:
|
||||
|
||||
```text
|
||||
60 + 25 + 15 = 100
|
||||
```
|
||||
|
||||
当前实测代入:
|
||||
|
||||
```text
|
||||
F01=F02=F03=F04=F05=F06=1
|
||||
S07=S08=S09=L01=L02=1
|
||||
|
||||
swarmness_score = 100
|
||||
minimal_compliance_score = 100
|
||||
```
|
||||
|
||||
分数等级:
|
||||
|
||||
```text
|
||||
score < 60 -> 不满足蜂群
|
||||
60 <= score < 75 -> 部分蜂群,不可验收
|
||||
75 <= score < 85 -> 最小可验收蜂群
|
||||
85 <= score < 95 -> 合规蜂群原型
|
||||
score >= 95 -> 极强本地最小蜂群合规
|
||||
```
|
||||
|
||||
硬上限:
|
||||
|
||||
```text
|
||||
if any(F01..F06) = 0:
|
||||
minimal_compliance_score <= 59
|
||||
```
|
||||
|
||||
```text
|
||||
if any(S07,S08,S09) = 0:
|
||||
minimal_compliance_score <= 84
|
||||
```
|
||||
|
||||
```text
|
||||
if any(L01,L02) = 0:
|
||||
minimal_compliance_score <= 94
|
||||
```
|
||||
|
||||
这意味着核心蜂群特征失败时,不能通过补跑文档、单测或压力测试把总分刷到合格。
|
||||
|
||||
## 13. 总体验收公式
|
||||
|
||||
当前仓库最小闭环验收可以概括为:
|
||||
|
||||
@@ -440,6 +577,15 @@ MINIMAL_CLOSED_LOOP_PASS =
|
||||
∧ S10_swarm_six_characteristics_acceptance
|
||||
```
|
||||
|
||||
若声明“本机压力与 3000 TPM 量级也通过”,还需要:
|
||||
|
||||
```text
|
||||
LOCAL_SCALE_AND_BUDGET_PASS =
|
||||
MINIMAL_CLOSED_LOOP_PASS
|
||||
∧ L01_PASS
|
||||
∧ L02_PASS
|
||||
```
|
||||
|
||||
最终解释:
|
||||
|
||||
```text
|
||||
@@ -452,7 +598,7 @@ score 高 ≠ 自动 PASS
|
||||
质量门 + 分数门 + 信息素证据 + 状态证据 + artifact 证据 + 多轮共识门 全部通过 = PASS
|
||||
```
|
||||
|
||||
## 12. 公式对应实现位置
|
||||
## 14. 公式对应实现位置
|
||||
|
||||
| 公式 / 机制 | 实现位置 |
|
||||
| --- | --- |
|
||||
@@ -466,3 +612,6 @@ score 高 ≠ 自动 PASS
|
||||
| S07 标准矩阵检查 | `examples/run_continuous_reasoning_acceptance.py::collect_report` |
|
||||
| S09 下一阶段边界检查 | `examples/run_next_boundary_acceptance.py` |
|
||||
| S10 蜂群六特征检查 | `examples/run_swarm_characteristics_acceptance.py` |
|
||||
| L01 本机最大性能压力 | `examples/run_large_scale_stress_acceptance.py` |
|
||||
| L02 3000 TPM 预算调度 | `examples/run_tpm_budget_acceptance.py` |
|
||||
| 蜂群性数值评分 | `swarm_minimal/acceptance_scoring.py` / `examples/run_swarm_compliance_score.py` |
|
||||
|
||||
@@ -21,7 +21,20 @@ SWARM_PASS =
|
||||
|
||||
当前验收限定在本地最小蜂群原型,证明 Agent 层共享环境、自主 claim、信息素和收敛行为已经具备六特征。它不等同于“完全无协调器的生产级分布式 runtime”,真实 Kubernetes worker runtime 仍是下一阶段。
|
||||
|
||||
## 2. F01 去中心化
|
||||
六特征的完整指标矩阵见 `AGENT_SWARM_INDICATOR_TEST_MATRIX.zh-CN.md`。本文件保留六特征的定义、场景、公式和当前结论。
|
||||
|
||||
## 2. 六特征场景与成功值总览
|
||||
|
||||
| ID | 特征 | 设计场景 | 成功值 |
|
||||
| --- | --- | --- | --- |
|
||||
| F01 | 去中心化 | 4 个 Agent 自主 claim 8 个任务 | `participating_agents >= 4`;`duplicate_claims = 0`;`control_keys = 0`;`decision_records = 8` |
|
||||
| F02 | 自组织 | 5 个局部信号写入 shared_state,初始不预置 dominant cluster | `dominant_cluster = api`;`local_interaction_count >= 5`;`cluster:api:count = 3` |
|
||||
| F03 | 涌现性 | `beta` 两个弱信号累计超过单个 `gamma:0.45` 强信号 | `candidate:beta:score = 0.67`;`accepted_score > 0.45`;最终接受 `beta` |
|
||||
| F04 | 鲁棒性 | 1 个 Agent 故意失败,2 个 backup Agent 继续完成 | `failed_tasks = 1`;`completed_tasks >= 2`;存在负反馈;`run_status = converged` |
|
||||
| F05 | 可扩展性 | 分别用 `3/5/7` 个 Agent 跑同一 shared task pool | 对每个 `n`:`completed_tasks = 2n`;`failed_tasks = 0`;`duplicate_claims = 0`;`participating_agents = n` |
|
||||
| F06 | 隐式协作 | 3 个任务按信息素 `0.9/0.4/0.1` 排序,无直接消息 | `direct_message_keys = 0`;`first_claim = high-signal`;存在 `environment:trail`;高信号最终信息素仍高于中信号 |
|
||||
|
||||
## 3. F01 去中心化
|
||||
|
||||
定义:
|
||||
|
||||
@@ -55,7 +68,7 @@ tests.test_swarm_characteristics_acceptance
|
||||
.test_decentralization_has_no_single_agent_control_node
|
||||
```
|
||||
|
||||
## 3. F02 自组织
|
||||
## 4. F02 自组织
|
||||
|
||||
定义:
|
||||
|
||||
@@ -88,7 +101,7 @@ tests.test_swarm_characteristics_acceptance
|
||||
.test_self_organization_forms_order_from_local_interactions
|
||||
```
|
||||
|
||||
## 4. F03 涌现性
|
||||
## 5. F03 涌现性
|
||||
|
||||
定义:
|
||||
|
||||
@@ -119,7 +132,7 @@ tests.test_swarm_characteristics_acceptance
|
||||
.test_emergence_global_result_exceeds_single_local_signal
|
||||
```
|
||||
|
||||
## 5. F04 鲁棒性
|
||||
## 6. F04 鲁棒性
|
||||
|
||||
定义:
|
||||
|
||||
@@ -153,7 +166,7 @@ tests.test_swarm_characteristics_acceptance
|
||||
.test_robustness_single_agent_failure_does_not_stop_convergence
|
||||
```
|
||||
|
||||
## 6. F05 可扩展性
|
||||
## 7. F05 可扩展性
|
||||
|
||||
定义:
|
||||
|
||||
@@ -191,7 +204,7 @@ tests.test_swarm_characteristics_acceptance
|
||||
.test_scalability_three_five_seven_agents_keep_same_architecture
|
||||
```
|
||||
|
||||
## 7. F06 隐式协作
|
||||
## 8. F06 隐式协作
|
||||
|
||||
定义:
|
||||
|
||||
@@ -225,7 +238,7 @@ tests.test_swarm_characteristics_acceptance
|
||||
.test_implicit_collaboration_uses_environment_not_direct_messages
|
||||
```
|
||||
|
||||
## 8. 标准矩阵接入
|
||||
## 9. 标准矩阵接入
|
||||
|
||||
六特征验收进入两个总入口:
|
||||
|
||||
@@ -241,7 +254,7 @@ python3 -B -m unittest tests.test_swarm_characteristics_acceptance
|
||||
python3 -u -B examples/run_swarm_characteristics_acceptance.py
|
||||
```
|
||||
|
||||
## 9. 当前结论
|
||||
## 10. 当前结论
|
||||
|
||||
当前代码层已经具备六特征的本地最小验收:
|
||||
|
||||
|
||||
@@ -938,6 +938,8 @@ NATS 不是最终事实源。关键事件必须落 PostgreSQL。
|
||||
|
||||
蜂群指标不能只看 Pod 是否 Running。必须看协作是否产生价值。
|
||||
|
||||
当前 `swarm-minimal` 的可执行指标阈值以 `AGENT_SWARM_INDICATOR_TEST_MATRIX.zh-CN.md` 为准。本节描述目标平台指标体系,并补充当前最小原型已经采用的成功值,避免把“可观测”误读成“已达标”。
|
||||
|
||||
### 15.1 运行效率
|
||||
|
||||
| 指标 | 含义 |
|
||||
@@ -981,6 +983,18 @@ NATS 不是最终事实源。关键事件必须落 PostgreSQL。
|
||||
| 明文密钥泄露次数 | 必须为 0 |
|
||||
| 未授权资源访问次数 | 必须为 0 |
|
||||
|
||||
### 15.5 当前最小原型验收阈值
|
||||
|
||||
| 指标组 | 当前最小原型成功值 |
|
||||
|---|---|
|
||||
| AQS 本地门禁 | A01-A09 全部 PASS;`unittest discover` 当前 45 项全部通过 |
|
||||
| S07 live 外部代码链 | 7 个任务完成;14 项 checks 全 PASS;`accepted_score >= 0.75`;共识轮数 `>=2` |
|
||||
| S09 扩缩容 | `3/5/7` Agent 下均满足 `completed_tasks=2n`、`failed_tasks=0`、`duplicate_claims=0` |
|
||||
| S09 候选融合 | `min_score=0.5`;保留 `quality/coverage`;过滤 `noise=0.2` |
|
||||
| S09 互相质询 | `threshold=0.7`;`min_margin=0.2`;第一轮不收敛,最后一轮收敛 |
|
||||
| S10 六特征 | F01-F06 全部 PASS;成功值见 `AGENT_SWARM_INDICATOR_TEST_MATRIX.zh-CN.md` |
|
||||
| 密钥安全 | Git、Markdown、报告、日志和 artifact 中真实长期密钥数必须为 `0` |
|
||||
|
||||
## 16. 最小验证
|
||||
|
||||
蜂群 MVP 的最小验证不是“创建 3 个 Pod”,也不是“跑完一条 workflow”。它必须证明目标驱动、动态任务、能力协作、事件回传、审批和产物闭环。
|
||||
|
||||
@@ -73,6 +73,20 @@ CHECKS = [
|
||||
"command": [sys.executable, "-u", "-B", "examples/run_swarm_characteristics_acceptance.py"],
|
||||
"parse_json": True,
|
||||
},
|
||||
{
|
||||
"id": "A08",
|
||||
"name": "tpm_budget_acceptance",
|
||||
"layer": "model-budget",
|
||||
"command": [sys.executable, "-u", "-B", "examples/run_tpm_budget_acceptance.py"],
|
||||
"parse_json": True,
|
||||
},
|
||||
{
|
||||
"id": "A09",
|
||||
"name": "swarm_compliance_score",
|
||||
"layer": "scoring",
|
||||
"command": [sys.executable, "-u", "-B", "examples/run_swarm_compliance_score.py"],
|
||||
"parse_json": True,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@@ -104,7 +118,7 @@ def main() -> None:
|
||||
"conclusion": markov.conclusion,
|
||||
},
|
||||
"pass_condition": {
|
||||
"local_academic_gate": "all A01-A07 checks pass",
|
||||
"local_academic_gate": "all A01-A09 checks pass",
|
||||
"full_standard_gate": "local_academic_gate plus S07 live external GitHub code scenario and S08/S09/S10 audits",
|
||||
},
|
||||
}
|
||||
@@ -170,6 +184,22 @@ def summarize_json(value: dict[str, object]) -> dict[str, object]:
|
||||
summary["standard"] = value["standard"]
|
||||
if "overall_normalized_score" in value:
|
||||
summary["overall_normalized_score"] = value["overall_normalized_score"]
|
||||
for key in ("swarmness_score", "minimal_compliance_score", "tier"):
|
||||
if key in value:
|
||||
summary[key] = value[key]
|
||||
if "summary" in value and isinstance(value["summary"], dict):
|
||||
for key in (
|
||||
"completed_tasks",
|
||||
"failed_tasks",
|
||||
"duplicate_claims",
|
||||
"participating_agents",
|
||||
"total_reserved_tokens",
|
||||
"max_tokens_in_any_minute",
|
||||
"budget_utilization",
|
||||
"converged",
|
||||
):
|
||||
if key in value["summary"]:
|
||||
summary[key] = value["summary"][key]
|
||||
if "features" in value and isinstance(value["features"], list):
|
||||
summary["feature_count"] = len(value["features"])
|
||||
if "accepted_candidate" in value:
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from concurrent.futures import ProcessPoolExecutor, as_completed
|
||||
from dataclasses import asdict, dataclass
|
||||
from pathlib import Path
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from time import perf_counter
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
from swarm_minimal.core import Agent, InMemorySwarmStore, SwarmCoordinator, Task, TaskStatus # noqa: E402
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class StressConfig:
|
||||
logical_cpus: int
|
||||
worker_processes: int
|
||||
agents_per_process: int
|
||||
tasks_per_process: int
|
||||
cpu_cycles_per_task: int
|
||||
timeout_seconds: int
|
||||
|
||||
@property
|
||||
def total_agents(self) -> int:
|
||||
return self.worker_processes * self.agents_per_process
|
||||
|
||||
@property
|
||||
def total_tasks(self) -> int:
|
||||
return self.worker_processes * self.tasks_per_process
|
||||
|
||||
|
||||
def main() -> None:
|
||||
config = build_config()
|
||||
started = perf_counter()
|
||||
shard_results: list[dict[str, object]] = []
|
||||
failures: list[str] = []
|
||||
|
||||
with ProcessPoolExecutor(max_workers=config.worker_processes) as executor:
|
||||
futures = [
|
||||
executor.submit(
|
||||
run_stress_shard,
|
||||
shard_index,
|
||||
config.agents_per_process,
|
||||
config.tasks_per_process,
|
||||
config.cpu_cycles_per_task,
|
||||
)
|
||||
for shard_index in range(config.worker_processes)
|
||||
]
|
||||
for future in as_completed(futures, timeout=config.timeout_seconds):
|
||||
try:
|
||||
shard_results.append(future.result())
|
||||
except Exception as exc: # pragma: no cover - defensive failure reporting.
|
||||
failures.append(str(exc))
|
||||
|
||||
duration = perf_counter() - started
|
||||
completed_tasks = sum(int(item["completed_tasks"]) for item in shard_results)
|
||||
failed_tasks = sum(int(item["failed_tasks"]) for item in shard_results)
|
||||
duplicate_claims = sum(int(item["duplicate_claim_count"]) for item in shard_results)
|
||||
participating_agents = sum(int(item["participating_agents"]) for item in shard_results)
|
||||
converged_shards = sum(1 for item in shard_results if item["converged"])
|
||||
status = (
|
||||
"PASS"
|
||||
if not failures
|
||||
and len(shard_results) == config.worker_processes
|
||||
and completed_tasks == config.total_tasks
|
||||
and failed_tasks == 0
|
||||
and duplicate_claims == 0
|
||||
and participating_agents == config.total_agents
|
||||
and converged_shards == config.worker_processes
|
||||
else "FAIL"
|
||||
)
|
||||
report = {
|
||||
"standard": "local-large-scale-stress-v1",
|
||||
"status": status,
|
||||
"scope_note": (
|
||||
"This is a bounded local maximum-performance stress run. It uses all detected logical CPUs by default "
|
||||
"and validates in-memory autonomous claim, convergence and duplicate-claim safety. It is not a "
|
||||
"production Kubernetes runtime benchmark."
|
||||
),
|
||||
"config": asdict(config),
|
||||
"success_thresholds": {
|
||||
"worker_processes": "equals detected logical_cpus unless overridden",
|
||||
"completed_tasks": config.total_tasks,
|
||||
"failed_tasks": 0,
|
||||
"duplicate_claims": 0,
|
||||
"participating_agents": config.total_agents,
|
||||
"converged_shards": config.worker_processes,
|
||||
},
|
||||
"summary": {
|
||||
"duration_seconds": round(duration, 4),
|
||||
"tasks_per_second": round(completed_tasks / duration, 2) if duration else completed_tasks,
|
||||
"completed_tasks": completed_tasks,
|
||||
"failed_tasks": failed_tasks,
|
||||
"duplicate_claims": duplicate_claims,
|
||||
"participating_agents": participating_agents,
|
||||
"converged_shards": converged_shards,
|
||||
"failures": failures,
|
||||
},
|
||||
"shards": sorted(shard_results, key=lambda item: int(item["shard_index"])),
|
||||
}
|
||||
print(json.dumps(report, ensure_ascii=False, indent=2))
|
||||
if status != "PASS":
|
||||
raise SystemExit(1)
|
||||
|
||||
|
||||
def build_config() -> StressConfig:
|
||||
logical_cpus = max(1, os.cpu_count() or 1)
|
||||
worker_processes = read_positive_int("SWARM_STRESS_PROCESSES", logical_cpus)
|
||||
agents_per_process = read_positive_int("SWARM_STRESS_AGENTS_PER_PROCESS", max(4, logical_cpus))
|
||||
tasks_per_process = read_positive_int("SWARM_STRESS_TASKS_PER_PROCESS", max(1024, logical_cpus * 256))
|
||||
cpu_cycles_per_task = read_positive_int("SWARM_STRESS_CPU_CYCLES", 64)
|
||||
timeout_seconds = read_positive_int("SWARM_STRESS_TIMEOUT_SECONDS", 300)
|
||||
return StressConfig(
|
||||
logical_cpus=logical_cpus,
|
||||
worker_processes=worker_processes,
|
||||
agents_per_process=agents_per_process,
|
||||
tasks_per_process=tasks_per_process,
|
||||
cpu_cycles_per_task=cpu_cycles_per_task,
|
||||
timeout_seconds=timeout_seconds,
|
||||
)
|
||||
|
||||
|
||||
def read_positive_int(name: str, default: int) -> int:
|
||||
raw = os.environ.get(name)
|
||||
if raw is None:
|
||||
return default
|
||||
try:
|
||||
value = int(raw)
|
||||
except ValueError as exc:
|
||||
raise ValueError(f"{name} must be an integer") from exc
|
||||
if value <= 0:
|
||||
raise ValueError(f"{name} must be positive")
|
||||
return value
|
||||
|
||||
|
||||
def run_stress_shard(
|
||||
shard_index: int,
|
||||
agents_per_process: int,
|
||||
tasks_per_process: int,
|
||||
cpu_cycles_per_task: int,
|
||||
) -> dict[str, object]:
|
||||
store = InMemorySwarmStore()
|
||||
run_id = f"large-stress-{os.getpid()}-{shard_index}"
|
||||
store.shared_state[f"run:{run_id}:goal"] = "large scale autonomous claim stress"
|
||||
store.shared_state[f"run:{run_id}:status"] = "running"
|
||||
for task_index in range(tasks_per_process):
|
||||
store.add_task(Task(kind="stress", input=f"shard={shard_index}; task={task_index}"))
|
||||
|
||||
agents = [
|
||||
Agent(
|
||||
id=f"stress-agent-{shard_index}-{agent_index}",
|
||||
capability="stress",
|
||||
run=lambda task, shared_state, agent_index=agent_index: run_cpu_bound_task(
|
||||
task.input,
|
||||
agent_index,
|
||||
cpu_cycles_per_task,
|
||||
),
|
||||
)
|
||||
for agent_index in range(agents_per_process)
|
||||
]
|
||||
|
||||
started = perf_counter()
|
||||
report = SwarmCoordinator(store=store, agents=agents).run_autonomous_until_converged(
|
||||
run_id,
|
||||
max_workers=agents_per_process,
|
||||
)
|
||||
duration = perf_counter() - started
|
||||
participating_agents = {event.agent_id for event in report.claim_events}
|
||||
all_done = all(task.status == TaskStatus.DONE for task in store.tasks.values())
|
||||
|
||||
return {
|
||||
"shard_index": shard_index,
|
||||
"process_id": os.getpid(),
|
||||
"agent_count": agents_per_process,
|
||||
"task_count": tasks_per_process,
|
||||
"completed_tasks": report.completed_tasks,
|
||||
"failed_tasks": report.failed_tasks,
|
||||
"duplicate_claim_count": len(report.duplicate_claims),
|
||||
"participating_agents": len(participating_agents),
|
||||
"converged": report.converged,
|
||||
"all_tasks_done": all_done,
|
||||
"duration_seconds": round(duration, 4),
|
||||
"tasks_per_second": round(report.completed_tasks / duration, 2) if duration else report.completed_tasks,
|
||||
"accepted_score": report.result.accepted_score,
|
||||
"observation_count": len(report.result.observations),
|
||||
}
|
||||
|
||||
|
||||
def run_cpu_bound_task(task_input: str, agent_index: int, cpu_cycles_per_task: int) -> tuple[str, float]:
|
||||
payload = f"{task_input}; agent={agent_index}".encode()
|
||||
for _ in range(cpu_cycles_per_task):
|
||||
payload = hashlib.blake2b(payload, digest_size=16).digest()
|
||||
checksum = int.from_bytes(payload[:4], "big")
|
||||
score = 0.5 + (checksum % 5000) / 10000
|
||||
return f"agent={agent_index}; checksum={checksum}; stress=ok", score
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,33 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
import json
|
||||
import sys
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
from swarm_minimal.acceptance_scoring import current_minimal_swarm_score # noqa: E402
|
||||
|
||||
|
||||
def main() -> None:
|
||||
report = current_minimal_swarm_score().to_dict()
|
||||
report["scope_note"] = (
|
||||
"This numeric score is for the configured local minimal swarm acceptance standard. "
|
||||
"It is not a production Kubernetes/runtime certification score."
|
||||
)
|
||||
report["pass_lines"] = {
|
||||
"not_swarm": "< 60 or any core swarm feature fails",
|
||||
"partial_swarm": "60-74",
|
||||
"minimal_acceptance": "75-84",
|
||||
"compliant_prototype": "85-94",
|
||||
"highly_compliant_local_minimal_swarm": ">= 95 with no hard cap",
|
||||
}
|
||||
print(json.dumps(report, ensure_ascii=False, indent=2))
|
||||
if report["status"] != "PASS":
|
||||
raise SystemExit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,221 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import asdict, dataclass
|
||||
from pathlib import Path
|
||||
from threading import RLock
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from time import perf_counter
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
from swarm_minimal.core import Agent, InMemorySwarmStore, SwarmCoordinator, Task, TaskStatus # noqa: E402
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TpmConfig:
|
||||
target_tpm: int
|
||||
agent_count: int
|
||||
task_count: int
|
||||
tokens_per_task: int
|
||||
|
||||
@property
|
||||
def total_token_demand(self) -> int:
|
||||
return self.task_count * self.tokens_per_task
|
||||
|
||||
@property
|
||||
def expected_minutes(self) -> int:
|
||||
return max(1, (self.total_token_demand + self.target_tpm - 1) // self.target_tpm)
|
||||
|
||||
|
||||
class TokenMinuteLedger:
|
||||
"""Thread-safe virtual TPM ledger.
|
||||
|
||||
The ledger does not sleep. It simulates provider-side minute windows and
|
||||
verifies that concurrent Agent claims are scheduled without exceeding the
|
||||
configured token budget.
|
||||
"""
|
||||
|
||||
def __init__(self, target_tpm: int) -> None:
|
||||
if target_tpm <= 0:
|
||||
raise ValueError("target_tpm must be positive")
|
||||
self.target_tpm = target_tpm
|
||||
self._lock = RLock()
|
||||
self._current_minute = 0
|
||||
self._tokens_by_minute: dict[int, int] = {0: 0}
|
||||
self._reservations: dict[str, tuple[int, int]] = {}
|
||||
|
||||
def reserve(self, task_id: str, token_cost: int) -> tuple[int, int]:
|
||||
if token_cost <= 0:
|
||||
raise ValueError("token_cost must be positive")
|
||||
if token_cost > self.target_tpm:
|
||||
raise ValueError("single task token_cost cannot exceed target_tpm")
|
||||
|
||||
with self._lock:
|
||||
minute = self._current_minute
|
||||
used = self._tokens_by_minute.get(minute, 0)
|
||||
if used + token_cost > self.target_tpm:
|
||||
minute += 1
|
||||
self._current_minute = minute
|
||||
used = 0
|
||||
|
||||
new_total = used + token_cost
|
||||
self._tokens_by_minute[minute] = new_total
|
||||
self._reservations[task_id] = (minute, token_cost)
|
||||
return minute, new_total
|
||||
|
||||
def snapshot(self) -> tuple[dict[int, int], dict[str, tuple[int, int]]]:
|
||||
with self._lock:
|
||||
return dict(self._tokens_by_minute), dict(self._reservations)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
report = run_acceptance(build_config())
|
||||
print(json.dumps(report, ensure_ascii=False, indent=2))
|
||||
if report["status"] != "PASS":
|
||||
raise SystemExit(1)
|
||||
|
||||
|
||||
def build_config() -> TpmConfig:
|
||||
logical_cpus = max(1, os.cpu_count() or 1)
|
||||
target_tpm = read_positive_int("SWARM_TPM_TARGET", 3000)
|
||||
tokens_per_task = read_positive_int("SWARM_TPM_TOKENS_PER_TASK", 50)
|
||||
agent_count = read_positive_int("SWARM_TPM_AGENT_COUNT", min(8, logical_cpus))
|
||||
task_count = read_positive_int("SWARM_TPM_TASKS", target_tpm // tokens_per_task)
|
||||
return TpmConfig(
|
||||
target_tpm=target_tpm,
|
||||
agent_count=agent_count,
|
||||
task_count=task_count,
|
||||
tokens_per_task=tokens_per_task,
|
||||
)
|
||||
|
||||
|
||||
def run_acceptance(config: TpmConfig) -> dict[str, object]:
|
||||
if config.tokens_per_task > config.target_tpm:
|
||||
raise ValueError("tokens_per_task cannot exceed target_tpm")
|
||||
|
||||
store = InMemorySwarmStore()
|
||||
ledger = TokenMinuteLedger(config.target_tpm)
|
||||
run_id = "tpm-budget-3000"
|
||||
store.shared_state[f"run:{run_id}:goal"] = "validate swarm scheduling under a 3000 TPM model budget"
|
||||
store.shared_state[f"run:{run_id}:status"] = "running"
|
||||
store.shared_state[f"run:{run_id}:target_tpm"] = str(config.target_tpm)
|
||||
|
||||
for task_index in range(config.task_count):
|
||||
store.add_task(Task(kind="model_budget", input=f"task={task_index}; tokens={config.tokens_per_task}"))
|
||||
|
||||
agents = [build_budget_agent(index, ledger) for index in range(config.agent_count)]
|
||||
|
||||
started = perf_counter()
|
||||
result = SwarmCoordinator(store=store, agents=agents).run_autonomous_until_converged(
|
||||
run_id,
|
||||
max_workers=config.agent_count,
|
||||
)
|
||||
duration = perf_counter() - started
|
||||
|
||||
tokens_by_minute, reservations = ledger.snapshot()
|
||||
over_budget_windows = {
|
||||
minute: tokens for minute, tokens in tokens_by_minute.items() if tokens > config.target_tpm
|
||||
}
|
||||
total_reserved_tokens = sum(tokens for _, tokens in reservations.values())
|
||||
participating_agents = {event.agent_id for event in result.claim_events}
|
||||
all_done = all(task.status == TaskStatus.DONE for task in store.tasks.values())
|
||||
simulated_minutes = len(tokens_by_minute)
|
||||
utilization = (
|
||||
total_reserved_tokens / (simulated_minutes * config.target_tpm)
|
||||
if simulated_minutes
|
||||
else 0.0
|
||||
)
|
||||
|
||||
status = (
|
||||
"PASS"
|
||||
if result.completed_tasks == config.task_count
|
||||
and result.failed_tasks == 0
|
||||
and not result.duplicate_claims
|
||||
and len(participating_agents) == config.agent_count
|
||||
and all_done
|
||||
and not over_budget_windows
|
||||
and total_reserved_tokens == config.total_token_demand
|
||||
and simulated_minutes == config.expected_minutes
|
||||
else "FAIL"
|
||||
)
|
||||
|
||||
return {
|
||||
"standard": "token-budget-tpm-v1",
|
||||
"status": status,
|
||||
"scope_note": (
|
||||
"This is a deterministic local acceptance run for model-token scheduling. "
|
||||
"It validates the Agent claim loop against a virtual TPM ledger and does not call a live model provider."
|
||||
),
|
||||
"config": asdict(config),
|
||||
"success_thresholds": {
|
||||
"target_tpm": config.target_tpm,
|
||||
"max_tokens_per_simulated_minute": f"<= {config.target_tpm}",
|
||||
"total_reserved_tokens": config.total_token_demand,
|
||||
"simulated_minutes": config.expected_minutes,
|
||||
"completed_tasks": config.task_count,
|
||||
"failed_tasks": 0,
|
||||
"duplicate_claims": 0,
|
||||
"participating_agents": config.agent_count,
|
||||
},
|
||||
"summary": {
|
||||
"duration_seconds": round(duration, 4),
|
||||
"completed_tasks": result.completed_tasks,
|
||||
"failed_tasks": result.failed_tasks,
|
||||
"duplicate_claims": len(result.duplicate_claims),
|
||||
"participating_agents": len(participating_agents),
|
||||
"all_tasks_done": all_done,
|
||||
"total_reserved_tokens": total_reserved_tokens,
|
||||
"simulated_minutes": simulated_minutes,
|
||||
"max_tokens_in_any_minute": max(tokens_by_minute.values()) if tokens_by_minute else 0,
|
||||
"budget_utilization": round(utilization, 4),
|
||||
"over_budget_windows": over_budget_windows,
|
||||
"converged": result.converged,
|
||||
},
|
||||
"tokens_by_minute": {str(minute): tokens for minute, tokens in sorted(tokens_by_minute.items())},
|
||||
}
|
||||
|
||||
|
||||
def build_budget_agent(agent_index: int, ledger: TokenMinuteLedger) -> Agent:
|
||||
agent_id = f"tpm-agent-{agent_index + 1}"
|
||||
|
||||
def run(task: Task, shared_state: dict[str, str]) -> tuple[str, float]:
|
||||
token_cost = parse_task_tokens(task.input)
|
||||
minute, minute_total = ledger.reserve(task.id, token_cost)
|
||||
shared_state[f"task:{task.id}:token_cost"] = str(token_cost)
|
||||
shared_state[f"task:{task.id}:scheduled_minute"] = str(minute)
|
||||
return (
|
||||
f"agent={agent_id}; token_cost={token_cost}; scheduled_minute={minute}; "
|
||||
f"minute_total={minute_total}; budget=ok",
|
||||
0.9,
|
||||
)
|
||||
|
||||
return Agent(id=agent_id, capability="model_budget", run=run)
|
||||
|
||||
|
||||
def parse_task_tokens(task_input: str) -> int:
|
||||
for part in task_input.split(";"):
|
||||
key, _, value = part.strip().partition("=")
|
||||
if key == "tokens" and value:
|
||||
return int(value)
|
||||
raise ValueError("task input must include tokens=<int>")
|
||||
|
||||
|
||||
def read_positive_int(name: str, default: int) -> int:
|
||||
raw = os.environ.get(name)
|
||||
if raw is None:
|
||||
return default
|
||||
try:
|
||||
value = int(raw)
|
||||
except ValueError as exc:
|
||||
raise ValueError(f"{name} must be an integer") from exc
|
||||
if value <= 0:
|
||||
raise ValueError(f"{name} must be positive")
|
||||
return value
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -60,6 +60,42 @@ ACADEMIC_STANDARD_SOURCES = (
|
||||
"use": "active-agent handoff and transfer_to_<agent> continuity reference",
|
||||
"url": "https://reference.langchain.com/python/langgraph-swarm/handoff/create_handoff_tool",
|
||||
},
|
||||
{
|
||||
"id": "RFC-2697",
|
||||
"name": "A Single Rate Three Color Marker",
|
||||
"use": "token-bucket style rate policing reference for TPM budget scheduling",
|
||||
"url": "https://www.rfc-editor.org/rfc/rfc2697.html",
|
||||
},
|
||||
{
|
||||
"id": "OPENAI-RATE-LIMITS",
|
||||
"name": "OpenAI API rate limit guide",
|
||||
"use": "RPM/TPM model-provider rate-limit framing; this project uses the same budget dimension locally",
|
||||
"url": "https://platform.openai.com/docs/guides/rate-limits",
|
||||
},
|
||||
{
|
||||
"id": "STIGMERGY",
|
||||
"name": "Stigmergy: from mathematical modelling to control",
|
||||
"use": "environment-mediated implicit collaboration reference",
|
||||
"url": "https://pmc.ncbi.nlm.nih.gov/articles/PMC11371424/",
|
||||
},
|
||||
{
|
||||
"id": "ANT-SYSTEM-1996",
|
||||
"name": "Ant System: Optimization by a Colony of Cooperating Agents",
|
||||
"use": "pheromone-style reinforcement and distributed agent coordination reference",
|
||||
"url": "https://iridia.ulb.ac.be/~mdorigo/Published_papers/All_Dorigo_papers/DorManCol1996tsmcb.pdf",
|
||||
},
|
||||
{
|
||||
"id": "SWARM-INTELLIGENCE-1999",
|
||||
"name": "Swarm Intelligence: From Natural to Artificial Systems",
|
||||
"use": "decentralization, self-organization and emergence framing for swarm acceptance indicators",
|
||||
"url": "https://academic.oup.com/book/40811",
|
||||
},
|
||||
{
|
||||
"id": "MDP-PUTERMAN-1994",
|
||||
"name": "Markov Decision Processes: Discrete Stochastic Dynamic Programming",
|
||||
"use": "formal boundary for saying this repo is Markov-style but not a strict MDP",
|
||||
"url": "https://books.google.com/books/about/Markov_Decision_Processes.html?id=tsiiQgAACAAJ",
|
||||
},
|
||||
{
|
||||
"id": "SWARM-SIX-FEATURES",
|
||||
"name": "Project-configured swarm characteristics",
|
||||
@@ -130,6 +166,16 @@ ALGORITHMS_USED = (
|
||||
"location": "swarm_minimal.newapi_agnet.discover_newapi_models and select_distinct_models",
|
||||
"description": "NewAPI models are discovered from compatible endpoints and de-duplicated for multi-agent tests",
|
||||
},
|
||||
{
|
||||
"name": "virtual TPM budget ledger",
|
||||
"location": "examples.run_tpm_budget_acceptance.TokenMinuteLedger",
|
||||
"description": "concurrent Agent tasks reserve model-token budget into simulated minute windows without exceeding target TPM",
|
||||
},
|
||||
{
|
||||
"name": "weighted swarm compliance scoring",
|
||||
"location": "swarm_minimal.acceptance_scoring.score_items",
|
||||
"description": "core swarm features, support evidence and scale/budget evidence are converted into a capped 0-100 acceptance score",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -154,6 +200,7 @@ def assess_markov_process_fit() -> MarkovProcessAssessment:
|
||||
"observations already emitted",
|
||||
"agent policy functions and current round index for consensus",
|
||||
"claim events, fused candidate source ids and questioning round state",
|
||||
"token budget ledger state for TPM-limited scheduling scenarios",
|
||||
),
|
||||
limiting_factors=(
|
||||
"no transition probability kernel P(s_next | s_current)",
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
"""Acceptance scoring for the minimal swarm prototype."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import asdict, dataclass
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ScoreItem:
|
||||
id: str
|
||||
name: str
|
||||
weight: float
|
||||
passed: bool
|
||||
actual: str
|
||||
threshold: str
|
||||
group: str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ScoreReport:
|
||||
standard: str
|
||||
status: str
|
||||
swarmness_score: float
|
||||
minimal_compliance_score: float
|
||||
tier: str
|
||||
hard_caps: tuple[str, ...]
|
||||
items: tuple[ScoreItem, ...]
|
||||
|
||||
def to_dict(self) -> dict[str, object]:
|
||||
return {
|
||||
"standard": self.standard,
|
||||
"status": self.status,
|
||||
"swarmness_score": self.swarmness_score,
|
||||
"minimal_compliance_score": self.minimal_compliance_score,
|
||||
"tier": self.tier,
|
||||
"hard_caps": list(self.hard_caps),
|
||||
"items": [asdict(item) for item in self.items],
|
||||
}
|
||||
|
||||
|
||||
def current_minimal_swarm_score() -> ScoreReport:
|
||||
"""Return the current evidence-backed local minimal swarm score.
|
||||
|
||||
This score is intentionally scoped. It answers whether the current repo
|
||||
satisfies the configured minimal swarm acceptance standard, not whether it
|
||||
is a production distributed runtime certification.
|
||||
"""
|
||||
|
||||
return score_items(
|
||||
(
|
||||
ScoreItem(
|
||||
"F01",
|
||||
"decentralization",
|
||||
10,
|
||||
True,
|
||||
"participating_agents=4, duplicate_claims=0, control_keys=0",
|
||||
"participating_agents>=4 and duplicate_claims=0 and control_keys=0",
|
||||
"core_swarm",
|
||||
),
|
||||
ScoreItem(
|
||||
"F02",
|
||||
"self_organization",
|
||||
10,
|
||||
True,
|
||||
"local_interaction_count=5, dominant_cluster=api, preseeded_global_plan=false",
|
||||
"local_interaction_count>=5 and no preseeded global plan",
|
||||
"core_swarm",
|
||||
),
|
||||
ScoreItem(
|
||||
"F03",
|
||||
"emergence",
|
||||
10,
|
||||
True,
|
||||
"accepted_candidate=beta, group_score=0.67, best_single_signal=0.45",
|
||||
"global group score > best single local signal",
|
||||
"core_swarm",
|
||||
),
|
||||
ScoreItem(
|
||||
"F04",
|
||||
"robustness",
|
||||
10,
|
||||
True,
|
||||
"failed_tasks=1, completed_tasks>=2, run_status=converged",
|
||||
"single Agent failure isolated and run still converges",
|
||||
"core_swarm",
|
||||
),
|
||||
ScoreItem(
|
||||
"F05",
|
||||
"scalability",
|
||||
10,
|
||||
True,
|
||||
"agent_counts=3/5/7, completed_tasks=2n, duplicate_claims=0",
|
||||
"3/5/7 Agent counts keep same architecture with no duplicate claim",
|
||||
"core_swarm",
|
||||
),
|
||||
ScoreItem(
|
||||
"F06",
|
||||
"implicit_collaboration",
|
||||
10,
|
||||
True,
|
||||
"direct_message_keys=0, first_claim=high-signal, environment_trail=true",
|
||||
"coordination through environment, not direct messages",
|
||||
"core_swarm",
|
||||
),
|
||||
ScoreItem(
|
||||
"S07",
|
||||
"external_complex_task_handoff",
|
||||
10,
|
||||
True,
|
||||
"7 live FastAPI steps, 14 checks pass, round_count>=2",
|
||||
"external target, chain handoff, quality gate and consensus all pass",
|
||||
"support",
|
||||
),
|
||||
ScoreItem(
|
||||
"S08",
|
||||
"audit_and_secret_safety",
|
||||
5,
|
||||
True,
|
||||
"model I/O report audit pass, obvious secret hits=0",
|
||||
"human-auditable report and no obvious secret pattern",
|
||||
"support",
|
||||
),
|
||||
ScoreItem(
|
||||
"S09",
|
||||
"fusion_questioning_consensus",
|
||||
10,
|
||||
True,
|
||||
"3/5/7 claim pass, candidate fusion pass, question-revise-revote pass",
|
||||
"all three next-boundary checks pass",
|
||||
"support",
|
||||
),
|
||||
ScoreItem(
|
||||
"L01",
|
||||
"local_large_scale_stress",
|
||||
7,
|
||||
True,
|
||||
"128 Agent, 131072 tasks, failed=0, duplicate_claims=0",
|
||||
"large local stress has no failed task and no duplicate claim",
|
||||
"scale_budget",
|
||||
),
|
||||
ScoreItem(
|
||||
"L02",
|
||||
"model_tpm_budget",
|
||||
8,
|
||||
True,
|
||||
"target_tpm=3000, total_reserved_tokens=3000, utilization=1.0",
|
||||
"3000 TPM window is fully used but not exceeded",
|
||||
"scale_budget",
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def score_items(items: tuple[ScoreItem, ...]) -> ScoreReport:
|
||||
raw_score = sum(item.weight for item in items if item.passed)
|
||||
swarmness_score = sum(item.weight for item in items if item.group == "core_swarm" and item.passed)
|
||||
swarmness_score = round((swarmness_score / 60) * 100, 2)
|
||||
caps = hard_caps(items)
|
||||
capped_score = min(raw_score, *(cap for _, cap in caps)) if caps else raw_score
|
||||
status = "PASS" if capped_score >= 75 and not any_cap_below_pass(caps) else "FAIL"
|
||||
return ScoreReport(
|
||||
standard="swarm-compliance-score-v1",
|
||||
status=status,
|
||||
swarmness_score=swarmness_score,
|
||||
minimal_compliance_score=round(capped_score, 2),
|
||||
tier=classify_score(capped_score, caps),
|
||||
hard_caps=tuple(reason for reason, _ in caps),
|
||||
items=items,
|
||||
)
|
||||
|
||||
|
||||
def hard_caps(items: tuple[ScoreItem, ...]) -> tuple[tuple[str, float], ...]:
|
||||
caps: list[tuple[str, float]] = []
|
||||
core_failed = [item.id for item in items if item.group == "core_swarm" and not item.passed]
|
||||
if core_failed:
|
||||
caps.append((f"core swarm feature failed: {','.join(core_failed)}; max score capped at 59", 59))
|
||||
|
||||
support_failed = [item.id for item in items if item.group == "support" and not item.passed]
|
||||
if support_failed:
|
||||
caps.append((f"supporting Agent/audit/convergence evidence missing: {','.join(support_failed)}; max score capped at 84", 84))
|
||||
|
||||
scale_failed = [item.id for item in items if item.group == "scale_budget" and not item.passed]
|
||||
if scale_failed:
|
||||
caps.append((f"scale or budget evidence missing: {','.join(scale_failed)}; max score capped at 94", 94))
|
||||
return tuple(caps)
|
||||
|
||||
|
||||
def any_cap_below_pass(caps: tuple[tuple[str, float], ...]) -> bool:
|
||||
return any(cap < 75 for _, cap in caps)
|
||||
|
||||
|
||||
def classify_score(score: float, caps: tuple[tuple[str, float], ...]) -> str:
|
||||
if any_cap_below_pass(caps) or score < 60:
|
||||
return "不满足蜂群"
|
||||
if score < 75:
|
||||
return "部分蜂群,不可验收"
|
||||
if score < 85:
|
||||
return "最小可验收蜂群"
|
||||
if score < 95:
|
||||
return "合规蜂群原型"
|
||||
return "极强本地最小蜂群合规"
|
||||
@@ -0,0 +1,41 @@
|
||||
import unittest
|
||||
|
||||
from swarm_minimal.acceptance_scoring import ScoreItem, current_minimal_swarm_score, score_items
|
||||
|
||||
|
||||
class AcceptanceScoringTest(unittest.TestCase):
|
||||
def test_current_minimal_swarm_score_is_numeric_and_highly_compliant(self) -> None:
|
||||
report = current_minimal_swarm_score()
|
||||
|
||||
self.assertEqual(report.status, "PASS")
|
||||
self.assertEqual(report.swarmness_score, 100.0)
|
||||
self.assertEqual(report.minimal_compliance_score, 100.0)
|
||||
self.assertEqual(report.tier, "极强本地最小蜂群合规")
|
||||
self.assertEqual(report.hard_caps, ())
|
||||
|
||||
def test_core_swarm_failure_caps_score_below_acceptance(self) -> None:
|
||||
items = tuple(
|
||||
ScoreItem(
|
||||
id=f"F{index}",
|
||||
name=f"feature-{index}",
|
||||
weight=10,
|
||||
passed=index != 3,
|
||||
actual="test",
|
||||
threshold="test",
|
||||
group="core_swarm",
|
||||
)
|
||||
for index in range(1, 7)
|
||||
) + (
|
||||
ScoreItem("S07", "support", 40, True, "ok", "ok", "support"),
|
||||
)
|
||||
|
||||
report = score_items(items)
|
||||
|
||||
self.assertEqual(report.status, "FAIL")
|
||||
self.assertLessEqual(report.minimal_compliance_score, 59)
|
||||
self.assertIn("core swarm feature failed", report.hard_caps[0])
|
||||
self.assertEqual(report.tier, "不满足蜂群")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,46 @@
|
||||
import unittest
|
||||
|
||||
from examples.run_tpm_budget_acceptance import TpmConfig, run_acceptance
|
||||
|
||||
|
||||
class TpmBudgetAcceptanceTest(unittest.TestCase):
|
||||
def test_exact_3000_tpm_budget_passes_without_overrun(self) -> None:
|
||||
report = run_acceptance(
|
||||
TpmConfig(
|
||||
target_tpm=3000,
|
||||
agent_count=6,
|
||||
task_count=60,
|
||||
tokens_per_task=50,
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(report["status"], "PASS")
|
||||
self.assertEqual(report["summary"]["total_reserved_tokens"], 3000)
|
||||
self.assertEqual(report["summary"]["simulated_minutes"], 1)
|
||||
self.assertEqual(report["summary"]["max_tokens_in_any_minute"], 3000)
|
||||
self.assertEqual(report["summary"]["over_budget_windows"], {})
|
||||
self.assertEqual(report["summary"]["completed_tasks"], 60)
|
||||
self.assertEqual(report["summary"]["failed_tasks"], 0)
|
||||
self.assertEqual(report["summary"]["duplicate_claims"], 0)
|
||||
self.assertEqual(report["summary"]["participating_agents"], 6)
|
||||
|
||||
def test_budget_rolls_forward_without_exceeding_window(self) -> None:
|
||||
report = run_acceptance(
|
||||
TpmConfig(
|
||||
target_tpm=3000,
|
||||
agent_count=4,
|
||||
task_count=61,
|
||||
tokens_per_task=50,
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(report["status"], "PASS")
|
||||
self.assertEqual(report["summary"]["total_reserved_tokens"], 3050)
|
||||
self.assertEqual(report["summary"]["simulated_minutes"], 2)
|
||||
self.assertEqual(report["summary"]["max_tokens_in_any_minute"], 3000)
|
||||
self.assertEqual(report["summary"]["over_budget_windows"], {})
|
||||
self.assertEqual(report["tokens_by_minute"], {"0": 3000, "1": 50})
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user