whosellm 0.2.4__tar.gz → 0.2.6__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 (124) hide show
  1. {whosellm-0.2.4 → whosellm-0.2.6}/.bumpversion.toml +1 -1
  2. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/skills/review-provider-model/providers/gemini.md +9 -0
  3. {whosellm-0.2.4 → whosellm-0.2.6}/CHANGELOG.md +5 -0
  4. {whosellm-0.2.4 → whosellm-0.2.6}/PKG-INFO +2 -2
  5. {whosellm-0.2.4 → whosellm-0.2.6}/pyproject.toml +1 -1
  6. {whosellm-0.2.4 → whosellm-0.2.6}/tests/e2e/test_anthropic.py +46 -3
  7. whosellm-0.2.6/tests/e2e/test_google.py +458 -0
  8. {whosellm-0.2.4 → whosellm-0.2.6}/tests/e2e/test_openai.py +156 -2
  9. {whosellm-0.2.4 → whosellm-0.2.6}/tests/e2e/test_zhipu.py +89 -1
  10. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_anthropic.py +173 -0
  11. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_gemini.py +109 -11
  12. whosellm-0.2.6/tests/models/families/test_glm41v_thinking.py +99 -0
  13. whosellm-0.2.6/tests/models/families/test_glm53.py +217 -0
  14. whosellm-0.2.6/tests/models/families/test_glm5v_turbo.py +81 -0
  15. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_gpt5.py +196 -0
  16. whosellm-0.2.6/tests/models/families/test_gpt6.py +70 -0
  17. {whosellm-0.2.4 → whosellm-0.2.6}/tests/test_variant_priority_config.py +11 -3
  18. {whosellm-0.2.4 → whosellm-0.2.6}/uv.lock +1 -1
  19. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/__init__.py +1 -1
  20. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/base.py +1 -0
  21. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/anthropic.py +90 -0
  22. whosellm-0.2.6/whosellm/models/families/gemini.py +764 -0
  23. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/openai/__init__.py +6 -0
  24. whosellm-0.2.6/whosellm/models/families/openai/openai_gpt_5_5.py +76 -0
  25. whosellm-0.2.6/whosellm/models/families/openai/openai_gpt_5_6.py +114 -0
  26. whosellm-0.2.6/whosellm/models/families/openai/openai_gpt_6.py +56 -0
  27. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/zhipu.py +178 -0
  28. whosellm-0.2.4/tests/e2e/test_google.py +0 -220
  29. whosellm-0.2.4/whosellm/models/families/gemini.py +0 -423
  30. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/commands/interview.md +0 -0
  31. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/projects/-Users-jqq-PycharmProjects-llmeta/memory/MEMORY.md +0 -0
  32. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/projects/-Users-jqq-PycharmProjects-llmeta/memory/feedback_use_uv.md +0 -0
  33. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/settings.json +0 -0
  34. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/skills/code-review/SKILL.md +0 -0
  35. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/skills/create-skill/SKILL.md +0 -0
  36. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/skills/e2e-metadata/SKILL.md +0 -0
  37. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/skills/evolve/SKILL.md +0 -0
  38. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/skills/fix-review/SKILL.md +0 -0
  39. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/skills/release/SKILL.md +0 -0
  40. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/skills/review-provider-model/SKILL.md +0 -0
  41. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/skills/review-provider-model/providers/alibaba.md +0 -0
  42. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/skills/review-provider-model/providers/anthropic.md +0 -0
  43. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/skills/review-provider-model/providers/deepseek.md +0 -0
  44. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/skills/review-provider-model/providers/openai.md +0 -0
  45. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/skills/review-provider-model/providers/others.md +0 -0
  46. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/skills/review-provider-model/providers/vidu.md +0 -0
  47. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/skills/review-provider-model/providers/zhipu.md +0 -0
  48. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/skills/update-provider-model/SKILL.md +0 -0
  49. {whosellm-0.2.4 → whosellm-0.2.6}/.claude/skills/update-provider-model/testing.md +0 -0
  50. {whosellm-0.2.4 → whosellm-0.2.6}/.coveragerc +0 -0
  51. {whosellm-0.2.4 → whosellm-0.2.6}/.github/workflows/publish.yml +0 -0
  52. {whosellm-0.2.4 → whosellm-0.2.6}/.github/workflows/tests.yml +0 -0
  53. {whosellm-0.2.4 → whosellm-0.2.6}/.gitignore +0 -0
  54. {whosellm-0.2.4 → whosellm-0.2.6}/.windsurf/workflows/addmodel.md +0 -0
  55. {whosellm-0.2.4 → whosellm-0.2.6}/.windsurf/workflows/arch.md +0 -0
  56. {whosellm-0.2.4 → whosellm-0.2.6}/.windsurf/workflows/testllmeta.md +0 -0
  57. {whosellm-0.2.4 → whosellm-0.2.6}/CLAUDE.md +0 -0
  58. {whosellm-0.2.4 → whosellm-0.2.6}/LICENSE +0 -0
  59. {whosellm-0.2.4 → whosellm-0.2.6}/README.md +0 -0
  60. {whosellm-0.2.4 → whosellm-0.2.6}/docs/add_new_model_family.md +0 -0
  61. {whosellm-0.2.4 → whosellm-0.2.6}/docs/refactor_proposal.md +0 -0
  62. {whosellm-0.2.4 → whosellm-0.2.6}/docs/spec_model_family_redesign.md +0 -0
  63. {whosellm-0.2.4 → whosellm-0.2.6}/examples/advanced_usage.py +0 -0
  64. {whosellm-0.2.4 → whosellm-0.2.6}/examples/basic_usage.py +0 -0
  65. {whosellm-0.2.4 → whosellm-0.2.6}/mypy.ini +0 -0
  66. {whosellm-0.2.4 → whosellm-0.2.6}/pytest.ini +0 -0
  67. {whosellm-0.2.4 → whosellm-0.2.6}/ruff.toml +0 -0
  68. {whosellm-0.2.4 → whosellm-0.2.6}/tests/__init__.py +0 -0
  69. {whosellm-0.2.4 → whosellm-0.2.6}/tests/e2e/__init__.py +0 -0
  70. {whosellm-0.2.4 → whosellm-0.2.6}/tests/e2e/conftest.py +0 -0
  71. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/__init__.py +0 -0
  72. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/__init__.py +0 -0
  73. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_deepseek.py +0 -0
  74. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_deepseek_tencent.py +0 -0
  75. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_glm45.py +0 -0
  76. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_glm45v.py +0 -0
  77. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_glm46.py +0 -0
  78. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_glm46v.py +0 -0
  79. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_glm5.py +0 -0
  80. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_gpt3_5.py +0 -0
  81. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_gpt4_1.py +0 -0
  82. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_gpt4o.py +0 -0
  83. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_o1.py +0 -0
  84. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_o3.py +0 -0
  85. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_o4.py +0 -0
  86. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_qwen.py +0 -0
  87. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_qwen3_vl_models.py +0 -0
  88. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_qwen_ollama.py +0 -0
  89. {whosellm-0.2.4 → whosellm-0.2.6}/tests/models/families/test_qwen_plus.py +0 -0
  90. {whosellm-0.2.4 → whosellm-0.2.6}/tests/test_auto_register.py +0 -0
  91. {whosellm-0.2.4 → whosellm-0.2.6}/tests/test_claude_4x_versions.py +0 -0
  92. {whosellm-0.2.4 → whosellm-0.2.6}/tests/test_llmeta.py +0 -0
  93. {whosellm-0.2.4 → whosellm-0.2.6}/tests/test_model_version.py +0 -0
  94. {whosellm-0.2.4 → whosellm-0.2.6}/tests/test_provider.py +0 -0
  95. {whosellm-0.2.4 → whosellm-0.2.6}/tests/test_registry_merge.py +0 -0
  96. {whosellm-0.2.4 → whosellm-0.2.6}/tests/test_specific_patterns.py +0 -0
  97. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/capabilities.py +0 -0
  98. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/model_version.py +0 -0
  99. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/__init__.py +0 -0
  100. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/config.py +0 -0
  101. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/dynamic_enum.py +0 -0
  102. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/__init__.py +0 -0
  103. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/alibaba.py +0 -0
  104. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/deepseek/__init__.py +0 -0
  105. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/deepseek/deepseek_official.py +0 -0
  106. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/deepseek/tencent.py +0 -0
  107. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/openai/openai_gpt_3_5.py +0 -0
  108. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/openai/openai_gpt_4.py +0 -0
  109. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/openai/openai_gpt_4_1.py +0 -0
  110. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/openai/openai_gpt_4o.py +0 -0
  111. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/openai/openai_gpt_5.py +0 -0
  112. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/openai/openai_gpt_5_1.py +0 -0
  113. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/openai/openai_gpt_5_2.py +0 -0
  114. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/openai/openai_gpt_5_3.py +0 -0
  115. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/openai/openai_gpt_5_4.py +0 -0
  116. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/openai/openai_o1.py +0 -0
  117. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/openai/openai_o3.py +0 -0
  118. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/openai/openai_o4.py +0 -0
  119. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/others.py +0 -0
  120. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/families/vidu.py +0 -0
  121. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/patterns.py +0 -0
  122. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/models/registry.py +0 -0
  123. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/provider.py +0 -0
  124. {whosellm-0.2.4 → whosellm-0.2.6}/whosellm/py.typed +0 -0
