fix: show something reasonable when missing embedding model (#8600)

* feat(组件): 在ModelSelector中添加模型删除错误提示和国际化支持

为ModelSelector组件添加了模型被删除时的错误提示,并引入react-i18next实现国际化支持

* feat(i18n): 添加模型删除错误提示和多语言支持

为知识库错误提示添加"model_deleted"多语言字段
移除重复的翻译条目并添加增量文本输出相关翻译

* style(ModelSelector): 修改已删除模型提示文字颜色为错误状态色

* fix(i18n): 更新模型无效的错误提示信息

将错误提示从“模型已被删除”改为“未选择模型或已删除”,以更准确地反映错误情况
This commit is contained in:
Phantom 2025-07-29 00:31:34 +08:00 committed by GitHub
parent 51835e32c5
commit 4e6ac847e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 68 additions and 22 deletions

View File

@ -3,10 +3,11 @@ import { getModelUniqId } from '@renderer/services/ModelService'
import { Model, Provider } from '@renderer/types'
import { matchKeywordsInString } from '@renderer/utils'
import { getFancyProviderName } from '@renderer/utils/naming'
import { Select, SelectProps } from 'antd'
import { Avatar, Select, SelectProps } from 'antd'
import { sortBy } from 'lodash'
import { BaseSelectRef } from 'rc-select'
import { memo, useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
interface ModelOption {
label: React.ReactNode
@ -50,6 +51,8 @@ const ModelSelector = ({
ref,
...props
}: ModelSelectorProps & { ref?: React.Ref<BaseSelectRef> | null }) => {
const { t } = useTranslation()
// 单个 provider 的模型选项
const getModelOptions = useCallback(
(p: Provider, fancyName: string) => {
@ -95,7 +98,33 @@ const ModelSelector = ({
return providers.flatMap((p) => getModelOptions(p, getFancyProviderName(p)))
}, [providers, grouped, getModelOptions])
return <Select ref={ref} options={options} filterOption={modelSelectFilter} showSearch {...props} />
const labelRender = useCallback(
(props) => {
const { label } = props
if (label) {
return label
} else {
return (
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
{showAvatar && <Avatar size={18} />}
<span>{t('knowledge.error.model_invalid')}</span>
</div>
)
}
},
[showAvatar, t]
)
return (
<Select
ref={ref}
options={options}
filterOption={modelSelectFilter}
labelRender={labelRender}
showSearch
{...props}
/>
)
}
export default memo(ModelSelector)

View File

@ -822,7 +822,8 @@
"empty": "No knowledge base found",
"error": {
"failed_to_create": "Knowledge base creation failed",
"failed_to_edit": "Knowledge base editing failed"
"failed_to_edit": "Knowledge base editing failed",
"model_invalid": "No model selected or deleted"
},
"file_hint": "Support {{file_types}}",
"index_all": "Index All",

View File

@ -822,7 +822,8 @@
"empty": "ナレッジベースが見つかりません",
"error": {
"failed_to_create": "ナレッジベースの作成に失敗しました",
"failed_to_edit": "ナレッジベースの編集に失敗しました"
"failed_to_edit": "ナレッジベースの編集に失敗しました",
"model_invalid": "モデルが選択されていないか、削除されています"
},
"file_hint": "{{file_types}} 形式をサポート",
"index_all": "すべてをインデックス",

View File

@ -822,7 +822,8 @@
"empty": "База знаний не найдена",
"error": {
"failed_to_create": "Создание базы знаний завершено с ошибками",
"failed_to_edit": "Редактирование базы знаний завершено с ошибками"
"failed_to_edit": "Редактирование базы знаний завершено с ошибками",
"model_invalid": "Модель не выбрана или удалена"
},
"file_hint": "Поддерживаются {{file_types}}",
"index_all": "Индексировать все",

View File

@ -822,7 +822,8 @@
"empty": "暂无知识库",
"error": {
"failed_to_create": "知识库创建失败",
"failed_to_edit": "知识库编辑失败"
"failed_to_edit": "知识库编辑失败",
"model_invalid": "未选择模型或已删除"
},
"file_hint": "支持 {{file_types}} 格式",
"index_all": "索引全部",

View File

@ -822,7 +822,8 @@
"empty": "暫無知識庫",
"error": {
"failed_to_create": "知識庫創建失敗",
"failed_to_edit": "知識庫編輯失敗"
"failed_to_edit": "知識庫編輯失敗",
"model_invalid": "未選擇模型或已刪除"
},
"file_hint": "支援 {{file_types}} 格式",
"index_all": "索引全部",

View File

@ -822,7 +822,8 @@
"empty": "Λεηλασία βάσης γνώσεων",
"error": {
"failed_to_create": "Αποτυχία δημιουργίας βάσης γνώσεων",
"failed_to_edit": "Αποτυχία επεξεργασίας βάσης γνώσεων"
"failed_to_edit": "Αποτυχία επεξεργασίας βάσης γνώσεων",
"model_invalid": "Δεν έχει επιλεγεί μοντέλο ή έχει διαγραφεί"
},
"file_hint": "Υποστηρίζεται το {{file_types}} μορφάττων",
"index_all": "Ευρετήριοποίηση όλων",
@ -2887,6 +2888,10 @@
"label": "Όνομα μοντέλου",
"placeholder": "Για παράδειγμα GPT-3.5",
"tooltip": "Για παράδειγμα GPT-4"
},
"supported_text_delta": {
"label": "αυξητική έξοδος κειμένου",
"tooltip": "Όταν το μοντέλο δεν υποστηρίζεται, απενεργοποιήστε αυτό το κουμπί"
}
},
"api_key": "Κλειδί API",
@ -2924,7 +2929,6 @@
"label": "Προσθήκη μοντέλων από τη λίστα"
},
"add_whole_group": "Προσθήκη ολόκληρης ομάδας",
"models.manage.add_listed.confirm": "Θέλετε να προσθέσετε όλα τα μοντέλα στη λίστα;",
"remove_listed": "Αφαίρεση μοντέλων από τη λίστα",
"remove_model": "Αφαίρεση Μοντέλου",
"remove_whole_group": "Αφαίρεση ολόκληρης ομάδας"
@ -3038,7 +3042,6 @@
"basic_auth": {
"label": "Πιστοποίηση HTTP",
"password": {
"basic_auth.password.tip": ":",
"label": "κωδικός πρόσβασης",
"tip": "εισαγάγετε τον κωδικό πρόσβασης"
},

View File

@ -822,7 +822,8 @@
"empty": "Sin bases de conocimientos",
"error": {
"failed_to_create": "Error al crear la base de conocimientos",
"failed_to_edit": "Error al editar la base de conocimientos"
"failed_to_edit": "Error al editar la base de conocimientos",
"model_invalid": "No se ha seleccionado un modelo o ha sido eliminado"
},
"file_hint": "Formatos soportados: {{file_types}}",
"index_all": "Indexar todo",
@ -2887,6 +2888,10 @@
"label": "Nombre del modelo",
"placeholder": "Por ejemplo, GPT-3.5",
"tooltip": "Por ejemplo, GPT-4"
},
"supported_text_delta": {
"label": "salida de texto incremental",
"tooltip": "Cuando el modelo no lo admita, desactive este botón"
}
},
"api_key": "Clave API",
@ -2921,8 +2926,7 @@
"manage": {
"add_listed": {
"confirm": "¿Está seguro de que desea agregar todos los modelos a la lista?",
"label": "Agregar modelo en la lista",
"models.manage.add_listed.confirm": "¿Desea agregar todos los modelos a la lista?"
"label": "Agregar modelo en la lista"
},
"add_whole_group": "Agregar todo el grupo",
"remove_listed": "Eliminar modelo de la lista",
@ -3038,7 +3042,6 @@
"basic_auth": {
"label": "Autenticación HTTP",
"password": {
"basic_auth.password.tip": "",
"label": "contraseña",
"tip": "Introduzca la contraseña"
},

View File

@ -822,7 +822,8 @@
"empty": "Aucune base de connaissances pour le moment",
"error": {
"failed_to_create": "Erreur lors de la création de la base de connaissances",
"failed_to_edit": "Erreur lors de la modification de la base de connaissances"
"failed_to_edit": "Erreur lors de la modification de la base de connaissances",
"model_invalid": "Aucun modèle sélectionné ou modèle supprimé"
},
"file_hint": "Format supporté : {{file_types}}",
"index_all": "Indexer tout",
@ -2887,6 +2888,10 @@
"label": "Nom du modèle",
"placeholder": "Par exemple, GPT-3.5",
"tooltip": "Par exemple GPT-4"
},
"supported_text_delta": {
"label": "sortie de texte incrémentielle",
"tooltip": "Lorsque le modèle n'est pas pris en charge, désactivez ce bouton"
}
},
"api_key": "Clé API",
@ -2921,8 +2926,7 @@
"manage": {
"add_listed": {
"confirm": "Êtes-vous sûr de vouloir ajouter tous les modèles à la liste ?",
"label": "Ajouter le modèle dans la liste",
"models.manage.add_listed.confirm": "Voulez-vous ajouter tous les modèles à la liste ?"
"label": "Ajouter le modèle dans la liste"
},
"add_whole_group": "Ajouter tout le groupe",
"remove_listed": "Supprimer un modèle de la liste",
@ -3038,7 +3042,6 @@
"basic_auth": {
"label": "Authentification HTTP",
"password": {
"basic_auth.password.tip": "",
"label": "mot de passe",
"tip": "Entrer le mot de passe"
},

View File

@ -822,7 +822,8 @@
"empty": "Sem repositório de conhecimento",
"error": {
"failed_to_create": "Falha ao criar o repositório de conhecimento",
"failed_to_edit": "Falha ao editar o repositório de conhecimento"
"failed_to_edit": "Falha ao editar o repositório de conhecimento",
"model_invalid": "Modelo não selecionado ou eliminado"
},
"file_hint": "Formatos suportados: {{file_types}}",
"index_all": "Índice total",
@ -2887,6 +2888,10 @@
"label": "Nome do modelo",
"placeholder": "Exemplo: GPT-3.5",
"tooltip": "Por exemplo, GPT-4"
},
"supported_text_delta": {
"label": "saída de texto incremental",
"tooltip": "Quando o modelo não for suportado, desative este botão"
}
},
"api_key": "Chave API",
@ -2921,8 +2926,7 @@
"manage": {
"add_listed": {
"confirm": "Tem a certeza de que deseja adicionar todos os modelos à lista?",
"label": "Adicionar modelo da lista",
"models.manage.add_listed.confirm": "Deseja adicionar todos os modelos à lista?"
"label": "Adicionar modelo da lista"
},
"add_whole_group": "Adicionar todo o grupo",
"remove_listed": "Remover modelo da lista",
@ -3038,7 +3042,6 @@
"basic_auth": {
"label": "Autenticação HTTP",
"password": {
"basic_auth.password.tip": "",
"label": "palavra-passe",
"tip": "Introduza a palavra-passe"
},