From 05e217ab8a4195a8cb10d8b8801a121362490965 Mon Sep 17 00:00:00 2001 From: ulleo Date: Tue, 16 Dec 2025 16:11:47 +0800 Subject: [PATCH] feat: implement parameter configuration in chat --- backend/apps/chat/task/llm.py | 16 ++++++- backend/apps/system/api/parameter.py | 16 +++++-- backend/common/core/config.py | 1 + frontend/src/stores/chatConfig.ts | 46 +++++++++++++++++++ frontend/src/views/chat/answer/BaseAnswer.vue | 6 ++- frontend/src/views/chat/index.vue | 7 ++- frontend/src/views/system/parameter/index.vue | 8 ++-- 7 files changed, 87 insertions(+), 13 deletions(-) create mode 100644 frontend/src/stores/chatConfig.ts diff --git a/backend/apps/chat/task/llm.py b/backend/apps/chat/task/llm.py index 4b2c4ebd..3e2106b1 100644 --- a/backend/apps/chat/task/llm.py +++ b/backend/apps/chat/task/llm.py @@ -17,6 +17,7 @@ from langchain_core.messages import BaseMessage, SystemMessage, HumanMessage, AIMessage, BaseMessageChunk from sqlalchemy import and_, select from sqlalchemy.orm import sessionmaker, scoped_session +from sqlbot_xpack.config.model import SysArgModel from sqlbot_xpack.custom_prompt.curd.custom_prompt import find_custom_prompts from sqlbot_xpack.custom_prompt.models.custom_prompt_model import CustomPromptTypeEnum from sqlbot_xpack.license.license_manage import SQLBotLicenseUtil @@ -39,6 +40,7 @@ from apps.datasource.models.datasource import CoreDatasource from apps.db.db import exec_sql, get_version, check_connection from apps.system.crud.assistant import AssistantOutDs, AssistantOutDsFactory, get_assistant_ds +from apps.system.crud.parameter_manage import get_groups from apps.system.schemas.system_schema import AssistantOutDsSchema from apps.terminology.curd.terminology import get_terminology_template from common.core.config import settings @@ -86,6 +88,8 @@ class LLMService: last_execute_sql_error: str = None articles_number: int = 4 + enable_sql_row_limit: bool = settings.GENERATE_SQL_QUERY_LIMIT_ENABLED + def __init__(self, session: Session, current_user: CurrentUser, chat_question: ChatQuestion, current_assistant: Optional[CurrentAssistant] = None, no_reasoning: bool = False, embedding: bool = False, config: LLMConfig = None): @@ -152,6 +156,14 @@ def __init__(self, session: Session, current_user: CurrentUser, chat_question: C async def create(cls, *args, **kwargs): config: LLMConfig = await get_default_config() instance = cls(*args, **kwargs, config=config) + + chat_params: list[SysArgModel] = await get_groups(args[0], "chat") + for config in chat_params: + if config.pkey == 'chat.limit_rows': + if config.pval.lower().strip() == 'true': + instance.enable_sql_row_limit = True + else: + instance.enable_sql_row_limit = False return instance def is_running(self, timeout=0.5): @@ -179,7 +191,7 @@ def init_messages(self): self.sql_message = [] # add sys prompt self.sql_message.append(SystemMessage( - content=self.chat_question.sql_sys_question(self.ds.type, settings.GENERATE_SQL_QUERY_LIMIT_ENABLED))) + content=self.chat_question.sql_sys_question(self.ds.type, self.enable_sql_row_limit))) if last_sql_messages is not None and len(last_sql_messages) > 0: # limit count for last_sql_message in last_sql_messages[count_limit:]: @@ -861,7 +873,7 @@ def save_sql_data(self, session: Session, data_obj: Dict[str, Any]): limit = 1000 if data_result: data_result = prepare_for_orjson(data_result) - if data_result and len(data_result) > limit and settings.GENERATE_SQL_QUERY_LIMIT_ENABLED: + if data_result and len(data_result) > limit and self.enable_sql_row_limit: data_obj['data'] = data_result[:limit] data_obj['limit'] = limit else: diff --git a/backend/apps/system/api/parameter.py b/backend/apps/system/api/parameter.py index fce8bd46..27901e59 100644 --- a/backend/apps/system/api/parameter.py +++ b/backend/apps/system/api/parameter.py @@ -1,24 +1,30 @@ - from fastapi import APIRouter, Request from sqlbot_xpack.config.model import SysArgModel - from apps.system.crud.parameter_manage import get_groups, get_parameter_args, save_parameter_args from apps.system.schemas.permission import SqlbotPermission, require_permissions from common.core.deps import SessionDep router = APIRouter(tags=["system/parameter"], prefix="/system/parameter", include_in_schema=False) + @router.get("/login") async def get_login_args(session: SessionDep) -> list[SysArgModel]: return await get_groups(session, "login") + @router.get("") -@require_permissions(permission=SqlbotPermission(role=['admin'])) +@require_permissions(permission=SqlbotPermission(role=['admin'])) async def get_args(session: SessionDep) -> list[SysArgModel]: return await get_parameter_args(session) + @router.post("", ) -@require_permissions(permission=SqlbotPermission(role=['admin'])) +@require_permissions(permission=SqlbotPermission(role=['admin'])) async def save_args(session: SessionDep, request: Request): - return await save_parameter_args(session = session, request = request) + return await save_parameter_args(session=session, request=request) + + +@router.get("/chat") +async def get_chat_args(session: SessionDep) -> list[SysArgModel]: + return await get_groups(session, "chat") diff --git a/backend/common/core/config.py b/backend/common/core/config.py index b2c2d66f..fec6832d 100644 --- a/backend/common/core/config.py +++ b/backend/common/core/config.py @@ -98,6 +98,7 @@ def SQLALCHEMY_DATABASE_URI(self) -> PostgresDsn | str: EMBEDDING_TERMINOLOGY_TOP_COUNT: int = EMBEDDING_DEFAULT_TOP_COUNT EMBEDDING_DATA_TRAINING_TOP_COUNT: int = EMBEDDING_DEFAULT_TOP_COUNT + # 是否启用SQL查询行数限制,默认值,可被参数配置覆盖 GENERATE_SQL_QUERY_LIMIT_ENABLED: bool = True PARSE_REASONING_BLOCK_ENABLED: bool = True diff --git a/frontend/src/stores/chatConfig.ts b/frontend/src/stores/chatConfig.ts new file mode 100644 index 00000000..a4ad4def --- /dev/null +++ b/frontend/src/stores/chatConfig.ts @@ -0,0 +1,46 @@ +import { defineStore } from 'pinia' +import { store } from '@/stores/index.ts' +import { request } from '@/utils/request.ts' +import { formatArg } from '@/utils/utils.ts' + +interface ChatConfig { + expand_thinking_block: boolean + limit_rows: boolean +} + +export const chatConfigStore = defineStore('chatConfigStore', { + state: (): ChatConfig => { + return { + expand_thinking_block: false, + limit_rows: true, + } + }, + getters: { + getExpandThinkingBlock(): boolean { + return this.expand_thinking_block + }, + getLimitRows(): boolean { + return this.limit_rows + }, + }, + actions: { + fetchGlobalConfig() { + request.get('/system/parameter/chat').then((res: any) => { + if (res) { + res.forEach((item: any) => { + if (item.pkey === 'chat.expand_thinking_block') { + this.expand_thinking_block = formatArg(item.pval) + } + if (item.pkey === 'chat.limit_rows') { + this.limit_rows = formatArg(item.pval) + } + }) + } + }) + }, + }, +}) + +export const useChatConfigStore = () => { + return chatConfigStore(store) +} diff --git a/frontend/src/views/chat/answer/BaseAnswer.vue b/frontend/src/views/chat/answer/BaseAnswer.vue index c3fb583f..cd957471 100644 --- a/frontend/src/views/chat/answer/BaseAnswer.vue +++ b/frontend/src/views/chat/answer/BaseAnswer.vue @@ -5,6 +5,7 @@ import MdComponent from '@/views/chat/component/MdComponent.vue' import icon_up_outlined from '@/assets/svg/icon_up_outlined.svg' import icon_down_outlined from '@/assets/svg/icon_down_outlined.svg' import { useI18n } from 'vue-i18n' +import { useChatConfigStore } from '@/stores/chatConfig.ts' const props = withDefaults( defineProps<{ @@ -24,6 +25,8 @@ const props = withDefaults( const { t } = useI18n() +const chatConfig = useChatConfigStore() + const show = ref(false) const reasoningContent = computed>(() => { @@ -63,7 +66,8 @@ function clickShow() { onMounted(() => { if (props.message.isTyping) { - show.value = true + // 根据配置项是否默认展开 + show.value = chatConfig.getExpandThinkingBlock } }) diff --git a/frontend/src/views/chat/index.vue b/frontend/src/views/chat/index.vue index da20796b..ffc28f45 100644 --- a/frontend/src/views/chat/index.vue +++ b/frontend/src/views/chat/index.vue @@ -410,7 +410,7 @@ type="primary" class="input-icon" :disabled="isTyping" - @click.stop="sendMessage" + @click.stop="($event: any) => sendMessage(undefined, $event)" > @@ -458,6 +458,7 @@ import { debounce } from 'lodash-es' import { isMobile } from '@/utils/utils' import router from '@/router' import QuickQuestion from '@/views/chat/QuickQuestion.vue' +import { useChatConfigStore } from '@/stores/chatConfig.ts' const userStore = useUserStore() const props = defineProps<{ startChatDsId?: number @@ -486,6 +487,9 @@ const customName = computed(() => { return '' }) const { t } = useI18n() + +const chatConfig = useChatConfigStore() + const isPhone = computed(() => { return isMobile() }) @@ -1062,6 +1066,7 @@ function jumpCreatChat() { } onMounted(() => { + chatConfig.fetchGlobalConfig() if (isPhone.value) { chatListSideBarShow.value = false if (props.pageEmbedded) { diff --git a/frontend/src/views/system/parameter/index.vue b/frontend/src/views/system/parameter/index.vue index ab9bf5c1..2c1e47b1 100644 --- a/frontend/src/views/system/parameter/index.vue +++ b/frontend/src/views/system/parameter/index.vue @@ -9,8 +9,8 @@ const { t } = useI18n() const state = reactive({ parameterForm: reactive({ - 'chat.enable_model_thinking': false, - 'chat.rows_of_data': false, + 'chat.expand_thinking_block': false, + 'chat.limit_rows': false, }), }) provide('parameterForm', state.parameterForm) @@ -99,7 +99,7 @@ onMounted(() => {
- +
@@ -118,7 +118,7 @@ onMounted(() => {