From b7a60e56c4cd395b9ccdd4ec71d176a490665dbb Mon Sep 17 00:00:00 2001
From: archer <545436317@qq.com>
Date: Fri, 7 Mar 2025 11:12:49 +0800
Subject: [PATCH 1/5] perf: pg config params
---
.../service/common/vectorStore/pg/class.ts | 21 +++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/packages/service/common/vectorStore/pg/class.ts b/packages/service/common/vectorStore/pg/class.ts
index 6b7f42bd3ff7..26db89074c16 100644
--- a/packages/service/common/vectorStore/pg/class.ts
+++ b/packages/service/common/vectorStore/pg/class.ts
@@ -38,6 +38,27 @@ export class PgVectorCtrl {
await PgClient.query(
`CREATE INDEX CONCURRENTLY IF NOT EXISTS create_time_index ON ${DatasetVectorTableName} USING btree(createtime);`
);
+ // 10w rows
+ // await PgClient.query(`
+ // ALTER TABLE modeldata SET (
+ // autovacuum_vacuum_scale_factor = 0.1,
+ // autovacuum_analyze_scale_factor = 0.05,
+ // autovacuum_vacuum_threshold = 50,
+ // autovacuum_analyze_threshold = 50,
+ // autovacuum_vacuum_cost_delay = 20,
+ // autovacuum_vacuum_cost_limit = 200
+ // );`);
+
+ // 100w rows
+ // await PgClient.query(`
+ // ALTER TABLE modeldata SET (
+ // autovacuum_vacuum_scale_factor = 0.01,
+ // autovacuum_analyze_scale_factor = 0.02,
+ // autovacuum_vacuum_threshold = 1000,
+ // autovacuum_analyze_threshold = 1000,
+ // autovacuum_vacuum_cost_delay = 10,
+ // autovacuum_vacuum_cost_limit = 2000
+ // );`)
addLog.info('init pg successful');
} catch (error) {
From ecbaffd861781bcee51846124d0697e1ba37684a Mon Sep 17 00:00:00 2001
From: archer <545436317@qq.com>
Date: Fri, 7 Mar 2025 15:52:53 +0800
Subject: [PATCH 2/5] perf: ai proxy avatar
---
.../web/components/common/Icon/constants.ts | 4 +++
.../common/Icon/icons/model/aws.svg | 1 +
.../common/Icon/icons/model/azure.svg | 1 +
.../common/Icon/icons/model/cloudflare.svg | 1 +
.../common/Icon/icons/model/cohere.svg | 1 +
projects/app/src/global/aiproxy/constants.ts | 29 ++++++++++++++++++-
.../model/Channel/EditChannelModal.tsx | 3 +-
.../app/src/pages/api/core/ai/model/test.ts | 4 +--
8 files changed, 40 insertions(+), 4 deletions(-)
create mode 100644 packages/web/components/common/Icon/icons/model/aws.svg
create mode 100644 packages/web/components/common/Icon/icons/model/azure.svg
create mode 100644 packages/web/components/common/Icon/icons/model/cloudflare.svg
create mode 100644 packages/web/components/common/Icon/icons/model/cohere.svg
diff --git a/packages/web/components/common/Icon/constants.ts b/packages/web/components/common/Icon/constants.ts
index 3d1d713b963f..5511c1fb10e7 100644
--- a/packages/web/components/common/Icon/constants.ts
+++ b/packages/web/components/common/Icon/constants.ts
@@ -373,9 +373,13 @@ export const iconPaths = {
'modal/teamPlans': () => import('./icons/modal/teamPlans.svg'),
'model/BAAI': () => import('./icons/model/BAAI.svg'),
'model/alicloud': () => import('./icons/model/alicloud.svg'),
+ 'model/aws': () => import('./icons/model/aws.svg'),
+ 'model/azure': () => import('./icons/model/azure.svg'),
'model/baichuan': () => import('./icons/model/baichuan.svg'),
'model/chatglm': () => import('./icons/model/chatglm.svg'),
'model/claude': () => import('./icons/model/claude.svg'),
+ 'model/cloudflare': () => import('./icons/model/cloudflare.svg'),
+ 'model/cohere': () => import('./icons/model/cohere.svg'),
'model/deepseek': () => import('./icons/model/deepseek.svg'),
'model/doubao': () => import('./icons/model/doubao.svg'),
'model/ernie': () => import('./icons/model/ernie.svg'),
diff --git a/packages/web/components/common/Icon/icons/model/aws.svg b/packages/web/components/common/Icon/icons/model/aws.svg
new file mode 100644
index 000000000000..39e8331497c4
--- /dev/null
+++ b/packages/web/components/common/Icon/icons/model/aws.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/web/components/common/Icon/icons/model/azure.svg b/packages/web/components/common/Icon/icons/model/azure.svg
new file mode 100644
index 000000000000..b93c3ea6b857
--- /dev/null
+++ b/packages/web/components/common/Icon/icons/model/azure.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/web/components/common/Icon/icons/model/cloudflare.svg b/packages/web/components/common/Icon/icons/model/cloudflare.svg
new file mode 100644
index 000000000000..839f98610898
--- /dev/null
+++ b/packages/web/components/common/Icon/icons/model/cloudflare.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/web/components/common/Icon/icons/model/cohere.svg b/packages/web/components/common/Icon/icons/model/cohere.svg
new file mode 100644
index 000000000000..9fd187431b92
--- /dev/null
+++ b/packages/web/components/common/Icon/icons/model/cohere.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/projects/app/src/global/aiproxy/constants.ts b/projects/app/src/global/aiproxy/constants.ts
index 5fb0d35c0ec6..5093fa664ef2 100644
--- a/projects/app/src/global/aiproxy/constants.ts
+++ b/projects/app/src/global/aiproxy/constants.ts
@@ -40,12 +40,16 @@ export const defaultChannel: ChannelInfoType = {
priority: 0
};
-export const aiproxyIdMap: Record = {
+export const aiproxyIdMap: Record<
+ number,
+ { label: string; provider: ModelProviderIdType; avatar?: string }
+> = {
1: {
label: 'OpenAI',
provider: 'OpenAI'
},
3: {
+ avatar: 'model/azure',
label: i18nT('account_model:azure'),
provider: 'OpenAI'
},
@@ -124,5 +128,28 @@ export const aiproxyIdMap: Record {
const res = providerList.find((item) => item.value === providerType);
return res;
diff --git a/projects/app/src/pages/api/core/ai/model/test.ts b/projects/app/src/pages/api/core/ai/model/test.ts
index aa9c1e65848a..02e15b0512ff 100644
--- a/projects/app/src/pages/api/core/ai/model/test.ts
+++ b/projects/app/src/pages/api/core/ai/model/test.ts
@@ -18,7 +18,7 @@ import { isProduction } from '@fastgpt/global/common/system/constants';
import * as fs from 'fs';
import { llmCompletionsBodyFormat } from '@fastgpt/service/core/ai/utils';
-export type testQuery = { model: string };
+export type testQuery = { model: string; channelId?: string };
export type testBody = {};
@@ -30,7 +30,7 @@ async function handler(
): Promise {
await authSystemAdmin({ req });
- const { model } = req.query;
+ const { model, channelId } = req.query;
const modelData = findModelFromAlldata(model);
if (!modelData) return Promise.reject('Model not found');
From 415417849e0d52ca761019fe728c7af726eac7df Mon Sep 17 00:00:00 2001
From: archer <545436317@qq.com>
Date: Mon, 10 Mar 2025 14:56:38 +0800
Subject: [PATCH 3/5] fix: import dataset step error
---
packages/global/common/string/textSplitter.ts | 4 ++--
packages/web/i18n/en/dataset.json | 1 +
packages/web/i18n/zh-CN/dataset.json | 1 +
packages/web/i18n/zh-Hant/dataset.json | 1 +
.../app/src/pageComponents/dataset/detail/Import/Context.tsx | 2 +-
.../dataset/detail/Import/diffSource/APIDataset.tsx | 4 +++-
.../dataset/detail/Import/diffSource/ExternalFile.tsx | 4 +++-
.../dataset/detail/Import/diffSource/FileCustomText.tsx | 4 +++-
.../dataset/detail/Import/diffSource/FileLink.tsx | 4 +++-
.../dataset/detail/Import/diffSource/ReTraining.tsx | 2 +-
10 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/packages/global/common/string/textSplitter.ts b/packages/global/common/string/textSplitter.ts
index c88023213065..fe1212ba7ea8 100644
--- a/packages/global/common/string/textSplitter.ts
+++ b/packages/global/common/string/textSplitter.ts
@@ -93,7 +93,7 @@ ${mdSplitString}
/*
1. 自定义分隔符:不需要重叠,不需要小块合并
- 2. Markdown 标题:不需要重叠;标题嵌套共享,不需要小块合并
+ 2. Markdown 标题:不需要重叠;标题嵌套共享,需要小块合并
3. 特殊 markdown 语法:不需要重叠,需要小块合并
4. 段落:尽可能保证它是一个完整的段落。
5. 标点分割:重叠
@@ -227,7 +227,7 @@ const commonSplit = (props: SplitProps): SplitResponse => {
}): string[] => {
const isMarkdownStep = checkIsMarkdownSplit(step);
const isCustomStep = checkIsCustomStep(step);
- const forbidConcat = isMarkdownStep || isCustomStep; // forbid=true时候,lastText肯定为空
+ const forbidConcat = isCustomStep; // forbid=true时候,lastText肯定为空
// oversize
if (step >= stepReges.length) {
diff --git a/packages/web/i18n/en/dataset.json b/packages/web/i18n/en/dataset.json
index 0902a421ed41..0b9a951c8998 100644
--- a/packages/web/i18n/en/dataset.json
+++ b/packages/web/i18n/en/dataset.json
@@ -69,6 +69,7 @@
"import_model_config": "Model selection",
"import_param_setting": "Parameter settings",
"import_select_file": "Select a file",
+ "import_select_link": "Enter link",
"is_open_schedule": "Enable scheduled synchronization",
"keep_image": "Keep the picture",
"move.hint": "After moving, the selected knowledge base/folder will inherit the permission settings of the new folder, and the original permission settings will become invalid.",
diff --git a/packages/web/i18n/zh-CN/dataset.json b/packages/web/i18n/zh-CN/dataset.json
index 2dc1cc54cc00..064b5a73bb91 100644
--- a/packages/web/i18n/zh-CN/dataset.json
+++ b/packages/web/i18n/zh-CN/dataset.json
@@ -69,6 +69,7 @@
"import_model_config": "模型选择",
"import_param_setting": "参数设置",
"import_select_file": "选择文件",
+ "import_select_link": "输入链接",
"is_open_schedule": "启用定时同步",
"keep_image": "保留图片",
"move.hint": "移动后,所选知识库/文件夹将继承新文件夹的权限设置,原先的权限设置失效。",
diff --git a/packages/web/i18n/zh-Hant/dataset.json b/packages/web/i18n/zh-Hant/dataset.json
index 7eab0f0805db..706714283744 100644
--- a/packages/web/i18n/zh-Hant/dataset.json
+++ b/packages/web/i18n/zh-Hant/dataset.json
@@ -69,6 +69,7 @@
"import_model_config": "模型選擇",
"import_param_setting": "參數設置",
"import_select_file": "選擇文件",
+ "import_select_link": "輸入鏈接",
"is_open_schedule": "啟用定時同步",
"keep_image": "保留圖片",
"move.hint": "移動後,所選資料集/資料夾將繼承新資料夾的權限設定,原先的權限設定將失效。",
diff --git a/projects/app/src/pageComponents/dataset/detail/Import/Context.tsx b/projects/app/src/pageComponents/dataset/detail/Import/Context.tsx
index 853efddecd3c..d437f39c1d55 100644
--- a/projects/app/src/pageComponents/dataset/detail/Import/Context.tsx
+++ b/projects/app/src/pageComponents/dataset/detail/Import/Context.tsx
@@ -113,7 +113,7 @@ const DatasetImportContextProvider = ({ children }: { children: React.ReactNode
],
[ImportDataSourceEnum.fileLink]: [
{
- title: t('dataset:import_select_file')
+ title: t('dataset:import_select_link')
},
{
title: t('dataset:import_param_setting')
diff --git a/projects/app/src/pageComponents/dataset/detail/Import/diffSource/APIDataset.tsx b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/APIDataset.tsx
index dee1dd83fa04..a8facf7eec3f 100644
--- a/projects/app/src/pageComponents/dataset/detail/Import/diffSource/APIDataset.tsx
+++ b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/APIDataset.tsx
@@ -21,6 +21,7 @@ const DataProcess = dynamic(() => import('../commonProgress/DataProcess'), {
loading: () =>
});
const Upload = dynamic(() => import('../commonProgress/Upload'));
+const PreviewData = dynamic(() => import('../commonProgress/PreviewData'));
const APIDatasetCollection = () => {
const activeStep = useContextSelector(DatasetImportContext, (v) => v.activeStep);
@@ -29,7 +30,8 @@ const APIDatasetCollection = () => {
<>
{activeStep === 0 && }
{activeStep === 1 && }
- {activeStep === 2 && }
+ {activeStep === 2 && }
+ {activeStep === 3 && }
>
);
};
diff --git a/projects/app/src/pageComponents/dataset/detail/Import/diffSource/ExternalFile.tsx b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/ExternalFile.tsx
index e1e29b00acf8..e1a6beb23705 100644
--- a/projects/app/src/pageComponents/dataset/detail/Import/diffSource/ExternalFile.tsx
+++ b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/ExternalFile.tsx
@@ -27,6 +27,7 @@ const DataProcess = dynamic(() => import('../commonProgress/DataProcess'), {
loading: () =>
});
const Upload = dynamic(() => import('../commonProgress/Upload'));
+const PreviewData = dynamic(() => import('../commonProgress/PreviewData'));
const ExternalFileCollection = () => {
const activeStep = useContextSelector(DatasetImportContext, (v) => v.activeStep);
@@ -35,7 +36,8 @@ const ExternalFileCollection = () => {
<>
{activeStep === 0 && }
{activeStep === 1 && }
- {activeStep === 2 && }
+ {activeStep === 2 && }
+ {activeStep === 3 && }
>
);
};
diff --git a/projects/app/src/pageComponents/dataset/detail/Import/diffSource/FileCustomText.tsx b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/FileCustomText.tsx
index 12c0c28de428..fcf08248d6c4 100644
--- a/projects/app/src/pageComponents/dataset/detail/Import/diffSource/FileCustomText.tsx
+++ b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/FileCustomText.tsx
@@ -13,6 +13,7 @@ const DataProcess = dynamic(() => import('../commonProgress/DataProcess'), {
loading: () =>
});
const Upload = dynamic(() => import('../commonProgress/Upload'));
+const PreviewData = dynamic(() => import('../commonProgress/PreviewData'));
const CustomTet = () => {
const activeStep = useContextSelector(DatasetImportContext, (v) => v.activeStep);
@@ -20,7 +21,8 @@ const CustomTet = () => {
<>
{activeStep === 0 && }
{activeStep === 1 && }
- {activeStep === 2 && }
+ {activeStep === 2 && }
+ {activeStep === 3 && }
>
);
};
diff --git a/projects/app/src/pageComponents/dataset/detail/Import/diffSource/FileLink.tsx b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/FileLink.tsx
index b9f0e192ea00..ca41cf40cfae 100644
--- a/projects/app/src/pageComponents/dataset/detail/Import/diffSource/FileLink.tsx
+++ b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/FileLink.tsx
@@ -16,6 +16,7 @@ const DataProcess = dynamic(() => import('../commonProgress/DataProcess'), {
loading: () =>
});
const Upload = dynamic(() => import('../commonProgress/Upload'));
+const PreviewData = dynamic(() => import('../commonProgress/PreviewData'));
const LinkCollection = () => {
const activeStep = useContextSelector(DatasetImportContext, (v) => v.activeStep);
@@ -24,7 +25,8 @@ const LinkCollection = () => {
<>
{activeStep === 0 && }
{activeStep === 1 && }
- {activeStep === 2 && }
+ {activeStep === 2 && }
+ {activeStep === 3 && }
>
);
};
diff --git a/projects/app/src/pageComponents/dataset/detail/Import/diffSource/ReTraining.tsx b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/ReTraining.tsx
index ba7d56fa2e10..068e0ea64e00 100644
--- a/projects/app/src/pageComponents/dataset/detail/Import/diffSource/ReTraining.tsx
+++ b/projects/app/src/pageComponents/dataset/detail/Import/diffSource/ReTraining.tsx
@@ -57,7 +57,7 @@ const ReTraining = () => {
qaChunkSize: collection.chunkSize,
customSplitChar: collection.chunkSplitter,
qaPrompt: collection.qaPrompt,
- webSelector: collection.metadata?.webSelector
+ webSelector: collection.metadata?.webPageSelector
});
}
});
From 3cccb00085a715360d44a37a45f516fe093c40ca Mon Sep 17 00:00:00 2001
From: archer <545436317@qq.com>
Date: Tue, 11 Mar 2025 12:30:27 +0800
Subject: [PATCH 4/5] feat: data input ux
---
deploy/docker/docker-compose-milvus.yml | 6 +-
deploy/docker/docker-compose-pgvector.yml | 6 +-
deploy/docker/docker-compose-zilliz.yml | 6 +-
.../zh-cn/docs/development/upgrading/4823.md | 2 +-
.../zh-cn/docs/development/upgrading/490.md | 2 +-
.../zh-cn/docs/development/upgrading/491.md | 23 +
.../web/components/common/Icon/button.tsx | 1 +
.../Icon/icons/core/chat/chevronDown.svg | 6 +-
.../common/Icon/icons/core/chat/chevronUp.svg | 6 +-
packages/web/i18n/en/common.json | 12 +-
packages/web/i18n/zh-CN/common.json | 14 +-
packages/web/i18n/zh-Hant/common.json | 12 +-
.../dataset/detail/InputDataModal.tsx | 541 +++++++++---------
.../app/src/pages/account/usage/index.tsx | 2 -
.../app/src/pages/api/core/ai/model/test.ts | 3 +-
15 files changed, 330 insertions(+), 312 deletions(-)
create mode 100644 docSite/content/zh-cn/docs/development/upgrading/491.md
diff --git a/deploy/docker/docker-compose-milvus.yml b/deploy/docker/docker-compose-milvus.yml
index e5a90446bd22..0ba7a90122b7 100644
--- a/deploy/docker/docker-compose-milvus.yml
+++ b/deploy/docker/docker-compose-milvus.yml
@@ -100,7 +100,7 @@ services:
exec docker-entrypoint.sh "$$@" &
# 等待MongoDB服务启动
- until mongo -u myusername -p mypassword --authenticationDatabase admin --eval "print('waited for connection')" > /dev/null 2>&1; do
+ until mongo -u myusername -p mypassword --authenticationDatabase admin --eval "print('waited for connection')"; do
echo "Waiting for MongoDB to start..."
sleep 2
done
@@ -175,7 +175,7 @@ services:
# AI Proxy
aiproxy:
- image: 'ghcr.io/labring/sealos-aiproxy-service:latest'
+ image: ghcr.io/labring/sealos-aiproxy-service:latest
container_name: aiproxy
restart: unless-stopped
depends_on:
@@ -191,7 +191,7 @@ services:
# 数据库连接地址
- SQL_DSN=postgres://postgres:aiproxy@aiproxy_pg:5432/aiproxy
# 最大重试次数
- - RetryTimes=3
+ - RETRY_TIMES=3
# 不需要计费
- BILLING_ENABLED=false
# 不需要严格检测模型
diff --git a/deploy/docker/docker-compose-pgvector.yml b/deploy/docker/docker-compose-pgvector.yml
index 0d763c912cd5..b4bb21a3a394 100644
--- a/deploy/docker/docker-compose-pgvector.yml
+++ b/deploy/docker/docker-compose-pgvector.yml
@@ -58,7 +58,7 @@ services:
exec docker-entrypoint.sh "$$@" &
# 等待MongoDB服务启动
- until mongo -u myusername -p mypassword --authenticationDatabase admin --eval "print('waited for connection')" > /dev/null 2>&1; do
+ until mongo -u myusername -p mypassword --authenticationDatabase admin --eval "print('waited for connection')"; do
echo "Waiting for MongoDB to start..."
sleep 2
done
@@ -132,7 +132,7 @@ services:
# AI Proxy
aiproxy:
- image: 'ghcr.io/labring/sealos-aiproxy-service:latest'
+ image: ghcr.io/labring/sealos-aiproxy-service:latest
container_name: aiproxy
restart: unless-stopped
depends_on:
@@ -148,7 +148,7 @@ services:
# 数据库连接地址
- SQL_DSN=postgres://postgres:aiproxy@aiproxy_pg:5432/aiproxy
# 最大重试次数
- - RetryTimes=3
+ - RETRY_TIMES=3
# 不需要计费
- BILLING_ENABLED=false
# 不需要严格检测模型
diff --git a/deploy/docker/docker-compose-zilliz.yml b/deploy/docker/docker-compose-zilliz.yml
index c4cafe71cf50..23cad557f7c0 100644
--- a/deploy/docker/docker-compose-zilliz.yml
+++ b/deploy/docker/docker-compose-zilliz.yml
@@ -41,7 +41,7 @@ services:
exec docker-entrypoint.sh "$$@" &
# 等待MongoDB服务启动
- until mongo -u myusername -p mypassword --authenticationDatabase admin --eval "print('waited for connection')" > /dev/null 2>&1; do
+ until mongo -u myusername -p mypassword --authenticationDatabase admin --eval "print('waited for connection')"; do
echo "Waiting for MongoDB to start..."
sleep 2
done
@@ -113,7 +113,7 @@ services:
# AI Proxy
aiproxy:
- image: 'ghcr.io/labring/sealos-aiproxy-service:latest'
+ image: ghcr.io/labring/sealos-aiproxy-service:latest
container_name: aiproxy
restart: unless-stopped
depends_on:
@@ -129,7 +129,7 @@ services:
# 数据库连接地址
- SQL_DSN=postgres://postgres:aiproxy@aiproxy_pg:5432/aiproxy
# 最大重试次数
- - RetryTimes=3
+ - RETRY_TIMES=3
# 不需要计费
- BILLING_ENABLED=false
# 不需要严格检测模型
diff --git a/docSite/content/zh-cn/docs/development/upgrading/4823.md b/docSite/content/zh-cn/docs/development/upgrading/4823.md
index 446245b1eb2f..4741613a3318 100644
--- a/docSite/content/zh-cn/docs/development/upgrading/4823.md
+++ b/docSite/content/zh-cn/docs/development/upgrading/4823.md
@@ -4,7 +4,7 @@ description: 'FastGPT V4.8.23 更新说明'
icon: 'upgrade'
draft: false
toc: true
-weight: 802
+weight: 801
---
## 更新指南
diff --git a/docSite/content/zh-cn/docs/development/upgrading/490.md b/docSite/content/zh-cn/docs/development/upgrading/490.md
index eb654c1b506e..b61bf0f0a453 100644
--- a/docSite/content/zh-cn/docs/development/upgrading/490.md
+++ b/docSite/content/zh-cn/docs/development/upgrading/490.md
@@ -4,7 +4,7 @@ description: 'FastGPT V4.9.0 更新说明'
icon: 'upgrade'
draft: false
toc: true
-weight: 801
+weight: 800
---
diff --git a/docSite/content/zh-cn/docs/development/upgrading/491.md b/docSite/content/zh-cn/docs/development/upgrading/491.md
new file mode 100644
index 000000000000..60006d7ec34a
--- /dev/null
+++ b/docSite/content/zh-cn/docs/development/upgrading/491.md
@@ -0,0 +1,23 @@
+---
+title: 'V4.9.1'
+description: 'FastGPT V4.9.1 更新说明'
+icon: 'upgrade'
+draft: false
+toc: true
+weight: 799
+---
+
+## 🚀 新增内容
+
+
+## ⚙️ 优化
+
+1. 知识库数据输入框交互
+2. 增加依赖包安全版本检测,并升级部分依赖包。
+
+## 🐛 修复
+
+1. 最大响应 tokens 提示显示错误的问题。
+2. HTTP Node 中,字符串包含换行符时,会解析失败。
+3. 知识库问题优化中,未传递历史记录。
+4. 错误提示翻译缺失。
\ No newline at end of file
diff --git a/packages/web/components/common/Icon/button.tsx b/packages/web/components/common/Icon/button.tsx
index b335a117a0e2..7a6bc8eedf77 100644
--- a/packages/web/components/common/Icon/button.tsx
+++ b/packages/web/components/common/Icon/button.tsx
@@ -34,6 +34,7 @@ const MyIconButton = ({
color: hoverColor
}}
onClick={onClick}
+ sx={{ userSelect: 'none' }}
{...props}
>
diff --git a/packages/web/components/common/Icon/icons/core/chat/chevronDown.svg b/packages/web/components/common/Icon/icons/core/chat/chevronDown.svg
index cc8ed229cf08..d69e3d30b4f5 100644
--- a/packages/web/components/common/Icon/icons/core/chat/chevronDown.svg
+++ b/packages/web/components/common/Icon/icons/core/chat/chevronDown.svg
@@ -1,3 +1,3 @@
-
+
\ No newline at end of file
diff --git a/packages/web/components/common/Icon/icons/core/chat/chevronUp.svg b/packages/web/components/common/Icon/icons/core/chat/chevronUp.svg
index 9088fc25812a..34de47bde169 100644
--- a/packages/web/components/common/Icon/icons/core/chat/chevronUp.svg
+++ b/packages/web/components/common/Icon/icons/core/chat/chevronUp.svg
@@ -1,3 +1,3 @@
-
+
\ No newline at end of file
diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json
index d71060c08059..0e4cc97c7ade 100644
--- a/packages/web/i18n/en/common.json
+++ b/packages/web/i18n/en/common.json
@@ -534,16 +534,10 @@
"core.dataset.collection.status.active": "Ready",
"core.dataset.collection.sync.result.sameRaw": "Content Unchanged, No Update Needed",
"core.dataset.collection.sync.result.success": "Sync Started",
- "core.dataset.data.Auxiliary Data": "Auxiliary Data",
- "core.dataset.data.Auxiliary Data Placeholder": "This part is optional and is usually used to construct structured prompts in conjunction with the 'Data Content' above for special scenarios, up to {{maxToken}} characters.",
- "core.dataset.data.Auxiliary Data Tip": "This part is optional\nThis content is usually used to construct structured prompts in conjunction with the data content above for special scenarios",
"core.dataset.data.Data Content": "Related Data Content",
- "core.dataset.data.Data Content Placeholder": "This input box is required. This content is usually a description of the knowledge point or a user's question, up to {{maxToken}} characters.",
- "core.dataset.data.Data Content Tip": "This input box is required\nThis content is usually a description of the knowledge point or a user's question.",
"core.dataset.data.Default Index Tip": "Cannot be edited. The default index will use the text of 'Related Data Content' and 'Auxiliary Data' to generate the index directly.",
"core.dataset.data.Edit": "Edit Data",
"core.dataset.data.Empty Tip": "This collection has no data yet",
- "core.dataset.data.Main Content": "Main Content",
"core.dataset.data.Search data placeholder": "Search Related Data",
"core.dataset.data.Too Long": "Total Length Exceeded",
"core.dataset.data.group": "Group",
@@ -867,6 +861,12 @@
"dataset.dataset_name": "Dataset Name",
"dataset.deleteFolderTips": "Confirm to Delete This Folder and All Its Contained Datasets? Data Cannot Be Recovered After Deletion, Please Confirm!",
"dataset.test.noResult": "No Search Results",
+ "dataset_data_import_q_placeholder": "Up to {{maxToken}} words.",
+ "dataset_data_input_a": "Answer",
+ "dataset_data_input_chunk": "Chunk",
+ "dataset_data_input_chunk_content": "Chunk",
+ "dataset_data_input_q": "question",
+ "dataset_data_input_qa": "QA",
"dataset_text_model_tip": "Used for text processing in the knowledge base preprocessing stage, such as automatic supplementary indexing, Q&A pair extraction.",
"deep_rag_search": "In-depth search",
"delete_api": "Are you sure you want to delete this API key? \nAfter deletion, the key will become invalid immediately and the corresponding conversation log will not be deleted. Please confirm!",
diff --git a/packages/web/i18n/zh-CN/common.json b/packages/web/i18n/zh-CN/common.json
index 47821542d1bc..bc119e67cf40 100644
--- a/packages/web/i18n/zh-CN/common.json
+++ b/packages/web/i18n/zh-CN/common.json
@@ -537,16 +537,10 @@
"core.dataset.collection.status.active": "已就绪",
"core.dataset.collection.sync.result.sameRaw": "内容未变动,无需更新",
"core.dataset.collection.sync.result.success": "开始同步",
- "core.dataset.data.Auxiliary Data": "辅助数据",
- "core.dataset.data.Auxiliary Data Placeholder": "该部分为可选填项,通常是为了与前面的【数据内容】配合,构建结构化提示词,用于特殊场景,最多 {{maxToken}} 字。",
- "core.dataset.data.Auxiliary Data Tip": "该部分为可选填项\n该内容通常是为了与前面的数据内容配合,构建结构化提示词,用于特殊场景",
"core.dataset.data.Data Content": "相关数据内容",
- "core.dataset.data.Data Content Placeholder": "该输入框是必填项,该内容通常是对于知识点的描述,也可以是用户的问题,最多 {{maxToken}} 字。",
- "core.dataset.data.Data Content Tip": "该输入框是必填项\n该内容通常是对于知识点的描述,也可以是用户的问题。",
"core.dataset.data.Default Index Tip": "无法编辑,默认索引会使用【相关数据内容】与【辅助数据】的文本直接生成索引。",
"core.dataset.data.Edit": "编辑数据",
"core.dataset.data.Empty Tip": "这个集合还没有数据~",
- "core.dataset.data.Main Content": "主要内容",
"core.dataset.data.Search data placeholder": "搜索相关数据",
"core.dataset.data.Too Long": "总长度超长了",
"core.dataset.data.group": "组",
@@ -560,6 +554,7 @@
"core.dataset.error.unAuthDatasetData": "无权操作该数据",
"core.dataset.error.unAuthDatasetFile": "无权操作该文件",
"core.dataset.error.unCreateCollection": "无权操作该数据",
+ "core.dataset.error.unExistDataset": "数据集不存在",
"core.dataset.error.unLinkCollection": "不是网络链接集合",
"core.dataset.externalFile": "外部文件库",
"core.dataset.file": "文件",
@@ -664,7 +659,6 @@
"core.dataset.website.Selector Course": "使用教程",
"core.dataset.website.Start Sync": "开始同步",
"core.dataset.website.UnValid Website Tip": "您的站点可能非静态站点,无法同步",
- "core.dataset.error.unExistDataset": "数据集不存在",
"core.module.Add question type": "添加问题类型",
"core.module.Add_option": "添加选项",
"core.module.Can not connect self": "不能连接自身",
@@ -871,6 +865,12 @@
"dataset.dataset_name": "知识库名称",
"dataset.deleteFolderTips": "确认删除该文件夹及其包含的所有知识库?删除后数据无法恢复,请确认!",
"dataset.test.noResult": "搜索结果为空",
+ "dataset_data_import_q_placeholder": "最多 {{maxToken}} 字。",
+ "dataset_data_input_a": "答案",
+ "dataset_data_input_chunk": "常规模式",
+ "dataset_data_input_chunk_content": "内容",
+ "dataset_data_input_q": "问题",
+ "dataset_data_input_qa": "QA 模式",
"dataset_text_model_tip": "用于知识库预处理阶段的文本处理,例如自动补充索引、问答对提取。",
"deep_rag_search": "深度搜索",
"delete_api": "确认删除该API密钥?删除后该密钥立即失效,对应的对话日志不会删除,请确认!",
diff --git a/packages/web/i18n/zh-Hant/common.json b/packages/web/i18n/zh-Hant/common.json
index e3fd6e908f54..4fb5a389c0e0 100644
--- a/packages/web/i18n/zh-Hant/common.json
+++ b/packages/web/i18n/zh-Hant/common.json
@@ -533,16 +533,10 @@
"core.dataset.collection.status.active": "已就緒",
"core.dataset.collection.sync.result.sameRaw": "內容未變更,無需更新",
"core.dataset.collection.sync.result.success": "開始同步",
- "core.dataset.data.Auxiliary Data": "輔助資料",
- "core.dataset.data.Auxiliary Data Placeholder": "此部分為選填項目,通常是為了與前面的【資料內容】配合,建構結構化提示詞,用於特殊場景,最多 {{maxToken}} 字。",
- "core.dataset.data.Auxiliary Data Tip": "此部分為選填項目\n此內容通常是為了與前面的資料內容配合,建構結構化提示詞,用於特殊場景",
"core.dataset.data.Data Content": "相關資料內容",
- "core.dataset.data.Data Content Placeholder": "此輸入欄位為必填項目,此內容通常是知識點的描述,也可以是使用者的問題,最多 {{maxToken}} 字。",
- "core.dataset.data.Data Content Tip": "此輸入欄位為必填項目\n此內容通常是知識點的描述,也可以是使用者的問題。",
"core.dataset.data.Default Index Tip": "無法編輯,預設索引會使用【相關資料內容】與【輔助資料】的文字直接產生索引。",
"core.dataset.data.Edit": "編輯資料",
"core.dataset.data.Empty Tip": "此集合還沒有資料",
- "core.dataset.data.Main Content": "主要內容",
"core.dataset.data.Search data placeholder": "搜尋相關資料",
"core.dataset.data.Too Long": "總長度超出上限",
"core.dataset.data.group": "組",
@@ -867,6 +861,12 @@
"dataset.dataset_name": "知識庫名稱",
"dataset.deleteFolderTips": "確認刪除此資料夾及其包含的所有知識庫?刪除後資料無法復原,請確認!",
"dataset.test.noResult": "搜尋結果為空",
+ "dataset_data_import_q_placeholder": "最多 {{maxToken}} 字。",
+ "dataset_data_input_a": "答案",
+ "dataset_data_input_chunk": "常規模式",
+ "dataset_data_input_chunk_content": "內容",
+ "dataset_data_input_q": "問題",
+ "dataset_data_input_qa": "QA 模式",
"dataset_text_model_tip": "用於知識庫預處理階段的文本處理,例如自動補充索引、問答對提取。",
"deep_rag_search": "深度搜索",
"delete_api": "確認刪除此 API 金鑰?\n刪除後該金鑰將立即失效,對應的對話記錄不會被刪除,請確認!",
diff --git a/projects/app/src/pageComponents/dataset/detail/InputDataModal.tsx b/projects/app/src/pageComponents/dataset/detail/InputDataModal.tsx
index ce69dea0128f..bbb9a73a0156 100644
--- a/projects/app/src/pageComponents/dataset/detail/InputDataModal.tsx
+++ b/projects/app/src/pageComponents/dataset/detail/InputDataModal.tsx
@@ -1,12 +1,6 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
-import { Box, Flex, Button, Textarea } from '@chakra-ui/react';
-import {
- FieldArrayWithId,
- UseFieldArrayRemove,
- UseFormRegister,
- useFieldArray,
- useForm
-} from 'react-hook-form';
+import { Box, Flex, Button, Textarea, ModalFooter, HStack, VStack } from '@chakra-ui/react';
+import { UseFormRegister, useFieldArray, useForm } from 'react-hook-form';
import {
postInsertData2Dataset,
putDatasetDataById,
@@ -17,7 +11,6 @@ import { useToast } from '@fastgpt/web/hooks/useToast';
import MyIcon from '@fastgpt/web/components/common/Icon';
import MyModal from '@fastgpt/web/components/common/MyModal';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
-import { useQuery } from '@tanstack/react-query';
import { useTranslation } from 'next-i18next';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { getSourceNameIcon } from '@fastgpt/global/core/dataset/utils';
@@ -28,25 +21,27 @@ import { getDocPath } from '@/web/common/system/doc';
import MyBox from '@fastgpt/web/components/common/MyBox';
import { getErrText } from '@fastgpt/global/common/error/utils';
import { useSystemStore } from '@/web/common/system/useSystemStore';
-import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
-import LightRowTabs from '@fastgpt/web/components/common/Tabs/LightRowTabs';
import styles from './styles.module.scss';
import {
DatasetDataIndexTypeEnum,
getDatasetIndexMapData
} from '@fastgpt/global/core/dataset/data/constants';
+import FillRowTabs from '@fastgpt/web/components/common/Tabs/FillRowTabs';
+import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
+import MyIconButton from '@fastgpt/web/components/common/Icon/button';
export type InputDataType = {
q: string;
a: string;
indexes: (Omit & {
dataId?: string; // pg data id
+ fold: boolean;
})[];
};
enum TabEnum {
- content = 'content',
- index = 'index'
+ chunk = 'chunk',
+ qa = 'qa'
}
const InputDataModal = ({
@@ -64,73 +59,47 @@ const InputDataModal = ({
}) => {
const { t } = useTranslation();
const { toast } = useToast();
- const [currentTab, setCurrentTab] = useState(TabEnum.content);
const { embeddingModelList, defaultModels } = useSystemStore();
+ const [currentTab, setCurrentTab] = useState(TabEnum.chunk);
+
const { register, handleSubmit, reset, control } = useForm();
const {
fields: indexes,
- append: appendIndexes,
- remove: removeIndexes
+ prepend: prependIndexes,
+ remove: removeIndexes,
+ update: updateIndexes
} = useFieldArray({
control,
name: 'indexes'
});
- const tabList = [
- {
- label: (
-
- {t('common:dataset.data.edit.divide_content')}
-
- ),
- value: TabEnum.content
- },
- {
- label: (
-
- {t('common:dataset.data.edit.Index', { amount: indexes.length })}
-
-
- window.open(getDocPath('/docs/guide/knowledge_base/dataset_engine/'), '_blank')
- }
- _hover={{
- color: 'primary.600',
- cursor: 'pointer'
- }}
- />
-
-
- ),
- value: TabEnum.index
- }
- ];
-
- const { data: collection = defaultCollectionDetail } = useQuery(
- ['loadCollectionId', collectionId],
+ const { data: collection = defaultCollectionDetail } = useRequest2(
() => {
return getDatasetCollectionById(collectionId);
+ },
+ {
+ manual: false,
+ refreshDeps: [collectionId]
}
);
- const { isFetching: isFetchingData } = useQuery(
- ['getDatasetDataItemById', dataId],
- () => {
+ const { loading: isFetchingData } = useRequest2(
+ async () => {
if (dataId) return getDatasetDataItemById(dataId);
return null;
},
{
+ manual: false,
+ refreshDeps: [dataId],
onSuccess(res) {
if (res) {
reset({
q: res.q,
a: res.a,
- indexes: res.indexes
+ indexes: res.indexes.map((item) => ({
+ ...item,
+ fold: true
+ }))
});
} else if (defaultValue) {
reset({
@@ -138,6 +107,10 @@ const InputDataModal = ({
a: defaultValue.a
});
}
+
+ if (res?.a || defaultValue?.a) {
+ setCurrentTab(TabEnum.qa);
+ }
},
onError(err) {
toast({
@@ -161,7 +134,6 @@ const InputDataModal = ({
const { runAsync: sureImportData, loading: isImporting } = useRequest2(
async (e: InputDataType) => {
if (!e.q) {
- setCurrentTab(TabEnum.content);
return Promise.reject(t('common:dataset.data.input is empty'));
}
@@ -175,9 +147,9 @@ const InputDataModal = ({
const dataId = await postInsertData2Dataset({
collectionId: collection._id,
q: e.q,
- a: e.a,
+ a: currentTab === TabEnum.qa ? e.a : '',
// Contains no default index
- indexes: e.indexes
+ indexes: e.indexes.filter((item) => !!item.text?.trim())
});
return {
@@ -186,6 +158,7 @@ const InputDataModal = ({
};
},
{
+ refreshDeps: [currentTab],
successToast: t('common:dataset.data.Input Success Tip'),
onSuccess(e) {
reset({
@@ -208,8 +181,9 @@ const InputDataModal = ({
// not exactly same
await putDatasetDataById({
dataId,
- ...e,
- indexes: e.indexes
+ q: e.q,
+ a: currentTab === TabEnum.qa ? e.a : '',
+ indexes: e.indexes.filter((item) => !!item.text?.trim())
});
return {
@@ -218,6 +192,7 @@ const InputDataModal = ({
};
},
{
+ refreshDeps: [currentTab],
successToast: t('common:dataset.data.Update Success Tip'),
onSuccess(data) {
onSuccess(data);
@@ -267,49 +242,166 @@ const InputDataModal = ({
isLoading={isLoading}
h={'100%'}
py={[6, '1.5rem']}
- px={[5, '3.25rem']}
>
-
-
-
- list={tabList}
- p={0}
- value={currentTab}
- onChange={(e: TabEnum) => setCurrentTab(e)}
- />
-
- {currentTab === TabEnum.index && (
-
- )}
+ )}
+
+ {/* Index */}
+
+
+
+ {t('common:dataset.data.edit.Index', {
+ amount: indexes.length
+ })}
+
+
+
+
+
+ {indexes?.map((index, i) => {
+ const data = getDatasetIndexMapData(index.type);
+ return (
+
+ {/* Header */}
+
+ {t(data.label)}
+ {/* Delete */}
+ {index.type !== 'default' && (
+
+ {
+ removeIndexes(i);
+ }}
+ />
+
+ )}
+ {indexes.length > 1 && (
+ {
+ updateIndexes(i, { ...index, fold: !index.fold });
+ }}
+ />
+ )}
+
+ {/* Content */}
+ 1}
+ maxToken={maxToken}
+ register={register}
+ onFocus={() => {
+ updateIndexes(i, { ...index, fold: false });
+ }}
+ />
+
+ );
+ })}
+
+
-
- {currentTab === TabEnum.content && }
- {currentTab === TabEnum.index && (
-
- )}
-
-
+
@@ -322,7 +414,7 @@ const InputDataModal = ({
{dataId ? t('common:common.Confirm Update') : t('common:common.Confirm Import')}
-
+
);
@@ -330,153 +422,23 @@ const InputDataModal = ({
export default React.memo(InputDataModal);
-const InputTab = ({
- maxToken,
- register
-}: {
- maxToken: number;
- register: UseFormRegister;
-}) => {
- const { t } = useTranslation();
-
- return (
- <>
-
-
-
- *
- {t('common:core.dataset.data.Main Content')}
-
-
-
-
-
-
-
-
- {t('common:core.dataset.data.Auxiliary Data')}
-
-
-
-
-
-
-
- >
- );
-};
-
-const DataIndex = ({
- maxToken,
- register,
- indexes,
- removeIndexes
-}: {
- maxToken: number;
- register: UseFormRegister;
- indexes: FieldArrayWithId[];
- removeIndexes: UseFieldArrayRemove;
-}) => {
- const { t } = useTranslation();
-
- return (
- <>
-
- {indexes?.map((index, i) => {
- const data = getDatasetIndexMapData(index.type);
- return (
-
-
-
- {t(data.label)}
-
- {index.type !== 'default' && (
- {
- removeIndexes(i);
- }}
- />
- )}
-
-
-
- );
- })}
-
- >
- );
-};
-
const textareaMinH = '40px';
const DataIndexTextArea = ({
value,
index,
maxToken,
register,
- disabled
+ disabled,
+ isFolder,
+ onFocus
}: {
value: string;
index: number;
maxToken: number;
register: UseFormRegister;
disabled?: boolean;
+ isFolder: boolean;
+ onFocus: () => void;
}) => {
const { t } = useTranslation();
const TextareaDom = useRef(null);
@@ -501,41 +463,76 @@ const DataIndexTextArea = ({
}
}, []);
- return disabled ? (
-
- {value}
+ const onclickMark = () => {
+ TextareaDom?.current?.focus();
+ onFocus();
+ };
+
+ return (
+
+ {disabled ? (
+
+ {value}
+
+ ) : (
+
- ) : (
-