feat: added error handling and knowledge base provider support

This commit is contained in:
kangfenmao 2025-01-02 14:16:37 +08:00
parent 3fc7911c97
commit 6384525e20
9 changed files with 75 additions and 12 deletions

View File

@ -573,6 +573,7 @@
"directory_placeholder": "Enter Directory Path", "directory_placeholder": "Enter Directory Path",
"model_info": "Model Info", "model_info": "Model Info",
"not_support": "Knowledge base database engine updated, the knowledge base will no longer be supported, please create a new knowledge base", "not_support": "Knowledge base database engine updated, the knowledge base will no longer be supported, please create a new knowledge base",
"no_provider": "Knowledge base model provider is not set, the knowledge base will no longer be supported, please create a new knowledge base",
"source": "Source" "source": "Source"
}, },
"models": { "models": {

View File

@ -556,7 +556,11 @@
"sitemap_placeholder": "サイトマップURLを入力", "sitemap_placeholder": "サイトマップURLを入力",
"directories": "ディレクトリ", "directories": "ディレクトリ",
"add_directory": "ディレクトリを追加", "add_directory": "ディレクトリを追加",
"directory_placeholder": "ディレクトリパスを入力" "directory_placeholder": "ディレクトリパスを入力",
"model_info": "モデル情報",
"not_support": "ナレッジベースデータベースエンジンが更新されました。このナレッジベースはもうサポートされていません。新しいナレッジベースを作成してください",
"no_provider": "ナレッジベースモデルプロバイダーが設定されていません。ナレッジベースはもうサポートされていません。新しいナレッジベースを作成してください",
"source": "ソース"
}, },
"models": { "models": {
"pinned": "固定済み", "pinned": "固定済み",

View File

@ -573,6 +573,7 @@
"directory_placeholder": "Введите путь к директории", "directory_placeholder": "Введите путь к директории",
"model_info": "Модель информации", "model_info": "Модель информации",
"not_support": "База знаний базы данных движок обновлен, база знаний больше не поддерживается, пожалуйста, создайте новую базу знаний", "not_support": "База знаний базы данных движок обновлен, база знаний больше не поддерживается, пожалуйста, создайте новую базу знаний",
"no_provider": "База знаний модель поставщика не настроена, база знаний больше не поддерживается, пожалуйста, создайте новую базу знаний",
"source": "Источник" "source": "Источник"
}, },
"models": { "models": {

View File

@ -562,6 +562,7 @@
"directory_placeholder": "请输入目录路径", "directory_placeholder": "请输入目录路径",
"model_info": "模型信息", "model_info": "模型信息",
"not_support": "知识库数据库引擎已更新,该知识库将不再支持,请重新创建知识库", "not_support": "知识库数据库引擎已更新,该知识库将不再支持,请重新创建知识库",
"no_provider": "知识库模型服务商丢失,该知识库将不再支持,请重新创建知识库",
"source": "来源" "source": "来源"
}, },
"models": { "models": {

View File

@ -561,6 +561,7 @@
"directory_placeholder": "請輸入目錄路徑", "directory_placeholder": "請輸入目錄路徑",
"model_info": "模型信息", "model_info": "模型信息",
"not_support": "知識庫數據庫引擎已更新,該知識庫將不再支持,請重新創建知識庫", "not_support": "知識庫數據庫引擎已更新,該知識庫將不再支持,請重新創建知識庫",
"no_provider": "知識庫模型提供商遺失,該知識庫將不再支持,請重新創建知識庫",
"source": "來源" "source": "來源"
}, },
"models": { "models": {

View File

@ -391,6 +391,7 @@ const Container = styled(Scrollbar)`
padding: 0 10px; padding: 0 10px;
padding-right: 5px; padding-right: 5px;
padding-top: 2px; padding-top: 2px;
padding-bottom: 10px;
` `
const Label = styled.p` const Label = styled.p`
@ -410,7 +411,7 @@ const SettingRowTitleSmall = styled(SettingRowTitle)`
` `
export const SettingGroup = styled.div<{ theme?: ThemeMode }>` export const SettingGroup = styled.div<{ theme?: ThemeMode }>`
padding: 10px 5px; padding: 0 5px;
width: 100%; width: 100%;
margin-top: 0; margin-top: 0;
border-radius: 8px; border-radius: 8px;

View File

@ -4,7 +4,7 @@ import SelectModelPopup from '@renderer/components/Popups/SelectModelPopup'
import { isLocalAi } from '@renderer/config/env' import { isLocalAi } from '@renderer/config/env'
import { isVisionModel } from '@renderer/config/models' import { isVisionModel } from '@renderer/config/models'
import { useAssistant } from '@renderer/hooks/useAssistant' import { useAssistant } from '@renderer/hooks/useAssistant'
import { getProviderByModel } from '@renderer/services/AssistantService' import { getProviderName } from '@renderer/services/ProviderService'
import { Assistant } from '@renderer/types' import { Assistant } from '@renderer/types'
import { Button } from 'antd' import { Button } from 'antd'
import { FC } from 'react' import { FC } from 'react'
@ -31,13 +31,14 @@ const SelectModelButton: FC<Props> = ({ assistant }) => {
} }
} }
const providerName = getProviderName(model?.provider)
return ( return (
<DropdownButton size="small" type="default" onClick={onSelectModel}> <DropdownButton size="small" type="default" onClick={onSelectModel}>
<ButtonContent> <ButtonContent>
<ModelAvatar model={model} size={20} /> <ModelAvatar model={model} size={20} />
<ModelName> <ModelName>
{model ? model.name : t('button.select_model')} |{' '} {model ? model.name : t('button.select_model')} {providerName ? '| ' + providerName : ''}
{t(`provider.${model?.provider}`, { defaultValue: getProviderByModel(model)?.name })}
</ModelName> </ModelName>
{isVisionModel(model) && <VisionIcon style={{ marginLeft: 0 }} />} {isVisionModel(model) && <VisionIcon style={{ marginLeft: 0 }} />}
</ButtonContent> </ButtonContent>

View File

@ -13,6 +13,7 @@ import TextEditPopup from '@renderer/components/Popups/TextEditPopup'
import Scrollbar from '@renderer/components/Scrollbar' import Scrollbar from '@renderer/components/Scrollbar'
import { useKnowledge } from '@renderer/hooks/useKnowledge' import { useKnowledge } from '@renderer/hooks/useKnowledge'
import FileManager from '@renderer/services/FileManager' import FileManager from '@renderer/services/FileManager'
import { getProviderName } from '@renderer/services/ProviderService'
import { FileType, FileTypes, KnowledgeBase } from '@renderer/types' import { FileType, FileTypes, KnowledgeBase } from '@renderer/types'
import { Alert, Button, Card, Divider, message, Tag, Typography, Upload } from 'antd' import { Alert, Button, Card, Divider, message, Tag, Typography, Upload } from 'antd'
import { FC } from 'react' import { FC } from 'react'
@ -74,11 +75,17 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
addDirectory addDirectory
} = useKnowledge(selectedBase.id || '') } = useKnowledge(selectedBase.id || '')
const providerName = getProviderName(base?.model.provider || '')
const disabled = !base?.version || !providerName
if (!base) { if (!base) {
return null return null
} }
const handleAddFile = () => { const handleAddFile = () => {
if (disabled) {
return
}
const input = document.createElement('input') const input = document.createElement('input')
input.type = 'file' input.type = 'file'
input.multiple = true input.multiple = true
@ -91,6 +98,10 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
} }
const handleDrop = async (files: File[]) => { const handleDrop = async (files: File[]) => {
if (disabled) {
return
}
if (files) { if (files) {
const _files: FileType[] = files.map((file) => ({ const _files: FileType[] = files.map((file) => ({
id: file.name, id: file.name,
@ -110,6 +121,10 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
} }
const handleAddUrl = async () => { const handleAddUrl = async () => {
if (disabled) {
return
}
const url = await PromptPopup.show({ const url = await PromptPopup.show({
title: t('knowledge_base.add_url'), title: t('knowledge_base.add_url'),
message: '', message: '',
@ -135,6 +150,10 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
} }
const handleAddSitemap = async () => { const handleAddSitemap = async () => {
if (disabled) {
return
}
const url = await PromptPopup.show({ const url = await PromptPopup.show({
title: t('knowledge_base.add_sitemap'), title: t('knowledge_base.add_sitemap'),
message: '', message: '',
@ -160,16 +179,28 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
} }
const handleAddNote = async () => { const handleAddNote = async () => {
if (disabled) {
return
}
const note = await TextEditPopup.show({ text: '', textareaProps: { rows: 20 } }) const note = await TextEditPopup.show({ text: '', textareaProps: { rows: 20 } })
note && addNote(note) note && addNote(note)
} }
const handleEditNote = async (note: any) => { const handleEditNote = async (note: any) => {
if (disabled) {
return
}
const editedText = await TextEditPopup.show({ text: note.content as string, textareaProps: { rows: 20 } }) const editedText = await TextEditPopup.show({ text: note.content as string, textareaProps: { rows: 20 } })
editedText && updateNoteContent(note.id, editedText) editedText && updateNoteContent(note.id, editedText)
} }
const handleAddDirectory = async () => { const handleAddDirectory = async () => {
if (disabled) {
return
}
const path = await window.api.file.selectFolder() const path = await window.api.file.selectFolder()
console.log('[KnowledgeContent] Selected directory:', path) console.log('[KnowledgeContent] Selected directory:', path)
path && addDirectory(path) path && addDirectory(path)
@ -180,10 +211,13 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
{!base?.version && ( {!base?.version && (
<Alert message={t('knowledge_base.not_support')} type="error" style={{ marginBottom: 20 }} showIcon /> <Alert message={t('knowledge_base.not_support')} type="error" style={{ marginBottom: 20 }} showIcon />
)} )}
{!providerName && (
<Alert message={t('knowledge_base.no_provider')} type="error" style={{ marginBottom: 20 }} showIcon />
)}
<FileSection> <FileSection>
<TitleWrapper> <TitleWrapper>
<Title level={5}>{t('files.title')}</Title> <Title level={5}>{t('files.title')}</Title>
<Button icon={<PlusOutlined />} onClick={handleAddFile}> <Button icon={<PlusOutlined />} onClick={handleAddFile} disabled={disabled}>
{t('knowledge_base.add_file')} {t('knowledge_base.add_file')}
</Button> </Button>
</TitleWrapper> </TitleWrapper>
@ -223,7 +257,7 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
<ContentSection> <ContentSection>
<TitleWrapper> <TitleWrapper>
<Title level={5}>{t('knowledge_base.directories')}</Title> <Title level={5}>{t('knowledge_base.directories')}</Title>
<Button icon={<PlusOutlined />} onClick={handleAddDirectory}> <Button icon={<PlusOutlined />} onClick={handleAddDirectory} disabled={disabled}>
{t('knowledge_base.add_directory')} {t('knowledge_base.add_directory')}
</Button> </Button>
</TitleWrapper> </TitleWrapper>
@ -250,7 +284,7 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
<ContentSection> <ContentSection>
<TitleWrapper> <TitleWrapper>
<Title level={5}>{t('knowledge_base.urls')}</Title> <Title level={5}>{t('knowledge_base.urls')}</Title>
<Button icon={<PlusOutlined />} onClick={handleAddUrl}> <Button icon={<PlusOutlined />} onClick={handleAddUrl} disabled={disabled}>
{t('knowledge_base.add_url')} {t('knowledge_base.add_url')}
</Button> </Button>
</TitleWrapper> </TitleWrapper>
@ -277,7 +311,7 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
<ContentSection> <ContentSection>
<TitleWrapper> <TitleWrapper>
<Title level={5}>{t('knowledge_base.sitemaps')}</Title> <Title level={5}>{t('knowledge_base.sitemaps')}</Title>
<Button icon={<PlusOutlined />} onClick={handleAddSitemap}> <Button icon={<PlusOutlined />} onClick={handleAddSitemap} disabled={disabled}>
{t('knowledge_base.add_sitemap')} {t('knowledge_base.add_sitemap')}
</Button> </Button>
</TitleWrapper> </TitleWrapper>
@ -304,7 +338,7 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
<ContentSection> <ContentSection>
<TitleWrapper> <TitleWrapper>
<Title level={5}>{t('knowledge_base.notes')}</Title> <Title level={5}>{t('knowledge_base.notes')}</Title>
<Button icon={<PlusOutlined />} onClick={handleAddNote}> <Button icon={<PlusOutlined />} onClick={handleAddNote} disabled={disabled}>
{t('knowledge_base.add_note')} {t('knowledge_base.add_note')}
</Button> </Button>
</TitleWrapper> </TitleWrapper>
@ -332,11 +366,15 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
<label htmlFor="model-info">{t('knowledge_base.model_info')}</label> <label htmlFor="model-info">{t('knowledge_base.model_info')}</label>
<Tag color="blue">{base.model.name}</Tag> <Tag color="blue">{base.model.name}</Tag>
<Tag color="cyan">{t('models.dimensions', { dimensions: base.dimensions || 0 })}</Tag> <Tag color="cyan">{t('models.dimensions', { dimensions: base.dimensions || 0 })}</Tag>
<Tag color="purple">{base.model.provider}</Tag> {providerName && <Tag color="purple">{providerName}</Tag>}
</ModelInfo> </ModelInfo>
<IndexSection> <IndexSection>
<Button type="primary" onClick={() => KnowledgeSearchPopup.show({ base })} icon={<SearchOutlined />}> <Button
type="primary"
onClick={() => KnowledgeSearchPopup.show({ base })}
icon={<SearchOutlined />}
disabled={disabled}>
{t('knowledge_base.search')} {t('knowledge_base.search')}
</Button> </Button>
</IndexSection> </IndexSection>

View File

@ -0,0 +1,15 @@
import i18n from '@renderer/i18n'
import store from '@renderer/store'
export function getProviderName(id: string) {
const provider = store.getState().llm.providers.find((p) => p.id === id)
if (!provider) {
return ''
}
if (provider.isSystem) {
return i18n.t(`provider.${provider.id}`, { defaultValue: provider.name })
}
return provider?.name
}