whosellm 0.2.1__tar.gz → 0.2.2__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.
- {whosellm-0.2.1 → whosellm-0.2.2}/.bumpversion.toml +1 -1
- {whosellm-0.2.1 → whosellm-0.2.2}/PKG-INFO +1 -1
- {whosellm-0.2.1 → whosellm-0.2.2}/pyproject.toml +1 -1
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_deepseek.py +76 -20
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_deepseek_tencent.py +23 -1
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_gpt5.py +0 -3
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/test_auto_register.py +2 -1
- {whosellm-0.2.1 → whosellm-0.2.2}/uv.lock +1 -1
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/__init__.py +1 -1
- whosellm-0.2.2/whosellm/models/families/deepseek/deepseek_official.py +117 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/deepseek/tencent.py +22 -2
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/openai/openai_gpt_4_1.py +0 -1
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/openai/openai_gpt_5.py +0 -4
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/openai/openai_gpt_5_1.py +0 -1
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/openai/openai_gpt_5_2.py +0 -2
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/openai/openai_gpt_5_4.py +0 -4
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/zhipu.py +0 -5
- whosellm-0.2.1/whosellm/models/families/deepseek/deepseek_official.py +0 -72
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/commands/interview.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/projects/-Users-jqq-PycharmProjects-llmeta/memory/MEMORY.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/projects/-Users-jqq-PycharmProjects-llmeta/memory/feedback_use_uv.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/code-review/SKILL.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/create-skill/SKILL.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/e2e-metadata/SKILL.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/evolve/SKILL.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/fix-review/SKILL.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/release/SKILL.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/review-provider-model/SKILL.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/review-provider-model/providers/alibaba.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/review-provider-model/providers/anthropic.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/review-provider-model/providers/deepseek.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/review-provider-model/providers/gemini.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/review-provider-model/providers/openai.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/review-provider-model/providers/others.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/review-provider-model/providers/vidu.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/review-provider-model/providers/zhipu.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/update-provider-model/SKILL.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/update-provider-model/testing.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.coveragerc +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.github/workflows/publish.yml +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.github/workflows/tests.yml +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.gitignore +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.windsurf/workflows/addmodel.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.windsurf/workflows/arch.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/.windsurf/workflows/testllmeta.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/CHANGELOG.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/CLAUDE.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/LICENSE +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/README.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/docs/add_new_model_family.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/docs/refactor_proposal.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/docs/spec_model_family_redesign.md +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/examples/advanced_usage.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/examples/basic_usage.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/mypy.ini +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/pytest.ini +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/ruff.toml +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/__init__.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/e2e/__init__.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/e2e/conftest.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/e2e/test_anthropic.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/e2e/test_google.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/e2e/test_openai.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/e2e/test_zhipu.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/__init__.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/__init__.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_anthropic.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_gemini.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_glm45.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_glm45v.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_glm46.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_glm46v.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_glm5.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_gpt3_5.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_gpt4_1.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_gpt4o.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_o1.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_o3.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_o4.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_qwen.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_qwen3_vl_models.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_qwen_ollama.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/models/families/test_qwen_plus.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/test_llmeta.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/test_model_version.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/test_provider.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/test_registry_merge.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/test_specific_patterns.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/tests/test_variant_priority_config.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/capabilities.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/model_version.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/__init__.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/base.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/config.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/dynamic_enum.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/__init__.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/alibaba.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/anthropic.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/deepseek/__init__.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/gemini.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/openai/__init__.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/openai/openai_gpt_3_5.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/openai/openai_gpt_4.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/openai/openai_gpt_4o.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/openai/openai_gpt_5_3.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/openai/openai_o1.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/openai/openai_o3.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/openai/openai_o4.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/others.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/families/vidu.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/patterns.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/models/registry.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/provider.py +0 -0
- {whosellm-0.2.1 → whosellm-0.2.2}/whosellm/py.typed +0 -0
|
@@ -11,7 +11,7 @@ from whosellm.provider import Provider
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def test_deepseek_default_capabilities() -> None:
|
|
14
|
-
"""验证 DeepSeek
|
|
14
|
+
"""验证 DeepSeek 官方家族默认能力(V4 基线) / Validate DeepSeek official family default capabilities (V4 baseline)"""
|
|
15
15
|
from whosellm import LLMeta
|
|
16
16
|
|
|
17
17
|
# 使用官方 Provider 前缀确保获取官方配置
|
|
@@ -20,8 +20,10 @@ def test_deepseek_default_capabilities() -> None:
|
|
|
20
20
|
|
|
21
21
|
assert capabilities.supports_streaming is True
|
|
22
22
|
assert capabilities.supports_function_calling is True
|
|
23
|
-
|
|
24
|
-
assert capabilities.
|
|
23
|
+
# V4 系列:1M 上下文,384K 最大输出
|
|
24
|
+
assert capabilities.max_tokens == 384_000
|
|
25
|
+
assert capabilities.context_window == 1_000_000
|
|
26
|
+
# deepseek-chat 是 v4-flash 非思考模式的别名
|
|
25
27
|
assert capabilities.supports_thinking is False
|
|
26
28
|
|
|
27
29
|
|
|
@@ -31,13 +33,13 @@ def test_deepseek_chat_specific_model() -> None:
|
|
|
31
33
|
|
|
32
34
|
assert config is not None
|
|
33
35
|
version, variant, capabilities = config
|
|
34
|
-
assert version == "
|
|
36
|
+
assert version == "4.0"
|
|
35
37
|
assert variant == "chat"
|
|
36
38
|
assert capabilities is not None
|
|
37
39
|
assert capabilities.supports_function_calling is True
|
|
38
40
|
assert capabilities.supports_streaming is True
|
|
39
|
-
assert capabilities.max_tokens ==
|
|
40
|
-
assert capabilities.context_window ==
|
|
41
|
+
assert capabilities.max_tokens == 384_000
|
|
42
|
+
assert capabilities.context_window == 1_000_000
|
|
41
43
|
|
|
42
44
|
|
|
43
45
|
def test_deepseek_chat_pattern_matching() -> None:
|
|
@@ -50,7 +52,7 @@ def test_deepseek_chat_pattern_matching() -> None:
|
|
|
50
52
|
|
|
51
53
|
assert model.family == ModelFamily.DEEPSEEK
|
|
52
54
|
assert model.variant == "chat"
|
|
53
|
-
assert model.version == "
|
|
55
|
+
assert model.version == "4.0"
|
|
54
56
|
assert model.provider == Provider.DEEPSEEK
|
|
55
57
|
|
|
56
58
|
|
|
@@ -60,10 +62,12 @@ def test_deepseek_reasoner_specific_model() -> None:
|
|
|
60
62
|
|
|
61
63
|
assert config is not None
|
|
62
64
|
version, variant, capabilities = config
|
|
63
|
-
assert version == "
|
|
65
|
+
assert version == "4.0"
|
|
64
66
|
assert variant == "reasoner"
|
|
65
67
|
assert capabilities is not None
|
|
66
68
|
assert capabilities.supports_thinking is True
|
|
69
|
+
assert capabilities.max_tokens == 384_000
|
|
70
|
+
assert capabilities.context_window == 1_000_000
|
|
67
71
|
|
|
68
72
|
|
|
69
73
|
def test_deepseek_base_pattern_without_variant() -> None:
|
|
@@ -71,17 +75,16 @@ def test_deepseek_base_pattern_without_variant() -> None:
|
|
|
71
75
|
from whosellm import LLMeta
|
|
72
76
|
|
|
73
77
|
# 使用 Provider 前缀确保匹配官方配置
|
|
74
|
-
# DeepSeek 官方只支持 chat 和 reasoner,默认使用 chat
|
|
75
78
|
model = LLMeta("deepseek::deepseek-chat")
|
|
76
79
|
|
|
77
80
|
assert model.family == ModelFamily.DEEPSEEK
|
|
78
81
|
assert model.variant == "chat"
|
|
79
|
-
assert model.version == "
|
|
82
|
+
assert model.version == "4.0"
|
|
80
83
|
assert model.capabilities.supports_function_calling is True
|
|
81
84
|
|
|
82
85
|
|
|
83
86
|
def test_deepseek_reasoner_does_not_use_chat_capabilities() -> None:
|
|
84
|
-
"""验证 reasoner 不会意外继承 chat
|
|
87
|
+
"""验证 reasoner 不会意外继承 chat 的能力 / Ensure reasoner capabilities override family defaults"""
|
|
85
88
|
from whosellm import LLMeta
|
|
86
89
|
|
|
87
90
|
model = LLMeta("deepseek::deepseek-reasoner")
|
|
@@ -95,7 +98,7 @@ def test_deepseek_no_structured_outputs() -> None:
|
|
|
95
98
|
"""验证 DeepSeek 官方模型不支持 structured_outputs(仅支持 json_object)"""
|
|
96
99
|
from whosellm import LLMeta
|
|
97
100
|
|
|
98
|
-
for model_id in ["deepseek-chat", "deepseek-reasoner"]:
|
|
101
|
+
for model_id in ["deepseek-chat", "deepseek-reasoner", "deepseek-v4-flash", "deepseek-v4-pro"]:
|
|
99
102
|
model = LLMeta(f"deepseek::{model_id}")
|
|
100
103
|
assert model.capabilities.supports_structured_outputs is False, (
|
|
101
104
|
f"{model_id}: DeepSeek API 仅支持 response_format={{type:'json_object'}},"
|
|
@@ -106,15 +109,68 @@ def test_deepseek_no_structured_outputs() -> None:
|
|
|
106
109
|
)
|
|
107
110
|
|
|
108
111
|
|
|
109
|
-
def
|
|
110
|
-
"""验证
|
|
112
|
+
def test_deepseek_v4_flash_specific_model() -> None:
|
|
113
|
+
"""验证 deepseek-v4-flash 特定模型配置 / Validate deepseek-v4-flash specific configuration"""
|
|
111
114
|
from whosellm import LLMeta
|
|
112
115
|
|
|
113
|
-
|
|
114
|
-
# 官方只支持 deepseek-chat-{suffix} 和 deepseek-reasoner-{suffix}
|
|
115
|
-
model = LLMeta("deepseek::deepseek-v3.2-exp")
|
|
116
|
+
model = LLMeta("deepseek::deepseek-v4-flash")
|
|
116
117
|
|
|
117
|
-
|
|
118
|
-
assert model.
|
|
118
|
+
assert model.family == ModelFamily.DEEPSEEK
|
|
119
|
+
assert model.provider == Provider.DEEPSEEK
|
|
120
|
+
assert model.version == "4.0"
|
|
121
|
+
assert model.variant == "flash"
|
|
122
|
+
|
|
123
|
+
caps = model.capabilities
|
|
124
|
+
assert caps.supports_thinking is True
|
|
125
|
+
assert caps.supports_function_calling is True
|
|
126
|
+
assert caps.supports_streaming is True
|
|
127
|
+
assert caps.supports_json_outputs is True
|
|
128
|
+
assert caps.supports_structured_outputs is False
|
|
129
|
+
assert caps.max_tokens == 384_000
|
|
130
|
+
assert caps.context_window == 1_000_000
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def test_deepseek_v4_pro_specific_model() -> None:
|
|
134
|
+
"""验证 deepseek-v4-pro 特定模型配置 / Validate deepseek-v4-pro specific configuration"""
|
|
135
|
+
from whosellm import LLMeta
|
|
136
|
+
|
|
137
|
+
model = LLMeta("deepseek::deepseek-v4-pro")
|
|
138
|
+
|
|
139
|
+
assert model.family == ModelFamily.DEEPSEEK
|
|
140
|
+
assert model.provider == Provider.DEEPSEEK
|
|
141
|
+
assert model.version == "4.0"
|
|
142
|
+
assert model.variant == "pro"
|
|
143
|
+
|
|
144
|
+
caps = model.capabilities
|
|
145
|
+
assert caps.supports_thinking is True
|
|
146
|
+
assert caps.supports_function_calling is True
|
|
147
|
+
assert caps.max_tokens == 384_000
|
|
148
|
+
assert caps.context_window == 1_000_000
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def test_deepseek_v4_variant_ordering() -> None:
|
|
152
|
+
"""验证 v4-flash < v4-pro 的排序关系 / Validate v4-flash < v4-pro ordering"""
|
|
153
|
+
from whosellm import LLMeta
|
|
154
|
+
|
|
155
|
+
flash = LLMeta("deepseek::deepseek-v4-flash")
|
|
156
|
+
pro = LLMeta("deepseek::deepseek-v4-pro")
|
|
157
|
+
|
|
158
|
+
assert flash < pro
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def test_deepseek_versioned_pattern_matches_official_family() -> None:
|
|
162
|
+
"""验证带版本号的 DS 模型名能被官方 family 识别 / Validate versioned DS names match the official family"""
|
|
163
|
+
from whosellm import LLMeta
|
|
164
|
+
|
|
165
|
+
# V4 是 DS 官方首次开放版本号命名的系列
|
|
166
|
+
model = LLMeta("deepseek::deepseek-v4-flash")
|
|
167
|
+
assert model.family == ModelFamily.DEEPSEEK
|
|
119
168
|
assert model.provider == Provider.DEEPSEEK
|
|
120
|
-
assert model.
|
|
169
|
+
assert model.version == "4.0"
|
|
170
|
+
|
|
171
|
+
# 带小数版本号也能匹配 family(即使当前没有 specific_model 条目)
|
|
172
|
+
model_v32 = LLMeta("deepseek::deepseek-v3.2-exp")
|
|
173
|
+
assert model_v32.family == ModelFamily.DEEPSEEK
|
|
174
|
+
assert model_v32.provider == Provider.DEEPSEEK
|
|
175
|
+
assert model_v32.version == "3.2"
|
|
176
|
+
assert model_v32.variant == "exp"
|
|
@@ -66,6 +66,8 @@ def test_tencent_deepseek_r1_0528() -> None:
|
|
|
66
66
|
assert capabilities is not None
|
|
67
67
|
assert capabilities.supports_thinking is True
|
|
68
68
|
assert capabilities.context_window == 128000
|
|
69
|
+
# 腾讯云 LKE 官方文档明确列为不支持 Function Calling
|
|
70
|
+
assert capabilities.supports_function_calling is False
|
|
69
71
|
|
|
70
72
|
|
|
71
73
|
def test_tencent_deepseek_v3_1() -> None:
|
|
@@ -109,6 +111,22 @@ def test_tencent_deepseek_v3_2_exp() -> None:
|
|
|
109
111
|
assert capabilities.context_window == 128000
|
|
110
112
|
|
|
111
113
|
|
|
114
|
+
def test_tencent_deepseek_v3_2() -> None:
|
|
115
|
+
"""测试腾讯云 DeepSeek-V3.2(GA) / Test Tencent DeepSeek-V3.2 (GA)"""
|
|
116
|
+
config = get_specific_model_config("deepseek-v3.2")
|
|
117
|
+
|
|
118
|
+
assert config is not None
|
|
119
|
+
version, variant, capabilities = config
|
|
120
|
+
assert version == "v3.2"
|
|
121
|
+
assert variant == "v3.2"
|
|
122
|
+
assert capabilities is not None
|
|
123
|
+
assert capabilities.supports_thinking is True
|
|
124
|
+
assert capabilities.supports_function_calling is True
|
|
125
|
+
assert capabilities.supports_streaming is True
|
|
126
|
+
assert capabilities.max_tokens == 32000
|
|
127
|
+
assert capabilities.context_window == 128000
|
|
128
|
+
|
|
129
|
+
|
|
112
130
|
def test_tencent_deepseek_pattern_matching() -> None:
|
|
113
131
|
"""测试腾讯云 DeepSeek 模式匹配 / Test Tencent DeepSeek pattern matching"""
|
|
114
132
|
# 测试 V3 系列
|
|
@@ -158,8 +176,12 @@ def test_tencent_deepseek_no_collision_with_official() -> None:
|
|
|
158
176
|
assert tencent_v3.variant == "base"
|
|
159
177
|
|
|
160
178
|
# 不同的能力配置
|
|
161
|
-
|
|
179
|
+
# 官方 deepseek-chat 当前指向 V4-flash 非思考模式(1M 上下文,384K 输出)
|
|
180
|
+
assert official_chat.capabilities.max_tokens == 384_000
|
|
181
|
+
assert official_chat.capabilities.context_window == 1_000_000
|
|
182
|
+
# 腾讯云保持其自有的 DeepSeek 部署规格
|
|
162
183
|
assert tencent_v3.capabilities.max_tokens == 16000
|
|
184
|
+
assert tencent_v3.capabilities.context_window == 64000
|
|
163
185
|
|
|
164
186
|
|
|
165
187
|
def test_tencent_deepseek_invalid_model_names() -> None:
|
|
@@ -193,7 +193,6 @@ def test_gpt5_4_model():
|
|
|
193
193
|
assert m.capabilities.supports_computer_use is True
|
|
194
194
|
|
|
195
195
|
|
|
196
|
-
|
|
197
196
|
def test_gpt5_4_with_date_suffix():
|
|
198
197
|
"""测试带日期的GPT-5.4模型 / Test GPT-5.4 with date suffix"""
|
|
199
198
|
m = LLMeta("gpt-5.4-2026-03-05")
|
|
@@ -239,7 +238,6 @@ def test_gpt5_4_mini_model():
|
|
|
239
238
|
assert m.capabilities.supports_computer_use is True
|
|
240
239
|
|
|
241
240
|
|
|
242
|
-
|
|
243
241
|
def test_gpt5_4_mini_with_date_suffix():
|
|
244
242
|
"""测试带日期的GPT-5.4-mini模型 / Test GPT-5.4-mini with date suffix"""
|
|
245
243
|
m = LLMeta("gpt-5.4-mini-2026-03-17")
|
|
@@ -267,7 +265,6 @@ def test_gpt5_4_nano_model():
|
|
|
267
265
|
assert m.capabilities.supports_computer_use is False
|
|
268
266
|
|
|
269
267
|
|
|
270
|
-
|
|
271
268
|
def test_gpt5_4_nano_with_date_suffix():
|
|
272
269
|
"""测试带日期的GPT-5.4-nano模型 / Test GPT-5.4-nano with date suffix"""
|
|
273
270
|
m = LLMeta("gpt-5.4-nano-2026-03-17")
|
|
@@ -102,7 +102,8 @@ class TestAutoRegister(unittest.TestCase):
|
|
|
102
102
|
assert model.family == ModelFamily.DEEPSEEK
|
|
103
103
|
assert model.provider == Provider.DEEPSEEK
|
|
104
104
|
assert model.capabilities.supports_function_calling is True
|
|
105
|
-
|
|
105
|
+
# V4 起 deepseek-chat 别名为 v4-flash 非思考模式,上下文扩展为 1M
|
|
106
|
+
assert model.capabilities.context_window == 1_000_000
|
|
106
107
|
|
|
107
108
|
def test_auto_register_qwen_variant(self) -> None:
|
|
108
109
|
"""测试自动注册 Qwen 新型号 / Test auto-register Qwen new variant"""
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# filename: deepseek_official.py
|
|
2
|
+
# @Time : 2025/11/9 15:57
|
|
3
|
+
# @Author : Cascade AI
|
|
4
|
+
"""
|
|
5
|
+
DeepSeek 官方模型家族配置 / DeepSeek official model family configuration
|
|
6
|
+
|
|
7
|
+
当前主力:deepseek-v4-flash / deepseek-v4-pro(1M 上下文,384K 最大输出,
|
|
8
|
+
支持思考与非思考双模式)。
|
|
9
|
+
Current primary models: deepseek-v4-flash / deepseek-v4-pro (1M context, 384K max output,
|
|
10
|
+
both thinking and non-thinking modes supported).
|
|
11
|
+
|
|
12
|
+
兼容别名:deepseek-chat / deepseek-reasoner(官方宣布未来将废弃,当前分别对应
|
|
13
|
+
deepseek-v4-flash 的非思考与思考模式)。
|
|
14
|
+
Legacy aliases: deepseek-chat / deepseek-reasoner (announced to be deprecated;
|
|
15
|
+
currently map to deepseek-v4-flash non-thinking and thinking modes respectively).
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from whosellm.capabilities import ModelCapabilities
|
|
19
|
+
from whosellm.models.base import ModelFamily
|
|
20
|
+
from whosellm.models.config import ModelFamilyConfig, SpecificModelConfig
|
|
21
|
+
from whosellm.provider import Provider
|
|
22
|
+
|
|
23
|
+
# V4 系列共用能力基线 / Shared capability baseline for V4 series
|
|
24
|
+
_V4_CAPABILITIES = ModelCapabilities(
|
|
25
|
+
supports_thinking=True,
|
|
26
|
+
supports_function_calling=True,
|
|
27
|
+
supports_streaming=True,
|
|
28
|
+
supports_json_outputs=True,
|
|
29
|
+
# DeepSeek 仅提供 response_format={type:"json_object"},不支持 json_schema
|
|
30
|
+
# DeepSeek only supports response_format={type:"json_object"}, not json_schema
|
|
31
|
+
supports_structured_outputs=False,
|
|
32
|
+
max_tokens=384_000,
|
|
33
|
+
context_window=1_000_000,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
DEEPSEEK = ModelFamilyConfig(
|
|
37
|
+
family=ModelFamily.DEEPSEEK,
|
|
38
|
+
provider=Provider.DEEPSEEK,
|
|
39
|
+
version_default="4.0",
|
|
40
|
+
variant_default="flash",
|
|
41
|
+
variant_priority_default=(0,),
|
|
42
|
+
patterns=[
|
|
43
|
+
# 版本号命名(V4 起开放给 API 调用) / Version-numbered naming (open to API since V4)
|
|
44
|
+
"deepseek-v{major:d}.{minor:d}-{variant:variant}",
|
|
45
|
+
"deepseek-v{major:d}.{minor:d}",
|
|
46
|
+
"deepseek-v{major:d}-{variant:variant}",
|
|
47
|
+
"deepseek-v{major:d}",
|
|
48
|
+
# 兼容别名 / Legacy aliases
|
|
49
|
+
"deepseek-chat-{suffix}",
|
|
50
|
+
"deepseek-chat",
|
|
51
|
+
"deepseek-reasoner-{suffix}",
|
|
52
|
+
"deepseek-reasoner",
|
|
53
|
+
],
|
|
54
|
+
capabilities=_V4_CAPABILITIES,
|
|
55
|
+
specific_models={
|
|
56
|
+
# 当前旗舰:deepseek-v4-flash / Current flagship: deepseek-v4-flash
|
|
57
|
+
"deepseek-v4-flash": SpecificModelConfig(
|
|
58
|
+
version_default="4.0",
|
|
59
|
+
variant_default="flash",
|
|
60
|
+
variant_priority=(0,),
|
|
61
|
+
capabilities=_V4_CAPABILITIES,
|
|
62
|
+
patterns=[
|
|
63
|
+
"deepseek-v4-flash",
|
|
64
|
+
],
|
|
65
|
+
),
|
|
66
|
+
# 高阶版:deepseek-v4-pro / Professional tier: deepseek-v4-pro
|
|
67
|
+
"deepseek-v4-pro": SpecificModelConfig(
|
|
68
|
+
version_default="4.0",
|
|
69
|
+
variant_default="pro",
|
|
70
|
+
variant_priority=(4,),
|
|
71
|
+
capabilities=_V4_CAPABILITIES,
|
|
72
|
+
patterns=[
|
|
73
|
+
"deepseek-v4-pro",
|
|
74
|
+
],
|
|
75
|
+
),
|
|
76
|
+
# 兼容别名:deepseek-chat → v4-flash 非思考模式
|
|
77
|
+
# Legacy alias: deepseek-chat → v4-flash non-thinking mode
|
|
78
|
+
"deepseek-chat": SpecificModelConfig(
|
|
79
|
+
version_default="4.0",
|
|
80
|
+
variant_default="chat",
|
|
81
|
+
variant_priority=(1,),
|
|
82
|
+
capabilities=ModelCapabilities(
|
|
83
|
+
supports_thinking=False,
|
|
84
|
+
supports_function_calling=True,
|
|
85
|
+
supports_streaming=True,
|
|
86
|
+
supports_json_outputs=True,
|
|
87
|
+
supports_structured_outputs=False,
|
|
88
|
+
max_tokens=384_000,
|
|
89
|
+
context_window=1_000_000,
|
|
90
|
+
),
|
|
91
|
+
patterns=[
|
|
92
|
+
"deepseek-chat-{suffix}",
|
|
93
|
+
"deepseek-chat",
|
|
94
|
+
],
|
|
95
|
+
),
|
|
96
|
+
# 兼容别名:deepseek-reasoner → v4-flash 思考模式
|
|
97
|
+
# Legacy alias: deepseek-reasoner → v4-flash thinking mode
|
|
98
|
+
"deepseek-reasoner": SpecificModelConfig(
|
|
99
|
+
version_default="4.0",
|
|
100
|
+
variant_default="reasoner",
|
|
101
|
+
variant_priority=(2,),
|
|
102
|
+
capabilities=ModelCapabilities(
|
|
103
|
+
supports_thinking=True,
|
|
104
|
+
supports_function_calling=True,
|
|
105
|
+
supports_streaming=True,
|
|
106
|
+
supports_json_outputs=True,
|
|
107
|
+
supports_structured_outputs=False,
|
|
108
|
+
max_tokens=384_000,
|
|
109
|
+
context_window=1_000_000,
|
|
110
|
+
),
|
|
111
|
+
patterns=[
|
|
112
|
+
"deepseek-reasoner-{suffix}",
|
|
113
|
+
"deepseek-reasoner",
|
|
114
|
+
],
|
|
115
|
+
),
|
|
116
|
+
},
|
|
117
|
+
)
|
|
@@ -78,12 +78,14 @@ DEEPSEEK_TENCENT = ModelFamilyConfig(
|
|
|
78
78
|
],
|
|
79
79
|
),
|
|
80
80
|
# DeepSeek-R1-0528
|
|
81
|
+
# 腾讯云 LKE 文档明确列为 Function Calling 不支持(位于"不支持设置的功能")
|
|
82
|
+
# Tencent LKE docs explicitly list Function Calling as unsupported for this model
|
|
81
83
|
"deepseek-r1-0528": SpecificModelConfig(
|
|
82
84
|
version_default="r1-0528",
|
|
83
85
|
variant_default="r1-0528",
|
|
84
86
|
capabilities=ModelCapabilities(
|
|
85
87
|
supports_thinking=True,
|
|
86
|
-
supports_function_calling=
|
|
88
|
+
supports_function_calling=False,
|
|
87
89
|
supports_streaming=True,
|
|
88
90
|
max_tokens=16000,
|
|
89
91
|
context_window=128000,
|
|
@@ -125,7 +127,8 @@ DEEPSEEK_TENCENT = ModelFamilyConfig(
|
|
|
125
127
|
"deepseek-v3.1-terminus",
|
|
126
128
|
],
|
|
127
129
|
),
|
|
128
|
-
# DeepSeek-V3.2-Exp
|
|
130
|
+
# DeepSeek-V3.2-Exp(已被 deepseek-v3.2 GA 版替代,保留以兼容历史调用)
|
|
131
|
+
# DeepSeek-V3.2-Exp (superseded by deepseek-v3.2 GA; kept for backward compatibility)
|
|
129
132
|
"deepseek-v3.2-exp": SpecificModelConfig(
|
|
130
133
|
version_default="v3.2-exp",
|
|
131
134
|
variant_default="v3.2-exp",
|
|
@@ -141,5 +144,22 @@ DEEPSEEK_TENCENT = ModelFamilyConfig(
|
|
|
141
144
|
"deepseek-v3.2-exp",
|
|
142
145
|
],
|
|
143
146
|
),
|
|
147
|
+
# DeepSeek-V3.2(GA 版,685B MoE,稀疏注意力,可选思考模式)
|
|
148
|
+
# DeepSeek-V3.2 (GA, 685B MoE, sparse attention, optional thinking mode)
|
|
149
|
+
"deepseek-v3.2": SpecificModelConfig(
|
|
150
|
+
version_default="v3.2",
|
|
151
|
+
variant_default="v3.2",
|
|
152
|
+
capabilities=ModelCapabilities(
|
|
153
|
+
supports_thinking=True,
|
|
154
|
+
supports_function_calling=True,
|
|
155
|
+
supports_streaming=True,
|
|
156
|
+
max_tokens=32000,
|
|
157
|
+
context_window=128000,
|
|
158
|
+
),
|
|
159
|
+
variant_priority=(1,),
|
|
160
|
+
patterns=[
|
|
161
|
+
"deepseek-v3.2",
|
|
162
|
+
],
|
|
163
|
+
),
|
|
144
164
|
},
|
|
145
165
|
)
|
|
@@ -33,7 +33,6 @@ GPT_5 = ModelFamilyConfig(
|
|
|
33
33
|
supports_file_search=True,
|
|
34
34
|
supports_image_generation=True,
|
|
35
35
|
supports_code_interpreter=True,
|
|
36
|
-
|
|
37
36
|
max_tokens=128_000,
|
|
38
37
|
context_window=400_000,
|
|
39
38
|
),
|
|
@@ -66,7 +65,6 @@ GPT_5 = ModelFamilyConfig(
|
|
|
66
65
|
supports_file_search=True,
|
|
67
66
|
supports_image_generation=False,
|
|
68
67
|
supports_code_interpreter=True,
|
|
69
|
-
|
|
70
68
|
max_tokens=128_000,
|
|
71
69
|
context_window=400_000,
|
|
72
70
|
),
|
|
@@ -93,7 +91,6 @@ GPT_5 = ModelFamilyConfig(
|
|
|
93
91
|
supports_file_search=True,
|
|
94
92
|
supports_image_generation=False,
|
|
95
93
|
supports_code_interpreter=False,
|
|
96
|
-
|
|
97
94
|
max_tokens=16_384,
|
|
98
95
|
context_window=128_000,
|
|
99
96
|
),
|
|
@@ -121,7 +118,6 @@ GPT_5 = ModelFamilyConfig(
|
|
|
121
118
|
supports_image_generation=True,
|
|
122
119
|
supports_code_interpreter=True,
|
|
123
120
|
supports_computer_use=True,
|
|
124
|
-
|
|
125
121
|
max_tokens=128_000,
|
|
126
122
|
context_window=400_000,
|
|
127
123
|
),
|
|
@@ -25,7 +25,6 @@ GPT_5_2 = ModelFamilyConfig(
|
|
|
25
25
|
supports_file_search=True,
|
|
26
26
|
supports_image_generation=True,
|
|
27
27
|
supports_code_interpreter=True,
|
|
28
|
-
|
|
29
28
|
max_tokens=128_000,
|
|
30
29
|
context_window=1_050_000,
|
|
31
30
|
),
|
|
@@ -57,7 +56,6 @@ GPT_5_2 = ModelFamilyConfig(
|
|
|
57
56
|
supports_image_generation=True,
|
|
58
57
|
supports_code_interpreter=True,
|
|
59
58
|
supports_computer_use=True,
|
|
60
|
-
|
|
61
59
|
max_tokens=128_000,
|
|
62
60
|
context_window=1_050_000,
|
|
63
61
|
),
|
|
@@ -40,7 +40,6 @@ GPT_5_4 = ModelFamilyConfig(
|
|
|
40
40
|
supports_image_generation=True,
|
|
41
41
|
supports_code_interpreter=True,
|
|
42
42
|
supports_computer_use=True,
|
|
43
|
-
|
|
44
43
|
max_tokens=128_000,
|
|
45
44
|
context_window=1_050_000,
|
|
46
45
|
),
|
|
@@ -72,7 +71,6 @@ GPT_5_4 = ModelFamilyConfig(
|
|
|
72
71
|
supports_image_generation=True,
|
|
73
72
|
supports_code_interpreter=False,
|
|
74
73
|
supports_computer_use=True,
|
|
75
|
-
|
|
76
74
|
max_tokens=128_000,
|
|
77
75
|
context_window=1_050_000,
|
|
78
76
|
),
|
|
@@ -98,7 +96,6 @@ GPT_5_4 = ModelFamilyConfig(
|
|
|
98
96
|
supports_image_generation=True,
|
|
99
97
|
supports_code_interpreter=True,
|
|
100
98
|
supports_computer_use=True,
|
|
101
|
-
|
|
102
99
|
max_tokens=128_000,
|
|
103
100
|
context_window=400_000,
|
|
104
101
|
),
|
|
@@ -124,7 +121,6 @@ GPT_5_4 = ModelFamilyConfig(
|
|
|
124
121
|
supports_image_generation=True,
|
|
125
122
|
supports_code_interpreter=True,
|
|
126
123
|
supports_computer_use=False,
|
|
127
|
-
|
|
128
124
|
max_tokens=128_000,
|
|
129
125
|
context_window=400_000,
|
|
130
126
|
),
|
|
@@ -260,7 +260,6 @@ GLM_TEXT = ModelFamilyConfig(
|
|
|
260
260
|
supports_function_calling=True,
|
|
261
261
|
supports_structured_outputs=False,
|
|
262
262
|
supports_streaming=True,
|
|
263
|
-
|
|
264
263
|
max_tokens=128000,
|
|
265
264
|
context_window=200000,
|
|
266
265
|
),
|
|
@@ -275,7 +274,6 @@ GLM_TEXT = ModelFamilyConfig(
|
|
|
275
274
|
supports_function_calling=True,
|
|
276
275
|
supports_structured_outputs=False,
|
|
277
276
|
supports_streaming=True,
|
|
278
|
-
|
|
279
277
|
max_tokens=128000,
|
|
280
278
|
context_window=200000,
|
|
281
279
|
),
|
|
@@ -289,7 +287,6 @@ GLM_TEXT = ModelFamilyConfig(
|
|
|
289
287
|
supports_function_calling=True,
|
|
290
288
|
supports_structured_outputs=False,
|
|
291
289
|
supports_streaming=True,
|
|
292
|
-
|
|
293
290
|
max_tokens=128000,
|
|
294
291
|
context_window=200000,
|
|
295
292
|
),
|
|
@@ -308,7 +305,6 @@ GLM_TEXT = ModelFamilyConfig(
|
|
|
308
305
|
supports_function_calling=True,
|
|
309
306
|
supports_structured_outputs=False,
|
|
310
307
|
supports_streaming=True,
|
|
311
|
-
|
|
312
308
|
max_tokens=128000,
|
|
313
309
|
context_window=200000,
|
|
314
310
|
),
|
|
@@ -329,7 +325,6 @@ GLM_TEXT = ModelFamilyConfig(
|
|
|
329
325
|
supports_streaming=True,
|
|
330
326
|
supports_structured_outputs=False,
|
|
331
327
|
supports_web_search=True,
|
|
332
|
-
|
|
333
328
|
max_tokens=128000,
|
|
334
329
|
context_window=200000,
|
|
335
330
|
),
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# filename: deepseek_official.py
|
|
2
|
-
# @Time : 2025/11/9 15:57
|
|
3
|
-
# @Author : Cascade AI
|
|
4
|
-
"""
|
|
5
|
-
DeepSeek 官方模型家族配置 / DeepSeek official model family configuration
|
|
6
|
-
|
|
7
|
-
包含 deepseek-chat 与 deepseek-reasoner 模型
|
|
8
|
-
Includes deepseek-chat and deepseek-reasoner models
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
from whosellm.capabilities import ModelCapabilities
|
|
12
|
-
from whosellm.models.base import ModelFamily
|
|
13
|
-
from whosellm.models.config import ModelFamilyConfig, SpecificModelConfig
|
|
14
|
-
from whosellm.provider import Provider
|
|
15
|
-
|
|
16
|
-
DEEPSEEK = ModelFamilyConfig(
|
|
17
|
-
family=ModelFamily.DEEPSEEK,
|
|
18
|
-
provider=Provider.DEEPSEEK,
|
|
19
|
-
version_default="1.0",
|
|
20
|
-
variant_default="base",
|
|
21
|
-
variant_priority_default=(1,),
|
|
22
|
-
patterns=[
|
|
23
|
-
"deepseek-chat-{suffix}",
|
|
24
|
-
"deepseek-chat",
|
|
25
|
-
"deepseek-reasoner-{suffix}",
|
|
26
|
-
"deepseek-reasoner",
|
|
27
|
-
],
|
|
28
|
-
capabilities=ModelCapabilities(
|
|
29
|
-
supports_function_calling=True,
|
|
30
|
-
supports_streaming=True,
|
|
31
|
-
supports_structured_outputs=False,
|
|
32
|
-
max_tokens=8000,
|
|
33
|
-
context_window=128000,
|
|
34
|
-
),
|
|
35
|
-
specific_models={
|
|
36
|
-
"deepseek-chat": SpecificModelConfig(
|
|
37
|
-
version_default="1.0",
|
|
38
|
-
variant_default="chat",
|
|
39
|
-
capabilities=ModelCapabilities(
|
|
40
|
-
supports_function_calling=True,
|
|
41
|
-
supports_streaming=True,
|
|
42
|
-
supports_structured_outputs=False,
|
|
43
|
-
max_tokens=8000,
|
|
44
|
-
context_window=128000,
|
|
45
|
-
),
|
|
46
|
-
variant_priority=(1,),
|
|
47
|
-
patterns=[
|
|
48
|
-
"deepseek-chat-{suffix}",
|
|
49
|
-
"deepseek-chat",
|
|
50
|
-
],
|
|
51
|
-
),
|
|
52
|
-
"deepseek-reasoner": SpecificModelConfig(
|
|
53
|
-
version_default="1.0",
|
|
54
|
-
variant_default="reasoner",
|
|
55
|
-
capabilities=ModelCapabilities(
|
|
56
|
-
supports_thinking=True,
|
|
57
|
-
supports_streaming=True,
|
|
58
|
-
# DS Reasoner模型原生是不支持工具调用的,但是官方做了优化,如果向R1模型发起带有Tools调用的请求,会自动路由至Chat模型。
|
|
59
|
-
# 因此在这里标记为支持FunctionCall
|
|
60
|
-
supports_function_calling=True,
|
|
61
|
-
supports_structured_outputs=False,
|
|
62
|
-
max_tokens=64000,
|
|
63
|
-
context_window=128000,
|
|
64
|
-
),
|
|
65
|
-
variant_priority=(2,),
|
|
66
|
-
patterns=[
|
|
67
|
-
"deepseek-reasoner-{suffix}",
|
|
68
|
-
"deepseek-reasoner",
|
|
69
|
-
],
|
|
70
|
-
),
|
|
71
|
-
},
|
|
72
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/review-provider-model/providers/anthropic.md
RENAMED
|
File without changes
|
{whosellm-0.2.1 → whosellm-0.2.2}/.claude/skills/review-provider-model/providers/deepseek.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|