relaycheck 0.1.0__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.
Files changed (42) hide show
  1. relaycheck-0.1.0/CHANGELOG.md +84 -0
  2. relaycheck-0.1.0/LICENSE +32 -0
  3. relaycheck-0.1.0/MANIFEST.in +17 -0
  4. relaycheck-0.1.0/PKG-INFO +627 -0
  5. relaycheck-0.1.0/README.en.md +649 -0
  6. relaycheck-0.1.0/README.md +595 -0
  7. relaycheck-0.1.0/RELEASING.md +72 -0
  8. relaycheck-0.1.0/SECURITY.md +66 -0
  9. relaycheck-0.1.0/examples/README.md +93 -0
  10. relaycheck-0.1.0/examples/report-clean.md +99 -0
  11. relaycheck-0.1.0/examples/report-dead.md +652 -0
  12. relaycheck-0.1.0/examples/report-fraudulent.md +884 -0
  13. relaycheck-0.1.0/examples/report-noisy.md +343 -0
  14. relaycheck-0.1.0/pyproject.toml +49 -0
  15. relaycheck-0.1.0/relaycheck/__init__.py +14 -0
  16. relaycheck-0.1.0/relaycheck/cli.py +400 -0
  17. relaycheck-0.1.0/relaycheck/client.py +505 -0
  18. relaycheck-0.1.0/relaycheck/families.py +62 -0
  19. relaycheck-0.1.0/relaycheck/models.py +256 -0
  20. relaycheck-0.1.0/relaycheck/probes/__init__.py +117 -0
  21. relaycheck-0.1.0/relaycheck/probes/base.py +293 -0
  22. relaycheck-0.1.0/relaycheck/probes/billing.py +396 -0
  23. relaycheck-0.1.0/relaycheck/probes/context.py +543 -0
  24. relaycheck-0.1.0/relaycheck/probes/echo.py +328 -0
  25. relaycheck-0.1.0/relaycheck/probes/identity.py +480 -0
  26. relaycheck-0.1.0/relaycheck/probes/params.py +578 -0
  27. relaycheck-0.1.0/relaycheck/probes/reliability.py +265 -0
  28. relaycheck-0.1.0/relaycheck/probes/stream.py +478 -0
  29. relaycheck-0.1.0/relaycheck/probes/tokenizer.py +323 -0
  30. relaycheck-0.1.0/relaycheck/probes/twins.py +365 -0
  31. relaycheck-0.1.0/relaycheck/reporter.py +324 -0
  32. relaycheck-0.1.0/relaycheck/selection.py +93 -0
  33. relaycheck-0.1.0/relaycheck.egg-info/PKG-INFO +627 -0
  34. relaycheck-0.1.0/relaycheck.egg-info/SOURCES.txt +40 -0
  35. relaycheck-0.1.0/relaycheck.egg-info/dependency_links.txt +1 -0
  36. relaycheck-0.1.0/relaycheck.egg-info/entry_points.txt +2 -0
  37. relaycheck-0.1.0/relaycheck.egg-info/requires.txt +5 -0
  38. relaycheck-0.1.0/relaycheck.egg-info/top_level.txt +1 -0
  39. relaycheck-0.1.0/setup.cfg +4 -0
  40. relaycheck-0.1.0/tests/mock_relay.py +890 -0
  41. relaycheck-0.1.0/tests/test_mock_relay.py +733 -0
  42. relaycheck-0.1.0/tests/test_selection.py +322 -0
