sothstan 0.1.0rc1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sothstan-0.1.0rc1/LICENSE +21 -0
- sothstan-0.1.0rc1/PKG-INFO +195 -0
- sothstan-0.1.0rc1/README.md +165 -0
- sothstan-0.1.0rc1/pyproject.toml +54 -0
- sothstan-0.1.0rc1/setup.cfg +4 -0
- sothstan-0.1.0rc1/src/sothstan/__init__.py +29 -0
- sothstan-0.1.0rc1/src/sothstan/_version.py +3 -0
- sothstan-0.1.0rc1/src/sothstan/audit.py +210 -0
- sothstan-0.1.0rc1/src/sothstan/baseline.py +165 -0
- sothstan-0.1.0rc1/src/sothstan/baselines/_demo_aqua-70b.json +163 -0
- sothstan-0.1.0rc1/src/sothstan/baselines/_demo_breeze-8b.json +163 -0
- sothstan-0.1.0rc1/src/sothstan/cli.py +307 -0
- sothstan-0.1.0rc1/src/sothstan/compare.py +124 -0
- sothstan-0.1.0rc1/src/sothstan/http.py +284 -0
- sothstan-0.1.0rc1/src/sothstan/mockserver.py +298 -0
- sothstan-0.1.0rc1/src/sothstan/probes/__init__.py +22 -0
- sothstan-0.1.0rc1/src/sothstan/probes/adversarial.py +86 -0
- sothstan-0.1.0rc1/src/sothstan/probes/base.py +53 -0
- sothstan-0.1.0rc1/src/sothstan/probes/canon.py +48 -0
- sothstan-0.1.0rc1/src/sothstan/probes/errors.py +48 -0
- sothstan-0.1.0rc1/src/sothstan/probes/limits.py +74 -0
- sothstan-0.1.0rc1/src/sothstan/probes/reasoning.py +63 -0
- sothstan-0.1.0rc1/src/sothstan/probes/template.py +67 -0
- sothstan-0.1.0rc1/src/sothstan/probes/token_count.py +99 -0
- sothstan-0.1.0rc1/src/sothstan/py.typed +0 -0
- sothstan-0.1.0rc1/src/sothstan/report.py +102 -0
- sothstan-0.1.0rc1/src/sothstan/runner.py +253 -0
- sothstan-0.1.0rc1/src/sothstan/types.py +51 -0
- sothstan-0.1.0rc1/src/sothstan/verdict.py +155 -0
- sothstan-0.1.0rc1/src/sothstan.egg-info/PKG-INFO +195 -0
- sothstan-0.1.0rc1/src/sothstan.egg-info/SOURCES.txt +42 -0
- sothstan-0.1.0rc1/src/sothstan.egg-info/dependency_links.txt +1 -0
- sothstan-0.1.0rc1/src/sothstan.egg-info/entry_points.txt +2 -0
- sothstan-0.1.0rc1/src/sothstan.egg-info/requires.txt +4 -0
- sothstan-0.1.0rc1/src/sothstan.egg-info/top_level.txt +1 -0
- sothstan-0.1.0rc1/tests/test_adversarial.py +93 -0
- sothstan-0.1.0rc1/tests/test_audit.py +152 -0
- sothstan-0.1.0rc1/tests/test_baseline_schema.py +65 -0
- sothstan-0.1.0rc1/tests/test_cli_and_report.py +99 -0
- sothstan-0.1.0rc1/tests/test_client.py +92 -0
- sothstan-0.1.0rc1/tests/test_iter1_fixes.py +135 -0
- sothstan-0.1.0rc1/tests/test_mock_tokens.py +33 -0
- sothstan-0.1.0rc1/tests/test_pipeline.py +108 -0
- sothstan-0.1.0rc1/tests/test_scoring.py +102 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 sothstan contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sothstan
|
|
3
|
+
Version: 0.1.0rc1
|
|
4
|
+
Summary: The Trial of the Hidden Voice (Sothstan) | Statistical audits for LLM API endpoints
|
|
5
|
+
Author: sothstan contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/cloudydreamland/TheTrialOfTheHiddenVoice
|
|
8
|
+
Project-URL: Repository, https://github.com/cloudydreamland/TheTrialOfTheHiddenVoice
|
|
9
|
+
Project-URL: Issues, https://github.com/cloudydreamland/TheTrialOfTheHiddenVoice/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/cloudydreamland/TheTrialOfTheHiddenVoice/blob/main/CHANGELOG.md
|
|
11
|
+
Project-URL: Security, https://github.com/cloudydreamland/TheTrialOfTheHiddenVoice/security/policy
|
|
12
|
+
Keywords: llm,api,fingerprint,verification,chinese,relay,模型验真
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Security
|
|
22
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
28
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# The Trial of the Hidden Voice — Sothstan
|
|
32
|
+
|
|
33
|
+
简体中文 · [English](README.en.md)
|
|
34
|
+
|
|
35
|
+
> 展示名 **The Trial of the Hidden Voice** 描绘对隐匿声音的审视;Sothstan 是该项目的短名。
|
|
36
|
+
|
|
37
|
+
**中文优先的 LLM API 模型验真库。一个端点声称自己在服务模型 X——它真的在服务 X 吗?**
|
|
38
|
+
用多层指纹 + 混淆集似然比给出统计判决,证据链哈希锁定,可复现、可审计。
|
|
39
|
+
|
|
40
|
+
[](.github/workflows/ci.yml)
|
|
41
|
+
[](pyproject.toml)
|
|
42
|
+
[](LICENSE)
|
|
43
|
+
|
|
44
|
+
## 为什么需要它 / Why
|
|
45
|
+
|
|
46
|
+
第三方中转、代理或聚合 API 往往会返回一个自报模型名。仅凭这个字段无法验证端点的实际行为是否与所声明模型一致;差异也可能来自版本变化、采样参数、服务策略或网络错误。Sothstan 用可信基线比较多种行为信号,并保留统计结果和不确定性。
|
|
47
|
+
|
|
48
|
+
## 安装 / Install
|
|
49
|
+
|
|
50
|
+
> 当前尚未发布到 PyPI;下方给出从 GitHub 获取并本地安装的命令。
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
git clone https://github.com/cloudydreamland/TheTrialOfTheHiddenVoice.git
|
|
54
|
+
cd TheTrialOfTheHiddenVoice
|
|
55
|
+
python -m pip install .
|
|
56
|
+
# PyPI 首发后:python -m pip install sothstan
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 快速开始 / Quickstart
|
|
60
|
+
|
|
61
|
+
**没有官方 API key?先离线验证工具本身**(内置 mock 模型与四种攻击场景):
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
sothstan selftest
|
|
65
|
+
# PASS 诚实服务器 → AUTHENTIC
|
|
66
|
+
|
|
67
|
+
# PASS 换模型中转 → MISMATCH(runner-up 正确指认)
|
|
68
|
+
|
|
69
|
+
# PASS 仅改 model 字段 → 仍 AUTHENTIC(字段回显零权重)
|
|
70
|
+
|
|
71
|
+
# PASS 伪造 usage 的说谎中转 → 仍 MISMATCH(行为/错误层暴露)
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
有 key 之后,两步验真:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# 第一步:对【官方】端点采集基线(至少 2 个模型,互为混淆集)
|
|
79
|
+
|
|
80
|
+
sothstan collect https://api.deepseek.com/v1 --model deepseek-chat \
|
|
81
|
+
--family deepseek --out baselines/deepseek-chat.json --api-key-env DEEPSEEK_API_KEY
|
|
82
|
+
sothstan collect https://api.deepseek.com/v1 --model deepseek-reasoner \
|
|
83
|
+
--family deepseek --out baselines/deepseek-reasoner.json --api-key-env DEEPSEEK_API_KEY
|
|
84
|
+
|
|
85
|
+
# 第二步:验证可疑端点
|
|
86
|
+
|
|
87
|
+
sothstan check https://relay.example.com/v1 --model deepseek-chat --api-key-env RELAY_KEY
|
|
88
|
+
# ✅ AUTHENTIC margin +212.4 证据链 9f3a… exit 0
|
|
89
|
+
|
|
90
|
+
# ❌ MISMATCH runner-up: deepseek-reasoner exit 2
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## 工作原理 / How it works
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
探测(probe)──产出──> 指纹信号(signal)──对比──> 基线(baseline,官方端点采集)
|
|
98
|
+
│
|
|
99
|
+
混淆集似然比(claimed vs 全部竞争模型)
|
|
100
|
+
│
|
|
101
|
+
判决 AUTHENTIC / SUSPICIOUS / MISMATCH / INCONCLUSIVE
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
- **tier-1 确定性层**:`usage` 自报 token 曲线(20 篇 canonical 文本,CJK 分歧最大)、
|
|
105
|
+
chat template 开销、max_tokens 限额、logprobs/n 参数支持、错误码族
|
|
106
|
+
- **tier-2 行为层**:思维链形态、风格标记、reasoning 字段
|
|
107
|
+
- **混淆集比较**是方法核心:冒充者通常与目标同家族(r1 冒充 v3),"像不像"没有意义,
|
|
108
|
+
"证据更支持谁"才有意义;且 claimed 总分低于硬地板时直接 MISMATCH——
|
|
109
|
+
**token 层再像也淹没不了行为层的全面矛盾**(mock 实验可复现)
|
|
110
|
+
- **零权重展示项**:响应体 `model` 字段回显——改字段是最廉价的伪造,报告里可见但不计分
|
|
111
|
+
|
|
112
|
+
内置 mock 服务器(Aqua/Breeze 双人格)完整演示四种场景:诚实 → AUTHENTIC;
|
|
113
|
+
换模型中转 → MISMATCH(runner-up 正确指向替代模型);只改 model 字段 → 仍 AUTHENTIC;
|
|
114
|
+
**伪造 usage 的完美说谎中转 → 仍 MISMATCH(行为/错误层暴露)**。
|
|
115
|
+
|
|
116
|
+
## 批量审计 / Audit
|
|
117
|
+
|
|
118
|
+
月度《中转站验真报告》的生产工具:CSV 目标清单 → 受控并发 → 可发布报告(逐端点证据链哈希):
|
|
119
|
+
|
|
120
|
+
```csv
|
|
121
|
+
name,base_url,model,key_env
|
|
122
|
+
relay-a,https://a.example.com/v1,deepseek-chat,KEY_A
|
|
123
|
+
relay-b,https://b.example.com/v1,deepseek-chat,
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
sothstan audit targets.csv -o report.md --json-out report.json --max-workers 4
|
|
128
|
+
# 退出码:0 全部 AUTHENTIC / 1 含 SUSPICIOUS / 2 含 MISMATCH / 3 全部 INCONCLUSIVE
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## 对抗模式 / Adversarial
|
|
133
|
+
|
|
134
|
+
canonical 文本池是公开的——中转可以对固定文本预置答案。`--adversarial` 让 token
|
|
135
|
+
探测改用**按 seed 确定性生成**的对抗文本(混合文种、ZWJ emoji 序列、组合字符、
|
|
136
|
+
罕见 CJK 区块、全角形式——tokenizer 分歧最大的类别):
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# 基线与验证必须同模式;换 --seed 即轮换探测集
|
|
140
|
+
|
|
141
|
+
sothstan collect https://api.official.com/v1 --model m1 --family f \
|
|
142
|
+
--out baselines/m1.json --adversarial --seed 777 --api-key-env K1
|
|
143
|
+
sothstan check https://relay.example.com/v1 --model m1 --adversarial --seed 777
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
- 同 seed 同文本:证据链可复现(fuzz 测试锁定确定性)
|
|
147
|
+
- 模式不一致时判决会附诚实警示(基线与运行的 token 曲线不可比)
|
|
148
|
+
- 诚实边界:字符池公开,安全性不靠保密,靠"探测集随 seed 轮换"的不可预置性
|
|
149
|
+
|
|
150
|
+
## 诚实边界 / Honesty
|
|
151
|
+
|
|
152
|
+
- 指纹验证是**统计证据,不是数学证明**——判决阈值全部公开(`verdict.THRESHOLDS_DOC`)
|
|
153
|
+
- 基线必须来自官方端点;内置 `_demo_*.json` 是 mock 人格指纹,**不代表任何真实模型**
|
|
154
|
+
- 军备竞赛真实存在:探测可被识别、转发。对策(种子化换题/多层信号/统计聚合)
|
|
155
|
+
见 [GAP_PROOF.md](GAP_PROOF.md) 第 4 节——部分可检测已远超现状(现状是零)
|
|
156
|
+
|
|
157
|
+
## 退出码(CI 友好)
|
|
158
|
+
|
|
159
|
+
| 码 | 含义 |
|
|
160
|
+
|---|---|
|
|
161
|
+
| 0 | AUTHENTIC |
|
|
162
|
+
| 1 | SUSPICIOUS |
|
|
163
|
+
| 2 | MISMATCH |
|
|
164
|
+
| 3 | INCONCLUSIVE(证据不足/无竞争基线——诚实说不足) |
|
|
165
|
+
| 4 | 基础设施错误(端点不可达/基线缺失) |
|
|
166
|
+
|
|
167
|
+
## 与现有方案的关系 / Landscape
|
|
168
|
+
|
|
169
|
+
| 方法类别 | 能回答的问题与限制 |
|
|
170
|
+
|---|---|
|
|
171
|
+
| 检查返回的 `model` 字段 | 能读取端点自报名称;不能单独证明服务端实际模型 |
|
|
172
|
+
| 固定提示词探测 | 可观察部分响应差异;结果会受参数、版本和服务端策略影响 |
|
|
173
|
+
| Sothstan | 将多个信号与可信基线比较,并报告判决、边界和可复现记录;不是密码学身份认证 |
|
|
174
|
+
|
|
175
|
+
## 路线图 / Roadmap
|
|
176
|
+
|
|
177
|
+
见 [ROADMAP.md](ROADMAP.md)。当前 v0.1.0rc1:5 探测器 + 混淆集判决 + mock 全链路 + CLI,
|
|
178
|
+
41 项测试全绿。接下来:对抗文本模式、对抗实验矩阵、批量审计、官方基线流水线。
|
|
179
|
+
|
|
180
|
+
## 开发 / Development
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
pip install -e ".[dev]"
|
|
184
|
+
./.venv/Scripts/python.exe -m pytest -q # Windows Git Bash
|
|
185
|
+
./.venv/Scripts/python.exe -m ruff check src tests tools
|
|
186
|
+
./.venv/Scripts/python.exe tools/gen_demo_baselines.py # 重新生成 demo 基线
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## 反馈与参与
|
|
190
|
+
|
|
191
|
+
使用问题和功能建议可以在 [Discussions](https://github.com/cloudydreamland/TheTrialOfTheHiddenVoice/discussions) 交流;可复现缺陷请提交 [Issue](https://github.com/cloudydreamland/TheTrialOfTheHiddenVoice/issues)。请只附合成或脱敏后的最小样例,不要上传真实个人信息、API key 或业务原文。安全问题请按 [SECURITY.md](SECURITY.md) 私下报告。
|
|
192
|
+
|
|
193
|
+
## License
|
|
194
|
+
|
|
195
|
+
MIT
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# The Trial of the Hidden Voice — Sothstan
|
|
2
|
+
|
|
3
|
+
简体中文 · [English](README.en.md)
|
|
4
|
+
|
|
5
|
+
> 展示名 **The Trial of the Hidden Voice** 描绘对隐匿声音的审视;Sothstan 是该项目的短名。
|
|
6
|
+
|
|
7
|
+
**中文优先的 LLM API 模型验真库。一个端点声称自己在服务模型 X——它真的在服务 X 吗?**
|
|
8
|
+
用多层指纹 + 混淆集似然比给出统计判决,证据链哈希锁定,可复现、可审计。
|
|
9
|
+
|
|
10
|
+
[](.github/workflows/ci.yml)
|
|
11
|
+
[](pyproject.toml)
|
|
12
|
+
[](LICENSE)
|
|
13
|
+
|
|
14
|
+
## 为什么需要它 / Why
|
|
15
|
+
|
|
16
|
+
第三方中转、代理或聚合 API 往往会返回一个自报模型名。仅凭这个字段无法验证端点的实际行为是否与所声明模型一致;差异也可能来自版本变化、采样参数、服务策略或网络错误。Sothstan 用可信基线比较多种行为信号,并保留统计结果和不确定性。
|
|
17
|
+
|
|
18
|
+
## 安装 / Install
|
|
19
|
+
|
|
20
|
+
> 当前尚未发布到 PyPI;下方给出从 GitHub 获取并本地安装的命令。
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
git clone https://github.com/cloudydreamland/TheTrialOfTheHiddenVoice.git
|
|
24
|
+
cd TheTrialOfTheHiddenVoice
|
|
25
|
+
python -m pip install .
|
|
26
|
+
# PyPI 首发后:python -m pip install sothstan
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## 快速开始 / Quickstart
|
|
30
|
+
|
|
31
|
+
**没有官方 API key?先离线验证工具本身**(内置 mock 模型与四种攻击场景):
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
sothstan selftest
|
|
35
|
+
# PASS 诚实服务器 → AUTHENTIC
|
|
36
|
+
|
|
37
|
+
# PASS 换模型中转 → MISMATCH(runner-up 正确指认)
|
|
38
|
+
|
|
39
|
+
# PASS 仅改 model 字段 → 仍 AUTHENTIC(字段回显零权重)
|
|
40
|
+
|
|
41
|
+
# PASS 伪造 usage 的说谎中转 → 仍 MISMATCH(行为/错误层暴露)
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
有 key 之后,两步验真:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# 第一步:对【官方】端点采集基线(至少 2 个模型,互为混淆集)
|
|
49
|
+
|
|
50
|
+
sothstan collect https://api.deepseek.com/v1 --model deepseek-chat \
|
|
51
|
+
--family deepseek --out baselines/deepseek-chat.json --api-key-env DEEPSEEK_API_KEY
|
|
52
|
+
sothstan collect https://api.deepseek.com/v1 --model deepseek-reasoner \
|
|
53
|
+
--family deepseek --out baselines/deepseek-reasoner.json --api-key-env DEEPSEEK_API_KEY
|
|
54
|
+
|
|
55
|
+
# 第二步:验证可疑端点
|
|
56
|
+
|
|
57
|
+
sothstan check https://relay.example.com/v1 --model deepseek-chat --api-key-env RELAY_KEY
|
|
58
|
+
# ✅ AUTHENTIC margin +212.4 证据链 9f3a… exit 0
|
|
59
|
+
|
|
60
|
+
# ❌ MISMATCH runner-up: deepseek-reasoner exit 2
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 工作原理 / How it works
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
探测(probe)──产出──> 指纹信号(signal)──对比──> 基线(baseline,官方端点采集)
|
|
68
|
+
│
|
|
69
|
+
混淆集似然比(claimed vs 全部竞争模型)
|
|
70
|
+
│
|
|
71
|
+
判决 AUTHENTIC / SUSPICIOUS / MISMATCH / INCONCLUSIVE
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- **tier-1 确定性层**:`usage` 自报 token 曲线(20 篇 canonical 文本,CJK 分歧最大)、
|
|
75
|
+
chat template 开销、max_tokens 限额、logprobs/n 参数支持、错误码族
|
|
76
|
+
- **tier-2 行为层**:思维链形态、风格标记、reasoning 字段
|
|
77
|
+
- **混淆集比较**是方法核心:冒充者通常与目标同家族(r1 冒充 v3),"像不像"没有意义,
|
|
78
|
+
"证据更支持谁"才有意义;且 claimed 总分低于硬地板时直接 MISMATCH——
|
|
79
|
+
**token 层再像也淹没不了行为层的全面矛盾**(mock 实验可复现)
|
|
80
|
+
- **零权重展示项**:响应体 `model` 字段回显——改字段是最廉价的伪造,报告里可见但不计分
|
|
81
|
+
|
|
82
|
+
内置 mock 服务器(Aqua/Breeze 双人格)完整演示四种场景:诚实 → AUTHENTIC;
|
|
83
|
+
换模型中转 → MISMATCH(runner-up 正确指向替代模型);只改 model 字段 → 仍 AUTHENTIC;
|
|
84
|
+
**伪造 usage 的完美说谎中转 → 仍 MISMATCH(行为/错误层暴露)**。
|
|
85
|
+
|
|
86
|
+
## 批量审计 / Audit
|
|
87
|
+
|
|
88
|
+
月度《中转站验真报告》的生产工具:CSV 目标清单 → 受控并发 → 可发布报告(逐端点证据链哈希):
|
|
89
|
+
|
|
90
|
+
```csv
|
|
91
|
+
name,base_url,model,key_env
|
|
92
|
+
relay-a,https://a.example.com/v1,deepseek-chat,KEY_A
|
|
93
|
+
relay-b,https://b.example.com/v1,deepseek-chat,
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
sothstan audit targets.csv -o report.md --json-out report.json --max-workers 4
|
|
98
|
+
# 退出码:0 全部 AUTHENTIC / 1 含 SUSPICIOUS / 2 含 MISMATCH / 3 全部 INCONCLUSIVE
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## 对抗模式 / Adversarial
|
|
103
|
+
|
|
104
|
+
canonical 文本池是公开的——中转可以对固定文本预置答案。`--adversarial` 让 token
|
|
105
|
+
探测改用**按 seed 确定性生成**的对抗文本(混合文种、ZWJ emoji 序列、组合字符、
|
|
106
|
+
罕见 CJK 区块、全角形式——tokenizer 分歧最大的类别):
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# 基线与验证必须同模式;换 --seed 即轮换探测集
|
|
110
|
+
|
|
111
|
+
sothstan collect https://api.official.com/v1 --model m1 --family f \
|
|
112
|
+
--out baselines/m1.json --adversarial --seed 777 --api-key-env K1
|
|
113
|
+
sothstan check https://relay.example.com/v1 --model m1 --adversarial --seed 777
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
- 同 seed 同文本:证据链可复现(fuzz 测试锁定确定性)
|
|
117
|
+
- 模式不一致时判决会附诚实警示(基线与运行的 token 曲线不可比)
|
|
118
|
+
- 诚实边界:字符池公开,安全性不靠保密,靠"探测集随 seed 轮换"的不可预置性
|
|
119
|
+
|
|
120
|
+
## 诚实边界 / Honesty
|
|
121
|
+
|
|
122
|
+
- 指纹验证是**统计证据,不是数学证明**——判决阈值全部公开(`verdict.THRESHOLDS_DOC`)
|
|
123
|
+
- 基线必须来自官方端点;内置 `_demo_*.json` 是 mock 人格指纹,**不代表任何真实模型**
|
|
124
|
+
- 军备竞赛真实存在:探测可被识别、转发。对策(种子化换题/多层信号/统计聚合)
|
|
125
|
+
见 [GAP_PROOF.md](GAP_PROOF.md) 第 4 节——部分可检测已远超现状(现状是零)
|
|
126
|
+
|
|
127
|
+
## 退出码(CI 友好)
|
|
128
|
+
|
|
129
|
+
| 码 | 含义 |
|
|
130
|
+
|---|---|
|
|
131
|
+
| 0 | AUTHENTIC |
|
|
132
|
+
| 1 | SUSPICIOUS |
|
|
133
|
+
| 2 | MISMATCH |
|
|
134
|
+
| 3 | INCONCLUSIVE(证据不足/无竞争基线——诚实说不足) |
|
|
135
|
+
| 4 | 基础设施错误(端点不可达/基线缺失) |
|
|
136
|
+
|
|
137
|
+
## 与现有方案的关系 / Landscape
|
|
138
|
+
|
|
139
|
+
| 方法类别 | 能回答的问题与限制 |
|
|
140
|
+
|---|---|
|
|
141
|
+
| 检查返回的 `model` 字段 | 能读取端点自报名称;不能单独证明服务端实际模型 |
|
|
142
|
+
| 固定提示词探测 | 可观察部分响应差异;结果会受参数、版本和服务端策略影响 |
|
|
143
|
+
| Sothstan | 将多个信号与可信基线比较,并报告判决、边界和可复现记录;不是密码学身份认证 |
|
|
144
|
+
|
|
145
|
+
## 路线图 / Roadmap
|
|
146
|
+
|
|
147
|
+
见 [ROADMAP.md](ROADMAP.md)。当前 v0.1.0rc1:5 探测器 + 混淆集判决 + mock 全链路 + CLI,
|
|
148
|
+
41 项测试全绿。接下来:对抗文本模式、对抗实验矩阵、批量审计、官方基线流水线。
|
|
149
|
+
|
|
150
|
+
## 开发 / Development
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
pip install -e ".[dev]"
|
|
154
|
+
./.venv/Scripts/python.exe -m pytest -q # Windows Git Bash
|
|
155
|
+
./.venv/Scripts/python.exe -m ruff check src tests tools
|
|
156
|
+
./.venv/Scripts/python.exe tools/gen_demo_baselines.py # 重新生成 demo 基线
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## 反馈与参与
|
|
160
|
+
|
|
161
|
+
使用问题和功能建议可以在 [Discussions](https://github.com/cloudydreamland/TheTrialOfTheHiddenVoice/discussions) 交流;可复现缺陷请提交 [Issue](https://github.com/cloudydreamland/TheTrialOfTheHiddenVoice/issues)。请只附合成或脱敏后的最小样例,不要上传真实个人信息、API key 或业务原文。安全问题请按 [SECURITY.md](SECURITY.md) 私下报告。
|
|
162
|
+
|
|
163
|
+
## License
|
|
164
|
+
|
|
165
|
+
MIT
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "sothstan"
|
|
7
|
+
version = "0.1.0rc1"
|
|
8
|
+
description = "The Trial of the Hidden Voice (Sothstan) | Statistical audits for LLM API endpoints"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "sothstan contributors" }]
|
|
13
|
+
keywords = ["llm", "api", "fingerprint", "verification", "chinese", "relay", "模型验真"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Topic :: Security",
|
|
24
|
+
"Topic :: Software Development :: Quality Assurance",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.scripts]
|
|
28
|
+
sothstan = "sothstan.cli:main"
|
|
29
|
+
|
|
30
|
+
[project.optional-dependencies]
|
|
31
|
+
dev = ["pytest>=8", "ruff>=0.6"]
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://github.com/cloudydreamland/TheTrialOfTheHiddenVoice"
|
|
35
|
+
Repository = "https://github.com/cloudydreamland/TheTrialOfTheHiddenVoice"
|
|
36
|
+
Issues = "https://github.com/cloudydreamland/TheTrialOfTheHiddenVoice/issues"
|
|
37
|
+
Changelog = "https://github.com/cloudydreamland/TheTrialOfTheHiddenVoice/blob/main/CHANGELOG.md"
|
|
38
|
+
Security = "https://github.com/cloudydreamland/TheTrialOfTheHiddenVoice/security/policy"
|
|
39
|
+
|
|
40
|
+
[tool.setuptools.packages.find]
|
|
41
|
+
where = ["src"]
|
|
42
|
+
|
|
43
|
+
[tool.setuptools.package-data]
|
|
44
|
+
sothstan = ["baselines/*.json", "py.typed"]
|
|
45
|
+
|
|
46
|
+
[tool.ruff]
|
|
47
|
+
line-length = 100
|
|
48
|
+
target-version = "py310"
|
|
49
|
+
|
|
50
|
+
[tool.ruff.lint]
|
|
51
|
+
select = ["E", "F", "W", "I", "UP", "B"]
|
|
52
|
+
|
|
53
|
+
[tool.pytest.ini_options]
|
|
54
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Sothstan — LLM API 模型验真。
|
|
2
|
+
|
|
3
|
+
一个端点声称自己在服务模型 X,它真的在服务 X 吗?
|
|
4
|
+
sothstan 用探测(probe)提取指纹信号(signal),与官方模型指纹基线(baseline)
|
|
5
|
+
做混淆集似然比比较(confusion-set likelihood ratio),给出统计判决(verdict)。
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from sothstan._version import __version__
|
|
9
|
+
from sothstan.baseline import Baseline, load_baseline, save_baseline
|
|
10
|
+
from sothstan.http import ApiClient, ApiError, BudgetExceeded
|
|
11
|
+
from sothstan.runner import collect_baseline_signals, verify
|
|
12
|
+
from sothstan.types import Signal, VerdictLabel
|
|
13
|
+
from sothstan.verdict import Verdict, decide
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"ApiError",
|
|
17
|
+
"ApiClient",
|
|
18
|
+
"Baseline",
|
|
19
|
+
"BudgetExceeded",
|
|
20
|
+
"Signal",
|
|
21
|
+
"Verdict",
|
|
22
|
+
"VerdictLabel",
|
|
23
|
+
"collect_baseline_signals",
|
|
24
|
+
"decide",
|
|
25
|
+
"load_baseline",
|
|
26
|
+
"save_baseline",
|
|
27
|
+
"verify",
|
|
28
|
+
"__version__",
|
|
29
|
+
]
|