# TransitTruth 🛡️

[English](README.en.md) · 中文

![TransitTruth Banner](docs/banner_1280x640.png)

> **AI API 模型真实性核验 / 路由层可信度监控** — 无状态验证你用的模型是否货真价实。

> **⚡ 快速安装（一句话）**：需 **Python 3.10+（3.10–3.13 实测）**。PyPI 尚未发布，从源码装（逐行复制即可，PowerShell 5.1 不支持 `&&` 链式）：
> ```
> git clone https://github.com/dafahaha/transit-truth.git
> cd transit-truth
> pip install .
> ```
> （建议先 `python -m venv .venv` 建虚拟环境再装；装完 `transit-truth` 应在 PATH 里，找不到就重开终端/激活 venv，或用 `python -m app.cli --help`。完整说明与 `[reference]` 可选件见下方「📦 从源码安装」。）

---

## 🌐 一键在线体检（打开网页就能测，零安装）

不想装 Python？直接打开 GitHub Pages 在线版，粘贴你自己的中转 Base URL（可选临时/低额度 Key），由**你的浏览器直连你填写的端点**做可达性、协议结构与基础能力快检，输出 fail-closed 三态报告。Key 只存在本页内存、直接发往你自己填写的端点：**不经本项目任何服务器、不入库、不进 URL、不打印到日志**。

**在线版地址**：<https://dafahaha.github.io/transit-truth/docs/online/index.html>

![在线体检演示 GIF（本地 mock 端点录制）](docs/assets/online/online-demo.gif)

![可达 · insufficient_evidence 报告示例（本地 mock 录制）](docs/assets/online/verify-good.png)

**能力边界（先读）**：浏览器受 CORS 同源策略限制，多数中转端点读不到响应（页面会诚实提示改用本地 CLI / serve）；浏览器无行为参考分布、也跑不了 tiktoken BPE 计数，**在线版不会签发 pass**。完整行为指纹 + tokenizer 统计核验仍需本地 `transit-truth serve` / CLI。在线版结果是概率性辅助证据，不是密码学证明。

---

## 🚦 模型真实性核验（`transit-truth verify`）

新增的核心产品能力：给一个 OpenAI 兼容端点和它**声称**的模型名，跑一个**有界**探针电池，对比本地参考指纹，输出**单一机器可读 JSON 报告**与三态结论。

key 从环境变量读，不落盘、不进日志/报告。

```bash
# bash / macOS / Linux
export TRANSIT_TRUTH_API_KEY=sk-...
transit-truth verify --base-url https://your-relay.com/v1 --model gpt-4o-mini
```

```powershell
# Windows PowerShell（逐行执行）
$env:TRANSIT_TRUTH_API_KEY="sk-..."
transit-truth verify --base-url https://your-relay.com/v1 --model gpt-4o-mini
```

报告样例：

```json
{
  "claimed_model": "gpt-4o-mini",
  "verdict": "pass",
  "confidence": "medium",
  "statistics": {
    "matched_reference_model": "gpt-4o-mini",
    "posterior": 0.87,
    "tokenizer_consistency": {"score": 1.0, "verdict": "match"}
  },
  "disclaimer": "Probabilistic auxiliary evidence, NOT a cryptographic proof."
}
```

三态结论：`pass` / `suspicious` / `insufficient_evidence`（证据不足时**绝不硬判**）。

退出码对照表（脚本请以 JSON 的 `verdict` 字段为准，别只看退出码）：

| 退出码 | 含义 |
|---|---|
| `0` | `pass`（干净通过） |
| `1` | 运行错误（其它命令的未捕获异常）；裸跑 `transit-truth`（不带子命令）打印帮助并 exit 1 |
| `2` | 非 `pass`（核验错误报告，或 `insufficient_evidence`）；**argparse 参数/用法错误也归 2**（argparse 默认，实测） |
| `3` | `suspicious`（与参考显著不符） |

### 🖥️ 本地 Web UI（`transit-truth serve`）

不想敲命令？本地起一个网页，填地址/模型/可选 Key，浏览器里直接出三态报告：

```bash
transit-truth serve            # 默认 http://127.0.0.1:8766，加 --open 自动开浏览器
```

- Key 仅本次会话内存使用：**不落盘、不进日志、不进可分享报告**；默认只绑 `127.0.0.1`，绑定 `0.0.0.0` 需显式 `--allow-public`。
- 浏览器受 CORS 限制，多数中转端点无法被网页直读；**完整测试由本地服务端发探针**。GitHub Pages 在线版只做浏览器可达性/协议/基础能力快检（不出 pass），部署（Docker / VPS + Caddy / Cloudflare 边界）见 [docs/serve.md](docs/serve.md)。

**本地 Web UI 实机截图**（本地 `transit-truth serve` 对本地桩后端采集；无真实 Key，报告不含 Key）：

| 首页表单 | pass（行为证据支持） | insufficient_evidence（证据不足，不硬判） | suspicious（与参考显著不符） |
| --- | --- | --- | --- |
| ![本地 Web UI 首页](docs/demo_4.png) | ![pass 报告](docs/demo_1.png) | ![insufficient_evidence 报告](docs/demo_2.png) | ![suspicious 报告](docs/demo_3.png) |

**无付费 Key 的自托管参考后端**（用真实 tokenizer 生成参考指纹）。verify 客户端**强制要求一个非空 API key**（本地 reference-server 本身不校验它），所以先设一个 dummy 值：

```bash
# bash / macOS / Linux
export TRANSIT_TRUTH_API_KEY=local-dummy-no-billing
```

