Skip to content

Commit 8c8115b

Browse files
authored
Merge pull request #1591 from Mai-with-u/dev
Dev
2 parents 28172cb + 5b9f418 commit 8c8115b

4 files changed

Lines changed: 160 additions & 6 deletions

File tree

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ dependencies = [
3535
"python-dotenv>=1.1.1",
3636
"python-multipart>=0.0.20",
3737
"python-levenshtein",
38-
"quick-algo>=0.1.4",
3938
"rich>=14.0.0",
4039
"scipy>=1.7.0",
4140
"sqlalchemy>=2.0.40",

requirements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ pypinyin>=0.54.0
2222
python-dotenv>=1.1.1
2323
python-multipart>=0.0.20
2424
python-levenshtein
25-
quick-algo>=0.1.4
2625
rich>=14.0.0
2726
scipy>=1.7.0
2827
sqlalchemy>=2.0.40

src/config/config.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
from .config_base import AttributeData, ConfigBase, Field
1313
from .config_utils import compare_versions, output_config_changes, recursive_parse_item_to_table
14+
from .default_model_config import create_default_model_config
1415
from .file_watcher import FileChange, FileWatcher
1516
from .legacy_migration import migrate_legacy_bind_env_to_bot_config_dict, try_migrate_legacy_bot_config_dict
1617
from .model_configs import APIProvider, ModelInfo, ModelTaskConfig
@@ -55,7 +56,7 @@
5556
LEGACY_ENV_PATH: Path = (PROJECT_ROOT / ".env").resolve().absolute()
5657
MMC_VERSION: str = "1.0.0"
5758
CONFIG_VERSION: str = "8.9.3"
58-
MODEL_CONFIG_VERSION: str = "1.14.0"
59+
MODEL_CONFIG_VERSION: str = "1.14.1"
5960

6061
logger = get_logger("config")
6162

@@ -439,15 +440,20 @@ async def _handle_file_changes(self, changes: Sequence[FileChange]) -> None:
439440
logger.error(t("config.reload_timeout", timeout_seconds=self._hot_reload_timeout_s))
440441

441442

442-
def generate_new_config_file(config_class: type[T], config_path: Path, inner_config_version: str) -> None:
443+
def generate_new_config_file(
444+
config_class: type[T], config_path: Path, inner_config_version: str, override_repr: bool = False
445+
) -> None:
443446
"""生成新的配置文件
444447
445448
:param config_class: 配置类
446449
:param config_path: 配置文件路径
447450
:param inner_config_version: 配置文件版本号
448451
"""
449-
config = config_class()
450-
write_config_to_file(config, config_path, inner_config_version)
452+
if config_class is ModelConfig:
453+
config = create_default_model_config(config_class)
454+
else:
455+
config = config_class()
456+
write_config_to_file(config, config_path, inner_config_version, override_repr)
451457

452458

453459
def remove_legacy_env_file(env_path: Path) -> None:
@@ -468,6 +474,9 @@ def load_config_from_file(
468474
config_class: type[T], config_path: Path, new_ver: str, override_repr: bool = False
469475
) -> tuple[T, bool]:
470476
attribute_data = AttributeData()
477+
if not config_path.exists():
478+
logger.warning(f"配置文件缺失,正在生成默认配置: {config_path}")
479+
generate_new_config_file(config_class, config_path, new_ver, override_repr)
471480
with open(config_path, "r", encoding="utf-8") as f:
472481
config_data = tomlkit.load(f)
473482
inner_table = config_data.get("inner")

src/config/default_model_config.py

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
from typing import Any, TypeVar
2+
3+
from .config_base import ConfigBase
4+
from .model_configs import APIProvider, ModelInfo, ModelTaskConfig, OpenAICompatibleAuthType, TaskConfig
5+
6+
T = TypeVar("T", bound=ConfigBase)
7+
8+
DEFAULT_PROVIDER_TEMPLATES: list[dict[str, Any]] = [
9+
{
10+
"name": "BaiLian",
11+
"base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
12+
"api_key": "your-api-key",
13+
"auth_type": OpenAICompatibleAuthType.BEARER.value,
14+
}
15+
]
16+
17+
DEFAULT_TASK_CONFIG_TEMPLATES: dict[str, dict[str, Any]] = {
18+
"utils": {
19+
"model_list": ["qwen3.5-35b-a3b-nonthink"],
20+
"max_tokens": 4096,
21+
"temperature": 0.5,
22+
"slow_threshold": 15.0,
23+
"selection_strategy": "random",
24+
},
25+
"replyer": {
26+
"model_list": ["ali-glm-5"],
27+
"max_tokens": 4096,
28+
"temperature": 1,
29+
"slow_threshold": 120.0,
30+
"selection_strategy": "random",
31+
},
32+
"planner": {
33+
"model_list": ["qwen3.5-35b-a3b", "qwen3.5-122b-a10b", "qwen3.5-flash"],
34+
"max_tokens": 8000,
35+
"temperature": 0.7,
36+
"slow_threshold": 12.0,
37+
"selection_strategy": "random",
38+
},
39+
"vlm": {
40+
"model_list": ["qwen3.5-flash"],
41+
"max_tokens": 512,
42+
"temperature": 0.3,
43+
"slow_threshold": 15.0,
44+
"selection_strategy": "random",
45+
},
46+
"voice": {
47+
"model_list": [""],
48+
"max_tokens": 1024,
49+
"temperature": 0.3,
50+
"slow_threshold": 12.0,
51+
"selection_strategy": "random",
52+
},
53+
"embedding": {
54+
"model_list": ["qwen3-embedding"],
55+
"max_tokens": 1024,
56+
"temperature": 0.3,
57+
"slow_threshold": 5.0,
58+
"selection_strategy": "random",
59+
},
60+
}
61+
62+
DEFAULT_MODEL_TEMPLATES: list[dict[str, Any]] = [
63+
{
64+
"model_identifier": "glm-5",
65+
"name": "ali-glm-5",
66+
"api_provider": "BaiLian",
67+
"price_in": 3.0,
68+
"price_out": 14.0,
69+
"temperature": 1.0,
70+
"visual": False,
71+
"extra_params": {"enable_thinking": False},
72+
},
73+
{
74+
"model_identifier": "qwen3.5-122b-a10b",
75+
"name": "qwen3.5-122b-a10b",
76+
"api_provider": "BaiLian",
77+
"price_in": 0.8,
78+
"price_out": 6.4,
79+
"visual": True,
80+
"extra_params": {"enable_thinking": "false"},
81+
},
82+
{
83+
"model_identifier": "qwen3.5-35b-a3b",
84+
"name": "qwen3.5-35b-a3b",
85+
"api_provider": "BaiLian",
86+
"price_in": 0.4,
87+
"price_out": 3.2,
88+
"visual": True,
89+
"extra_params": {},
90+
},
91+
{
92+
"model_identifier": "qwen3.5-35b-a3b",
93+
"name": "qwen3.5-35b-a3b-nonthink",
94+
"api_provider": "BaiLian",
95+
"price_in": 0.4,
96+
"price_out": 3.2,
97+
"visual": True,
98+
"extra_params": {"enable_thinking": "false"},
99+
},
100+
{
101+
"model_identifier": "qwen3.5-flash",
102+
"name": "qwen3.5-flash",
103+
"api_provider": "BaiLian",
104+
"price_in": 0.2,
105+
"price_out": 2.0,
106+
"visual": True,
107+
"extra_params": {"enable_thinking": "false"},
108+
},
109+
{
110+
"model_identifier": "text-embedding-v4",
111+
"name": "qwen3-embedding",
112+
"api_provider": "BaiLian",
113+
"price_in": 0.5,
114+
"price_out": 0.5,
115+
"visual": False,
116+
"extra_params": {},
117+
}
118+
]
119+
120+
121+
def build_default_model_templates() -> list[dict[str, Any]]:
122+
"""筛选任务分配中实际用到的模型模板。"""
123+
124+
used_model_names = {
125+
model_name
126+
for task_template in DEFAULT_TASK_CONFIG_TEMPLATES.values()
127+
for model_name in task_template["model_list"]
128+
}
129+
return [model_template for model_template in DEFAULT_MODEL_TEMPLATES if model_template["name"] in used_model_names]
130+
131+
132+
def create_default_model_config(config_class: type[T]) -> T:
133+
"""根据预置模板创建可通过校验的默认模型配置。"""
134+
135+
task_config_fields = {}
136+
for field_name, field_info in ModelTaskConfig.model_fields.items():
137+
if field_info.annotation is not TaskConfig:
138+
continue
139+
140+
task_template = DEFAULT_TASK_CONFIG_TEMPLATES.get(field_name, {})
141+
task_config_fields[field_name] = TaskConfig(**task_template)
142+
143+
return config_class(
144+
models=[ModelInfo(**model_template) for model_template in build_default_model_templates()],
145+
model_task_config=ModelTaskConfig(**task_config_fields),
146+
api_providers=[APIProvider(**provider_template) for provider_template in DEFAULT_PROVIDER_TEMPLATES],
147+
)

0 commit comments

Comments
 (0)