garak 的 PxD(Probes × Detectors)Harness 源码解析:全量探针 × 全量检测器扫描机制
garak 的 PxDProbes × DetectorsHarness 源码解析全量探针 × 全量检测器扫描机制【免费下载链接】garakthe LLM vulnerability scanner项目地址: https://gitcode.com/GitHub_Trending/ga/garak导读本文围绕 garak.harnesses.pxd 模块展开讲解 garakthe LLM vulnerability scanner中 PxDProbes × Detectorsharness 的设计与实现它负责把用户指定的所有 probe探针与所有 detector检测器做全量交叉扫描是彻底但可能产生无意义组合的检测模式。读完本文你将理解 PxD 与 Probewise 两种 harness 的分工、PxD 的完整运行流水线、它在 CLI 中的触发条件以及其底层所依赖的Harness.run核心机制与相关配置项。一、什么是 PxD harness全量交叉的扫描模式在 garak 中**harness测试框架**是协调在生成器generator上运行探针probe→ 对输出运行检测器detector→ 评估结果evaluator这一完整流程的执行器。所有 harness 都必须继承自 garak.harnesses.base 中的 Harness 基类。garak/harnesses/pxd.py 顶部的模块注释给出了 PxD 的准确定义The pxd (probes x detectors) harness runs all specified probes and analyses results using all specified detectors.即PxD Probes × Detectors它会运行所有指定的探针并用所有指定的检测器来分析结果。模块注释同时坦率地指出了该模式的特点与代价thorough彻底组合覆盖全面可能会产生一些不太有意义的比较comparisons that dont make so much sense因为并非所有检测器都是为捕捉所有场景下的失败模式而设计的not all detectors are designed to pick up failure modes in all situations。这一点是理解 PxD 的关键它是一个宁可错杀、不可放过的全量扫描模式适合追求覆盖率而非精度的场景。PxD 与 Probewise 的分工对比garak 当前提供了两个核心 harness二者的选择逻辑在 CLI 中直接体现Harness类名模块检测器选择策略适用场景ProbewiseProbewiseHarnessgarak/harnesses/probewise.py按每个 probe 自己推荐的检测器primary_detector/extended_detectors选择未显式指定-d使用 probe 的建议PxDPxDgarak/harnesses/pxd.py使用命令行指定的全部检测器显式指定了-d/--detectorsProbewise 的核心注释是 Selects detectors to run for each probe based on that probes recommendations根据 probe 的推荐为每个探针选择检测器而 PxD 则是用户显式给出检测器集合全部交叉运行。二、PxD 的完整运行流程源码级解析PxD类的核心是重写的run方法其签名如下garak/harnesses/pxd.pydef run(self, model, probe_names, detector_names, evaluator, buff_namesNone):参数含义model已实例化的生成器generator即被检测的 LLM 接口probe_names要运行的探针名称列表detector_names要使用的检测器名称列表evaluator用于判定检测结果的评估器实例buff_names可选本次运行要加载的 buff变形/增强器列表默认None。1. 参数归一化与队列打印if buff_names is None: buff_names [] probe_names sorted(probe_names) detector_names sorted(detector_names) print(f️ queue of ... probes: , .join([name.replace(probes., ) for name in probe_names])) print(f queue of ... detectors: , .join([name.replace(detectors., ) for name in detector_names])) logging.info(probe queue: %s, .join(probe_names))探针与检测器都被排序后进入队列保证运行顺序确定、可复现打印时通过replace(probes., )/replace(detectors., )去掉命名空间前缀只显示短名称方便阅读队列内容同时写入日志logging.info便于后续追溯。2. 加载 buffsself._load_buffs(buff_names)该方法继承自Harness基类garak/harnesses/base.py它把每个 buff 名通过_plugins.load_plugin(buff_name)实例化后追加到全局配置_config.buffmanager.buffs中单个 buff 加载失败只会打印告警并continue不会中断整个运行。3. 逐 probe 加载并运行核心循环是对每个探针名依次处理garak/harnesses/pxd.pyfor probename in probe_names: try: probe _plugins.load_plugin(probename) except Exception as e: message f{probename} load exception , skipping print(message, str(e)) logging.error(%s %s, message, str(e)) continue if not probe: message f{probename} load failed ⚠️, skipping print(message) logging.warning(message) continue detectors [] for detector_name in detector_names: detector _plugins.load_plugin(detector_name, break_on_failFalse) if detector: detectors.append(detector) else: msg f detector load failed: {detector_name}, skipping print(msg) logging.error(msg) super().run(model, [probe], detectors, evaluator, announce_probeFalse)这段代码的关键行为容错加载某个 probe 加载抛出异常load exception 或返回空load failed ⚠️时打印提示并continue跳过该 probe不影响队列中其余 probe逐 probe 重建检测器列表对每个 probe都重新遍历detector_names并逐个加载。注意这里使用了break_on_failFalse即某个检测器加载失败不会抛出异常而是返回空值后被记录并跳过单个 probe 单个检测器组合super().run(model, [probe], detectors, evaluator, announce_probeFalse)每次只传入一个probe 和当次全部可用的检测器并设置announce_probeFalse以避免重复的探针加载公告因为队列信息已在开头打印过。核心逻辑最终全部交给基类的Harness.run完成。三、底层引擎Harness.run做了什么PxD 之所以能一个 probe × 全部 detectors地工作靠的是基类 garak/harnesses/base.py 中的Harness.run。这一方法也是 Probewise 复用的核心理解它对理解 PxD 至关重要。1. 前置校验与运行钩子if not detectors: raise ValueError(No detectors, nothing to do) if not probes: raise ValueError(No probes, nothing to do) self._start_run_hook() _emit_plugin_cache_entry(self, model, *probes, *detectors, *_config.buffmanager.buffs)空探测器/空探针列表会直接抛出ValueError_start_run_hook()会临时把所有 HTTP 库的 User-Agent 替换为运行配置指定的user_agent运行结束后由_end_run_hook()还原_emit_plugin_cache_entry把本次运行涉及的所有插件元信息快照写入report.jsonl形成plugin_cache条目保证报告可复现。2. 模态匹配modality matchmodality_match _modality_match( probe.modality[in], model.modality[in], self.strict_modality_match ) if not modality_match: logging.warning(probe skipped due to modality mismatch: %s - model expects %s, ...) continue_modality_matchgarak/harnesses/base.py实现两种匹配策略strict严格模式探针输入模态必须与模型输入模态完全相等非严格模式默认探针要求的每个模态都必须被模型接受set(probe_modality).intersection(generator_modality) set(probe_modality)。模态不匹配的探针会被跳过这保证了 PxD 不会把文本探针硬塞给纯视觉模型之类的错误组合。strict_modality_match是Harness的DEFAULT_PARAMS中唯一的参数默认值为False。3. 探测与检测的两种路径attempt_results probe.probe(model) ... if not isinstance(probe, garak.probes.base.IntentProbe): for d in detectors: self._run_detector(attempt_results, d) else: # intent 驱动的检测器选择逻辑普通探针直接把 probe 产生的所有 attempts尝试记录喂给每一个检测器IntentProbe意图探针走意图服务intentservice路径——根据每个 attempt 的intent字段通过intentservice.get_detectors(intent)动态选出候选检测器只为匹配的 attempt 子集打分并把动态加载的检测器也补写入plugin_cache条目。_run_detectorgarak/harnesses/base.py用tqdm进度条展示probe_classname/detector_name形式的处理进度并把每个 attempt 的检测结果写入attempt.detector_results[detector_probe_name]。4. 结果落盘与评估for attempt in attempt_results: attempt.status garak.attempt.ATTEMPT_COMPLETE _config.transient.reportfile.write(json.dumps(attempt.as_dict(), ensure_asciiFalse) \n) ... evaluator.evaluate(attempt_results)每个 attempt 序列化为 JSON 行追加到report.jsonl报告文件路径由 garak/command.py 的start_run按garak.run_id.report.jsonl或report_prefix.report.jsonl命名创建随后调用评估器CLI 中默认是garak.evaluators.ThresholdEvaluator见 garak/cli.py 中的evaluator garak.evaluators.ThresholdEvaluator(_config.run.eval_threshold)对结果做判定。四、PxD 何时被启用CLI 的自动路由逻辑PxD 不是用户在命令行手动指定的插件名而是 CLI 根据是否显式给出检测器自动路由的结果。关键逻辑位于 garak/cli.pycommand.warn_unconsumed_intents(parsed_specs[probe]) if parsed_specs[detector] []: command.probewise_run(generator, parsed_specs[probe], evaluator, parsed_specs[buff]) else: command.pxd_run( generator, parsed_specs[probe], parsed_specs[detector], evaluator, parsed_specs[buff], )对应的命令行参数在 garak/cli.py 中定义--detectors, -d list of detectors to use, or all for all. Default is to use the probes suggestion. --extended_detectors If detectors arent specified on the command line, should we run all detectors? (default is just the primary detector, if given, else everything)也就是说不传-dparsed_specs[detector] []走probewise_runProbewiseHarness按探针自身推荐选择检测器传了-d包括-d all走pxd_runPxD你给出的全部检测器都会被用来分析每个探针的结果。pxd_run与probewise_run都是 garak/command.py 中定义的薄封装内部实例化对应 harness 并调用其run方法def pxd_run(generator, probe_names, detector_names, evaluator, buffs): pxd_h garak.harnesses.pxd.PxD() pxd_h.run(generator, probe_names, detector_names, evaluator, buffs)因此一次典型的全量扫描命令形如python -m garak --model_type openai --model_name gpt-4o-mini -d all其中-d all会激活 PxD harness让所有可用检测器去分析所有选中探针的输出。五、与 PxD 相关的配置项PxD 的行为由plugins与run两个配置分组驱动。从 garak/_config.py 可以看到plugins_params target_type target_name extended_detectors.split() run_params seed deprefix eval_threshold generations interactive system_prompt spec.split()garak/configs/fast.json 与 garak/configs/bag.yaml 等配置文件可覆盖这些默认值。与 PxD 直接相关的关键项配置项所属分组作用detector_specplugins检测器规格-d参数默认值取自它。在配置文件中设置该项等同于在命令行传-d会强制走 pxd harness见 docs/source/configurable.rstextended_detectorsplugins当未显式指定检测器时是否运行所有扩展检测器False默认时只运行 probe 的主检测器primary detectorTrue时更彻底对应 CLI 的--extended_detectorseval_thresholdrun阈值评估器ThresholdEvaluator的判定阈值影响最终 pass/fail 结论注意配置与 CLI 的对应关系文档 docs/source/configurable.rst 明确说明Specifyingdetector_specmeans thepxdharness will be used. This is equivalent to passing-dto the CLI——即配置文件中出现detector_spec就会切换到 PxD等价于命令行传-d。六、PxD 模式的特性与使用注意结合源码使用 PxD 时有几点值得注意彻底但可能产生无意义组合模块注释明确承认这一点。例如一个检测 DAN 越狱风格的检测器去分析一个本就不含任何对抗内容的探针输出往往没有判别意义。因此在-d all之前建议先通过--list_detectorsgarak/cli.py 中定义了解可用的检测器集合。容错但不静默probe 或 detector 加载失败会被打印出来带 /⚠️ 标记并跳过同时写入 error/warning 日志Harness.run在检测器列表为空时会直接抛ValueError(No detectors, nothing to do)所以不存在静默空跑的情况。执行顺序确定probe 与 detector 都经过sorted()排序同一组参数多次运行的结果可复现。运行成本高PxD 的组合数量为len(probes) × len(detectors)每个组合都要在模型输出上跑检测器属于成本换覆盖的模式官方文档也提示默认配置偏向速度而非彻底性见 garak/command.py 中 lite 模式下的提示语。报告自动生成每次运行结束garak/command.py 的end_run会关闭report.jsonl并调用write_report_digest生成 HTML 摘要garak.run_id.report.htmlPxD 的运行结果同样遵循这一流程。七、进一步阅读PxD 实现源码本文核心分析对象Probewise 实现源码与 PxD 互补的按推荐选择检测器的 harnessHarness 基类源码Harness.run、_run_detector、_load_buffs、模态匹配等底层机制CLI 路由逻辑-d/--detectors、--extended_detectors参数及 pxd/probewise 自动切换命令行封装pxd_run、probewise_run、start_run/end_run报告流程配置说明detector_spec、extended_detectors等与 harness 选择相关的配置配置示例、配置示例YAML可参考的运行时配置harness 文档索引base、probewise、pxd 三份文档的入口。【免费下载链接】garakthe LLM vulnerability scanner项目地址: https://gitcode.com/GitHub_Trending/ga/garak创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考