feat: Check default llm before chat

This commit is contained in:
fit2cloud-chenyw
2025-07-31 17:53:34 +08:00
parent 5ea91ec825
commit 0f8e1c8a19
11 changed files with 137 additions and 29 deletions
+1 -1
View File
@@ -110,7 +110,7 @@ def get_default_config() -> LLMConfig:
select(AiModelDetail).where(AiModelDetail.default_model == True)
).first()
if not db_model:
raise ValueError("The system default model has not been set")
raise Exception("The system default model has not been set")
additional_params = {}
if db_model.config:
+27 -17
View File
@@ -38,6 +38,33 @@ async def check_llm(info: AiModelCreator, trans: Trans):
return StreamingResponse(generate(), media_type="application/x-ndjson")
@router.get("/default")
async def check_default(session: SessionDep, trans: Trans):
db_model = session.exec(
select(AiModelDetail).where(AiModelDetail.default_model == True)
).first()
if not db_model:
raise Exception(trans('i18n_llm.miss_default'))
@router.put("/default/{id}")
async def set_default(session: SessionDep, id: int):
db_model = session.get(AiModelDetail, id)
if not db_model:
raise ValueError(f"AiModelDetail with id {id} not found")
if db_model.default_model:
return
try:
session.exec(
update(AiModelDetail).values(default_model=False)
)
db_model.default_model = True
session.add(db_model)
session.commit()
except Exception as e:
session.rollback()
raise e
@router.get("", response_model=list[AiModelGridItem])
async def query(
session: SessionDep,
@@ -119,22 +146,5 @@ async def delete_model(
session.delete(item)
session.commit()
@router.put("/default/{id}")
async def set_default(session: SessionDep, id: int):
db_model = session.get(AiModelDetail, id)
if not db_model:
raise ValueError(f"AiModelDetail with id {id} not found")
if db_model.default_model:
return
try:
session.exec(
update(AiModelDetail).values(default_model=False)
)
db_model.default_model = True
session.add(db_model)
session.commit()
except Exception as e:
session.rollback()
raise e
+2 -1
View File
@@ -29,6 +29,7 @@
},
"i18n_llm": {
"validate_error": "Validation failed [{msg}]",
"delete_default_error": "Cannot delete default model [{key}]!"
"delete_default_error": "Cannot delete default model [{key}]!",
"miss_default": "The default large language model has not been configured"
}
}
+2 -1
View File
@@ -30,6 +30,7 @@
},
"i18n_llm": {
"validate_error": "校验失败[{msg}]",
"delete_default_error": "无法删除默认模型[{key}]!"
"delete_default_error": "无法删除默认模型[{key}]!",
"miss_default": "尚未配置默认大语言模型"
}
}
+1
View File
@@ -328,4 +328,5 @@ export const chatApi = {
recommendQuestions: (record_id: number | undefined, controller?: AbortController) => {
return request.fetchStream(`/chat/recommend_questions/${record_id}`, {}, controller)
},
checkLLMModel: () => request.get('/system/aimodel/default', { requestOptions: { silent: true } }),
}
+1 -1
View File
@@ -22,7 +22,7 @@ export const supplierList: Array<{
},
{
id: 2,
name: '千帆大模型I',
name: '千帆大模型',
icon: icon_bdyzn_colorful,
model_config: {
0: {
+6 -2
View File
@@ -133,7 +133,8 @@
"no_time": "No Time",
"rename_conversation_title": "Rename conversation title",
"conversation_title": "Conversation title",
"copied": "Copied"
"copied": "Copied",
"ask_failed": "Q&A failed"
},
"ds": {
"title": "Data Sources",
@@ -291,7 +292,10 @@
"del_default_tip": "Unable to delete the model: {msg}",
"del_default_warn": "This model is the system default model. Please set another model as the system default before deleting this model.",
"del_warn_tip": "Would you like to remove the model: {msg}?",
"check_failed": "Model is invalid [{msg}]"
"check_failed": "Model is invalid [{msg}]",
"default_miss": "The default llm has not been configured yet, so the q&a feature cannot be enabled, Please contact the administrator to configure it.",
"default_miss_admin": "The default llm has not been configured yet, so the q&a feature cannot be enabled.",
"to_config": "Go to configuration"
},
"user": {
"workspace": "Workspace",
+6 -2
View File
@@ -133,7 +133,8 @@
"no_time": "没有时间",
"rename_conversation_title": "重命名对话标题",
"conversation_title": "对话标题",
"copied": "已复制"
"copied": "已复制",
"ask_failed": "问数失败"
},
"ds": {
"title": "数据源",
@@ -291,7 +292,10 @@
"del_default_tip": "无法删除模型: {msg}",
"del_default_warn": "该模型为系统默认模型,请先设置其他模型为系统默认模型,再删除此模型。",
"del_warn_tip": "是否删除模型: {msg}?",
"check_failed": "模型无效【{msg}】"
"check_failed": "模型无效【{msg}】",
"default_miss": "尚未配置默认大语言大模型,因此无法开启问数,请联系管理员配置。",
"default_miss_admin": "尚未配置默认大语言大模型,因此无法开启问数。",
"to_config": "去配置"
},
"user": {
"workspace": "工作空间",
+30 -1
View File
@@ -9,7 +9,9 @@ import ChatCreator from '@/views/chat/ChatCreator.vue'
import { useAssistantStore } from '@/stores/assistant'
import icon_sidebar_outlined from '@/assets/svg/icon_sidebar_outlined.svg'
import icon_new_chat_outlined from '@/assets/svg/icon_new_chat_outlined.svg'
import { useUserStore } from '@/stores/user'
import router from '@/router'
const userStore = useUserStore()
const props = withDefaults(
defineProps<{
inPopover?: boolean
@@ -112,6 +114,33 @@ function goEmpty(func?: (...p: any[]) => void, ...params: any[]) {
}
const createNewChat = async () => {
try {
await chatApi.checkLLMModel()
} catch (error: any) {
console.error(error)
let errorMsg = t('model.default_miss')
let confirm_text = t('datasource.got_it')
if (userStore.isAdmin) {
errorMsg = t('model.default_miss_admin')
confirm_text = t('model.to_config')
}
ElMessageBox.confirm(t('qa.ask_failed'), {
confirmButtonType: 'primary',
tip: errorMsg,
showCancelButton: userStore.isAdmin,
confirmButtonText: confirm_text,
cancelButtonText: t('common.cancel'),
customClass: 'confirm-no_icon',
autofocus: false,
showClose: false,
callback: (val: string) => {
if (userStore.isAdmin && val === 'confirm') {
router.push('/system/model')
}
},
})
return
}
goEmpty(doCreateNewChat)
}
+30 -1
View File
@@ -356,7 +356,9 @@ import logo from '@/assets/LOGO.svg'
import icon_send_filled from '@/assets/svg/icon_send_filled.svg'
import { useAssistantStore } from '@/stores/assistant'
import { onClickOutside } from '@vueuse/core'
import { useUserStore } from '@/stores/user'
import router from '@/router'
const userStore = useUserStore()
const props = defineProps<{
startChatDsId?: number
}>()
@@ -437,6 +439,33 @@ const createNewChatSimple = async () => {
}
const createNewChat = async () => {
try {
await chatApi.checkLLMModel()
} catch (error: any) {
console.error(error)
let errorMsg = t('model.default_miss')
let confirm_text = t('datasource.got_it')
if (userStore.isAdmin) {
errorMsg = t('model.default_miss_admin')
confirm_text = t('model.to_config')
}
ElMessageBox.confirm(t('qa.ask_failed'), {
confirmButtonType: 'primary',
tip: errorMsg,
showCancelButton: userStore.isAdmin,
confirmButtonText: confirm_text,
cancelButtonText: t('common.cancel'),
customClass: 'confirm-no_icon',
autofocus: false,
showClose: false,
callback: (val: string) => {
if (userStore.isAdmin && val === 'confirm') {
router.push('/system/model')
}
},
})
return
}
goEmpty()
if (isAssistant.value) {
currentChat.value = new ChatInfo()
+31 -2
View File
@@ -18,7 +18,9 @@ import Card from './Card.vue'
import DelMessageBox from './DelMessageBox.vue'
import { dsTypeWithImg } from './js/ds-type'
import { useI18n } from 'vue-i18n'
import { useUserStore } from '@/stores/user'
import { chatApi } from '@/api/chat'
const userStore = useUserStore()
interface Datasource {
name: string
num: string
@@ -99,7 +101,34 @@ const handleEditDatasource = (res: any) => {
})
}
const handleQuestion = (id: string) => {
const handleQuestion = async (id: string) => {
try {
await chatApi.checkLLMModel()
} catch (error: any) {
console.error(error)
let errorMsg = t('model.default_miss')
let confirm_text = t('datasource.got_it')
if (userStore.isAdmin) {
errorMsg = t('model.default_miss_admin')
confirm_text = t('model.to_config')
}
ElMessageBox.confirm(t('qa.ask_failed'), {
confirmButtonType: 'primary',
tip: errorMsg,
showCancelButton: userStore.isAdmin,
confirmButtonText: confirm_text,
cancelButtonText: t('common.cancel'),
customClass: 'confirm-no_icon',
autofocus: false,
showClose: false,
callback: (val: string) => {
if (userStore.isAdmin && val === 'confirm') {
router.push('/system/model')
}
},
})
return
}
router.push({
path: '/chat/index',
query: {