Compare commits
28 Commits
v4.9.10-de
...
v4.9.2-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6efd3318d | ||
|
|
95ffd710aa | ||
|
|
097bb97417 | ||
|
|
4faea8d2b8 | ||
|
|
7ecadb33d1 | ||
|
|
ce61bda223 | ||
|
|
8dba01da73 | ||
|
|
dcdad6fa39 | ||
|
|
11d080d521 | ||
|
|
2f954d2f3f | ||
|
|
a956fbca73 | ||
|
|
db7510c5eb | ||
|
|
b87cc353da | ||
|
|
ff85121546 | ||
|
|
79f9d83349 | ||
|
|
159bf17369 | ||
|
|
4512b23d4d | ||
|
|
5300ddf654 | ||
|
|
f1f0dfc691 | ||
|
|
e5acec8dc7 | ||
|
|
cb832b6305 | ||
|
|
ae9b8a2b8e | ||
|
|
d209255015 | ||
|
|
6eae841e4a | ||
|
|
75c1631670 | ||
|
|
97a182c7fd | ||
|
|
a0ad450032 | ||
|
|
74b36219e1 |
@@ -11,8 +11,6 @@ weight: 853
|
|||||||
| --------------------- | --------------------- |
|
| --------------------- | --------------------- |
|
||||||
|  |  |
|
|  |  |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 创建训练订单
|
## 创建训练订单
|
||||||
|
|
||||||
{{< tabs tabTotal="2" >}}
|
{{< tabs tabTotal="2" >}}
|
||||||
@@ -289,7 +287,7 @@ curl --location --request DELETE 'http://localhost:3000/api/core/dataset/delete?
|
|||||||
|
|
||||||
## 集合
|
## 集合
|
||||||
|
|
||||||
### 通用创建参数说明
|
### 通用创建参数说明(必看)
|
||||||
|
|
||||||
**入参**
|
**入参**
|
||||||
|
|
||||||
@@ -300,8 +298,11 @@ curl --location --request DELETE 'http://localhost:3000/api/core/dataset/delete?
|
|||||||
| trainingType | 数据处理方式。chunk: 按文本长度进行分割;qa: 问答对提取 | ✅ |
|
| trainingType | 数据处理方式。chunk: 按文本长度进行分割;qa: 问答对提取 | ✅ |
|
||||||
| autoIndexes | 是否自动生成索引(仅商业版支持) | |
|
| autoIndexes | 是否自动生成索引(仅商业版支持) | |
|
||||||
| imageIndex | 是否自动生成图片索引(仅商业版支持) | |
|
| imageIndex | 是否自动生成图片索引(仅商业版支持) | |
|
||||||
| chunkSize | 预估块大小 | |
|
| chunkSettingMode | 分块参数模式。auto: 系统默认参数; custom: 手动指定参数 | |
|
||||||
| chunkSplitter | 自定义最高优先分割符号 | |
|
| chunkSplitMode | 分块拆分模式。size: 按长度拆分; char: 按字符拆分。chunkSettingMode=auto时不生效。 | |
|
||||||
|
| chunkSize | 分块大小,默认 1500。chunkSettingMode=auto时不生效。 | |
|
||||||
|
| indexSize | 索引大小,默认 512,必须小于索引模型最大token。chunkSettingMode=auto时不生效。 | |
|
||||||
|
| chunkSplitter | 自定义最高优先分割符号,除非超出文件处理最大上下文,否则不会进行进一步拆分。chunkSettingMode=auto时不生效。 | |
|
||||||
| qaPrompt | qa拆分提示词 | |
|
| qaPrompt | qa拆分提示词 | |
|
||||||
| tags | 集合标签(字符串数组) | |
|
| tags | 集合标签(字符串数组) | |
|
||||||
| createTime | 文件创建时间(Date / String) | |
|
| createTime | 文件创建时间(Date / String) | |
|
||||||
@@ -389,9 +390,8 @@ curl --location --request POST 'http://localhost:3000/api/core/dataset/collectio
|
|||||||
"name":"测试训练",
|
"name":"测试训练",
|
||||||
|
|
||||||
"trainingType": "qa",
|
"trainingType": "qa",
|
||||||
"chunkSize":8000,
|
"chunkSettingMode": "auto",
|
||||||
"chunkSplitter":"",
|
"qaPrompt":"",
|
||||||
"qaPrompt":"11",
|
|
||||||
|
|
||||||
"metadata":{}
|
"metadata":{}
|
||||||
}'
|
}'
|
||||||
@@ -409,10 +409,6 @@ curl --location --request POST 'http://localhost:3000/api/core/dataset/collectio
|
|||||||
- parentId: 父级ID,不填则默认为根目录
|
- parentId: 父级ID,不填则默认为根目录
|
||||||
- name: 集合名称(必填)
|
- name: 集合名称(必填)
|
||||||
- metadata: 元数据(暂时没啥用)
|
- metadata: 元数据(暂时没啥用)
|
||||||
- trainingType: 训练模式(必填)
|
|
||||||
- chunkSize: 每个 chunk 的长度(可选). chunk模式:100~3000; qa模式: 4000~模型最大token(16k模型通常建议不超过10000)
|
|
||||||
- chunkSplitter: 自定义最高优先分割符号(可选)
|
|
||||||
- qaPrompt: qa拆分自定义提示词(可选)
|
|
||||||
{{% /alert %}}
|
{{% /alert %}}
|
||||||
|
|
||||||
{{< /markdownify >}}
|
{{< /markdownify >}}
|
||||||
@@ -462,8 +458,7 @@ curl --location --request POST 'http://localhost:3000/api/core/dataset/collectio
|
|||||||
"parentId": null,
|
"parentId": null,
|
||||||
|
|
||||||
"trainingType": "chunk",
|
"trainingType": "chunk",
|
||||||
"chunkSize":512,
|
"chunkSettingMode": "auto",
|
||||||
"chunkSplitter":"",
|
|
||||||
"qaPrompt":"",
|
"qaPrompt":"",
|
||||||
|
|
||||||
"metadata":{
|
"metadata":{
|
||||||
@@ -483,10 +478,6 @@ curl --location --request POST 'http://localhost:3000/api/core/dataset/collectio
|
|||||||
- datasetId: 知识库的ID(必填)
|
- datasetId: 知识库的ID(必填)
|
||||||
- parentId: 父级ID,不填则默认为根目录
|
- parentId: 父级ID,不填则默认为根目录
|
||||||
- metadata.webPageSelector: 网页选择器,用于指定网页中的哪个元素作为文本(可选)
|
- metadata.webPageSelector: 网页选择器,用于指定网页中的哪个元素作为文本(可选)
|
||||||
- trainingType:训练模式(必填)
|
|
||||||
- chunkSize: 每个 chunk 的长度(可选). chunk模式:100~3000; qa模式: 4000~模型最大token(16k模型通常建议不超过10000)
|
|
||||||
- chunkSplitter: 自定义最高优先分割符号(可选)
|
|
||||||
- qaPrompt: qa拆分自定义提示词(可选)
|
|
||||||
{{% /alert %}}
|
{{% /alert %}}
|
||||||
|
|
||||||
{{< /markdownify >}}
|
{{< /markdownify >}}
|
||||||
@@ -545,13 +536,7 @@ curl --location --request POST 'http://localhost:3000/api/core/dataset/collectio
|
|||||||
|
|
||||||
{{% alert icon=" " context="success" %}}
|
{{% alert icon=" " context="success" %}}
|
||||||
- file: 文件
|
- file: 文件
|
||||||
- data: 知识库相关信息(json序列化后传入)
|
- data: 知识库相关信息(json序列化后传入),参数说明见上方“通用创建参数说明”
|
||||||
- datasetId: 知识库的ID(必填)
|
|
||||||
- parentId: 父级ID,不填则默认为根目录
|
|
||||||
- trainingType:训练模式(必填)
|
|
||||||
- chunkSize: 每个 chunk 的长度(可选). chunk模式:100~3000; qa模式: 4000~模型最大token(16k模型通常建议不超过10000)
|
|
||||||
- chunkSplitter: 自定义最高优先分割符号(可选)
|
|
||||||
- qaPrompt: qa拆分自定义提示词(可选)
|
|
||||||
{{% /alert %}}
|
{{% /alert %}}
|
||||||
|
|
||||||
{{< /markdownify >}}
|
{{< /markdownify >}}
|
||||||
|
|||||||
44
docSite/content/zh-cn/docs/development/upgrading/492.md
Normal file
44
docSite/content/zh-cn/docs/development/upgrading/492.md
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
title: 'V4.9.2(进行中)'
|
||||||
|
description: 'FastGPT V4.9.2 更新说明'
|
||||||
|
icon: 'upgrade'
|
||||||
|
draft: false
|
||||||
|
toc: true
|
||||||
|
weight: 799
|
||||||
|
---
|
||||||
|
|
||||||
|
## 重要提示
|
||||||
|
|
||||||
|
- 知识库导入数据 API 变更,增加`chunkSettingMode`,`chunkSplitMode`,`indexSize`可选参数,具体可参考 [知识库导入数据 API](/docs/development/openapi/dataset) 文档。
|
||||||
|
|
||||||
|
|
||||||
|
## 🚀 新增内容
|
||||||
|
|
||||||
|
1. 知识库分块优化:支持单独配置分块大小和索引大小,允许进行超大分块,以更大的输入 Tokens 换取完整分块。
|
||||||
|
2. 知识库分块增加自定义分隔符预设值,同时支持自定义换行符分割。
|
||||||
|
3. 外部变量改名:自定义变量。 并且支持在测试时调试,在分享链接中,该变量直接隐藏。
|
||||||
|
4. 集合同步时,支持同步修改标题。
|
||||||
|
5. 团队成员管理重构,抽离主流 IM SSO(企微、飞书、钉钉),并支持通过自定义 SSO 接入 FastGPT。同时完善与外部系统的成员同步。
|
||||||
|
|
||||||
|
## ⚙️ 优化
|
||||||
|
|
||||||
|
1. 导出对话日志时,支持导出成员名。
|
||||||
|
2. 邀请链接交互。
|
||||||
|
3. 无 SSL 证书时复制失败,会提示弹窗用于手动复制。
|
||||||
|
4. FastGPT 未内置 ai proxy 渠道时,也能正常展示其名称。
|
||||||
|
5. 升级 nextjs 版本至 14.2.25。
|
||||||
|
6. 工作流节点数组字符串类型,自动适配 string 输入。
|
||||||
|
7. 工作流节点数组类型,自动进行 JSON parse 解析 string 输入。
|
||||||
|
8. AI proxy 日志优化,去除重试失败的日志,仅保留最后一份错误日志。
|
||||||
|
9. 分块算法小调整:
|
||||||
|
* 跨处理符号之间连续性更强。
|
||||||
|
* 代码块分割时,用 LLM 模型上下文作为分块大小,尽可能保证代码块完整性。
|
||||||
|
* 表格分割时,用 LLM 模型上下文作为分块大小,尽可能保证表格完整性。
|
||||||
|
|
||||||
|
## 🐛 修复
|
||||||
|
|
||||||
|
1. 飞书和语雀知识库无法同步。
|
||||||
|
2. 渠道测试时,如果配置了模型自定义请求地址,会走自定义请求地址,而不是渠道请求地址。
|
||||||
|
3. 语音识别模型测试未启用的模型时,无法正常测试。
|
||||||
|
4. 管理员配置系统插件时,如果插件包含其他系统应用,无法正常鉴权。
|
||||||
|
5. 移除 TTS 自定义请求地址时,必须需要填 requestAuth 字段。
|
||||||
@@ -124,6 +124,7 @@ curl --location --request GET '{{baseURL}}/v1/file/content?id=xx' \
|
|||||||
"success": true,
|
"success": true,
|
||||||
"message": "",
|
"message": "",
|
||||||
"data": {
|
"data": {
|
||||||
|
"title": "文档标题",
|
||||||
"content": "FastGPT 是一个基于 LLM 大语言模型的知识库问答系统,提供开箱即用的数据处理、模型调用等能力。同时可以通过 Flow 可视化进行工作流编排,从而实现复杂的问答场景!\n",
|
"content": "FastGPT 是一个基于 LLM 大语言模型的知识库问答系统,提供开箱即用的数据处理、模型调用等能力。同时可以通过 Flow 可视化进行工作流编排,从而实现复杂的问答场景!\n",
|
||||||
"previewUrl": "xxxx"
|
"previewUrl": "xxxx"
|
||||||
}
|
}
|
||||||
@@ -131,10 +132,13 @@ curl --location --request GET '{{baseURL}}/v1/file/content?id=xx' \
|
|||||||
```
|
```
|
||||||
|
|
||||||
{{% alert icon=" " context="success" %}}
|
{{% alert icon=" " context="success" %}}
|
||||||
二选一返回,如果同时返回则 content 优先级更高。
|
|
||||||
|
|
||||||
|
- title - 文件标题。
|
||||||
- content - 文件内容,直接拿来用。
|
- content - 文件内容,直接拿来用。
|
||||||
- previewUrl - 文件链接,系统会请求该地址获取文件内容。
|
- previewUrl - 文件链接,系统会请求该地址获取文件内容。
|
||||||
|
|
||||||
|
`content`和`previewUrl`二选一返回,如果同时返回则 `content` 优先级更高,返回 `previewUrl`时,则会访问该链接进行文档内容读取。
|
||||||
|
|
||||||
{{% /alert %}}
|
{{% /alert %}}
|
||||||
|
|
||||||
{{< /markdownify >}}
|
{{< /markdownify >}}
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
|
import { defaultMaxChunkSize } from '../../core/dataset/training/utils';
|
||||||
import { getErrText } from '../error/utils';
|
import { getErrText } from '../error/utils';
|
||||||
import { replaceRegChars } from './tools';
|
|
||||||
|
|
||||||
export const CUSTOM_SPLIT_SIGN = '-----CUSTOM_SPLIT_SIGN-----';
|
export const CUSTOM_SPLIT_SIGN = '-----CUSTOM_SPLIT_SIGN-----';
|
||||||
|
|
||||||
type SplitProps = {
|
type SplitProps = {
|
||||||
text: string;
|
text: string;
|
||||||
chunkLen: number;
|
chunkSize: number;
|
||||||
|
maxSize?: number;
|
||||||
overlapRatio?: number;
|
overlapRatio?: number;
|
||||||
customReg?: string[];
|
customReg?: string[];
|
||||||
};
|
};
|
||||||
export type TextSplitProps = Omit<SplitProps, 'text' | 'chunkLen'> & {
|
export type TextSplitProps = Omit<SplitProps, 'text' | 'chunkSize'> & {
|
||||||
chunkLen?: number;
|
chunkSize?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type SplitResponse = {
|
type SplitResponse = {
|
||||||
@@ -56,7 +57,7 @@ const strIsMdTable = (str: string) => {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
const markdownTableSplit = (props: SplitProps): SplitResponse => {
|
const markdownTableSplit = (props: SplitProps): SplitResponse => {
|
||||||
let { text = '', chunkLen } = props;
|
let { text = '', chunkSize } = props;
|
||||||
const splitText2Lines = text.split('\n');
|
const splitText2Lines = text.split('\n');
|
||||||
const header = splitText2Lines[0];
|
const header = splitText2Lines[0];
|
||||||
const headerSize = header.split('|').length - 2;
|
const headerSize = header.split('|').length - 2;
|
||||||
@@ -72,7 +73,7 @@ ${mdSplitString}
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
for (let i = 2; i < splitText2Lines.length; i++) {
|
for (let i = 2; i < splitText2Lines.length; i++) {
|
||||||
if (chunk.length + splitText2Lines[i].length > chunkLen * 1.2) {
|
if (chunk.length + splitText2Lines[i].length > chunkSize * 1.2) {
|
||||||
chunks.push(chunk);
|
chunks.push(chunk);
|
||||||
chunk = `${header}
|
chunk = `${header}
|
||||||
${mdSplitString}
|
${mdSplitString}
|
||||||
@@ -99,11 +100,17 @@ ${mdSplitString}
|
|||||||
5. 标点分割:重叠
|
5. 标点分割:重叠
|
||||||
*/
|
*/
|
||||||
const commonSplit = (props: SplitProps): SplitResponse => {
|
const commonSplit = (props: SplitProps): SplitResponse => {
|
||||||
let { text = '', chunkLen, overlapRatio = 0.15, customReg = [] } = props;
|
let {
|
||||||
|
text = '',
|
||||||
|
chunkSize,
|
||||||
|
maxSize = defaultMaxChunkSize,
|
||||||
|
overlapRatio = 0.15,
|
||||||
|
customReg = []
|
||||||
|
} = props;
|
||||||
|
|
||||||
const splitMarker = 'SPLIT_HERE_SPLIT_HERE';
|
const splitMarker = 'SPLIT_HERE_SPLIT_HERE';
|
||||||
const codeBlockMarker = 'CODE_BLOCK_LINE_MARKER';
|
const codeBlockMarker = 'CODE_BLOCK_LINE_MARKER';
|
||||||
const overlapLen = Math.round(chunkLen * overlapRatio);
|
const overlapLen = Math.round(chunkSize * overlapRatio);
|
||||||
|
|
||||||
// replace code block all \n to codeBlockMarker
|
// replace code block all \n to codeBlockMarker
|
||||||
text = text.replace(/(```[\s\S]*?```|~~~[\s\S]*?~~~)/g, function (match) {
|
text = text.replace(/(```[\s\S]*?```|~~~[\s\S]*?~~~)/g, function (match) {
|
||||||
@@ -115,34 +122,38 @@ const commonSplit = (props: SplitProps): SplitResponse => {
|
|||||||
// The larger maxLen is, the next sentence is less likely to trigger splitting
|
// The larger maxLen is, the next sentence is less likely to trigger splitting
|
||||||
const markdownIndex = 4;
|
const markdownIndex = 4;
|
||||||
const forbidOverlapIndex = 8;
|
const forbidOverlapIndex = 8;
|
||||||
const stepReges: { reg: RegExp; maxLen: number }[] = [
|
|
||||||
...customReg.map((text) => ({
|
|
||||||
reg: new RegExp(`(${replaceRegChars(text)})`, 'g'),
|
|
||||||
maxLen: chunkLen * 1.4
|
|
||||||
})),
|
|
||||||
{ reg: /^(#\s[^\n]+\n)/gm, maxLen: chunkLen * 1.2 },
|
|
||||||
{ reg: /^(##\s[^\n]+\n)/gm, maxLen: chunkLen * 1.4 },
|
|
||||||
{ reg: /^(###\s[^\n]+\n)/gm, maxLen: chunkLen * 1.6 },
|
|
||||||
{ reg: /^(####\s[^\n]+\n)/gm, maxLen: chunkLen * 1.8 },
|
|
||||||
{ reg: /^(#####\s[^\n]+\n)/gm, maxLen: chunkLen * 1.8 },
|
|
||||||
|
|
||||||
{ reg: /([\n]([`~]))/g, maxLen: chunkLen * 4 }, // code block
|
const stepReges: { reg: RegExp | string; maxLen: number }[] = [
|
||||||
{ reg: /([\n](?=\s*[0-9]+\.))/g, maxLen: chunkLen * 2 }, // 增大块,尽可能保证它是一个完整的段落。 (?![\*\-|>`0-9]): markdown special char
|
...customReg.map((text) => ({
|
||||||
{ reg: /(\n{2,})/g, maxLen: chunkLen * 1.6 },
|
reg: text.replaceAll('\\n', '\n'),
|
||||||
{ reg: /([\n])/g, maxLen: chunkLen * 1.2 },
|
maxLen: chunkSize
|
||||||
|
})),
|
||||||
|
{ reg: /^(#\s[^\n]+\n)/gm, maxLen: chunkSize },
|
||||||
|
{ reg: /^(##\s[^\n]+\n)/gm, maxLen: chunkSize },
|
||||||
|
{ reg: /^(###\s[^\n]+\n)/gm, maxLen: chunkSize },
|
||||||
|
{ reg: /^(####\s[^\n]+\n)/gm, maxLen: chunkSize },
|
||||||
|
{ reg: /^(#####\s[^\n]+\n)/gm, maxLen: chunkSize },
|
||||||
|
|
||||||
|
{ reg: /([\n](```[\s\S]*?```|~~~[\s\S]*?~~~))/g, maxLen: maxSize }, // code block
|
||||||
|
{
|
||||||
|
reg: /(\n\|(?:(?:[^\n|]+\|){1,})\n\|(?:[:\-\s]+\|){1,}\n(?:\|(?:[^\n|]+\|)*\n)*)/g,
|
||||||
|
maxLen: maxSize
|
||||||
|
}, // Table 尽可能保证完整性
|
||||||
|
{ reg: /(\n{2,})/g, maxLen: chunkSize },
|
||||||
|
{ reg: /([\n])/g, maxLen: chunkSize },
|
||||||
// ------ There's no overlap on the top
|
// ------ There's no overlap on the top
|
||||||
{ reg: /([。]|([a-zA-Z])\.\s)/g, maxLen: chunkLen * 1.2 },
|
{ reg: /([。]|([a-zA-Z])\.\s)/g, maxLen: chunkSize },
|
||||||
{ reg: /([!]|!\s)/g, maxLen: chunkLen * 1.2 },
|
{ reg: /([!]|!\s)/g, maxLen: chunkSize },
|
||||||
{ reg: /([?]|\?\s)/g, maxLen: chunkLen * 1.4 },
|
{ reg: /([?]|\?\s)/g, maxLen: chunkSize },
|
||||||
{ reg: /([;]|;\s)/g, maxLen: chunkLen * 1.6 },
|
{ reg: /([;]|;\s)/g, maxLen: chunkSize },
|
||||||
{ reg: /([,]|,\s)/g, maxLen: chunkLen * 2 }
|
{ reg: /([,]|,\s)/g, maxLen: chunkSize }
|
||||||
];
|
];
|
||||||
|
|
||||||
const customRegLen = customReg.length;
|
const customRegLen = customReg.length;
|
||||||
const checkIsCustomStep = (step: number) => step < customRegLen;
|
const checkIsCustomStep = (step: number) => step < customRegLen;
|
||||||
const checkIsMarkdownSplit = (step: number) =>
|
const checkIsMarkdownSplit = (step: number) =>
|
||||||
step >= customRegLen && step <= markdownIndex + customRegLen;
|
step >= customRegLen && step <= markdownIndex + customRegLen;
|
||||||
+customReg.length;
|
|
||||||
const checkForbidOverlap = (step: number) => step <= forbidOverlapIndex + customRegLen;
|
const checkForbidOverlap = (step: number) => step <= forbidOverlapIndex + customRegLen;
|
||||||
|
|
||||||
// if use markdown title split, Separate record title
|
// if use markdown title split, Separate record title
|
||||||
@@ -151,7 +162,8 @@ const commonSplit = (props: SplitProps): SplitResponse => {
|
|||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
text,
|
text,
|
||||||
title: ''
|
title: '',
|
||||||
|
chunkMaxSize: chunkSize
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -159,27 +171,46 @@ const commonSplit = (props: SplitProps): SplitResponse => {
|
|||||||
const isCustomStep = checkIsCustomStep(step);
|
const isCustomStep = checkIsCustomStep(step);
|
||||||
const isMarkdownSplit = checkIsMarkdownSplit(step);
|
const isMarkdownSplit = checkIsMarkdownSplit(step);
|
||||||
|
|
||||||
const { reg } = stepReges[step];
|
const { reg, maxLen } = stepReges[step];
|
||||||
|
|
||||||
const splitTexts = text
|
const replaceText = (() => {
|
||||||
.replace(
|
if (typeof reg === 'string') {
|
||||||
|
let tmpText = text;
|
||||||
|
reg.split('|').forEach((itemReg) => {
|
||||||
|
tmpText = tmpText.replaceAll(
|
||||||
|
itemReg,
|
||||||
|
(() => {
|
||||||
|
if (isCustomStep) return splitMarker;
|
||||||
|
if (isMarkdownSplit) return `${splitMarker}$1`;
|
||||||
|
return `$1${splitMarker}`;
|
||||||
|
})()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
return tmpText;
|
||||||
|
}
|
||||||
|
|
||||||
|
return text.replace(
|
||||||
reg,
|
reg,
|
||||||
(() => {
|
(() => {
|
||||||
if (isCustomStep) return splitMarker;
|
if (isCustomStep) return splitMarker;
|
||||||
if (isMarkdownSplit) return `${splitMarker}$1`;
|
if (isMarkdownSplit) return `${splitMarker}$1`;
|
||||||
return `$1${splitMarker}`;
|
return `$1${splitMarker}`;
|
||||||
})()
|
})()
|
||||||
)
|
);
|
||||||
.split(`${splitMarker}`)
|
})();
|
||||||
.filter((part) => part.trim());
|
|
||||||
|
const splitTexts = replaceText.split(splitMarker).filter((part) => part.trim());
|
||||||
|
|
||||||
return splitTexts
|
return splitTexts
|
||||||
.map((text) => {
|
.map((text) => {
|
||||||
const matchTitle = isMarkdownSplit ? text.match(reg)?.[0] || '' : '';
|
const matchTitle = isMarkdownSplit ? text.match(reg)?.[0] || '' : '';
|
||||||
|
// 如果一个分块没有匹配到,则使用默认块大小,否则使用最大块大小
|
||||||
|
const chunkMaxSize = text.match(reg) === null ? chunkSize : maxLen;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
text: isMarkdownSplit ? text.replace(matchTitle, '') : text,
|
text: isMarkdownSplit ? text.replace(matchTitle, '') : text,
|
||||||
title: matchTitle
|
title: matchTitle,
|
||||||
|
chunkMaxSize
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter((item) => !!item.title || !!item.text?.trim());
|
.filter((item) => !!item.title || !!item.text?.trim());
|
||||||
@@ -188,7 +219,7 @@ const commonSplit = (props: SplitProps): SplitResponse => {
|
|||||||
/* Gets the overlap at the end of a text as the beginning of the next block */
|
/* Gets the overlap at the end of a text as the beginning of the next block */
|
||||||
const getOneTextOverlapText = ({ text, step }: { text: string; step: number }): string => {
|
const getOneTextOverlapText = ({ text, step }: { text: string; step: number }): string => {
|
||||||
const forbidOverlap = checkForbidOverlap(step);
|
const forbidOverlap = checkForbidOverlap(step);
|
||||||
const maxOverlapLen = chunkLen * 0.4;
|
const maxOverlapLen = chunkSize * 0.4;
|
||||||
|
|
||||||
// step >= stepReges.length: Do not overlap incomplete sentences
|
// step >= stepReges.length: Do not overlap incomplete sentences
|
||||||
if (forbidOverlap || overlapLen === 0 || step >= stepReges.length) return '';
|
if (forbidOverlap || overlapLen === 0 || step >= stepReges.length) return '';
|
||||||
@@ -229,15 +260,15 @@ const commonSplit = (props: SplitProps): SplitResponse => {
|
|||||||
const isCustomStep = checkIsCustomStep(step);
|
const isCustomStep = checkIsCustomStep(step);
|
||||||
const forbidConcat = isCustomStep; // forbid=true时候,lastText肯定为空
|
const forbidConcat = isCustomStep; // forbid=true时候,lastText肯定为空
|
||||||
|
|
||||||
// oversize
|
// Over step
|
||||||
if (step >= stepReges.length) {
|
if (step >= stepReges.length) {
|
||||||
if (text.length < chunkLen * 3) {
|
if (text.length < maxSize) {
|
||||||
return [text];
|
return [text];
|
||||||
}
|
}
|
||||||
// use slice-chunkLen to split text
|
// use slice-chunkSize to split text
|
||||||
const chunks: string[] = [];
|
const chunks: string[] = [];
|
||||||
for (let i = 0; i < text.length; i += chunkLen - overlapLen) {
|
for (let i = 0; i < text.length; i += chunkSize - overlapLen) {
|
||||||
chunks.push(text.slice(i, i + chunkLen));
|
chunks.push(text.slice(i, i + chunkSize));
|
||||||
}
|
}
|
||||||
return chunks;
|
return chunks;
|
||||||
}
|
}
|
||||||
@@ -245,19 +276,18 @@ const commonSplit = (props: SplitProps): SplitResponse => {
|
|||||||
// split text by special char
|
// split text by special char
|
||||||
const splitTexts = getSplitTexts({ text, step });
|
const splitTexts = getSplitTexts({ text, step });
|
||||||
|
|
||||||
const maxLen = splitTexts.length > 1 ? stepReges[step].maxLen : chunkLen;
|
|
||||||
const minChunkLen = chunkLen * 0.7;
|
|
||||||
|
|
||||||
const chunks: string[] = [];
|
const chunks: string[] = [];
|
||||||
for (let i = 0; i < splitTexts.length; i++) {
|
for (let i = 0; i < splitTexts.length; i++) {
|
||||||
const item = splitTexts[i];
|
const item = splitTexts[i];
|
||||||
|
|
||||||
|
const maxLen = item.chunkMaxSize; // 当前块最大长度
|
||||||
|
|
||||||
const lastTextLen = lastText.length;
|
const lastTextLen = lastText.length;
|
||||||
const currentText = item.text;
|
const currentText = item.text;
|
||||||
const newText = lastText + currentText;
|
const newText = lastText + currentText;
|
||||||
const newTextLen = newText.length;
|
const newTextLen = newText.length;
|
||||||
|
|
||||||
// Markdown 模式下,会强制向下拆分最小块,并再最后一个标题时候,给小块都补充上所有标题(包含父级标题)
|
// Markdown 模式下,会强制向下拆分最小块,并再最后一个标题深度,给小块都补充上所有标题(包含父级标题)
|
||||||
if (isMarkdownStep) {
|
if (isMarkdownStep) {
|
||||||
// split new Text, split chunks must will greater 1 (small lastText)
|
// split new Text, split chunks must will greater 1 (small lastText)
|
||||||
const innerChunks = splitTextRecursively({
|
const innerChunks = splitTextRecursively({
|
||||||
@@ -267,11 +297,13 @@ const commonSplit = (props: SplitProps): SplitResponse => {
|
|||||||
parentTitle: parentTitle + item.title
|
parentTitle: parentTitle + item.title
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 只有标题,没有内容。
|
||||||
if (innerChunks.length === 0) {
|
if (innerChunks.length === 0) {
|
||||||
chunks.push(`${parentTitle}${item.title}`);
|
chunks.push(`${parentTitle}${item.title}`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 在合并最深级标题时,需要补充标题
|
||||||
chunks.push(
|
chunks.push(
|
||||||
...innerChunks.map(
|
...innerChunks.map(
|
||||||
(chunk) =>
|
(chunk) =>
|
||||||
@@ -282,9 +314,18 @@ const commonSplit = (props: SplitProps): SplitResponse => {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// newText is too large(now, The lastText must be smaller than chunkLen)
|
// newText is too large(now, The lastText must be smaller than chunkSize)
|
||||||
if (newTextLen > maxLen) {
|
if (newTextLen > maxLen) {
|
||||||
// lastText greater minChunkLen, direct push it to chunks, not add to next chunk. (large lastText)
|
const minChunkLen = maxLen * 0.8; // 当前块最小长度
|
||||||
|
const maxChunkLen = maxLen * 1.2; // 当前块最大长度
|
||||||
|
|
||||||
|
// 新文本没有非常大,直接认为它是一个新的块
|
||||||
|
if (newTextLen < maxChunkLen) {
|
||||||
|
chunks.push(newText);
|
||||||
|
lastText = getOneTextOverlapText({ text: newText, step }); // next chunk will start with overlayText
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 上一个文本块已经挺大的,单独做一个块
|
||||||
if (lastTextLen > minChunkLen) {
|
if (lastTextLen > minChunkLen) {
|
||||||
chunks.push(lastText);
|
chunks.push(lastText);
|
||||||
|
|
||||||
@@ -294,13 +335,13 @@ const commonSplit = (props: SplitProps): SplitResponse => {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 说明是新的文本块比较大,需要进一步拆分
|
// 说明是当前文本比较大,需要进一步拆分
|
||||||
|
|
||||||
// split new Text, split chunks must will greater 1 (small lastText)
|
// 把新的文本块进行一个拆分,并追加到 latestText 中
|
||||||
const innerChunks = splitTextRecursively({
|
const innerChunks = splitTextRecursively({
|
||||||
text: newText,
|
text: currentText,
|
||||||
step: step + 1,
|
step: step + 1,
|
||||||
lastText: '',
|
lastText,
|
||||||
parentTitle: parentTitle + item.title
|
parentTitle: parentTitle + item.title
|
||||||
});
|
});
|
||||||
const lastChunk = innerChunks[innerChunks.length - 1];
|
const lastChunk = innerChunks[innerChunks.length - 1];
|
||||||
@@ -328,16 +369,16 @@ const commonSplit = (props: SplitProps): SplitResponse => {
|
|||||||
|
|
||||||
// Not overlap
|
// Not overlap
|
||||||
if (forbidConcat) {
|
if (forbidConcat) {
|
||||||
chunks.push(item.text);
|
chunks.push(currentText);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastText += item.text;
|
lastText = newText;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the last chunk is independent, it needs to be push chunks. */
|
/* If the last chunk is independent, it needs to be push chunks. */
|
||||||
if (lastText && chunks[chunks.length - 1] && !chunks[chunks.length - 1].endsWith(lastText)) {
|
if (lastText && chunks[chunks.length - 1] && !chunks[chunks.length - 1].endsWith(lastText)) {
|
||||||
if (lastText.length < chunkLen * 0.4) {
|
if (lastText.length < chunkSize * 0.4) {
|
||||||
chunks[chunks.length - 1] = chunks[chunks.length - 1] + lastText;
|
chunks[chunks.length - 1] = chunks[chunks.length - 1] + lastText;
|
||||||
} else {
|
} else {
|
||||||
chunks.push(lastText);
|
chunks.push(lastText);
|
||||||
@@ -371,9 +412,9 @@ const commonSplit = (props: SplitProps): SplitResponse => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* text split into chunks
|
* text split into chunks
|
||||||
* chunkLen - one chunk len. max: 3500
|
* chunkSize - one chunk len. max: 3500
|
||||||
* overlapLen - The size of the before and after Text
|
* overlapLen - The size of the before and after Text
|
||||||
* chunkLen > overlapLen
|
* chunkSize > overlapLen
|
||||||
* markdown
|
* markdown
|
||||||
*/
|
*/
|
||||||
export const splitText2Chunks = (props: SplitProps): SplitResponse => {
|
export const splitText2Chunks = (props: SplitProps): SplitResponse => {
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export const replaceSensitiveText = (text: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Make sure the first letter is definitely lowercase */
|
/* Make sure the first letter is definitely lowercase */
|
||||||
export const getNanoid = (size = 12) => {
|
export const getNanoid = (size = 16) => {
|
||||||
const firstChar = customAlphabet('abcdefghijklmnopqrstuvwxyz', 1)();
|
const firstChar = customAlphabet('abcdefghijklmnopqrstuvwxyz', 1)();
|
||||||
|
|
||||||
if (size === 1) return firstChar;
|
if (size === 1) return firstChar;
|
||||||
|
|||||||
@@ -84,11 +84,6 @@ export type FastGPTFeConfigsType = {
|
|||||||
github?: string;
|
github?: string;
|
||||||
google?: string;
|
google?: string;
|
||||||
wechat?: string;
|
wechat?: string;
|
||||||
dingtalk?: string;
|
|
||||||
wecom?: {
|
|
||||||
corpid?: string;
|
|
||||||
agentid?: string;
|
|
||||||
};
|
|
||||||
microsoft?: {
|
microsoft?: {
|
||||||
clientId?: string;
|
clientId?: string;
|
||||||
tenantId?: string;
|
tenantId?: string;
|
||||||
|
|||||||
@@ -1,54 +1,70 @@
|
|||||||
import { PromptTemplateItem } from '../type.d';
|
import { PromptTemplateItem } from '../type.d';
|
||||||
import { i18nT } from '../../../../web/i18n/utils';
|
import { i18nT } from '../../../../web/i18n/utils';
|
||||||
|
import { getPromptByVersion } from './utils';
|
||||||
|
|
||||||
export const Prompt_QuoteTemplateList: PromptTemplateItem[] = [
|
export const Prompt_QuoteTemplateList: PromptTemplateItem[] = [
|
||||||
{
|
{
|
||||||
title: i18nT('app:template.standard_template'),
|
title: i18nT('app:template.standard_template'),
|
||||||
desc: i18nT('app:template.standard_template_des'),
|
desc: i18nT('app:template.standard_template_des'),
|
||||||
value: `{
|
value: {
|
||||||
|
['4.9.2']: `{
|
||||||
"sourceName": "{{source}}",
|
"sourceName": "{{source}}",
|
||||||
"updateTime": "{{updateTime}}",
|
"updateTime": "{{updateTime}}",
|
||||||
"content": "{{q}}\n{{a}}"
|
"content": "{{q}}\n{{a}}"
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18nT('app:template.qa_template'),
|
title: i18nT('app:template.qa_template'),
|
||||||
desc: i18nT('app:template.qa_template_des'),
|
desc: i18nT('app:template.qa_template_des'),
|
||||||
value: `<Question>
|
value: {
|
||||||
|
['4.9.2']: `<Question>
|
||||||
{{q}}
|
{{q}}
|
||||||
</Question>
|
</Question>
|
||||||
<Answer>
|
<Answer>
|
||||||
{{a}}
|
{{a}}
|
||||||
</Answer>`
|
</Answer>`
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18nT('app:template.standard_strict'),
|
title: i18nT('app:template.standard_strict'),
|
||||||
desc: i18nT('app:template.standard_strict_des'),
|
desc: i18nT('app:template.standard_strict_des'),
|
||||||
value: `{
|
value: {
|
||||||
|
['4.9.2']: `{
|
||||||
"sourceName": "{{source}}",
|
"sourceName": "{{source}}",
|
||||||
"updateTime": "{{updateTime}}",
|
"updateTime": "{{updateTime}}",
|
||||||
"content": "{{q}}\n{{a}}"
|
"content": "{{q}}\n{{a}}"
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18nT('app:template.hard_strict'),
|
title: i18nT('app:template.hard_strict'),
|
||||||
desc: i18nT('app:template.hard_strict_des'),
|
desc: i18nT('app:template.hard_strict_des'),
|
||||||
value: `<Question>
|
value: {
|
||||||
|
['4.9.2']: `<Question>
|
||||||
{{q}}
|
{{q}}
|
||||||
</Question>
|
</Question>
|
||||||
<Answer>
|
<Answer>
|
||||||
{{a}}
|
{{a}}
|
||||||
</Answer>`
|
</Answer>`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const getQuoteTemplate = (version?: string) => {
|
||||||
|
const defaultTemplate = Prompt_QuoteTemplateList[0].value;
|
||||||
|
|
||||||
|
return getPromptByVersion(version, defaultTemplate);
|
||||||
|
};
|
||||||
|
|
||||||
export const Prompt_userQuotePromptList: PromptTemplateItem[] = [
|
export const Prompt_userQuotePromptList: PromptTemplateItem[] = [
|
||||||
{
|
{
|
||||||
title: i18nT('app:template.standard_template'),
|
title: i18nT('app:template.standard_template'),
|
||||||
desc: '',
|
desc: '',
|
||||||
value: `使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
|
value: {
|
||||||
|
['4.9.2']: `使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
|
||||||
|
|
||||||
<Reference>
|
<Reference>
|
||||||
{{quote}}
|
{{quote}}
|
||||||
@@ -62,11 +78,13 @@ export const Prompt_userQuotePromptList: PromptTemplateItem[] = [
|
|||||||
- 使用与问题相同的语言回答。
|
- 使用与问题相同的语言回答。
|
||||||
|
|
||||||
问题:"""{{question}}"""`
|
问题:"""{{question}}"""`
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18nT('app:template.qa_template'),
|
title: i18nT('app:template.qa_template'),
|
||||||
desc: '',
|
desc: '',
|
||||||
value: `使用 <QA></QA> 标记中的问答对进行回答。
|
value: {
|
||||||
|
['4.9.2']: `使用 <QA></QA> 标记中的问答对进行回答。
|
||||||
|
|
||||||
<QA>
|
<QA>
|
||||||
{{quote}}
|
{{quote}}
|
||||||
@@ -79,11 +97,13 @@ export const Prompt_userQuotePromptList: PromptTemplateItem[] = [
|
|||||||
- 避免提及你是从 QA 获取的知识,只需要回复答案。
|
- 避免提及你是从 QA 获取的知识,只需要回复答案。
|
||||||
|
|
||||||
问题:"""{{question}}"""`
|
问题:"""{{question}}"""`
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18nT('app:template.standard_strict'),
|
title: i18nT('app:template.standard_strict'),
|
||||||
desc: '',
|
desc: '',
|
||||||
value: `忘记你已有的知识,仅使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
|
value: {
|
||||||
|
['4.9.2']: `忘记你已有的知识,仅使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
|
||||||
|
|
||||||
<Reference>
|
<Reference>
|
||||||
{{quote}}
|
{{quote}}
|
||||||
@@ -101,11 +121,13 @@ export const Prompt_userQuotePromptList: PromptTemplateItem[] = [
|
|||||||
- 使用与问题相同的语言回答。
|
- 使用与问题相同的语言回答。
|
||||||
|
|
||||||
问题:"""{{question}}"""`
|
问题:"""{{question}}"""`
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18nT('app:template.hard_strict'),
|
title: i18nT('app:template.hard_strict'),
|
||||||
desc: '',
|
desc: '',
|
||||||
value: `忘记你已有的知识,仅使用 <QA></QA> 标记中的问答对进行回答。
|
value: {
|
||||||
|
['4.9.2']: `忘记你已有的知识,仅使用 <QA></QA> 标记中的问答对进行回答。
|
||||||
|
|
||||||
<QA>
|
<QA>
|
||||||
{{quote}}
|
{{quote}}
|
||||||
@@ -126,6 +148,7 @@ export const Prompt_userQuotePromptList: PromptTemplateItem[] = [
|
|||||||
- 使用与问题相同的语言回答。
|
- 使用与问题相同的语言回答。
|
||||||
|
|
||||||
问题:"""{{question}}"""`
|
问题:"""{{question}}"""`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -133,7 +156,8 @@ export const Prompt_systemQuotePromptList: PromptTemplateItem[] = [
|
|||||||
{
|
{
|
||||||
title: i18nT('app:template.standard_template'),
|
title: i18nT('app:template.standard_template'),
|
||||||
desc: '',
|
desc: '',
|
||||||
value: `使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
|
value: {
|
||||||
|
['4.9.2']: `使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
|
||||||
|
|
||||||
<Reference>
|
<Reference>
|
||||||
{{quote}}
|
{{quote}}
|
||||||
@@ -145,11 +169,13 @@ export const Prompt_systemQuotePromptList: PromptTemplateItem[] = [
|
|||||||
- 保持答案与 <Reference></Reference> 中描述的一致。
|
- 保持答案与 <Reference></Reference> 中描述的一致。
|
||||||
- 使用 Markdown 语法优化回答格式。
|
- 使用 Markdown 语法优化回答格式。
|
||||||
- 使用与问题相同的语言回答。`
|
- 使用与问题相同的语言回答。`
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18nT('app:template.qa_template'),
|
title: i18nT('app:template.qa_template'),
|
||||||
desc: '',
|
desc: '',
|
||||||
value: `使用 <QA></QA> 标记中的问答对进行回答。
|
value: {
|
||||||
|
['4.9.2']: `使用 <QA></QA> 标记中的问答对进行回答。
|
||||||
|
|
||||||
<QA>
|
<QA>
|
||||||
{{quote}}
|
{{quote}}
|
||||||
@@ -160,11 +186,13 @@ export const Prompt_systemQuotePromptList: PromptTemplateItem[] = [
|
|||||||
- 回答的内容应尽可能与 <答案></答案> 中的内容一致。
|
- 回答的内容应尽可能与 <答案></答案> 中的内容一致。
|
||||||
- 如果没有相关的问答对,你需要澄清。
|
- 如果没有相关的问答对,你需要澄清。
|
||||||
- 避免提及你是从 QA 获取的知识,只需要回复答案。`
|
- 避免提及你是从 QA 获取的知识,只需要回复答案。`
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18nT('app:template.standard_strict'),
|
title: i18nT('app:template.standard_strict'),
|
||||||
desc: '',
|
desc: '',
|
||||||
value: `忘记你已有的知识,仅使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
|
value: {
|
||||||
|
['4.9.2']: `忘记你已有的知识,仅使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
|
||||||
|
|
||||||
<Reference>
|
<Reference>
|
||||||
{{quote}}
|
{{quote}}
|
||||||
@@ -180,11 +208,13 @@ export const Prompt_systemQuotePromptList: PromptTemplateItem[] = [
|
|||||||
- 保持答案与 <Reference></Reference> 中描述的一致。
|
- 保持答案与 <Reference></Reference> 中描述的一致。
|
||||||
- 使用 Markdown 语法优化回答格式。
|
- 使用 Markdown 语法优化回答格式。
|
||||||
- 使用与问题相同的语言回答。`
|
- 使用与问题相同的语言回答。`
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18nT('app:template.hard_strict'),
|
title: i18nT('app:template.hard_strict'),
|
||||||
desc: '',
|
desc: '',
|
||||||
value: `忘记你已有的知识,仅使用 <QA></QA> 标记中的问答对进行回答。
|
value: {
|
||||||
|
['4.9.2']: `忘记你已有的知识,仅使用 <QA></QA> 标记中的问答对进行回答。
|
||||||
|
|
||||||
<QA>
|
<QA>
|
||||||
{{quote}}
|
{{quote}}
|
||||||
@@ -203,12 +233,28 @@ export const Prompt_systemQuotePromptList: PromptTemplateItem[] = [
|
|||||||
- 避免提及你是从 QA 获取的知识,只需要回复答案。
|
- 避免提及你是从 QA 获取的知识,只需要回复答案。
|
||||||
- 使用 Markdown 语法优化回答格式。
|
- 使用 Markdown 语法优化回答格式。
|
||||||
- 使用与问题相同的语言回答。`
|
- 使用与问题相同的语言回答。`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const getQuotePrompt = (version?: string, role: 'user' | 'system' = 'user') => {
|
||||||
|
const quotePromptTemplates =
|
||||||
|
role === 'user' ? Prompt_userQuotePromptList : Prompt_systemQuotePromptList;
|
||||||
|
|
||||||
|
const defaultTemplate = quotePromptTemplates[0].value;
|
||||||
|
|
||||||
|
return getPromptByVersion(version, defaultTemplate);
|
||||||
|
};
|
||||||
|
|
||||||
// Document quote prompt
|
// Document quote prompt
|
||||||
export const Prompt_DocumentQuote = `将 <FilesContent></FilesContent> 中的内容作为本次对话的参考:
|
export const getDocumentQuotePrompt = (version: string) => {
|
||||||
<FilesContent>
|
const promptMap = {
|
||||||
{{quote}}
|
['4.9.2']: `将 <FilesContent></FilesContent> 中的内容作为本次对话的参考:
|
||||||
</FilesContent>
|
<FilesContent>
|
||||||
`;
|
{{quote}}
|
||||||
|
</FilesContent>
|
||||||
|
`
|
||||||
|
};
|
||||||
|
|
||||||
|
return getPromptByVersion(version, promptMap);
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { getPromptByVersion } from './utils';
|
||||||
|
|
||||||
export const Prompt_AgentQA = {
|
export const Prompt_AgentQA = {
|
||||||
description: `<Context></Context> 标记中是一段文本,学习和分析它,并整理学习成果:
|
description: `<Context></Context> 标记中是一段文本,学习和分析它,并整理学习成果:
|
||||||
- 提出问题并给出每个问题的答案。
|
- 提出问题并给出每个问题的答案。
|
||||||
@@ -25,7 +27,9 @@ A2:
|
|||||||
`
|
`
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Prompt_ExtractJson = `你可以从 <对话记录></对话记录> 中提取指定 Json 信息,你仅需返回 Json 字符串,无需回答问题。
|
export const getExtractJsonPrompt = (version?: string) => {
|
||||||
|
const promptMap: Record<string, string> = {
|
||||||
|
['4.9.2']: `你可以从 <对话记录></对话记录> 中提取指定 Json 信息,你仅需返回 Json 字符串,无需回答问题。
|
||||||
<提取要求>
|
<提取要求>
|
||||||
{{description}}
|
{{description}}
|
||||||
</提取要求>
|
</提取要求>
|
||||||
@@ -44,9 +48,31 @@ export const Prompt_ExtractJson = `你可以从 <对话记录></对话记录>
|
|||||||
{{text}}
|
{{text}}
|
||||||
</对话记录>
|
</对话记录>
|
||||||
|
|
||||||
提取的 json 字符串:`;
|
提取的 json 字符串:`
|
||||||
|
};
|
||||||
|
|
||||||
export const Prompt_CQJson = `请帮我执行一个“问题分类”任务,将问题分类为以下几种类型之一:
|
return getPromptByVersion(version, promptMap);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getExtractJsonToolPrompt = (version?: string) => {
|
||||||
|
const promptMap: Record<string, string> = {
|
||||||
|
['4.9.2']: `我正在执行一个函数,需要你提供一些参数,请以 JSON 字符串格式返回这些参数,要求:
|
||||||
|
"""
|
||||||
|
- {{description}}
|
||||||
|
- 不是每个参数都是必须生成的,如果没有合适的参数值,不要生成该参数,或返回空字符串。
|
||||||
|
- 需要结合前面的对话内容,一起生成合适的参数。
|
||||||
|
"""
|
||||||
|
|
||||||
|
本次输入内容: """{{content}}"""
|
||||||
|
`
|
||||||
|
};
|
||||||
|
|
||||||
|
return getPromptByVersion(version, promptMap);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getCQPrompt = (version?: string) => {
|
||||||
|
const promptMap: Record<string, string> = {
|
||||||
|
['4.9.2']: `请帮我执行一个"问题分类"任务,将问题分类为以下几种类型之一:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
{{typeList}}
|
{{typeList}}
|
||||||
@@ -64,9 +90,13 @@ export const Prompt_CQJson = `请帮我执行一个“问题分类”任务,
|
|||||||
|
|
||||||
问题:"{{question}}"
|
问题:"{{question}}"
|
||||||
类型ID=
|
类型ID=
|
||||||
`;
|
`
|
||||||
|
};
|
||||||
|
|
||||||
export const PROMPT_QUESTION_GUIDE = `You are an AI assistant tasked with predicting the user's next question based on the conversation history. Your goal is to generate 3 potential questions that will guide the user to continue the conversation. When generating these questions, adhere to the following rules:
|
return getPromptByVersion(version, promptMap);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const QuestionGuidePrompt = `You are an AI assistant tasked with predicting the user's next question based on the conversation history. Your goal is to generate 3 potential questions that will guide the user to continue the conversation. When generating these questions, adhere to the following rules:
|
||||||
|
|
||||||
1. Use the same language as the user's last question in the conversation history.
|
1. Use the same language as the user's last question in the conversation history.
|
||||||
2. Keep each question under 20 characters in length.
|
2. Keep each question under 20 characters in length.
|
||||||
@@ -74,4 +104,5 @@ export const PROMPT_QUESTION_GUIDE = `You are an AI assistant tasked with predic
|
|||||||
Analyze the conversation history provided to you and use it as context to generate relevant and engaging follow-up questions. Your predictions should be logical extensions of the current topic or related areas that the user might be interested in exploring further.
|
Analyze the conversation history provided to you and use it as context to generate relevant and engaging follow-up questions. Your predictions should be logical extensions of the current topic or related areas that the user might be interested in exploring further.
|
||||||
|
|
||||||
Remember to maintain consistency in tone and style with the existing conversation while providing diverse options for the user to choose from. Your goal is to keep the conversation flowing naturally and help the user delve deeper into the subject matter or explore related topics.`;
|
Remember to maintain consistency in tone and style with the existing conversation while providing diverse options for the user to choose from. Your goal is to keep the conversation flowing naturally and help the user delve deeper into the subject matter or explore related topics.`;
|
||||||
export const PROMPT_QUESTION_GUIDE_FOOTER = `Please strictly follow the format rules: \nReturn questions in JSON format: ['Question 1', 'Question 2', 'Question 3']. Your output: `;
|
|
||||||
|
export const QuestionGuideFooterPrompt = `Please strictly follow the format rules: \nReturn questions in JSON format: ['Question 1', 'Question 2', 'Question 3']. Your output: `;
|
||||||
|
|||||||
19
packages/global/core/ai/prompt/utils.ts
Normal file
19
packages/global/core/ai/prompt/utils.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
export const getPromptByVersion = (version?: string, promptMap: Record<string, string> = {}) => {
|
||||||
|
const versions = Object.keys(promptMap).sort((a, b) => {
|
||||||
|
const [majorA, minorA, patchA] = a.split('.').map(Number);
|
||||||
|
const [majorB, minorB, patchB] = b.split('.').map(Number);
|
||||||
|
|
||||||
|
if (majorA !== majorB) return majorB - majorA;
|
||||||
|
if (minorA !== minorB) return minorB - minorA;
|
||||||
|
return patchB - patchA;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!version) {
|
||||||
|
return promptMap[versions[0]];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version in promptMap) {
|
||||||
|
return promptMap[version];
|
||||||
|
}
|
||||||
|
return promptMap[versions[versions.length - 1]];
|
||||||
|
};
|
||||||
2
packages/global/core/ai/type.d.ts
vendored
2
packages/global/core/ai/type.d.ts
vendored
@@ -80,5 +80,5 @@ export * from 'openai';
|
|||||||
export type PromptTemplateItem = {
|
export type PromptTemplateItem = {
|
||||||
title: string;
|
title: string;
|
||||||
desc: string;
|
desc: string;
|
||||||
value: string;
|
value: Record<string, string>;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { PROMPT_QUESTION_GUIDE } from '../ai/prompt/agent';
|
|
||||||
import {
|
import {
|
||||||
AppTTSConfigType,
|
AppTTSConfigType,
|
||||||
AppFileSelectConfigType,
|
AppFileSelectConfigType,
|
||||||
|
|||||||
13
packages/global/core/dataset/api.d.ts
vendored
13
packages/global/core/dataset/api.d.ts
vendored
@@ -1,5 +1,10 @@
|
|||||||
import { DatasetDataIndexItemType, DatasetSchemaType } from './type';
|
import { DatasetDataIndexItemType, DatasetSchemaType } from './type';
|
||||||
import { DatasetCollectionTypeEnum, DatasetCollectionDataProcessModeEnum } from './constants';
|
import {
|
||||||
|
DatasetCollectionTypeEnum,
|
||||||
|
DatasetCollectionDataProcessModeEnum,
|
||||||
|
ChunkSettingModeEnum,
|
||||||
|
DataChunkSplitModeEnum
|
||||||
|
} from './constants';
|
||||||
import type { LLMModelItemType } from '../ai/model.d';
|
import type { LLMModelItemType } from '../ai/model.d';
|
||||||
import { ParentIdType } from 'common/parentFolder/type';
|
import { ParentIdType } from 'common/parentFolder/type';
|
||||||
|
|
||||||
@@ -33,7 +38,13 @@ export type DatasetCollectionChunkMetadataType = {
|
|||||||
trainingType?: DatasetCollectionDataProcessModeEnum;
|
trainingType?: DatasetCollectionDataProcessModeEnum;
|
||||||
imageIndex?: boolean;
|
imageIndex?: boolean;
|
||||||
autoIndexes?: boolean;
|
autoIndexes?: boolean;
|
||||||
|
|
||||||
|
chunkSettingMode?: ChunkSettingModeEnum;
|
||||||
|
chunkSplitMode?: DataChunkSplitModeEnum;
|
||||||
|
|
||||||
chunkSize?: number;
|
chunkSize?: number;
|
||||||
|
indexSize?: number;
|
||||||
|
|
||||||
chunkSplitter?: string;
|
chunkSplitter?: string;
|
||||||
qaPrompt?: string;
|
qaPrompt?: string;
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, any>;
|
||||||
|
|||||||
8
packages/global/core/dataset/apiDataset.d.ts
vendored
8
packages/global/core/dataset/apiDataset.d.ts
vendored
@@ -1,3 +1,5 @@
|
|||||||
|
import { RequireOnlyOne } from '../../common/type/utils';
|
||||||
|
|
||||||
export type APIFileItem = {
|
export type APIFileItem = {
|
||||||
id: string;
|
id: string;
|
||||||
parentId: string | null;
|
parentId: string | null;
|
||||||
@@ -15,9 +17,9 @@ export type APIFileServer = {
|
|||||||
|
|
||||||
export type APIFileListResponse = APIFileItem[];
|
export type APIFileListResponse = APIFileItem[];
|
||||||
|
|
||||||
export type APIFileContentResponse = {
|
export type ApiFileReadContentResponse = {
|
||||||
content?: string;
|
title?: string;
|
||||||
previewUrl?: string;
|
rawText: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type APIFileReadResponse = {
|
export type APIFileReadResponse = {
|
||||||
|
|||||||
@@ -16,3 +16,7 @@ export const getCollectionSourceData = (collection?: DatasetCollectionSchemaType
|
|||||||
export const checkCollectionIsFolder = (type: DatasetCollectionTypeEnum) => {
|
export const checkCollectionIsFolder = (type: DatasetCollectionTypeEnum) => {
|
||||||
return type === DatasetCollectionTypeEnum.folder || type === DatasetCollectionTypeEnum.virtual;
|
return type === DatasetCollectionTypeEnum.folder || type === DatasetCollectionTypeEnum.virtual;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const collectionCanSync = (type: DatasetCollectionTypeEnum) => {
|
||||||
|
return [DatasetCollectionTypeEnum.link, DatasetCollectionTypeEnum.apiFile].includes(type);
|
||||||
|
};
|
||||||
|
|||||||
@@ -13,38 +13,38 @@ export enum DatasetTypeEnum {
|
|||||||
export const DatasetTypeMap = {
|
export const DatasetTypeMap = {
|
||||||
[DatasetTypeEnum.folder]: {
|
[DatasetTypeEnum.folder]: {
|
||||||
icon: 'common/folderFill',
|
icon: 'common/folderFill',
|
||||||
label: 'folder_dataset',
|
label: i18nT('dataset:folder_dataset'),
|
||||||
collectionLabel: 'common.Folder'
|
collectionLabel: i18nT('common:Folder')
|
||||||
},
|
},
|
||||||
[DatasetTypeEnum.dataset]: {
|
[DatasetTypeEnum.dataset]: {
|
||||||
icon: 'core/dataset/commonDatasetOutline',
|
icon: 'core/dataset/commonDatasetOutline',
|
||||||
label: 'common_dataset',
|
label: i18nT('dataset:common_dataset'),
|
||||||
collectionLabel: 'common.File'
|
collectionLabel: i18nT('common:common.File')
|
||||||
},
|
},
|
||||||
[DatasetTypeEnum.websiteDataset]: {
|
[DatasetTypeEnum.websiteDataset]: {
|
||||||
icon: 'core/dataset/websiteDatasetOutline',
|
icon: 'core/dataset/websiteDatasetOutline',
|
||||||
label: 'website_dataset',
|
label: i18nT('dataset:website_dataset'),
|
||||||
collectionLabel: 'common.Website'
|
collectionLabel: i18nT('common:common.Website')
|
||||||
},
|
},
|
||||||
[DatasetTypeEnum.externalFile]: {
|
[DatasetTypeEnum.externalFile]: {
|
||||||
icon: 'core/dataset/externalDatasetOutline',
|
icon: 'core/dataset/externalDatasetOutline',
|
||||||
label: 'external_file',
|
label: i18nT('dataset:external_file'),
|
||||||
collectionLabel: 'common.File'
|
collectionLabel: i18nT('common:common.File')
|
||||||
},
|
},
|
||||||
[DatasetTypeEnum.apiDataset]: {
|
[DatasetTypeEnum.apiDataset]: {
|
||||||
icon: 'core/dataset/externalDatasetOutline',
|
icon: 'core/dataset/externalDatasetOutline',
|
||||||
label: 'api_file',
|
label: i18nT('dataset:api_file'),
|
||||||
collectionLabel: 'common.File'
|
collectionLabel: i18nT('common:common.File')
|
||||||
},
|
},
|
||||||
[DatasetTypeEnum.feishu]: {
|
[DatasetTypeEnum.feishu]: {
|
||||||
icon: 'core/dataset/feishuDatasetOutline',
|
icon: 'core/dataset/feishuDatasetOutline',
|
||||||
label: 'feishu_dataset',
|
label: i18nT('dataset:feishu_dataset'),
|
||||||
collectionLabel: 'common.File'
|
collectionLabel: i18nT('common:common.File')
|
||||||
},
|
},
|
||||||
[DatasetTypeEnum.yuque]: {
|
[DatasetTypeEnum.yuque]: {
|
||||||
icon: 'core/dataset/yuqueDatasetOutline',
|
icon: 'core/dataset/yuqueDatasetOutline',
|
||||||
label: 'yuque_dataset',
|
label: i18nT('dataset:yuque_dataset'),
|
||||||
collectionLabel: 'common.File'
|
collectionLabel: i18nT('common:common.File')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -129,6 +129,16 @@ export const DatasetCollectionDataProcessModeMap = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export enum ChunkSettingModeEnum {
|
||||||
|
auto = 'auto',
|
||||||
|
custom = 'custom'
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum DataChunkSplitModeEnum {
|
||||||
|
size = 'size',
|
||||||
|
char = 'char'
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------ data -------------- */
|
/* ------------ data -------------- */
|
||||||
|
|
||||||
/* ------------ training -------------- */
|
/* ------------ training -------------- */
|
||||||
|
|||||||
1
packages/global/core/dataset/controller.d.ts
vendored
1
packages/global/core/dataset/controller.d.ts
vendored
@@ -13,6 +13,7 @@ export type CreateDatasetDataProps = {
|
|||||||
|
|
||||||
export type UpdateDatasetDataProps = {
|
export type UpdateDatasetDataProps = {
|
||||||
dataId: string;
|
dataId: string;
|
||||||
|
|
||||||
q?: string;
|
q?: string;
|
||||||
a?: string;
|
a?: string;
|
||||||
indexes?: (Omit<DatasetDataIndexItemType, 'dataId'> & {
|
indexes?: (Omit<DatasetDataIndexItemType, 'dataId'> & {
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ export type PushDataToTrainingQueueProps = {
|
|||||||
vectorModel: string;
|
vectorModel: string;
|
||||||
vlmModel?: string;
|
vlmModel?: string;
|
||||||
|
|
||||||
|
indexSize?: number;
|
||||||
|
|
||||||
billId?: string;
|
billId?: string;
|
||||||
session?: ClientSession;
|
session?: ClientSession;
|
||||||
};
|
};
|
||||||
|
|||||||
136
packages/global/core/dataset/training/utils.ts
Normal file
136
packages/global/core/dataset/training/utils.ts
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
import { EmbeddingModelItemType, LLMModelItemType } from '../../../core/ai/model.d';
|
||||||
|
import {
|
||||||
|
ChunkSettingModeEnum,
|
||||||
|
DataChunkSplitModeEnum,
|
||||||
|
DatasetCollectionDataProcessModeEnum
|
||||||
|
} from '../constants';
|
||||||
|
|
||||||
|
export const minChunkSize = 64; // min index and chunk size
|
||||||
|
|
||||||
|
// Chunk size
|
||||||
|
export const chunkAutoChunkSize = 1500;
|
||||||
|
export const getMaxChunkSize = (model: LLMModelItemType) => {
|
||||||
|
return Math.max(model.maxContext - model.maxResponse, 2000);
|
||||||
|
};
|
||||||
|
|
||||||
|
// QA
|
||||||
|
export const defaultMaxChunkSize = 8000;
|
||||||
|
export const getLLMDefaultChunkSize = (model?: LLMModelItemType) => {
|
||||||
|
if (!model) return defaultMaxChunkSize;
|
||||||
|
return Math.max(Math.min(model.maxContext - model.maxResponse, defaultMaxChunkSize), 2000);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getLLMMaxChunkSize = (model?: LLMModelItemType) => {
|
||||||
|
if (!model) return 8000;
|
||||||
|
return Math.max(model.maxContext - model.maxResponse, 2000);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Index size
|
||||||
|
export const getMaxIndexSize = (model?: EmbeddingModelItemType) => {
|
||||||
|
return model?.maxToken || 512;
|
||||||
|
};
|
||||||
|
export const getAutoIndexSize = (model?: EmbeddingModelItemType) => {
|
||||||
|
return model?.defaultToken || 512;
|
||||||
|
};
|
||||||
|
|
||||||
|
const indexSizeSelectList = [
|
||||||
|
{
|
||||||
|
label: '64',
|
||||||
|
value: 64
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '128',
|
||||||
|
value: 128
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '256',
|
||||||
|
value: 256
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '512',
|
||||||
|
value: 512
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '768',
|
||||||
|
value: 768
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '1024',
|
||||||
|
value: 1024
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '1536',
|
||||||
|
value: 1536
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '2048',
|
||||||
|
value: 2048
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '3072',
|
||||||
|
value: 3072
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '4096',
|
||||||
|
value: 4096
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '5120',
|
||||||
|
value: 5120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '6144',
|
||||||
|
value: 6144
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '7168',
|
||||||
|
value: 7168
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '8192',
|
||||||
|
value: 8192
|
||||||
|
}
|
||||||
|
];
|
||||||
|
export const getIndexSizeSelectList = (max = 512) => {
|
||||||
|
return indexSizeSelectList.filter((item) => item.value <= max);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Compute
|
||||||
|
export const computeChunkSize = (params: {
|
||||||
|
trainingType: DatasetCollectionDataProcessModeEnum;
|
||||||
|
chunkSettingMode?: ChunkSettingModeEnum;
|
||||||
|
chunkSplitMode?: DataChunkSplitModeEnum;
|
||||||
|
llmModel?: LLMModelItemType;
|
||||||
|
chunkSize?: number;
|
||||||
|
}) => {
|
||||||
|
if (params.trainingType === DatasetCollectionDataProcessModeEnum.qa) {
|
||||||
|
if (params.chunkSettingMode === ChunkSettingModeEnum.auto) {
|
||||||
|
return getLLMDefaultChunkSize(params.llmModel);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// chunk
|
||||||
|
if (params.chunkSettingMode === ChunkSettingModeEnum.auto) {
|
||||||
|
return chunkAutoChunkSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.chunkSplitMode === DataChunkSplitModeEnum.char) {
|
||||||
|
return getLLMMaxChunkSize(params.llmModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.min(params.chunkSize || chunkAutoChunkSize, getLLMMaxChunkSize(params.llmModel));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const computeChunkSplitter = (params: {
|
||||||
|
chunkSettingMode?: ChunkSettingModeEnum;
|
||||||
|
chunkSplitMode?: DataChunkSplitModeEnum;
|
||||||
|
chunkSplitter?: string;
|
||||||
|
}) => {
|
||||||
|
if (params.chunkSettingMode === ChunkSettingModeEnum.auto) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (params.chunkSplitMode === DataChunkSplitModeEnum.size) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return params.chunkSplitter;
|
||||||
|
};
|
||||||
9
packages/global/core/dataset/type.d.ts
vendored
9
packages/global/core/dataset/type.d.ts
vendored
@@ -2,6 +2,7 @@ import type { LLMModelItemType, EmbeddingModelItemType } from '../../core/ai/mod
|
|||||||
import { PermissionTypeEnum } from '../../support/permission/constant';
|
import { PermissionTypeEnum } from '../../support/permission/constant';
|
||||||
import { PushDatasetDataChunkProps } from './api';
|
import { PushDatasetDataChunkProps } from './api';
|
||||||
import {
|
import {
|
||||||
|
DataChunkSplitModeEnum,
|
||||||
DatasetCollectionDataProcessModeEnum,
|
DatasetCollectionDataProcessModeEnum,
|
||||||
DatasetCollectionTypeEnum,
|
DatasetCollectionTypeEnum,
|
||||||
DatasetStatusEnum,
|
DatasetStatusEnum,
|
||||||
@@ -14,6 +15,7 @@ import { Permission } from '../../support/permission/controller';
|
|||||||
import { APIFileServer, FeishuServer, YuqueServer } from './apiDataset';
|
import { APIFileServer, FeishuServer, YuqueServer } from './apiDataset';
|
||||||
import { SourceMemberType } from 'support/user/type';
|
import { SourceMemberType } from 'support/user/type';
|
||||||
import { DatasetDataIndexTypeEnum } from './data/constants';
|
import { DatasetDataIndexTypeEnum } from './data/constants';
|
||||||
|
import { ChunkSettingModeEnum } from './constants';
|
||||||
|
|
||||||
export type DatasetSchemaType = {
|
export type DatasetSchemaType = {
|
||||||
_id: string;
|
_id: string;
|
||||||
@@ -88,7 +90,12 @@ export type DatasetCollectionSchemaType = {
|
|||||||
autoIndexes?: boolean;
|
autoIndexes?: boolean;
|
||||||
imageIndex?: boolean;
|
imageIndex?: boolean;
|
||||||
trainingType: DatasetCollectionDataProcessModeEnum;
|
trainingType: DatasetCollectionDataProcessModeEnum;
|
||||||
chunkSize: number;
|
|
||||||
|
chunkSettingMode?: ChunkSettingModeEnum;
|
||||||
|
chunkSplitMode?: DataChunkSplitModeEnum;
|
||||||
|
|
||||||
|
chunkSize?: number;
|
||||||
|
indexSize?: number;
|
||||||
chunkSplitter?: string;
|
chunkSplitter?: string;
|
||||||
qaPrompt?: string;
|
qaPrompt?: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { TrainingModeEnum, DatasetCollectionTypeEnum } from './constants';
|
import { TrainingModeEnum, DatasetCollectionTypeEnum } from './constants';
|
||||||
import { getFileIcon } from '../../common/file/icon';
|
import { getFileIcon } from '../../common/file/icon';
|
||||||
import { strIsLink } from '../../common/string/tools';
|
import { strIsLink } from '../../common/string/tools';
|
||||||
import { DatasetDataIndexTypeEnum } from './data/constants';
|
|
||||||
|
|
||||||
export function getCollectionIcon(
|
export function getCollectionIcon(
|
||||||
type: DatasetCollectionTypeEnum = DatasetCollectionTypeEnum.file,
|
type: DatasetCollectionTypeEnum = DatasetCollectionTypeEnum.file,
|
||||||
@@ -38,26 +37,6 @@ export function getSourceNameIcon({
|
|||||||
return 'file/fill/file';
|
return 'file/fill/file';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get dataset data default index */
|
|
||||||
export function getDefaultIndex(props?: { q?: string; a?: string }) {
|
|
||||||
const { q = '', a } = props || {};
|
|
||||||
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
text: q,
|
|
||||||
type: DatasetDataIndexTypeEnum.default
|
|
||||||
},
|
|
||||||
...(a
|
|
||||||
? [
|
|
||||||
{
|
|
||||||
text: a,
|
|
||||||
type: DatasetDataIndexTypeEnum.default
|
|
||||||
}
|
|
||||||
]
|
|
||||||
: [])
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
export const predictDataLimitLength = (mode: TrainingModeEnum, data: any[]) => {
|
export const predictDataLimitLength = (mode: TrainingModeEnum, data: any[]) => {
|
||||||
if (mode === TrainingModeEnum.qa) return data.length * 20;
|
if (mode === TrainingModeEnum.qa) return data.length * 20;
|
||||||
if (mode === TrainingModeEnum.auto) return data.length * 5;
|
if (mode === TrainingModeEnum.auto) return data.length * 5;
|
||||||
|
|||||||
2
packages/global/core/plugin/type.d.ts
vendored
2
packages/global/core/plugin/type.d.ts
vendored
@@ -41,6 +41,8 @@ export type PluginTemplateType = PluginRuntimeType & {
|
|||||||
export type PluginRuntimeType = {
|
export type PluginRuntimeType = {
|
||||||
id: string;
|
id: string;
|
||||||
teamId?: string;
|
teamId?: string;
|
||||||
|
tmbId?: string;
|
||||||
|
|
||||||
name: string;
|
name: string;
|
||||||
avatar: string;
|
avatar: string;
|
||||||
showStatus?: boolean;
|
showStatus?: boolean;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export enum WorkflowIOValueTypeEnum {
|
|||||||
number = 'number',
|
number = 'number',
|
||||||
boolean = 'boolean',
|
boolean = 'boolean',
|
||||||
object = 'object',
|
object = 'object',
|
||||||
|
|
||||||
arrayString = 'arrayString',
|
arrayString = 'arrayString',
|
||||||
arrayNumber = 'arrayNumber',
|
arrayNumber = 'arrayNumber',
|
||||||
arrayBoolean = 'arrayBoolean',
|
arrayBoolean = 'arrayBoolean',
|
||||||
|
|||||||
@@ -76,16 +76,9 @@ export const Input_Template_Text_Quote: FlowNodeInputItemType = {
|
|||||||
valueType: WorkflowIOValueTypeEnum.string
|
valueType: WorkflowIOValueTypeEnum.string
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Input_Template_File_Link_Prompt: FlowNodeInputItemType = {
|
|
||||||
key: NodeInputKeyEnum.fileUrlList,
|
|
||||||
renderTypeList: [FlowNodeInputTypeEnum.reference, FlowNodeInputTypeEnum.input],
|
|
||||||
label: i18nT('app:file_quote_link'),
|
|
||||||
debugLabel: i18nT('app:file_quote_link'),
|
|
||||||
valueType: WorkflowIOValueTypeEnum.arrayString
|
|
||||||
};
|
|
||||||
export const Input_Template_File_Link: FlowNodeInputItemType = {
|
export const Input_Template_File_Link: FlowNodeInputItemType = {
|
||||||
key: NodeInputKeyEnum.fileUrlList,
|
key: NodeInputKeyEnum.fileUrlList,
|
||||||
renderTypeList: [FlowNodeInputTypeEnum.reference],
|
renderTypeList: [FlowNodeInputTypeEnum.reference, FlowNodeInputTypeEnum.input],
|
||||||
label: i18nT('app:workflow.user_file_input'),
|
label: i18nT('app:workflow.user_file_input'),
|
||||||
debugLabel: i18nT('app:workflow.user_file_input'),
|
debugLabel: i18nT('app:workflow.user_file_input'),
|
||||||
description: i18nT('app:workflow.user_file_input_desc'),
|
description: i18nT('app:workflow.user_file_input_desc'),
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
Input_Template_History,
|
Input_Template_History,
|
||||||
Input_Template_System_Prompt,
|
Input_Template_System_Prompt,
|
||||||
Input_Template_UserChatInput,
|
Input_Template_UserChatInput,
|
||||||
Input_Template_File_Link_Prompt
|
Input_Template_File_Link
|
||||||
} from '../../input';
|
} from '../../input';
|
||||||
import { chatNodeSystemPromptTip, systemPromptTip } from '../../tip';
|
import { chatNodeSystemPromptTip, systemPromptTip } from '../../tip';
|
||||||
import { getHandleConfig } from '../../utils';
|
import { getHandleConfig } from '../../utils';
|
||||||
@@ -55,7 +55,7 @@ export const AiChatModule: FlowNodeTemplateType = {
|
|||||||
showStatus: true,
|
showStatus: true,
|
||||||
isTool: true,
|
isTool: true,
|
||||||
courseUrl: '/docs/guide/workbench/workflow/ai_chat/',
|
courseUrl: '/docs/guide/workbench/workflow/ai_chat/',
|
||||||
version: '490',
|
version: '4.9.0',
|
||||||
inputs: [
|
inputs: [
|
||||||
Input_Template_SettingAiModel,
|
Input_Template_SettingAiModel,
|
||||||
// --- settings modal
|
// --- settings modal
|
||||||
@@ -129,7 +129,7 @@ export const AiChatModule: FlowNodeTemplateType = {
|
|||||||
},
|
},
|
||||||
Input_Template_History,
|
Input_Template_History,
|
||||||
Input_Template_Dataset_Quote,
|
Input_Template_Dataset_Quote,
|
||||||
Input_Template_File_Link_Prompt,
|
Input_Template_File_Link,
|
||||||
{ ...Input_Template_UserChatInput, toolDescription: i18nT('workflow:user_question') }
|
{ ...Input_Template_UserChatInput, toolDescription: i18nT('workflow:user_question') }
|
||||||
],
|
],
|
||||||
outputs: [
|
outputs: [
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export const ClassifyQuestionModule: FlowNodeTemplateType = {
|
|||||||
name: i18nT('workflow:question_classification'),
|
name: i18nT('workflow:question_classification'),
|
||||||
intro: i18nT('workflow:intro_question_classification'),
|
intro: i18nT('workflow:intro_question_classification'),
|
||||||
showStatus: true,
|
showStatus: true,
|
||||||
version: '481',
|
version: '4.9.2',
|
||||||
courseUrl: '/docs/guide/workbench/workflow/question_classify/',
|
courseUrl: '/docs/guide/workbench/workflow/question_classify/',
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export const ContextExtractModule: FlowNodeTemplateType = {
|
|||||||
showStatus: true,
|
showStatus: true,
|
||||||
isTool: true,
|
isTool: true,
|
||||||
courseUrl: '/docs/guide/workbench/workflow/content_extract/',
|
courseUrl: '/docs/guide/workbench/workflow/content_extract/',
|
||||||
version: '481',
|
version: '4.9.2',
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
...Input_Template_SelectAIModel,
|
...Input_Template_SelectAIModel,
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export const DatasetSearchModule: FlowNodeTemplateType = {
|
|||||||
showStatus: true,
|
showStatus: true,
|
||||||
isTool: true,
|
isTool: true,
|
||||||
courseUrl: '/docs/guide/workbench/workflow/dataset_search/',
|
courseUrl: '/docs/guide/workbench/workflow/dataset_search/',
|
||||||
version: '481',
|
version: '4.9.2',
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
key: NodeInputKeyEnum.datasetSelectList,
|
key: NodeInputKeyEnum.datasetSelectList,
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export const ReadFilesNode: FlowNodeTemplateType = {
|
|||||||
name: i18nT('app:workflow.read_files'),
|
name: i18nT('app:workflow.read_files'),
|
||||||
intro: i18nT('app:workflow.read_files_tip'),
|
intro: i18nT('app:workflow.read_files_tip'),
|
||||||
showStatus: true,
|
showStatus: true,
|
||||||
version: '4812',
|
version: '4.9.2',
|
||||||
isTool: false,
|
isTool: false,
|
||||||
courseUrl: '/docs/guide/course/fileinput/',
|
courseUrl: '/docs/guide/course/fileinput/',
|
||||||
inputs: [
|
inputs: [
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import { chatNodeSystemPromptTip, systemPromptTip } from '../tip';
|
|||||||
import { LLMModelTypeEnum } from '../../../ai/constants';
|
import { LLMModelTypeEnum } from '../../../ai/constants';
|
||||||
import { getHandleConfig } from '../utils';
|
import { getHandleConfig } from '../utils';
|
||||||
import { i18nT } from '../../../../../web/i18n/utils';
|
import { i18nT } from '../../../../../web/i18n/utils';
|
||||||
import { Input_Template_File_Link_Prompt } from '../input';
|
import { Input_Template_File_Link } from '../input';
|
||||||
|
|
||||||
export const ToolModule: FlowNodeTemplateType = {
|
export const ToolModule: FlowNodeTemplateType = {
|
||||||
id: FlowNodeTypeEnum.tools,
|
id: FlowNodeTypeEnum.tools,
|
||||||
@@ -33,7 +33,7 @@ export const ToolModule: FlowNodeTemplateType = {
|
|||||||
intro: i18nT('workflow:template.tool_call_intro'),
|
intro: i18nT('workflow:template.tool_call_intro'),
|
||||||
showStatus: true,
|
showStatus: true,
|
||||||
courseUrl: '/docs/guide/workbench/workflow/tool/',
|
courseUrl: '/docs/guide/workbench/workflow/tool/',
|
||||||
version: '4813',
|
version: '4.9.2',
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
...Input_Template_SettingAiModel,
|
...Input_Template_SettingAiModel,
|
||||||
@@ -97,7 +97,7 @@ export const ToolModule: FlowNodeTemplateType = {
|
|||||||
placeholder: chatNodeSystemPromptTip
|
placeholder: chatNodeSystemPromptTip
|
||||||
},
|
},
|
||||||
Input_Template_History,
|
Input_Template_History,
|
||||||
Input_Template_File_Link_Prompt,
|
Input_Template_File_Link,
|
||||||
Input_Template_UserChatInput
|
Input_Template_UserChatInput
|
||||||
],
|
],
|
||||||
outputs: [
|
outputs: [
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"jschardet": "3.1.1",
|
"jschardet": "3.1.1",
|
||||||
"nanoid": "^5.1.3",
|
"nanoid": "^5.1.3",
|
||||||
"next": "14.2.24",
|
"next": "14.2.25",
|
||||||
"openai": "4.61.0",
|
"openai": "4.61.0",
|
||||||
"openapi-types": "^12.1.3",
|
"openapi-types": "^12.1.3",
|
||||||
"json5": "^2.2.3",
|
"json5": "^2.2.3",
|
||||||
|
|||||||
4
packages/global/support/permission/memberGroup/api.d.ts
vendored
Normal file
4
packages/global/support/permission/memberGroup/api.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export type GetGroupListBody = {
|
||||||
|
searchKey?: string;
|
||||||
|
withMembers?: boolean;
|
||||||
|
};
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { TeamMemberItemType } from 'support/user/team/type';
|
import { TeamMemberItemType } from 'support/user/team/type';
|
||||||
import { TeamPermission } from '../user/controller';
|
import { TeamPermission } from '../user/controller';
|
||||||
import { GroupMemberRole } from './constant';
|
import { GroupMemberRole } from './constant';
|
||||||
|
import { Permission } from '../controller';
|
||||||
|
|
||||||
type MemberGroupSchemaType = {
|
type MemberGroupSchemaType = {
|
||||||
_id: string;
|
_id: string;
|
||||||
@@ -16,12 +17,28 @@ type GroupMemberSchemaType = {
|
|||||||
role: `${GroupMemberRole}`;
|
role: `${GroupMemberRole}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
type MemberGroupType = MemberGroupSchemaType & {
|
type MemberGroupListItemType<T extends boolean | undefined> = MemberGroupSchemaType & {
|
||||||
members: {
|
members: T extends true
|
||||||
tmbId: string;
|
? {
|
||||||
role: `${GroupMemberRole}`;
|
tmbId: string;
|
||||||
}[]; // we can get tmb's info from other api. there is no need but only need to get tmb's id
|
name: string;
|
||||||
permission: TeamPermission;
|
avatar: string;
|
||||||
|
}[]
|
||||||
|
: undefined;
|
||||||
|
count: T extends true ? number : undefined;
|
||||||
|
owner?: T extends true
|
||||||
|
? {
|
||||||
|
tmbId: string;
|
||||||
|
name: string;
|
||||||
|
avatar: string;
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
permission: T extends true ? Permission : undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
type MemberGroupListType = MemberGroupType[];
|
type GroupMemberItemType = {
|
||||||
|
tmbId: string;
|
||||||
|
name: string;
|
||||||
|
avatar: string;
|
||||||
|
role: `${GroupMemberRole}`;
|
||||||
|
};
|
||||||
|
|||||||
7
packages/global/support/user/api.d.ts
vendored
7
packages/global/support/user/api.d.ts
vendored
@@ -1,4 +1,7 @@
|
|||||||
import { MemberGroupSchemaType, MemberGroupType } from 'support/permission/memberGroup/type';
|
import {
|
||||||
|
MemberGroupSchemaType,
|
||||||
|
MemberGroupListItemType
|
||||||
|
} from 'support/permission/memberGroup/type';
|
||||||
import { OAuthEnum } from './constant';
|
import { OAuthEnum } from './constant';
|
||||||
import { TrackRegisterParams } from './login/api';
|
import { TrackRegisterParams } from './login/api';
|
||||||
import { TeamMemberStatusEnum } from './team/constant';
|
import { TeamMemberStatusEnum } from './team/constant';
|
||||||
@@ -12,8 +15,8 @@ export type PostLoginProps = {
|
|||||||
|
|
||||||
export type OauthLoginProps = {
|
export type OauthLoginProps = {
|
||||||
type: `${OAuthEnum}`;
|
type: `${OAuthEnum}`;
|
||||||
code: string;
|
|
||||||
callbackUrl: string;
|
callbackUrl: string;
|
||||||
|
props: Record<string, string>;
|
||||||
} & TrackRegisterParams;
|
} & TrackRegisterParams;
|
||||||
|
|
||||||
export type WxLoginProps = {
|
export type WxLoginProps = {
|
||||||
|
|||||||
@@ -16,7 +16,5 @@ export enum OAuthEnum {
|
|||||||
google = 'google',
|
google = 'google',
|
||||||
wechat = 'wechat',
|
wechat = 'wechat',
|
||||||
microsoft = 'microsoft',
|
microsoft = 'microsoft',
|
||||||
dingtalk = 'dingtalk',
|
|
||||||
wecom = 'wecom',
|
|
||||||
sso = 'sso'
|
sso = 'sso'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
export type postCreateOrgData = {
|
export type postCreateOrgData = {
|
||||||
name: string;
|
name: string;
|
||||||
parentId: string;
|
|
||||||
description?: string;
|
description?: string;
|
||||||
avatar?: string;
|
avatar?: string;
|
||||||
|
orgId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type putUpdateOrgMembersData = {
|
export type putUpdateOrgMembersData = {
|
||||||
orgId: string;
|
orgId?: string;
|
||||||
members: {
|
members: {
|
||||||
tmbId: string;
|
tmbId: string;
|
||||||
// role: `${OrgMemberRole}`;
|
// role: `${OrgMemberRole}`;
|
||||||
@@ -14,7 +14,7 @@ export type putUpdateOrgMembersData = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type putUpdateOrgData = {
|
export type putUpdateOrgData = {
|
||||||
orgId: string;
|
orgId: string; // can not be undefined because can not uppdate root org
|
||||||
name?: string;
|
name?: string;
|
||||||
avatar?: string;
|
avatar?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
@@ -22,7 +22,7 @@ export type putUpdateOrgData = {
|
|||||||
|
|
||||||
export type putMoveOrgType = {
|
export type putMoveOrgType = {
|
||||||
orgId: string;
|
orgId: string;
|
||||||
targetOrgId: string;
|
targetOrgId?: string; // '' ===> move to root org
|
||||||
};
|
};
|
||||||
|
|
||||||
// type putChnageOrgOwnerData = {
|
// type putChnageOrgOwnerData = {
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ import { OrgSchemaType } from './type';
|
|||||||
export const OrgCollectionName = 'team_orgs';
|
export const OrgCollectionName = 'team_orgs';
|
||||||
export const OrgMemberCollectionName = 'team_org_members';
|
export const OrgMemberCollectionName = 'team_org_members';
|
||||||
|
|
||||||
export const getOrgChildrenPath = (org: OrgSchemaType) => `${org.path}/${org.pathId}`;
|
export const getOrgChildrenPath = (org: OrgSchemaType) => {
|
||||||
|
if (org.path === '' && org.pathId === '') return '';
|
||||||
|
return `${org.path ?? ''}/${org.pathId}`;
|
||||||
|
};
|
||||||
|
|
||||||
export enum SyncOrgSourceEnum {
|
export enum SyncOrgSourceEnum {
|
||||||
wecom = 'wecom'
|
wecom = 'wecom'
|
||||||
|
|||||||
13
packages/global/support/user/team/org/type.d.ts
vendored
13
packages/global/support/user/team/org/type.d.ts
vendored
@@ -1,5 +1,6 @@
|
|||||||
import type { TeamPermission } from 'support/permission/user/controller';
|
import type { TeamPermission } from '../../../permission/user/controller';
|
||||||
import { ResourcePermissionType } from '../type';
|
import { ResourcePermissionType } from '../type';
|
||||||
|
import { SourceMemberType } from '../../type';
|
||||||
|
|
||||||
type OrgSchemaType = {
|
type OrgSchemaType = {
|
||||||
_id: string;
|
_id: string;
|
||||||
@@ -7,7 +8,7 @@ type OrgSchemaType = {
|
|||||||
pathId: string;
|
pathId: string;
|
||||||
path: string;
|
path: string;
|
||||||
name: string;
|
name: string;
|
||||||
avatar?: string;
|
avatar: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
updateTime: Date;
|
updateTime: Date;
|
||||||
};
|
};
|
||||||
@@ -19,8 +20,14 @@ type OrgMemberSchemaType = {
|
|||||||
tmbId: string;
|
tmbId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type OrgType = Omit<OrgSchemaType, 'avatar'> & {
|
export type OrgListItemType = OrgSchemaType & {
|
||||||
|
permission?: TeamPermission;
|
||||||
|
total: number; // members + children orgs
|
||||||
|
};
|
||||||
|
|
||||||
|
export type OrgType = Omit<OrgSchemaType, 'avatar'> & {
|
||||||
avatar: string;
|
avatar: string;
|
||||||
permission: TeamPermission;
|
permission: TeamPermission;
|
||||||
members: OrgMemberSchemaType[];
|
members: OrgMemberSchemaType[];
|
||||||
|
total: number; // members + children orgs
|
||||||
};
|
};
|
||||||
|
|||||||
25
packages/global/support/user/team/type.d.ts
vendored
25
packages/global/support/user/team/type.d.ts
vendored
@@ -70,7 +70,13 @@ export type TeamTmbItemType = {
|
|||||||
permission: TeamPermission;
|
permission: TeamPermission;
|
||||||
} & ThirdPartyAccountType;
|
} & ThirdPartyAccountType;
|
||||||
|
|
||||||
export type TeamMemberItemType = {
|
export type TeamMemberItemType<
|
||||||
|
Options extends {
|
||||||
|
withPermission?: boolean;
|
||||||
|
withOrgs?: boolean;
|
||||||
|
withGroupRole?: boolean;
|
||||||
|
} = { withPermission: true; withOrgs: true; withGroupRole: false }
|
||||||
|
> = {
|
||||||
userId: string;
|
userId: string;
|
||||||
tmbId: string;
|
tmbId: string;
|
||||||
teamId: string;
|
teamId: string;
|
||||||
@@ -78,11 +84,24 @@ export type TeamMemberItemType = {
|
|||||||
avatar: string;
|
avatar: string;
|
||||||
role: `${TeamMemberRoleEnum}`;
|
role: `${TeamMemberRoleEnum}`;
|
||||||
status: `${TeamMemberStatusEnum}`;
|
status: `${TeamMemberStatusEnum}`;
|
||||||
permission: TeamPermission;
|
|
||||||
contact?: string;
|
contact?: string;
|
||||||
createTime: Date;
|
createTime: Date;
|
||||||
updateTime?: Date;
|
updateTime?: Date;
|
||||||
};
|
} & (Options extends { withPermission: true }
|
||||||
|
? {
|
||||||
|
permission: TeamPermission;
|
||||||
|
}
|
||||||
|
: {}) &
|
||||||
|
(Options extends { withOrgs: true }
|
||||||
|
? {
|
||||||
|
orgs?: string[]; // full path name, pattern: /teamName/orgname1/orgname2
|
||||||
|
}
|
||||||
|
: {}) &
|
||||||
|
(Options extends { withGroupRole: true }
|
||||||
|
? {
|
||||||
|
groupRole?: `${GroupMemberRole}`;
|
||||||
|
}
|
||||||
|
: {});
|
||||||
|
|
||||||
export type TeamTagItemType = {
|
export type TeamTagItemType = {
|
||||||
label: string;
|
label: string;
|
||||||
|
|||||||
@@ -30,11 +30,11 @@ export async function text2Speech({
|
|||||||
response_format: 'mp3',
|
response_format: 'mp3',
|
||||||
speed
|
speed
|
||||||
},
|
},
|
||||||
modelData.requestUrl && modelData.requestAuth
|
modelData.requestUrl
|
||||||
? {
|
? {
|
||||||
path: modelData.requestUrl,
|
path: modelData.requestUrl,
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${modelData.requestAuth}`
|
...(modelData.requestAuth ? { Authorization: `Bearer ${modelData.requestAuth}` } : {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
: {}
|
: {}
|
||||||
|
|||||||
@@ -3,21 +3,25 @@ import { getAxiosConfig } from '../config';
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import FormData from 'form-data';
|
import FormData from 'form-data';
|
||||||
import { getSTTModel } from '../model';
|
import { getSTTModel } from '../model';
|
||||||
|
import { STTModelType } from '@fastgpt/global/core/ai/model.d';
|
||||||
|
|
||||||
export const aiTranscriptions = async ({
|
export const aiTranscriptions = async ({
|
||||||
model,
|
model: modelData,
|
||||||
fileStream,
|
fileStream,
|
||||||
headers
|
headers
|
||||||
}: {
|
}: {
|
||||||
model: string;
|
model: STTModelType;
|
||||||
fileStream: fs.ReadStream;
|
fileStream: fs.ReadStream;
|
||||||
headers?: Record<string, string>;
|
headers?: Record<string, string>;
|
||||||
}) => {
|
}) => {
|
||||||
|
if (!modelData) {
|
||||||
|
return Promise.reject('no model');
|
||||||
|
}
|
||||||
|
|
||||||
const data = new FormData();
|
const data = new FormData();
|
||||||
data.append('model', model);
|
data.append('model', modelData.model);
|
||||||
data.append('file', fileStream);
|
data.append('file', fileStream);
|
||||||
|
|
||||||
const modelData = getSTTModel(model);
|
|
||||||
const aiAxiosConfig = getAxiosConfig();
|
const aiAxiosConfig = getAxiosConfig();
|
||||||
|
|
||||||
const { data: result } = await axios<{ text: string }>({
|
const { data: result } = await axios<{ text: string }>({
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import { countGptMessagesTokens, countPromptTokens } from '../../../common/strin
|
|||||||
import { loadRequestMessages } from '../../chat/utils';
|
import { loadRequestMessages } from '../../chat/utils';
|
||||||
import { llmCompletionsBodyFormat } from '../utils';
|
import { llmCompletionsBodyFormat } from '../utils';
|
||||||
import {
|
import {
|
||||||
PROMPT_QUESTION_GUIDE,
|
QuestionGuidePrompt,
|
||||||
PROMPT_QUESTION_GUIDE_FOOTER
|
QuestionGuideFooterPrompt
|
||||||
} from '@fastgpt/global/core/ai/prompt/agent';
|
} from '@fastgpt/global/core/ai/prompt/agent';
|
||||||
import { addLog } from '../../../common/system/log';
|
import { addLog } from '../../../common/system/log';
|
||||||
import json5 from 'json5';
|
import json5 from 'json5';
|
||||||
@@ -27,7 +27,7 @@ export async function createQuestionGuide({
|
|||||||
...messages,
|
...messages,
|
||||||
{
|
{
|
||||||
role: 'user',
|
role: 'user',
|
||||||
content: `${customPrompt || PROMPT_QUESTION_GUIDE}\n${PROMPT_QUESTION_GUIDE_FOOTER}`
|
content: `${customPrompt || QuestionGuidePrompt}\n${QuestionGuideFooterPrompt}`
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
const requestMessages = await loadRequestMessages({
|
const requestMessages = await loadRequestMessages({
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ export const llmCompletionsBodyFormat = <T extends CompletionsBodyType>(
|
|||||||
|
|
||||||
const requestBody: T = {
|
const requestBody: T = {
|
||||||
...body,
|
...body,
|
||||||
|
model: modelData.model,
|
||||||
temperature:
|
temperature:
|
||||||
typeof body.temperature === 'number'
|
typeof body.temperature === 'number'
|
||||||
? computedTemperature({
|
? computedTemperature({
|
||||||
|
|||||||
@@ -37,11 +37,12 @@ export async function splitCombinePluginId(id: string) {
|
|||||||
return { source, pluginId: id };
|
return { source, pluginId: id };
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChildAppType = SystemPluginTemplateItemType & { teamId?: string };
|
type ChildAppType = SystemPluginTemplateItemType & { teamId?: string; tmbId?: string };
|
||||||
|
|
||||||
const getSystemPluginTemplateById = async (
|
const getSystemPluginTemplateById = async (
|
||||||
pluginId: string,
|
pluginId: string,
|
||||||
versionId?: string
|
versionId?: string
|
||||||
): Promise<SystemPluginTemplateItemType> => {
|
): Promise<ChildAppType> => {
|
||||||
const item = getSystemPluginTemplates().find((plugin) => plugin.id === pluginId);
|
const item = getSystemPluginTemplates().find((plugin) => plugin.id === pluginId);
|
||||||
if (!item) return Promise.reject(PluginErrEnum.unAuth);
|
if (!item) return Promise.reject(PluginErrEnum.unAuth);
|
||||||
|
|
||||||
@@ -67,12 +68,17 @@ const getSystemPluginTemplateById = async (
|
|||||||
: await getAppLatestVersion(plugin.associatedPluginId, app);
|
: await getAppLatestVersion(plugin.associatedPluginId, app);
|
||||||
if (!version.versionId) return Promise.reject('App version not found');
|
if (!version.versionId) return Promise.reject('App version not found');
|
||||||
|
|
||||||
plugin.workflow = {
|
return {
|
||||||
nodes: version.nodes,
|
...plugin,
|
||||||
edges: version.edges,
|
workflow: {
|
||||||
chatConfig: version.chatConfig
|
nodes: version.nodes,
|
||||||
|
edges: version.edges,
|
||||||
|
chatConfig: version.chatConfig
|
||||||
|
},
|
||||||
|
version: versionId || String(version.versionId),
|
||||||
|
teamId: String(app.teamId),
|
||||||
|
tmbId: String(app.tmbId)
|
||||||
};
|
};
|
||||||
plugin.version = versionId || String(version.versionId);
|
|
||||||
}
|
}
|
||||||
return plugin;
|
return plugin;
|
||||||
};
|
};
|
||||||
@@ -168,6 +174,7 @@ export async function getChildAppRuntimeById(
|
|||||||
return {
|
return {
|
||||||
id: String(item._id),
|
id: String(item._id),
|
||||||
teamId: String(item.teamId),
|
teamId: String(item.teamId),
|
||||||
|
tmbId: String(item.tmbId),
|
||||||
name: item.name,
|
name: item.name,
|
||||||
avatar: item.avatar,
|
avatar: item.avatar,
|
||||||
intro: item.intro,
|
intro: item.intro,
|
||||||
@@ -187,6 +194,7 @@ export async function getChildAppRuntimeById(
|
|||||||
pluginOrder: 0
|
pluginOrder: 0
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
// System
|
||||||
return getSystemPluginTemplateById(pluginId, versionId);
|
return getSystemPluginTemplateById(pluginId, versionId);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
@@ -194,6 +202,7 @@ export async function getChildAppRuntimeById(
|
|||||||
return {
|
return {
|
||||||
id: app.id,
|
id: app.id,
|
||||||
teamId: app.teamId,
|
teamId: app.teamId,
|
||||||
|
tmbId: app.tmbId,
|
||||||
name: app.name,
|
name: app.name,
|
||||||
avatar: app.avatar,
|
avatar: app.avatar,
|
||||||
showStatus: app.showStatus,
|
showStatus: app.showStatus,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type {
|
import type {
|
||||||
APIFileContentResponse,
|
|
||||||
APIFileListResponse,
|
APIFileListResponse,
|
||||||
|
ApiFileReadContentResponse,
|
||||||
APIFileReadResponse,
|
APIFileReadResponse,
|
||||||
APIFileServer
|
APIFileServer
|
||||||
} from '@fastgpt/global/core/dataset/apiDataset';
|
} from '@fastgpt/global/core/dataset/apiDataset';
|
||||||
@@ -8,6 +8,7 @@ import axios, { Method } from 'axios';
|
|||||||
import { addLog } from '../../../common/system/log';
|
import { addLog } from '../../../common/system/log';
|
||||||
import { readFileRawTextByUrl } from '../read';
|
import { readFileRawTextByUrl } from '../read';
|
||||||
import { ParentIdType } from '@fastgpt/global/common/parentFolder/type';
|
import { ParentIdType } from '@fastgpt/global/common/parentFolder/type';
|
||||||
|
import { RequireOnlyOne } from '@fastgpt/global/common/type/utils';
|
||||||
|
|
||||||
type ResponseDataType = {
|
type ResponseDataType = {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
@@ -118,17 +119,24 @@ export const useApiDatasetRequest = ({ apiServer }: { apiServer: APIFileServer }
|
|||||||
tmbId: string;
|
tmbId: string;
|
||||||
apiFileId: string;
|
apiFileId: string;
|
||||||
customPdfParse?: boolean;
|
customPdfParse?: boolean;
|
||||||
}) => {
|
}): Promise<ApiFileReadContentResponse> => {
|
||||||
const data = await request<APIFileContentResponse>(
|
const data = await request<
|
||||||
`/v1/file/content`,
|
{
|
||||||
{ id: apiFileId },
|
title?: string;
|
||||||
'GET'
|
} & RequireOnlyOne<{
|
||||||
);
|
content: string;
|
||||||
|
previewUrl: string;
|
||||||
|
}>
|
||||||
|
>(`/v1/file/content`, { id: apiFileId }, 'GET');
|
||||||
|
const title = data.title;
|
||||||
const content = data.content;
|
const content = data.content;
|
||||||
const previewUrl = data.previewUrl;
|
const previewUrl = data.previewUrl;
|
||||||
|
|
||||||
if (content) {
|
if (content) {
|
||||||
return content;
|
return {
|
||||||
|
title,
|
||||||
|
rawText: content
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (previewUrl) {
|
if (previewUrl) {
|
||||||
const rawText = await readFileRawTextByUrl({
|
const rawText = await readFileRawTextByUrl({
|
||||||
@@ -138,7 +146,10 @@ export const useApiDatasetRequest = ({ apiServer }: { apiServer: APIFileServer }
|
|||||||
relatedId: apiFileId,
|
relatedId: apiFileId,
|
||||||
customPdfParse
|
customPdfParse
|
||||||
});
|
});
|
||||||
return rawText;
|
return {
|
||||||
|
title,
|
||||||
|
rawText
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return Promise.reject('Invalid content type: content or previewUrl is required');
|
return Promise.reject('Invalid content type: content or previewUrl is required');
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,6 +27,11 @@ import { addDays } from 'date-fns';
|
|||||||
import { MongoDatasetDataText } from '../data/dataTextSchema';
|
import { MongoDatasetDataText } from '../data/dataTextSchema';
|
||||||
import { retryFn } from '@fastgpt/global/common/system/utils';
|
import { retryFn } from '@fastgpt/global/common/system/utils';
|
||||||
import { getTrainingModeByCollection } from './utils';
|
import { getTrainingModeByCollection } from './utils';
|
||||||
|
import {
|
||||||
|
computeChunkSize,
|
||||||
|
computeChunkSplitter,
|
||||||
|
getLLMMaxChunkSize
|
||||||
|
} from '@fastgpt/global/core/dataset/training/utils';
|
||||||
|
|
||||||
export const createCollectionAndInsertData = async ({
|
export const createCollectionAndInsertData = async ({
|
||||||
dataset,
|
dataset,
|
||||||
@@ -54,18 +59,22 @@ export const createCollectionAndInsertData = async ({
|
|||||||
|
|
||||||
const teamId = createCollectionParams.teamId;
|
const teamId = createCollectionParams.teamId;
|
||||||
const tmbId = createCollectionParams.tmbId;
|
const tmbId = createCollectionParams.tmbId;
|
||||||
// Chunk split params
|
|
||||||
|
// Set default params
|
||||||
const trainingType =
|
const trainingType =
|
||||||
createCollectionParams.trainingType || DatasetCollectionDataProcessModeEnum.chunk;
|
createCollectionParams.trainingType || DatasetCollectionDataProcessModeEnum.chunk;
|
||||||
const chunkSize = createCollectionParams.chunkSize || 512;
|
const chunkSize = computeChunkSize({
|
||||||
const chunkSplitter = createCollectionParams.chunkSplitter;
|
...createCollectionParams,
|
||||||
const qaPrompt = createCollectionParams.qaPrompt;
|
trainingType,
|
||||||
const usageName = createCollectionParams.name;
|
llmModel: getLLMModel(dataset.agentModel)
|
||||||
|
});
|
||||||
|
const chunkSplitter = computeChunkSplitter(createCollectionParams);
|
||||||
|
|
||||||
// 1. split chunks
|
// 1. split chunks
|
||||||
const chunks = rawText2Chunks({
|
const chunks = rawText2Chunks({
|
||||||
rawText,
|
rawText,
|
||||||
chunkLen: chunkSize,
|
chunkSize,
|
||||||
|
maxSize: getLLMMaxChunkSize(getLLMModel(dataset.agentModel)),
|
||||||
overlapRatio: trainingType === DatasetCollectionDataProcessModeEnum.chunk ? 0.2 : 0,
|
overlapRatio: trainingType === DatasetCollectionDataProcessModeEnum.chunk ? 0.2 : 0,
|
||||||
customReg: chunkSplitter ? [chunkSplitter] : [],
|
customReg: chunkSplitter ? [chunkSplitter] : [],
|
||||||
isQAImport
|
isQAImport
|
||||||
@@ -76,7 +85,7 @@ export const createCollectionAndInsertData = async ({
|
|||||||
teamId,
|
teamId,
|
||||||
insertLen: predictDataLimitLength(
|
insertLen: predictDataLimitLength(
|
||||||
getTrainingModeByCollection({
|
getTrainingModeByCollection({
|
||||||
trainingType,
|
trainingType: trainingType,
|
||||||
autoIndexes: createCollectionParams.autoIndexes,
|
autoIndexes: createCollectionParams.autoIndexes,
|
||||||
imageIndex: createCollectionParams.imageIndex
|
imageIndex: createCollectionParams.imageIndex
|
||||||
}),
|
}),
|
||||||
@@ -88,6 +97,9 @@ export const createCollectionAndInsertData = async ({
|
|||||||
// 3. create collection
|
// 3. create collection
|
||||||
const { _id: collectionId } = await createOneCollection({
|
const { _id: collectionId } = await createOneCollection({
|
||||||
...createCollectionParams,
|
...createCollectionParams,
|
||||||
|
trainingType,
|
||||||
|
chunkSize,
|
||||||
|
chunkSplitter,
|
||||||
|
|
||||||
hashRawText: hashStr(rawText),
|
hashRawText: hashStr(rawText),
|
||||||
rawTextLength: rawText.length,
|
rawTextLength: rawText.length,
|
||||||
@@ -111,7 +123,7 @@ export const createCollectionAndInsertData = async ({
|
|||||||
const { billId: newBillId } = await createTrainingUsage({
|
const { billId: newBillId } = await createTrainingUsage({
|
||||||
teamId,
|
teamId,
|
||||||
tmbId,
|
tmbId,
|
||||||
appName: usageName,
|
appName: createCollectionParams.name,
|
||||||
billSource: UsageSourceEnum.training,
|
billSource: UsageSourceEnum.training,
|
||||||
vectorModel: getEmbeddingModel(dataset.vectorModel)?.name,
|
vectorModel: getEmbeddingModel(dataset.vectorModel)?.name,
|
||||||
agentModel: getLLMModel(dataset.agentModel)?.name,
|
agentModel: getLLMModel(dataset.agentModel)?.name,
|
||||||
@@ -130,12 +142,13 @@ export const createCollectionAndInsertData = async ({
|
|||||||
agentModel: dataset.agentModel,
|
agentModel: dataset.agentModel,
|
||||||
vectorModel: dataset.vectorModel,
|
vectorModel: dataset.vectorModel,
|
||||||
vlmModel: dataset.vlmModel,
|
vlmModel: dataset.vlmModel,
|
||||||
|
indexSize: createCollectionParams.indexSize,
|
||||||
mode: getTrainingModeByCollection({
|
mode: getTrainingModeByCollection({
|
||||||
trainingType,
|
trainingType: trainingType,
|
||||||
autoIndexes: createCollectionParams.autoIndexes,
|
autoIndexes: createCollectionParams.autoIndexes,
|
||||||
imageIndex: createCollectionParams.imageIndex
|
imageIndex: createCollectionParams.imageIndex
|
||||||
}),
|
}),
|
||||||
prompt: qaPrompt,
|
prompt: createCollectionParams.qaPrompt,
|
||||||
billId: traingBillId,
|
billId: traingBillId,
|
||||||
data: chunks.map((item, index) => ({
|
data: chunks.map((item, index) => ({
|
||||||
...item,
|
...item,
|
||||||
@@ -207,11 +220,14 @@ export async function createOneCollection({
|
|||||||
// Parse settings
|
// Parse settings
|
||||||
customPdfParse,
|
customPdfParse,
|
||||||
imageIndex,
|
imageIndex,
|
||||||
|
autoIndexes,
|
||||||
|
|
||||||
// Chunk settings
|
// Chunk settings
|
||||||
trainingType = DatasetCollectionDataProcessModeEnum.chunk,
|
trainingType,
|
||||||
autoIndexes,
|
chunkSettingMode,
|
||||||
chunkSize = 512,
|
chunkSplitMode,
|
||||||
|
chunkSize,
|
||||||
|
indexSize,
|
||||||
chunkSplitter,
|
chunkSplitter,
|
||||||
qaPrompt,
|
qaPrompt,
|
||||||
|
|
||||||
@@ -249,11 +265,14 @@ export async function createOneCollection({
|
|||||||
// Parse settings
|
// Parse settings
|
||||||
customPdfParse,
|
customPdfParse,
|
||||||
imageIndex,
|
imageIndex,
|
||||||
|
autoIndexes,
|
||||||
|
|
||||||
// Chunk settings
|
// Chunk settings
|
||||||
trainingType,
|
trainingType,
|
||||||
autoIndexes,
|
chunkSettingMode,
|
||||||
|
chunkSplitMode,
|
||||||
chunkSize,
|
chunkSize,
|
||||||
|
indexSize,
|
||||||
chunkSplitter,
|
chunkSplitter,
|
||||||
qaPrompt
|
qaPrompt
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ const { Schema, model, models } = connectionMongo;
|
|||||||
import { DatasetCollectionSchemaType } from '@fastgpt/global/core/dataset/type.d';
|
import { DatasetCollectionSchemaType } from '@fastgpt/global/core/dataset/type.d';
|
||||||
import {
|
import {
|
||||||
DatasetCollectionTypeMap,
|
DatasetCollectionTypeMap,
|
||||||
DatasetCollectionDataProcessModeEnum
|
DatasetCollectionDataProcessModeEnum,
|
||||||
|
ChunkSettingModeEnum,
|
||||||
|
DataChunkSplitModeEnum
|
||||||
} from '@fastgpt/global/core/dataset/constants';
|
} from '@fastgpt/global/core/dataset/constants';
|
||||||
import { DatasetCollectionName } from '../schema';
|
import { DatasetCollectionName } from '../schema';
|
||||||
import {
|
import {
|
||||||
@@ -94,11 +96,18 @@ const DatasetCollectionSchema = new Schema({
|
|||||||
type: String,
|
type: String,
|
||||||
enum: Object.values(DatasetCollectionDataProcessModeEnum)
|
enum: Object.values(DatasetCollectionDataProcessModeEnum)
|
||||||
},
|
},
|
||||||
chunkSize: {
|
chunkSettingMode: {
|
||||||
type: Number,
|
type: String,
|
||||||
required: true
|
enum: Object.values(ChunkSettingModeEnum)
|
||||||
},
|
},
|
||||||
|
chunkSplitMode: {
|
||||||
|
type: String,
|
||||||
|
enum: Object.values(DataChunkSplitModeEnum)
|
||||||
|
},
|
||||||
|
chunkSize: Number,
|
||||||
chunkSplitter: String,
|
chunkSplitter: String,
|
||||||
|
|
||||||
|
indexSize: Number,
|
||||||
qaPrompt: String
|
qaPrompt: String
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import {
|
|||||||
DatasetCollectionSyncResultEnum,
|
DatasetCollectionSyncResultEnum,
|
||||||
DatasetCollectionTypeEnum,
|
DatasetCollectionTypeEnum,
|
||||||
DatasetSourceReadTypeEnum,
|
DatasetSourceReadTypeEnum,
|
||||||
DatasetTypeEnum,
|
|
||||||
TrainingModeEnum
|
TrainingModeEnum
|
||||||
} from '@fastgpt/global/core/dataset/constants';
|
} from '@fastgpt/global/core/dataset/constants';
|
||||||
import { DatasetErrEnum } from '@fastgpt/global/common/error/code/dataset';
|
import { DatasetErrEnum } from '@fastgpt/global/common/error/code/dataset';
|
||||||
@@ -19,6 +18,7 @@ import { readDatasetSourceRawText } from '../read';
|
|||||||
import { hashStr } from '@fastgpt/global/common/string/tools';
|
import { hashStr } from '@fastgpt/global/common/string/tools';
|
||||||
import { mongoSessionRun } from '../../../common/mongo/sessionRun';
|
import { mongoSessionRun } from '../../../common/mongo/sessionRun';
|
||||||
import { createCollectionAndInsertData, delCollection } from './controller';
|
import { createCollectionAndInsertData, delCollection } from './controller';
|
||||||
|
import { collectionCanSync } from '@fastgpt/global/core/dataset/collection/utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get all collection by top collectionId
|
* get all collection by top collectionId
|
||||||
@@ -137,10 +137,7 @@ export const collectionTagsToTagLabel = async ({
|
|||||||
export const syncCollection = async (collection: CollectionWithDatasetType) => {
|
export const syncCollection = async (collection: CollectionWithDatasetType) => {
|
||||||
const dataset = collection.dataset;
|
const dataset = collection.dataset;
|
||||||
|
|
||||||
if (
|
if (!collectionCanSync(collection.type)) {
|
||||||
collection.type !== DatasetCollectionTypeEnum.link &&
|
|
||||||
dataset.type !== DatasetTypeEnum.apiDataset
|
|
||||||
) {
|
|
||||||
return Promise.reject(DatasetErrEnum.notSupportSync);
|
return Promise.reject(DatasetErrEnum.notSupportSync);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,15 +152,20 @@ export const syncCollection = async (collection: CollectionWithDatasetType) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!collection.apiFileId) return Promise.reject('apiFileId is missing');
|
const sourceId = collection.apiFileId;
|
||||||
if (!dataset.apiServer) return Promise.reject('apiServer not found');
|
|
||||||
|
if (!sourceId) return Promise.reject('apiFileId is missing');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: DatasetSourceReadTypeEnum.apiFile,
|
type: DatasetSourceReadTypeEnum.apiFile,
|
||||||
sourceId: collection.apiFileId,
|
sourceId,
|
||||||
apiServer: dataset.apiServer
|
apiServer: dataset.apiServer,
|
||||||
|
feishuServer: dataset.feishuServer,
|
||||||
|
yuqueServer: dataset.yuqueServer
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
const rawText = await readDatasetSourceRawText({
|
|
||||||
|
const { title, rawText } = await readDatasetSourceRawText({
|
||||||
teamId: collection.teamId,
|
teamId: collection.teamId,
|
||||||
tmbId: collection.tmbId,
|
tmbId: collection.tmbId,
|
||||||
...sourceReadType
|
...sourceReadType
|
||||||
@@ -196,7 +198,7 @@ export const syncCollection = async (collection: CollectionWithDatasetType) => {
|
|||||||
createCollectionParams: {
|
createCollectionParams: {
|
||||||
teamId: collection.teamId,
|
teamId: collection.teamId,
|
||||||
tmbId: collection.tmbId,
|
tmbId: collection.tmbId,
|
||||||
name: collection.name,
|
name: title || collection.name,
|
||||||
datasetId: collection.datasetId,
|
datasetId: collection.datasetId,
|
||||||
parentId: collection.parentId,
|
parentId: collection.parentId,
|
||||||
type: collection.type,
|
type: collection.type,
|
||||||
|
|||||||
@@ -79,9 +79,12 @@ export const readDatasetSourceRawText = async ({
|
|||||||
apiServer?: APIFileServer; // api dataset
|
apiServer?: APIFileServer; // api dataset
|
||||||
feishuServer?: FeishuServer; // feishu dataset
|
feishuServer?: FeishuServer; // feishu dataset
|
||||||
yuqueServer?: YuqueServer; // yuque dataset
|
yuqueServer?: YuqueServer; // yuque dataset
|
||||||
}): Promise<string> => {
|
}): Promise<{
|
||||||
|
title?: string;
|
||||||
|
rawText: string;
|
||||||
|
}> => {
|
||||||
if (type === DatasetSourceReadTypeEnum.fileLocal) {
|
if (type === DatasetSourceReadTypeEnum.fileLocal) {
|
||||||
const { rawText } = await readFileContentFromMongo({
|
const { filename, rawText } = await readFileContentFromMongo({
|
||||||
teamId,
|
teamId,
|
||||||
tmbId,
|
tmbId,
|
||||||
bucketName: BucketNameEnum.dataset,
|
bucketName: BucketNameEnum.dataset,
|
||||||
@@ -89,14 +92,20 @@ export const readDatasetSourceRawText = async ({
|
|||||||
isQAImport,
|
isQAImport,
|
||||||
customPdfParse
|
customPdfParse
|
||||||
});
|
});
|
||||||
return rawText;
|
return {
|
||||||
|
title: filename,
|
||||||
|
rawText
|
||||||
|
};
|
||||||
} else if (type === DatasetSourceReadTypeEnum.link) {
|
} else if (type === DatasetSourceReadTypeEnum.link) {
|
||||||
const result = await urlsFetch({
|
const result = await urlsFetch({
|
||||||
urlList: [sourceId],
|
urlList: [sourceId],
|
||||||
selector
|
selector
|
||||||
});
|
});
|
||||||
|
|
||||||
return result[0]?.content || '';
|
return {
|
||||||
|
title: result[0]?.title,
|
||||||
|
rawText: result[0]?.content || ''
|
||||||
|
};
|
||||||
} else if (type === DatasetSourceReadTypeEnum.externalFile) {
|
} else if (type === DatasetSourceReadTypeEnum.externalFile) {
|
||||||
if (!externalFileId) return Promise.reject('FileId not found');
|
if (!externalFileId) return Promise.reject('FileId not found');
|
||||||
const rawText = await readFileRawTextByUrl({
|
const rawText = await readFileRawTextByUrl({
|
||||||
@@ -106,9 +115,11 @@ export const readDatasetSourceRawText = async ({
|
|||||||
relatedId: externalFileId,
|
relatedId: externalFileId,
|
||||||
customPdfParse
|
customPdfParse
|
||||||
});
|
});
|
||||||
return rawText;
|
return {
|
||||||
|
rawText
|
||||||
|
};
|
||||||
} else if (type === DatasetSourceReadTypeEnum.apiFile) {
|
} else if (type === DatasetSourceReadTypeEnum.apiFile) {
|
||||||
const rawText = await readApiServerFileContent({
|
const { title, rawText } = await readApiServerFileContent({
|
||||||
apiServer,
|
apiServer,
|
||||||
feishuServer,
|
feishuServer,
|
||||||
yuqueServer,
|
yuqueServer,
|
||||||
@@ -116,9 +127,15 @@ export const readDatasetSourceRawText = async ({
|
|||||||
teamId,
|
teamId,
|
||||||
tmbId
|
tmbId
|
||||||
});
|
});
|
||||||
return rawText;
|
return {
|
||||||
|
title,
|
||||||
|
rawText
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return '';
|
return {
|
||||||
|
title: '',
|
||||||
|
rawText: ''
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const readApiServerFileContent = async ({
|
export const readApiServerFileContent = async ({
|
||||||
@@ -137,7 +154,10 @@ export const readApiServerFileContent = async ({
|
|||||||
teamId: string;
|
teamId: string;
|
||||||
tmbId: string;
|
tmbId: string;
|
||||||
customPdfParse?: boolean;
|
customPdfParse?: boolean;
|
||||||
}) => {
|
}): Promise<{
|
||||||
|
title?: string;
|
||||||
|
rawText: string;
|
||||||
|
}> => {
|
||||||
if (apiServer) {
|
if (apiServer) {
|
||||||
return useApiDatasetRequest({ apiServer }).getFileContent({
|
return useApiDatasetRequest({ apiServer }).getFileContent({
|
||||||
teamId,
|
teamId,
|
||||||
@@ -148,7 +168,10 @@ export const readApiServerFileContent = async ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (feishuServer || yuqueServer) {
|
if (feishuServer || yuqueServer) {
|
||||||
return POST<string>(`/core/dataset/systemApiDataset`, {
|
return POST<{
|
||||||
|
title?: string;
|
||||||
|
rawText: string;
|
||||||
|
}>(`/core/dataset/systemApiDataset`, {
|
||||||
type: 'content',
|
type: 'content',
|
||||||
feishuServer,
|
feishuServer,
|
||||||
yuqueServer,
|
yuqueServer,
|
||||||
@@ -162,7 +185,7 @@ export const readApiServerFileContent = async ({
|
|||||||
export const rawText2Chunks = ({
|
export const rawText2Chunks = ({
|
||||||
rawText,
|
rawText,
|
||||||
isQAImport,
|
isQAImport,
|
||||||
chunkLen = 512,
|
chunkSize = 512,
|
||||||
...splitProps
|
...splitProps
|
||||||
}: {
|
}: {
|
||||||
rawText: string;
|
rawText: string;
|
||||||
@@ -175,7 +198,7 @@ export const rawText2Chunks = ({
|
|||||||
|
|
||||||
const { chunks } = splitText2Chunks({
|
const { chunks } = splitText2Chunks({
|
||||||
text: rawText,
|
text: rawText,
|
||||||
chunkLen,
|
chunkSize,
|
||||||
...splitProps
|
...splitProps
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -134,12 +134,10 @@ export const filterDatasetDataByMaxTokens = async (
|
|||||||
let totalTokens = 0;
|
let totalTokens = 0;
|
||||||
|
|
||||||
for await (const item of tokensScoreFilter) {
|
for await (const item of tokensScoreFilter) {
|
||||||
|
results.push(item);
|
||||||
|
|
||||||
totalTokens += item.tokens;
|
totalTokens += item.tokens;
|
||||||
|
|
||||||
if (totalTokens > maxTokens + 500) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
results.push(item);
|
|
||||||
if (totalTokens > maxTokens) {
|
if (totalTokens > maxTokens) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ import { getCollectionWithDataset } from '../controller';
|
|||||||
import { mongoSessionRun } from '../../../common/mongo/sessionRun';
|
import { mongoSessionRun } from '../../../common/mongo/sessionRun';
|
||||||
import { PushDataToTrainingQueueProps } from '@fastgpt/global/core/dataset/training/type';
|
import { PushDataToTrainingQueueProps } from '@fastgpt/global/core/dataset/training/type';
|
||||||
import { i18nT } from '../../../../web/i18n/utils';
|
import { i18nT } from '../../../../web/i18n/utils';
|
||||||
|
import {
|
||||||
|
getLLMDefaultChunkSize,
|
||||||
|
getLLMMaxChunkSize
|
||||||
|
} from '../../../../global/core/dataset/training/utils';
|
||||||
|
|
||||||
export const lockTrainingDataByTeamId = async (teamId: string): Promise<any> => {
|
export const lockTrainingDataByTeamId = async (teamId: string): Promise<any> => {
|
||||||
try {
|
try {
|
||||||
@@ -55,6 +59,7 @@ export async function pushDataListToTrainingQueue({
|
|||||||
prompt,
|
prompt,
|
||||||
billId,
|
billId,
|
||||||
mode = TrainingModeEnum.chunk,
|
mode = TrainingModeEnum.chunk,
|
||||||
|
indexSize,
|
||||||
session
|
session
|
||||||
}: PushDataToTrainingQueueProps): Promise<PushDatasetDataResponse> {
|
}: PushDataToTrainingQueueProps): Promise<PushDatasetDataResponse> {
|
||||||
const getImageChunkMode = (data: PushDatasetDataChunkProps, mode: TrainingModeEnum) => {
|
const getImageChunkMode = (data: PushDatasetDataChunkProps, mode: TrainingModeEnum) => {
|
||||||
@@ -68,38 +73,41 @@ export async function pushDataListToTrainingQueue({
|
|||||||
}
|
}
|
||||||
return mode;
|
return mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const vectorModelData = getEmbeddingModel(vectorModel);
|
||||||
|
if (!vectorModelData) {
|
||||||
|
return Promise.reject(i18nT('common:error_embedding_not_config'));
|
||||||
|
}
|
||||||
|
const agentModelData = getLLMModel(agentModel);
|
||||||
|
if (!agentModelData) {
|
||||||
|
return Promise.reject(i18nT('common:error_llm_not_config'));
|
||||||
|
}
|
||||||
|
if (mode === TrainingModeEnum.chunk || mode === TrainingModeEnum.auto) {
|
||||||
|
prompt = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
const { model, maxToken, weight } = await (async () => {
|
const { model, maxToken, weight } = await (async () => {
|
||||||
if (mode === TrainingModeEnum.chunk) {
|
if (mode === TrainingModeEnum.chunk) {
|
||||||
const vectorModelData = getEmbeddingModel(vectorModel);
|
|
||||||
if (!vectorModelData) {
|
|
||||||
return Promise.reject(i18nT('common:error_embedding_not_config'));
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
maxToken: vectorModelData.maxToken * 1.5,
|
maxToken: getLLMMaxChunkSize(agentModelData),
|
||||||
model: vectorModelData.model,
|
model: vectorModelData.model,
|
||||||
weight: vectorModelData.weight
|
weight: vectorModelData.weight
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode === TrainingModeEnum.qa || mode === TrainingModeEnum.auto) {
|
if (mode === TrainingModeEnum.qa || mode === TrainingModeEnum.auto) {
|
||||||
const agentModelData = getLLMModel(agentModel);
|
|
||||||
if (!agentModelData) {
|
|
||||||
return Promise.reject(i18nT('common:error_llm_not_config'));
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
maxToken: agentModelData.maxContext * 0.8,
|
maxToken: getLLMMaxChunkSize(agentModelData),
|
||||||
model: agentModelData.model,
|
model: agentModelData.model,
|
||||||
weight: 0
|
weight: 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode === TrainingModeEnum.image) {
|
if (mode === TrainingModeEnum.image) {
|
||||||
const vllmModelData = getVlmModel(vlmModel);
|
const vllmModelData = getVlmModel(vlmModel);
|
||||||
if (!vllmModelData) {
|
if (!vllmModelData) {
|
||||||
return Promise.reject(i18nT('common:error_vlm_not_config'));
|
return Promise.reject(i18nT('common:error_vlm_not_config'));
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
maxToken: vllmModelData.maxContext * 0.8,
|
maxToken: getLLMMaxChunkSize(vllmModelData),
|
||||||
model: vllmModelData.model,
|
model: vllmModelData.model,
|
||||||
weight: 0
|
weight: 0
|
||||||
};
|
};
|
||||||
@@ -107,10 +115,6 @@ export async function pushDataListToTrainingQueue({
|
|||||||
|
|
||||||
return Promise.reject(`Training mode "${mode}" is inValid`);
|
return Promise.reject(`Training mode "${mode}" is inValid`);
|
||||||
})();
|
})();
|
||||||
// Filter redundant params
|
|
||||||
if (mode === TrainingModeEnum.chunk || mode === TrainingModeEnum.auto) {
|
|
||||||
prompt = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// filter repeat or equal content
|
// filter repeat or equal content
|
||||||
const set = new Set();
|
const set = new Set();
|
||||||
@@ -143,13 +147,13 @@ export async function pushDataListToTrainingQueue({
|
|||||||
|
|
||||||
const text = item.q + item.a;
|
const text = item.q + item.a;
|
||||||
|
|
||||||
|
// Oversize llm tokens
|
||||||
if (text.length > maxToken) {
|
if (text.length > maxToken) {
|
||||||
filterResult.overToken.push(item);
|
filterResult.overToken.push(item);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (set.has(text)) {
|
if (set.has(text)) {
|
||||||
console.log('repeat', item);
|
|
||||||
filterResult.repeat.push(item);
|
filterResult.repeat.push(item);
|
||||||
} else {
|
} else {
|
||||||
filterResult.success.push(item);
|
filterResult.success.push(item);
|
||||||
@@ -182,6 +186,7 @@ export async function pushDataListToTrainingQueue({
|
|||||||
q: item.q,
|
q: item.q,
|
||||||
a: item.a,
|
a: item.a,
|
||||||
chunkIndex: item.chunkIndex ?? 0,
|
chunkIndex: item.chunkIndex ?? 0,
|
||||||
|
indexSize,
|
||||||
weight: weight ?? 0,
|
weight: weight ?? 0,
|
||||||
indexes: item.indexes,
|
indexes: item.indexes,
|
||||||
retryCount: 5
|
retryCount: 5
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ const TrainingDataSchema = new Schema({
|
|||||||
type: Number,
|
type: Number,
|
||||||
default: 0
|
default: 0
|
||||||
},
|
},
|
||||||
|
indexSize: Number,
|
||||||
weight: {
|
weight: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 0
|
default: 0
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ import type { ClassifyQuestionAgentItemType } from '@fastgpt/global/core/workflo
|
|||||||
import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
|
import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
|
||||||
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
|
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
|
||||||
import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type';
|
import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type';
|
||||||
import { replaceVariable } from '@fastgpt/global/common/string/tools';
|
import { getCQPrompt } from '@fastgpt/global/core/ai/prompt/agent';
|
||||||
import { Prompt_CQJson } from '@fastgpt/global/core/ai/prompt/agent';
|
|
||||||
import { LLMModelItemType } from '@fastgpt/global/core/ai/model.d';
|
import { LLMModelItemType } from '@fastgpt/global/core/ai/model.d';
|
||||||
import { getLLMModel } from '../../../ai/model';
|
import { getLLMModel } from '../../../ai/model';
|
||||||
import { getHistories } from '../utils';
|
import { getHistories } from '../utils';
|
||||||
@@ -23,6 +22,7 @@ import { loadRequestMessages } from '../../../chat/utils';
|
|||||||
import { llmCompletionsBodyFormat } from '../../../ai/utils';
|
import { llmCompletionsBodyFormat } from '../../../ai/utils';
|
||||||
import { addLog } from '../../../../common/system/log';
|
import { addLog } from '../../../../common/system/log';
|
||||||
import { ModelTypeEnum } from '../../../../../global/core/ai/model';
|
import { ModelTypeEnum } from '../../../../../global/core/ai/model';
|
||||||
|
import { replaceVariable } from '@fastgpt/global/common/string/tools';
|
||||||
|
|
||||||
type Props = ModuleDispatchProps<{
|
type Props = ModuleDispatchProps<{
|
||||||
[NodeInputKeyEnum.aiModel]: string;
|
[NodeInputKeyEnum.aiModel]: string;
|
||||||
@@ -99,7 +99,8 @@ const completions = async ({
|
|||||||
cqModel,
|
cqModel,
|
||||||
externalProvider,
|
externalProvider,
|
||||||
histories,
|
histories,
|
||||||
params: { agents, systemPrompt = '', userChatInput }
|
params: { agents, systemPrompt = '', userChatInput },
|
||||||
|
node: { version }
|
||||||
}: ActionProps) => {
|
}: ActionProps) => {
|
||||||
const messages: ChatItemType[] = [
|
const messages: ChatItemType[] = [
|
||||||
{
|
{
|
||||||
@@ -108,7 +109,7 @@ const completions = async ({
|
|||||||
{
|
{
|
||||||
type: ChatItemValueTypeEnum.text,
|
type: ChatItemValueTypeEnum.text,
|
||||||
text: {
|
text: {
|
||||||
content: replaceVariable(cqModel.customCQPrompt || Prompt_CQJson, {
|
content: replaceVariable(cqModel.customCQPrompt || getCQPrompt(version), {
|
||||||
systemPrompt: systemPrompt || 'null',
|
systemPrompt: systemPrompt || 'null',
|
||||||
typeList: agents
|
typeList: agents
|
||||||
.map((item) => `{"类型ID":"${item.key}", "问题类型":"${item.value}"}`)
|
.map((item) => `{"类型ID":"${item.key}", "问题类型":"${item.value}"}`)
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import {
|
|||||||
} from '@fastgpt/global/core/workflow/constants';
|
} from '@fastgpt/global/core/workflow/constants';
|
||||||
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
|
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
|
||||||
import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type';
|
import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type';
|
||||||
import { Prompt_ExtractJson } from '@fastgpt/global/core/ai/prompt/agent';
|
|
||||||
import { replaceVariable, sliceJsonStr } from '@fastgpt/global/common/string/tools';
|
import { replaceVariable, sliceJsonStr } from '@fastgpt/global/common/string/tools';
|
||||||
import { LLMModelItemType } from '@fastgpt/global/core/ai/model.d';
|
import { LLMModelItemType } from '@fastgpt/global/core/ai/model.d';
|
||||||
import { getHistories } from '../utils';
|
import { getHistories } from '../utils';
|
||||||
@@ -33,6 +32,10 @@ import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/ty
|
|||||||
import { chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt';
|
import { chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt';
|
||||||
import { llmCompletionsBodyFormat } from '../../../ai/utils';
|
import { llmCompletionsBodyFormat } from '../../../ai/utils';
|
||||||
import { ModelTypeEnum } from '../../../../../global/core/ai/model';
|
import { ModelTypeEnum } from '../../../../../global/core/ai/model';
|
||||||
|
import {
|
||||||
|
getExtractJsonPrompt,
|
||||||
|
getExtractJsonToolPrompt
|
||||||
|
} from '@fastgpt/global/core/ai/prompt/agent';
|
||||||
|
|
||||||
type Props = ModuleDispatchProps<{
|
type Props = ModuleDispatchProps<{
|
||||||
[NodeInputKeyEnum.history]?: ChatItemType[];
|
[NodeInputKeyEnum.history]?: ChatItemType[];
|
||||||
@@ -154,7 +157,8 @@ export async function dispatchContentExtract(props: Props): Promise<Response> {
|
|||||||
const getFunctionCallSchema = async ({
|
const getFunctionCallSchema = async ({
|
||||||
extractModel,
|
extractModel,
|
||||||
histories,
|
histories,
|
||||||
params: { content, extractKeys, description }
|
params: { content, extractKeys, description },
|
||||||
|
node: { version }
|
||||||
}: ActionProps) => {
|
}: ActionProps) => {
|
||||||
const messages: ChatItemType[] = [
|
const messages: ChatItemType[] = [
|
||||||
...histories,
|
...histories,
|
||||||
@@ -164,15 +168,10 @@ const getFunctionCallSchema = async ({
|
|||||||
{
|
{
|
||||||
type: ChatItemValueTypeEnum.text,
|
type: ChatItemValueTypeEnum.text,
|
||||||
text: {
|
text: {
|
||||||
content: `我正在执行一个函数,需要你提供一些参数,请以 JSON 字符串格式返回这些参数,要求:
|
content: replaceVariable(getExtractJsonToolPrompt(version), {
|
||||||
"""
|
description,
|
||||||
${description ? `- ${description}` : ''}
|
content
|
||||||
- 不是每个参数都是必须生成的,如果没有合适的参数值,不要生成该参数,或返回空字符串。
|
})
|
||||||
- 需要结合前面的对话内容,一起生成合适的参数。
|
|
||||||
"""
|
|
||||||
|
|
||||||
本次输入内容: """${content}"""
|
|
||||||
`
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -334,7 +333,8 @@ const completions = async ({
|
|||||||
extractModel,
|
extractModel,
|
||||||
externalProvider,
|
externalProvider,
|
||||||
histories,
|
histories,
|
||||||
params: { content, extractKeys, description = 'No special requirements' }
|
params: { content, extractKeys, description = 'No special requirements' },
|
||||||
|
node: { version }
|
||||||
}: ActionProps) => {
|
}: ActionProps) => {
|
||||||
const messages: ChatItemType[] = [
|
const messages: ChatItemType[] = [
|
||||||
{
|
{
|
||||||
@@ -343,23 +343,26 @@ const completions = async ({
|
|||||||
{
|
{
|
||||||
type: ChatItemValueTypeEnum.text,
|
type: ChatItemValueTypeEnum.text,
|
||||||
text: {
|
text: {
|
||||||
content: replaceVariable(extractModel.customExtractPrompt || Prompt_ExtractJson, {
|
content: replaceVariable(
|
||||||
description,
|
extractModel.customExtractPrompt || getExtractJsonPrompt(version),
|
||||||
json: extractKeys
|
{
|
||||||
.map((item) => {
|
description,
|
||||||
const valueType = item.valueType || 'string';
|
json: extractKeys
|
||||||
if (valueType !== 'string' && valueType !== 'number') {
|
.map((item) => {
|
||||||
item.enum = undefined;
|
const valueType = item.valueType || 'string';
|
||||||
}
|
if (valueType !== 'string' && valueType !== 'number') {
|
||||||
|
item.enum = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
return `{"type":${item.valueType || 'string'}, "key":"${item.key}", "description":"${item.desc}" ${
|
return `{"type":${item.valueType || 'string'}, "key":"${item.key}", "description":"${item.desc}" ${
|
||||||
item.enum ? `, "enum":"[${item.enum.split('\n')}]"` : ''
|
item.enum ? `, "enum":"[${item.enum.split('\n')}]"` : ''
|
||||||
}}`;
|
}}`;
|
||||||
})
|
})
|
||||||
.join('\n'),
|
.join('\n'),
|
||||||
text: `${histories.map((item) => `${item.obj}:${chatValue2RuntimePrompt(item.value).text}`).join('\n')}
|
text: `${histories.map((item) => `${item.obj}:${chatValue2RuntimePrompt(item.value).text}`).join('\n')}
|
||||||
Human: ${content}`
|
Human: ${content}`
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ import { filterToolResponseToPreview } from './utils';
|
|||||||
import { InteractiveNodeResponseType } from '@fastgpt/global/core/workflow/template/system/interactive/type';
|
import { InteractiveNodeResponseType } from '@fastgpt/global/core/workflow/template/system/interactive/type';
|
||||||
import { getFileContentFromLinks, getHistoryFileLinks } from '../../tools/readFiles';
|
import { getFileContentFromLinks, getHistoryFileLinks } from '../../tools/readFiles';
|
||||||
import { parseUrlToFileType } from '@fastgpt/global/common/file/tools';
|
import { parseUrlToFileType } from '@fastgpt/global/common/file/tools';
|
||||||
import { Prompt_DocumentQuote } from '@fastgpt/global/core/ai/prompt/AIChat';
|
|
||||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
||||||
import { postTextCensor } from '../../../../../common/api/requestPlusApi';
|
import { postTextCensor } from '../../../../../common/api/requestPlusApi';
|
||||||
import { ModelTypeEnum } from '@fastgpt/global/core/ai/model';
|
import { ModelTypeEnum } from '@fastgpt/global/core/ai/model';
|
||||||
|
import { getDocumentQuotePrompt } from '@fastgpt/global/core/ai/prompt/AIChat';
|
||||||
|
|
||||||
type Response = DispatchNodeResultType<{
|
type Response = DispatchNodeResultType<{
|
||||||
[NodeOutputKeyEnum.answerText]: string;
|
[NodeOutputKeyEnum.answerText]: string;
|
||||||
@@ -40,7 +40,7 @@ type Response = DispatchNodeResultType<{
|
|||||||
|
|
||||||
export const dispatchRunTools = async (props: DispatchToolModuleProps): Promise<Response> => {
|
export const dispatchRunTools = async (props: DispatchToolModuleProps): Promise<Response> => {
|
||||||
const {
|
const {
|
||||||
node: { nodeId, name, isEntry },
|
node: { nodeId, name, isEntry, version },
|
||||||
runtimeNodes,
|
runtimeNodes,
|
||||||
runtimeEdges,
|
runtimeEdges,
|
||||||
histories,
|
histories,
|
||||||
@@ -118,7 +118,7 @@ export const dispatchRunTools = async (props: DispatchToolModuleProps): Promise<
|
|||||||
toolModel.defaultSystemChatPrompt,
|
toolModel.defaultSystemChatPrompt,
|
||||||
systemPrompt,
|
systemPrompt,
|
||||||
documentQuoteText
|
documentQuoteText
|
||||||
? replaceVariable(Prompt_DocumentQuote, {
|
? replaceVariable(getDocumentQuotePrompt(version), {
|
||||||
quote: documentQuoteText
|
quote: documentQuoteText
|
||||||
})
|
})
|
||||||
: ''
|
: ''
|
||||||
|
|||||||
@@ -24,10 +24,9 @@ import {
|
|||||||
runtimePrompt2ChatsValue
|
runtimePrompt2ChatsValue
|
||||||
} from '@fastgpt/global/core/chat/adapt';
|
} from '@fastgpt/global/core/chat/adapt';
|
||||||
import {
|
import {
|
||||||
Prompt_DocumentQuote,
|
getQuoteTemplate,
|
||||||
Prompt_userQuotePromptList,
|
getQuotePrompt,
|
||||||
Prompt_QuoteTemplateList,
|
getDocumentQuotePrompt
|
||||||
Prompt_systemQuotePromptList
|
|
||||||
} from '@fastgpt/global/core/ai/prompt/AIChat';
|
} from '@fastgpt/global/core/ai/prompt/AIChat';
|
||||||
import type { AIChatNodeProps } from '@fastgpt/global/core/workflow/runtime/type.d';
|
import type { AIChatNodeProps } from '@fastgpt/global/core/workflow/runtime/type.d';
|
||||||
import { replaceVariable } from '@fastgpt/global/common/string/tools';
|
import { replaceVariable } from '@fastgpt/global/common/string/tools';
|
||||||
@@ -70,7 +69,7 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise<ChatResp
|
|||||||
stream = false,
|
stream = false,
|
||||||
externalProvider,
|
externalProvider,
|
||||||
histories,
|
histories,
|
||||||
node: { name },
|
node: { name, version },
|
||||||
query,
|
query,
|
||||||
runningUserInfo,
|
runningUserInfo,
|
||||||
workflowStreamResponse,
|
workflowStreamResponse,
|
||||||
@@ -115,7 +114,7 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise<ChatResp
|
|||||||
filterDatasetQuote({
|
filterDatasetQuote({
|
||||||
quoteQA,
|
quoteQA,
|
||||||
model: modelConstantsData,
|
model: modelConstantsData,
|
||||||
quoteTemplate
|
quoteTemplate: quoteTemplate || getQuoteTemplate(version)
|
||||||
}),
|
}),
|
||||||
getMultiInput({
|
getMultiInput({
|
||||||
histories: chatHistories,
|
histories: chatHistories,
|
||||||
@@ -147,6 +146,7 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise<ChatResp
|
|||||||
datasetQuoteText,
|
datasetQuoteText,
|
||||||
aiChatQuoteRole,
|
aiChatQuoteRole,
|
||||||
datasetQuotePrompt: quotePrompt,
|
datasetQuotePrompt: quotePrompt,
|
||||||
|
version,
|
||||||
userChatInput,
|
userChatInput,
|
||||||
systemPrompt,
|
systemPrompt,
|
||||||
userFiles,
|
userFiles,
|
||||||
@@ -326,10 +326,10 @@ async function filterDatasetQuote({
|
|||||||
}: {
|
}: {
|
||||||
quoteQA: ChatProps['params']['quoteQA'];
|
quoteQA: ChatProps['params']['quoteQA'];
|
||||||
model: LLMModelItemType;
|
model: LLMModelItemType;
|
||||||
quoteTemplate?: string;
|
quoteTemplate: string;
|
||||||
}) {
|
}) {
|
||||||
function getValue(item: SearchDataResponseItemType, index: number) {
|
function getValue(item: SearchDataResponseItemType, index: number) {
|
||||||
return replaceVariable(quoteTemplate || Prompt_QuoteTemplateList[0].value, {
|
return replaceVariable(quoteTemplate, {
|
||||||
id: item.id,
|
id: item.id,
|
||||||
q: item.q,
|
q: item.q,
|
||||||
a: item.a,
|
a: item.a,
|
||||||
@@ -425,6 +425,7 @@ async function getChatMessages({
|
|||||||
datasetQuotePrompt = '',
|
datasetQuotePrompt = '',
|
||||||
datasetQuoteText,
|
datasetQuoteText,
|
||||||
useDatasetQuote,
|
useDatasetQuote,
|
||||||
|
version,
|
||||||
histories = [],
|
histories = [],
|
||||||
systemPrompt,
|
systemPrompt,
|
||||||
userChatInput,
|
userChatInput,
|
||||||
@@ -437,6 +438,7 @@ async function getChatMessages({
|
|||||||
aiChatQuoteRole: AiChatQuoteRoleType; // user: replace user prompt; system: replace system prompt
|
aiChatQuoteRole: AiChatQuoteRoleType; // user: replace user prompt; system: replace system prompt
|
||||||
datasetQuotePrompt?: string;
|
datasetQuotePrompt?: string;
|
||||||
datasetQuoteText: string;
|
datasetQuoteText: string;
|
||||||
|
version: string;
|
||||||
|
|
||||||
useDatasetQuote: boolean;
|
useDatasetQuote: boolean;
|
||||||
histories: ChatItemType[];
|
histories: ChatItemType[];
|
||||||
@@ -451,11 +453,7 @@ async function getChatMessages({
|
|||||||
const quoteRole =
|
const quoteRole =
|
||||||
aiChatQuoteRole === 'user' || datasetQuotePrompt.includes('{{question}}') ? 'user' : 'system';
|
aiChatQuoteRole === 'user' || datasetQuotePrompt.includes('{{question}}') ? 'user' : 'system';
|
||||||
|
|
||||||
const datasetQuotePromptTemplate = datasetQuotePrompt
|
const datasetQuotePromptTemplate = datasetQuotePrompt || getQuotePrompt(version, quoteRole);
|
||||||
? datasetQuotePrompt
|
|
||||||
: quoteRole === 'user'
|
|
||||||
? Prompt_userQuotePromptList[0].value
|
|
||||||
: Prompt_systemQuotePromptList[0].value;
|
|
||||||
|
|
||||||
// Reset user input, add dataset quote to user input
|
// Reset user input, add dataset quote to user input
|
||||||
const replaceInputValue =
|
const replaceInputValue =
|
||||||
@@ -477,7 +475,7 @@ async function getChatMessages({
|
|||||||
})
|
})
|
||||||
: '',
|
: '',
|
||||||
documentQuoteText
|
documentQuoteText
|
||||||
? replaceVariable(Prompt_DocumentQuote, {
|
? replaceVariable(getDocumentQuotePrompt(version), {
|
||||||
quote: documentQuoteText
|
quote: documentQuoteText
|
||||||
})
|
})
|
||||||
: ''
|
: ''
|
||||||
|
|||||||
@@ -88,9 +88,9 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
|
|||||||
: {}),
|
: {}),
|
||||||
runningAppInfo: {
|
runningAppInfo: {
|
||||||
id: String(plugin.id),
|
id: String(plugin.id),
|
||||||
// 如果是系统插件,则使用当前团队的 teamId 和 tmbId
|
// 如果系统插件有 teamId 和 tmbId,则使用系统插件的 teamId 和 tmbId(管理员指定了插件作为系统插件)
|
||||||
teamId: plugin.teamId || runningAppInfo.teamId,
|
teamId: plugin.teamId || runningAppInfo.teamId,
|
||||||
tmbId: pluginData?.tmbId || runningAppInfo.tmbId
|
tmbId: plugin.tmbId || runningAppInfo.tmbId
|
||||||
},
|
},
|
||||||
variables: runtimeVariables,
|
variables: runtimeVariables,
|
||||||
query: getPluginRunUserQuery({
|
query: getPluginRunUserQuery({
|
||||||
|
|||||||
@@ -117,6 +117,9 @@ export const valueTypeFormat = (value: any, type?: WorkflowIOValueTypeEnum) => {
|
|||||||
return Boolean(value);
|
return Boolean(value);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
if (WorkflowIOValueTypeEnum.arrayString && typeof value === 'string') {
|
||||||
|
return [value];
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
type &&
|
type &&
|
||||||
[
|
[
|
||||||
@@ -124,7 +127,12 @@ export const valueTypeFormat = (value: any, type?: WorkflowIOValueTypeEnum) => {
|
|||||||
WorkflowIOValueTypeEnum.chatHistory,
|
WorkflowIOValueTypeEnum.chatHistory,
|
||||||
WorkflowIOValueTypeEnum.datasetQuote,
|
WorkflowIOValueTypeEnum.datasetQuote,
|
||||||
WorkflowIOValueTypeEnum.selectApp,
|
WorkflowIOValueTypeEnum.selectApp,
|
||||||
WorkflowIOValueTypeEnum.selectDataset
|
WorkflowIOValueTypeEnum.selectDataset,
|
||||||
|
WorkflowIOValueTypeEnum.arrayString,
|
||||||
|
WorkflowIOValueTypeEnum.arrayNumber,
|
||||||
|
WorkflowIOValueTypeEnum.arrayBoolean,
|
||||||
|
WorkflowIOValueTypeEnum.arrayObject,
|
||||||
|
WorkflowIOValueTypeEnum.arrayAny
|
||||||
].includes(type) &&
|
].includes(type) &&
|
||||||
typeof value !== 'object'
|
typeof value !== 'object'
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
"mammoth": "^1.6.0",
|
"mammoth": "^1.6.0",
|
||||||
"mongoose": "^8.10.1",
|
"mongoose": "^8.10.1",
|
||||||
"multer": "1.4.5-lts.1",
|
"multer": "1.4.5-lts.1",
|
||||||
"next": "14.2.24",
|
"next": "14.2.25",
|
||||||
"nextjs-cors": "^2.2.0",
|
"nextjs-cors": "^2.2.0",
|
||||||
"node-cron": "^3.0.3",
|
"node-cron": "^3.0.3",
|
||||||
"node-xlsx": "^0.24.0",
|
"node-xlsx": "^0.24.0",
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export const authOrgMember = async ({
|
|||||||
orgIds,
|
orgIds,
|
||||||
...props
|
...props
|
||||||
}: {
|
}: {
|
||||||
orgIds: string | string[];
|
orgIds?: string | string[];
|
||||||
} & AuthModeType): Promise<AuthResponseType> => {
|
} & AuthModeType): Promise<AuthResponseType> => {
|
||||||
const result = await authUserPer({
|
const result = await authUserPer({
|
||||||
...props,
|
...props,
|
||||||
|
|||||||
@@ -90,6 +90,6 @@ export async function createRootOrg({
|
|||||||
path: ''
|
path: ''
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
{ session }
|
{ session, ordered: true }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,14 @@ async function getTeamMember(match: Record<string, any>): Promise<TeamTmbItemTyp
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getTeamOwner = async (teamId: string) => {
|
||||||
|
const tmb = await MongoTeamMember.findOne({
|
||||||
|
teamId,
|
||||||
|
role: TeamMemberRoleEnum.owner
|
||||||
|
}).lean();
|
||||||
|
return tmb;
|
||||||
|
};
|
||||||
|
|
||||||
export async function getTmbInfoByTmbId({ tmbId }: { tmbId: string }) {
|
export async function getTmbInfoByTmbId({ tmbId }: { tmbId: string }) {
|
||||||
if (!tmbId) {
|
if (!tmbId) {
|
||||||
return Promise.reject('tmbId or userId is required');
|
return Promise.reject('tmbId or userId is required');
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
import {
|
|
||||||
TeamCollectionName,
|
|
||||||
TeamMemberCollectionName
|
|
||||||
} from '@fastgpt/global/support/user/team/constant';
|
|
||||||
import { connectionMongo, getMongoModel } from '../../../../common/mongo';
|
|
||||||
import { InvitationSchemaType } from './type';
|
|
||||||
import addDays from 'date-fns/esm/fp/addDays/index.js';
|
|
||||||
const { Schema } = connectionMongo;
|
|
||||||
|
|
||||||
export const InvitationCollectionName = 'team_invitation_links';
|
|
||||||
|
|
||||||
const InvitationSchema = new Schema({
|
|
||||||
teamId: {
|
|
||||||
type: Schema.Types.ObjectId,
|
|
||||||
ref: TeamCollectionName,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
usedTimesLimit: {
|
|
||||||
type: Number,
|
|
||||||
default: 1,
|
|
||||||
enum: [1, -1]
|
|
||||||
},
|
|
||||||
forbidden: Boolean,
|
|
||||||
expires: Date,
|
|
||||||
description: String,
|
|
||||||
members: {
|
|
||||||
type: [String],
|
|
||||||
default: []
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
InvitationSchema.virtual('team', {
|
|
||||||
ref: TeamCollectionName,
|
|
||||||
localField: 'teamId',
|
|
||||||
foreignField: '_id',
|
|
||||||
justOne: true
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
InvitationSchema.index({ teamId: 1 });
|
|
||||||
InvitationSchema.index({ expires: 1 }, { expireAfterSeconds: 30 * 24 * 60 * 60 });
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MongoInvitationLink = getMongoModel<InvitationSchemaType>(
|
|
||||||
InvitationCollectionName,
|
|
||||||
InvitationSchema
|
|
||||||
);
|
|
||||||
@@ -2,6 +2,7 @@ import { TeamMemberSchema } from '@fastgpt/global/support/user/team/type';
|
|||||||
|
|
||||||
export type InvitationSchemaType = {
|
export type InvitationSchemaType = {
|
||||||
_id: string;
|
_id: string;
|
||||||
|
linkId: string;
|
||||||
teamId: string;
|
teamId: string;
|
||||||
usedTimesLimit?: number;
|
usedTimesLimit?: number;
|
||||||
forbidden?: boolean;
|
forbidden?: boolean;
|
||||||
@@ -25,11 +26,10 @@ export type InvitationLinkCreateType = {
|
|||||||
expires: InvitationLinkExpiresType;
|
expires: InvitationLinkExpiresType;
|
||||||
usedTimesLimit: 1 | -1;
|
usedTimesLimit: 1 | -1;
|
||||||
};
|
};
|
||||||
export type InvitationLinkUpdateType = Partial<
|
|
||||||
Omit<InvitationSchemaType, 'members' | 'teamId' | '_id'>
|
// export type InvitationLinkUpdateType = Partial<
|
||||||
> & {
|
// Omit<InvitationSchemaType, 'members' | 'teamId' | '_id'>
|
||||||
linkId: string;
|
// >;
|
||||||
};
|
|
||||||
|
|
||||||
export type InvitationInfoType = InvitationSchemaType & {
|
export type InvitationInfoType = InvitationSchemaType & {
|
||||||
teamAvatar: string;
|
teamAvatar: string;
|
||||||
|
|||||||
8
packages/web/common/zustand/index.ts
Normal file
8
packages/web/common/zustand/index.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import zustandNpm from 'zustand';
|
||||||
|
|
||||||
|
export * from 'zustand';
|
||||||
|
export * from 'zustand/middleware';
|
||||||
|
export * from 'zustand/middleware/immer';
|
||||||
|
|
||||||
|
export * from 'zustand';
|
||||||
|
export default zustandNpm;
|
||||||
@@ -10,7 +10,16 @@ import { Box, Flex } from '@chakra-ui/react';
|
|||||||
* @param [groupId] - group id to make the key unique
|
* @param [groupId] - group id to make the key unique
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
function AvatarGroup({ avatars, max = 3 }: { max?: number; avatars: string[] }) {
|
function AvatarGroup({
|
||||||
|
avatars,
|
||||||
|
max = 3,
|
||||||
|
total
|
||||||
|
}: {
|
||||||
|
max?: number;
|
||||||
|
avatars: string[];
|
||||||
|
total?: number;
|
||||||
|
}) {
|
||||||
|
const remain = (total ?? avatars.length) - max;
|
||||||
return (
|
return (
|
||||||
<Flex position="relative">
|
<Flex position="relative">
|
||||||
{avatars.slice(0, max).map((avatar, index) => (
|
{avatars.slice(0, max).map((avatar, index) => (
|
||||||
@@ -24,10 +33,10 @@ function AvatarGroup({ avatars, max = 3 }: { max?: number; avatars: string[] })
|
|||||||
borderRadius={'50%'}
|
borderRadius={'50%'}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{avatars.length > max && (
|
{remain > 0 && (
|
||||||
<Box
|
<Box
|
||||||
position="relative"
|
position="relative"
|
||||||
left={`${(max - 1) * 15}px`}
|
left={`${(max - 1) * 15 + 15}px`}
|
||||||
w={'24px'}
|
w={'24px'}
|
||||||
h={'24px'}
|
h={'24px'}
|
||||||
borderRadius="50%"
|
borderRadius="50%"
|
||||||
@@ -37,7 +46,7 @@ function AvatarGroup({ avatars, max = 3 }: { max?: number; avatars: string[] })
|
|||||||
fontSize="sm"
|
fontSize="sm"
|
||||||
color="myGray.500"
|
color="myGray.500"
|
||||||
>
|
>
|
||||||
+{avatars.length - max}
|
+{String(remain)}
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ const EditFolderModal = ({
|
|||||||
{...register('name', { required: true })}
|
{...register('name', { required: true })}
|
||||||
bg={'myGray.50'}
|
bg={'myGray.50'}
|
||||||
autoFocus
|
autoFocus
|
||||||
maxLength={20}
|
maxLength={100}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box mt={4}>
|
<Box mt={4}>
|
||||||
|
|||||||
67
packages/web/components/common/Radio/RadioGroup.tsx
Normal file
67
packages/web/components/common/Radio/RadioGroup.tsx
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Box, Flex, Grid, type GridProps, HStack } from '@chakra-ui/react';
|
||||||
|
import { useTranslation } from 'next-i18next';
|
||||||
|
import QuestionTip from '../MyTooltip/QuestionTip';
|
||||||
|
|
||||||
|
type Props<T> = Omit<GridProps, 'onChange'> & {
|
||||||
|
list: {
|
||||||
|
title: string;
|
||||||
|
value: T;
|
||||||
|
tooltip?: string;
|
||||||
|
}[];
|
||||||
|
value: T;
|
||||||
|
defaultBg?: string;
|
||||||
|
activeBg?: string;
|
||||||
|
onChange: (e: T) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const RadioGroup = <T = any,>({ list, value, onChange, ...props }: Props<T>) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Flex gap={[3, 5]} fontSize={['sm', 'md']} alignItems={'center'} {...props}>
|
||||||
|
{list.map((item) => (
|
||||||
|
<Flex
|
||||||
|
alignItems={'center'}
|
||||||
|
key={item.value as any}
|
||||||
|
cursor={'pointer'}
|
||||||
|
userSelect={'none'}
|
||||||
|
gap={1}
|
||||||
|
onClick={() => onChange(item.value)}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
w={'18px'}
|
||||||
|
h={'18px'}
|
||||||
|
borderWidth={'2.4px'}
|
||||||
|
borderColor={value === item.value ? 'primary.015' : 'transparent'}
|
||||||
|
borderRadius={'50%'}
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
w={'100%'}
|
||||||
|
h={'100%'}
|
||||||
|
borderWidth={'1px'}
|
||||||
|
borderColor={value === item.value ? 'primary.600' : 'borderColor.high'}
|
||||||
|
bg={value === item.value ? 'primary.1' : 'transparent'}
|
||||||
|
borderRadius={'50%'}
|
||||||
|
alignItems={'center'}
|
||||||
|
justifyContent={'center'}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
w={'5px'}
|
||||||
|
h={'5px'}
|
||||||
|
borderRadius={'50%'}
|
||||||
|
bg={value === item.value ? 'primary.600' : 'transparent'}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
|
<HStack spacing={1} color={'myGray.900'} whiteSpace={'nowrap'} fontSize={'sm'}>
|
||||||
|
<Box>{typeof item.title === 'string' ? t(item.title as any) : item.title}</Box>
|
||||||
|
{!!item.tooltip && <QuestionTip label={item.tooltip} color={'myGray.600'} />}
|
||||||
|
</HStack>
|
||||||
|
</Flex>
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RadioGroup;
|
||||||
@@ -3,6 +3,11 @@ import { useToast } from './useToast';
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { hasHttps } from '../common/system/utils';
|
import { hasHttps } from '../common/system/utils';
|
||||||
import { isProduction } from '@fastgpt/global/common/system/constants';
|
import { isProduction } from '@fastgpt/global/common/system/constants';
|
||||||
|
import MyModal from '../components/common/MyModal';
|
||||||
|
import React from 'react';
|
||||||
|
import { Box, ModalBody } from '@chakra-ui/react';
|
||||||
|
import Tag from '../components/common/Tag';
|
||||||
|
import { useCommonStore } from '../store/useCommonStore';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* copy text data
|
* copy text data
|
||||||
@@ -10,11 +15,12 @@ import { isProduction } from '@fastgpt/global/common/system/constants';
|
|||||||
export const useCopyData = () => {
|
export const useCopyData = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
const { setCopyContent } = useCommonStore();
|
||||||
|
|
||||||
const copyData = useCallback(
|
const copyData = useCallback(
|
||||||
async (
|
async (
|
||||||
data: string,
|
data: string,
|
||||||
title: string | null = t('common:common.Copy Successful'),
|
title: string | null | undefined = t('common:common.Copy Successful'),
|
||||||
duration = 1000
|
duration = 1000
|
||||||
) => {
|
) => {
|
||||||
data = data.trim();
|
data = data.trim();
|
||||||
@@ -22,37 +28,18 @@ export const useCopyData = () => {
|
|||||||
try {
|
try {
|
||||||
if ((hasHttps() || !isProduction) && navigator.clipboard) {
|
if ((hasHttps() || !isProduction) && navigator.clipboard) {
|
||||||
await navigator.clipboard.writeText(data);
|
await navigator.clipboard.writeText(data);
|
||||||
|
if (title) {
|
||||||
|
toast({
|
||||||
|
title,
|
||||||
|
status: 'success',
|
||||||
|
duration
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error('');
|
throw new Error('');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// console.log(error);
|
setCopyContent(data);
|
||||||
|
|
||||||
const textarea = document.createElement('textarea');
|
|
||||||
textarea.value = data;
|
|
||||||
textarea.style.position = 'absolute';
|
|
||||||
textarea.style.opacity = '0';
|
|
||||||
document.body.appendChild(textarea);
|
|
||||||
|
|
||||||
textarea.select();
|
|
||||||
const res = document.execCommand('copy');
|
|
||||||
document.body.removeChild(textarea);
|
|
||||||
|
|
||||||
if (!res) {
|
|
||||||
return toast({
|
|
||||||
title: t('common:common.Copy_failed'),
|
|
||||||
status: 'error',
|
|
||||||
duration
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (title) {
|
|
||||||
toast({
|
|
||||||
title,
|
|
||||||
status: 'success',
|
|
||||||
duration
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[t, toast]
|
[t, toast]
|
||||||
@@ -62,3 +49,29 @@ export const useCopyData = () => {
|
|||||||
copyData
|
copyData
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const ManualCopyModal = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { copyContent, setCopyContent } = useCommonStore();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MyModal
|
||||||
|
isOpen={!!copyContent}
|
||||||
|
iconSrc="copy"
|
||||||
|
iconColor="primary.600"
|
||||||
|
title={t('common:common.Copy')}
|
||||||
|
maxW={['90vw', '500px']}
|
||||||
|
w={'100%'}
|
||||||
|
onClose={() => setCopyContent(undefined)}
|
||||||
|
>
|
||||||
|
<ModalBody>
|
||||||
|
<Tag w={'100%'} colorSchema="blue">
|
||||||
|
{t('common:can_copy_content_tip')}
|
||||||
|
</Tag>
|
||||||
|
<Box mt={3} borderRadius={'md'} p={3} border={'base'} userSelect={'all'}>
|
||||||
|
{copyContent}
|
||||||
|
</Box>
|
||||||
|
</ModalBody>
|
||||||
|
</MyModal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"channel_status_unknown": "unknown",
|
"channel_status_unknown": "unknown",
|
||||||
"channel_type": "Manufacturer",
|
"channel_type": "Manufacturer",
|
||||||
"clear_model": "Clear the model",
|
"clear_model": "Clear the model",
|
||||||
|
"confirm_delete_channel": "Confirm the deletion of the [{{name}}] channel?",
|
||||||
"copy_model_id_success": "Copyed model id",
|
"copy_model_id_success": "Copyed model id",
|
||||||
"create_channel": "Added channels",
|
"create_channel": "Added channels",
|
||||||
"default_url": "Default address",
|
"default_url": "Default address",
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
"model_tokens": "Input/Output tokens",
|
"model_tokens": "Input/Output tokens",
|
||||||
"request_at": "Request time",
|
"request_at": "Request time",
|
||||||
"request_duration": "Request duration: {{duration}}s",
|
"request_duration": "Request duration: {{duration}}s",
|
||||||
|
"retry_times": "Number of retry times",
|
||||||
"running_test": "In testing",
|
"running_test": "In testing",
|
||||||
"search_model": "Search for models",
|
"search_model": "Search for models",
|
||||||
"select_channel": "Select a channel name",
|
"select_channel": "Select a channel name",
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
"delete_org": "Delete organization",
|
"delete_org": "Delete organization",
|
||||||
"edit_info": "Edit information",
|
"edit_info": "Edit information",
|
||||||
"edit_org_info": "Edit organization information",
|
"edit_org_info": "Edit organization information",
|
||||||
"expires": "Expiration",
|
"expires": "Expiration time",
|
||||||
"forbid_hint": "After forbidden, this invitation link will become invalid. This action is irreversible. Are you sure you want to deactivate?",
|
"forbid_hint": "After forbidden, this invitation link will become invalid. This action is irreversible. Are you sure you want to deactivate?",
|
||||||
"forbid_success": "Forbid success",
|
"forbid_success": "Forbid success",
|
||||||
"forbidden": "Forbidden",
|
"forbidden": "Forbidden",
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
"has_forbidden": "Forbidden",
|
"has_forbidden": "Forbidden",
|
||||||
"has_invited": "Invited",
|
"has_invited": "Invited",
|
||||||
"ignore": "Ignore",
|
"ignore": "Ignore",
|
||||||
|
"invitation_copy_link": "[{{systemName}}] {{userName}} invites you to join the {{teamName}} team, link: {{url}}",
|
||||||
"invitation_link_auto_clean_hint": "Expired links will be automatically cleaned up after 30 days",
|
"invitation_link_auto_clean_hint": "Expired links will be automatically cleaned up after 30 days",
|
||||||
"invitation_link_description": "Link description",
|
"invitation_link_description": "Link description",
|
||||||
"invitation_link_list": "Invitation link list",
|
"invitation_link_list": "Invitation link list",
|
||||||
@@ -58,6 +59,5 @@
|
|||||||
"user_team_invite_member": "Invite members",
|
"user_team_invite_member": "Invite members",
|
||||||
"user_team_leave_team": "Leave the team",
|
"user_team_leave_team": "Leave the team",
|
||||||
"user_team_leave_team_failed": "Failure to leave the team",
|
"user_team_leave_team_failed": "Failure to leave the team",
|
||||||
"waiting": "To be accepted",
|
"waiting": "To be accepted"
|
||||||
"invitation_copy_link": "[{{systemName}}] {{userName}} invites you to join the {{teamName}} team, link: {{url}}"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@
|
|||||||
"to_dataset": "Go to the Knowledge Base",
|
"to_dataset": "Go to the Knowledge Base",
|
||||||
"unsupported_file_type": "Unsupported file types",
|
"unsupported_file_type": "Unsupported file types",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
|
"variable_invisable_in_share": "Custom variables are not visible in login-free links",
|
||||||
"view_citations": "View References",
|
"view_citations": "View References",
|
||||||
"web_site_sync": "Web Site Sync"
|
"web_site_sync": "Web Site Sync"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
"add_new_param": "Add new param",
|
"add_new_param": "Add new param",
|
||||||
"app.templateMarket.templateTags.Writing": "Writing",
|
"app.templateMarket.templateTags.Writing": "Writing",
|
||||||
"back": "Back",
|
"back": "Back",
|
||||||
|
"can_copy_content_tip": "It is not possible to copy automatically using the browser, please manually copy the following content",
|
||||||
"chose_condition": "Choose Condition",
|
"chose_condition": "Choose Condition",
|
||||||
"chosen": "Chosen",
|
"chosen": "Chosen",
|
||||||
"classification": "Classification",
|
"classification": "Classification",
|
||||||
@@ -128,7 +129,6 @@
|
|||||||
"common.Continue_Adding": "Continue adding",
|
"common.Continue_Adding": "Continue adding",
|
||||||
"common.Copy": "Copy",
|
"common.Copy": "Copy",
|
||||||
"common.Copy Successful": "Copied Successfully",
|
"common.Copy Successful": "Copied Successfully",
|
||||||
"common.Copy_failed": "Copy Failed, Please Copy Manually",
|
|
||||||
"common.Create Failed": "Creation Failed",
|
"common.Create Failed": "Creation Failed",
|
||||||
"common.Create Success": "Created Successfully",
|
"common.Create Success": "Created Successfully",
|
||||||
"common.Create Time": "Creation Time",
|
"common.Create Time": "Creation Time",
|
||||||
@@ -569,8 +569,6 @@
|
|||||||
"core.dataset.import.Custom process": "Custom Rules",
|
"core.dataset.import.Custom process": "Custom Rules",
|
||||||
"core.dataset.import.Custom process desc": "Customize segmentation and preprocessing rules",
|
"core.dataset.import.Custom process desc": "Customize segmentation and preprocessing rules",
|
||||||
"core.dataset.import.Custom prompt": "Custom Prompt",
|
"core.dataset.import.Custom prompt": "Custom Prompt",
|
||||||
"core.dataset.import.Custom split char": "Custom Separator",
|
|
||||||
"core.dataset.import.Custom split char Tips": "Allows you to segment based on custom separators. Usually used for pre-processed data, using specific separators for precise segmentation.",
|
|
||||||
"core.dataset.import.Custom text": "Custom Text",
|
"core.dataset.import.Custom text": "Custom Text",
|
||||||
"core.dataset.import.Custom text desc": "Manually enter a piece of text as a dataset",
|
"core.dataset.import.Custom text desc": "Manually enter a piece of text as a dataset",
|
||||||
"core.dataset.import.Data process params": "Data Processing Parameters",
|
"core.dataset.import.Data process params": "Data Processing Parameters",
|
||||||
@@ -646,11 +644,11 @@
|
|||||||
"core.dataset.training.Auto mode": "Auto index",
|
"core.dataset.training.Auto mode": "Auto index",
|
||||||
"core.dataset.training.Auto mode Tip": "Increase the semantic richness of data blocks by generating related questions and summaries through sub-indexes and calling models, making it more conducive to retrieval. Requires more storage space and increases AI call times.",
|
"core.dataset.training.Auto mode Tip": "Increase the semantic richness of data blocks by generating related questions and summaries through sub-indexes and calling models, making it more conducive to retrieval. Requires more storage space and increases AI call times.",
|
||||||
"core.dataset.training.Chunk mode": "Chunk",
|
"core.dataset.training.Chunk mode": "Chunk",
|
||||||
"core.dataset.training.Full": "Estimated Over 5 Minutes",
|
"core.dataset.training.Full": "It is expected to be more than 20 minutes",
|
||||||
"core.dataset.training.Leisure": "Idle",
|
"core.dataset.training.Leisure": "Idle",
|
||||||
"core.dataset.training.QA mode": "QA",
|
"core.dataset.training.QA mode": "QA",
|
||||||
"core.dataset.training.Vector queue": "Index Queue",
|
"core.dataset.training.Vector queue": "Index Queue",
|
||||||
"core.dataset.training.Waiting": "Estimated 5 Minutes",
|
"core.dataset.training.Waiting": "Estimated 20 minutes",
|
||||||
"core.dataset.training.Website Sync": "Website Sync",
|
"core.dataset.training.Website Sync": "Website Sync",
|
||||||
"core.dataset.training.tag": "Queue Status",
|
"core.dataset.training.tag": "Queue Status",
|
||||||
"core.dataset.website.Base Url": "Base URL",
|
"core.dataset.website.Base Url": "Base URL",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
"api_url": "API Url",
|
"api_url": "API Url",
|
||||||
"auto_indexes": "Automatically generate supplementary indexes",
|
"auto_indexes": "Automatically generate supplementary indexes",
|
||||||
"auto_indexes_tips": "Additional index generation is performed through large models to improve semantic richness and improve retrieval accuracy.",
|
"auto_indexes_tips": "Additional index generation is performed through large models to improve semantic richness and improve retrieval accuracy.",
|
||||||
|
"auto_training_queue": "Enhanced index queueing",
|
||||||
"chunk_max_tokens": "max_tokens",
|
"chunk_max_tokens": "max_tokens",
|
||||||
"close_auto_sync": "Are you sure you want to turn off automatic sync?",
|
"close_auto_sync": "Are you sure you want to turn off automatic sync?",
|
||||||
"collection.Create update time": "Creation/Update Time",
|
"collection.Create update time": "Creation/Update Time",
|
||||||
@@ -25,7 +26,7 @@
|
|||||||
"core.dataset.import.Adjust parameters": "Adjust parameters",
|
"core.dataset.import.Adjust parameters": "Adjust parameters",
|
||||||
"custom_data_process_params": "Custom",
|
"custom_data_process_params": "Custom",
|
||||||
"custom_data_process_params_desc": "Customize data processing rules",
|
"custom_data_process_params_desc": "Customize data processing rules",
|
||||||
"data.ideal_chunk_length": "ideal block length",
|
"custom_split_sign_tip": "Allows you to chunk according to custom delimiters. \nUsually used for processed data, using specific separators for precise chunking. \nYou can use the | symbol to represent multiple splitters, such as: \".|.\" to represent a period in Chinese and English.\n\nTry to avoid using special symbols related to regular, such as: * () [] {}, etc.",
|
||||||
"data_amount": "{{dataAmount}} Datas, {{indexAmount}} Indexes",
|
"data_amount": "{{dataAmount}} Datas, {{indexAmount}} Indexes",
|
||||||
"data_index_num": "Index {{index}}",
|
"data_index_num": "Index {{index}}",
|
||||||
"data_process_params": "Params",
|
"data_process_params": "Params",
|
||||||
@@ -51,10 +52,9 @@
|
|||||||
"file_model_function_tip": "Enhances indexing and QA generation",
|
"file_model_function_tip": "Enhances indexing and QA generation",
|
||||||
"filename": "Filename",
|
"filename": "Filename",
|
||||||
"folder_dataset": "Folder",
|
"folder_dataset": "Folder",
|
||||||
"ideal_chunk_length": "ideal block length",
|
|
||||||
"ideal_chunk_length_tips": "Segment according to the end symbol and combine multiple segments into one block. This value determines the estimated size of the block, if there is any fluctuation.",
|
|
||||||
"image_auto_parse": "Automatic image indexing",
|
"image_auto_parse": "Automatic image indexing",
|
||||||
"image_auto_parse_tips": "Call VLM to automatically label the pictures in the document and generate additional search indexes",
|
"image_auto_parse_tips": "Call VLM to automatically label the pictures in the document and generate additional search indexes",
|
||||||
|
"image_training_queue": "Queue of image processing",
|
||||||
"import.Auto mode Estimated Price Tips": "The text understanding model needs to be called, which requires more points: {{price}} points/1K tokens",
|
"import.Auto mode Estimated Price Tips": "The text understanding model needs to be called, which requires more points: {{price}} points/1K tokens",
|
||||||
"import.Embedding Estimated Price Tips": "Only use the index model and consume a small amount of AI points: {{price}} points/1K tokens",
|
"import.Embedding Estimated Price Tips": "Only use the index model and consume a small amount of AI points: {{price}} points/1K tokens",
|
||||||
"import_confirm": "Confirm upload",
|
"import_confirm": "Confirm upload",
|
||||||
@@ -65,6 +65,8 @@
|
|||||||
"import_param_setting": "Parameter settings",
|
"import_param_setting": "Parameter settings",
|
||||||
"import_select_file": "Select a file",
|
"import_select_file": "Select a file",
|
||||||
"import_select_link": "Enter link",
|
"import_select_link": "Enter link",
|
||||||
|
"index_size": "Index size",
|
||||||
|
"index_size_tips": "When vectorized, the system will automatically further segment the blocks according to this size.",
|
||||||
"is_open_schedule": "Enable scheduled synchronization",
|
"is_open_schedule": "Enable scheduled synchronization",
|
||||||
"keep_image": "Keep the picture",
|
"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.",
|
"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.",
|
||||||
@@ -78,7 +80,7 @@
|
|||||||
"permission.des.write": "Ability to add and change knowledge base content",
|
"permission.des.write": "Ability to add and change knowledge base content",
|
||||||
"preview_chunk": "Preview chunks",
|
"preview_chunk": "Preview chunks",
|
||||||
"preview_chunk_empty": "Unable to read the contents of the file",
|
"preview_chunk_empty": "Unable to read the contents of the file",
|
||||||
"preview_chunk_intro": "Display up to 10 pieces",
|
"preview_chunk_intro": "A total of {{total}} blocks, up to 10",
|
||||||
"preview_chunk_not_selected": "Click on the file on the left to preview",
|
"preview_chunk_not_selected": "Click on the file on the left to preview",
|
||||||
"rebuild_embedding_start_tip": "Index model switching task has started",
|
"rebuild_embedding_start_tip": "Index model switching task has started",
|
||||||
"rebuilding_index_count": "Number of indexes being rebuilt: {{count}}",
|
"rebuilding_index_count": "Number of indexes being rebuilt: {{count}}",
|
||||||
@@ -86,6 +88,16 @@
|
|||||||
"retain_collection": "Adjust Training Parameters",
|
"retain_collection": "Adjust Training Parameters",
|
||||||
"retrain_task_submitted": "The retraining task has been submitted",
|
"retrain_task_submitted": "The retraining task has been submitted",
|
||||||
"same_api_collection": "The same API set exists",
|
"same_api_collection": "The same API set exists",
|
||||||
|
"split_chunk_char": "Block by specified splitter",
|
||||||
|
"split_chunk_size": "Block by length",
|
||||||
|
"split_sign_break": "1 newline character",
|
||||||
|
"split_sign_break2": "2 newline characters",
|
||||||
|
"split_sign_custom": "Customize",
|
||||||
|
"split_sign_exclamatiob": "exclamation mark",
|
||||||
|
"split_sign_null": "Not set",
|
||||||
|
"split_sign_period": "period",
|
||||||
|
"split_sign_question": "question mark",
|
||||||
|
"split_sign_semicolon": "semicolon",
|
||||||
"start_sync_website_tip": "Confirm to start synchronizing data? \nThe old data will be deleted and retrieved again, please confirm!",
|
"start_sync_website_tip": "Confirm to start synchronizing data? \nThe old data will be deleted and retrieved again, please confirm!",
|
||||||
"sync_collection_failed": "Synchronization collection error, please check whether the source file can be accessed normally",
|
"sync_collection_failed": "Synchronization collection error, please check whether the source file can be accessed normally",
|
||||||
"sync_schedule": "Timing synchronization",
|
"sync_schedule": "Timing synchronization",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"channel_status_unknown": "未知",
|
"channel_status_unknown": "未知",
|
||||||
"channel_type": "厂商",
|
"channel_type": "厂商",
|
||||||
"clear_model": "清空模型",
|
"clear_model": "清空模型",
|
||||||
|
"confirm_delete_channel": "确认删除 【{{name}}】渠道?",
|
||||||
"copy_model_id_success": "已复制模型id",
|
"copy_model_id_success": "已复制模型id",
|
||||||
"create_channel": "新增渠道",
|
"create_channel": "新增渠道",
|
||||||
"default_url": "默认地址",
|
"default_url": "默认地址",
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
"model_tokens": "输入/输出 Tokens",
|
"model_tokens": "输入/输出 Tokens",
|
||||||
"request_at": "请求时间",
|
"request_at": "请求时间",
|
||||||
"request_duration": "请求时长: {{duration}}s",
|
"request_duration": "请求时长: {{duration}}s",
|
||||||
|
"retry_times": "重试次数",
|
||||||
"running_test": "测试中",
|
"running_test": "测试中",
|
||||||
"search_model": "搜索模型",
|
"search_model": "搜索模型",
|
||||||
"select_channel": "选择渠道名",
|
"select_channel": "选择渠道名",
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
"delete_org": "删除部门",
|
"delete_org": "删除部门",
|
||||||
"edit_info": "编辑信息",
|
"edit_info": "编辑信息",
|
||||||
"edit_org_info": "编辑部门信息",
|
"edit_org_info": "编辑部门信息",
|
||||||
"expires": "有效期",
|
"expires": "过期时间",
|
||||||
"export_members": "导出成员",
|
"export_members": "导出成员",
|
||||||
"forbid_hint": "停用后,该邀请链接将失效。 该操作不可撤销,是否确认停用?",
|
"forbid_hint": "停用后,该邀请链接将失效。 该操作不可撤销,是否确认停用?",
|
||||||
"forbid_success": "停用成功",
|
"forbid_success": "停用成功",
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
"has_forbidden": "已失效",
|
"has_forbidden": "已失效",
|
||||||
"has_invited": "已邀请",
|
"has_invited": "已邀请",
|
||||||
"ignore": "忽略",
|
"ignore": "忽略",
|
||||||
|
"invitation_copy_link": "【{{systemName}}】 {{userName}} 邀请您加入{{teamName}}团队,链接:{{url}}",
|
||||||
"invitation_link_auto_clean_hint": "已失效链接将在30天后自动清理",
|
"invitation_link_auto_clean_hint": "已失效链接将在30天后自动清理",
|
||||||
"invitation_link_description": "链接描述",
|
"invitation_link_description": "链接描述",
|
||||||
"invitation_link_list": "链接列表",
|
"invitation_link_list": "链接列表",
|
||||||
@@ -53,6 +54,7 @@
|
|||||||
"org_name": "部门名称",
|
"org_name": "部门名称",
|
||||||
"owner": "所有者",
|
"owner": "所有者",
|
||||||
"permission": "权限",
|
"permission": "权限",
|
||||||
|
"please_bind_contact": "请绑定联系方式",
|
||||||
"remark": "备注",
|
"remark": "备注",
|
||||||
"remove_tip": "确认将 {{username}} 移出团队?成员将被标记为“已离职”,不删除操作数据,账号下资源自动转让给团队所有者。",
|
"remove_tip": "确认将 {{username}} 移出团队?成员将被标记为“已离职”,不删除操作数据,账号下资源自动转让给团队所有者。",
|
||||||
"restore_tip": "确认将 {{username}} 加入团队吗?仅恢复该成员账号可用性及相关权限,无法恢复账号下资源。",
|
"restore_tip": "确认将 {{username}} 加入团队吗?仅恢复该成员账号可用性及相关权限,无法恢复账号下资源。",
|
||||||
@@ -73,7 +75,5 @@
|
|||||||
"user_team_invite_member": "邀请成员",
|
"user_team_invite_member": "邀请成员",
|
||||||
"user_team_leave_team": "离开团队",
|
"user_team_leave_team": "离开团队",
|
||||||
"user_team_leave_team_failed": "离开团队失败",
|
"user_team_leave_team_failed": "离开团队失败",
|
||||||
"waiting": "待接受",
|
"waiting": "待接受"
|
||||||
"invitation_copy_link": "【{{systemName}}】 {{userName}} 邀请您加入{{teamName}}团队,链接:{{url}}",
|
|
||||||
"please_bind_contact": "请绑定联系方式"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@
|
|||||||
"to_dataset": "前往知识库",
|
"to_dataset": "前往知识库",
|
||||||
"unsupported_file_type": "不支持的文件类型",
|
"unsupported_file_type": "不支持的文件类型",
|
||||||
"upload": "上传",
|
"upload": "上传",
|
||||||
|
"variable_invisable_in_share": "自定义变量在免登录链接中不可见",
|
||||||
"view_citations": "查看引用",
|
"view_citations": "查看引用",
|
||||||
"web_site_sync": "Web站点同步"
|
"web_site_sync": "Web站点同步"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"app.templateMarket.templateTags.Web_search": "联网搜索",
|
"app.templateMarket.templateTags.Web_search": "联网搜索",
|
||||||
"app.templateMarket.templateTags.Writing": "文本创作",
|
"app.templateMarket.templateTags.Writing": "文本创作",
|
||||||
"back": "返回",
|
"back": "返回",
|
||||||
|
"can_copy_content_tip": "无法使用浏览器自动复制,请手动复制下面内容",
|
||||||
"chose_condition": "选择条件",
|
"chose_condition": "选择条件",
|
||||||
"chosen": "已选",
|
"chosen": "已选",
|
||||||
"classification": "分类",
|
"classification": "分类",
|
||||||
@@ -132,7 +133,6 @@
|
|||||||
"common.Continue_Adding": "继续添加",
|
"common.Continue_Adding": "继续添加",
|
||||||
"common.Copy": "复制",
|
"common.Copy": "复制",
|
||||||
"common.Copy Successful": "复制成功",
|
"common.Copy Successful": "复制成功",
|
||||||
"common.Copy_failed": "复制失败,请手动复制",
|
|
||||||
"common.Create Failed": "创建异常",
|
"common.Create Failed": "创建异常",
|
||||||
"common.Create Success": "创建成功",
|
"common.Create Success": "创建成功",
|
||||||
"common.Create Time": "创建时间",
|
"common.Create Time": "创建时间",
|
||||||
@@ -335,7 +335,7 @@
|
|||||||
"core.app.deterministic": "严谨",
|
"core.app.deterministic": "严谨",
|
||||||
"core.app.edit.Prompt Editor": "提示词编辑",
|
"core.app.edit.Prompt Editor": "提示词编辑",
|
||||||
"core.app.edit.Query extension background prompt": "对话背景描述",
|
"core.app.edit.Query extension background prompt": "对话背景描述",
|
||||||
"core.app.edit.Query extension background tip": "描述当前对话的范围,便于 AI 为当前问题进行补全和扩展。填写的内容,通常为该助手",
|
"core.app.edit.Query extension background tip": "描述当前对话的范围,便于 AI 为当前问题进行补全和扩展。填写的内容,通常为该助手所用",
|
||||||
"core.app.edit_content": "应用信息编辑",
|
"core.app.edit_content": "应用信息编辑",
|
||||||
"core.app.error.App name can not be empty": "应用名不能为空",
|
"core.app.error.App name can not be empty": "应用名不能为空",
|
||||||
"core.app.error.Get app failed": "获取应用异常",
|
"core.app.error.Get app failed": "获取应用异常",
|
||||||
@@ -573,8 +573,6 @@
|
|||||||
"core.dataset.import.Custom process": "自定义规则",
|
"core.dataset.import.Custom process": "自定义规则",
|
||||||
"core.dataset.import.Custom process desc": "自定义设置数据处理规则",
|
"core.dataset.import.Custom process desc": "自定义设置数据处理规则",
|
||||||
"core.dataset.import.Custom prompt": "自定义提示词",
|
"core.dataset.import.Custom prompt": "自定义提示词",
|
||||||
"core.dataset.import.Custom split char": "自定义分隔符",
|
|
||||||
"core.dataset.import.Custom split char Tips": "允许你根据自定义的分隔符进行分块。通常用于已处理好的数据,使用特定的分隔符来精确分块。",
|
|
||||||
"core.dataset.import.Custom text": "自定义文本",
|
"core.dataset.import.Custom text": "自定义文本",
|
||||||
"core.dataset.import.Custom text desc": "手动输入一段文本作为数据集",
|
"core.dataset.import.Custom text desc": "手动输入一段文本作为数据集",
|
||||||
"core.dataset.import.Data process params": "数据处理参数",
|
"core.dataset.import.Data process params": "数据处理参数",
|
||||||
@@ -649,11 +647,11 @@
|
|||||||
"core.dataset.training.Auto mode": "补充索引",
|
"core.dataset.training.Auto mode": "补充索引",
|
||||||
"core.dataset.training.Auto mode Tip": "通过子索引以及调用模型生成相关问题与摘要,来增加数据块的语义丰富度,更利于检索。需要消耗更多的存储空间和增加 AI 调用次数。",
|
"core.dataset.training.Auto mode Tip": "通过子索引以及调用模型生成相关问题与摘要,来增加数据块的语义丰富度,更利于检索。需要消耗更多的存储空间和增加 AI 调用次数。",
|
||||||
"core.dataset.training.Chunk mode": "直接分块",
|
"core.dataset.training.Chunk mode": "直接分块",
|
||||||
"core.dataset.training.Full": "预计 5 分钟以上",
|
"core.dataset.training.Full": "预计 20 分钟以上",
|
||||||
"core.dataset.training.Leisure": "空闲",
|
"core.dataset.training.Leisure": "空闲",
|
||||||
"core.dataset.training.QA mode": "问答对提取",
|
"core.dataset.training.QA mode": "问答对提取",
|
||||||
"core.dataset.training.Vector queue": "索引排队",
|
"core.dataset.training.Vector queue": "索引排队",
|
||||||
"core.dataset.training.Waiting": "预计 5 分钟",
|
"core.dataset.training.Waiting": "预计 20 分钟",
|
||||||
"core.dataset.training.Website Sync": "Web 站点同步",
|
"core.dataset.training.Website Sync": "Web 站点同步",
|
||||||
"core.dataset.training.tag": "排队情况",
|
"core.dataset.training.tag": "排队情况",
|
||||||
"core.dataset.website.Base Url": "根地址",
|
"core.dataset.website.Base Url": "根地址",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
"api_url": "接口地址",
|
"api_url": "接口地址",
|
||||||
"auto_indexes": "自动生成补充索引",
|
"auto_indexes": "自动生成补充索引",
|
||||||
"auto_indexes_tips": "通过大模型进行额外索引生成,提高语义丰富度,提高检索的精度。",
|
"auto_indexes_tips": "通过大模型进行额外索引生成,提高语义丰富度,提高检索的精度。",
|
||||||
|
"auto_training_queue": "增强索引排队",
|
||||||
"chunk_max_tokens": "分块上限",
|
"chunk_max_tokens": "分块上限",
|
||||||
"close_auto_sync": "确认关闭自动同步功能?",
|
"close_auto_sync": "确认关闭自动同步功能?",
|
||||||
"collection.Create update time": "创建/更新时间",
|
"collection.Create update time": "创建/更新时间",
|
||||||
@@ -25,7 +26,7 @@
|
|||||||
"core.dataset.import.Adjust parameters": "调整参数",
|
"core.dataset.import.Adjust parameters": "调整参数",
|
||||||
"custom_data_process_params": "自定义",
|
"custom_data_process_params": "自定义",
|
||||||
"custom_data_process_params_desc": "自定义设置数据处理规则",
|
"custom_data_process_params_desc": "自定义设置数据处理规则",
|
||||||
"data.ideal_chunk_length": "理想分块长度",
|
"custom_split_sign_tip": "允许你根据自定义的分隔符进行分块。通常用于已处理好的数据,使用特定的分隔符来精确分块。可以使用 | 符号表示多个分割符,例如:“。|.” 表示中英文句号。\n尽量避免使用正则相关特殊符号,例如: * () [] {} 等。",
|
||||||
"data_amount": "{{dataAmount}} 组数据, {{indexAmount}} 组索引",
|
"data_amount": "{{dataAmount}} 组数据, {{indexAmount}} 组索引",
|
||||||
"data_index_num": "索引 {{index}}",
|
"data_index_num": "索引 {{index}}",
|
||||||
"data_process_params": "处理参数",
|
"data_process_params": "处理参数",
|
||||||
@@ -51,10 +52,9 @@
|
|||||||
"file_model_function_tip": "用于增强索引和 QA 生成",
|
"file_model_function_tip": "用于增强索引和 QA 生成",
|
||||||
"filename": "文件名",
|
"filename": "文件名",
|
||||||
"folder_dataset": "文件夹",
|
"folder_dataset": "文件夹",
|
||||||
"ideal_chunk_length": "理想分块长度",
|
|
||||||
"ideal_chunk_length_tips": "按结束符号进行分段,并将多个分段组成一个分块,该值决定了分块的预估大小,如果会有上下浮动。",
|
|
||||||
"image_auto_parse": "图片自动索引",
|
"image_auto_parse": "图片自动索引",
|
||||||
"image_auto_parse_tips": "调用 VLM 自动标注文档里的图片,并生成额外的检索索引",
|
"image_auto_parse_tips": "调用 VLM 自动标注文档里的图片,并生成额外的检索索引",
|
||||||
|
"image_training_queue": "图片处理排队",
|
||||||
"import.Auto mode Estimated Price Tips": "需调用文本理解模型,需要消耗较多AI 积分:{{price}} 积分/1K tokens",
|
"import.Auto mode Estimated Price Tips": "需调用文本理解模型,需要消耗较多AI 积分:{{price}} 积分/1K tokens",
|
||||||
"import.Embedding Estimated Price Tips": "仅使用索引模型,消耗少量 AI 积分:{{price}} 积分/1K tokens",
|
"import.Embedding Estimated Price Tips": "仅使用索引模型,消耗少量 AI 积分:{{price}} 积分/1K tokens",
|
||||||
"import_confirm": "确认上传",
|
"import_confirm": "确认上传",
|
||||||
@@ -65,6 +65,8 @@
|
|||||||
"import_param_setting": "参数设置",
|
"import_param_setting": "参数设置",
|
||||||
"import_select_file": "选择文件",
|
"import_select_file": "选择文件",
|
||||||
"import_select_link": "输入链接",
|
"import_select_link": "输入链接",
|
||||||
|
"index_size": "索引大小",
|
||||||
|
"index_size_tips": "向量化时内容的长度,系统会自动按该大小对分块进行进一步的分割。",
|
||||||
"is_open_schedule": "启用定时同步",
|
"is_open_schedule": "启用定时同步",
|
||||||
"keep_image": "保留图片",
|
"keep_image": "保留图片",
|
||||||
"move.hint": "移动后,所选知识库/文件夹将继承新文件夹的权限设置,原先的权限设置失效。",
|
"move.hint": "移动后,所选知识库/文件夹将继承新文件夹的权限设置,原先的权限设置失效。",
|
||||||
@@ -78,7 +80,7 @@
|
|||||||
"permission.des.write": "可增加和变更知识库内容",
|
"permission.des.write": "可增加和变更知识库内容",
|
||||||
"preview_chunk": "分块预览",
|
"preview_chunk": "分块预览",
|
||||||
"preview_chunk_empty": "无法读取该文件内容",
|
"preview_chunk_empty": "无法读取该文件内容",
|
||||||
"preview_chunk_intro": "最多展示 10 个分块",
|
"preview_chunk_intro": "共 {{total}} 个分块,最多展示 10 个",
|
||||||
"preview_chunk_not_selected": "点击左侧文件后进行预览",
|
"preview_chunk_not_selected": "点击左侧文件后进行预览",
|
||||||
"rebuild_embedding_start_tip": "切换索引模型任务已开始",
|
"rebuild_embedding_start_tip": "切换索引模型任务已开始",
|
||||||
"rebuilding_index_count": "重建中索引数量:{{count}}",
|
"rebuilding_index_count": "重建中索引数量:{{count}}",
|
||||||
@@ -86,6 +88,16 @@
|
|||||||
"retain_collection": "调整训练参数",
|
"retain_collection": "调整训练参数",
|
||||||
"retrain_task_submitted": "重新训练任务已提交",
|
"retrain_task_submitted": "重新训练任务已提交",
|
||||||
"same_api_collection": "存在相同的 API 集合",
|
"same_api_collection": "存在相同的 API 集合",
|
||||||
|
"split_chunk_char": "按指定分割符分块",
|
||||||
|
"split_chunk_size": "按长度分块",
|
||||||
|
"split_sign_break": "1 个换行符",
|
||||||
|
"split_sign_break2": "2 个换行符",
|
||||||
|
"split_sign_custom": "自定义",
|
||||||
|
"split_sign_exclamatiob": "感叹号",
|
||||||
|
"split_sign_null": "不设置",
|
||||||
|
"split_sign_period": "句号",
|
||||||
|
"split_sign_question": "问号",
|
||||||
|
"split_sign_semicolon": "分号",
|
||||||
"start_sync_website_tip": "确认开始同步数据?将会删除旧数据后重新获取,请确认!",
|
"start_sync_website_tip": "确认开始同步数据?将会删除旧数据后重新获取,请确认!",
|
||||||
"sync_collection_failed": "同步集合错误,请检查是否能正常访问源文件",
|
"sync_collection_failed": "同步集合错误,请检查是否能正常访问源文件",
|
||||||
"sync_schedule": "定时同步",
|
"sync_schedule": "定时同步",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"channel_status_unknown": "未知",
|
"channel_status_unknown": "未知",
|
||||||
"channel_type": "廠商",
|
"channel_type": "廠商",
|
||||||
"clear_model": "清空模型",
|
"clear_model": "清空模型",
|
||||||
|
"confirm_delete_channel": "確認刪除 【{{name}}】渠道?",
|
||||||
"copy_model_id_success": "已復制模型id",
|
"copy_model_id_success": "已復制模型id",
|
||||||
"create_channel": "新增渠道",
|
"create_channel": "新增渠道",
|
||||||
"default_url": "默認地址",
|
"default_url": "默認地址",
|
||||||
@@ -34,6 +35,7 @@
|
|||||||
"model_tokens": "輸入/輸出 Tokens",
|
"model_tokens": "輸入/輸出 Tokens",
|
||||||
"request_at": "請求時間",
|
"request_at": "請求時間",
|
||||||
"request_duration": "請求時長: {{duration}}s",
|
"request_duration": "請求時長: {{duration}}s",
|
||||||
|
"retry_times": "重試次數",
|
||||||
"running_test": "測試中",
|
"running_test": "測試中",
|
||||||
"search_model": "搜索模型",
|
"search_model": "搜索模型",
|
||||||
"select_channel": "選擇渠道名",
|
"select_channel": "選擇渠道名",
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
"delete_org": "刪除部門",
|
"delete_org": "刪除部門",
|
||||||
"edit_info": "編輯訊息",
|
"edit_info": "編輯訊息",
|
||||||
"edit_org_info": "編輯部門資訊",
|
"edit_org_info": "編輯部門資訊",
|
||||||
"expires": "有效期",
|
"expires": "過期時間",
|
||||||
"forbid_hint": "停用後,該邀請連結將失效。 該操作不可撤銷,是否確認停用?",
|
"forbid_hint": "停用後,該邀請連結將失效。 該操作不可撤銷,是否確認停用?",
|
||||||
"forbid_success": "停用成功",
|
"forbid_success": "停用成功",
|
||||||
"forbidden": "停用",
|
"forbidden": "停用",
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
"has_forbidden": "已失效",
|
"has_forbidden": "已失效",
|
||||||
"has_invited": "已邀請",
|
"has_invited": "已邀請",
|
||||||
"ignore": "忽略",
|
"ignore": "忽略",
|
||||||
|
"invitation_copy_link": "【{{systemName}}】 {{userName}} 邀請您加入{{teamName}}團隊,連結:{{url}}",
|
||||||
"invitation_link_auto_clean_hint": "已失效連結將在30天後自動清理",
|
"invitation_link_auto_clean_hint": "已失效連結將在30天後自動清理",
|
||||||
"invitation_link_description": "連結描述",
|
"invitation_link_description": "連結描述",
|
||||||
"invitation_link_list": "連結列表",
|
"invitation_link_list": "連結列表",
|
||||||
@@ -58,6 +59,5 @@
|
|||||||
"user_team_invite_member": "邀請成員",
|
"user_team_invite_member": "邀請成員",
|
||||||
"user_team_leave_team": "離開團隊",
|
"user_team_leave_team": "離開團隊",
|
||||||
"user_team_leave_team_failed": "離開團隊失敗",
|
"user_team_leave_team_failed": "離開團隊失敗",
|
||||||
"waiting": "待接受",
|
"waiting": "待接受"
|
||||||
"invitation_copy_link": "【{{systemName}}】 {{userName}} 邀請您加入{{teamName}}團隊,連結:{{url}}"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
"to_dataset": "前往知識庫",
|
"to_dataset": "前往知識庫",
|
||||||
"unsupported_file_type": "不支援的檔案類型",
|
"unsupported_file_type": "不支援的檔案類型",
|
||||||
"upload": "上傳",
|
"upload": "上傳",
|
||||||
|
"variable_invisable_in_share": "自定義變量在免登錄鏈接中不可見",
|
||||||
"view_citations": "檢視引用",
|
"view_citations": "檢視引用",
|
||||||
"web_site_sync": "網站同步"
|
"web_site_sync": "網站同步"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
"add_new_param": "新增參數",
|
"add_new_param": "新增參數",
|
||||||
"app.templateMarket.templateTags.Writing": "文字創作",
|
"app.templateMarket.templateTags.Writing": "文字創作",
|
||||||
"back": "返回",
|
"back": "返回",
|
||||||
|
"can_copy_content_tip": "無法使用瀏覽器自動複製,請手動複製下面內容",
|
||||||
"chose_condition": "選擇條件",
|
"chose_condition": "選擇條件",
|
||||||
"chosen": "已選擇",
|
"chosen": "已選擇",
|
||||||
"classification": "分類",
|
"classification": "分類",
|
||||||
@@ -127,7 +128,6 @@
|
|||||||
"common.Continue_Adding": "繼續新增",
|
"common.Continue_Adding": "繼續新增",
|
||||||
"common.Copy": "複製",
|
"common.Copy": "複製",
|
||||||
"common.Copy Successful": "複製成功",
|
"common.Copy Successful": "複製成功",
|
||||||
"common.Copy_failed": "複製失敗,請手動複製",
|
|
||||||
"common.Create Failed": "建立失敗",
|
"common.Create Failed": "建立失敗",
|
||||||
"common.Create Success": "建立成功",
|
"common.Create Success": "建立成功",
|
||||||
"common.Create Time": "建立時間",
|
"common.Create Time": "建立時間",
|
||||||
@@ -568,8 +568,6 @@
|
|||||||
"core.dataset.import.Custom process": "自訂規則",
|
"core.dataset.import.Custom process": "自訂規則",
|
||||||
"core.dataset.import.Custom process desc": "自訂設定資料處理規則",
|
"core.dataset.import.Custom process desc": "自訂設定資料處理規則",
|
||||||
"core.dataset.import.Custom prompt": "自訂提示詞",
|
"core.dataset.import.Custom prompt": "自訂提示詞",
|
||||||
"core.dataset.import.Custom split char": "自訂分隔符",
|
|
||||||
"core.dataset.import.Custom split char Tips": "允許您根據自訂的分隔符進行分割。通常用於已處理好的資料,使用特定的分隔符來精確分割。",
|
|
||||||
"core.dataset.import.Custom text": "自訂文字",
|
"core.dataset.import.Custom text": "自訂文字",
|
||||||
"core.dataset.import.Custom text desc": "手動輸入一段文字作為資料集",
|
"core.dataset.import.Custom text desc": "手動輸入一段文字作為資料集",
|
||||||
"core.dataset.import.Data process params": "資料處理參數",
|
"core.dataset.import.Data process params": "資料處理參數",
|
||||||
@@ -645,11 +643,11 @@
|
|||||||
"core.dataset.training.Auto mode": "補充索引",
|
"core.dataset.training.Auto mode": "補充索引",
|
||||||
"core.dataset.training.Auto mode Tip": "透過子索引以及呼叫模型產生相關問題與摘要,來增加資料區塊的語意豐富度,更有利於檢索。需要消耗更多的儲存空間並增加 AI 呼叫次數。",
|
"core.dataset.training.Auto mode Tip": "透過子索引以及呼叫模型產生相關問題與摘要,來增加資料區塊的語意豐富度,更有利於檢索。需要消耗更多的儲存空間並增加 AI 呼叫次數。",
|
||||||
"core.dataset.training.Chunk mode": "直接分块",
|
"core.dataset.training.Chunk mode": "直接分块",
|
||||||
"core.dataset.training.Full": "預計超過 5 分鐘",
|
"core.dataset.training.Full": "預計 20 分鐘以上",
|
||||||
"core.dataset.training.Leisure": "閒置",
|
"core.dataset.training.Leisure": "閒置",
|
||||||
"core.dataset.training.QA mode": "問答對提取",
|
"core.dataset.training.QA mode": "問答對提取",
|
||||||
"core.dataset.training.Vector queue": "索引排隊中",
|
"core.dataset.training.Vector queue": "索引排隊中",
|
||||||
"core.dataset.training.Waiting": "預計 5 分鐘",
|
"core.dataset.training.Waiting": "預計 20 分鐘",
|
||||||
"core.dataset.training.Website Sync": "網站同步",
|
"core.dataset.training.Website Sync": "網站同步",
|
||||||
"core.dataset.training.tag": "排隊狀況",
|
"core.dataset.training.tag": "排隊狀況",
|
||||||
"core.dataset.website.Base Url": "根網址",
|
"core.dataset.website.Base Url": "根網址",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
"api_url": "介面位址",
|
"api_url": "介面位址",
|
||||||
"auto_indexes": "自動生成補充索引",
|
"auto_indexes": "自動生成補充索引",
|
||||||
"auto_indexes_tips": "通過大模型進行額外索引生成,提高語義豐富度,提高檢索的精度。",
|
"auto_indexes_tips": "通過大模型進行額外索引生成,提高語義豐富度,提高檢索的精度。",
|
||||||
|
"auto_training_queue": "增強索引排隊",
|
||||||
"chunk_max_tokens": "分塊上限",
|
"chunk_max_tokens": "分塊上限",
|
||||||
"close_auto_sync": "確認關閉自動同步功能?",
|
"close_auto_sync": "確認關閉自動同步功能?",
|
||||||
"collection.Create update time": "建立/更新時間",
|
"collection.Create update time": "建立/更新時間",
|
||||||
@@ -25,7 +26,7 @@
|
|||||||
"core.dataset.import.Adjust parameters": "調整參數",
|
"core.dataset.import.Adjust parameters": "調整參數",
|
||||||
"custom_data_process_params": "自訂",
|
"custom_data_process_params": "自訂",
|
||||||
"custom_data_process_params_desc": "自訂資料處理規則",
|
"custom_data_process_params_desc": "自訂資料處理規則",
|
||||||
"data.ideal_chunk_length": "理想分塊長度",
|
"custom_split_sign_tip": "允許你根據自定義的分隔符進行分塊。\n通常用於已處理好的數據,使用特定的分隔符來精確分塊。\n可以使用 | 符號表示多個分割符,例如:“。|.” 表示中英文句號。\n\n盡量避免使用正則相關特殊符號,例如: * () [] {} 等。",
|
||||||
"data_amount": "{{dataAmount}} 組數據, {{indexAmount}} 組索引",
|
"data_amount": "{{dataAmount}} 組數據, {{indexAmount}} 組索引",
|
||||||
"data_index_num": "索引 {{index}}",
|
"data_index_num": "索引 {{index}}",
|
||||||
"data_process_params": "處理參數",
|
"data_process_params": "處理參數",
|
||||||
@@ -51,10 +52,9 @@
|
|||||||
"file_model_function_tip": "用於增強索引和問答生成",
|
"file_model_function_tip": "用於增強索引和問答生成",
|
||||||
"filename": "檔案名稱",
|
"filename": "檔案名稱",
|
||||||
"folder_dataset": "資料夾",
|
"folder_dataset": "資料夾",
|
||||||
"ideal_chunk_length": "理想分塊長度",
|
|
||||||
"ideal_chunk_length_tips": "依結束符號進行分段,並將多個分段組成一個分塊,此值決定了分塊的預估大小,可能會有上下浮動。",
|
|
||||||
"image_auto_parse": "圖片自動索引",
|
"image_auto_parse": "圖片自動索引",
|
||||||
"image_auto_parse_tips": "調用 VLM 自動標註文檔裡的圖片,並生成額外的檢索索引",
|
"image_auto_parse_tips": "調用 VLM 自動標註文檔裡的圖片,並生成額外的檢索索引",
|
||||||
|
"image_training_queue": "圖片處理排隊",
|
||||||
"import.Auto mode Estimated Price Tips": "需呼叫文字理解模型,將消耗較多 AI 點數:{{price}} 點數 / 1K tokens",
|
"import.Auto mode Estimated Price Tips": "需呼叫文字理解模型,將消耗較多 AI 點數:{{price}} 點數 / 1K tokens",
|
||||||
"import.Embedding Estimated Price Tips": "僅使用索引模型,消耗少量 AI 點數:{{price}} 點數 / 1K tokens",
|
"import.Embedding Estimated Price Tips": "僅使用索引模型,消耗少量 AI 點數:{{price}} 點數 / 1K tokens",
|
||||||
"import_confirm": "確認上傳",
|
"import_confirm": "確認上傳",
|
||||||
@@ -65,6 +65,8 @@
|
|||||||
"import_param_setting": "參數設置",
|
"import_param_setting": "參數設置",
|
||||||
"import_select_file": "選擇文件",
|
"import_select_file": "選擇文件",
|
||||||
"import_select_link": "輸入鏈接",
|
"import_select_link": "輸入鏈接",
|
||||||
|
"index_size": "索引大小",
|
||||||
|
"index_size_tips": "向量化時內容的長度,系統會自動按該大小對分塊進行進一步的分割。",
|
||||||
"is_open_schedule": "啟用定時同步",
|
"is_open_schedule": "啟用定時同步",
|
||||||
"keep_image": "保留圖片",
|
"keep_image": "保留圖片",
|
||||||
"move.hint": "移動後,所選資料集/資料夾將繼承新資料夾的權限設定,原先的權限設定將失效。",
|
"move.hint": "移動後,所選資料集/資料夾將繼承新資料夾的權限設定,原先的權限設定將失效。",
|
||||||
@@ -78,7 +80,7 @@
|
|||||||
"permission.des.write": "可新增和變更資料集內容",
|
"permission.des.write": "可新增和變更資料集內容",
|
||||||
"preview_chunk": "分塊預覽",
|
"preview_chunk": "分塊預覽",
|
||||||
"preview_chunk_empty": "無法讀取該文件內容",
|
"preview_chunk_empty": "無法讀取該文件內容",
|
||||||
"preview_chunk_intro": "最多展示 10 個分塊",
|
"preview_chunk_intro": "共 {{total}} 個分塊,最多展示 10 個",
|
||||||
"preview_chunk_not_selected": "點擊左側文件後進行預覽",
|
"preview_chunk_not_selected": "點擊左側文件後進行預覽",
|
||||||
"rebuild_embedding_start_tip": "切換索引模型任務已開始",
|
"rebuild_embedding_start_tip": "切換索引模型任務已開始",
|
||||||
"rebuilding_index_count": "重建中索引數量:{{count}}",
|
"rebuilding_index_count": "重建中索引數量:{{count}}",
|
||||||
@@ -86,6 +88,16 @@
|
|||||||
"retain_collection": "調整訓練參數",
|
"retain_collection": "調整訓練參數",
|
||||||
"retrain_task_submitted": "重新訓練任務已提交",
|
"retrain_task_submitted": "重新訓練任務已提交",
|
||||||
"same_api_collection": "存在相同的 API 集合",
|
"same_api_collection": "存在相同的 API 集合",
|
||||||
|
"split_chunk_char": "按指定分割符分塊",
|
||||||
|
"split_chunk_size": "按長度分塊",
|
||||||
|
"split_sign_break": "1 個換行符",
|
||||||
|
"split_sign_break2": "2 個換行符",
|
||||||
|
"split_sign_custom": "自定義",
|
||||||
|
"split_sign_exclamatiob": "驚嘆號",
|
||||||
|
"split_sign_null": "不設置",
|
||||||
|
"split_sign_period": "句號",
|
||||||
|
"split_sign_question": "問號",
|
||||||
|
"split_sign_semicolon": "分號",
|
||||||
"start_sync_website_tip": "確認開始同步資料?\n將會刪除舊資料後重新獲取,請確認!",
|
"start_sync_website_tip": "確認開始同步資料?\n將會刪除舊資料後重新獲取,請確認!",
|
||||||
"sync_collection_failed": "同步集合錯誤,請檢查是否能正常存取來源文件",
|
"sync_collection_failed": "同步集合錯誤,請檢查是否能正常存取來源文件",
|
||||||
"sync_schedule": "定時同步",
|
"sync_schedule": "定時同步",
|
||||||
|
|||||||
@@ -34,7 +34,8 @@
|
|||||||
"react-hook-form": "7.43.1",
|
"react-hook-form": "7.43.1",
|
||||||
"react-i18next": "14.1.2",
|
"react-i18next": "14.1.2",
|
||||||
"react-photo-view": "^1.2.6",
|
"react-photo-view": "^1.2.6",
|
||||||
"use-context-selector": "^1.4.4"
|
"use-context-selector": "^1.4.4",
|
||||||
|
"zustand": "^4.3.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/js-cookie": "^3.0.5",
|
"@types/js-cookie": "^3.0.5",
|
||||||
|
|||||||
25
packages/web/store/useCommonStore.ts
Normal file
25
packages/web/store/useCommonStore.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { create, devtools, persist, immer } from '../common/zustand';
|
||||||
|
|
||||||
|
type State = {
|
||||||
|
copyContent?: string;
|
||||||
|
setCopyContent: (val?: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useCommonStore = create<State>()(
|
||||||
|
devtools(
|
||||||
|
persist(
|
||||||
|
immer((set, get) => ({
|
||||||
|
copyContent: undefined,
|
||||||
|
setCopyContent(val) {
|
||||||
|
set((state) => {
|
||||||
|
state.copyContent = val;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
{
|
||||||
|
name: 'commonStore',
|
||||||
|
partialize: (state) => ({})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
128
pnpm-lock.yaml
generated
128
pnpm-lock.yaml
generated
@@ -25,7 +25,7 @@ importers:
|
|||||||
version: 13.3.0
|
version: 13.3.0
|
||||||
next-i18next:
|
next-i18next:
|
||||||
specifier: 15.4.2
|
specifier: 15.4.2
|
||||||
version: 15.4.2(i18next@23.16.8)(next@14.2.24(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
version: 15.4.2(i18next@23.16.8)(next@14.2.25(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
||||||
prettier:
|
prettier:
|
||||||
specifier: 3.2.4
|
specifier: 3.2.4
|
||||||
version: 3.2.4
|
version: 3.2.4
|
||||||
@@ -75,8 +75,8 @@ importers:
|
|||||||
specifier: ^5.1.3
|
specifier: ^5.1.3
|
||||||
version: 5.1.3
|
version: 5.1.3
|
||||||
next:
|
next:
|
||||||
specifier: 14.2.24
|
specifier: 14.2.25
|
||||||
version: 14.2.24(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1)
|
version: 14.2.25(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1)
|
||||||
openai:
|
openai:
|
||||||
specifier: 4.61.0
|
specifier: 4.61.0
|
||||||
version: 4.61.0(encoding@0.1.13)(zod@3.24.2)
|
version: 4.61.0(encoding@0.1.13)(zod@3.24.2)
|
||||||
@@ -221,11 +221,11 @@ importers:
|
|||||||
specifier: 1.4.5-lts.1
|
specifier: 1.4.5-lts.1
|
||||||
version: 1.4.5-lts.1
|
version: 1.4.5-lts.1
|
||||||
next:
|
next:
|
||||||
specifier: 14.2.24
|
specifier: 14.2.25
|
||||||
version: 14.2.24(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1)
|
version: 14.2.25(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1)
|
||||||
nextjs-cors:
|
nextjs-cors:
|
||||||
specifier: ^2.2.0
|
specifier: ^2.2.0
|
||||||
version: 2.2.0(next@14.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))
|
version: 2.2.0(next@14.2.25(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))
|
||||||
node-cron:
|
node-cron:
|
||||||
specifier: ^3.0.3
|
specifier: ^3.0.3
|
||||||
version: 3.0.3
|
version: 3.0.3
|
||||||
@@ -307,7 +307,7 @@ importers:
|
|||||||
version: 2.1.1(@chakra-ui/system@2.6.1(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
version: 2.1.1(@chakra-ui/system@2.6.1(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
||||||
'@chakra-ui/next-js':
|
'@chakra-ui/next-js':
|
||||||
specifier: 2.4.2
|
specifier: 2.4.2
|
||||||
version: 2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.24(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1)
|
version: 2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.25(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1)
|
||||||
'@chakra-ui/react':
|
'@chakra-ui/react':
|
||||||
specifier: 2.10.7
|
specifier: 2.10.7
|
||||||
version: 2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
@@ -370,7 +370,7 @@ importers:
|
|||||||
version: 4.17.21
|
version: 4.17.21
|
||||||
next-i18next:
|
next-i18next:
|
||||||
specifier: 15.4.2
|
specifier: 15.4.2
|
||||||
version: 15.4.2(i18next@23.16.8)(next@14.2.24(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
version: 15.4.2(i18next@23.16.8)(next@14.2.25(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
||||||
papaparse:
|
papaparse:
|
||||||
specifier: ^5.4.1
|
specifier: ^5.4.1
|
||||||
version: 5.4.1
|
version: 5.4.1
|
||||||
@@ -398,6 +398,9 @@ importers:
|
|||||||
use-context-selector:
|
use-context-selector:
|
||||||
specifier: ^1.4.4
|
specifier: ^1.4.4
|
||||||
version: 1.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)
|
version: 1.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)
|
||||||
|
zustand:
|
||||||
|
specifier: ^4.3.5
|
||||||
|
version: 4.5.6(@types/react@18.3.1)(immer@9.0.21)(react@18.3.1)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@types/js-cookie':
|
'@types/js-cookie':
|
||||||
specifier: ^3.0.5
|
specifier: ^3.0.5
|
||||||
@@ -428,7 +431,7 @@ importers:
|
|||||||
version: 2.1.1(@chakra-ui/system@2.6.1(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
version: 2.1.1(@chakra-ui/system@2.6.1(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
||||||
'@chakra-ui/next-js':
|
'@chakra-ui/next-js':
|
||||||
specifier: 2.4.2
|
specifier: 2.4.2
|
||||||
version: 2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.24(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1)
|
version: 2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.25(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1)
|
||||||
'@chakra-ui/react':
|
'@chakra-ui/react':
|
||||||
specifier: 2.10.7
|
specifier: 2.10.7
|
||||||
version: 2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
@@ -523,11 +526,11 @@ importers:
|
|||||||
specifier: ^5.1.3
|
specifier: ^5.1.3
|
||||||
version: 5.1.3
|
version: 5.1.3
|
||||||
next:
|
next:
|
||||||
specifier: 14.2.24
|
specifier: 14.2.25
|
||||||
version: 14.2.24(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1)
|
version: 14.2.25(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1)
|
||||||
next-i18next:
|
next-i18next:
|
||||||
specifier: 15.4.2
|
specifier: 15.4.2
|
||||||
version: 15.4.2(i18next@23.16.8)(next@14.2.24(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
version: 15.4.2(i18next@23.16.8)(next@14.2.25(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
||||||
nprogress:
|
nprogress:
|
||||||
specifier: ^0.2.0
|
specifier: ^0.2.0
|
||||||
version: 0.2.0
|
version: 0.2.0
|
||||||
@@ -588,9 +591,6 @@ importers:
|
|||||||
use-context-selector:
|
use-context-selector:
|
||||||
specifier: ^1.4.4
|
specifier: ^1.4.4
|
||||||
version: 1.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)
|
version: 1.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)
|
||||||
zustand:
|
|
||||||
specifier: ^4.3.5
|
|
||||||
version: 4.5.6(@types/react@18.3.1)(immer@9.0.21)(react@18.3.1)
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@svgr/webpack':
|
'@svgr/webpack':
|
||||||
specifier: ^6.5.1
|
specifier: ^6.5.1
|
||||||
@@ -2412,62 +2412,62 @@ packages:
|
|||||||
'@nestjs/platform-express':
|
'@nestjs/platform-express':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/env@14.2.24':
|
'@next/env@14.2.25':
|
||||||
resolution: {integrity: sha512-LAm0Is2KHTNT6IT16lxT+suD0u+VVfYNQqM+EJTKuFRRuY2z+zj01kueWXPCxbMBDt0B5vONYzabHGUNbZYAhA==}
|
resolution: {integrity: sha512-JnzQ2cExDeG7FxJwqAksZ3aqVJrHjFwZQAEJ9gQZSoEhIow7SNoKZzju/AwQ+PLIR4NY8V0rhcVozx/2izDO0w==}
|
||||||
|
|
||||||
'@next/eslint-plugin-next@14.2.24':
|
'@next/eslint-plugin-next@14.2.24':
|
||||||
resolution: {integrity: sha512-FDL3qs+5DML0AJz56DCVr+KnFYivxeAX73En8QbPw9GjJZ6zbfvqDy+HrarHFzbsIASn7y8y5ySJ/lllSruNVQ==}
|
resolution: {integrity: sha512-FDL3qs+5DML0AJz56DCVr+KnFYivxeAX73En8QbPw9GjJZ6zbfvqDy+HrarHFzbsIASn7y8y5ySJ/lllSruNVQ==}
|
||||||
|
|
||||||
'@next/swc-darwin-arm64@14.2.24':
|
'@next/swc-darwin-arm64@14.2.25':
|
||||||
resolution: {integrity: sha512-7Tdi13aojnAZGpapVU6meVSpNzgrFwZ8joDcNS8cJVNuP3zqqrLqeory9Xec5TJZR/stsGJdfwo8KeyloT3+rQ==}
|
resolution: {integrity: sha512-09clWInF1YRd6le00vt750s3m7SEYNehz9C4PUcSu3bAdCTpjIV4aTYQZ25Ehrr83VR1rZeqtKUPWSI7GfuKZQ==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
'@next/swc-darwin-x64@14.2.24':
|
'@next/swc-darwin-x64@14.2.25':
|
||||||
resolution: {integrity: sha512-lXR2WQqUtu69l5JMdTwSvQUkdqAhEWOqJEYUQ21QczQsAlNOW2kWZCucA6b3EXmPbcvmHB1kSZDua/713d52xg==}
|
resolution: {integrity: sha512-V+iYM/QR+aYeJl3/FWWU/7Ix4b07ovsQ5IbkwgUK29pTHmq+5UxeDr7/dphvtXEq5pLB/PucfcBNh9KZ8vWbug==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
'@next/swc-linux-arm64-gnu@14.2.24':
|
'@next/swc-linux-arm64-gnu@14.2.25':
|
||||||
resolution: {integrity: sha512-nxvJgWOpSNmzidYvvGDfXwxkijb6hL9+cjZx1PVG6urr2h2jUqBALkKjT7kpfurRWicK6hFOvarmaWsINT1hnA==}
|
resolution: {integrity: sha512-LFnV2899PJZAIEHQ4IMmZIgL0FBieh5keMnriMY1cK7ompR+JUd24xeTtKkcaw8QmxmEdhoE5Mu9dPSuDBgtTg==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@next/swc-linux-arm64-musl@14.2.24':
|
'@next/swc-linux-arm64-musl@14.2.25':
|
||||||
resolution: {integrity: sha512-PaBgOPhqa4Abxa3y/P92F3kklNPsiFjcjldQGT7kFmiY5nuFn8ClBEoX8GIpqU1ODP2y8P6hio6vTomx2Vy0UQ==}
|
resolution: {integrity: sha512-QC5y5PPTmtqFExcKWKYgUNkHeHE/z3lUsu83di488nyP0ZzQ3Yse2G6TCxz6nNsQwgAx1BehAJTZez+UQxzLfw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@next/swc-linux-x64-gnu@14.2.24':
|
'@next/swc-linux-x64-gnu@14.2.25':
|
||||||
resolution: {integrity: sha512-vEbyadiRI7GOr94hd2AB15LFVgcJZQWu7Cdi9cWjCMeCiUsHWA0U5BkGPuoYRnTxTn0HacuMb9NeAmStfBCLoQ==}
|
resolution: {integrity: sha512-y6/ML4b9eQ2D/56wqatTJN5/JR8/xdObU2Fb1RBidnrr450HLCKr6IJZbPqbv7NXmje61UyxjF5kvSajvjye5w==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@next/swc-linux-x64-musl@14.2.24':
|
'@next/swc-linux-x64-musl@14.2.25':
|
||||||
resolution: {integrity: sha512-df0FC9ptaYsd8nQCINCzFtDWtko8PNRTAU0/+d7hy47E0oC17tI54U/0NdGk7l/76jz1J377dvRjmt6IUdkpzQ==}
|
resolution: {integrity: sha512-sPX0TSXHGUOZFvv96GoBXpB3w4emMqKeMgemrSxI7A6l55VBJp/RKYLwZIB9JxSqYPApqiREaIIap+wWq0RU8w==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@next/swc-win32-arm64-msvc@14.2.24':
|
'@next/swc-win32-arm64-msvc@14.2.25':
|
||||||
resolution: {integrity: sha512-ZEntbLjeYAJ286eAqbxpZHhDFYpYjArotQ+/TW9j7UROh0DUmX7wYDGtsTPpfCV8V+UoqHBPU7q9D4nDNH014Q==}
|
resolution: {integrity: sha512-ReO9S5hkA1DU2cFCsGoOEp7WJkhFzNbU/3VUF6XxNGUCQChyug6hZdYL/istQgfT/GWE6PNIg9cm784OI4ddxQ==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@next/swc-win32-ia32-msvc@14.2.24':
|
'@next/swc-win32-ia32-msvc@14.2.25':
|
||||||
resolution: {integrity: sha512-9KuS+XUXM3T6v7leeWU0erpJ6NsFIwiTFD5nzNg8J5uo/DMIPvCp3L1Ao5HjbHX0gkWPB1VrKoo/Il4F0cGK2Q==}
|
resolution: {integrity: sha512-DZ/gc0o9neuCDyD5IumyTGHVun2dCox5TfPQI/BJTYwpSNYM3CZDI4i6TOdjeq1JMo+Ug4kPSMuZdwsycwFbAw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [ia32]
|
cpu: [ia32]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@next/swc-win32-x64-msvc@14.2.24':
|
'@next/swc-win32-x64-msvc@14.2.25':
|
||||||
resolution: {integrity: sha512-cXcJ2+x0fXQ2CntaE00d7uUH+u1Bfp/E0HsNQH79YiLaZE5Rbm7dZzyAYccn3uICM7mw+DxoMqEfGXZtF4Fgaw==}
|
resolution: {integrity: sha512-KSznmS6eFjQ9RJ1nEc66kJvtGIL1iZMYmGEXsZPh2YtnLtqrgdVvKXJY2ScjjoFnG6nGLyPFR0UiEvDwVah4Tw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
@@ -7191,8 +7191,8 @@ packages:
|
|||||||
react: '>= 17.0.2'
|
react: '>= 17.0.2'
|
||||||
react-i18next: '>= 13.5.0'
|
react-i18next: '>= 13.5.0'
|
||||||
|
|
||||||
next@14.2.24:
|
next@14.2.25:
|
||||||
resolution: {integrity: sha512-En8VEexSJ0Py2FfVnRRh8gtERwDRaJGNvsvad47ShkC2Yi8AXQPXEA2vKoDJlGFSj5WE5SyF21zNi4M5gyi+SQ==}
|
resolution: {integrity: sha512-N5M7xMc4wSb4IkPvEV5X2BRRXUmhVHNyaXwEM86+voXthSZz8ZiRyQW4p9mwAoAPIm6OzuVZtn7idgEJeAJN3Q==}
|
||||||
engines: {node: '>=18.17.0'}
|
engines: {node: '>=18.17.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -10652,12 +10652,12 @@ snapshots:
|
|||||||
'@chakra-ui/system': 2.6.1(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(react@18.3.1)
|
'@chakra-ui/system': 2.6.1(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(react@18.3.1)
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
|
|
||||||
'@chakra-ui/next-js@2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.24(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1)':
|
'@chakra-ui/next-js@2.4.2(@chakra-ui/react@2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(next@14.2.25(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react@18.3.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@chakra-ui/react': 2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@chakra-ui/react': 2.10.7(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@emotion/cache': 11.14.0
|
'@emotion/cache': 11.14.0
|
||||||
'@emotion/react': 11.11.1(@types/react@18.3.1)(react@18.3.1)
|
'@emotion/react': 11.11.1(@types/react@18.3.1)(react@18.3.1)
|
||||||
next: 14.2.24(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1)
|
next: 14.2.25(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1)
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
|
|
||||||
'@chakra-ui/object-utils@2.1.0': {}
|
'@chakra-ui/object-utils@2.1.0': {}
|
||||||
@@ -11665,37 +11665,37 @@ snapshots:
|
|||||||
'@nestjs/core': 10.4.15(@nestjs/common@10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.2))(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.2)
|
'@nestjs/core': 10.4.15(@nestjs/common@10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.2))(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.2)
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@next/env@14.2.24': {}
|
'@next/env@14.2.25': {}
|
||||||
|
|
||||||
'@next/eslint-plugin-next@14.2.24':
|
'@next/eslint-plugin-next@14.2.24':
|
||||||
dependencies:
|
dependencies:
|
||||||
glob: 10.3.10
|
glob: 10.3.10
|
||||||
|
|
||||||
'@next/swc-darwin-arm64@14.2.24':
|
'@next/swc-darwin-arm64@14.2.25':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-darwin-x64@14.2.24':
|
'@next/swc-darwin-x64@14.2.25':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-linux-arm64-gnu@14.2.24':
|
'@next/swc-linux-arm64-gnu@14.2.25':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-linux-arm64-musl@14.2.24':
|
'@next/swc-linux-arm64-musl@14.2.25':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-linux-x64-gnu@14.2.24':
|
'@next/swc-linux-x64-gnu@14.2.25':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-linux-x64-musl@14.2.24':
|
'@next/swc-linux-x64-musl@14.2.25':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-win32-arm64-msvc@14.2.24':
|
'@next/swc-win32-arm64-msvc@14.2.25':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-win32-ia32-msvc@14.2.24':
|
'@next/swc-win32-ia32-msvc@14.2.25':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-win32-x64-msvc@14.2.24':
|
'@next/swc-win32-x64-msvc@14.2.25':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@node-rs/jieba-android-arm-eabi@2.0.1':
|
'@node-rs/jieba-android-arm-eabi@2.0.1':
|
||||||
@@ -17532,7 +17532,7 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
next-i18next@15.4.2(i18next@23.16.8)(next@14.2.24(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1):
|
next-i18next@15.4.2(i18next@23.16.8)(next@14.2.25(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1))(react-i18next@14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.26.10
|
'@babel/runtime': 7.26.10
|
||||||
'@types/hoist-non-react-statics': 3.3.6
|
'@types/hoist-non-react-statics': 3.3.6
|
||||||
@@ -17540,13 +17540,13 @@ snapshots:
|
|||||||
hoist-non-react-statics: 3.3.2
|
hoist-non-react-statics: 3.3.2
|
||||||
i18next: 23.16.8
|
i18next: 23.16.8
|
||||||
i18next-fs-backend: 2.6.0
|
i18next-fs-backend: 2.6.0
|
||||||
next: 14.2.24(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1)
|
next: 14.2.25(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1)
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
react-i18next: 14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
react-i18next: 14.1.2(i18next@23.16.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
|
||||||
next@14.2.24(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1):
|
next@14.2.25(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@next/env': 14.2.24
|
'@next/env': 14.2.25
|
||||||
'@swc/helpers': 0.5.5
|
'@swc/helpers': 0.5.5
|
||||||
busboy: 1.6.0
|
busboy: 1.6.0
|
||||||
caniuse-lite: 1.0.30001704
|
caniuse-lite: 1.0.30001704
|
||||||
@@ -17556,24 +17556,24 @@ snapshots:
|
|||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
styled-jsx: 5.1.1(@babel/core@7.26.10)(react@18.3.1)
|
styled-jsx: 5.1.1(@babel/core@7.26.10)(react@18.3.1)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@next/swc-darwin-arm64': 14.2.24
|
'@next/swc-darwin-arm64': 14.2.25
|
||||||
'@next/swc-darwin-x64': 14.2.24
|
'@next/swc-darwin-x64': 14.2.25
|
||||||
'@next/swc-linux-arm64-gnu': 14.2.24
|
'@next/swc-linux-arm64-gnu': 14.2.25
|
||||||
'@next/swc-linux-arm64-musl': 14.2.24
|
'@next/swc-linux-arm64-musl': 14.2.25
|
||||||
'@next/swc-linux-x64-gnu': 14.2.24
|
'@next/swc-linux-x64-gnu': 14.2.25
|
||||||
'@next/swc-linux-x64-musl': 14.2.24
|
'@next/swc-linux-x64-musl': 14.2.25
|
||||||
'@next/swc-win32-arm64-msvc': 14.2.24
|
'@next/swc-win32-arm64-msvc': 14.2.25
|
||||||
'@next/swc-win32-ia32-msvc': 14.2.24
|
'@next/swc-win32-ia32-msvc': 14.2.25
|
||||||
'@next/swc-win32-x64-msvc': 14.2.24
|
'@next/swc-win32-x64-msvc': 14.2.25
|
||||||
sass: 1.85.1
|
sass: 1.85.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@babel/core'
|
- '@babel/core'
|
||||||
- babel-plugin-macros
|
- babel-plugin-macros
|
||||||
|
|
||||||
nextjs-cors@2.2.0(next@14.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1)):
|
nextjs-cors@2.2.0(next@14.2.25(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
cors: 2.8.5
|
cors: 2.8.5
|
||||||
next: 14.2.24(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1)
|
next: 14.2.25(@babel/core@7.26.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.85.1)
|
||||||
|
|
||||||
node-abi@3.74.0:
|
node-abi@3.74.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "app",
|
"name": "app",
|
||||||
"version": "4.9.1",
|
"version": "4.9.2",
|
||||||
"private": false,
|
"private": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"mermaid": "^10.2.3",
|
"mermaid": "^10.2.3",
|
||||||
"nanoid": "^5.1.3",
|
"nanoid": "^5.1.3",
|
||||||
"next": "14.2.24",
|
"next": "14.2.25",
|
||||||
"next-i18next": "15.4.2",
|
"next-i18next": "15.4.2",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"qrcode": "^1.5.4",
|
"qrcode": "^1.5.4",
|
||||||
@@ -64,8 +64,7 @@
|
|||||||
"request-ip": "^3.3.0",
|
"request-ip": "^3.3.0",
|
||||||
"sass": "^1.58.3",
|
"sass": "^1.58.3",
|
||||||
"use-context-selector": "^1.4.4",
|
"use-context-selector": "^1.4.4",
|
||||||
"@node-rs/jieba": "2.0.1",
|
"@node-rs/jieba": "2.0.1"
|
||||||
"zustand": "^4.3.5"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@svgr/webpack": "^6.5.1",
|
"@svgr/webpack": "^6.5.1",
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ const NotSufficientModal = dynamic(() => import('@/components/support/wallet/Not
|
|||||||
const SystemMsgModal = dynamic(() => import('@/components/support/user/inform/SystemMsgModal'));
|
const SystemMsgModal = dynamic(() => import('@/components/support/user/inform/SystemMsgModal'));
|
||||||
const ImportantInform = dynamic(() => import('@/components/support/user/inform/ImportantInform'));
|
const ImportantInform = dynamic(() => import('@/components/support/user/inform/ImportantInform'));
|
||||||
const UpdateContact = dynamic(() => import('@/components/support/user/inform/UpdateContactModal'));
|
const UpdateContact = dynamic(() => import('@/components/support/user/inform/UpdateContactModal'));
|
||||||
|
const ManualCopyModal = dynamic(() =>
|
||||||
|
import('@fastgpt/web/hooks/useCopyData').then((mod) => mod.ManualCopyModal)
|
||||||
|
);
|
||||||
|
|
||||||
const pcUnShowLayoutRoute: Record<string, boolean> = {
|
const pcUnShowLayoutRoute: Record<string, boolean> = {
|
||||||
'/': true,
|
'/': true,
|
||||||
@@ -162,6 +165,7 @@ const Layout = ({ children }: { children: JSX.Element }) => {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<ManualCopyModal />
|
||||||
<Loading loading={loading} zIndex={999999} />
|
<Loading loading={loading} zIndex={999999} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ const EditResourceModal = ({
|
|||||||
{...register('name', { required: true })}
|
{...register('name', { required: true })}
|
||||||
bg={'myGray.50'}
|
bg={'myGray.50'}
|
||||||
autoFocus
|
autoFocus
|
||||||
maxLength={20}
|
maxLength={100}
|
||||||
/>
|
/>
|
||||||
</HStack>
|
</HStack>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ const FolderPath = (props: {
|
|||||||
py={0.5}
|
py={0.5}
|
||||||
px={1.5}
|
px={1.5}
|
||||||
borderRadius={'md'}
|
borderRadius={'md'}
|
||||||
|
maxW={'45vw'}
|
||||||
|
className={'textEllipsis'}
|
||||||
{...(i === concatPaths.length - 1
|
{...(i === concatPaths.length - 1
|
||||||
? {
|
? {
|
||||||
cursor: 'default',
|
cursor: 'default',
|
||||||
|
|||||||
@@ -69,31 +69,37 @@ export const DatasetSelectModal = ({
|
|||||||
{selectedDatasets.map((item) =>
|
{selectedDatasets.map((item) =>
|
||||||
(() => {
|
(() => {
|
||||||
return (
|
return (
|
||||||
<Card
|
<MyTooltip label={item.name}>
|
||||||
key={item.datasetId}
|
<Card
|
||||||
p={3}
|
key={item.datasetId}
|
||||||
border={theme.borders.base}
|
p={3}
|
||||||
boxShadow={'sm'}
|
border={'base'}
|
||||||
bg={'primary.200'}
|
boxShadow={'sm'}
|
||||||
>
|
bg={'primary.200'}
|
||||||
<Flex alignItems={'center'} h={'38px'}>
|
>
|
||||||
<Avatar src={item.avatar} w={['1.25rem', '1.75rem']}></Avatar>
|
<Flex alignItems={'center'} h={'38px'}>
|
||||||
<Box flex={'1 0 0'} w={0} className="textEllipsis" mx={3}>
|
<Avatar
|
||||||
{item.name}
|
src={item.avatar}
|
||||||
</Box>
|
w={['1.25rem', '1.75rem']}
|
||||||
<MyIcon
|
borderRadius={'sm'}
|
||||||
name={'delete'}
|
></Avatar>
|
||||||
w={'14px'}
|
<Box flex={'1 0 0'} w={0} className="textEllipsis" mx={3} fontSize={'sm'}>
|
||||||
cursor={'pointer'}
|
{item.name}
|
||||||
_hover={{ color: 'red.500' }}
|
</Box>
|
||||||
onClick={() => {
|
<MyIcon
|
||||||
setSelectedDatasets((state) =>
|
name={'delete'}
|
||||||
state.filter((dataset) => dataset.datasetId !== item.datasetId)
|
w={'14px'}
|
||||||
);
|
cursor={'pointer'}
|
||||||
}}
|
_hover={{ color: 'red.500' }}
|
||||||
/>
|
onClick={() => {
|
||||||
</Flex>
|
setSelectedDatasets((state) =>
|
||||||
</Card>
|
state.filter((dataset) => dataset.datasetId !== item.datasetId)
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Card>
|
||||||
|
</MyTooltip>
|
||||||
);
|
);
|
||||||
})()
|
})()
|
||||||
)}
|
)}
|
||||||
@@ -117,7 +123,7 @@ export const DatasetSelectModal = ({
|
|||||||
label={
|
label={
|
||||||
item.type === DatasetTypeEnum.folder
|
item.type === DatasetTypeEnum.folder
|
||||||
? t('common:dataset.Select Folder')
|
? t('common:dataset.Select Folder')
|
||||||
: t('common:dataset.Select Dataset')
|
: item.name
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Card
|
<Card
|
||||||
@@ -152,14 +158,18 @@ export const DatasetSelectModal = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Flex alignItems={'center'} h={'38px'}>
|
<Flex alignItems={'center'} h={'38px'}>
|
||||||
<Avatar src={item.avatar} w={['24px', '28px']}></Avatar>
|
<Avatar
|
||||||
|
src={item.avatar}
|
||||||
|
w={['1.25rem', '1.75rem']}
|
||||||
|
borderRadius={'sm'}
|
||||||
|
></Avatar>
|
||||||
<Box
|
<Box
|
||||||
flex={'1 0 0'}
|
flex={'1 0 0'}
|
||||||
w={0}
|
w={0}
|
||||||
className="textEllipsis"
|
className="textEllipsis"
|
||||||
ml={3}
|
ml={3}
|
||||||
fontSize={'md'}
|
|
||||||
color={'myGray.900'}
|
color={'myGray.900'}
|
||||||
|
fontSize={'sm'}
|
||||||
>
|
>
|
||||||
{item.name}
|
{item.name}
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import { useSystemStore } from '@/web/common/system/useSystemStore';
|
|||||||
import AIModelSelector from '@/components/Select/AIModelSelector';
|
import AIModelSelector from '@/components/Select/AIModelSelector';
|
||||||
import CustomPromptEditor from '@fastgpt/web/components/common/Textarea/CustomPromptEditor';
|
import CustomPromptEditor from '@fastgpt/web/components/common/Textarea/CustomPromptEditor';
|
||||||
import {
|
import {
|
||||||
PROMPT_QUESTION_GUIDE,
|
QuestionGuideFooterPrompt,
|
||||||
PROMPT_QUESTION_GUIDE_FOOTER
|
QuestionGuidePrompt
|
||||||
} from '@fastgpt/global/core/ai/prompt/agent';
|
} from '@fastgpt/global/core/ai/prompt/agent';
|
||||||
|
|
||||||
// question generator config
|
// question generator config
|
||||||
@@ -38,7 +38,7 @@ const QGConfig = ({
|
|||||||
return (
|
return (
|
||||||
<Flex alignItems={'center'}>
|
<Flex alignItems={'center'}>
|
||||||
<MyIcon name={'core/chat/QGFill'} mr={2} w={'20px'} />
|
<MyIcon name={'core/chat/QGFill'} mr={2} w={'20px'} />
|
||||||
<FormLabel>{t('common:core.app.Question Guide')}</FormLabel>
|
<FormLabel color={'myGray.600'}>{t('common:core.app.Question Guide')}</FormLabel>
|
||||||
<ChatFunctionTip type={'nextQuestion'} />
|
<ChatFunctionTip type={'nextQuestion'} />
|
||||||
<Box flex={1} />
|
<Box flex={1} />
|
||||||
<MyTooltip label={t('app:config_question_guide')}>
|
<MyTooltip label={t('app:config_question_guide')}>
|
||||||
@@ -168,7 +168,7 @@ const QGConfigModal = ({
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{customPrompt || PROMPT_QUESTION_GUIDE}
|
{customPrompt || QuestionGuidePrompt}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
@@ -178,8 +178,8 @@ const QGConfigModal = ({
|
|||||||
{isOpenCustomPrompt && (
|
{isOpenCustomPrompt && (
|
||||||
<CustomPromptEditor
|
<CustomPromptEditor
|
||||||
defaultValue={customPrompt}
|
defaultValue={customPrompt}
|
||||||
defaultPrompt={PROMPT_QUESTION_GUIDE}
|
defaultPrompt={QuestionGuidePrompt}
|
||||||
footerPrompt={PROMPT_QUESTION_GUIDE_FOOTER}
|
footerPrompt={QuestionGuideFooterPrompt}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
onChange({
|
onChange({
|
||||||
...value,
|
...value,
|
||||||
|
|||||||
@@ -1,20 +1,26 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect, useMemo } from 'react';
|
||||||
import { Controller, UseFormReturn } from 'react-hook-form';
|
import { Controller, UseFormReturn } from 'react-hook-form';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { Box, Button, Card, Textarea } from '@chakra-ui/react';
|
import { Box, Button, Card, Flex, Switch, Textarea } from '@chakra-ui/react';
|
||||||
import ChatAvatar from './ChatAvatar';
|
import ChatAvatar from './ChatAvatar';
|
||||||
import { MessageCardStyle } from '../constants';
|
import { MessageCardStyle } from '../constants';
|
||||||
import { VariableInputEnum } from '@fastgpt/global/core/workflow/constants';
|
import {
|
||||||
|
VariableInputEnum,
|
||||||
|
WorkflowIOValueTypeEnum
|
||||||
|
} from '@fastgpt/global/core/workflow/constants';
|
||||||
import MySelect from '@fastgpt/web/components/common/MySelect';
|
import MySelect from '@fastgpt/web/components/common/MySelect';
|
||||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||||
import { ChatBoxInputFormType } from '../type.d';
|
import { ChatBoxInputFormType } from '../type.d';
|
||||||
import { useContextSelector } from 'use-context-selector';
|
import { useContextSelector } from 'use-context-selector';
|
||||||
import { ChatBoxContext } from '../Provider';
|
|
||||||
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
|
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
|
||||||
import { VariableItemType } from '@fastgpt/global/core/app/type';
|
import { VariableItemType } from '@fastgpt/global/core/app/type';
|
||||||
import MyTextarea from '@/components/common/Textarea/MyTextarea';
|
import MyTextarea from '@/components/common/Textarea/MyTextarea';
|
||||||
import MyNumberInput from '@fastgpt/web/components/common/Input/NumberInput';
|
import MyNumberInput from '@fastgpt/web/components/common/Input/NumberInput';
|
||||||
import { ChatItemContext } from '@/web/core/chat/context/chatItemContext';
|
import { ChatItemContext } from '@/web/core/chat/context/chatItemContext';
|
||||||
|
import { ChatBoxContext } from '../Provider';
|
||||||
|
import dynamic from 'next/dynamic';
|
||||||
|
|
||||||
|
const JsonEditor = dynamic(() => import('@fastgpt/web/components/common/Textarea/JsonEditor'));
|
||||||
|
|
||||||
export const VariableInputItem = ({
|
export const VariableInputItem = ({
|
||||||
item,
|
item,
|
||||||
@@ -23,7 +29,11 @@ export const VariableInputItem = ({
|
|||||||
item: VariableItemType;
|
item: VariableItemType;
|
||||||
variablesForm: UseFormReturn<any>;
|
variablesForm: UseFormReturn<any>;
|
||||||
}) => {
|
}) => {
|
||||||
const { register, control, setValue } = variablesForm;
|
const {
|
||||||
|
control,
|
||||||
|
setValue,
|
||||||
|
formState: { errors }
|
||||||
|
} = variablesForm;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box key={item.id} mb={4} pl={1}>
|
<Box key={item.id} mb={4} pl={1}>
|
||||||
@@ -43,37 +53,31 @@ export const VariableInputItem = ({
|
|||||||
)}
|
)}
|
||||||
{item.description && <QuestionTip ml={1} label={item.description} />}
|
{item.description && <QuestionTip ml={1} label={item.description} />}
|
||||||
</Box>
|
</Box>
|
||||||
{item.type === VariableInputEnum.input && (
|
|
||||||
<MyTextarea
|
<Controller
|
||||||
autoHeight
|
key={`variables.${item.key}`}
|
||||||
minH={40}
|
control={control}
|
||||||
maxH={160}
|
name={`variables.${item.key}`}
|
||||||
bg={'myGray.50'}
|
rules={{
|
||||||
{...register(`variables.${item.key}`, {
|
required: item.required
|
||||||
required: item.required
|
}}
|
||||||
})}
|
render={({ field: { onChange, value } }) => {
|
||||||
/>
|
if (item.type === VariableInputEnum.input) {
|
||||||
)}
|
return (
|
||||||
{item.type === VariableInputEnum.textarea && (
|
<MyTextarea
|
||||||
<Textarea
|
autoHeight
|
||||||
{...register(`variables.${item.key}`, {
|
minH={40}
|
||||||
required: item.required
|
maxH={160}
|
||||||
})}
|
bg={'myGray.50'}
|
||||||
rows={5}
|
value={value}
|
||||||
bg={'myGray.50'}
|
isInvalid={errors?.variables && Object.keys(errors.variables).includes(item.key)}
|
||||||
maxLength={item.maxLength || 4000}
|
onChange={onChange}
|
||||||
/>
|
/>
|
||||||
)}
|
);
|
||||||
{item.type === VariableInputEnum.select && (
|
}
|
||||||
<Controller
|
if (item.type === VariableInputEnum.select) {
|
||||||
key={`variables.${item.key}`}
|
|
||||||
control={control}
|
|
||||||
name={`variables.${item.key}`}
|
|
||||||
rules={{ required: item.required }}
|
|
||||||
render={({ field: { ref, value } }) => {
|
|
||||||
return (
|
return (
|
||||||
<MySelect
|
<MySelect
|
||||||
ref={ref}
|
|
||||||
width={'100%'}
|
width={'100%'}
|
||||||
list={(item.enums || []).map((item: { value: any }) => ({
|
list={(item.enums || []).map((item: { value: any }) => ({
|
||||||
label: item.value,
|
label: item.value,
|
||||||
@@ -83,86 +87,217 @@ export const VariableInputItem = ({
|
|||||||
onChange={(e) => setValue(`variables.${item.key}`, e)}
|
onChange={(e) => setValue(`variables.${item.key}`, e)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}}
|
}
|
||||||
/>
|
if (item.type === VariableInputEnum.numberInput) {
|
||||||
)}
|
return (
|
||||||
{item.type === VariableInputEnum.numberInput && (
|
<MyNumberInput
|
||||||
<Controller
|
step={1}
|
||||||
key={`variables.${item.key}`}
|
min={item.min}
|
||||||
control={control}
|
max={item.max}
|
||||||
name={`variables.${item.key}`}
|
bg={'white'}
|
||||||
rules={{ required: item.required, min: item.min, max: item.max }}
|
value={value}
|
||||||
render={({ field: { value, onChange } }) => (
|
onChange={onChange}
|
||||||
<MyNumberInput
|
isInvalid={errors?.variables && Object.keys(errors.variables).includes(item.key)}
|
||||||
step={1}
|
/>
|
||||||
min={item.min}
|
);
|
||||||
max={item.max}
|
}
|
||||||
bg={'white'}
|
return (
|
||||||
|
<Textarea
|
||||||
value={value}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
rows={5}
|
||||||
|
bg={'myGray.50'}
|
||||||
|
maxLength={item.maxLength || 4000}
|
||||||
/>
|
/>
|
||||||
)}
|
);
|
||||||
/>
|
}}
|
||||||
)}
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ExternalVariableInputItem = ({
|
||||||
|
item,
|
||||||
|
variablesForm,
|
||||||
|
showTag = false
|
||||||
|
}: {
|
||||||
|
item: VariableItemType;
|
||||||
|
variablesForm: UseFormReturn<any>;
|
||||||
|
showTag?: boolean;
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { control } = variablesForm;
|
||||||
|
|
||||||
|
const Label = useMemo(() => {
|
||||||
|
return (
|
||||||
|
<Box display={'flex'} position={'relative'} mb={1} alignItems={'center'} w={'full'}>
|
||||||
|
{item.label}
|
||||||
|
{item.description && <QuestionTip ml={1} label={item.description} />}
|
||||||
|
{showTag && (
|
||||||
|
<Flex
|
||||||
|
color={'primary.600'}
|
||||||
|
bg={'primary.100'}
|
||||||
|
px={2}
|
||||||
|
py={1}
|
||||||
|
gap={1}
|
||||||
|
ml={2}
|
||||||
|
fontSize={'mini'}
|
||||||
|
rounded={'sm'}
|
||||||
|
>
|
||||||
|
<MyIcon name={'common/info'} color={'primary.600'} w={4} />
|
||||||
|
{t('chat:variable_invisable_in_share')}
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}, [item.description, item.label, showTag, t]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box key={item.id} mb={4} pl={1}>
|
||||||
|
{Label}
|
||||||
|
<Controller
|
||||||
|
key={`variables.${item.key}`}
|
||||||
|
control={control}
|
||||||
|
name={`variables.${item.key}`}
|
||||||
|
render={({ field: { onChange, value } }) => {
|
||||||
|
if (item.valueType === WorkflowIOValueTypeEnum.string) {
|
||||||
|
return (
|
||||||
|
<MyTextarea
|
||||||
|
autoHeight
|
||||||
|
minH={40}
|
||||||
|
maxH={160}
|
||||||
|
bg={'myGray.50'}
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (item.valueType === WorkflowIOValueTypeEnum.number) {
|
||||||
|
return <MyNumberInput step={1} bg={'myGray.50'} value={value} onChange={onChange} />;
|
||||||
|
}
|
||||||
|
if (item.valueType === WorkflowIOValueTypeEnum.boolean) {
|
||||||
|
return <Switch isChecked={value} onChange={onChange} />;
|
||||||
|
}
|
||||||
|
return <JsonEditor bg={'myGray.50'} resize value={value} onChange={onChange} />;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const VariableInput = ({
|
const VariableInput = ({
|
||||||
chatForm,
|
chatForm,
|
||||||
chatStarted
|
chatStarted,
|
||||||
|
showExternalVariables = false
|
||||||
}: {
|
}: {
|
||||||
chatStarted: boolean;
|
|
||||||
chatForm: UseFormReturn<ChatBoxInputFormType>;
|
chatForm: UseFormReturn<ChatBoxInputFormType>;
|
||||||
|
chatStarted: boolean;
|
||||||
|
showExternalVariables?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const appAvatar = useContextSelector(ChatItemContext, (v) => v.chatBoxData?.app?.avatar);
|
const appAvatar = useContextSelector(ChatItemContext, (v) => v.chatBoxData?.app?.avatar);
|
||||||
const variablesForm = useContextSelector(ChatItemContext, (v) => v.variablesForm);
|
const variablesForm = useContextSelector(ChatItemContext, (v) => v.variablesForm);
|
||||||
const variableList = useContextSelector(ChatBoxContext, (v) => v.variableList);
|
const variableList = useContextSelector(ChatBoxContext, (v) => v.variableList);
|
||||||
|
const allVariableList = useContextSelector(ChatBoxContext, (v) => v.allVariableList);
|
||||||
|
|
||||||
|
const externalVariableList = useMemo(
|
||||||
|
() =>
|
||||||
|
allVariableList.filter((item) =>
|
||||||
|
showExternalVariables ? item.type === VariableInputEnum.custom : false
|
||||||
|
),
|
||||||
|
[allVariableList, showExternalVariables]
|
||||||
|
);
|
||||||
|
|
||||||
const { getValues, setValue, handleSubmit: handleSubmitChat } = variablesForm;
|
const { getValues, setValue, handleSubmit: handleSubmitChat } = variablesForm;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
variableList.forEach((item) => {
|
allVariableList.forEach((item) => {
|
||||||
const val = getValues(`variables.${item.key}`);
|
const val = getValues(`variables.${item.key}`);
|
||||||
if (item.defaultValue !== undefined && (val === undefined || val === null || val === '')) {
|
if (item.defaultValue !== undefined && (val === undefined || val === null || val === '')) {
|
||||||
setValue(`variables.${item.key}`, item.defaultValue);
|
setValue(`variables.${item.key}`, item.defaultValue);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [variableList]);
|
}, [allVariableList, getValues, setValue, variableList]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box py={3}>
|
<Box py={3}>
|
||||||
<ChatAvatar src={appAvatar} type={'AI'} />
|
<ChatAvatar src={appAvatar} type={'AI'} />
|
||||||
<Box textAlign={'left'}>
|
{externalVariableList.length > 0 && (
|
||||||
<Card
|
<Box textAlign={'left'}>
|
||||||
order={2}
|
<Card
|
||||||
mt={2}
|
order={2}
|
||||||
w={'400px'}
|
mt={2}
|
||||||
{...MessageCardStyle}
|
w={'400px'}
|
||||||
bg={'white'}
|
{...MessageCardStyle}
|
||||||
boxShadow={'0 0 8px rgba(0,0,0,0.15)'}
|
bg={'white'}
|
||||||
>
|
boxShadow={'0 0 8px rgba(0,0,0,0.15)'}
|
||||||
{variableList.map((item) => (
|
>
|
||||||
<VariableInputItem key={item.id} item={item} variablesForm={variablesForm} />
|
<Flex
|
||||||
))}
|
color={'primary.600'}
|
||||||
{!chatStarted && (
|
bg={'primary.100'}
|
||||||
<Box>
|
mb={3}
|
||||||
<Button
|
px={3}
|
||||||
leftIcon={<MyIcon name={'core/chat/chatFill'} w={'16px'} />}
|
py={1.5}
|
||||||
size={'sm'}
|
gap={1}
|
||||||
maxW={'100px'}
|
fontSize={'mini'}
|
||||||
onClick={handleSubmitChat(() => {
|
rounded={'sm'}
|
||||||
chatForm.setValue('chatStarted', true);
|
>
|
||||||
})}
|
<MyIcon name={'common/info'} color={'primary.600'} w={4} />
|
||||||
>
|
{t('chat:variable_invisable_in_share')}
|
||||||
{t('common:core.chat.Start Chat')}
|
</Flex>
|
||||||
</Button>
|
{externalVariableList.map((item) => (
|
||||||
</Box>
|
<ExternalVariableInputItem key={item.id} item={item} variablesForm={variablesForm} />
|
||||||
)}
|
))}
|
||||||
</Card>
|
{variableList.length === 0 && !chatStarted && (
|
||||||
</Box>
|
<Box>
|
||||||
|
<Button
|
||||||
|
leftIcon={<MyIcon name={'core/chat/chatFill'} w={'16px'} />}
|
||||||
|
size={'sm'}
|
||||||
|
maxW={'100px'}
|
||||||
|
onClick={handleSubmitChat(() => {
|
||||||
|
chatForm.setValue('chatStarted', true);
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{t('common:core.chat.Start Chat')}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{variableList.length > 0 && (
|
||||||
|
<Box textAlign={'left'}>
|
||||||
|
<Card
|
||||||
|
order={2}
|
||||||
|
mt={2}
|
||||||
|
w={'400px'}
|
||||||
|
{...MessageCardStyle}
|
||||||
|
bg={'white'}
|
||||||
|
boxShadow={'0 0 8px rgba(0,0,0,0.15)'}
|
||||||
|
>
|
||||||
|
{variableList.map((item) => (
|
||||||
|
<VariableInputItem key={item.id} item={item} variablesForm={variablesForm} />
|
||||||
|
))}
|
||||||
|
{!chatStarted && (
|
||||||
|
<Box>
|
||||||
|
<Button
|
||||||
|
leftIcon={<MyIcon name={'core/chat/chatFill'} w={'16px'} />}
|
||||||
|
size={'sm'}
|
||||||
|
maxW={'100px'}
|
||||||
|
onClick={handleSubmitChat(() => {
|
||||||
|
console.log('start chat');
|
||||||
|
chatForm.setValue('chatStarted', true);
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{t('common:core.chat.Start Chat')}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
import { Box, Button, Flex } from '@chakra-ui/react';
|
||||||
|
import MyPopover from '@fastgpt/web/components/common/MyPopover';
|
||||||
|
import { useTranslation } from 'next-i18next';
|
||||||
|
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||||
|
import { useContextSelector } from 'use-context-selector';
|
||||||
|
import { ChatItemContext } from '@/web/core/chat/context/chatItemContext';
|
||||||
|
import { VariableInputEnum } from '@fastgpt/global/core/workflow/constants';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { ExternalVariableInputItem, VariableInputItem } from './VariableInput';
|
||||||
|
import MyDivider from '@fastgpt/web/components/common/MyDivider';
|
||||||
|
|
||||||
|
const VariablePopover = ({
|
||||||
|
showExternalVariables = false
|
||||||
|
}: {
|
||||||
|
showExternalVariables?: boolean;
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const variablesForm = useContextSelector(ChatItemContext, (v) => v.variablesForm);
|
||||||
|
const variables = useContextSelector(
|
||||||
|
ChatItemContext,
|
||||||
|
(v) => v.chatBoxData?.app?.chatConfig?.variables ?? []
|
||||||
|
);
|
||||||
|
const variableList = variables.filter((item) => item.type !== VariableInputEnum.custom);
|
||||||
|
const externalVariableList = variables.filter((item) =>
|
||||||
|
showExternalVariables ? item.type === VariableInputEnum.custom : false
|
||||||
|
);
|
||||||
|
|
||||||
|
const hasExternalVariable = externalVariableList.length > 0;
|
||||||
|
const hasVariable = variableList.length > 0;
|
||||||
|
|
||||||
|
const { getValues, setValue } = variablesForm;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
variables.forEach((item) => {
|
||||||
|
const val = getValues(`variables.${item.key}`);
|
||||||
|
if (item.defaultValue !== undefined && (val === undefined || val === null || val === '')) {
|
||||||
|
setValue(`variables.${item.key}`, item.defaultValue);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [variables]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MyPopover
|
||||||
|
placement="bottom"
|
||||||
|
trigger={'click'}
|
||||||
|
closeOnBlur={true}
|
||||||
|
Trigger={
|
||||||
|
<Button variant={'whiteBase'} size={'sm'} leftIcon={<MyIcon name={'edit'} w={4} />}>
|
||||||
|
{t('common:core.module.Variable')}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{({ onClose }) => (
|
||||||
|
<Box p={4}>
|
||||||
|
{hasExternalVariable && (
|
||||||
|
<Box textAlign={'left'}>
|
||||||
|
<Flex
|
||||||
|
color={'primary.600'}
|
||||||
|
bg={'primary.100'}
|
||||||
|
mb={3}
|
||||||
|
px={3}
|
||||||
|
py={1.5}
|
||||||
|
gap={1}
|
||||||
|
fontSize={'mini'}
|
||||||
|
rounded={'sm'}
|
||||||
|
>
|
||||||
|
<MyIcon name={'common/info'} color={'primary.600'} w={4} />
|
||||||
|
{t('chat:variable_invisable_in_share')}
|
||||||
|
</Flex>
|
||||||
|
{externalVariableList.map((item) => (
|
||||||
|
<ExternalVariableInputItem
|
||||||
|
key={item.id}
|
||||||
|
item={item}
|
||||||
|
variablesForm={variablesForm}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
{hasExternalVariable && hasVariable && <MyDivider h={'1px'} />}
|
||||||
|
{hasVariable && (
|
||||||
|
<Box textAlign={'left'}>
|
||||||
|
{variableList.map((item) => (
|
||||||
|
<VariableInputItem key={item.id} item={item} variablesForm={variablesForm} />
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
<Flex w={'full'} justifyContent={'flex-end'}>
|
||||||
|
<Button size={'sm'} onClick={onClose}>
|
||||||
|
{t('common:common.Confirm')}
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</MyPopover>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default VariablePopover;
|
||||||
@@ -65,6 +65,7 @@ import { ChatRecordContext } from '@/web/core/chat/context/chatRecordContext';
|
|||||||
import { ChatItemContext } from '@/web/core/chat/context/chatItemContext';
|
import { ChatItemContext } from '@/web/core/chat/context/chatItemContext';
|
||||||
import TimeBox from './components/TimeBox';
|
import TimeBox from './components/TimeBox';
|
||||||
import MyBox from '@fastgpt/web/components/common/MyBox';
|
import MyBox from '@fastgpt/web/components/common/MyBox';
|
||||||
|
import { VariableInputEnum } from '@fastgpt/global/core/workflow/constants';
|
||||||
|
|
||||||
const ResponseTags = dynamic(() => import('./components/ResponseTags'));
|
const ResponseTags = dynamic(() => import('./components/ResponseTags'));
|
||||||
const FeedbackModal = dynamic(() => import('./components/FeedbackModal'));
|
const FeedbackModal = dynamic(() => import('./components/FeedbackModal'));
|
||||||
@@ -103,7 +104,8 @@ const ChatBox = ({
|
|||||||
showVoiceIcon = true,
|
showVoiceIcon = true,
|
||||||
showEmptyIntro = false,
|
showEmptyIntro = false,
|
||||||
active = true,
|
active = true,
|
||||||
onStartChat
|
onStartChat,
|
||||||
|
chatType
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const ScrollContainerRef = useRef<HTMLDivElement>(null);
|
const ScrollContainerRef = useRef<HTMLDivElement>(null);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -129,6 +131,8 @@ const ChatBox = ({
|
|||||||
const chatBoxData = useContextSelector(ChatItemContext, (v) => v.chatBoxData);
|
const chatBoxData = useContextSelector(ChatItemContext, (v) => v.chatBoxData);
|
||||||
const ChatBoxRef = useContextSelector(ChatItemContext, (v) => v.ChatBoxRef);
|
const ChatBoxRef = useContextSelector(ChatItemContext, (v) => v.ChatBoxRef);
|
||||||
const variablesForm = useContextSelector(ChatItemContext, (v) => v.variablesForm);
|
const variablesForm = useContextSelector(ChatItemContext, (v) => v.variablesForm);
|
||||||
|
const setIsVariableVisible = useContextSelector(ChatItemContext, (v) => v.setIsVariableVisible);
|
||||||
|
|
||||||
const chatRecords = useContextSelector(ChatRecordContext, (v) => v.chatRecords);
|
const chatRecords = useContextSelector(ChatRecordContext, (v) => v.chatRecords);
|
||||||
const setChatRecords = useContextSelector(ChatRecordContext, (v) => v.setChatRecords);
|
const setChatRecords = useContextSelector(ChatRecordContext, (v) => v.setChatRecords);
|
||||||
const isChatRecordsLoaded = useContextSelector(ChatRecordContext, (v) => v.isChatRecordsLoaded);
|
const isChatRecordsLoaded = useContextSelector(ChatRecordContext, (v) => v.isChatRecordsLoaded);
|
||||||
@@ -150,6 +154,12 @@ const ChatBox = ({
|
|||||||
// Workflow running, there are user input or selection
|
// Workflow running, there are user input or selection
|
||||||
const isInteractive = useMemo(() => checkIsInteractiveByHistories(chatRecords), [chatRecords]);
|
const isInteractive = useMemo(() => checkIsInteractiveByHistories(chatRecords), [chatRecords]);
|
||||||
|
|
||||||
|
const externalVariableList = useMemo(() => {
|
||||||
|
if (chatType === 'chat') {
|
||||||
|
return allVariableList.filter((item) => item.type === VariableInputEnum.custom);
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}, [allVariableList, chatType]);
|
||||||
// compute variable input is finish.
|
// compute variable input is finish.
|
||||||
const chatForm = useForm<ChatBoxInputFormType>({
|
const chatForm = useForm<ChatBoxInputFormType>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
@@ -162,7 +172,9 @@ const ChatBox = ({
|
|||||||
const chatStartedWatch = watch('chatStarted');
|
const chatStartedWatch = watch('chatStarted');
|
||||||
const chatStarted =
|
const chatStarted =
|
||||||
chatBoxData?.appId === appId &&
|
chatBoxData?.appId === appId &&
|
||||||
(chatStartedWatch || chatRecords.length > 0 || variableList.length === 0);
|
(chatStartedWatch ||
|
||||||
|
chatRecords.length > 0 ||
|
||||||
|
[...variableList, ...externalVariableList].length === 0);
|
||||||
|
|
||||||
// 滚动到底部
|
// 滚动到底部
|
||||||
const scrollToBottom = useMemoizedFn((behavior: 'smooth' | 'auto' = 'smooth', delay = 0) => {
|
const scrollToBottom = useMemoizedFn((behavior: 'smooth' | 'auto' = 'smooth', delay = 0) => {
|
||||||
@@ -891,6 +903,33 @@ const ChatBox = ({
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Visibility check
|
||||||
|
useEffect(() => {
|
||||||
|
const checkVariableVisibility = () => {
|
||||||
|
if (!ScrollContainerRef.current) return;
|
||||||
|
const container = ScrollContainerRef.current;
|
||||||
|
const variableInput = container.querySelector('#variable-input');
|
||||||
|
if (!variableInput) return;
|
||||||
|
|
||||||
|
const containerRect = container.getBoundingClientRect();
|
||||||
|
const elementRect = variableInput.getBoundingClientRect();
|
||||||
|
|
||||||
|
setIsVariableVisible(
|
||||||
|
elementRect.bottom > containerRect.top && elementRect.top < containerRect.bottom
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const container = ScrollContainerRef.current;
|
||||||
|
if (container) {
|
||||||
|
checkVariableVisibility();
|
||||||
|
container.addEventListener('scroll', checkVariableVisibility);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
container.removeEventListener('scroll', checkVariableVisibility);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, [chatType, setIsVariableVisible]);
|
||||||
|
|
||||||
const RenderRecords = useMemo(() => {
|
const RenderRecords = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
<ScrollData
|
<ScrollData
|
||||||
@@ -906,8 +945,14 @@ const ChatBox = ({
|
|||||||
{showEmpty && <Empty />}
|
{showEmpty && <Empty />}
|
||||||
{!!welcomeText && <WelcomeBox welcomeText={welcomeText} />}
|
{!!welcomeText && <WelcomeBox welcomeText={welcomeText} />}
|
||||||
{/* variable input */}
|
{/* variable input */}
|
||||||
{!!variableList?.length && (
|
{(!!variableList?.length || !!externalVariableList?.length) && (
|
||||||
<VariableInput chatStarted={chatStarted} chatForm={chatForm} />
|
<Box id="variable-input">
|
||||||
|
<VariableInput
|
||||||
|
chatStarted={chatStarted}
|
||||||
|
chatForm={chatForm}
|
||||||
|
showExternalVariables={chatType === 'chat'}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
)}
|
)}
|
||||||
{/* chat history */}
|
{/* chat history */}
|
||||||
<Box id={'history'}>
|
<Box id={'history'}>
|
||||||
@@ -1006,7 +1051,9 @@ const ChatBox = ({
|
|||||||
chatForm,
|
chatForm,
|
||||||
chatRecords,
|
chatRecords,
|
||||||
chatStarted,
|
chatStarted,
|
||||||
|
chatType,
|
||||||
delOneMessage,
|
delOneMessage,
|
||||||
|
externalVariableList?.length,
|
||||||
isChatting,
|
isChatting,
|
||||||
onAddUserDislike,
|
onAddUserDislike,
|
||||||
onAddUserLike,
|
onAddUserLike,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { ChatBoxInputFormType } from '../../ChatBox/type';
|
|||||||
import { FlowNodeInputItemType } from '@fastgpt/global/core/workflow/type/io';
|
import { FlowNodeInputItemType } from '@fastgpt/global/core/workflow/type/io';
|
||||||
import { ChatItemContext } from '@/web/core/chat/context/chatItemContext';
|
import { ChatItemContext } from '@/web/core/chat/context/chatItemContext';
|
||||||
import { ChatRecordContext } from '@/web/core/chat/context/chatRecordContext';
|
import { ChatRecordContext } from '@/web/core/chat/context/chatRecordContext';
|
||||||
|
import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
||||||
|
|
||||||
const RenderInput = () => {
|
const RenderInput = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -213,36 +214,43 @@ const RenderInput = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
{/* Filed */}
|
{/* Filed */}
|
||||||
{formatPluginInputs.map((input) => {
|
{formatPluginInputs
|
||||||
return (
|
.filter((input) => {
|
||||||
<Controller
|
if (outLinkAuthData && Object.keys(outLinkAuthData).length > 0) {
|
||||||
key={`variables.${input.key}`}
|
return input.renderTypeList[0] !== FlowNodeInputTypeEnum.customVariable;
|
||||||
control={control}
|
}
|
||||||
name={`variables.${input.key}`}
|
return true;
|
||||||
rules={{
|
})
|
||||||
validate: (value) => {
|
.map((input) => {
|
||||||
if (!input.required) return true;
|
return (
|
||||||
if (input.valueType === WorkflowIOValueTypeEnum.boolean) {
|
<Controller
|
||||||
return value !== undefined;
|
key={`variables.${input.key}`}
|
||||||
|
control={control}
|
||||||
|
name={`variables.${input.key}`}
|
||||||
|
rules={{
|
||||||
|
validate: (value) => {
|
||||||
|
if (!input.required) return true;
|
||||||
|
if (input.valueType === WorkflowIOValueTypeEnum.boolean) {
|
||||||
|
return value !== undefined;
|
||||||
|
}
|
||||||
|
return !!value;
|
||||||
}
|
}
|
||||||
return !!value;
|
}}
|
||||||
}
|
render={({ field: { onChange, value } }) => {
|
||||||
}}
|
return (
|
||||||
render={({ field: { onChange, value } }) => {
|
<RenderPluginInput
|
||||||
return (
|
value={value}
|
||||||
<RenderPluginInput
|
onChange={onChange}
|
||||||
value={value}
|
isDisabled={isDisabledInput}
|
||||||
onChange={onChange}
|
isInvalid={errors && Object.keys(errors).includes(input.key)}
|
||||||
isDisabled={isDisabledInput}
|
input={input}
|
||||||
isInvalid={errors && Object.keys(errors).includes(input.key)}
|
setUploading={setUploading}
|
||||||
input={input}
|
/>
|
||||||
setUploading={setUploading}
|
);
|
||||||
/>
|
}}
|
||||||
);
|
/>
|
||||||
}}
|
);
|
||||||
/>
|
})}
|
||||||
);
|
|
||||||
})}
|
|
||||||
{/* Run Button */}
|
{/* Run Button */}
|
||||||
{onStartChat && onNewChat && (
|
{onStartChat && onNewChat && (
|
||||||
<Flex justifyContent={'end'} mt={8}>
|
<Flex justifyContent={'end'} mt={8}>
|
||||||
|
|||||||
@@ -157,9 +157,6 @@ const RenderPluginInput = ({
|
|||||||
const { llmModelList } = useSystemStore();
|
const { llmModelList } = useSystemStore();
|
||||||
|
|
||||||
const render = (() => {
|
const render = (() => {
|
||||||
if (inputType === FlowNodeInputTypeEnum.customVariable) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (inputType === FlowNodeInputTypeEnum.select && input.list) {
|
if (inputType === FlowNodeInputTypeEnum.select && input.list) {
|
||||||
return (
|
return (
|
||||||
<MySelect list={input.list} value={value} onChange={onChange} isDisabled={isDisabled} />
|
<MySelect list={input.list} value={value} onChange={onChange} isDisabled={isDisabled} />
|
||||||
@@ -246,6 +243,21 @@ const RenderPluginInput = ({
|
|||||||
<FormLabel fontWeight={'500'}>{t(input.label as any)}</FormLabel>
|
<FormLabel fontWeight={'500'}>{t(input.label as any)}</FormLabel>
|
||||||
</Box>
|
</Box>
|
||||||
{input.description && <QuestionTip ml={2} label={t(input.description as any)} />}
|
{input.description && <QuestionTip ml={2} label={t(input.description as any)} />}
|
||||||
|
{inputType === FlowNodeInputTypeEnum.customVariable && (
|
||||||
|
<Flex
|
||||||
|
color={'primary.600'}
|
||||||
|
bg={'primary.100'}
|
||||||
|
px={2}
|
||||||
|
py={1}
|
||||||
|
gap={1}
|
||||||
|
ml={2}
|
||||||
|
fontSize={'mini'}
|
||||||
|
rounded={'sm'}
|
||||||
|
>
|
||||||
|
<MyIcon name={'common/info'} color={'primary.600'} w={4} />
|
||||||
|
{t('chat:variable_invisable_in_share')}
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -268,10 +268,10 @@ const RenderUserFormInteractive = React.memo(function RenderFormInput({
|
|||||||
{interactive.params.description && <Markdown source={interactive.params.description} />}
|
{interactive.params.description && <Markdown source={interactive.params.description} />}
|
||||||
{interactive.params.inputForm?.map((input) => (
|
{interactive.params.inputForm?.map((input) => (
|
||||||
<Box key={input.label}>
|
<Box key={input.label}>
|
||||||
<Flex mb={1} alignItems={'center'}>
|
<FormLabel mb={1} required={input.required} whiteSpace={'pre-wrap'}>
|
||||||
<FormLabel required={input.required}>{input.label}</FormLabel>
|
{input.label}
|
||||||
{input.description && <QuestionTip ml={1} label={input.description} />}
|
{input.description && <QuestionTip ml={1} label={input.description} />}
|
||||||
</Flex>
|
</FormLabel>
|
||||||
{input.type === FlowNodeInputTypeEnum.input && (
|
{input.type === FlowNodeInputTypeEnum.input && (
|
||||||
<MyTextarea
|
<MyTextarea
|
||||||
isDisabled={interactive.params.submitted}
|
isDisabled={interactive.params.submitted}
|
||||||
|
|||||||
@@ -250,22 +250,24 @@ export const WholeResponseContent = ({
|
|||||||
value={activeModule?.similarity}
|
value={activeModule?.similarity}
|
||||||
/>
|
/>
|
||||||
<Row label={t('common:core.chat.response.module limit')} value={activeModule?.limit} />
|
<Row label={t('common:core.chat.response.module limit')} value={activeModule?.limit} />
|
||||||
<Row
|
{activeModule?.searchUsingReRank !== undefined && (
|
||||||
label={t('common:core.chat.response.search using reRank')}
|
<Row
|
||||||
rawDom={
|
label={t('common:core.chat.response.search using reRank')}
|
||||||
<Box border={'base'} borderRadius={'md'} p={2}>
|
rawDom={
|
||||||
{activeModule?.searchUsingReRank ? (
|
<Box border={'base'} borderRadius={'md'} p={2}>
|
||||||
activeModule?.rerankModel ? (
|
{activeModule?.searchUsingReRank ? (
|
||||||
<Box>{`${activeModule.rerankModel}: ${activeModule.rerankWeight}`}</Box>
|
activeModule?.rerankModel ? (
|
||||||
|
<Box>{`${activeModule.rerankModel}: ${activeModule.rerankWeight}`}</Box>
|
||||||
|
) : (
|
||||||
|
'True'
|
||||||
|
)
|
||||||
) : (
|
) : (
|
||||||
'True'
|
`False`
|
||||||
)
|
)}
|
||||||
) : (
|
</Box>
|
||||||
`False`
|
}
|
||||||
)}
|
/>
|
||||||
</Box>
|
)}
|
||||||
}
|
|
||||||
/>
|
|
||||||
{activeModule.queryExtensionResult && (
|
{activeModule.queryExtensionResult && (
|
||||||
<>
|
<>
|
||||||
<Row
|
<Row
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ function EditKeyModal({
|
|||||||
<FormLabel flex={'0 0 90px'}>{t('common:Name')}</FormLabel>
|
<FormLabel flex={'0 0 90px'}>{t('common:Name')}</FormLabel>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('publish:key_alias') || 'key_alias'}
|
placeholder={t('publish:key_alias') || 'key_alias'}
|
||||||
maxLength={20}
|
maxLength={100}
|
||||||
{...register('name', {
|
{...register('name', {
|
||||||
required: t('common:common.name_is_empty') || 'name_is_empty'
|
required: t('common:common.name_is_empty') || 'name_is_empty'
|
||||||
})}
|
})}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user