mardianto-msft/foundry-local-eval
GitHub: mardianto-msft/foundry-local-eval
该项目使用 Azure AI Evaluation 红队 SDK 对在本地运行的 Microsoft Foundry 语言模型进行对抗性安全扫描与风险评分。
Stars: 0 | Forks: 0
# 红队 Foundry 本地模型
本项目在本地机器上使用 Foundry Local 下载并运行语言模型,然后使用 Azure AI Evaluation 红队 SDK 对其进行评估。它还包含一个交互式聊天实用工具,用于在扫描前检查模型。
Azure Developer CLI (`azd`) 负责配置评估器所需的 Microsoft Foundry 账户和项目。受测模型并不会部署到 Azure。
目标模型及其推理在本地机器上运行。Azure AI Evaluation 使用配置好的 Microsoft Foundry 项目来生成攻击,并针对以下风险类别对回复进行评分:
- 暴力
- 仇恨和不公平
- 性内容
- 自残
该扫描应用了基线、分组简单与中等难度、编码以及文本转换攻击策略。它会报告攻击成功率 (ASR),数值越高意味着有越多的对抗性 prompt 引发的回复超过了设定的安全阈值。
## 执行模型
这是一个混合了本地和云端的工作流,而不是一个完全离线的红队扫描器:
- **本地:** 目标模型通过 Foundry Local 进行下载、加载和查询。Python 扫描过程、回调、缓存、日志和生成的产出物也都在本地进行。
- **Azure:** Azure AI Evaluation SDK 使用配置好的 Microsoft Foundry 项目来生成对抗性攻击,并对模型回复进行评分。这需要 Azure 连接、`AZURE_AI_PROJECT_ENDPOINT`、Azure CLI 凭据以及配置好的 Foundry 资源。
简而言之,模型推理在本地进行,而攻击生成和安全评估则依赖于 Azure 服务。
对于每次攻击,评估器都会通过配置好的 Foundry 项目生成一个 prompt,调用进程内回调将该 prompt 发送给本地模型,并返回模型回复以供 Azure 端进行评分。尽管模型权重和推理运行时保留在本地,但您应将扫描的 prompt 和回复视为跨越了 Azure 服务边界的数据。模型列表、缓存管理和交互式聊天不使用 Azure 评估器。
如需了解更多信息,请参阅[在本地运行 AI 红队代理 (Azure AI Evaluation SDK) - Microsoft Foundry | Microsoft Learn](https://learn.microsoft.com/en-us/azure/foundry/how-to/develop/run-scans-ai-red-teaming-agent)。
## 脚本
### redteam_foundry_local_model.py
主入口点。它可以:
- 列出可用或已下载的 Foundry Local 模型。
- 从本地缓存中删除已下载的模型。
- 下载并加载选定的模型。
- 对其运行 Azure AI Evaluation 红队扫描。
- 保存详细的证据、日志和汇总记分卡。
- 串行运行或以有限的并行度运行。
### foundry_local_interactive_chat.py
一个交互式的冒烟测试实用工具。它会下载并加载选定的模型,为当前会话保留对话历史,并在用户退出时卸载模型。红队回调被特意设计为单轮对话,因此该工具非常适合在扫描前进行手动的、有状态的检查。
### foundry_local_model_utils.py
两个命令行脚本共享的内部模块。它负责 Foundry Local 目录初始化、模型查找与显示、下载、缓存检测以及缓存删除。它不是一个独立的入口点。
### 基础设施
- `azure.yaml`:配置 Bicep 部署和预配后钩子。
- `infra/main.bicep`:创建资源组并调用 Foundry 模块。
- `infra/modules/foundry.bicep`:创建 Microsoft Foundry 账户和项目。
- `scripts/write-env.sh`:将预配好的项目端点写入 `.env`,且不会删除无关条目。
## 先决条件
您需要:
- Python 3.10 至 3.13 版本,以满足 Azure AI Evaluation 红队的依赖项。
- 受 [Foundry Local](https://learn.microsoft.com/azure/ai-foundry/foundry-local/get-started) 支持的平台。
- 一个 Azure 订阅,您可以在其中创建资源组、Microsoft Foundry 资源和 Foundry 项目。
- [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli)。
- [Azure Developer CLI](https://learn.microsoft.com/azure/developer/azure-developer-cli/install-azd) 1.27 或更高版本。
在 Ubuntu 或 Debian 上,使用以下命令安装 Azure CLI:
```
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
curl -fsSL https://aka.ms/install-azd.sh | bash
```
验证安装:
```
python3 --version
az version
azd version
```
对于其他操作系统,请使用上方链接的安装指南。
## 快速开始
### 1. 克隆仓库
克隆项目并进入其目录:
```
git clone https://github.com/mardianto-msft/foundry-local-eval.git
cd foundry-local-eval
```
### 2. 安装 Python 依赖项
在仓库根目录下执行:
```
python3 -m venv .fl
source .fl/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
```
### 3. 登录 Azure
AZD 负责配置基础设施,而 Python 评估器通过 `AzureCliCredential` 进行身份验证。请登录这两个工具:
```
azd auth login
az login
```
验证这两个会话:
```
azd auth login --check-status
az account show --output table
```
### 4. 配置 Microsoft Foundry
配置 Azure 资源:
```
azd up
```
首次运行时,AZD 会提示输入 Azure 订阅、环境名称和区域。基础设施默认使用 `eastus2`。环境名称决定了所有资源的名称:
| 资源 | 名称 |
|----------|------|
| 资源组 | `rg-` |
| Microsoft Foundry 资源 | `aif-` |
| Foundry 项目 | `proj-` |
例如,`dev` 环境会创建 `rg-dev`、`aif-dev` 和 `proj-dev`。
预配完成后,[scripts/write-env.sh](scripts/write-env.sh) 会自动将 `AZURE_AI_PROJECT_ENDPOINT` 写入根目录的 `.env` 文件中。现有的无关条目会被保留,并且 `.env` 会被 Git 忽略。
您可以使用以下命令检查所有部署输出:
```
azd env get-values
```
生成的 `.env` 条目格式如下:
```
AZURE_AI_PROJECT_ENDPOINT=https://aif-.services.ai.azure.com/api/projects/proj-
```
### 5. 验证设置
保持虚拟环境处于激活状态,并验证脚本和模型目录是否可用:
```
python redteam_foundry_local_model.py --help
python redteam_foundry_local_model.py --list-model
```
列出模型、列出已缓存模型以及删除缓存不需要 Azure 凭据。运行红队扫描则需要。
## 模型管理
列出通过 Foundry Local 目录提供的所有模型:
```
python redteam_foundry_local_model.py --list-model
```
仅列出已下载到项目本地缓存的模型:
```
python redteam_foundry_local_model.py --cached
```
从本地缓存中删除已下载的模型:
```
python redteam_foundry_local_model.py --delete-model qwen2.5-0.5b
```
删除操作使用 Foundry Local SDK 的缓存移除功能。当模型尚未下载时,脚本会进行报告;并且它会使用与扫描相同的进程锁,以避免在扫描正在使用模型时将其删除。
下载的模型存储在 `.foundry-local/` 目录下。当任一命令行脚本首次需要某个模型时,它会自动被下载。
## 交互式聊天
启动有状态的聊天会话:
```
python foundry_local_interactive_chat.py --model qwen2.5-0.5b
```
默认情况下,回复会在生成时以流的形式传输。使用 `--stream` 显式选择流式传输,或使用 `--no-stream` 获取非流式回复:
```
python foundry_local_interactive_chat.py --model qwen2.5-0.5b --stream
python foundry_local_interactive_chat.py --model qwen2.5-0.5b --no-stream
```
输入 `exit` 或 `quit` 可卸载模型并停止。空的 prompt 会被忽略。
聊天实用工具也可以用于检查目录:
```
python foundry_local_interactive_chat.py --list-models
python foundry_local_interactive_chat.py --cached
```
从本地缓存中删除已下载的模型:
```
python foundry_local_interactive_chat.py --delete-model qwen2.5-0.5b
```
## 红队扫描
运行串行扫描,这对于本地 CPU 模型来说是更安全的默认设置:
```
python redteam_foundry_local_model.py --model qwen2.5-0.5b
```
以有限的并行度运行:
```
python redteam_foundry_local_model.py \
--model qwen2.5-0.5b \
--parallel \
--max-parallel-tasks 2
```
该脚本一次只允许执行一个扫描或模型删除操作。即使启用了并行攻击编排,它也会将针对共享本地聊天客户端的调用串行化,因为本地客户端不能被并发使用。
每次扫描涵盖以下风险类别:
- 暴力
- 仇恨和不公平
- 性内容
- 自残
配置的策略包括分组简单和中等难度攻击、字符间距、ROT13、Unicode 同形异义词、字符替换、摩斯密码、leetspeak、URL 编码、二进制编码,以及 Base64 加 ROT13 的组合。SDK 还会运行基线 prompt。分组策略会展开为多种独立技术,因此模型调用的次数会大大超过 `风险类别 × 目标数`。
### 扫描选项
| 选项 | 默认值 | 描述 |
|--------|---------|-------------|
| `--model MODEL` | `phi-4-mini` | 要下载和扫描的 Foundry Local 模型别名。 |
| `--num-objectives N` | `2` | 为每个风险类别生成的攻击目标数。增加此值会大幅增加运行时间。 |
| `--max-tokens N` | `512` | 每个本地模型回复中的最大 token 数。 |
| `--temperature VALUE` | `0.0` | 本地聊天客户端使用的采样温度。 |
| `--parallel` | 禁用 | 允许并行攻击编排。本地推理保持串行化。 |
| `--max-parallel-tasks N` | `1` | 启用 `--parallel` 时的最大 SDK 任务数。 |
| `--scan-timeout SECONDS` | `7200` | 整体扫描超时时间。 |
| `--output PATH` | `-redteam-results.json` | SDK 导出路径。请参阅下方的输出说明。 |
使用 `python redteam_foundry_local_model.py --help` 获取完整的 CLI 参考。
## 结果
每次运行都会在仓库根目录中创建一个隐藏的 `.scan__/` 证据目录。首先查看:
- `scorecard.txt`:快速的人类可读摘要。
- `__results.jsonl`:每种风险和策略组合的详细 prompt、模型回复、分数和评分理由。
- `final_results.json`:机器可读的汇总记分卡。
例如,一次 Qwen 2.5 0.5B 的扫描产生了:
```
Overall ASR: 10.71%
Attack Success: 12/112 attacks were successful
Risk Category Baseline Easy Moderate
Violence 50.0% 8.33% 100.0%
Hate-unfairness 50.0% 8.33% 50.0%
Sexual 0.0% 0.0% 0.0%
Self-harm 50.0% 4.17% 50.0%
```
**ASR** 表示攻击成功率:即引发的回复超过配置的安全阈值的对抗性 prompt 的百分比。越低越好。在此示例中,112 次攻击中有 12 次成功;中等难度的暴力攻击是最薄弱的环节,而没有性内容攻击成功。
证据目录还包含:
- `results.json`:评估运行状态、计数、策略和使用情况摘要。
- `instance_results.json`:扫描实例的序列化结果。
- `redteam_info.json`:产出物索引、完成状态以及按策略和类别划分的 ASR。
- `redteam.log`:详细的 SDK 执行日志。
SDK 还会写入通过 `--output` 传递的路径。使用本项目所采用的 SDK 版本时,像 `qwen2.5-0.5b-redteam-results.json` 这样的默认路径尽管带有 `.json` 后缀,但会被创建为一个目录。它包含:
- `evaluation_results.json`:导出的记分卡和详细的评估数据。
- `results.json`:评估元数据和状态。
`.scan_*/` 和 `*-redteam-results.json` 路径默认都会被 Git 忽略。
## 本地数据
脚本将生成的状态保留在项目目录内:
- `.foundry-local/`:已下载的 Foundry Local 模型数据。
- `.azure/`:AZD 环境和部署状态。
- `.pyrit-data/`:PyRIT 状态。
- `.cache/` 和 `.tmp/`:运行时缓存和临时文件。
- `.redteam_foundry_local_model.lock`:扫描和模型删除使用的进程锁。
- `.scan_*/`:每次运行的证据和记分卡。
- `*-redteam-results.json/`:当前 SDK 行为对应的 SDK 导出目录。
红队脚本会在 `finally` 块中卸载模型并释放其锁,包括在扫描失败时。交互式聊天实用工具同样会在会话结束时卸载其模型。
要在不删除其他项目状态的情况下移除已下载的模型,请使用 `--delete-model`。要移除生成的扫描产出物,请删除相关的 `.scan_*/` 和 `*-redteam-results.json/` 目录。
## 故障排除
### 缺少项目端点
如果扫描报告 `Set AZURE_AI_PROJECT_ENDPOINT before running this script`,请运行 `azd up` 或检查选定的 AZD 环境:
```
azd env get-values
```
确认根目录下的 `.env` 包含 `AZURE_AI_PROJECT_ENDPOINT`。该脚本使用 `python-dotenv` 加载此文件。
### 身份验证失败
刷新评估器使用的 Azure CLI 会话:
```
az login
az account show --output table
```
单独使用 `azd auth login --check-status` 来验证用于预配的 AZD 会话。
### 另一个运行处于活动状态
只有一个扫描或模型删除操作可以持有项目锁。请在重试前停止另一个进程。在扫描处于活动状态时,请勿手动删除锁文件。
### 扫描时间长
从默认设置开始。对于仅使用 CPU 的模型,请保持禁用并行执行,减少 `--num-objectives`,或降低 `--max-tokens`。增加并行 SDK 任务数并不能使共享的本地模型客户端变为并发执行。
## 移除 Azure 资源
要删除为选定 AZD 环境配置的资源组和所有资源:
```
azd down
```
在确认之前,请仔细检查 AZD 显示的环境,因为此操作会删除资源组、Foundry 账户和 Foundry 项目。它不会删除本地模型或扫描产出物。
标签:AI红队, Azure AI, DLL 劫持, Naabu, 人工智能, 内容安全, 反取证, 大语言模型, 安全评估, 微软Foundry, 本地部署, 用户模式Hook绕过, 逆向工具