Skip to content

Commit cc5a90a

Browse files
committed
feat(Application): Application can configure specified model
1 parent b2de038 commit cc5a90a

14 files changed

Lines changed: 159 additions & 27 deletions

File tree

backend/alembic/env.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@
2424

2525
# from apps.system.models.user import SQLModel # noqa
2626
# from apps.settings.models.setting_models import SQLModel
27-
from apps.chat.models.chat_model import SQLModel
28-
from apps.terminology.models.terminology_model import SQLModel
27+
#from apps.chat.models.chat_model import SQLModel
28+
#from apps.terminology.models.terminology_model import SQLModel
2929
#from apps.custom_prompt.models.custom_prompt_model import SQLModel
30-
from apps.data_training.models.data_training_model import SQLModel
30+
#from apps.data_training.models.data_training_model import SQLModel
3131
# from apps.dashboard.models.dashboard_model import SQLModel
3232
from common.core.config import settings # noqa
3333
#from apps.datasource.models.datasource import SQLModel
34+
from apps.system.models.system_model import SQLModel
3435

3536
target_metadata = SQLModel.metadata
3637

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""066_update_assistant_model
2+
3+
Revision ID: 8adc3a4919be
4+
Revises: 8ff90df7871d
5+
Create Date: 2026-04-28 15:55:42.757276
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
import sqlmodel.sql.sqltypes
11+
from sqlalchemy.dialects import postgresql
12+
13+
# revision identifiers, used by Alembic.
14+
revision = '8adc3a4919be'
15+
down_revision = '8ff90df7871d'
16+
branch_labels = None
17+
depends_on = None
18+
19+
20+
def upgrade():
21+
# ### commands auto generated by Alembic - please adjust! ###
22+
op.add_column('sys_assistant', sa.Column('enable_custom_model', sa.Boolean(), nullable=True))
23+
op.add_column('sys_assistant', sa.Column('custom_model', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=True))
24+
# ### end Alembic commands ###
25+
26+
27+
def downgrade():
28+
op.drop_column('sys_assistant', 'custom_model')
29+
op.drop_column('sys_assistant', 'enable_custom_model')
30+
# ### end Alembic commands ###

backend/apps/ai_model/model_factory.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
from common.utils.utils import prepare_model_arg
1515
from langchain_community.llms import VLLMOpenAI
1616
from langchain_openai import AzureChatOpenAI
17+
18+
1719
# from langchain_community.llms import Tongyi, VLLM
1820

1921
class LLMConfig(BaseModel):
@@ -24,16 +26,17 @@ class LLMConfig(BaseModel):
2426
api_key: Optional[str] = None
2527
api_base_url: Optional[str] = None
2628
additional_params: Dict[str, Any] = {}
29+
2730
class Config:
2831
frozen = True
2932

