【免费下载链接】Decepticon
Autonomous Hacking Agent for Red Team
Skillogy 是 Decepticon 的技能目录检索服务:红队 Agent 在攻击任务中通过自然语言查询find_skill定位安全技能(如 SSRF、Kerberoasting),再调用load_skill载入技能正文。本文围绕仓库内版本化的评测数据集 benchmark/skillogy/cases-v1.json 与评测运行器 evaluation.py,完整讲解如何在本地对 Skillogy 服务执行可复现的检索质量评测——你将掌握:数据集结构与字段契约、一键评测命令与参数含义、Recall@1/3/10、拒答(abstention)精确率/召回率、Forbidden-skill 暴露率、p95 延迟与加载 Token 估算等全部指标的计算口径,以及如何结合源码读懂每项指标背后的检索机制。
上图来自仓库 assets/cli.png,展示了 Decepticon CLI 在评测相关流程中的运行界面,帮助读者建立评测命令的终端上下文。
一、评测定位:为什么需要 skillogy 检索评测
Skillogy 是 Agent 技能发现的入口:Agent 产生一个目标描述(例如verify SQL injection with controlled database query evidence)后,通过 Skillogy 服务在技能库中检索对应技能。检索质量直接决定 Agent 能否在合适时机拿到合适的操作手册,因此在开源仓库中沉淀了一套服务级(service-level)、可复现的评测方案:
- 版本化数据集:benchmark/skillogy/cases-v1.json 是一个
version: 1、含 18 个用例的检索评测集; - 独立评测运行器:evaluation.py 通过真实的 REST 接口(
/v1/skills:find、/v1/skills:load)驱动服务,逐用例计算指标并输出结构化 JSON 报告; - 单元测试固化契约:test_evaluation.py 验证了数据集 schema 校验、路径存在性校验与全部指标计算口径,保证评测逻辑本身不漂移。
评测结果可用于同一数据集、同一技能目录、同一服务配置下的回归对比(例如混合检索语义化改造前后),而不是设定一个绝对通过/失败阈值。
二、数据集结构:cases-v1.json 的字段契约
数据集整体是一个 JSON 对象,包含version(固定为1)与cases(用例数组)。运行器用 Pydantic 模型EvaluationSuite/EvaluationCase(evaluation.py)加载并严格校验。每个用例的字段如下:
| 字段 | 类型 | 含义 | 约束 |
|---|---|---|---|
id | string | 用例唯一标识 | 非空;整个数据集内不允许重复 |
query | string | 传给服务的自然语言检索查询 | 非空 |
allowed_path_prefixes | string[] | 本次查询允许命中的技能路径前缀(角色 ACL 范围) | 必须全部以/skills/开头 |
expected_paths | string[] | 期望命中的技能路径(正例标签) | 以/skills/开头、以/SKILL.md结尾;不得与forbidden_paths重叠;必须落在allowed_path_prefixes内 |
forbidden_paths | string[] | 禁止暴露的技能路径(污染标签) | 同上 |
abstain | bool | 该用例期望服务“拒答”(不返回任何技能) | 与expected_paths二选一:abstain为 true 时不得声明期望路径 |
Schema 校验的硬性规则(见 evaluation.py):
abstain == bool(expected_paths)会直接抛错——即“期望拒答”与“期望命中”必须互斥;expected_paths与forbidden_paths不允许重叠(一个路径不可能既是目标又是污染源);- 所有标签路径必须位于该用例
allowed_path_prefixes声明的范围内,防止标签与查询范围自相矛盾; - 通过
validate_dataset_paths(evaluation.py)会把每个标签路径换算为相对路径,逐一检查在--skills-root指向的技能树中真实存在,任何缺失都会直接失败。
2.1 数据集的来源与裁剪
数据集源自生产环境的同名数据集(apps/decepticon/benchmark/skillogy/cases-v1.json@aae2ef8e),针对开源技能树做了两处调整:
- 剔除 2 个依赖前置/校验器 bundle 的生产用例——开源
find_skill响应尚未暴露选择角色(selection roles)与 bundle 信息,此类用例在开源服务下无法正确打分; - 新增 2 个开源专属用例:
web-sqli(SQL 注入验证)与cloud-aws-iam-enum(AWS IAM 枚举),覆盖开源技能树中sql-injection与aws-iam-enum等技能。
2.2 18 个用例速览
- 正例(15 个,期望命中):
recon-passive-dns-ct、recon-auth-surface、web-idor、web-ssrf、web-graphql、web-xss、web-oauth-redirect(双期望路径:oauth+open-redirect)、ad-kerberoasting、ad-adcs-esc1、ics-modbus、ko-web-idor(韩语查询)、ko-ad-kerberoasting(韩语查询)、paraphrase-ssrf(同义改写)、web-sqli、cloud-aws-iam-enum; - 负例(3 个,期望拒答):
abstain-business-spreadsheet(财务报表格式化)、abstain-wedding-planning(婚礼座位安排)、abstain-financial-calculation(房贷分期计算)——均为与安全操作完全无关的日常事务查询。
其中韩语用例(ko-*)验证多语言查询下的召回,paraphrase-ssrf验证同义改写后语义检索是否仍能命中——这两类用例正是 ADR-0011 混合检索(hybrid retrieval)改造要解决的核心场景:自然语言多词查询与“没人写过的措辞”必须通过语义向量腿才能召回。
三、运行评测:命令、参数与前置条件
3.1 前置条件
- Skillogy 服务已运行且目录已加载。服务通过 __main__.py 启动:连接 Neo4j(默认
bolt://neo4j:7687)、后台线程 reconcile 内置目录、随后在$SKILLOGY_REST_PORT(默认9100)上启动 FastAPI REST 应用;启动时会顺带创建全文索引与(在配置了 embedding 代理时)向量索引。可通过GET /v1/health确认就绪。 - 仓库根目录下可用的
uv环境(项目使用 uv 管理依赖,见根目录 pyproject.toml 与 uv.lock)。
3.2 评测命令
从仓库根目录执行(原文档命令,参数含义见下表):
DECEPTICON_SKIP_BOOT=1 uv run python -m decepticon.skillogy.evaluation \ benchmark/skillogy/cases-v1.json \ --skills-root packages/decepticon/decepticon/skills \ --source-revision "$(git rev-parse HEAD)" \ --url http://localhost:9100 > skillogy-evaluation.json3.3 命令行参数
运行器使用argparse解析(evaluation.py):
| 参数 | 必填 | 默认值 | 作用 |
|---|---|---|---|
dataset(位置参数) | 是 | — | 评测数据集 JSON 路径,此处传benchmark/skillogy/cases-v1.json |
--skills-root | 是 | — | 开源技能树根目录,用于校验数据集标签路径真实存在;仓库中对应packages/decepticon/decepticon/skills |
--source-revision | 是 | — | 记录评测时的源码版本(git rev-parse HEAD),写入报告便于复现溯源 |
--url | 否 | $DECEPTICON_SKILLOGY_URL或http://localhost:9100 | Skillogy REST 服务地址 |
--api-key | 否 | $SKILLOGY_API_KEY | 服务开启了 Bearer 鉴权时透传 API Key |
--check-dataset | 否 | 关闭 | 只校验数据集(schema + 标签路径存在性),不请求服务,立即输出{"version": 1, "case_count": 18}后退出 |
两个细节值得注意:
--url与--api-key均可通过环境变量提供(DECEPTICON_SKILLOGY_URL/SKILLOGY_API_KEY),与 rest.py 中from_env()工厂的取值逻辑一致;- 若
SKILLOGY_API_KEY已设置,运行器会自动转发给服务——服务端用hmac.compare_digest校验Authorization: Bearer(见 server/app.py),未配置 Key 时受保护端点保持开放。
3.4 评测驱动链路
运行器通过RestSkillogyClient(rest.py)驱动服务,该客户端与Neo4jBackend保持同形接口,可无缝替换。每个用例执行两步:
find_skill(query=case.query, limit=10, allowed_path_prefixes=case.allowed_path_prefixes)发起检索(固定取前 10 条),服务端命中后由后端按混合检索排序(细节见第五节);- 对第一名命中路径调用
load_skill(path, allowed_path_prefixes=...)拉取技能正文,用于统计“首个技能正文加载字节数”。
评测同时校验服务返回的每一条路径都必须落在该用例声明的allowed_path_prefixes内,一旦越界立即抛ValueError(“backend returned invalid or out-of-scope path”)——这由单元测试test_backend_must_observe_scope(test_evaluation.py)固化。
四、报告与指标口径
运行成功后,skillogy-evaluation.json输出结构化报告,模型定义见 evaluation.py,顶层包含dataset_version、source_revision、metrics与逐用例cases。指标计算逻辑全部集中在evaluate_suite/_evaluate_case/_recall_at/_percentile_95(evaluation.py),口径如下:
| 指标 | 计算方式 | 解读 |
|---|---|---|
recall_at_1 | 正例中,期望路径出现在返回第 1 位的比例 | 首个结果即为正确技能的命中率 |
recall_at_3 | 正例中,期望路径出现在返回前 3 位的比例 | 前 3 条结果覆盖正确技能的比例 |
recall_at_10 | 正例中,期望路径出现在返回前 10 位的比例 | 全量返回(limit=10)覆盖正确技能的比例 |
abstention_precision | 被预测为“拒答”的用例中,实际期望拒答的比例 | 服务“敢不敢拒”的准确度 |
abstention_recall | 期望拒答的用例中,服务确实拒答的比例 | 服务“会不会漏答日常事务”的覆盖度 |
forbidden_at_3_rate | 正例中,forbidden_paths出现在返回前 3 位的比例 | 污染技能(如把主动侦察当被动侦察)泄露进 Top3 的概率 |
p95_latency_ms | 全部用例find_skill耗时的 P95 分位数 | 检索延迟的尾延迟表现 |
loaded_skill_bytes | 每用例首个返回技能正文的 UTF-8 字节数之和 | 首条结果加载量的总量 |
estimated_loaded_tokens | ceil(loaded_skill_bytes / 4) | 以 bytes/4 代理估算的加载 Token,与生产环境同一口径 |
4.1 指标口径中的三个“坑”
- 字节与 Token 是代理估算:
estimated_loaded_tokens使用bytes/4的粗粒度代理,并非模型 tokenizer 的真实计数。评测单元测试用"évidence"验证 UTF-8 字节统计(7 字节)与 Token 估算(ceil(7/4)=3)的计算正确性(test_evaluation.py)。 - 零分母语义:当服务从未拒答任何查询时,
abstention_precision的分母为 0,指标固定返回 0.0——此时该指标“没有正预测”,不代表服务拒答能力差,必须结合abstention_recall一起解读(_ratio在 evaluation.py)。 - 无阈值设定:运行器不内置通过/失败阈值。正确用法是在相同数据集、相同技能目录、相同服务配置、相同 embedding 可用性前提下对比不同版本报告(例如混合检索上线前后、embedding 模型切换前后、技能库增删前后)。
4.2 只校验数据集
不启动服务也能先行校验数据集本身是否合法、标签是否都存在于技能树:
DECEPTICON_SKIP_BOOT=1 uv run python -m decepticon.skillogy.evaluation \ benchmark/skillogy/cases-v1.json \ --skills-root packages/decepticon/decepticon/skills \ --source-revision "$(git rev-parse HEAD)" \ --check-dataset输出形如{"version": 1, "case_count": 18}。该模式正好对应测试test_shipped_dataset_labels_exist(test_evaluation.py):它断言内置数据集合规(18 个用例、3 个拒答用例)且所有标签在开源技能树中真实存在。
五、源码视角:检索机制如何决定评测结果
评测分数本质上是find_skill检索质量的度量,理解底层机制才能解读分数变化。
5.1 混合检索:lexical + semantic 两腿融合
Neo4jBackend.find_skill(neo4j_backend.py)按 ADR-0011(0011-skillogy-lightrag-hybrid-retrieval.md)实现 LightRAG 风格的混合检索:
- Lexical 腿:把查询交给 Neo4j 全文索引(BM25 + Lucene 分词),对技能元数据与正文做字段加权检索——
name与when_to_use触发条件权重最高,正文低权重兜底召回。这修复了早期“整句子串CONTAINS匹配”的缺陷(多词查询如oauth redirect_uri bypass在旧实现下 0 命中,ADR 中记录的 run-004 实战事故); - Semantic 腿:查询经 litellm 代理嵌入为向量(默认模型
openai/text-embedding-3-small、1536 维,见 embeddings.py),对:Skill(embedding)原生向量索引做余弦 k-NN,让“没人写进when_to_use的措辞”也能按语义命中; - RRF 融合:两腿各按排名贡献
1/(60 + rank)的分数(_rrf_fuse,neo4j_backend.py),双腿同时命中的技能排在单腿命中之前;每行携带matched_by(["lexical"]/["semantic"]/ 两者)作为可解释信号。
5.2 评测正例正是混合检索的“靶场”
数据集里的paraphrase-ssrf(“make the server fetch an attacker-observed destination and preserve callback proof”)就是为语义腿设计的:该查询不含ssrf字样,lexical 腿几乎不可能召回web/ssrf技能,只有 embedding 命中才能让recall_at_*过关。韩语用例(ko-*)同理。若服务未配置 embedding(无DECEPTICON_LLM__PROXY_URL/DECEPTICON_LLM__PROXY_API_KEY),find_skill会优雅降级为纯词法检索(embeddings.py 与 neo4j_backend.py),因此同一数据集在不同 embedding 可用性下会得到不同分数——这正是 README 强调“对比需保持 embedding 可用性一致”的原因。
5.3 ACL 与拒答判定
- 每个用例的
allowed_path_prefixes在评测中直接透传给find_skill/load_skill,服务端将其编译为ANY(p IN $allowed_path_prefixes WHERE s.path STARTS WITH p)的后置过滤(ADR-0008 的路径前缀 ACL,见 neo4j_backend.py),越界路径会被过滤; predicted_abstention的判定是“find_skill返回空列表”(evaluation.py)。三个负例(财务报表、婚礼安排、房贷计算)均落在安全技能前缀范围内(/skills/standard/recon/等),但查询语义与任何安全技能无关——合格的检索应当在词法与语义两腿都找不到匹配时返回空,从而获得较高的abstention_precision。
5.4 加载字节与负载评估
每个用例评测会对 Top-1 结果调用load_skill并统计body的 UTF-8 字节数(_loaded_bytes,evaluation.py)。这个“首个技能正文加载量”指标直接关系到 Agent 上下文预算:检索不仅要“命中”,还要“以尽量少的 Token 载入正确的技能”。estimated_loaded_tokens以 bytes/4 代理估算(与生产环境同一口径),可用于比较不同排序策略下首条结果的“上下文成本”。
六、评测结果解读与回归对比建议
6.1 组合解读指标
- 召回 + 拒答组合:高
recall_at_3搭配高abstention_recall意味着检索“该找到的能找到、不该找的找不到”,是检索质量健康的核心信号; - 污染暴露单独看:
forbidden_at_3_rate反映边界混淆风险(例如将主动侦察技能混入被动侦察查询的 Top3)。零暴露是最优目标,任何非零值都值得排查词法/语义排序是否把近义技能提得太靠前; - 延迟与质量平衡:
p95_latency_ms应结合 embedding 可用性解读——语义腿在查询时多一次 embedding 往返(查询路径超时 5 秒、单次尝试,见 embeddings.py),若 p95 显著上升,需检查 litellm 代理的响应稳定性。
6.2 推荐的回归对比基线
- 固定
--skills-root指向同一技能树提交; - 固定服务版本与
SKILLOGY_NEO4J_*、embedding 模型等配置; - 记录每次运行的
source_revision与数据集dataset_version; - 在改动前后各跑一次,diff 两份
skillogy-evaluation.json的metrics段。
单元测试test_evaluate_counts_rank_abstention_pollution_and_utf8_bytes(test_evaluation.py)演示了最直接的回归验证方式:给定固定返回序列(如["ssrf"] → [sqli, ssrf]),断言recall_at_1 == 0、recall_at_3 == 0.5、abstention_recall == 1,并确认find_skill以limit=10、ACL 前缀原样透传。
七、相关参考
- 评测数据集:benchmark/skillogy/cases-v1.json
- 评测运行器:packages/decepticon/decepticon/skillogy/evaluation.py
- 评测单元测试:packages/decepticon/tests/unit/skillogy/test_evaluation.py
- REST 客户端:packages/decepticon/decepticon/skillogy/client/rest.py
- 服务端接口:packages/decepticon/decepticon/skillogy/server/app.py
- 混合检索后端:packages/decepticon/decepticon/skillogy/server/neo4j_backend.py
- 嵌入模块:packages/decepticon/decepticon/skillogy/embeddings.py
- 启动入口与环境变量:packages/decepticon/decepticon/skillogy/main.py
- 混合检索设计决策:docs/adr/0011-skillogy-lightrag-hybrid-retrieval.md
【免费下载链接】Decepticon
Autonomous Hacking Agent for Red Team
相关推荐
Onyx(Danswer)搜索质量回归评测指南:基于 Ground Truth 的检索与回答自动评估
Onyx(Danswer)搜索质量回归评测指南:基于 Ground Truth 的检索与回答自动评估 导读 本文围绕 Onyx 开源仓库(即原 Danswer
AI 应用大模型RAGAI Agent后端前端MemoryBear 知识库召回评测与检索压测实战指南:从快照生成到性能门禁的完整链路
MemoryBear 知识库召回评测与检索压测实战指南:从快照生成到性能门禁的完整链路 本文是 MemoryBear 开源仓库中 api/scripts/REA
LlamaIndex Tonic Validate 评估集成:用 LLM-as-Judge 度量 RAG 检索与回答质量的完整指南
LlamaIndex Tonic Validate 评估集成:用 LLM as Judge 度量 RAG 检索与回答质量的完整指南 本文围绕 LlamaInde
人工智能RAG大模型
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考