@@ -2,7 +2,7 @@
2
2
  # 文档 / Documentation: https://callowayproject.github.io/bump-my-version/
3
3
 
4
4
  [tool.bumpversion]
5
- current_version = "0.2.4"
5
+ current_version = "0.2.6"
6
6
  parse = """(?x)
7
7
  (?P<major>0|[1-9]\\d*)\\.
8
8
  (?P<minor>0|[1-9]\\d*)\\.
@@ -63,3 +63,12 @@ description: Google Gemini 模型信息采集指南
63
63
  - `supports_file_search` 和 `supports_code_interpreter` 并非所有变体都支持,flash-lite 和 2.0 系列通常不支持 code_interpreter
64
64
  - 大部分 Gemini 模型的 `context_window` 为 `1048576`(1M tokens),但特殊变体例外
65
65
  - `supports_web_search` 在 2.0 flash 及以上版本可用,2.0 flash-lite 不支持
66
+
67
+ ## 采集经验(2026-08-20 更新)
68
+
69
+ - **3.1 及以后的官方 ID 一律用点号**:`gemini-3.1-pro-preview`、`gemini-3.5-flash` 等。曾误注册短横线 `gemini-3-1-pro-preview`,导致真实 ID 走泛型 pattern、variant 解析错误
70
+ - **弃用时间线看 `deprecations` 页**:`https://ai.google.dev/gemini-api/docs/deprecations` 有每个模型的发布日期、关停日期、推荐替代品,比模型列表页信息更全
71
+ - **部分模型详情页没有规格卡**(如 gemini-3.1-flash-lite、gemini-3.1-flash-live-preview)。Live API 模型的上下文上限在 `live-api/capabilities` 页(原生音频输出模型 128k);其余可参照官方指定的迁移源模型规格,并在配置注释中说明数据来源
72
+ - **模型详情页与总览页的 model code 可能不一致**(如 gemini-omni-flash vs gemini-omni-flash-preview),两个都收录进 patterns
73
+ - `capabilities.py` 的默认值中 `supports_structured_outputs/Json_outputs/streaming` 默认 True,受限模型(image/TTS/live 特化版)必须显式置 False
74
+ - 特化端点别名也应收录:如 `gemini-3.1-pro-preview-customtools`
@@ -2,6 +2,11 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.2.4] - Unreleased
6
+
7
+ ### Added
8
+ - 新增 Claude 5 代模型配置(官方规格核实):`claude-sonnet-5`(2026-06-30 GA,$2/$10)、`claude-opus-5`(2026-07-24 GA,$5/$25)。两者均 1M 上下文(默认且最大)、128K 最大输出、自适应思考默认开启(映射 `supports_thinking=True`),支持结构化输出 + computer use。版本 5.0 高于 4.8/4.6(如 `claude-opus-5 > claude-opus-4-8`),同版本下变体优先级维持 `mythos > fable > opus > sonnet`
9
+
5
10
  ## [0.2.3] - Unreleased
6
11
 
7
12
  ### Added
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: whosellm
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: A unified LLM model version and capability management library
5
5
  Author-email: JQQ <jqq1716@gmail.com>
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "whosellm"
3
- version = "0.2.4"
3
+ version = "0.2.6"
4
4
  description = "A unified LLM model version and capability management library"
5
5
  authors = [
6
6
  {name = "JQQ", email = "jqq1716@gmail.com"}
@@ -1,7 +1,7 @@
1
1
  """Anthropic E2E 元数据测试。