```powershell
# Windows PowerShell
$env:TRANSIT_TRUTH_API_KEY="local-dummy-no-billing"
```

注意：要开两个终端——终端 1 常驻 reference-server，终端 2 再跑 verify。

```text
# 终端 1：本地参考后端（常驻，别关）
transit-truth reference-server --model qwen2.5-0.5b-instruct --port 8765

# 终端 2：对它跑自检（逐行执行，不要写成带 \ 的多行）
transit-truth verify --base-url http://127.0.0.1:8765/v1 --model qwen2.5-0.5b-instruct --allow-local
```

**自检"理应"看到什么（免得把正确结果当成 bug）：**

| 安装方式 | reference-server 模式 | verify 结论（退出码） | 原因 |
|---|---|---|---|
| 直接 `pip install .`（未装 `[reference]`） | 诚实标注的 plumbing stub（`prompt_tokens` 是哈希占位、行为内容固定） | **`suspicious`（退出 3）** | 占位计数**故意不**匹配真实 Qwen 参考数 |
| `pip install ".[reference]"`（tokenizer 可下载时） | 真实本地 tokenizer；行为内容仍是确定性 stub | **`insufficient_evidence`（退出 2）** | tokenizer 计数匹配，但开源目录没有行为分布，无法认证 |

这次自检的目的是**证明管线端到端跑通、且绝不出 false `pass`**，**不是**拿到 `pass`。在此本地环回设置下看到 `suspicious` 是 fail-closed 的正确行为；若反而看到 `pass`，那才是 bug。另外：base-url 端口没人监听时，现在约 5 秒快速失败，报 `error.code = "endpoint_unreachable"`（不再耗满 90s 电池超时再误诊为 `battery_timeout`）。

> **无 tokenizers 时降级为 stub**：需要真实 tokenizer 计数时先 `pip install ".[reference]"`（从源码装、装 `tokenizers` 包）；reference-server 启动时若下载不到真实 tokenizer（网络受限，`HF_ENDPOINT` 默认 `https://hf-mirror.com`），会自动降级为**显式标注的 plumbing stub** 模式——`prompt_tokens` 只是哈希占位值、行为内容是 `stub-*` 固定串，服务启动 stderr 与 `GET /v1/models` 的 `mode`/`note` 会明确告诉你是 stub，**不会假装是真模型**。此时 verify 只能跑通管线，无法给出任何认证。
>
> **覆盖范围（诚实标注）**：当前自带参考指纹——
> - `gpt-4o-mini` 与 `gpt-4o`：n=50 基线，经**单个第三方中转站 wolfai.top 采集，非 OpenAI 官方端点**；只能声明这两个命名端点在该中转站可被区分，不是厂商无关指纹。
> - Qwen2.5-0.5B-Instruct：仅真实本地 tokenizer 计数，**无行为分布**，自身永远不可能给出 `pass`。
> - DeepSeek-R1-Distill-Qwen：派生自 Qwen2 tokenizer，计数无法与 Qwen 区分；GLM 已收录、tokenizer 下载 pending。
> - Claude / Gemini / 其它 GPT 声明的闭源指纹，需你提供自己的 key 采集。
>
> **定位声明**：黑盒结果是**概率性辅助证据，不是密码学证明，也不做真伪裁判**。`suspicious` 不等于"确定造假"。行为探针在 temperature=0 下退化为点质量，公开基线可被确定性回放（硬编码约 4 个众数字符串即可复现"匹配"），报告对此会显式标 `deterministic_replay_risk` 并把置信封顶——**官方密码学 attestation 才是终局，本工具只是概率性辅助**。详见 [docs/verify.md](docs/verify.md) 与 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。

Python SDK：`from app.verify import verify_endpoint`（可选 OpenTelemetry/OpenInference、DeepEval、Langfuse 集成见 `examples/`）。

下面保留的原有能力（行为指纹动物探针、Token 计费审计、社区排行榜、持续监控）均为**子模块**，见目录与下文各节。

---

## 🔥 我们发现了什么？

我们用27分钟、2600次API请求，发现了GPT模型的"行为指纹"：

| 探针 | gpt-4o-mini | gpt-4o | 正常随机 |
|---|---|---|---|
| 选1-10的数字 | **7（100%）** | 7（98%） | 每个数字10% |
| 掷骰子 | **4（96%）** | 4（56%） | 每个数字16.7% |
| 选随机动物 | Dolphin（16%） | **Okapi（76%!）** | 均匀分布 |
| 选随机字母 | **G/M（并列 40%）** | **K（44%）** | 每个字母3.8% |
| 选颜色 | Cerulean（74%） | Cerulean（92%） | 均匀分布 |

**关键发现：**
- gpt-4o-mini选1-10的数字，**100%返回7**（零方差！）
- gpt-4o选随机动物，**76%返回Okapi**（㺢㹢狓，罕见非洲长颈鹿近亲）
- 用"响应是否为 Okapi"这条简单规则，在**同一基准样本上**做重代入（resubstitution）得到 **88% 准确率**（Wilson 95%CI [0.80, 0.93]，bootstrap [0.81, 0.94]）。注意：动物探针的 TVD=0.90 是**分布距离**，不是分类准确率；这是 in-distribution 自洽检验，不是独立 held-out 准确率。

> **效度说明（务必先读）**：上述基准均通过**单个 OpenAI 兼容中转站（wolfai.top）**采集，**不是官方端点**。我们只声称"在该中转站，两个标称端点呈现可区分的行为画像"，不声称是与厂商无关的模型指纹；基准本身也继承了中转站实际提供的模型。官方金标准基线需要官方 API 访问，属未来工作。

