diff --git a/deploy/docker/docker-compose-pgvector.yml b/deploy/docker/docker-compose-pgvector.yml index ec4f35817..9b034a7ab 100644 --- a/deploy/docker/docker-compose-pgvector.yml +++ b/deploy/docker/docker-compose-pgvector.yml @@ -7,8 +7,8 @@ version: '3.3' services: # db pg: - image: pgvector/pgvector:0.7.0-pg15 # docker hub - # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/pgvector:v0.7.0 # 阿里云 + image: pgvector/pgvector:0.8.0-pg15 # docker hub + # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/pgvector:v0.8.0-pg15 # 阿里云 container_name: pg restart: always ports: # 生产环境建议不要暴露 diff --git a/docSite/content/zh-cn/docs/development/openapi/dataset.md b/docSite/content/zh-cn/docs/development/openapi/dataset.md index c32889683..d41cc080e 100644 --- a/docSite/content/zh-cn/docs/development/openapi/dataset.md +++ b/docSite/content/zh-cn/docs/development/openapi/dataset.md @@ -298,6 +298,8 @@ curl --location --request DELETE 'http://localhost:3000/api/core/dataset/delete? | datasetId | 知识库ID | ✅ | | parentId: | 父级ID,不填则默认为根目录 | | | trainingType | 数据处理方式。chunk: 按文本长度进行分割;qa: 问答对提取 | ✅ | +| autoIndexes | 是否自动生成索引(仅商业版支持) | | +| imageIndex | 是否自动生成图片索引(仅商业版支持) | | | chunkSize | 预估块大小 | | | chunkSplitter | 自定义最高优先分割符号 | | | qaPrompt | qa拆分提示词 | | diff --git a/docSite/content/zh-cn/docs/development/upgrading/490.md b/docSite/content/zh-cn/docs/development/upgrading/490.md index cabcc87a1..9992676f3 100644 --- a/docSite/content/zh-cn/docs/development/upgrading/490.md +++ b/docSite/content/zh-cn/docs/development/upgrading/490.md @@ -19,6 +19,7 @@ weight: 803 1. PDF增强解析交互添加到页面上。同时内嵌 Doc2x 服务,可直接使用 Doc2x 服务解析 PDF 文件。 2. 图片自动标注,同时修改知识库文件上传部分数据逻辑和交互。 +3. pg vector 插件升级 0.8.0 版本,引入迭代搜索,减少部分数据无法被检索的情况。 ## ⚙️ 优化 diff --git a/packages/global/core/app/type.d.ts b/packages/global/core/app/type.d.ts index 52b6964fb..1a0a53b85 100644 --- a/packages/global/core/app/type.d.ts +++ b/packages/global/core/app/type.d.ts @@ -188,6 +188,7 @@ export type AppAutoExecuteConfigType = { // File export type AppFileSelectConfigType = { canSelectFile: boolean; + customPdfParse?: boolean; canSelectImg: boolean; maxFiles: number; }; diff --git a/packages/service/common/vectorStore/pg/class.ts b/packages/service/common/vectorStore/pg/class.ts index ba08adf43..6b7f42bd3 100644 --- a/packages/service/common/vectorStore/pg/class.ts +++ b/packages/service/common/vectorStore/pg/class.ts @@ -164,34 +164,22 @@ export class PgVectorCtrl { } try { - // const explan: any = await PgClient.query( - // `BEGIN; - // SET LOCAL hnsw.ef_search = ${global.systemEnv?.pgHNSWEfSearch || 100}; - // EXPLAIN ANALYZE select id, collection_id, vector <#> '[${vector}]' AS score - // from ${DatasetVectorTableName} - // where team_id='${teamId}' - // AND dataset_id IN (${datasetIds.map((id) => `'${String(id)}'`).join(',')}) - // ${forbidCollectionSql} - // order by score limit ${limit}; - // COMMIT;` - // ); - // console.log(explan[2].rows); - const results: any = await PgClient.query( - ` - BEGIN; + `BEGIN; SET LOCAL hnsw.ef_search = ${global.systemEnv?.pgHNSWEfSearch || 100}; - select id, collection_id, vector <#> '[${vector}]' AS score - from ${DatasetVectorTableName} - where team_id='${teamId}' - AND dataset_id IN (${datasetIds.map((id) => `'${String(id)}'`).join(',')}) - ${filterCollectionIdSql} - ${forbidCollectionSql} - order by score limit ${limit}; + SET LOCAL hnsw.iterative_scan = relaxed_order; + WITH relaxed_results AS MATERIALIZED ( + select id, collection_id, vector <#> '[${vector}]' AS score + from ${DatasetVectorTableName} + where team_id='${teamId}' + AND dataset_id IN (${datasetIds.map((id) => `'${String(id)}'`).join(',')}) + ${filterCollectionIdSql} + ${forbidCollectionSql} + order by score limit ${limit} + ) SELECT id, collection_id, score FROM relaxed_results ORDER BY score; COMMIT;` ); - - const rows = results?.[2]?.rows as PgSearchRawType[]; + const rows = results?.[3]?.rows as PgSearchRawType[]; return { results: rows.map((item) => ({ diff --git a/packages/service/core/ai/config/utils.ts b/packages/service/core/ai/config/utils.ts index c64ea2c57..86c3786df 100644 --- a/packages/service/core/ai/config/utils.ts +++ b/packages/service/core/ai/config/utils.ts @@ -163,6 +163,13 @@ export const loadSystemModels = async (init = false) => { global.systemDefaultModel.rerank = Array.from(global.reRankModelMap.values())[0]; } + // Sort model list + global.systemActiveModelList.sort((a, b) => { + const providerA = getModelProvider(a.provider); + const providerB = getModelProvider(b.provider); + return providerA.order - providerB.order; + }); + console.log('Load models success', JSON.stringify(global.systemActiveModelList, null, 2)); } catch (error) { console.error('Load models error', error); diff --git a/packages/service/core/dataset/data/schema.ts b/packages/service/core/dataset/data/schema.ts index 6bec731e5..bdba3b87c 100644 --- a/packages/service/core/dataset/data/schema.ts +++ b/packages/service/core/dataset/data/schema.ts @@ -45,8 +45,7 @@ const DatasetDataSchema = new Schema({ { // Abandon defaultIndex: { - type: Boolean, - default: false + type: Boolean }, type: { type: String, diff --git a/packages/service/core/dataset/training/controller.ts b/packages/service/core/dataset/training/controller.ts index 013f62c95..d740eec55 100644 --- a/packages/service/core/dataset/training/controller.ts +++ b/packages/service/core/dataset/training/controller.ts @@ -11,6 +11,7 @@ import { addLog } from '../../../common/system/log'; import { getCollectionWithDataset } from '../controller'; import { mongoSessionRun } from '../../../common/mongo/sessionRun'; import { PushDataToTrainingQueueProps } from '@fastgpt/global/core/dataset/training/type'; +import { i18nT } from '../../../../web/i18n/utils'; export const lockTrainingDataByTeamId = async (teamId: string): Promise => { try { @@ -71,7 +72,7 @@ export async function pushDataListToTrainingQueue({ if (mode === TrainingModeEnum.chunk) { const vectorModelData = getEmbeddingModel(vectorModel); if (!vectorModelData) { - return Promise.reject(`Vector model ${vectorModel} is inValid`); + return Promise.reject(i18nT('common:error_embedding_not_config')); } return { maxToken: vectorModelData.maxToken * 1.5, @@ -83,7 +84,7 @@ export async function pushDataListToTrainingQueue({ if (mode === TrainingModeEnum.qa || mode === TrainingModeEnum.auto) { const agentModelData = getLLMModel(agentModel); if (!agentModelData) { - return Promise.reject(`File model ${agentModel} is inValid`); + return Promise.reject(i18nT('common:error_llm_not_config')); } return { maxToken: agentModelData.maxContext * 0.8, @@ -95,7 +96,7 @@ export async function pushDataListToTrainingQueue({ if (mode === TrainingModeEnum.image) { const vllmModelData = getVlmModel(vlmModel); if (!vllmModelData) { - return Promise.reject(`Vlm model ${vlmModel} is inValid`); + return Promise.reject(i18nT('common:error_vlm_not_config')); } return { maxToken: vllmModelData.maxContext * 0.8, diff --git a/packages/service/core/workflow/dispatch/agent/runTool/index.ts b/packages/service/core/workflow/dispatch/agent/runTool/index.ts index 9d3dd8ec8..d0f99583f 100644 --- a/packages/service/core/workflow/dispatch/agent/runTool/index.ts +++ b/packages/service/core/workflow/dispatch/agent/runTool/index.ts @@ -104,6 +104,7 @@ export const dispatchRunTools = async (props: DispatchToolModuleProps): Promise< histories: chatHistories, requestOrigin, maxFiles: chatConfig?.fileSelectConfig?.maxFiles || 20, + customPdfParse: chatConfig?.fileSelectConfig?.customPdfParse, fileLinks, inputFiles: globalFiles, hasReadFilesTool @@ -295,6 +296,7 @@ const getMultiInput = async ({ fileLinks, requestOrigin, maxFiles, + customPdfParse, inputFiles, hasReadFilesTool }: { @@ -303,6 +305,7 @@ const getMultiInput = async ({ fileLinks?: string[]; requestOrigin?: string; maxFiles: number; + customPdfParse?: boolean; inputFiles: UserChatItemValueItemType['file'][]; hasReadFilesTool: boolean; }) => { @@ -330,6 +333,7 @@ const getMultiInput = async ({ urls, requestOrigin, maxFiles, + customPdfParse, teamId: runningUserInfo.teamId, tmbId: runningUserInfo.tmbId }); diff --git a/packages/service/core/workflow/dispatch/chat/oneapi.ts b/packages/service/core/workflow/dispatch/chat/oneapi.ts index 25a8cd724..41df8e31d 100644 --- a/packages/service/core/workflow/dispatch/chat/oneapi.ts +++ b/packages/service/core/workflow/dispatch/chat/oneapi.ts @@ -124,6 +124,7 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise @@ -403,6 +406,7 @@ async function getMultiInput({ urls, requestOrigin, maxFiles, + customPdfParse, teamId: runningUserInfo.teamId, tmbId: runningUserInfo.tmbId }); diff --git a/packages/service/core/workflow/dispatch/tools/readFiles.ts b/packages/service/core/workflow/dispatch/tools/readFiles.ts index 369d0dbd9..f4593c375 100644 --- a/packages/service/core/workflow/dispatch/tools/readFiles.ts +++ b/packages/service/core/workflow/dispatch/tools/readFiles.ts @@ -52,6 +52,7 @@ export const dispatchReadFiles = async (props: Props): Promise => { params: { fileUrlList = [] } } = props; const maxFiles = chatConfig?.fileSelectConfig?.maxFiles || 20; + const customPdfParse = chatConfig?.fileSelectConfig?.customPdfParse || false; // Get files from histories const filesFromHistories = version !== '489' ? [] : getHistoryFileLinks(histories); @@ -62,7 +63,8 @@ export const dispatchReadFiles = async (props: Props): Promise => { requestOrigin, maxFiles, teamId, - tmbId + tmbId, + customPdfParse }); return { @@ -107,13 +109,15 @@ export const getFileContentFromLinks = async ({ requestOrigin, maxFiles, teamId, - tmbId + tmbId, + customPdfParse }: { urls: string[]; requestOrigin?: string; maxFiles: number; teamId: string; tmbId: string; + customPdfParse?: boolean; }) => { const parseUrlList = urls // Remove invalid urls @@ -210,7 +214,8 @@ export const getFileContentFromLinks = async ({ teamId, tmbId, buffer, - encoding + encoding, + customPdfParse }); // Add to buffer diff --git a/packages/web/i18n/en/account_model.json b/packages/web/i18n/en/account_model.json index dcf4a7866..d409b97fd 100644 --- a/packages/web/i18n/en/account_model.json +++ b/packages/web/i18n/en/account_model.json @@ -43,5 +43,7 @@ "selected_model_empty": "Choose at least one model", "start_test": "Start testing {{num}} models", "test_failed": "There are {{num}} models that report errors", + "vlm_model": "Vlm", + "vlm_model_tip": "Used to generate additional indexing of images in a document in the knowledge base", "waiting_test": "Waiting for testing" } diff --git a/packages/web/i18n/en/app.json b/packages/web/i18n/en/app.json index 0295f3f94..cc0bc8f46 100644 --- a/packages/web/i18n/en/app.json +++ b/packages/web/i18n/en/app.json @@ -105,6 +105,9 @@ "open_vision_function_tip": "Models with icon switches have image recognition capabilities. \nAfter being turned on, the model will parse the pictures in the file link and automatically parse the pictures in the user's question (user question ≤ 500 words).", "or_drag_JSON": "or drag in JSON file", "paste_config_or_drag": "Paste config or drag JSON file here", + "pdf_enhance_parse": "PDF enhancement analysis", + "pdf_enhance_parse_price": "{{price}}Points/page", + "pdf_enhance_parse_tips": "Calling PDF recognition model for parsing, you can convert it into Markdown and retain pictures in the document. At the same time, you can also identify scanned documents, which will take a long time to identify them.", "permission.des.manage": "Based on write permissions, you can configure publishing channels, view conversation logs, and assign permissions to the application.", "permission.des.read": "Use the app to have conversations", "permission.des.write": "Can view and edit apps", diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json index 342996bd6..d71060c08 100644 --- a/packages/web/i18n/en/common.json +++ b/packages/web/i18n/en/common.json @@ -883,6 +883,9 @@ "error.upload_image_error": "File upload failed", "error.username_empty": "Account cannot be empty", "error_collection_not_exist": "The collection does not exist", + "error_embedding_not_config": "Unconfigured index model", + "error_llm_not_config": "Unconfigured file understanding model", + "error_vlm_not_config": "Image comprehension model not configured", "extraction_results": "Extraction Results", "field_name": "Field Name", "free": "Free", diff --git a/packages/web/i18n/en/dataset.json b/packages/web/i18n/en/dataset.json index 7c5491589..0902a421e 100644 --- a/packages/web/i18n/en/dataset.json +++ b/packages/web/i18n/en/dataset.json @@ -76,7 +76,7 @@ "params_setting": "Parameter settings", "pdf_enhance_parse": "PDF enhancement analysis", "pdf_enhance_parse_price": "{{price}} points/page", - "pdf_enhance_parse_tips": "When parsing a PDF file, the PDF recognition model is called for recognition, which can be converted into Markdown and retained the pictures in the document, and can also identify the scanned files.", + "pdf_enhance_parse_tips": "Calling PDF recognition model for parsing, you can convert it into Markdown and retain pictures in the document. At the same time, you can also identify scanned documents, which will take a long time to identify them.", "permission.des.manage": "Can manage the entire knowledge base data and information", "permission.des.read": "View knowledge base content", "permission.des.write": "Ability to add and change knowledge base content", diff --git a/packages/web/i18n/zh-CN/account_model.json b/packages/web/i18n/zh-CN/account_model.json index 89550d17b..73c3fced9 100644 --- a/packages/web/i18n/zh-CN/account_model.json +++ b/packages/web/i18n/zh-CN/account_model.json @@ -43,5 +43,7 @@ "selected_model_empty": "至少选择一个模型", "start_test": "开始测试{{num}}个模型", "test_failed": "有{{num}}个模型报错", + "vlm_model": "图片理解模型", + "vlm_model_tip": "用于知识库中对文档中的图片进行额外的索引生成", "waiting_test": "等待测试" } diff --git a/packages/web/i18n/zh-CN/app.json b/packages/web/i18n/zh-CN/app.json index e76d5901f..75232c3d2 100644 --- a/packages/web/i18n/zh-CN/app.json +++ b/packages/web/i18n/zh-CN/app.json @@ -105,6 +105,9 @@ "open_vision_function_tip": "有图示开关的模型即拥有图片识别能力。若开启,模型会解析文件链接里的图片,并自动解析用户问题中的图片(用户问题≤500字时生效)。", "or_drag_JSON": "或拖入JSON文件", "paste_config_or_drag": "粘贴配置或拖入 JSON 文件", + "pdf_enhance_parse": "PDF增强解析", + "pdf_enhance_parse_price": "{{price}}积分/页", + "pdf_enhance_parse_tips": "调用 PDF 识别模型进行解析,可以将其转换成 Markdown 并保留文档中的图片,同时也可以对扫描件进行识别,识别时间较长。", "permission.des.manage": "写权限基础上,可配置发布渠道、查看对话日志、分配该应用权限", "permission.des.read": "可使用该应用进行对话", "permission.des.write": "可查看和编辑应用", diff --git a/packages/web/i18n/zh-CN/common.json b/packages/web/i18n/zh-CN/common.json index a5dac2608..3279be401 100644 --- a/packages/web/i18n/zh-CN/common.json +++ b/packages/web/i18n/zh-CN/common.json @@ -886,6 +886,9 @@ "error.upload_image_error": "上传文件失败", "error.username_empty": "账号不能为空", "error_collection_not_exist": "集合不存在", + "error_embedding_not_config": "未配置索引模型", + "error_llm_not_config": "未配置文件理解模型", + "error_vlm_not_config": "未配置图片理解模型", "extraction_results": "提取结果", "field_name": "字段名", "free": "免费", diff --git a/packages/web/i18n/zh-CN/dataset.json b/packages/web/i18n/zh-CN/dataset.json index 8c7d8ed59..2dc1cc54c 100644 --- a/packages/web/i18n/zh-CN/dataset.json +++ b/packages/web/i18n/zh-CN/dataset.json @@ -76,7 +76,7 @@ "params_setting": "参数设置", "pdf_enhance_parse": "PDF增强解析", "pdf_enhance_parse_price": "{{price}}积分/页", - "pdf_enhance_parse_tips": "解析 PDF 文件时,调用 PDF 识别模型进行识别,可以将其转换成 Markdown 并保留文档中的图片,同时也可以对扫描件进行识别。", + "pdf_enhance_parse_tips": "调用 PDF 识别模型进行解析,可以将其转换成 Markdown 并保留文档中的图片,同时也可以对扫描件进行识别,识别时间较长。", "permission.des.manage": "可管理整个知识库数据和信息", "permission.des.read": "可查看知识库内容", "permission.des.write": "可增加和变更知识库内容", diff --git a/packages/web/i18n/zh-Hant/account_model.json b/packages/web/i18n/zh-Hant/account_model.json index 20b56ca6a..b62b937d6 100644 --- a/packages/web/i18n/zh-Hant/account_model.json +++ b/packages/web/i18n/zh-Hant/account_model.json @@ -41,5 +41,7 @@ "selected_model_empty": "至少選擇一個模型", "start_test": "開始測試{{num}}個模型", "test_failed": "有{{num}}個模型報錯", + "vlm_model": "圖片理解模型", + "vlm_model_tip": "用於知識庫中對文檔中的圖片進行額外的索引生成", "waiting_test": "等待測試" } diff --git a/packages/web/i18n/zh-Hant/app.json b/packages/web/i18n/zh-Hant/app.json index 8173ff642..dfa6bfc7d 100644 --- a/packages/web/i18n/zh-Hant/app.json +++ b/packages/web/i18n/zh-Hant/app.json @@ -105,6 +105,9 @@ "open_vision_function_tip": "有圖示開關的模型即擁有圖片辨識功能。若開啟,模型會解析檔案連結中的圖片,並自動解析使用者問題中的圖片(使用者問題 ≤ 500 字時生效)。", "or_drag_JSON": "或拖曳 JSON 檔案", "paste_config_or_drag": "貼上配置或拖入 JSON 文件", + "pdf_enhance_parse": "PDF增強解析", + "pdf_enhance_parse_price": "{{price}}積分/頁", + "pdf_enhance_parse_tips": "調用 PDF 識別模型進行解析,可以將其轉換成 Markdown 並保留文檔中的圖片,同時也可以對掃描件進行識別,識別時間較長。", "permission.des.manage": "在寫入權限基礎上,可以設定發布通道、檢視對話紀錄、分配這個應用程式的權限", "permission.des.read": "可以使用這個應用程式進行對話", "permission.des.write": "可以檢視和編輯應用程式", diff --git a/packages/web/i18n/zh-Hant/common.json b/packages/web/i18n/zh-Hant/common.json index d8ab0c424..e3fd6e908 100644 --- a/packages/web/i18n/zh-Hant/common.json +++ b/packages/web/i18n/zh-Hant/common.json @@ -883,6 +883,9 @@ "error.upload_image_error": "上傳文件失敗", "error.username_empty": "帳號不能為空", "error_collection_not_exist": "集合不存在", + "error_embedding_not_config": "未配置索引模型", + "error_llm_not_config": "未配置文件理解模型", + "error_vlm_not_config": "未配置圖片理解模型", "extraction_results": "提取結果", "field_name": "欄位名稱", "free": "免費", diff --git a/packages/web/i18n/zh-Hant/dataset.json b/packages/web/i18n/zh-Hant/dataset.json index 4175c459c..7eab0f080 100644 --- a/packages/web/i18n/zh-Hant/dataset.json +++ b/packages/web/i18n/zh-Hant/dataset.json @@ -76,7 +76,7 @@ "params_setting": "參數設置", "pdf_enhance_parse": "PDF增強解析", "pdf_enhance_parse_price": "{{price}}積分/頁", - "pdf_enhance_parse_tips": "解析 PDF 文件時,調用 PDF 識別模型進行識別,可以將其轉換成 Markdown 並保留文檔中的圖片,同時也可以對掃描件進行識別。", + "pdf_enhance_parse_tips": "調用 PDF 識別模型進行解析,可以將其轉換成 Markdown 並保留文檔中的圖片,同時也可以對掃描件進行識別,識別時間較長。", "permission.des.manage": "可管理整個資料集的資料和資訊", "permission.des.read": "可檢視資料集內容", "permission.des.write": "可新增和變更資料集內容", diff --git a/projects/app/package.json b/projects/app/package.json index 5f088e1d3..3762a2bae 100644 --- a/projects/app/package.json +++ b/projects/app/package.json @@ -1,6 +1,6 @@ { "name": "app", - "version": "4.8.23", + "version": "4.9.0", "private": false, "scripts": { "dev": "next dev", diff --git a/projects/app/src/components/Layout/index.tsx b/projects/app/src/components/Layout/index.tsx index 9d53d3da0..2ece77c27 100644 --- a/projects/app/src/components/Layout/index.tsx +++ b/projects/app/src/components/Layout/index.tsx @@ -51,13 +51,13 @@ export const navbarWidth = '64px'; const Layout = ({ children }: { children: JSX.Element }) => { const router = useRouter(); + const { toast } = useToast(); const { t } = useTranslation(); const { Loading } = useLoading(); const { loading, feConfigs, notSufficientModalType, llmModelList, embeddingModelList } = useSystemStore(); const { isPc } = useSystem(); - const { userInfo, teamPlanStatus, isUpdateNotification, setIsUpdateNotification } = - useUserStore(); + const { userInfo, isUpdateNotification, setIsUpdateNotification } = useUserStore(); const { setUserDefaultLng } = useI18nLng(); const isChatPage = useMemo( @@ -87,7 +87,6 @@ const Layout = ({ children }: { children: JSX.Element }) => { }); // Check model invalid - const { toast } = useToast(); useDebounceEffect( () => { if (userInfo?.username === 'root') { diff --git a/projects/app/src/components/Select/AIModelSelector.tsx b/projects/app/src/components/Select/AIModelSelector.tsx index 4fdcaa748..3a760e44a 100644 --- a/projects/app/src/components/Select/AIModelSelector.tsx +++ b/projects/app/src/components/Select/AIModelSelector.tsx @@ -110,7 +110,7 @@ const OneRowSelector = ({ list, onchange, disableTip, ...props }: Props) => { ); }; -const MultipleRowSelector = ({ list, onchange, disableTip, ...props }: Props) => { +const MultipleRowSelector = ({ list, onchange, disableTip, placeholder, ...props }: Props) => { const { t } = useTranslation(); const { llmModelList, embeddingModelList, ttsModelList, sttModelList, reRankModelList } = useSystemStore(); @@ -124,7 +124,7 @@ const MultipleRowSelector = ({ list, onchange, disableTip, ...props }: Props) => ]; return list.map((item) => getModelFromList(allModels, item.value)!).filter(Boolean); - }, [llmModelList, embeddingModelList, ttsModelList, sttModelList, reRankModelList]); + }, [llmModelList, embeddingModelList, ttsModelList, sttModelList, reRankModelList, list]); const [value, setValue] = useState([]); @@ -174,7 +174,7 @@ const MultipleRowSelector = ({ list, onchange, disableTip, ...props }: Props) => } return renderList.filter((item) => item.children.length > 0); - }, [avatarSize, list, modelList]); + }, [avatarSize, list, modelList, t]); const onSelect = useCallback( (e: string[]) => { @@ -184,7 +184,9 @@ const MultipleRowSelector = ({ list, onchange, disableTip, ...props }: Props) => ); const SelectedModel = useMemo(() => { + if (!props.value) return <>{t('common:not_model_config')}; const modelData = getModelFromList(modelList, props.value); + if (!modelData) return <>{t('common:not_model_config')}; setValue([modelData.provider, props.value]); @@ -201,7 +203,7 @@ const MultipleRowSelector = ({ list, onchange, disableTip, ...props }: Props) => {modelData?.name} ); - }, [modelList, props.value, avatarSize]); + }, [modelList, props.value, t, avatarSize]); return ( list={selectorList} onSelect={onSelect} value={value} + placeholder={placeholder} rowMinWidth="160px" ButtonProps={{ isDisabled: !!disableTip, diff --git a/projects/app/src/components/core/app/FileSelect.tsx b/projects/app/src/components/core/app/FileSelect.tsx index 7f7361d9c..f1e3879bc 100644 --- a/projects/app/src/components/core/app/FileSelect.tsx +++ b/projects/app/src/components/core/app/FileSelect.tsx @@ -9,7 +9,8 @@ import { HStack, Switch, ModalFooter, - BoxProps + BoxProps, + Checkbox } from '@chakra-ui/react'; import React, { useMemo } from 'react'; import { useTranslation } from 'next-i18next'; @@ -22,6 +23,8 @@ import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel'; import { useMount } from 'ahooks'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; +import MyTag from '@fastgpt/web/components/common/Tag/index'; +import MyDivider from '@fastgpt/web/components/common/MyDivider'; const FileSelect = ({ forbidVision = false, @@ -95,6 +98,42 @@ const FileSelect = ({ }} /> + {value.canSelectFile && feConfigs.showCustomPdfParse && ( + <> + + { + onChange({ + ...value, + customPdfParse: e.target.checked + }); + }} + > + {t('app:pdf_enhance_parse')} + + + {feConfigs?.show_pay && ( + + {t('app:pdf_enhance_parse_price', { + price: feConfigs.customPdfParsePrice || 0 + })} + + )} + + + + )} {t('app:image_upload')} {forbidVision ? ( diff --git a/projects/app/src/pageComponents/account/model/ModelConfigTable.tsx b/projects/app/src/pageComponents/account/model/ModelConfigTable.tsx index c2a59a829..7bf61393e 100644 --- a/projects/app/src/pageComponents/account/model/ModelConfigTable.tsx +++ b/projects/app/src/pageComponents/account/model/ModelConfigTable.tsx @@ -563,8 +563,10 @@ const DefaultModelModal = ({ embeddingModelList, ttsModelList, sttModelList, - reRankModelList + reRankModelList, + getVlmModelList } = useSystemStore(); + const vlmModelList = useMemo(() => getVlmModelList(), [getVlmModelList]); // Create a copy of defaultModels for local state management const [defaultData, setDefaultData] = useState(defaultModels); @@ -703,6 +705,28 @@ const DefaultModelModal = ({ /> + + + {t('account_model:vlm_model')} + + + + ({ + value: item.model, + label: item.name + }))} + onchange={(e) => { + setDefaultData((state) => ({ + ...state, + datasetImageLLM: vlmModelList.find((item) => item.model === e) + })); + }} + /> + +