3033
def __hash__(self):
3134
if hasattr(self, 'additional_params') and isinstance(self.additional_params, dict):
32-
hashable_params = frozenset((k, tuple(v) if isinstance(v, (list, dict)) else v)
33-
for k, v in self.additional_params.items())
35+
hashable_params = frozenset((k, tuple(v) if isinstance(v, (list, dict)) else v)
36+
for k, v in self.additional_params.items())
3437
else:
3538
hashable_params = None
36-
39+
3740
return hash((
3841
self.model_id,
3942
self.model_type,
@@ -61,6 +64,7 @@ def llm(self) -> BaseChatModel:
6164
"""Return the langchain LLM instance"""
6265
return self._llm
6366

67+
6468
class OpenAIvLLM(BaseLLM):
6569
def _init_llm(self) -> VLLMOpenAI:
6670
return VLLMOpenAI(
@@ -71,6 +75,7 @@ def _init_llm(self) -> VLLMOpenAI:
7175
**self.config.additional_params,
7276
)
7377

78+
7479
class OpenAIAzureLLM(BaseLLM):
7580
def _init_llm(self) -> AzureChatOpenAI:
7681
api_version = self.config.additional_params.get("api_version")
@@ -88,6 +93,8 @@ def _init_llm(self) -> AzureChatOpenAI:
8893
streaming=True,
8994
**self.config.additional_params,
9095
)
96+
97+
9198
class OpenAILLM(BaseLLM):
9299
def _init_llm(self) -> BaseChatModel:
93100
return BaseChatOpenAI(
@@ -138,26 +145,30 @@ def register_llm(cls, model_type: str, llm_class: Type[BaseLLM]):
138145
return config """
139146

140147

141-
async def get_default_config() -> LLMConfig:
148+
async def get_default_config(custom_model_id: Optional[int] = None) -> LLMConfig:
142149
with Session(engine) as session:
143-
db_model = session.exec(
144-
select(AiModelDetail).where(AiModelDetail.default_model == True)
145-
).first()
150+
db_model: AiModelDetail | None = None
151+
if custom_model_id:
152+
db_model = session.get(AiModelDetail, custom_model_id)
153+
if not db_model:
154+
db_model = session.exec(
155+
select(AiModelDetail).where(AiModelDetail.default_model == True)
156+
).first()
146157
if not db_model:
147158
raise Exception("The system default model has not been set")
148159

149160
additional_params = {}
150161
if db_model.config:
151162
try:
152163
config_raw = json.loads(db_model.config)
153-
additional_params = {item["key"]: prepare_model_arg(item.get('val')) for item in config_raw if "key" in item and "val" in item}
164+
additional_params = {item["key"]: prepare_model_arg(item.get('val')) for item in config_raw if
165+
"key" in item and "val" in item}
154166
except Exception:
155167
pass
156168
if not db_model.api_domain.startswith("http"):
157169
db_model.api_domain = await sqlbot_decrypt(db_model.api_domain)
158170
if db_model.api_key:
159171
db_model.api_key = await sqlbot_decrypt(db_model.api_key)
160-
161172

162173
# 构造 LLMConfig
163174
return LLMConfig(

backend/apps/chat/task/llm.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import warnings
77
from concurrent.futures import ThreadPoolExecutor, Future
88
from datetime import datetime
9+
from dis import specialized
910
from typing import Any, List, Optional, Union, Dict, Iterator
1011

1112
import orjson
@@ -174,7 +175,13 @@ def __init__(self, session: Session, current_user: CurrentUser, chat_question: C
174175

175176
@classmethod
176177
async def create(cls, *args, **kwargs):
177-
config: LLMConfig = await get_default_config()
178+
specialized_model_id = None
179+
if args[3]:
180+
if args[3].enable_custom_model:
181+
if args[3].custom_model:
182+
specialized_model_id = args[3].custom_model
183+
print("use custom model: id[" + args[3].custom_model + "]")
184+
config: LLMConfig = await get_default_config(specialized_model_id)
178185
instance = cls(*args, **kwargs, config=config)
179186

180187
chat_params: list[SysArgModel] = await get_groups(args[0], "chat")

backend/apps/swagger/locales/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@
117117
"assistant_type": "Assistant Type (0: Basic, 1: Advanced, 4: Page)",
118118
"assistant_configuration": "Configuration",
119119
"assistant_description": "Description",
120+
"assistant_enableCustomModel": "Use specified model",
121+
"assistant_customModel": "Large Language Model",
120122

121123
"system_embedded_api": "Page Embedded API",
122124
"embedded_resetsecret_api": "Reset Secret",

backend/apps/swagger/locales/zh.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@
117117
"assistant_type": "助手类型(0: 基础, 1: 高级, 4: 页面)",
118118
"assistant_configuration": "配置",
119119
"assistant_description": "描述",
120+
"assistant_enableCustomModel": "使用指定大模型",
121+
"assistant_customModel": "大语言模型",
120122

121123
"system_embedded_api": "页面嵌入式api",
122124
"embedded_resetsecret_api": "重置 Secret",

backend/apps/system/models/system_model.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ class AssistantBaseModel(SQLModel):
5353
app_id: Optional[str] = Field(default=None, max_length=255, nullable=True)
5454
app_secret: Optional[str] = Field(default=None, max_length=255, nullable=True)
5555
oid: Optional[int] = Field(nullable=True, sa_type=BigInteger(), default=1)
56+
enable_custom_model: Optional[bool] = Field(default=False, nullable=True)
57+
custom_model: Optional[str] = Field(default=None, max_length=255, nullable=True)
5658

5759
class AssistantModel(SnowflakeBase, AssistantBaseModel, table=True):
5860
__tablename__ = "sys_assistant"

backend/apps/system/schemas/system_schema.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ class AssistantBase(BaseModel):
111111
configuration: Optional[str] = Field(default=None, description=f"{PLACEHOLDER_PREFIX}assistant_configuration")
112112
description: Optional[str] = Field(default=None, description=f"{PLACEHOLDER_PREFIX}assistant_description")
113113
oid: Optional[int] = Field(default=1, description=f"{PLACEHOLDER_PREFIX}oid")
114+
enable_custom_model: Optional[bool] = Field(default=False, description=f"{PLACEHOLDER_PREFIX}oid")
115+
custom_model: Optional[str] = Field(description=f"{PLACEHOLDER_PREFIX}oid")
114116

115117

116118
class AssistantDTO(AssistantBase, BaseCreatorDTO):

backend/templates/template.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ template:
8787
generate_rules: |
8888
以下是你必须遵守的规则和可以参考的基础示例:
8989
<Rules>
90-
<rule>
90+
<rule priority="critical">
9191
你只能生成查询用的SQL语句,不得生成增删改相关或操作数据库以及操作数据库数据的SQL
9292
</rule>
9393
<rule>

frontend/src/i18n/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,7 @@
665665
"application_name": "Application name",
666666
"application_description": "Application description",
667667
"cross_domain_settings": "Cross-domain settings",
668+
"enableCustomModel": "Use specified model",
668669
"third_party_address": "Please enter the embedded third party address,multiple items separated by semicolons",
669670
"set_to_private": "Set as private",
670671
"set_to_public": "Set as public",

0 commit comments

Comments
 (0)