这些"行为指纹"是训练数据和 RLHF 的产物；要在真实流量上伪造它，中转站需要实际返回真模型、后处理输出分布，或微调一个替身模型——成本不低，但并非"不可能"。

---

## 这是什么？

TransitTruth 是一个开源、无状态、本地可跑的 **中转站模型身份核验**工具：通过 CLI/SDK 与 `transit-truth serve` 本地浏览器界面，用行为指纹 + tokenizer 指纹 + 贝叶斯后验判断"你付费的端点实际返回的是不是所声称的模型"，API Key 只在会话内存、不落盘。

当前随包（`verify` 无状态核验 / `transit-truth serve` 本地 Web / CLI）主打能力：

- **🔍 模型身份核验**：你付了 GPT-4o 的钱，实际应答的是 GPT-4o、GPT-4o-mini 还是更小的模型？（tokenizer 指纹 + 行为探针 + 卡方/KS 检验 + 贝叶斯后验，三态 fail-closed）

> 说明：💰 Token 计费审计、⚡ 延迟/可用性/错误率性能监控、📋 OpenAI 响应格式协议合规、余额查询/低余额告警、持续监控与告警通道、🏆 社区排行榜/在线投稿，均属于**早期独立 web 平台（legacy `app.main`，需自行部署）**，**不包含**在当前 `verify`/`serve`/PyPI 随包路径中。

## 为什么需要这个？