2
2
 
3
3
  来源: https://platform.claude.com/docs/en/docs/about-claude/models
4
- 采集日期: 2026-04-12
4
+ 采集日期: 2026-04-12(2026-09-04 增补 Fable 5.1 / Mythos 5.1)
5
5
  """
6
6
 
7
7
  import pytest
@@ -11,7 +11,50 @@ from whosellm import ModelFamily, Provider
11
11
  from .conftest import assert_model_metadata
12
12
 
13
13
  # ============================================================================
14
- # Claude Family — Latest (version 4.6)
14
+ # Claude Family — Version 5.1 (2026-09-01 发布 / Released 2026-09-01)
15
+ # 来源: https://platform.claude.com/docs/en/models/fable-5-1/overview
16
+ # ============================================================================
17
+
18
+ CLAUDE_51_MODELS = [
19
+ (
20
+ "claude-fable-5-1",
21
+ {
22
+ "provider": Provider.ANTHROPIC,
23
+ "family": ModelFamily.CLAUDE,
24
+ "version": "5.1",
25
+ "variant": "fable",
26
+ "supports_thinking": True,
27
+ "supports_vision": True,
28
+ "supports_streaming": True,
29
+ "supports_function_calling": True,
30
+ "supports_structured_outputs": True,
31
+ "supports_computer_use": True,
32
+ "context_window": 1_000_000,
33
+ "max_tokens": 128_000,
34
+ },
35
+ ),
36
+ (
37
+ "claude-mythos-5-1",
38
+ {
39
+ # Glasswing 受邀版,与 Fable 5.1 同规格 / Glasswing invite-only, same specs as Fable 5.1
40
+ "provider": Provider.ANTHROPIC,
41
+ "family": ModelFamily.CLAUDE,
42
+ "version": "5.1",
43
+ "variant": "mythos",
44
+ "supports_thinking": True,
45
+ "supports_vision": True,
46
+ "supports_streaming": True,
47
+ "supports_function_calling": True,
48
+ "supports_structured_outputs": True,
49
+ "supports_computer_use": True,
50
+ "context_window": 1_000_000,
51
+ "max_tokens": 128_000,
52
+ },
53
+ ),
54
+ ]
55
+
56
+ # ============================================================================
57
+ # Claude Family — Version 4.6
15
58
  # 来源: https://platform.claude.com/docs/en/docs/about-claude/models/overview
16
59
  # ============================================================================
17
60
 
@@ -190,7 +233,7 @@ CLAUDE_30_MODELS = [
190
233
  # 聚合 + 参数化
191
234
  # ============================================================================
192
235
 
193
- ALL_MODELS = CLAUDE_LATEST_MODELS + CLAUDE_45_MODELS + CLAUDE_41_MODELS + CLAUDE_40_MODELS + CLAUDE_30_MODELS
236
+ ALL_MODELS = CLAUDE_51_MODELS + CLAUDE_LATEST_MODELS + CLAUDE_45_MODELS + CLAUDE_41_MODELS + CLAUDE_40_MODELS + CLAUDE_30_MODELS
194
237
 
195
238
 
196
239
  @pytest.mark.e2e
@@ -0,0 +1,458 @@
1
+ """Google E2E 元数据测试。
2
+
3
+ 来源: https://ai.google.dev/gemini-api/docs/models
4
+ 采集日期: 2026-04-12(2026-08-20 增补 3.5/3.6/3.7 Flash、Nano Banana 2 系列、Live/TTS 等新模型)
5
+ """
6
+
7
+ import pytest
8
+
9
+ from whosellm import ModelFamily, Provider
10
+
11
+ from .conftest import assert_model_metadata
12
+
13
+ # ============================================================================
14
+ # Gemini Family — Version 3.x (Preview)
15
+ # 来源: https://ai.google.dev/gemini-api/docs/gemini-3
16
+ # ============================================================================
17
+
18
+ GEMINI_3X_MODELS = [
19
+ (
20
+ "gemini-3.1-pro-preview",
21
+ {
22
+ "provider": Provider.GOOGLE,
23
+ "family": ModelFamily.GEMINI,
24
+ "version": "3.1",
25
+ "variant": "pro",
26
+ "supports_thinking": True,
27
+ "supports_vision": True,
28
+ "supports_audio": True,
29
+ "supports_video": True,
30
+ "supports_streaming": True,
31
+ "supports_function_calling": True,
32
+ "supports_structured_outputs": True,
33
+ "context_window": 1_048_576,
34
+ "max_tokens": 65_536,
35
+ },
36
+ ),
37
+ (
38
+ "gemini-3-flash-preview",
39
+ {
40
+ "provider": Provider.GOOGLE,
41
+ "family": ModelFamily.GEMINI,
42
+ "version": "3.0",
43
+ "variant": "flash",
44
+ "supports_thinking": True,
45
+ "supports_vision": True,
46
+ "supports_audio": True,
47
+ "supports_video": True,
48
+ "supports_streaming": True,
49
+ "supports_function_calling": True,
50
+ "supports_structured_outputs": True,
51
+ "context_window": 1_048_576,
52
+ "max_tokens": 65_536,
53
+ },
54
+ ),
55
+ (
56
+ "gemini-3.1-flash-lite-preview",
57
+ {
58
+ "provider": Provider.GOOGLE,
59
+ "family": ModelFamily.GEMINI,
60
+ "version": "3.1",
61
+ "variant": "flash-lite",
62
+ "supports_thinking": True,
63
+ "supports_vision": True,
64
+ "supports_audio": True,
65
+ "supports_video": True,
66
+ "supports_streaming": True,
67
+ "supports_function_calling": True,
68
+ "supports_structured_outputs": True,
69
+ "context_window": 1_048_576,
70
+ "max_tokens": 65_536,
71
+ },
72
+ ),
73
+ (
74
+ # NOTE: 官方文档标注 thinking=Supported,但实测 image-preview 模型开启
75
+ # thinking 存在问题,因此保持 False。
76
+ "gemini-3-pro-image-preview",
77
+ {
78
+ "provider": Provider.GOOGLE,
79
+ "family": ModelFamily.GEMINI,
80
+ "version": "3.0",
81
+ "variant": "pro-image",
82
+ "supports_thinking": False,
83
+ "supports_vision": True,
84
+ "supports_audio": False,
85
+ "supports_video": False,
86
+ "supports_streaming": True,
87
+ "supports_function_calling": False,
88
+ "supports_structured_outputs": True,
89
+ "supports_image_generation": True,
90
+ "context_window": 65_536,
91
+ "max_tokens": 32_768,
92
+ },
93
+ ),
94
+ ]
95
+
96
+ # ============================================================================
97
+ # Gemini Family — 2026-08/09 新增(GA Flash 主线 / Nano Banana 2 / Live / TTS / Transcribe)
98
+ # 来源: https://ai.google.dev/gemini-api/docs/models/gemini-3.7-flash 等(2026-08-20 采集)
99
+ # https://ai.google.dev/gemini-api/docs/models/gemini-3.8-flash(2026-09-04 采集 3.8/transcribe/omni-1.1)
100
+ # ============================================================================
101
+
102
+ GEMINI_2026_NEW_MODELS = [
103
+ (
104
+ "gemini-3.8-flash",
105
+ {
106
+ "provider": Provider.GOOGLE,
107
+ "family": ModelFamily.GEMINI,
108
+ "version": "3.8",
109
+ "variant": "flash",
110
+ "supports_thinking": True,
111
+ "supports_vision": True,
112
+ "supports_audio": True,
113
+ "supports_video": True,
114
+ "supports_streaming": True,
115
+ "supports_function_calling": True,
116
+ "supports_structured_outputs": True,
117
+ "context_window": 1_048_576,
118
+ "max_tokens": 65_536,
119
+ },
120
+ ),
121
+ (
122
+ "gemini-3.7-flash",
123
+ {
124
+ "provider": Provider.GOOGLE,
125
+ "family": ModelFamily.GEMINI,
126
+ "version": "3.7",
127
+ "variant": "flash",
128
+ "supports_thinking": True,
129
+ "supports_vision": True,
130
+ "supports_audio": True,
131
+ "supports_video": True,
132
+ "supports_streaming": True,
133
+ "supports_function_calling": True,
134
+ "supports_structured_outputs": True,
135
+ "context_window": 1_048_576,
136
+ "max_tokens": 65_536,
137
+ },
138
+ ),
139
+ (
140
+ "gemini-3.6-flash",
141
+ {
142
+ "provider": Provider.GOOGLE,
143
+ "family": ModelFamily.GEMINI,
144
+ "version": "3.6",
145
+ "variant": "flash",
146
+ "supports_thinking": True,
147
+ "supports_vision": True,
148
+ "supports_audio": True,
149
+ "supports_video": True,
150
+ "supports_streaming": True,
151
+ "supports_function_calling": True,
152
+ "supports_structured_outputs": True,
153
+ "context_window": 1_048_576,
154
+ "max_tokens": 65_536,
155
+ },
156
+ ),
157
+ (
158
+ "gemini-3.5-flash",
159
+ {
160
+ "provider": Provider.GOOGLE,
161
+ "family": ModelFamily.GEMINI,
162
+ "version": "3.5",
163
+ "variant": "flash",
164
+ "supports_thinking": True,
165
+ "supports_vision": True,
166
+ "supports_audio": True,
167
+ "supports_video": True,
168
+ "supports_streaming": True,
169
+ "supports_function_calling": True,
170
+ "supports_structured_outputs": True,
171
+ "context_window": 1_048_576,
172
+ "max_tokens": 65_536,
173
+ },
174
+ ),
175
+ (
176
+ "gemini-3.5-flash-lite",
177
+ {
178
+ "provider": Provider.GOOGLE,
179
+ "family": ModelFamily.GEMINI,
180
+ "version": "3.5",
181
+ "variant": "flash-lite",
182
+ "supports_thinking": True,
183
+ "supports_vision": True,
184
+ "supports_audio": True,
185
+ "supports_video": True,
186
+ "supports_streaming": True,
187
+ "supports_function_calling": True,
188
+ "supports_structured_outputs": True,
189
+ "context_window": 1_048_576,
190
+ "max_tokens": 65_536,
191
+ },
192
+ ),
193
+ (
194
+ "gemini-3.1-flash-lite",
195
+ {
196
+ "provider": Provider.GOOGLE,
197
+ "family": ModelFamily.GEMINI,
198
+ "version": "3.1",
199
+ "variant": "flash-lite",
200
+ "supports_thinking": True,
201
+ "supports_vision": True,
202
+ "supports_audio": True,
203
+ "supports_video": True,
204
+ "supports_streaming": True,
205
+ "supports_function_calling": True,
206
+ "supports_structured_outputs": True,
207
+ "context_window": 1_048_576,
208
+ "max_tokens": 65_536,
209
+ },
210
+ ),
211
+ (
212
+ # Nano Banana 2:官方卡片 thinking=Supported,但接口不支持配置 thinking 行为,按家族惯例置 False
213
+ "gemini-3.1-flash-image",
214
+ {
215
+ "provider": Provider.GOOGLE,
216
+ "family": ModelFamily.GEMINI,
217
+ "version": "3.1",
218
+ "variant": "flash-image",
219
+ "supports_thinking": False,
220
+ "supports_vision": True,
221
+ "supports_audio": False,
222
+ "supports_streaming": True,
223
+ "supports_function_calling": False,
224
+ "supports_structured_outputs": False,
225
+ "supports_image_generation": True,
226
+ "context_window": 131_072,
227
+ "max_tokens": 32_768,
228
+ },
229
+ ),
230
+ (
231
+ "gemini-3.1-flash-lite-image",
232
+ {
233
+ "provider": Provider.GOOGLE,
234
+ "family": ModelFamily.GEMINI,
235
+ "version": "3.1",
236
+ "variant": "flash-lite-image",
237
+ "supports_thinking": False,
238
+ "supports_vision": True,
239
+ "supports_audio": False,
240
+ "supports_streaming": True,
241
+ "supports_function_calling": True,
242
+ "supports_structured_outputs": False,
243
+ "supports_image_generation": True,
244
+ "context_window": 65_536,
245
+ "max_tokens": 4_096,
246
+ },
247
+ ),
248
+ (
249
+ # Nano Banana Pro(GA)
250
+ "gemini-3-pro-image",
251
+ {
252
+ "provider": Provider.GOOGLE,
253
+ "family": ModelFamily.GEMINI,
254
+ "version": "3.0",
255
+ "variant": "pro-image",
256
+ "supports_thinking": False,
257
+ "supports_vision": True,
258
+ "supports_audio": False,
259
+ "supports_streaming": True,
260
+ "supports_function_calling": False,
261
+ "supports_structured_outputs": False,
262
+ "supports_image_generation": True,
263
+ "context_window": 65_536,
264
+ "max_tokens": 32_768,
265
+ },
266
+ ),
267
+ (
268
+ # 官方详情页未附规格卡:ctx 取 Live API 原生音频模型约束 128k,max 参照迁移源 12-2025
269
+ "gemini-3.1-flash-live-preview",
270
+ {
271
+ "provider": Provider.GOOGLE,
272
+ "family": ModelFamily.GEMINI,
273
+ "version": "3.1",
274
+ "variant": "flash-live",
275
+ "supports_thinking": True,
276
+ "supports_audio": True,
277
+ "supports_video": True,
278
+ "supports_streaming": True,
279
+ "supports_function_calling": True,
280
+ "supports_audio_generation": True,
281
+ "context_window": 131_072,
282
+ "max_tokens": 8_192,
283
+ },
284
+ ),
285
+ (
286
+ "gemini-3.1-flash-tts-preview",
287
+ {
288
+ "provider": Provider.GOOGLE,
289
+ "family": ModelFamily.GEMINI,
290
+ "version": "3.1",
291
+ "variant": "flash-tts",
292
+ "supports_thinking": False,
293
+ "supports_vision": False,
294
+ "supports_audio": False,
295
+ "supports_streaming": True,
296
+ "supports_structured_outputs": False,
297
+ "supports_audio_generation": True,
298
+ "context_window": 8_192,
299
+ "max_tokens": 16_384,
300
+ },
301
+ ),
302
+ (
303
+ # 官方无 token 上限说明(按音频时长限制);live 端点走 Live API
304
+ "gemini-3.5-transcribe",
305
+ {
306
+ "provider": Provider.GOOGLE,
307
+ "family": ModelFamily.GEMINI,
308
+ "version": "3.5",
309
+ "variant": "transcribe",
310
+ "supports_audio": True,
311
+ "supports_thinking": False,
312
+ "supports_function_calling": False,
313
+ "supports_streaming": True,
314
+ "supports_structured_outputs": False,
315
+ },
316
+ ),
317
+ (
318
+ "gemini-omni-1.1-flash",
319
+ {
320
+ "provider": Provider.GOOGLE,
321
+ "family": ModelFamily.GEMINI,
322
+ "version": "3.0",
323
+ "variant": "omni-flash",
324
+ "supports_vision": True,
325
+ "supports_video": True,
326
+ "supports_thinking": False,
327
+ "supports_streaming": True,
328
+ "supports_structured_outputs": False,
329
+ "context_window": 1_048_576,
330
+ },
331
+ ),
332
+ ]
333
+
334
+ # ============================================================================
335
+ # Gemini Family — Version 2.5 (Stable)
336
+ # 来源: https://ai.google.dev/gemini-api/docs/models/gemini-2.5-flash
337
+ # https://ai.google.dev/gemini-api/docs/models/gemini-2.5-pro
338
+ # https://ai.google.dev/gemini-api/docs/models/gemini-2.5-flash-lite
339
+ # ============================================================================
340
+
341
+ GEMINI_25_MODELS = [
342
+ (
343
+ "gemini-2.5-pro",
344
+ {
345
+ "provider": Provider.GOOGLE,
346
+ "family": ModelFamily.GEMINI,
347
+ "version": "2.5",
348
+ "variant": "pro",
349
+ "supports_thinking": True,
350
+ "supports_vision": True,
351
+ "supports_audio": True,
352
+ "supports_video": True,
353
+ "supports_streaming": True,
354
+ "supports_function_calling": True,
355
+ "supports_structured_outputs": True,
356
+ "context_window": 1_048_576,
357
+ "max_tokens": 65_536,
358
+ },
359
+ ),
360
+ (
361
+ "gemini-2.5-flash",
362
+ {
363
+ "provider": Provider.GOOGLE,
364
+ "family": ModelFamily.GEMINI,
365
+ "version": "2.5",
366
+ "variant": "flash",
367
+ "supports_thinking": True,
368
+ "supports_vision": True,
369
+ "supports_audio": True,
370
+ "supports_video": True,
371
+ "supports_streaming": True,
372
+ "supports_function_calling": True,
373
+ "supports_structured_outputs": True,
374
+ "context_window": 1_048_576,
375
+ "max_tokens": 65_536,
376
+ },
377
+ ),
378
+ (
379
+ "gemini-2.5-flash-lite",
380
+ {
381
+ "provider": Provider.GOOGLE,
382
+ "family": ModelFamily.GEMINI,
383
+ "version": "2.5",
384
+ "variant": "flash-lite",
385
+ "supports_thinking": True,
386
+ "supports_vision": True,
387
+ "supports_audio": True,
388
+ "supports_video": True,
389
+ "supports_streaming": True,
390
+ "supports_function_calling": True,
391
+ "supports_structured_outputs": True,
392
+ "context_window": 1_048_576,
393
+ "max_tokens": 65_536,
394
+ },
395
+ ),
396
+ ]
397
+
398
+ # ============================================================================
399
+ # Gemini Family — Version 2.0 (Deprecated)
400
+ # 来源: https://ai.google.dev/gemini-api/docs/models/gemini-2.0-flash
401
+ # https://ai.google.dev/gemini-api/docs/models/gemini-2.0-flash-lite
402
+ # ============================================================================
403
+
404
+ GEMINI_20_MODELS = [
405
+ (
406
+ "gemini-2.0-flash",
407
+ {
408
+ "provider": Provider.GOOGLE,
409
+ "family": ModelFamily.GEMINI,
410
+ "version": "2.0",
411
+ "variant": "flash",
412
+ "supports_thinking": True,
413
+ "supports_vision": True,
414
+ "supports_audio": True,
415
+ "supports_video": True,
416
+ "supports_streaming": True,
417
+ "supports_function_calling": True,
418
+ "supports_structured_outputs": True,
419
+ "context_window": 1_048_576,
420
+ "max_tokens": 8_192,
421
+ },
422
+ ),
423
+ (
424
+ "gemini-2.0-flash-lite",
425
+ {
426
+ "provider": Provider.GOOGLE,
427
+ "family": ModelFamily.GEMINI,
428
+ "version": "2.0",
429
+ "variant": "flash-lite",
430
+ "supports_thinking": False,
431
+ "supports_vision": True,
432
+ "supports_audio": True,
433
+ "supports_video": True,
434
+ "supports_streaming": True,
435
+ "supports_function_calling": True,
436
+ "supports_structured_outputs": True,
437
+ "context_window": 1_048_576,
438
+ "max_tokens": 8_192,
439
+ },
440
+ ),
441
+ ]
442
+
443
+ # ============================================================================
444
+ # 聚合 + 参数化
445
+ # ============================================================================
446
+
447
+ ALL_MODELS = GEMINI_3X_MODELS + GEMINI_2026_NEW_MODELS + GEMINI_25_MODELS + GEMINI_20_MODELS
448
+
449
+
450
+ @pytest.mark.e2e
451
+ @pytest.mark.parametrize(
452
+ "model_name,expected",
453
+ ALL_MODELS,
454
+ ids=[m[0] for m in ALL_MODELS],
455
+ )
456
+ def test_model_metadata(model_name: str, expected: dict) -> None: # type: ignore[type-arg]
457
+ """验证 Google 模型元数据与官方文档一致。"""
458
+ assert_model_metadata(model_name, expected)