@@ -0,0 +1,84 @@
1
+ # 变更记录
2
+
3
+ 本文件记录**行为**的变化,尤其是「严重程度」和「finding id」的语义变化——
4
+ 一个已经发布过的 finding id 尽量不重用;如果它的含义变了,这里必须写明。
5
+
6
+ ## [0.1.0] — 2026-09-26
7
+
8
+ 首个版本。11 个探针,8 个本地模拟场景,15 项端到端验收,外加 15 项模型选择单元测试。
9
+
10
+ ### 探针
11
+
12
+ | 探针 | 查什么 |
13
+ |---|---|
14
+ | `reliability` | 可用性与延迟(先确认对方能不能干活) |
15
+ | `billing-panel` | 面板公开的上游成本 vs 实际计费(加价倍率) |
16
+ | `echo` | 响应体自报的 `model` 是否等于你请求的名字 |
17
+ | `tokenizer` | 固定串的 `prompt_tokens` 指纹,找出共享 tokenizer 的模型对 |
18
+ | `twins` | 开放性提示下逐字比对,找出输出完全相同的「双胞胎」 |
19
+ | `identity` | 直接问模型「你是谁」,与售卖名称对照 |
20
+ | `canary` | 注入唯一标记,验证提示词有没有原样送达 |
21
+ | `billing-hidden-reasoning` | 有没有把隐藏的思维链按输出价计费 |
22
+ | `params` | `max_tokens` / `stop` / `temperature` / `n` / `response_format` / `tools` 有没有被透传 |
23
+ | `stream` | 流式与完整返回是否一致 |
24
+ | `context` | 长输入有没有被静默截断(**唯一明显花钱的探针,默认不跑**) |
25
+
26
+ ### 核心不变量
27
+
28
+ - **`CLEAN` 必须意味着「已经验证过」。** 「没测到」永远不能写成 `CLEAN`,
29
+ 它走 `*-000` 保留编号 + `INFO`。
30
+ - **「测不出来」不能写成「测出了问题」。** 空回复、该站自身不可复现、自述前后矛盾,
31
+ 都是 `INFO` 的「无法判定」,不是指控。
32
+ - **退出码 0 / 1 / 2 互不重叠**:`0` 没问题、`1` 有达到 `--fail-on` 的发现、`2` 这次没查成。
33
+ 崩溃一律是 `2`——绝不与「发现了问题」共用 `1`。
34
+ - **严格性分两档**:`severity`(有多严重)与 `confidence`(有多确定)分开,
35
+ `LOW` 不触发默认的 `--fail-on high`。
36
+
37
+ ### 修正(都是同一类错误的变体:报告高估或误读了自己测到的东西)
38
+
39
+ - `twins` 不再把「样本为空」算成「输出不稳定」——空输出分成 `blank` 与 `shaky` 两桶。
40
+ - `params` 的 `temperature` 检查改为三态(`honoured` / `ignored` / `inconclusive` /
41
+ `nondeterministic`):`temperature=0` 两次结果不一致时,结论是「该站不可复现」,
42
+ 而不是「参数被忽略」。
43
+ - `stream` 不再把「比较根本没跑成」写成 `stream-clean`。
44
+ - `tokenizer` / `twins` 遇到「声明同一个厂商」的模型对时降级为 `tok-101` / `twins-101`,
45
+ 不再把合法的别名对(`gpt-4o` / `gpt-4o-mini`)判成掉包。
46
+ - 推理模型的 `reasoning_content` 挤占 `max_tokens` 导致可见正文为空或只剩残片时,
47
+ 探针以更大的预算重试一次;仍拿不到就判「无法判定」,不判「不一致」。
48
+ - `echo-000` 不再用观测条数冒充「测到几个模型」(死站上这句话会自相矛盾)。
49
+ - `id-100` 的严重程度:`MEDIUM` → `LOW` → **`INFO`**。原因见下。
50
+
51
+ ### `id-100` 为什么最终是 `INFO`
52
+
53
+ `id-100` 报告的是「模型自述的厂商与售卖名称不一致」。三次降级的理由是同一条:
54
+ **撑不起指控的东西不该出现在指控栏里。**
55
+
56
+ 1. 它自己的文案就写着「必须由 `tokenizer` 指纹或行为比对独立指向同一结论」——
57
+ 那两条各自有 `CRITICAL` / `HIGH` 的 finding,它作为指控完全冗余。
58
+ 2. 模型会幻觉自己的身份。非 OpenAI 的模型自称 OpenAI 是训练语料导致的常态,
59
+ **诚实站上照样出现**:实测中一个正常转售 `deepseek-v4-flash` 的站,该模型两轮都
60
+ 稳定地自称 OpenAI。留成 `LOW` 的结果是**每一个转售 DeepSeek 的诚实站都白挨一条**。
61
+ 3. 于是它降到与 `echo-101` / `tok-101` / `bill-201` 同档:**值得写进报告,
62
+ 不值得写进指控栏。**
63
+
64
+ 同时加了一道门槛:**自述只有被重复一遍才算线索**——同一个问题问两遍,两次都点名同一个
65
+ 外国厂商才输出 `id-100`;答得不一致降级为 `id-101`(`INFO`,措辞里明确写着「不指控掉包」);
66
+ 有一轮没答上来则记为 `id-102`。
67
+
68
+ ### 文档
69
+
70
+ - 中文 `README.md` 与英文 `README.en.md` 逐节对应。
71
+ - `examples/` 四份报告由真实工具输出生成(`fraudulent` / `clean` / `dead` / `noisy`),
72
+ 不是手写的。
73
+ - 「六种结局」表把 `CLEAN` / 没跑成 / 没有可判定内容 / 该站不可复现 / 值得记录但不构成指控 /
74
+ 发现异常分开列清楚。
75
+
76
+ ### 验收(`tests/test_mock_relay.py` 15 项端到端 + `tests/test_selection.py` 15 项单元)
77
+
78
+ - `fraudulent` 必须被抓出来:≥1 条 `CRITICAL`,且是具体的 finding id。
79
+ - `clean` / `same-vendor` / `slow` / `dead` / `reasoning` / `noisy` / `unstable-self`
80
+ 必须**零误报**(`same-vendor` 允许一条 `LOW` 别名提示)。
81
+ - `dead` 永远不能被报成 `CLEAN`。
82
+ - CLI 在 cp936 控制台下必须正常收尾并退出 `0`。
83
+ - 省略 `--models` 时,受测模型由 `/v1/models` 按**厂商多样性**选出,而不是照目录顺序取前 N 个
84
+ (`tests/test_selection.py`)。
@@ -0,0 +1,32 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 relaycheck 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.
22
+
23
+ ---
24
+
25
+ NOTE ON USE
26
+
27
+ relaycheck sends requests to third-party services using credentials supplied by
28
+ its operator. Those requests consume the operator's quota and are subject to the
29
+ target service's terms of service. Only run it against endpoints you are
30
+ authorised to test, and do not use its output to make an accusation you cannot
31
+ support with the evidence it actually collected. Every finding carries an
32
+ explicit confidence level for exactly this reason; respect it.
@@ -0,0 +1,17 @@
1
+ # Ship the self-test inside the sdist.
2
+ #
3
+ # SECURITY.md tells people to reproduce a suspected bug against
4
+ # ``tests/mock_relay.py`` rather than paste a real report. That instruction is
5
+ # only useful if the mock relay is actually in the archive, and setuptools does
6
+ # not pick up tests/ or examples/ on its own.
7
+ include LICENSE
8
+ include README.md
9
+ include README.en.md
10
+ include CHANGELOG.md
11
+ include SECURITY.md
12
+ # Not needed to build, but the sdist carries every root document so the archive
13
+ # is self-describing: someone reading a copy of the source should be able to see
14
+ # how a release is cut without going back to the repository.
15
+ include RELEASING.md
16
+ recursive-include tests *.py
17
+ recursive-include examples *.md