通过中转站（relay）使用 LLM API 时，用户无法在技术上确认"应答的模型就是付费的那个"。由于大模型单价更高，中转站有经济动机用更小/更便宜的模型顶替旗舰模型，同时按旗舰计费。学术界已从工程与硬件路径提出对策：[arXiv:2504.04715](https://arxiv.org/abs/2504.04715)（Berkeley）主张用 **TEE（可信执行环境）**给出模型完整性的密码学证明（形式化/硬件路线，非商业端点实测统计），作为"官方 attestation 终局"的一类方案；本仓库则走轻量黑盒概率辅助路线。Token 计数虚高、费率不透明等问题也让自验证变得有必要。

但普通用户没有工具能核查自己用的中转站是否"参水分"。TransitTruth 就是为了给用户一个低成本、可复现的核查手段。

## 检测原理

### 1. 🧬 行为指纹（核心技术）

不同模型在"随机"任务上有强烈的分布偏好——这是训练数据和 RLHF 的产物。我们用 8 个英文行为探针（随机数 1-100、随机数 1-10、字母、颜色、抛硬币、掷骰子、动物、星期；另有 6 个中文文化探针，合计 14 个），每个采样 50 次，构建经验分布，再用**卡方检验 + KS 检验 + 贝叶斯更新**对比基准分布，计算模型匹配的后验概率。

> 响应做了归一化（如 "Heads." 与 "Heads" 合并、大小写统一）。

> **探针口径交叉标注（v0.4.7）**：旧分析子模块的探针目录含 14 个行为探针（8 英文 + 6 中文）；自托管 `verify` 电池只与"已采集参考"的探针重叠比对，shipped gpt-4o-mini 参考覆盖 **5 tokenizer + 8 behavioral**（其中多数为可确定性回放的模态/点质量探针），6 个中文行为探针尚无参考分布；10 个能力探针仅作辅助、不参与 pass/suspicious/insufficient 三态判定。默认电池 = 5 tokenizer + 4 behavioral×3 repeats = 17 请求。

**实测效果（同一中转站两个标称端点）：**
- gpt-4o-mini vs gpt-4o：**5/8 探针**统计显著差异（p<0.05；抛硬币探针在归一化后 TVD=0.08、未校正 Pearson 卡方 p=0.092，不再显著；经 Yates 连续性校正后 p≈0.206，两种口径下硬币均不显著，5/8 结论稳健）
- 最强区分探针（选动物）：TVD=0.90；"是否为 Okapi"规则的重代入准确率 **88%**（Wilson [0.80,0.93]）。TVD 是分布距离，不等于准确率。
- 整体管线：后验概率 **0.913**，95% 可信区间 [0.885, 0.937]。这是**基线样本对自身参考的 in-distribution resubstitution（自洽性检验）**，用于验证管线内部一致；**不是**独立数据上的 held-out 检测准确率。

### 2. 🔤 Tokenizer指纹

不同模型家族历史上使用不同的tokenizer（GPT用cl100k/o200k，Claude用自定义tokenizer，Gemini用SentencePiece）。发送精心构造的字符串（数字序列、CJK、emoji、代码、URL），对比token计数，可作为后端模型家族的**辅助线索**。

**弱信号，不可反推家族（v0.4.5 重校后诚实口径）**：重校基线后发现，不同家族的 tokenizer 在公开探针上可能高度趋同——Qwen2.5 的 tokenizer 与 o200k（gpt-4o）在电池 5 个探针中 **4 项完全相等**（仅 mixed-unicode 差 3 token）。因此 tokenizer 计数只是**弱信号**：满探针覆盖下 4/5 一致已判 `ambiguous` 而非 `match`，**不能据此反推模型家族**；行为指纹才是主判据，官方密码学 attestation（厂商签名响应）是唯一终局，本工具只是概率性辅助证据。

**局限**：不能区分同一家族的不同模型（如gpt-4o vs gpt-4o-mini）——这正是行为指纹的价值。

### 3. 🧠 能力测试

简单推理题、代码生成题、指令跟随测试、多语言翻译，区分高/中/低等级模型。

### 4. 💰 Token计数对比

将中转站返回的token计数与本地tiktoken精确计算对比，检测是否存在计费膨胀。同时估算chat template overhead，避免误判。

### 5. ⚡ 延迟与协议检查

测量延迟分布（P50/P95/P99）、错误率，验证响应结构、错误格式、响应头是否符合OpenAI API规范。

## 快速开始

### 🎬 离线演示（根 index.html，无需 Key）

打开根目录 [index.html](index.html)（GitHub Pages: https://dafahaha.github.io/transit-truth/）可以**先看演示**：一键体验完整审计流程，看到"声称 gpt-4o 实际降级"的典型场景。这是**离线/内置演示数据**，不连接任何真实中转站。

> 注：根 `index.html` 是**完全自包含的单页**，不依赖任何 CDN、不加载外部脚本、不发起任何外网请求；离线/无公网环境下也能完整打开。页面只做内置种子的离线演示，不发送 Key、不连接真实中转站。真实 tokenizer 与行为核验由本地 `transit-truth serve`（或 reference-server）在服务端完成。

### 🖥️ 真实模型身份核验（必须本地/自托管 `transit-truth serve`）

**注意：本 Pages 静态页不能直接测真实中转站。** 浏览器受 **CORS** 限制无法跨域直连第三方中转端点，在网页里填自己的 key 直接请求只会得到含糊的 `Failed to fetch`，且浏览器也不应把 key 交给目标域。要真实验证"声称的模型是不是货真价实"，请在本机或 VPS 跑本地服务（服务端发探针，页面只做表单+渲染）：

```bash
transit-truth serve            # 默认 http://127.0.0.1:8766，加 --open 自动开浏览器
```

Key 仅本次会话内存使用，不落盘/不进日志/不进分享报告；详见 [docs/serve.md](docs/serve.md)。

> 注：`standalone/index.html` 现为跳转到根 `index.html` 的重定向页。

### 🐳 使用Docker

> ⚠️ **legacy 提示**：下方 `docker-compose.yml` + `Dockerfile` 启动的是**早期 legacy `app.main` 审计 web 平台（无鉴权）**，已被 `Dockerfile.serve` + `docker-compose.serve.yml`（当前 verify Web UI）取代，**勿公网发布**。compose 默认只绑宿主 `127.0.0.1:8000`，请勿改成 `0.0.0.0` 或公网发布；需要对外服务请使用 serve 部署并前置 Caddy/Nginx + TLS。

```bash
docker-compose up -d
```

然后访问 http://127.0.0.1:8000 （仅本机；legacy API 无鉴权，不要发布到局域网/公网）

> 部署注意：compose 已显式 `user: "1000:1000"`（与 Dockerfile 内 `appuser` 对齐）。`./data` 挂载到容器 `/app/data` 后，该目录属主由**宿主目录**决定；若宿主 `./data` 对 UID 1000 不可写，请先在宿主 `sudo chown -R 1000:1000 ./data`，否则首次写 SQLite 会因 EACCES 返回 500。

> 反向代理与限流：限流默认按 **TCP 对端 IP** 分桶，因此直连部署最安全（调用方无法伪造 `X-Forwarded-For` 换配额桶）。若必须把本服务放在 nginx / 云 LB 之后，请设置环境变量 `TRUSTED_PROXIES=<代理IP,逗号分隔>`，例如 `TRUSTED_PROXIES=10.0.0.1,10.0.0.2`。只有当请求的 TCP 对端落在可信代理列表内时，服务才会解析 `X-Forwarded-For`（从右向左跳过可信代理后取第一个不可信跳作为真实客户端 IP）；未配置时即使客户端带了 `X-Forwarded-For` 也会被忽略。请勿把公网客户端 IP 加入 `TRUSTED_PROXIES`。
>
> 两个部署前提：① 上述右向左解析**依赖每个可信代理在 `X-Forwarded-For` 右侧追加自身地址**——nginx 请用 `proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;`，切勿用 `$http_x_forwarded_for` 原样透传（否则客户端在左侧伪造的 IP 会被当成真实客户端）。② 限流计数器是**进程内**状态，`uvicorn --workers N>1` 时各 worker 独立计数，实际配额约为单 worker 的 N 倍；需要严格全局配额请前置统一网关或改用外部存储限流。
>
> 审核与内存快照：`python -m app.moderation approve` 会把 `contributions.status='approved'` 落库并原子写入排行榜行，但**正在运行的 web worker** 里那个信誉系统实例是启动时从 DB 载入的内存快照，不会自动感知这次 approve——其 `get_contributor_stats` / `get_top_contributors` 的 `valid_contributions` 计数会保持陈旧，直到 worker 重启。如需立即反映到前端贡献者计数，请在 CLI approve 后滚动重启 web worker（systemd `restart=always` 或 k8s rolling restart 均可）；排行榜数据本身读 DB，不受此影响。

### 💻 本地运行

```bash
cd backend
pip install -r requirements.txt
uvicorn app.main:app --host 0.0.0.0 --port 8000
```

然后访问 http://localhost:8000

> ⚠️ **公开绑定风险（legacy `app.main`）**：上面的 `--host 0.0.0.0` 会把服务发布到**所有网卡**，任何能访问该端口的人都可触达——默认应只绑 `127.0.0.1`。确需公开暴露时，你必须自行承担鉴权、暴露与被当作探测代理的风险，并显式开启对应公开门控（不要裸 `0.0.0.0` 直接对外）。注意：这是早期 legacy web 平台的启动方式，与当前无状态 `verify` / 本地 `transit-truth serve`（默认仅 `127.0.0.1`、`--allow-public` 才放开）是两条独立路径。

### 📦 从源码安装（CLI）

<!-- PYPI-FLIP：发布到 PyPI 后，把下面整段替换为 `pip install transit-truth`
     （真实 tokenizer 用 `pip install "transit-truth[reference]"`），并删除
     "PyPI 上没有"这句话；具体清单见 docs/PUBLISHING.md 的 post-publish checklist。 -->
PyPI 上**尚未发布** `transit-truth` 包，当前请从源码安装。**需要 Python 3.10 及以上（3.10–3.13 实测）**：

```text
git clone https://github.com/dafahaha/transit-truth.git
cd transit-truth
python -m venv .venv
# 激活虚拟环境：
#   bash / macOS / Linux: source .venv/bin/activate
#   Windows PowerShell:   .venv\Scripts\Activate.ps1
# 普通用户：pip install .
# 贡献者（可编辑）：pip install -e .
```

key 从环境变量读（位置传 sk-xxx / --api-key sk-xxx 会在进程列表可见，仅兼容告警）：

```bash
# bash / macOS / Linux
export TRANSIT_TRUTH_API_KEY=sk-your-key
transit-truth verify --base-url https://your-relay.com/v1 --model gpt-4o
```

```powershell
# Windows PowerShell
$env:TRANSIT_TRUTH_API_KEY="sk-your-key"
transit-truth verify --base-url https://your-relay.com/v1 --model gpt-4o
```

装完后 `transit-truth` 命令应在你的 PATH 中（位于 Python 的 `Scripts`/`bin` 目录）。如果终端找不到它：重开终端、确认虚拟环境已激活，或直接用模块方式调用 `python -m app.cli --help`。

（后端方式见上方"本地运行"：`cd backend; pip install -r requirements.txt`。）

> 说明：`audit` / `list` / `export` / `benchmark` / `balance` 是早期 legacy web 平台遗留的子命令（`--help` 已标注 legacy），**不属于**当前随包的 `verify`/`serve` 路径，新用户请直接使用 `verify`、`reference-server`、`serve`。

## 使用方法

当前无状态模型身份核验（测中转站真假）有两个入口：

**1. 本地 Web UI（推荐，浏览器点选）**

```bash
transit-truth serve                 # 默认 http://127.0.0.1:8766
transit-truth serve --open          # 自动打开浏览器
```

填写中转站 `base_url`、声称模型（可从参考目录选择或手填）、可选 API Key，采样数/超时可在高级项折叠设置，点"开始核验"得到三态报告（pass / suspicious / insufficient_evidence）。Key 仅存于本次会话内存，不落盘、不进日志、不进可分享报告。

**2. CLI（一行命令）**

```bash
# bash / macOS / Linux
export TRANSIT_TRUTH_API_KEY=你的key
transit-truth verify --base-url https://relay.example/v1 --model gpt-4o-mini
```

```powershell
# Windows PowerShell
$env:TRANSIT_TRUTH_API_KEY="你的key"
transit-truth verify --base-url https://relay.example/v1 --model gpt-4o-mini
```

> 真实核验必须在本地/自托管 `serve`（或 CLI）进行：浏览器跨域直连中转站端点受 CORS 限制，GitHub Pages 只能托管离线演示/引导，不能在线实测。详见 [docs/serve.md](docs/serve.md)。

## 功能特性

### ✅ 已实现

#### 当前随包能力（`verify` 无状态核验 / `transit-truth serve` 本地 Web / CLI）
- [x] **行为指纹验证**（内置行为探针库：卡方检验 + KS 检验 + 贝叶斯更新）
- [x] **Tokenizer 指纹**（内置 tokenizer 探针库；离线用 o200k 重算基线 token 计数）
- [x] **统计不确定性量化**（贝叶斯后验 + 95% 可信区间 + 样本充分性评估）
- [x] **客户端弹性**（指数退避重试 + 请求超时 + 429 限流退避；**无**断路器）
- [x] **浏览器离线演示**（零安装，内置种子演示数据，非真实端点实测，不发送 Key）
- [x] **CLI 工具**（`verify` / `reference-server` / `serve`；无状态、单一 JSON 输出）
- [x] **真实基准数据库**（gpt-4o-mini、gpt-4o，各 50 样本）
- [x] **本地 `transit-truth serve`**（仅绑 127.0.0.1，Key 仅在会话内存、不落盘/不进日志/不进报告）
- [x] **`reference-server`**（自托管 OpenAI 兼容参考后端，离线生成/比对参考指纹，不向云付费）

#### 历史 web 平台遗留（legacy `app.main`，需自部署；**不在** `verify`/`serve`/PyPI 随包路径）
> 以下特性来自早期独立 web 平台子模块，当前 `verify`/`serve` 随包**不包含**余额告警、持续监控、在线排行榜/投稿端点；仅在你自部署 legacy `app.main` 时才存在。
- [ ] **余额查询**（多中转站账户余额聚合，低余额自动告警）— legacy
- [ ] **模型参考数据**（14个模型的公开数据：价格/ELO/智能指数/延迟）— legacy
- [ ] **Web UI**（4个Tab，步骤式表单，进度条，苹果风格设计）— legacy
- [ ] **社区排行榜**（全民共建，贡献者信誉系统）— legacy；**当前 serve 无在线排行/投稿端点**
- [ ] **持续监控+告警**（4种告警检测，4种告警通道）— legacy
- [ ] **能力测试**（10 个能力探针，模型等级估算）— legacy；verify 有界电池不跑能力探针
- [ ] **Token 计费审计**（tiktoken 精确计算，差异率检测）— legacy；verify 内 tiktoken 仅用于离线基线 token 计数重算，不对活端点做计费差异检测
- [ ] **延迟与协议检查**（P50/P95/P99，7 项 OpenAI 响应格式协议合规）— legacy
- [ ] **HTML 报告生成**（可分享的审计报告）— legacy
- [ ] **审计结果分享卡片**（1200x630 PNG，一键下载分享社交媒体）— legacy
- [ ] **灵活配置管理**（legacy web 的 14 个环境变量）— legacy；`serve` 使用自己的少量旋钮（max_requests/behavioral_samples/timeout/total_timeout）
- [x] **测试**：实测 **378 passed / 7 skipped**（385 collected；v1–v5 累计新增无状态核验、指纹库、序贯检验、加固与集成测试；v0.4.2 诚实性/抗回放、v0.4.3 饥饿式样本绕过回归、v0.4.4 覆盖率门+tokenizer 口径、v0.4.5 版本一致性+tokenizer 严格匹配回归、v0.4.6 单字段容错+stdout 单一 JSON 契约+负 verdict 自洽回归、v0.4.7 非 JSON 200 响应体容错+tokenizer 不确定带不升级 pass 回归、v0.5.0 本地 Web serve 端点+key 不落盘/不进日志/脱敏+公共绑定门控回归、v0.5.1 serve XSS 转义+Origin/Host/Content-Type 守卫+绑定门控+Docker 修正回归、v0.5.2 wheel 打包 webapp+全局 Host/Origin 守卫+NaN/Infinity 拒绝+上游错误体不泄漏 key 回归、v0.5.3 门面模块崩溃修复+非法参数 400+非阻塞 429、v0.5.4 消除外链静态 import+整数旋钮非整 400+CI 守卫/checkout 升级、v0.5.5 hard-cap 理由自洽+错误页人话+守卫扩面+严格整数串+Host fail-closed、v0.5.6 错误码映射对齐+hard-cap 证据标签拆分+IPv6 环回放行+守卫扩面、v0.5.7 hard-cap 两分支变异可失败+双向错误码守卫+静态守卫补盲+弱 pass 强制 low、v0.5.8 开篇/能力清单诚实分区+弱 pass band 边界钉、v0.5.9 参考目录缺失/空目录 fail-loud stderr 警告+sync 陈旧 JSON prune）；其中端到端桩测试离线可跑，真实 API key 集成测试用 `pytest -m integration` 单独运行
- [x] **CI/CD**（GitHub Actions，Python 3.10/3.11/3.12/3.13 矩阵）

### 🚧 开发中
- [ ] 更多模型基准数据（Claude、Gemini、Llama、Qwen）
- [ ] 增加基准样本量到200+（当前 50 样本；76%/88% 的 Wilson 95% 区间半宽约 ±6~12 个百分点，为 resubstitution 口径）
- [ ] 浏览器插件（实时审计正在使用的API）
- [ ] 移动端适配

## 学术背景

本项目基于以下学术研究：

- **[One Token Is Enough](https://arxiv.org/abs/2607.10252)** (arXiv:2607.10252, 2026) — 在 OpenRouter 165 个模型上做 split-half 生物特征式验真（AUC 0.971；165 genuine / 27060 impostor；8 cell 时 EER 10.6%）；这是模型生物特征验真，**不是替换攻击检出率**
- **[CoIn](https://arxiv.org/abs/2505.13778)** (arXiv:2505.13778, 2025) — 隐藏推理token计数审计框架，检测token数膨胀（94.7%成功率）
- **[RAFP](https://arxiv.org/abs/2505.12682)** (arXiv:2505.12682, 2025) — Rare-region 指纹，识别 LLM 谱系，对微调/量化稳健
- **[Model Provenance Testing](https://arxiv.org/abs/2502.00706)** (arXiv:2502.00706, 2025) — 黑盒模型来源测试

我们的工作定位：
1. **同家族细粒度区分**：在两个标称同家族端点（gpt-4o vs gpt-4o-mini）上展示行为画像可被区分（最强 TVD=0.90）；这是 tokenizer 指纹做不到的。我们**不**声称这是"首个"此类研究，也不声称已在独立 held-out 数据上验证泛化。
2. **可本地运行的核验内核**：随包交付无状态 `verify` CLI/SDK、本地 `transit-truth serve` 浏览器界面与本地 `reference-server`；在线排行榜/在线审核平台属早期 legacy web 平台，**不随包发货**
3. **中文社区优先**：面向中文用户，解决国内中转站乱象
4. **零门槛离线演示**：根 index.html 浏览器即用（内置演示数据；真实模型身份核验走本地 `transit-truth serve`）

### 相关工作与已上线竞品（诚实对标）

本赛道已相当拥挤，我们**不**是首个做中转站审计的工具。已上线的同类项目：

| 项目 | 状态 | 与本项目重叠 |
|---|---|---|
| **knowlyr-modelaudit**（PyPI，MIT） | 已上线 CLI+MCP，行为指纹+蒸馏检测 | 与 `verify` SDK/CLI 几乎同定位 |
| **zing-audit**（PyPI） | local-first CLI，审计偷换/截断上下文/假流式/计费虚高 | 与 CLI 直接同赛道 |
| **veridrop.org**（开源） | 官网自称覆盖约 11878 家中转站（含付费展示位，非中立实测榜），贝叶斯加权红黑榜 | 与"排行榜/买徽章"方向**直接撞车且已规模化**——该身位已被占据 |
| **IRIS**（arXiv:2607.20860） | 纯文本自定预算审计，联合检测整流替换与分数稀释并估计 ε；Qwen3 家族内 0.99 AUROC | 已覆盖本仓库"ε-稀释预算化检验"的核心思想 |
| **KBF**（arXiv:2605.29524） | 知识边界指纹（受控池结果）：budget-tier 替身在被替换流量低于 7% 即可检出；强同档替身在 13–35% 替换流量达 80% TPR（MDR₉₅ 约 16–43%）；受控 155 对经济相关替换全检出、0 同模型误拒；**这是可检测比例下限，不是错误率** | 覆盖 ε-稀释场景 |
| **truthprobe**（GitHub+PyPI） | **[DEPRECATED]** PyPI 自述已弃用，后继转 npm `truthprobe-mcp`（`npm install -g truthprobe-mcp`），旧 LLM 审计 CLI 不再维护 | 与 `verify` 同定位（已弃用） |
| **token-difr**（PyPI） | 基于 **Gumbel-Max 采样核验**（Gumbel-Max sampling verification）比对生成输出，非纯 log-prob 比对 | Gumbel-Max 采样核验路线，与自报 token 计数是不同信号 |
| **TokensQC**（tokensqc.com） | 在线 AI API 质检：协议一致性 / 模型身份 / 延迟探针（页面含赞助位） | 同定位在线工具 |
| **Ztest 真测**（ztest.ai） | 中转站模型真伪检测 + 可信度排行（付费榜单，非中立实测） | 与"红黑榜"方向直接撞车 |
| **大模型照妖镜**（llmtest.cn） | 个人维护的多维度套壳检测（纯前端，基于 GitHub 开源项目） | 同定位在线工具 |

> **勘误（v0.5.1）**：早先表中误把 bazaarlink.ai 列为"84 项规则 Probe 检测器"、把 tosea.ai 列为"随机数行为指纹工具"。经复核：**BazaarLink（bazaarlink.ai）实为多模型聚合 API 网关/计费路由**（OpenAI/Anthropic/Google 等单 endpoint 聚合），并非模型真伪检测器，故移出检测器对比表；**Tosea.ai 实为 PDF/论文转幻灯片的生成工具**，与 LLM 身份核验无关，已删除该行。

我们的真实身位（二次工程集成，**非方法论创新**）：
- **三态 fail-closed JSON 报告契约**（`pass / suspicious / insufficient_evidence`，证据不足绝不硬判）；
- **自托管 / 可嵌入**（无 SaaS、无排行榜）：`verify` SDK 与 `reference-server` 可嵌入 Agent/网关做准入，与 zing-audit 错位竞争；
- **中文开源模型 tokenizer 目录**——但需诚实说明其**当前规模是 1 个模型的 PoC**（见下）。

> **关于"预算化 ε-稀释检验"**：`backend/app/verify/sequential.py` 的样本量/检出力计算是闭式工程估算工具，用于回答"给定预算 N 与稀释 ε，能否检出掺假"。方法层面 IRIS（arXiv:2607.20860）已做过预算化审计与 ε 估计，我们此处只是一个实用辅助计算器，**不声称方法论原创**。
>
> **指纹库覆盖现状（诚实标注）**：`data/fingerprints/` 当前仅 **Qwen2.5-0.5B-Instruct 一个模型的真实 tokenizer 计数 PoC**（7 个探针，无行为分布）；GLM tokenizer 因镜像限流 pending；DeepSeek-R1-Distill-Qwen 派生自 Qwen2 tokenizer（计数相同，tokenizer 无法区分两者）。GPT/Claude/Gemini 闭源指纹需用户自配 key 采集。tokenizer 信号分两种情形：① **tokenizer 匹配但无行为参考**——只能说明同族，**不得输出 `pass`**，结论封顶 `insufficient_evidence`；② **tokenizer 不匹配（错族）**——会计 `mismatch` 并升级为 `suspicious`（覆盖行为统计结果，同时置空 posterior/LR/CI/卡方以免自相矛盾）。

## 真实基准数据

我们开源了真实采集的模型基准数据（经同一 OpenAI 兼容中转站 wolfai.top 采集，非官方端点）：

| 模型 | 样本数 | 探针数 | 总请求 | 采集时间 | 文件 |
|---|---|---|---|---|---|
| gpt-4o-mini | 50 | 26 | 1300 | 15 分钟 | `data/baselines/gpt-4o-mini.json` |
| gpt-4o | 50 | 26 | 1300 | 12 分钟 | `data/baselines/gpt-4o.json` |

> **开发期样本说明**：`data/baselines/dev_samples/` 下的 `gpt-4o-mini-test.json`、`gpt-4o-mini-concurrent-test.json` 是早期 3→5→50 采样的开发期增量样本，已移出正式基线目录。`load_real_baselines` 仅加载上表两个正式文件（子目录内文件不参与 glob，且文件名含 "test" 显式跳过），这些样本不进入任何分析。

> **数据缺口披露（gpt-4o-mini）**：mini 的 tokenizer 探针未全部拿到可用样本——`tok-digits`、`tok-cjk`、`tok-emoji` 三个探针零可用响应（冷启动限流），`tok-whitespace` 仅 37/50 条可用；实际拿到可用样本的 tokenizer 探针为 5/8（4 个 n=50、1 个 n=37）。上表"26 探针 / 1300 请求"为设计口径（gpt-4o 侧为完整 26/1300）。所有头条行为指纹结论（Okapi、TVD=0.90、后验 0.913 等）均来自 8 个 n=50 齐全的 behavioral 探针，不受此缺口影响。

数据采集脚本：`collect_baseline.py`（支持并发，用任何 OpenAI 兼容 API 即可）；分布/TVD/卡方/分类器表格由 `docs/generate_tables.py` 从 JSON 自动生成。

## 学术产出（Tech Report）

本项目的实验方法、数据与结论整理为**扩展技术报告（extended technical report）**（含完整方法论/公式推导/统计检验/跨模型对比/Threats to Validity/可复现性附录）：

- 📄 **PDF版**：[Behavioral Fingerprinting of Large Language Models — Extended Tech Report](docs/tech_report.pdf)
- 🌐 **HTML版**：[tech_report.html](docs/tech_report.html)（在线阅读）
- 📝 **Markdown源**：[experiment_report.md](docs/experiment_report.md)
- 🧾 **Workshop投稿版（双盲精简版，LaTeX）**：[paper/](paper/) · [paper/main.pdf](paper/main.pdf)

**核心结论（均为同一中转站、in-distribution 结果）：**
- 行为画像能区分同家族两个标称端点（tokenizer 指纹做不到）
- 最强探针 TVD=0.90；"是否为 Okapi"规则重代入准确率 88%（Wilson [0.80,0.93]）；TVD≠准确率
- 管线自洽检验后验 0.913（CrI [0.885,0.937]），为 resubstitution，非 held-out
- 单次审计按公开低档定价估算约 < $0.01（实际取决于模型档位与 token 单价，代码内无计价逻辑）

**与前沿工作的关系**：我们的行为画像方法与 [One Token Is Enough](https://arxiv.org/abs/2607.10252)（OpenRouter 165 模型 split-half 生物特征验真，AUC 0.971；非替换攻击检出率）互为补充——它聚焦模型生物特征验真/谱系识别，我们在同家族两个标称端点上展示了可区分性；官方金标准基线与 held-out 泛化验证属未来工作。

## 项目结构

```
transit-truth/
├── index.html                  # 浏览器离线演示（GitHub Pages 入口；真实核验走 webapp/ + serve）
├── web/                        # Web 资源
├── standalone/index.html       # 跳转页（重定向到根 index.html）
├── backend/                    # Python 后端（FastAPI）
│   ├── app/
│   │   ├── core/              # 核心引擎（auditor/fingerprint/probes/
│   │   │                      #   statistical_analyzer/retry/balance_checker/...）
│   │   ├── verify/            # 无状态模型真实性核验（v1–v5：battery/reference/
│   │   │                      #   report/sequential/otel/reference_server）
│   │   ├── api/               # REST API
│   │   ├── utils/             # 工具函数
│   │   ├── config.py          # 配置管理（14 个环境变量）
│   │   ├── tests/             # 离线桩 e2e + 统计/加固/集成测试（计数见顶部"测试"行）
│   │   └── main.py            # FastAPI 入口
│   └── requirements.txt
├── webapp/                     # transit-truth serve 本地 WebUI（随包分发）
├── data/
│   ├── baselines/              # 真实基准数据（经同一中转站采集）
│   │   ├── gpt-4o-mini.json
│   │   └── gpt-4o.json
│   └── fingerprints/           # 开源参考指纹目录（Qwen 真实 tokenizer 计数等）
├── docs/
│   ├── tech_report.tex         # 扩展技术报告 LaTeX 源
│   ├── tech_report.pdf / .html # 扩展技术报告
│   ├── experiment_report.md    # 实验报告 Markdown 源
│   ├── generate_tables.py      # 从 JSON 自动生成分布/TVD/卡方/分类器表
│   ├── make_fig.py             # 重画 fig_results.png
│   └── ...
├── paper/                      # 双盲精简 workshop 版（main.tex / main.pdf / fig_results.png）
├── examples/
├── collect_baseline.py         # 基准数据采集脚本（支持并发）
├── analyze_baseline.py         # 基准数据分析脚本
├── compare_models.py           # 跨模型对比分析脚本
├── Dockerfile / docker-compose.yml
├── pyproject.toml              # 源码安装配置（pip install -e .）
├── CHANGELOG.md / CONTRIBUTING.md / CODE_OF_CONDUCT.md / LICENSE
└── README.md
```

## 贡献指南

我们欢迎所有形式的贡献！

- **提交基准数据**：用`collect_baseline.py`采集你常用模型的基准数据，提交PR
- **分享审计结果**：用工具审计你使用的中转站后，把结果发到 [GitHub Discussions → Show your audit results](https://github.com/dafahaha/transit-truth/discussions)；请勿在公开帖子中粘贴 API Key。本项目没有在线排行榜或投稿端点。
- **开发新功能**：看GitHub Issues，认领任务
- **写文档/教程**：帮助更多人用上这个工具
- **报告Bug**：提交Issue，我们会尽快修复

详见 [CONTRIBUTING.md](CONTRIBUTING.md)

## 免责声明

1. 本工具仅供学习和研究使用，请勿用于非法用途
2. 审计结果基于统计分析，仅供参考，不构成法律证据
3. 请遵守目标API服务的使用条款，不要对服务造成过大压力
4. 标记中转站为"可疑"不等于"确定造假"，请结合多方面信息判断
5. 本工具不对任何中转站的商业行为负责

## 许可证

MIT License

## 联系方式

- GitHub Issues：https://github.com/dafahaha/transit-truth/issues
- 邮箱：156556011+dafahaha@users.noreply.github.com

---

**如果你觉得这个工具有用，请给个Star ⭐，让更多人看到。**

> "你用的 GPT-4 是真的吗？本地 `transit-truth serve` 发探针比对行为指纹与 tokenizer，给出 fail-closed 的三态证据。"
