Compare commits

...

13 Commits

Author SHA1 Message Date
Archer
5fa2e3c5ac fix: milvus sdk (#3249) 2024-11-27 10:06:12 +08:00
Archer
4723a08d98 fix: check reference (#3240) 2024-11-26 14:57:32 +08:00
Archer
3d9c1d5472 Update official_account.md (#3239) 2024-11-26 14:23:32 +08:00
Archer
a75036b626 fix: base64 image (#3238)
* fix: base64 image

* perf: quote qa
2024-11-26 13:28:51 +08:00
Archer
cf1a90c596 doc (#3237) 2024-11-26 13:00:54 +08:00
Archer
8aa6b53760 V4.8.14 dev (#3234)
* feat: rewrite chat context (#3176)

* feat: add app auto execute (#3115)

* feat: add app auto execute

* auto exec configtion

* chatting animation

* change icon

* fix

* fix

* fix link

* feat: add chat context to all chatbox

* perf: loading ui

---------

Co-authored-by: heheer <heheer@sealos.io>

* app auto exec (#3179)

* add chat records loaded state (#3184)

* perf: chat store reset storage (#3186)

* perf: chat store reset storage

* perf: auto exec code

* chore: workflow ui (#3175)

* chore: workflow ui

* fix

* change icon color config

* change popover to mymenu

* 4.8.14 test (#3189)

* update doc

* fix: token check

* perf: icon button

* update doc

* feat: share page support configuration Whether to allow the original view (#3194)

* update doc

* perf: fix index (#3206)

* perf: i18n

* perf: Add service entry (#3226)

* 4.8.14 test (#3228)

* fix: ai log

* fix: text splitter

* fix: reference unselect & user form description & simple to advance (#3229)

* fix: reference unselect & user form description & simple to advance

* change abort position

* perf

* perf: code (#3232)

* perf: code

* update doc

* fix: create btn permission (#3233)

* update doc

* fix: refresh chatbox listener

* perf: check invalid reference

* perf: check invalid reference

* update doc

* fix: ui props

---------

Co-authored-by: heheer <heheer@sealos.io>
2024-11-26 12:02:58 +08:00
Archer
7e1d31b5a9 Update intro.md (#3235) 2024-11-25 22:47:31 +08:00
Menghuan
bc79d46d4b 更新Doc2X插件:输出文本预处理改进 (#3199)
* Error text fix

* Add post-processing for table

* Some table can not convert

* Refactor table conversion logic in PDF2text plugin

* Fix table separator formatting issue

* Refactor table separator formatting in PDF2text plugin

* Refactor table conversion logic in PDF2text plugin and add HTMLtable option

* 修复本地部署时无法获取文件的问题

* Refactor PDF fetching and parsing logic

* Refactor PDF fetching and parsing logic, and fix table separator formatting issue

* Bug fix: HTMLtable control not work
2024-11-25 20:01:50 +08:00
Peter Dave Hello
dfd2fed033 Add zh_TW Traditional Chinese translation (#3220) 2024-11-25 10:04:08 +08:00
Archer
51559bc821 update deploy yml (#3224) 2024-11-25 00:00:45 +08:00
Chenglong.li
c7681342f7 Fix milvus description (#3216)
Signed-off-by: JackLCL <chenglong.li@zilliz.com>
2024-11-23 00:49:47 +08:00
Jiangween
0f4870a7a5 修复文档图片路径问题和更新用户选择示意图 (#3210)
* 修复 userSelect.svg 文件的问题

* 图片路径有误
2024-11-21 23:03:59 +08:00
heheer
763b41b385 simple app snapshot init (#3207)
* simple init

* change old past position
2024-11-21 17:38:30 +08:00
238 changed files with 6069 additions and 2917 deletions

View File

@@ -21,7 +21,7 @@ assignees: ''
- [ ] 公有云版本
- [ ] 私有部署版本, 具体版本号:
**问题描述, 日志截图**
**问题描述, 日志截图,配置文件等**
**复现步骤**

View File

@@ -16,8 +16,8 @@
"i18n-ally.keystyle": "flat",
"i18n-ally.sortKeys": true,
"i18n-ally.keepFulfilled": false,
"i18n-ally.sourceLanguage": "zh", // 根据此语言文件翻译其他语言文件的变量和内容
"i18n-ally.displayLanguage": "zh", // 显示语言
"i18n-ally.sourceLanguage": "zh-CN", // 根据此语言文件翻译其他语言文件的变量和内容
"i18n-ally.displayLanguage": "zh-CN", // 显示语言
"i18n-ally.namespace": true,
"i18n-ally.pathMatcher": "{locale}/{namespaces}.json",
"i18n-ally.extract.targetPickingStrategy": "most-similar-by-key",

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

View File

@@ -35,9 +35,7 @@ weight: 707
### Milvus版本
暂不推荐,部分系统存在精度丢失,等待修复
对于千万级以上向量性能更优秀。
生产部署首选,对于千万级以上向量性能更优秀
[点击查看 Milvus 官方推荐配置](https://milvus.io/docs/prerequisite-docker.md)
@@ -51,9 +49,7 @@ weight: 707
### zilliz cloud版本
暂不推荐,部分系统存在精度丢失,等待修复
亿级以上向量首选。
Milvus 的全托管服务,性能优于 Milvus 并提供 SLA点击使用 [Zilliz Cloud](https://zilliz.com.cn/)
由于向量库使用了 Cloud无需占用本地资源无需太关注。
@@ -138,14 +134,16 @@ curl -o docker-compose.yml https://raw.githubusercontent.com/labring/FastGPT/mai
# curl -o docker-compose.yml https://raw.githubusercontent.com/labring/FastGPT/main/files/docker/docker-compose-zilliz.yml
```
### 2. 修改 docker-compose.yml 环境变量
### 2. 修改环境变量
找到 yml 文件中fastgpt 容器的环境变量进行下面操作:
{{< tabs tabTotal="3" >}}
{{< tab tabName="PgVector版本" >}}
{{< markdownify >}}
```
无需操作
FE_DOMAIN=你的前端你访问地址,例如 http://192.168.0.1:3000;https://cloud.fastgpt.cn
```
{{< /markdownify >}}
@@ -154,7 +152,7 @@ curl -o docker-compose.yml https://raw.githubusercontent.com/labring/FastGPT/mai
{{< markdownify >}}
```
无需操作
FE_DOMAIN=你的前端你访问地址,例如 http://192.168.0.1:3000;https://cloud.fastgpt.cn
```
{{< /markdownify >}}
@@ -162,11 +160,14 @@ curl -o docker-compose.yml https://raw.githubusercontent.com/labring/FastGPT/mai
{{< tab tabName="Zilliz版本" >}}
{{< markdownify >}}
打开 [Zilliz Cloud](https://zilliz.com.cn/), 创建实例并获取相关秘钥。
![zilliz_key](/imgs/zilliz_key.png)
{{% alert icon="🤖" context="success" %}}
修改`MILVUS_ADDRESS``MILVUS_TOKEN`链接参数,分别对应 `zilliz``Public Endpoint``Api key`记得把自己ip加入白名单。
1. 修改`MILVUS_ADDRESS``MILVUS_TOKEN`链接参数,分别对应 `zilliz``Public Endpoint``Api key`记得把自己ip加入白名单。
2. 修改FE_DOMAIN=你的前端你访问地址,例如 http://192.168.0.1:3000;https://cloud.fastgpt.cn
{{% /alert %}}

View File

@@ -25,7 +25,7 @@ FastGPT 的 API Key **有 2 类**,一类是全局通用的 key (无法直接
| 通用key | 应用特定 key |
| --------------------- | --------------------- |
| ![](/imgs/fastgpt-api2.jpg) | ![](/imgs/fastgpt-api.jpg) |
| ![](/imgs/fastgpt-api2.jpg) | ![](/imgs/fastgpt-api1.jpg) |
## 基本配置

View File

@@ -31,17 +31,6 @@ curl --location --request POST 'http://localhost:3000/api/support/wallet/usage/c
}'
```
**x例子**
```bash
curl --location --request POST 'http://localhost:3000/api/support/wallet/bill/createTrainingBill' \
--header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "可选,自定义订单名称,例如:文档训练-fastgpt.docx"
}'
```
{{< /markdownify >}}
{{< /tab >}}

View File

@@ -1,5 +1,5 @@
---
title: 'V4.8.14(进行中)'
title: 'V4.8.14'
description: 'FastGPT V4.8.14 更新说明'
icon: 'upgrade'
draft: false
@@ -7,13 +7,46 @@ toc: true
weight: 810
---
## 更新预告
## 更新指南
1.
2. 新增 - 工作流支持进入聊天框/点击开始对话后,自动触发一轮对话。
3. 新增 - 重写 chatContext对话测试也会有日志并且刷新后不会丢失对话。
4. 新增 - 分享链接支持配置是否允许查看原文。
5. 优化 - 工作流 ui 细节。
6. 优化 - 应用编辑记录采用 diff 存储,避免浏览器溢出。
7. 修复 - 分块策略,四级标题会被丢失。 同时新增了五级标题的支持。
8. 修复 - MongoDB 知识库集合唯一索引。
### 1. 做好数据备份
### 2. 修改镜像
- 更新 FastGPT 镜像 tag: v4.8.14
- 更新 FastGPT 商业版镜像 tag: v4.8.14 fastgpt-pro镜像
- Sandbox 镜像,可以不更新
## 新功能预览
### 自动触发工作流
可以允许你配置用户加载对话时,自动触发一次工作流。可以用于一些 CRM 系统,可以快速的引导用户使用,无需等待用户主动触发。
| | |
| --- | --- |
| ![alt text](/imgs/image-8.png) | ![alt text](/imgs/image-9.png) |
## 完整更新内容
1. 新增 - 工作流支持进入聊天框/点击开始对话后,自动触发一轮对话。
2. 新增 - 重写 chatContext对话测试也会有日志并且刷新后不会丢失对话。
3. 新增 - 分享链接支持配置是否允许查看原文。
4. 新增 - 新的 doc2x 插件。
5. 新增 - 繁体中文-台湾。
6. 新增 - 分析链接和 chat api 支持传入自定义 uid。
7. 商业版新增 - 微软 oauth 登录
8. 优化 - 工作流 ui 细节。
9. 优化 - 应用编辑记录采用 diff 存储,避免浏览器溢出。
10. 优化 - 代码入口,增加 register 入口,无需等待首次访问才执行。
11. 优化 - 工作流检查,增加更多缺失值检查。
12. 优化 - 增加知识库训练最大重试次数限制。
13. 优化 - 图片路径问题和示意图任务
14. 优化 - Milvus description
15. 修复 - 分块策略,四级标题会被丢失。 同时新增了五级标题的支持。
16. 修复 - MongoDB 知识库集合唯一索引。
17. 修复 - 反选知识库引用后可能会报错。
18. 修复 - 简易模式转工作流,不是使用最新编辑记录进行转移。
19. 修复 - 表单输入的说明文字不显示。
20. 修复 - API 无法使用 base64 图片。

View File

@@ -85,16 +85,15 @@ FastGPT 商业版软件根据不同的部署方式,分为 3 类收费模式。
## QA
1. 如何交付?
### 如何交付?
完整版应用 = 开源版镜像 + 商业版镜像
我们会提供一个商业版镜像给你使用,该镜像需要一个 License 启动。
2. 二次开发如何操作?
可自行修改开源版代码进行二次开发,不支持修改商业版镜像。
### 二次开发如何操作?
可以修改开源版部分代码,不支持修改商业版镜像。完整版本=开源版+商业版镜像,所以是可以修改部分内容的。但是如果二开了,后续则需要自己进行代码合并升级。
## Sealos 费用

View File

@@ -78,6 +78,14 @@ weight: 506
121.196.235.183
121.41.75.88
121.43.108.48
112.124.12.6
121.43.52.222
121.199.162.43
121.199.162.102
120.55.94.163
47.99.59.223
112.124.46.5
121.40.46.247
```
## 4. 获取AES Key选择加密方式

View File

@@ -114,15 +114,15 @@ services:
# fastgpt
sandbox:
container_name: sandbox
image: ghcr.io/labring/fastgpt-sandbox:v4.8.11 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.11 # 阿里云
image: ghcr.io/labring/fastgpt-sandbox:v4.8.13-fix # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.13-fix # 阿里云
networks:
- fastgpt
restart: always
fastgpt:
container_name: fastgpt
image: ghcr.io/labring/fastgpt:v4.8.11 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.11 # 阿里云
image: ghcr.io/labring/fastgpt:v4.8.13-fix # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.13-fix # 阿里云
ports:
- 3000:3000
networks:
@@ -133,6 +133,8 @@ services:
- sandbox
restart: always
environment:
# 前端访问地址: http://localhost:3000
- FE_DOMAIN=
# root 密码,用户名为: root。如果需要修改 root 密码,直接修改这个环境变量,并重启即可。
- DEFAULT_ROOT_PSW=1234
# AI模型的API地址哦。务必加 /v1。这里默认填写了OneApi的访问地址。
@@ -154,8 +156,6 @@ services:
- MILVUS_TOKEN=none
# sandbox 地址
- SANDBOX_URL=http://sandbox:3000
# 前端地址: http://localhost:3000
- FE_DOMAIN=
# 日志等级: debug, info, warn, error
- LOG_LEVEL=info
- STORE_LOG_LEVEL=warn

View File

@@ -72,15 +72,15 @@ services:
# fastgpt
sandbox:
container_name: sandbox
image: ghcr.io/labring/fastgpt-sandbox:v4.8.11 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.11 # 阿里云
image: ghcr.io/labring/fastgpt-sandbox:v4.8.13 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.13 # 阿里云
networks:
- fastgpt
restart: always
fastgpt:
container_name: fastgpt
image: ghcr.io/labring/fastgpt:v4.8.11 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.11 # 阿里云
image: ghcr.io/labring/fastgpt:v4.8.14 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.14 # 阿里云
ports:
- 3000:3000
networks:
@@ -91,6 +91,8 @@ services:
- sandbox
restart: always
environment:
# 前端访问地址: http://localhost:3000
- FE_DOMAIN=
# root 密码,用户名为: root。如果需要修改 root 密码,直接修改这个环境变量,并重启即可。
- DEFAULT_ROOT_PSW=1234
# AI模型的API地址哦。务必加 /v1。这里默认填写了OneApi的访问地址。
@@ -111,8 +113,6 @@ services:
- PG_URL=postgresql://username:password@pg:5432/postgres
# sandbox 地址
- SANDBOX_URL=http://sandbox:3000
# 前端地址: http://localhost:3000
- FE_DOMAIN=
# 日志等级: debug, info, warn, error
- LOG_LEVEL=info
- STORE_LOG_LEVEL=warn

View File

@@ -53,15 +53,15 @@ services:
wait $$!
sandbox:
container_name: sandbox
image: ghcr.io/labring/fastgpt-sandbox:v4.8.11 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.11 # 阿里云
image: ghcr.io/labring/fastgpt-sandbox:v4.8.13-fix # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.13-fix # 阿里云
networks:
- fastgpt
restart: always
fastgpt:
container_name: fastgpt
image: ghcr.io/labring/fastgpt:v4.8.11 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.11 # 阿里云
image: ghcr.io/labring/fastgpt:v4.8.13-fix # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.13-fix # 阿里云
ports:
- 3000:3000
networks:
@@ -71,6 +71,8 @@ services:
- sandbox
restart: always
environment:
# 前端访问地址: http://localhost:3000
- FE_DOMAIN=
# root 密码,用户名为: root。如果需要修改 root 密码,直接修改这个环境变量,并重启即可。
- DEFAULT_ROOT_PSW=1234
# AI模型的API地址哦。务必加 /v1。这里默认填写了OneApi的访问地址。
@@ -92,8 +94,6 @@ services:
- MILVUS_TOKEN=zilliz_cloud_token
# sandbox 地址
- SANDBOX_URL=http://sandbox:3000
# 前端地址: http://localhost:3000
- FE_DOMAIN=
# 日志等级: debug, info, warn, error
- LOG_LEVEL=info
- STORE_LOG_LEVEL=warn

View File

@@ -12,5 +12,7 @@ export const fileImgs = [
];
export function getFileIcon(name = '', defaultImg = 'file/fill/file') {
return fileImgs.find((item) => new RegExp(item.suffix, 'gi').test(name))?.src || defaultImg;
return (
fileImgs.find((item) => new RegExp(`\.${item.suffix}`, 'gi').test(name))?.src || defaultImg
);
}

View File

@@ -23,6 +23,11 @@ export const parseUrlToFileType = (url: string): UserChatItemValueItemType['file
const parseUrl = new URL(url, 'https://locaohost:3000');
const filename = (() => {
// Check base64 image
if (url.startsWith('data:image/')) {
const mime = url.split(',')[0].split(':')[1].split(';')[0];
return `image.${mime.split('/')[1]}`;
}
// Old version file url: https://xxx.com/file/read?filename=xxx.pdf
const filenameQuery = parseUrl.searchParams.get('filename');
if (filenameQuery) return filenameQuery;

View File

@@ -3,6 +3,7 @@ import { BucketNameEnum } from './constants';
export type FileTokenQuery = {
bucketName: `${BucketNameEnum}`;
teamId: string;
tmbId: string;
uid: string; // tmbId/ share uid/ teamChat uid
fileId: string;
customExpireMinutes?: number;
};

View File

@@ -140,9 +140,10 @@ const commonSplit = (props: SplitProps): SplitResponse => {
const customRegLen = customReg.length;
const checkIsCustomStep = (step: number) => step < customRegLen;
const checkIsMarkdownSplit = (step: number) => step >= customRegLen && step <= markdownIndex;
const checkIsMarkdownSplit = (step: number) =>
step >= customRegLen && step <= markdownIndex + customRegLen;
+customReg.length;
const checkForbidOverlap = (step: number) => step <= forbidOverlapIndex + customReg.length;
const checkForbidOverlap = (step: number) => step <= forbidOverlapIndex + customRegLen;
// if use markdown title split, Separate record title
const getSplitTexts = ({ text, step }: { text: string; step: number }) => {

View File

@@ -49,6 +49,7 @@ export type ChatCompletionMessageParam = (
| CustomChatCompletionAssistantMessageParam
) & {
dataId?: string;
hideInUI?: boolean;
};
export type SdkChatCompletionMessageParam = SdkChatCompletionMessageParam;

View File

@@ -1,4 +1,9 @@
import { AppTTSConfigType, AppFileSelectConfigType, AppWhisperConfigType } from './type';
import {
AppTTSConfigType,
AppFileSelectConfigType,
AppWhisperConfigType,
AppAutoExecuteConfigType
} from './type';
export enum AppTypeEnum {
folder = 'folder',
@@ -12,6 +17,11 @@ export const AppFolderTypeList = [AppTypeEnum.folder, AppTypeEnum.httpPlugin];
export const defaultTTSConfig: AppTTSConfigType = { type: 'web' };
export const defaultAutoExecuteConfig: AppAutoExecuteConfigType = {
open: false,
defaultPrompt: ''
};
export const defaultWhisperConfig: AppWhisperConfigType = {
open: false,
autoSend: false,

View File

@@ -96,6 +96,7 @@ export type AppSimpleEditFormType = {
export type AppChatConfigType = {
welcomeText?: string;
variables?: VariableItemType[];
autoExecute?: AppAutoExecuteConfigType;
questionGuide?: boolean;
ttsConfig?: AppTTSConfigType;
whisperConfig?: AppWhisperConfigType;
@@ -158,6 +159,11 @@ export type AppScheduledTriggerConfigType = {
timezone: string;
defaultPrompt: string;
};
// auto execute
export type AppAutoExecuteConfigType = {
open: boolean;
defaultPrompt: string;
};
// File
export type AppFileSelectConfigType = {
canSelectFile: boolean;

View File

@@ -76,6 +76,7 @@ export const chats2GPTMessages = ({
results.push({
dataId,
hideInUI: item.hideInUI,
role: ChatCompletionRequestMessageRoleEnum.User,
content: simpleUserContentPart(value)
});
@@ -318,6 +319,7 @@ export const GPTMessages2Chats = (
return {
dataId: item.dataId,
obj,
hideInUI: item.hideInUI,
value
} as ChatItemType;
})

View File

@@ -56,6 +56,7 @@ export type UserChatItemValueItemType = {
export type UserChatItemType = {
obj: ChatRoleEnum.Human;
value: UserChatItemValueItemType[];
hideInUI?: boolean;
};
export type SystemChatItemValueItemType = {
type: ChatItemValueTypeEnum.text;

View File

@@ -101,7 +101,7 @@ export const filterPublicNodeResponseData = ({
for (let key in item) {
if (key === 'toolDetail' || key === 'pluginDetail') {
// @ts-ignore
obj[key] = filterPublicNodeResponseData({ flowResponses: item[key] });
obj[key] = filterPublicNodeResponseData({ flowResponses: item[key], responseDetail });
} else if (filedList.includes(key)) {
// @ts-ignore
obj[key] = item[key];

View File

@@ -204,7 +204,8 @@ export type DatasetFileSchema = {
contentType: string;
metadata: {
teamId: string;
tmbId: string;
tmbId?: string;
uid: string;
encoding?: string;
};
};

View File

@@ -106,6 +106,7 @@ export enum NodeInputKeyEnum {
variables = 'variables',
scheduleTrigger = 'scheduleTrigger',
chatInputGuide = 'chatInputGuide',
autoExecute = 'autoExecute',
// plugin config
instruction = 'instruction',

View File

@@ -25,10 +25,12 @@ import type {
AppWhisperConfigType,
AppScheduledTriggerConfigType,
ChatInputGuideConfigType,
AppChatConfigType
AppChatConfigType,
AppAutoExecuteConfigType
} from '../app/type';
import { EditorVariablePickerType } from '../../../web/components/common/Textarea/PromptEditor/type';
import {
defaultAutoExecuteConfig,
defaultChatInputGuideConfig,
defaultTTSConfig,
defaultWhisperConfig
@@ -69,34 +71,37 @@ export const getGuideModule = (modules: StoreNodeItemType[]) =>
);
export const splitGuideModule = (guideModules?: StoreNodeItemType) => {
const welcomeText: string =
guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.welcomeText)?.value || '';
guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.welcomeText)?.value ?? '';
const variables: VariableItemType[] =
guideModules?.inputs.find((item) => item.key === NodeInputKeyEnum.variables)?.value || [];
guideModules?.inputs.find((item) => item.key === NodeInputKeyEnum.variables)?.value ?? [];
const questionGuide: boolean =
!!guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.questionGuide)?.value ||
!!guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.questionGuide)?.value ??
false;
const ttsConfig: AppTTSConfigType =
guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.tts)?.value ||
guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.tts)?.value ??
defaultTTSConfig;
const whisperConfig: AppWhisperConfigType =
guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.whisper)?.value ||
guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.whisper)?.value ??
defaultWhisperConfig;
const scheduledTriggerConfig: AppScheduledTriggerConfigType = guideModules?.inputs?.find(
(item) => item.key === NodeInputKeyEnum.scheduleTrigger
)?.value;
const scheduledTriggerConfig: AppScheduledTriggerConfigType =
guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.scheduleTrigger)?.value ??
undefined;
const chatInputGuide: ChatInputGuideConfigType =
guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.chatInputGuide)?.value ||
guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.chatInputGuide)?.value ??
defaultChatInputGuideConfig;
// plugin
const instruction: string =
guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.instruction)?.value || '';
guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.instruction)?.value ?? '';
const autoExecute: AppAutoExecuteConfigType =
guideModules?.inputs?.find((item) => item.key === NodeInputKeyEnum.autoExecute)?.value ??
defaultAutoExecuteConfig;
return {
welcomeText,
@@ -106,7 +111,8 @@ export const splitGuideModule = (guideModules?: StoreNodeItemType) => {
whisperConfig,
scheduledTriggerConfig,
chatInputGuide,
instruction
instruction,
autoExecute
};
};
@@ -132,7 +138,8 @@ export const getAppChatConfig = ({
whisperConfig,
scheduledTriggerConfig,
chatInputGuide,
instruction
instruction,
autoExecute
} = splitGuideModule(systemConfigNode);
const config: AppChatConfigType = {
@@ -142,6 +149,7 @@ export const getAppChatConfig = ({
scheduledTriggerConfig,
chatInputGuide,
instruction,
autoExecute,
...chatConfig,
variables: storeVariables ?? chatConfig?.variables ?? variables,
welcomeText: storeWelcomeText ?? chatConfig?.welcomeText ?? welcomeText

View File

@@ -4,6 +4,7 @@ import { getErrText } from '@fastgpt/global/common/error/utils';
type Props = {
apikey: string;
HTMLtable: boolean;
files: string[];
};
@@ -14,7 +15,88 @@ type Response = Promise<{
error?: Record<string, any>;
}>;
const main = async ({ apikey, files }: Props): Response => {
function processContent(content: string, HTMLtable: boolean): string {
if (HTMLtable) {
return content;
}
return content.replace(/<table>[\s\S]*?<\/table>/g, (htmlTable) => {
try {
// Clean up whitespace and newlines
const cleanHtml = htmlTable.replace(/\n\s*/g, '');
const rows = cleanHtml.match(/<tr>(.*?)<\/tr>/g);
if (!rows) return htmlTable;
// Parse table data
let tableData: string[][] = [];
let maxColumns = 0;
// Try to convert to markdown table
try {
rows.forEach((row, rowIndex) => {
if (!tableData[rowIndex]) {
tableData[rowIndex] = [];
}
let colIndex = 0;
const cells = row.match(/<td.*?>(.*?)<\/td>/g) || [];
cells.forEach((cell) => {
while (tableData[rowIndex][colIndex]) {
colIndex++;
}
const colspan = parseInt(cell.match(/colspan="(\d+)"/)?.[1] || '1');
const rowspan = parseInt(cell.match(/rowspan="(\d+)"/)?.[1] || '1');
const content = cell.replace(/<td.*?>|<\/td>/g, '').trim();
for (let i = 0; i < rowspan; i++) {
for (let j = 0; j < colspan; j++) {
if (!tableData[rowIndex + i]) {
tableData[rowIndex + i] = [];
}
tableData[rowIndex + i][colIndex + j] = i === 0 && j === 0 ? content : '^^';
}
}
colIndex += colspan;
maxColumns = Math.max(maxColumns, colIndex);
});
for (let i = 0; i < maxColumns; i++) {
if (!tableData[rowIndex][i]) {
tableData[rowIndex][i] = ' ';
}
}
});
const chunks: string[] = [];
const headerCells = tableData[0]
.slice(0, maxColumns)
.map((cell) => (cell === '^^' ? ' ' : cell || ' '));
const headerRow = '| ' + headerCells.join(' | ') + ' |';
chunks.push(headerRow);
const separator = '| ' + Array(headerCells.length).fill('---').join(' | ') + ' |';
chunks.push(separator);
tableData.slice(1).forEach((row) => {
const paddedRow = row
.slice(0, maxColumns)
.map((cell) => (cell === '^^' ? ' ' : cell || ' '));
while (paddedRow.length < maxColumns) {
paddedRow.push(' ');
}
chunks.push('| ' + paddedRow.join(' | ') + ' |');
});
return chunks.join('\n');
} catch (error) {
return htmlTable;
}
} catch (error) {
return htmlTable;
}
});
}
const main = async ({ apikey, files, HTMLtable }: Props): Response => {
// Check the apikey
if (!apikey) {
return Promise.reject(`API key is required`);
@@ -30,77 +112,88 @@ const main = async ({ apikey, files }: Props): Response => {
for await (const url of files) {
try {
//Fetch the pdf and check its content type
const PDFResponse = await axiosInstance.get(url, { responseType: 'arraybuffer' });
const PDFResponse = await axios
.get(url, {
responseType: 'arraybuffer',
proxy: false,
timeout: 20000
})
.catch((error) => {
throw new Error(`[Fetch PDF Error] Failed to fetch PDF: ${getErrText(error)}`);
});
if (PDFResponse.status !== 200) {
throw new Error(
`File:${url} \n<Content>\nFailed to fetch PDF from URL: ${PDFResponse.statusText}\n</Content>`
`[Fetch PDF Error] Failed with status ${PDFResponse.status}: ${PDFResponse.data}`
);
}
const contentType = PDFResponse.headers['content-type'];
const file_name = url.match(/read\/([^?]+)/)?.[1] || 'unknown.pdf';
if (!contentType || !contentType.startsWith('application/pdf')) {
throw new Error(
`File:${file_name}\n<Content>\nThe provided file does not point to a PDF: ${contentType}\n</Content>`
);
throw new Error(`The provided file does not point to a PDF: ${contentType}`);
}
const blob = new Blob([PDFResponse.data], { type: 'application/pdf' });
// Get pre-upload URL first
const preupload_response = await axiosInstance.post(
'https://v2.doc2x.noedgeai.com/api/v2/parse/preupload',
null,
{
const preupload_response = await axiosInstance
.post('https://v2.doc2x.noedgeai.com/api/v2/parse/preupload', null, {
headers: {
Authorization: `Bearer ${apikey}`
}
}
);
})
.catch((error) => {
throw new Error(`[Pre-upload Error] Failed to get pre-upload URL: ${getErrText(error)}`);
});
if (preupload_response.status !== 200) {
throw new Error(
`File:${file_name}\n<Content>\nFailed to get pre-upload URL: ${preupload_response.statusText}\n</Content>`
);
throw new Error(`Failed to get pre-upload URL: ${preupload_response.data}`);
}
const preupload_data = preupload_response.data;
if (preupload_data.code !== 'success') {
throw new Error(
`File:${file_name}\n<Content>\nFailed to get pre-upload URL: ${JSON.stringify(preupload_data)}\n</Content>`
);
throw new Error(`Failed to get pre-upload URL: ${JSON.stringify(preupload_data)}`);
}
const upload_url = preupload_data.data.url;
const uid = preupload_data.data.uid;
// Upload file to pre-signed URL with binary stream
const response = await axiosInstance.put(upload_url, blob, {
headers: {
'Content-Type': 'application/pdf'
}
});
const response = await axiosInstance
.put(upload_url, blob, {
headers: {
'Content-Type': 'application/pdf'
}
})
.catch((error) => {
throw new Error(`[Upload Error] Failed to upload file: ${getErrText(error)}`);
});
if (response.status !== 200) {
throw new Error(`Upload failed with status ${response.status}: ${response.statusText}`);
}
// Get the result by uid
// Wait for the result, at most 90s
const checkResult = async (retry = 30) => {
// Wait for the result
const checkResult = async (retry = 20) => {
if (retry <= 0)
return Promise.reject(
`File:${file_name}\n<Content>\nFailed to get result (uid: ${uid}): Get result timeout\n</Content>`
`File:${file_name}\n<Content>\n[Parse Timeout Error] Failed to get result (uid: ${uid}): Process timeout\n</Content>`
);
try {
const result_response = await axiosInstance.get(
`https://v2.doc2x.noedgeai.com/api/v2/parse/status?uid=${uid}`,
{
const result_response = await axiosInstance
.get(`https://v2.doc2x.noedgeai.com/api/v2/parse/status?uid=${uid}`, {
headers: {
Authorization: `Bearer ${apikey}`
}
}
);
})
.catch((error) => {
throw new Error(
`[Parse Status Error] Failed to get parse status: ${getErrText(error)}`
);
});
const result_data = result_response.data;
if (!['ok', 'success'].includes(result_data.code)) {
@@ -110,29 +203,35 @@ const main = async ({ apikey, files }: Props): Response => {
}
if (['ready', 'processing'].includes(result_data.data.status)) {
await delay(3000);
await delay(4000);
return checkResult(retry - 1);
}
if (result_data.data.status === 'success') {
const result = (
const result = processContent(
await Promise.all(
result_data.data.result.pages.map((page: { md: any }) => page.md)
).then((pages) => pages.join('\n'))
).then((pages) => pages.join('\n')),
HTMLtable
)
// Do some post-processing
.replace(/\\[\(\)]/g, '$')
.replace(/\\[\[\]]/g, '$$')
.replace(/<img\s+src="([^"]+)"(?:\s*\?[^>]*)?(?:\s*\/>|>)/g, '![img]($1)');
.replace(/<img\s+src="([^"]+)"(?:\s*\?[^>]*)?(?:\s*\/>|>)/g, '![img]($1)')
.replace(/<!-- Media -->/g, '')
.replace(/<!-- Footnote -->/g, '')
.replace(/\$(.+?)\s+\\tag\{(.+?)\}\$/g, '$$$1 \\qquad \\qquad ($2)$$')
.replace(/\\text\{([^}]*?)(\b\w+)_(\w+\b)([^}]*?)\}/g, '\\text{$1$2\\_$3$4}');
return `File:${file_name}\n<Content>\n${result}\n</Content>`;
}
await delay(100);
return checkResult(retry - 1);
} catch (error) {
await delay(100);
return checkResult(retry - 1);
if (retry > 1) {
await delay(100);
return checkResult(retry - 1);
}
throw error;
}
};
@@ -140,7 +239,7 @@ const main = async ({ apikey, files }: Props): Response => {
successResult.push(result);
} catch (error) {
failedResult.push(
`File:${url} \n<Content>\nFailed to fetch image from URL: ${getErrText(error)}\n</Content>`
`File:${url} \n<Content>\nFailed to fetch file from URL: ${getErrText(error)}\n</Content>`
);
}
}

View File

@@ -7,10 +7,8 @@
"courseUrl": "https://fael3z0zfze.feishu.cn/wiki/Rkc5witXWiJoi5kORd2cofh6nDg?fromScene=spaceOverview",
"showStatus": true,
"weight": 10,
"isTool": true,
"templateType": "tools",
"workflow": {
"nodes": [
{
@@ -52,6 +50,26 @@
"canSelectImg": false,
"maxFiles": 14,
"defaultValue": ""
},
{
"renderTypeList": ["switch", "reference"],
"selectedTypeIndex": 0,
"valueType": "boolean",
"canEdit": true,
"key": "HTMLtable",
"label": "HTMLtable",
"description": "是否以HTML格式输出表格。如果需要精确地输出表格请打开此开关以使用HTML格式。关闭后表格将转换为Markdown形式输出但这可能会损失一些表格特性如合并单元格。",
"defaultValue": false,
"list": [
{
"label": "",
"value": ""
}
],
"maxFiles": 5,
"canSelectFile": true,
"canSelectImg": true,
"required": true
}
],
"outputs": [
@@ -68,6 +86,13 @@
"key": "files",
"label": "files",
"type": "hidden"
},
{
"id": "htmltable",
"valueType": "boolean",
"key": "HTMLtable",
"label": "HTMLtable",
"type": "hidden"
}
]
},
@@ -220,7 +245,7 @@
"key": "system_httpJsonBody",
"renderTypeList": ["hidden"],
"valueType": "any",
"value": "{\n \"apikey\": \"{{apikey}}\",\n \"files\": {{files}}\n}",
"value": "{\n \"apikey\": \"{{apikey}}\",\n \"HTMLtable\": {{HTMLtable}},\n \"files\": {{files}}\n}",
"label": "",
"required": false,
"debugLabel": "",
@@ -305,6 +330,36 @@
},
"required": true,
"value": [["pluginInput", "url"]]
},
{
"renderTypeList": ["reference"],
"valueType": "boolean",
"canEdit": true,
"key": "HTMLtable",
"label": "HTMLtable",
"customInputConfig": {
"selectValueTypeList": [
"string",
"number",
"boolean",
"object",
"arrayString",
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
"dynamic",
"selectApp",
"selectDataset"
],
"showDescription": false,
"showDefaultValue": true
},
"required": true,
"value": ["pluginInput", "htmltable"]
}
],
"outputs": [

View File

@@ -32,7 +32,7 @@ export function getGridBucket(bucket: `${BucketNameEnum}`) {
export async function uploadFile({
bucketName,
teamId,
tmbId,
uid,
path,
filename,
contentType,
@@ -41,7 +41,7 @@ export async function uploadFile({
}: {
bucketName: `${BucketNameEnum}`;
teamId: string;
tmbId: string;
uid: string; // tmbId / outLinkUId
path: string;
filename: string;
contentType?: string;
@@ -58,7 +58,7 @@ export async function uploadFile({
// Add default metadata
metadata.teamId = teamId;
metadata.tmbId = tmbId;
metadata.uid = uid;
metadata.encoding = encoding;
// create a gridfs bucket

View File

@@ -4,7 +4,7 @@ import path from 'path';
import { BucketNameEnum, bucketNameMap } from '@fastgpt/global/common/file/constants';
import { getNanoid } from '@fastgpt/global/common/string/tools';
type FileType = {
export type FileType = {
fieldname: string;
originalname: string;
encoding: string;
@@ -41,7 +41,7 @@ export const getUploadModel = ({ maxSize = 500 }: { maxSize?: number }) => {
})
}).single('file');
async doUpload<T = Record<string, any>>(
async doUpload<T = any>(
req: NextApiRequest,
res: NextApiResponse,
originBucketName?: `${BucketNameEnum}`

View File

@@ -6,6 +6,7 @@ import {
} from '@fastgpt/global/core/ai/type';
import { getErrText } from '@fastgpt/global/common/error/utils';
import { addLog } from '../../common/system/log';
import { i18nT } from '../../../web/i18n/utils';
export const openaiBaseUrl = process.env.OPENAI_BASE_URL || 'https://api.openai.com/v1';
@@ -62,6 +63,7 @@ export const createChatCompletion = async <T extends CompletionsBodyType>({
}): Promise<{
response: InferResponseType<T>;
isStreamResponse: boolean;
getEmptyResponseTip: () => string;
}> => {
try {
const formatTimeout = timeout ? timeout : body.stream ? 60000 : 600000;
@@ -76,9 +78,21 @@ export const createChatCompletion = async <T extends CompletionsBodyType>({
response !== null &&
('iterator' in response || 'controller' in response);
const getEmptyResponseTip = () => {
addLog.warn(`LLM response empty`, {
baseUrl: userKey?.baseUrl,
requestBody: body
});
if (userKey?.baseUrl) {
return `您的 OpenAI key 没有响应: ${JSON.stringify(body)}`;
}
return i18nT('chat:LLM_model_response_empty');
};
return {
response: response as InferResponseType<T>,
isStreamResponse
isStreamResponse,
getEmptyResponseTip
};
} catch (error) {
addLog.error(`LLM response error`, error);

View File

@@ -17,7 +17,8 @@ export const chatConfigType = {
scheduledTriggerConfig: Object,
chatInputGuide: Object,
fileSelectConfig: Object,
instruction: String
instruction: String,
autoExecute: Object
};
// schema

View File

@@ -46,6 +46,10 @@ const ChatItemSchema = new Schema({
type: Date,
default: () => new Date()
},
hideInUI: {
type: Boolean,
default: false
},
obj: {
// chat role
type: String,

View File

@@ -1,15 +1,6 @@
import type {
AIChatItemType,
ChatItemType,
UserChatItemType
} from '@fastgpt/global/core/chat/type.d';
import axios from 'axios';
import type { AIChatItemType, UserChatItemType } from '@fastgpt/global/core/chat/type.d';
import { MongoApp } from '../app/schema';
import {
ChatItemValueTypeEnum,
ChatRoleEnum,
ChatSourceEnum
} from '@fastgpt/global/core/chat/constants';
import { ChatItemValueTypeEnum, ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
import { MongoChatItem } from './chatItemSchema';
import { MongoChat } from './chatSchema';
import { addLog } from '../../common/system/log';
@@ -133,21 +124,15 @@ export async function saveChat({
export const updateInteractiveChat = async ({
chatId,
appId,
teamId,
tmbId,
userInteractiveVal,
aiResponse,
newVariables,
newTitle
newVariables
}: {
chatId: string;
appId: string;
teamId: string;
tmbId: string;
userInteractiveVal: string;
aiResponse: AIChatItemType & { dataId?: string };
newVariables?: Record<string, any>;
newTitle: string;
}) => {
if (!chatId) return;
@@ -232,7 +217,6 @@ export const updateInteractiveChat = async ({
{
$set: {
variables: newVariables,
title: newTitle,
updateTime: new Date()
}
},

View File

@@ -118,6 +118,11 @@ export const loadRequestMessages = async ({
return item.image_url.url;
})();
// base64 image
if (imgUrl.startsWith('data:image/')) {
return item;
}
try {
// If imgUrl is a local path, load image from local, and set url to base64
if (imgUrl.startsWith('/')) {

View File

@@ -67,7 +67,7 @@ export async function createOneCollection({
fileId,
rawLink,
externalFileId,
...(externalFileId ? { externalFileId } : {}),
externalFileUrl,
rawTextLength,

View File

@@ -118,7 +118,7 @@ try {
{
unique: true,
partialFilterExpression: {
externalFileId: { $exists: true, $ne: '' }
externalFileId: { $exists: true }
}
}
);

View File

@@ -77,7 +77,7 @@ export async function pushDataListToTrainingQueue({
if (trainingMode === TrainingModeEnum.chunk) {
return {
maxToken: vectorModelData.maxToken * 1.3,
maxToken: vectorModelData.maxToken * 1.5,
model: vectorModelData.model,
weight: vectorModelData.weight
};
@@ -125,10 +125,7 @@ export async function pushDataListToTrainingQueue({
const text = item.q + item.a;
// count q token
const token = item.q.length;
if (token > maxToken) {
if (text.length > maxToken) {
filterResult.overToken.push(item);
return;
}

View File

@@ -27,7 +27,6 @@ import { computedMaxToken, llmCompletionsBodyFormat } from '../../../../ai/utils
import { toolValueTypeList } from '@fastgpt/global/core/workflow/constants';
import { WorkflowInteractiveResponseType } from '@fastgpt/global/core/workflow/template/system/interactive/type';
import { ChatItemValueTypeEnum } from '@fastgpt/global/core/chat/constants';
import { i18nT } from '../../../../../../web/i18n/utils';
type FunctionRunResponseType = {
toolRunResponse: DispatchFlowResponse;
@@ -216,7 +215,11 @@ export const runToolWithFunctionCall = async (
// console.log(JSON.stringify(requestMessages, null, 2));
/* Run llm */
const { response: aiResponse, isStreamResponse } = await createChatCompletion({
const {
response: aiResponse,
isStreamResponse,
getEmptyResponseTip
} = await createChatCompletion({
body: requestBody,
userKey: user.openaiAccount,
options: {
@@ -256,6 +259,9 @@ export const runToolWithFunctionCall = async (
};
}
})();
if (!answer && functionCalls.length === 0) {
return Promise.reject(getEmptyResponseTip());
}
// Run the selected tool.
const toolsRunResponse = (
@@ -549,9 +555,5 @@ async function streamResponse({
}
}
if (!textAnswer && functionCalls.length === 0) {
return Promise.reject(i18nT('chat:LLM_model_response_empty'));
}
return { answer: textAnswer, functionCalls };
}

View File

@@ -29,7 +29,6 @@ import { WorkflowResponseType } from '../../type';
import { toolValueTypeList } from '@fastgpt/global/core/workflow/constants';
import { WorkflowInteractiveResponseType } from '@fastgpt/global/core/workflow/template/system/interactive/type';
import { ChatItemValueTypeEnum } from '@fastgpt/global/core/chat/constants';
import { i18nT } from '../../../../../../web/i18n/utils';
type FunctionCallCompletion = {
id: string;
@@ -225,7 +224,11 @@ export const runToolWithPromptCall = async (
// console.log(JSON.stringify(requestMessages, null, 2));
/* Run llm */
const { response: aiResponse, isStreamResponse } = await createChatCompletion({
const {
response: aiResponse,
isStreamResponse,
getEmptyResponseTip
} = await createChatCompletion({
body: requestBody,
userKey: user.openaiAccount,
options: {
@@ -251,8 +254,11 @@ export const runToolWithPromptCall = async (
return result.choices?.[0]?.message?.content || '';
}
})();
const { answer: replaceAnswer, toolJson } = parseAnswer(answer);
if (!answer && !toolJson) {
return Promise.reject(getEmptyResponseTip());
}
// No tools
if (!toolJson) {
if (replaceAnswer === ERROR_TEXT) {
@@ -534,9 +540,6 @@ async function streamResponse({
}
}
if (!textAnswer) {
return Promise.reject(i18nT('chat:LLM_model_response_empty'));
}
return { answer: textAnswer.trim() };
}

View File

@@ -272,7 +272,11 @@ export const runToolWithToolChoice = async (
);
// console.log(JSON.stringify(requestBody, null, 2), '==requestBody');
/* Run llm */
const { response: aiResponse, isStreamResponse } = await createChatCompletion({
const {
response: aiResponse,
isStreamResponse,
getEmptyResponseTip
} = await createChatCompletion({
body: requestBody,
userKey: user.openaiAccount,
options: {
@@ -336,6 +340,9 @@ export const runToolWithToolChoice = async (
};
}
})();
if (!answer && toolCalls.length === 0) {
return Promise.reject(getEmptyResponseTip());
}
// Run the selected tool by LLM.
const toolsRunResponse = (
@@ -645,9 +652,5 @@ async function streamResponse({
}
}
if (!textAnswer && toolCalls.length === 0) {
return Promise.reject(i18nT('chat:LLM_model_response_empty'));
}
return { answer: textAnswer, toolCalls };
}

View File

@@ -33,15 +33,13 @@ import { getLLMModel, ModelTypeEnum } from '../../../ai/model';
import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type';
import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
import { getHistories } from '../utils';
import { checkQuoteQAValue, getHistories } from '../utils';
import { filterSearchResultsByMaxChars } from '../../utils';
import { getHistoryPreview } from '@fastgpt/global/core/chat/utils';
import { addLog } from '../../../../common/system/log';
import { computedMaxToken, llmCompletionsBodyFormat } from '../../../ai/utils';
import { WorkflowResponseType } from '../type';
import { formatTime2YMDHM } from '@fastgpt/global/common/string/time';
import { AiChatQuoteRoleType } from '@fastgpt/global/core/workflow/template/system/aiChat/type';
import { getErrText } from '@fastgpt/global/common/error/utils';
import { getFileContentFromLinks, getHistoryFileLinks } from '../tools/readFiles';
import { parseUrlToFileType } from '@fastgpt/global/common/file/tools';
import { i18nT } from '../../../../../web/i18n/utils';
@@ -93,6 +91,7 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise<ChatResp
stream = stream && isResponseAnswerText;
const chatHistories = getHistories(history, histories);
quoteQA = checkQuoteQAValue(quoteQA);
const modelConstantsData = getLLMModel(model);
if (!modelConstantsData) {
@@ -169,99 +168,91 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise<ChatResp
modelConstantsData
);
// console.log(JSON.stringify(requestBody, null, 2), '===');
try {
const { response, isStreamResponse } = await createChatCompletion({
body: requestBody,
userKey: user.openaiAccount,
options: {
headers: {
Accept: 'application/json, text/plain, */*'
}
const { response, isStreamResponse, getEmptyResponseTip } = await createChatCompletion({
body: requestBody,
userKey: user.openaiAccount,
options: {
headers: {
Accept: 'application/json, text/plain, */*'
}
});
}
});
const { answerText } = await (async () => {
if (res && isStreamResponse) {
// sse response
const { answer } = await streamResponse({
res,
stream: response,
workflowStreamResponse
const { answerText } = await (async () => {
if (res && isStreamResponse) {
// sse response
const { answer } = await streamResponse({
res,
stream: response,
workflowStreamResponse
});
return {
answerText: answer
};
} else {
const unStreamResponse = response as ChatCompletion;
const answer = unStreamResponse.choices?.[0]?.message?.content || '';
if (stream) {
// Some models do not support streaming
workflowStreamResponse?.({
event: SseResponseEventEnum.fastAnswer,
data: textAdaptGptResponse({
text: answer
})
});
if (!answer) {
return Promise.reject(i18nT('chat:LLM_model_response_empty'));
}
return {
answerText: answer
};
} else {
const unStreamResponse = response as ChatCompletion;
const answer = unStreamResponse.choices?.[0]?.message?.content || '';
if (stream) {
// Some models do not support streaming
workflowStreamResponse?.({
event: SseResponseEventEnum.fastAnswer,
data: textAdaptGptResponse({
text: answer
})
});
}
return {
answerText: answer
};
}
})();
const completeMessages = requestMessages.concat({
role: ChatCompletionRequestMessageRoleEnum.Assistant,
content: answerText
});
const chatCompleteMessages = GPTMessages2Chats(completeMessages);
return {
answerText: answer
};
}
})();
const tokens = await countMessagesTokens(chatCompleteMessages);
const { totalPoints, modelName } = formatModelChars2Points({
model,
if (!answerText) {
return Promise.reject(getEmptyResponseTip());
}
const completeMessages = requestMessages.concat({
role: ChatCompletionRequestMessageRoleEnum.Assistant,
content: answerText
});
const chatCompleteMessages = GPTMessages2Chats(completeMessages);
const tokens = await countMessagesTokens(chatCompleteMessages);
const { totalPoints, modelName } = formatModelChars2Points({
model,
tokens,
modelType: ModelTypeEnum.llm
});
return {
answerText,
[DispatchNodeResponseKeyEnum.nodeResponse]: {
totalPoints: user.openaiAccount?.key ? 0 : totalPoints,
model: modelName,
tokens,
modelType: ModelTypeEnum.llm
});
return {
answerText,
[DispatchNodeResponseKeyEnum.nodeResponse]: {
query: `${userChatInput}`,
maxToken: max_tokens,
historyPreview: getHistoryPreview(
chatCompleteMessages,
10000,
modelConstantsData.vision && aiChatVision
),
contextTotalLen: completeMessages.length
},
[DispatchNodeResponseKeyEnum.nodeDispatchUsages]: [
{
moduleName: name,
totalPoints: user.openaiAccount?.key ? 0 : totalPoints,
model: modelName,
tokens,
query: `${userChatInput}`,
maxToken: max_tokens,
historyPreview: getHistoryPreview(
chatCompleteMessages,
10000,
modelConstantsData.vision && aiChatVision
),
contextTotalLen: completeMessages.length
},
[DispatchNodeResponseKeyEnum.nodeDispatchUsages]: [
{
moduleName: name,
totalPoints: user.openaiAccount?.key ? 0 : totalPoints,
model: modelName,
tokens
}
],
[DispatchNodeResponseKeyEnum.toolResponses]: answerText,
history: chatCompleteMessages
};
} catch (error) {
if (user.openaiAccount?.baseUrl) {
return Promise.reject(`您的 OpenAI key 出错了: ${getErrText(error)}`);
}
return Promise.reject(error);
}
tokens
}
],
[DispatchNodeResponseKeyEnum.toolResponses]: answerText,
history: chatCompleteMessages
};
};
async function filterDatasetQuote({

View File

@@ -209,7 +209,6 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
try {
const { formatResponse, rawResponse } = await (async () => {
const systemPluginCb = global.systemPluginCb;
console.log(systemPluginCb, '-=', httpReqUrl);
if (systemPluginCb[httpReqUrl]) {
const pluginResult = await replaceSystemPluginResponse({
response: await systemPluginCb[httpReqUrl](requestBody),
@@ -395,7 +394,7 @@ async function replaceSystemPluginResponse({
response[key] = `${ReadFileBaseUrl}/${filename}?token=${await createFileToken({
bucketName: 'chat',
teamId,
tmbId,
uid: tmbId,
fileId
})}`;
} catch (error) {}

View File

@@ -13,6 +13,7 @@ import { responseWrite } from '../../../common/response';
import { NextApiResponse } from 'next';
import { SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/constants';
import { getNanoid } from '@fastgpt/global/common/string/tools';
import { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type';
export const getWorkflowResponseWrite = ({
res,
@@ -87,27 +88,6 @@ export const filterToolNodeIdByEdges = ({
.map((edge) => edge.target);
};
// export const checkTheModuleConnectedByTool = (
// modules: StoreNodeItemType[],
// node: StoreNodeItemType
// ) => {
// let sign = false;
// const toolModules = modules.filter((item) => item.flowNodeType === FlowNodeTypeEnum.tools);
// toolModules.forEach((item) => {
// const toolOutput = item.outputs.find(
// (output) => output.key === NodeOutputKeyEnum.selectedTools
// );
// toolOutput?.targets.forEach((target) => {
// if (target.moduleId === node.moduleId) {
// sign = true;
// }
// });
// });
// return sign;
// };
export const getHistories = (history?: ChatItemType[] | number, histories: ChatItemType[] = []) => {
if (!history) return [];
@@ -149,6 +129,17 @@ export const valueTypeFormat = (value: any, type?: WorkflowIOValueTypeEnum) => {
return value;
};
export const checkQuoteQAValue = (quoteQA?: SearchDataResponseItemType[]) => {
if (!quoteQA) return undefined;
if (quoteQA.length === 0) {
return [];
}
if (quoteQA.some((item) => !item.q || !item.datasetId)) {
return undefined;
}
return quoteQA;
};
/* remove system variable */
export const removeSystemVariable = (variables: Record<string, any>) => {
const copyVariables = { ...variables };

View File

@@ -48,7 +48,8 @@ const OutLinkSchema = new Schema({
default: false
},
showNodeStatus: {
type: Boolean
type: Boolean,
default: true
},
showRawSource: {
type: Boolean

View File

@@ -7,7 +7,7 @@ import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
import { OwnerPermissionVal, ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { Permission } from '@fastgpt/global/support/permission/controller';
export async function authFile({
export const authCollectionFile = async ({
fileId,
per = OwnerPermissionVal,
...props
@@ -17,7 +17,7 @@ export async function authFile({
AuthResponseType & {
file: DatasetFileSchema;
}
> {
> => {
const authRes = await parseHeaderCert(props);
const { teamId, tmbId } = authRes;
@@ -33,7 +33,7 @@ export async function authFile({
const permission = new Permission({
per: ReadPermissionVal,
isOwner: file.metadata?.tmbId === tmbId
isOwner: file.metadata?.uid === tmbId || file.metadata?.tmbId === tmbId
});
if (!permission.checkPer(per)) {
@@ -45,4 +45,4 @@ export async function authFile({
permission,
file
};
}
};

View File

@@ -413,7 +413,8 @@ export const createFileToken = (data: FileTokenQuery) => {
return Promise.reject('System unset FILE_TOKEN_KEY');
}
const expireMinutes = bucketNameMap[data.bucketName].previewExpireMinutes;
const expireMinutes =
data.customExpireMinutes ?? bucketNameMap[data.bucketName].previewExpireMinutes;
const expiredTime = Math.floor(addMinutes(new Date(), expireMinutes).getTime() / 1000);
const key = (process.env.FILE_TOKEN_KEY as string) ?? 'filetoken';
@@ -435,14 +436,14 @@ export const authFileToken = (token?: string) =>
const key = (process.env.FILE_TOKEN_KEY as string) ?? 'filetoken';
jwt.verify(token, key, function (err, decoded: any) {
if (err || !decoded.bucketName || !decoded?.teamId || !decoded?.tmbId || !decoded?.fileId) {
if (err || !decoded.bucketName || !decoded?.teamId || !decoded?.fileId) {
reject(ERROR_ENUM.unAuthFile);
return;
}
resolve({
bucketName: decoded.bucketName,
teamId: decoded.teamId,
tmbId: decoded.tmbId,
uid: decoded.uid,
fileId: decoded.fileId
});
});

View File

@@ -62,14 +62,14 @@ export async function authOutLinkValid<T extends OutlinkAppType = undefined>({
if (!shareId) {
return Promise.reject(OutLinkErrEnum.linkUnInvalid);
}
const shareChat = (await MongoOutLink.findOne({ shareId }).lean()) as OutLinkSchema<T>;
const outLinkConfig = (await MongoOutLink.findOne({ shareId }).lean()) as OutLinkSchema<T>;
if (!shareChat) {
if (!outLinkConfig) {
return Promise.reject(OutLinkErrEnum.linkUnInvalid);
}
return {
appId: shareChat.appId,
shareChat
appId: outLinkConfig.appId,
outLinkConfig
};
}

View File

@@ -2,6 +2,7 @@ import { Permission } from '@fastgpt/global/support/permission/controller';
import { ApiRequestProps } from '../../type/next';
import type { PermissionValueType } from '@fastgpt/global/support/permission/type';
import { RequireAtLeastOne } from '@fastgpt/global/common/type/utils';
import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant';
export type ReqHeaderAuthType = {
cookie?: string;

View File

@@ -23,9 +23,6 @@ declare global {
var whisperModel: WhisperModelType;
var reRankModels: ReRankModelItemType[];
var systemLoadedGlobalVariables: boolean;
var systemLoadedGlobalConfig: boolean;
var workerPoll: Record<WorkerNameEnum, WorkerPool>;
var appMarketTemplates: TemplateMarketItemType[];
}

View File

@@ -10,6 +10,8 @@ export const hasHttps = () => {
return window.location.protocol === 'https:';
};
export const subRoute = process.env.NEXT_PUBLIC_BASE_URL;
export const getWebReqUrl = (url: string = '') => {
if (!url) return '/';
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL;

View File

@@ -0,0 +1,41 @@
import React from 'react';
import { Flex, FlexProps } from '@chakra-ui/react';
import MyIcon from './index';
type Props = FlexProps & {
icon: string;
size?: string;
onClick?: () => void;
hoverColor?: string;
};
const MyIconButton = ({
icon,
onClick,
hoverColor = 'primary.600',
size = '1rem',
...props
}: Props) => {
return (
<Flex
mr={1}
p={1}
color={'myGray.500'}
rounded={'sm'}
alignItems={'center'}
bg={'transparent'}
transition={'background 0.1s'}
cursor={'pointer'}
_hover={{
bg: 'myGray.05',
color: hoverColor
}}
onClick={onClick}
{...props}
>
<MyIcon name={icon as any} w={size} />
</Flex>
);
};
export default MyIconButton;

View File

@@ -5,6 +5,7 @@ export const iconPaths = {
change: () => import('./icons/change.svg'),
chatSend: () => import('./icons/chatSend.svg'),
check: () => import('./icons/check.svg'),
checkCircle: () => import('./icons/checkCircle.svg'),
closeSolid: () => import('./icons/closeSolid.svg'),
collectionLight: () => import('./icons/collectionLight.svg'),
collectionSolid: () => import('./icons/collectionSolid.svg'),
@@ -101,6 +102,7 @@ export const iconPaths = {
'core/app/schedulePlan': () => import('./icons/core/app/schedulePlan.svg'),
'core/app/simpleBot': () => import('./icons/core/app/simpleBot.svg'),
'core/app/simpleMode/ai': () => import('./icons/core/app/simpleMode/ai.svg'),
'core/app/simpleMode/autoExec': () => import('./icons/core/app/simpleMode/autoExec.svg'),
'core/app/simpleMode/chat': () => import('./icons/core/app/simpleMode/chat.svg'),
'core/app/simpleMode/dataset': () => import('./icons/core/app/simpleMode/dataset.svg'),
'core/app/simpleMode/file': () => import('./icons/core/app/simpleMode/file.svg'),
@@ -183,6 +185,7 @@ export const iconPaths = {
'core/workflow/debugNext': () => import('./icons/core/workflow/debugNext.svg'),
'core/workflow/debugResult': () => import('./icons/core/workflow/debugResult.svg'),
'core/workflow/edgeArrow': () => import('./icons/core/workflow/edgeArrow.svg'),
'core/workflow/edgeArrowBold': () => import('./icons/core/workflow/edgeArrowBold.svg'),
'core/workflow/grout': () => import('./icons/core/workflow/grout.svg'),
'core/workflow/inputType/array': () => import('./icons/core/workflow/inputType/array.svg'),
'core/workflow/inputType/customVariable': () =>

View File

@@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 17 17" fill="none">
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.5587 3.69438C13.9492 3.30386 14.5824 3.30386 14.9729 3.69438C15.3634 4.08491 15.3634 4.71807 14.9729 5.1086L7.63956 12.4419C7.24904 12.8325 6.61587 12.8325 6.22535 12.4419L2.89201 9.1086C2.50149 8.71807 2.50149 8.08491 2.89201 7.69438C3.28254 7.30386 3.9157 7.30386 4.30623 7.69438L6.93245 10.3206L13.5587 3.69438Z"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none">
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.8043 3.52859C14.0646 3.78894 14.0646 4.21105 13.8043 4.4714L6.47092 11.8047C6.21057 12.0651 5.78846 12.0651 5.52811 11.8047L2.19477 8.4714C1.93442 8.21105 1.93442 7.78894 2.19477 7.52859C2.45512 7.26824 2.87723 7.26824 3.13758 7.52859L5.99951 10.3905L12.8614 3.52859C13.1218 3.26824 13.5439 3.26824 13.8043 3.52859Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 452 B

After

Width:  |  Height:  |  Size: 453 B

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 17" fill="none">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.1848 3.90471C9.12756 3.43362 7.94633 3.31691 6.81731 3.572C5.6883 3.82708 4.67198 4.44029 3.91995 5.32018C3.16791 6.20006 2.72044 7.29947 2.64429 8.45443C2.56813 9.6094 2.86736 10.758 3.49735 11.7291C4.12734 12.7001 5.05433 13.4414 6.14008 13.8426C7.22582 14.2437 8.41215 14.2831 9.52213 13.9549C10.6321 13.6267 11.6063 12.9485 12.2993 12.0215C12.9923 11.0944 13.3671 9.96815 13.3678 8.81067V8.2559C13.3678 7.88771 13.6663 7.58924 14.0345 7.58924C14.4027 7.58924 14.7011 7.88771 14.7011 8.2559V8.81105C14.7003 10.2561 14.2324 11.6625 13.3672 12.8198C12.502 13.9771 11.2859 14.8238 9.90017 15.2335C8.51447 15.6432 7.03346 15.594 5.67801 15.0933C4.32255 14.5925 3.16529 13.667 2.37881 12.4548C1.59232 11.2425 1.21877 9.80857 1.31384 8.3667C1.40892 6.92484 1.96754 5.55233 2.90638 4.45388C3.84523 3.35543 5.114 2.5899 6.52347 2.27144C7.93294 1.95299 9.4076 2.09869 10.7275 2.6868C11.0638 2.83666 11.215 3.23077 11.0651 3.56709C10.9153 3.9034 10.5211 4.05456 10.1848 3.90471ZM14.5056 3.50856C14.7661 3.76878 14.7663 4.19089 14.5061 4.45137L8.47187 10.4917C8.34686 10.6168 8.17726 10.6871 8.00039 10.6871C7.82352 10.6872 7.65389 10.617 7.52882 10.4919L5.71855 8.68161C5.4582 8.42126 5.4582 7.99915 5.71855 7.7388C5.9789 7.47846 6.40101 7.47846 6.66136 7.7388L7.99999 9.07744L13.5628 3.50904C13.823 3.24856 14.2452 3.24835 14.5056 3.50856Z" />
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1 +1,6 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1694403033666" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4053" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M1016.32 494.08l-143.872-143.36c-9.728-9.728-26.112-9.728-35.84 0-9.728 9.728-9.728 26.112 0 35.84L936.96 486.4h-399.36V87.04l99.84 100.352c9.728 9.728 26.112 9.728 35.84 0 9.728-9.728 9.728-26.112 0-35.84l-143.36-143.872c-9.728-9.728-26.112-9.728-35.84 0l-143.36 143.872c-9.728 9.728-9.728 26.112 0 35.84 9.728 9.728 26.112 9.728 35.84 0L486.4 87.04v399.36H87.04l100.352-99.84c9.728-9.728 9.728-26.112 0-35.84-9.728-9.728-26.112-9.728-35.84 0l-143.872 143.36c-9.728 9.728-9.728 26.112 0 35.84l143.872 143.36c9.728 9.728 26.112 9.728 35.84 0 9.728-9.728 9.728-26.112 0-35.84L87.04 537.6h399.36v399.36l-99.84-100.352c-9.728-9.728-26.112-9.728-35.84 0-9.728 9.728-9.728 26.112 0 35.84l143.36 143.872c9.728 9.728 26.112 9.728 35.84 0l143.36-143.872c9.728-9.728 9.728-26.112 0-35.84-9.728-9.728-26.112-9.728-35.84 0L537.6 936.96v-399.36h399.36l-100.352 99.84c-9.728 9.728-9.728 26.112 0 35.84 9.728 9.728 26.112 9.728 35.84 0l143.872-143.36c10.24-9.728 10.24-26.112 0-35.84z" p-id="4054"></path></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none">
<path d="M8.47188 1.52653C8.34159 1.39624 8.17079 1.33115 8.00003 1.33127C7.82926 1.33115 7.65847 1.39624 7.52818 1.52653C7.52123 1.53348 7.51447 1.54054 7.5079 1.54771L6.11486 2.94074C5.85451 3.20109 5.85451 3.6232 6.11486 3.88355C6.37521 4.1439 6.79732 4.1439 7.05767 3.88355L7.33381 3.60741V5.99835C7.33381 6.36654 7.63229 6.66502 8.00048 6.66502C8.36867 6.66502 8.66714 6.36654 8.66714 5.99835V3.60831L8.94239 3.88355C9.20274 4.1439 9.62485 4.1439 9.8852 3.88355C10.1455 3.6232 10.1455 3.20109 9.8852 2.94074L8.49216 1.54771C8.48559 1.54054 8.47883 1.53348 8.47188 1.52653Z" />
<path d="M7.33381 12.3926V10.0039C7.33381 9.6357 7.63229 9.33723 8.00048 9.33723C8.36867 9.33723 8.66714 9.6357 8.66714 10.0039V12.3917L8.94239 12.1164C9.20274 11.8561 9.62485 11.8561 9.8852 12.1164C10.1455 12.3768 10.1455 12.7989 9.8852 13.0593L8.49216 14.4523C8.48559 14.4595 8.47883 14.4665 8.47188 14.4735C8.34159 14.6038 8.17079 14.6688 8.00003 14.6687C7.82926 14.6688 7.65847 14.6038 7.52818 14.4735C7.52123 14.4665 7.51447 14.4595 7.5079 14.4523L6.11486 13.0593C5.85451 12.7989 5.85451 12.3768 6.11486 12.1164C6.37521 11.8561 6.79732 11.8561 7.05767 12.1164L7.33381 12.3926Z" />
<path d="M6.0646 7.33378C6.43279 7.33378 6.73126 7.63226 6.73126 8.00045C6.73126 8.36864 6.43279 8.66711 6.0646 8.66711H3.60834L3.88358 8.94236C4.14393 9.20271 4.14393 9.62482 3.88358 9.88517C3.62323 10.1455 3.20112 10.1455 2.94077 9.88517L1.54774 8.49213C1.54057 8.48556 1.53351 8.4788 1.52656 8.47185C1.39627 8.34156 1.33118 8.17075 1.3313 7.99998C1.33119 7.82922 1.39628 7.65843 1.52656 7.52815C1.53351 7.5212 1.54057 7.51444 1.54774 7.50786L2.94077 6.11483C3.20112 5.85448 3.62323 5.85448 3.88358 6.11483C4.14393 6.37518 4.14393 6.79729 3.88358 7.05764L3.60744 7.33378H6.0646Z" />
<path d="M13.0593 6.11483L14.4523 7.50786C14.4595 7.51444 14.4666 7.5212 14.4735 7.52815C14.6038 7.65843 14.6689 7.82923 14.6688 8C14.6689 8.17076 14.6038 8.34156 14.4735 8.47185C14.4666 8.4788 14.4595 8.48556 14.4523 8.49213L13.0593 9.88517C12.799 10.1455 12.3768 10.1455 12.1165 9.88517C11.8562 9.62482 11.8562 9.20271 12.1165 8.94236L12.3911 8.66779H9.92959C9.5614 8.66779 9.26292 8.36931 9.26292 8.00112C9.26292 7.63293 9.5614 7.33445 9.92959 7.33445H12.3933L12.1165 7.05764C11.8562 6.79729 11.8562 6.37518 12.1165 6.11483C12.3769 5.85448 12.799 5.85448 13.0593 6.11483Z" />
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="21" height="21" viewBox="0 0 21 21" fill="none">
<path d="M7.56249 11.1348L9.12024 7.33546C9.17155 7.21031 9.2934 7.12858 9.42866 7.12858H11.6153C11.857 7.12858 12.0184 7.37785 11.9194 7.5984L10.9629 9.72956C10.9134 9.83984 10.9941 9.96447 11.1149 9.96447H12.7714C13.0487 9.96447 13.2048 10.2834 13.0346 10.5024L9.93738 14.4874C9.73038 14.7537 9.30408 14.5793 9.34309 14.2443L9.62999 11.7805C9.64152 11.6815 9.56413 11.5946 9.46444 11.5946H7.87091C7.63386 11.5946 7.47257 11.3541 7.56249 11.1348Z" fill="#8774EE"/>
<path d="M3.68233 14.3773C3.28604 14.6067 2.77464 14.4728 2.58571 14.0557C1.82751 12.3817 1.64076 10.4957 2.06882 8.69266C2.561 6.61955 3.82859 4.81371 5.61106 3.64631C7.39354 2.47891 9.55548 2.03863 11.6525 2.41596C13.4764 2.74413 15.1306 3.66906 16.3621 5.03305C16.6689 5.37293 16.5873 5.89525 16.2187 6.16683C15.85 6.43841 15.3344 6.3554 15.0192 6.02321C14.0456 4.99697 12.7652 4.301 11.3589 4.04796C9.67911 3.74571 7.94736 4.09838 6.51957 5.03349C5.09178 5.9686 4.07642 7.4151 3.68218 9.07569C3.35212 10.4659 3.47839 11.9178 4.03001 13.2204C4.20857 13.6421 4.07861 14.1479 3.68233 14.3773Z" fill="#8774EE"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.04324 13.2533C4.0589 13.2943 4.07172 13.336 4.08171 13.3781C4.17284 13.7615 4.0302 14.1759 3.68233 14.3773C3.28604 14.6067 2.77464 14.4728 2.58571 14.0557C2.55736 13.9931 2.52981 13.9302 2.50307 13.867C2.48986 13.8358 2.47685 13.8046 2.46403 13.7733C1.80857 12.1713 1.66467 10.395 2.06882 8.69266C2.561 6.61955 3.82859 4.81371 5.61106 3.64631C7.39354 2.47891 9.55548 2.03863 11.6525 2.41596C13.3745 2.7258 14.9453 3.5676 16.1518 4.80865C16.1754 4.83292 16.1989 4.85734 16.2222 4.88192C16.2694 4.93168 16.316 4.98206 16.3621 5.03305C16.6689 5.37293 16.5873 5.89525 16.2187 6.16683C15.895 6.40524 15.4582 6.37039 15.1431 6.1336C15.1085 6.10762 15.0754 6.07921 15.0441 6.04846C15.0357 6.04021 15.0274 6.03179 15.0192 6.02321C14.0456 4.99697 12.7652 4.301 11.3589 4.04796C9.67911 3.74571 7.94736 4.09838 6.51957 5.03349C5.09178 5.9686 4.07642 7.4151 3.68218 9.07569C3.35212 10.4659 3.47839 11.9178 4.03001 13.2204C4.03463 13.2313 4.03904 13.2423 4.04324 13.2533Z" fill="#8774EE"/>
<path d="M17.123 7.77804C17.5469 7.60478 18.0353 7.80718 18.1656 8.24615C18.6407 9.84662 18.6258 11.5599 18.1122 13.1618C17.5139 15.028 16.277 16.6236 14.6189 17.6682C12.9608 18.7129 10.9876 19.1397 9.04598 18.8738C7.37931 18.6455 5.82746 17.9193 4.58891 16.7998C4.24921 16.4928 4.27748 15.9649 4.61675 15.6574C4.95601 15.3498 5.47737 15.3802 5.82456 15.6788C6.79537 16.5136 7.9909 17.0556 9.27099 17.2309C10.8262 17.444 12.4068 17.102 13.735 16.2652C15.0631 15.4285 16.0539 14.1504 16.5332 12.6556C16.9276 11.4252 16.9548 10.1128 16.6209 8.87674C16.5015 8.43469 16.6992 7.95131 17.123 7.77804Z" fill="#8774EE"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.6123 8.8424C16.615 8.85387 16.6178 8.86532 16.6209 8.87674C16.9548 10.1128 16.9276 11.4252 16.5332 12.6556C16.0539 14.1504 15.0631 15.4285 13.735 16.2652C12.4068 17.102 10.8262 17.444 9.27099 17.2309C7.9909 17.0556 6.79537 16.5136 5.82456 15.6788C5.81558 15.671 5.8065 15.6635 5.7973 15.6561C5.76301 15.6287 5.72719 15.6038 5.69016 15.5815C5.3527 15.3778 4.91457 15.3874 4.61675 15.6574C4.27748 15.9649 4.24921 16.4928 4.58891 16.7998C4.63988 16.8459 4.69138 16.8913 4.74339 16.936C4.76907 16.9581 4.79489 16.98 4.82082 17.0018C6.01868 18.0067 7.48176 18.6596 9.04598 18.8738C10.9876 19.1397 12.9608 18.7129 14.6189 17.6682C16.277 16.6236 17.5139 15.028 18.1122 13.1618C18.5942 11.6584 18.637 10.0568 18.2476 8.54252C18.2392 8.50973 18.2306 8.47699 18.2217 8.44429C18.2038 8.37806 18.1851 8.31201 18.1656 8.24615C18.0353 7.80718 17.5469 7.60478 17.123 7.77804C16.751 7.93014 16.5532 8.32121 16.5912 8.71352C16.5953 8.75657 16.6024 8.79963 16.6123 8.8424Z" fill="#8774EE"/>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 16" fill="none">
<path d="M3.07373 0.535309C2.48828 -0.0505066 1.53809 -0.0505066 0.952637 0.535309C0.366699 1.12106 0.366699 2.07083 0.952637 2.65665L6.26123 7.96536L0.952637 13.2737C0.367188 13.8595 0.367188 14.8092 0.952637 15.395C1.53857 15.9807 2.48828 15.9807 3.07422 15.395L9.43799 9.03104C9.66016 8.80875 9.7959 8.53372 9.84961 8.24643C9.90283 7.97018 9.87842 7.68179 9.77588 7.41672C9.70264 7.22818 9.58984 7.05142 9.43799 6.89926L3.07373 0.535309Z"/>
</svg>

After

Width:  |  Height:  |  Size: 525 B

View File

@@ -1,7 +1,7 @@
import React from 'react';
import React, { ForwardedRef, forwardRef } from 'react';
import { Image, ImageProps } from '@chakra-ui/react';
import { getWebReqUrl } from '../../../common/system/utils';
const MyImage = (props: ImageProps) => {
const MyImage = (props: ImageProps, ref?: ForwardedRef<any>) => {
return <Image {...props} src={getWebReqUrl(props.src)} alt={props.alt || ''} />;
};
export default React.memo(MyImage);
export default forwardRef(MyImage);

View File

@@ -7,22 +7,26 @@ import {
useOutsideClick,
MenuButton,
MenuItemProps,
PlacementWithLogical
PlacementWithLogical,
AvatarProps,
BoxProps,
DividerProps
} from '@chakra-ui/react';
import MyDivider from '../MyDivider';
import type { IconNameType } from '../Icon/type';
import { useSystem } from '../../../hooks/useSystem';
import Avatar from '../Avatar';
export type MenuItemType = 'primary' | 'danger';
export type MenuItemType = 'primary' | 'danger' | 'gray' | 'grayBg';
export type MenuSizeType = 'sm' | 'md' | 'xs' | 'mini';
export type Props = {
width?: number | string;
offset?: [number, number];
Button: React.ReactNode;
trigger?: 'hover' | 'click';
iconSize?: string;
iconRadius?: string;
size?: MenuSizeType;
placement?: PlacementWithLogical;
menuList: {
@@ -39,18 +43,9 @@ export type Props = {
}[];
};
const MyMenu = ({
width = 'auto',
trigger = 'hover',
offset,
iconSize = '1rem',
Button,
menuList,
iconRadius,
placement = 'bottom-start'
}: Props) => {
const typeMapStyle: Record<MenuItemType, MenuItemProps> = {
primary: {
const typeMapStyle: Record<MenuItemType, { styles: MenuItemProps; iconColor?: string }> = {
primary: {
styles: {
_hover: {
backgroundColor: 'primary.50',
color: 'primary.600'
@@ -64,7 +59,44 @@ const MyMenu = ({
color: 'primary.600'
}
},
danger: {
iconColor: 'myGray.600'
},
gray: {
styles: {
_hover: {
backgroundColor: 'myGray.05',
color: 'primary.600'
},
_focus: {
backgroundColor: 'myGray.05',
color: 'primary.600'
},
_active: {
backgroundColor: 'myGray.05',
color: 'primary.600'
}
},
iconColor: 'myGray.400'
},
grayBg: {
styles: {
_hover: {
backgroundColor: 'myGray.05',
color: 'primary.600'
},
_focus: {
backgroundColor: 'myGray.05',
color: 'primary.600'
},
_active: {
backgroundColor: 'myGray.05',
color: 'primary.600'
}
},
iconColor: 'myGray.600'
},
danger: {
styles: {
color: 'red.600',
_hover: {
background: 'red.1'
@@ -75,9 +107,97 @@ const MyMenu = ({
_active: {
background: 'red.1'
}
},
iconColor: 'red.600'
}
};
const sizeMapStyle: Record<
MenuSizeType,
{
iconStyle: AvatarProps;
labelStyle: BoxProps;
dividerStyle: DividerProps;
menuItemStyle: MenuItemProps;
}
> = {
mini: {
iconStyle: {
w: '14px'
},
labelStyle: {
fontSize: 'mini'
},
dividerStyle: {
my: 0.5
},
menuItemStyle: {
py: 1.5,
px: 2
}
};
},
xs: {
iconStyle: {
w: '14px'
},
labelStyle: {
fontSize: 'sm'
},
dividerStyle: {
my: 0.5
},
menuItemStyle: {
py: 1.5,
px: 2
}
},
sm: {
iconStyle: {
w: '1rem'
},
labelStyle: {
fontSize: 'sm'
},
dividerStyle: {
my: 1
},
menuItemStyle: {
py: 2,
px: 3,
_notLast: {
mb: 0.5
}
}
},
md: {
iconStyle: {
w: '2rem',
borderRadius: '6px'
},
labelStyle: {
fontSize: 'sm'
},
dividerStyle: {
my: 1
},
menuItemStyle: {
py: 2,
px: 3,
_notLast: {
mb: 0.5
}
}
}
};
const MyMenu = ({
width = 'auto',
trigger = 'hover',
size = 'sm',
offset,
Button,
menuList,
placement = 'bottom-start'
}: Props) => {
const { isPc } = useSystem();
const ref = useRef<HTMLDivElement>(null);
const closeTimer = useRef<any>();
@@ -165,7 +285,7 @@ const MyMenu = ({
return (
<Box key={i}>
{item.label && <Box fontSize={'sm'}>{item.label}</Box>}
{i !== 0 && <MyDivider h={'1.5px'} my={1} />}
{i !== 0 && <MyDivider h={'1.5px'} {...sizeMapStyle[size].dividerStyle} />}
{item.children.map((child, index) => (
<MenuItem
key={index}
@@ -177,29 +297,36 @@ const MyMenu = ({
child.onClick();
}
}}
py={2}
px={3}
alignItems={'center'}
fontSize={'sm'}
color={child.isActive ? 'primary.700' : 'myGray.600'}
whiteSpace={'pre-wrap'}
_notLast={{ mb: 0.5 }}
{...typeMapStyle[child.type || 'primary']}
{...typeMapStyle[child.type || 'primary'].styles}
{...sizeMapStyle[size].menuItemStyle}
{...child.menuItemStyles}
>
{!!child.icon && (
<Avatar
src={child.icon as any}
borderRadius={iconRadius}
w={iconSize}
mr={3}
mr={2}
{...sizeMapStyle[size].iconStyle}
color={
child.isActive
? 'inherit'
: typeMapStyle[child.type || 'primary'].iconColor
}
sx={{
'[role="menuitem"]:hover &': {
color: 'inherit'
}
}}
/>
)}
<Box w={'100%'}>
<Box
w={'100%'}
color={child.description ? 'myGray.900' : 'inherit'}
fontSize={'sm'}
{...sizeMapStyle[size].labelStyle}
>
{child.label}
</Box>

View File

@@ -60,7 +60,9 @@ export const MultipleRowSelect = ({
const newValue = [...cloneValue];
if (item.value === selectedValue) {
newValue[index] = undefined;
for (let i = index; i < newValue.length; i++) {
newValue[i] = undefined;
}
setCloneValue(newValue);
onSelect(newValue);
} else {

View File

@@ -18,12 +18,13 @@ const FillRowTabs = ({ list, value, onChange, py = '7px', px = '12px', ...props
display={'inline-flex'}
px={'3px'}
py={'3px'}
borderRadius={'md'}
borderRadius={'sm'}
borderWidth={'1px'}
borderColor={'borderColor.base'}
borderColor={'myGray.200'}
bg={'myGray.50'}
gap={'4px'}
fontSize={'sm'}
fontWeight={'medium'}
{...props}
>
{list.map((item) => (
@@ -33,7 +34,7 @@ const FillRowTabs = ({ list, value, onChange, py = '7px', px = '12px', ...props
alignItems={'center'}
justifyContent={'center'}
cursor={'pointer'}
borderRadius={'md'}
borderRadius={'xs'}
px={px}
py={py}
userSelect={'none'}
@@ -45,10 +46,14 @@ const FillRowTabs = ({ list, value, onChange, py = '7px', px = '12px', ...props
color: 'primary.600'
}
: {
color: 'myGray.500',
_hover: {
color: 'primary.600'
},
onClick: () => onChange(item.value)
})}
>
{item.icon && <MyIcon name={item.icon as any} mr={1} w={'14px'} />}
{item.icon && <MyIcon name={item.icon as any} mr={1.5} w={'18px'} />}
<Box>{item.label}</Box>
</Flex>
))}

View File

@@ -224,8 +224,8 @@ const JSONEditor = ({
{resize && (
<Box
position={'absolute'}
right={'0'}
bottom={'0'}
right={'-2'}
bottom={'-3'}
zIndex={10}
cursor={'ns-resize'}
px={'4px'}
@@ -269,6 +269,8 @@ const JSONEditor = ({
fontSize={'xs'}
color={'myGray.500'}
display={placeholderDisplay}
pointerEvents={'none'}
userSelect={'none'}
>
{placeholder}
</Box>

View File

@@ -105,8 +105,8 @@ export default function Editor({
left={0}
right={0}
bottom={0}
py={2}
px={3}
py={3}
px={3.5}
pointerEvents={'none'}
overflow={'hidden'}
>

View File

@@ -1,5 +1,5 @@
import { ChevronRightIcon } from '@chakra-ui/icons';
import { Box } from '@chakra-ui/react';
import { Box, Flex } from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
import Avatar from '../../../../../../../components/common/Avatar';
@@ -28,7 +28,7 @@ export default function VariableLabel({
color={parentLabel !== 'undefined' ? 'myGray.900' : 'red.600'}
>
{parentLabel !== 'undefined' ? (
<span>
<Flex alignItems={'center'} color={'myGray.600'}>
<Avatar
src={nodeAvatar as any}
w={'1rem'}
@@ -36,12 +36,11 @@ export default function VariableLabel({
borderRadius={'xs'}
display={'inline-flex'}
verticalAlign={'middle'}
mb={'3px'}
/>
{parentLabel}
<ChevronRightIcon />
<ChevronRightIcon color={'myGray.500'} />
{childLabel}
</span>
</Flex>
) : (
<>
<Box>{t('common:invalid_variable')}</Box>

View File

@@ -6,7 +6,7 @@ import { TextNode } from 'lexical';
import { getHashtagRegexString } from './utils';
import { mergeRegister } from '@lexical/utils';
import { registerLexicalTextEntity } from '../../utils';
import { useTranslation } from 'react-i18next';
import { useTranslation } from 'next-i18next';
const REGEX = new RegExp(getHashtagRegexString(), 'i');

View File

@@ -1,13 +1,12 @@
import React, { useMemo, useRef } from 'react';
import MyMenu from '../../common/MyMenu';
import MyMenu, { MenuItemType } from '../../common/MyMenu';
import {
FlowNodeInputMap,
FlowNodeInputTypeEnum
} from '@fastgpt/global/core/workflow/node/constant';
import { Box, Button, useTheme } from '@chakra-ui/react';
import { Button, useTheme } from '@chakra-ui/react';
import MyIcon from '../../common/Icon';
import { useTranslation } from 'next-i18next';
import { useConfirm } from '../../../hooks/useConfirm';
const NodeInputSelect = ({
renderTypeList,
@@ -19,9 +18,6 @@ const NodeInputSelect = ({
onChange: (e: string) => void;
}) => {
const { t } = useTranslation();
const { openConfirm, ConfirmModal } = useConfirm({
title: t('common:core.workflow.Change input type tip')
});
const renderType = renderTypeList[renderTypeIndex];
const theme = useTheme();
@@ -136,7 +132,22 @@ const NodeInputSelect = ({
);
const filterMenuList = useMemo(
() => renderList.filter((item) => renderTypeList.includes(item.renderType)),
() =>
renderList
.filter((item) => renderTypeList.includes(item.renderType))
.map((item) => ({
...item,
type: 'gray' as MenuItemType,
menuItemStyles: {
fontWeight: 'medium',
minH: 7,
h: 7,
px: 1,
py: 0,
mb: 0,
borderRadius: 'xs'
}
})),
[renderTypeList, renderList]
);
const renderTypeData = useMemo(
@@ -148,24 +159,37 @@ const NodeInputSelect = ({
<MyMenu
offset={[-0.5, 0.5]}
trigger="click"
size="mini"
Button={
<Button
leftIcon={
<MyIcon name={renderTypeData.icon as any} w={'14px'} color={'primary.600'} mr={-0.5} />
}
rightIcon={<MyIcon name={'common/select'} w={'0.8rem'} color={'myGray.500'} ml={-1} />}
rightIcon={
<MyIcon
name={'common/select'}
w={'0.8rem'}
color={'myGray.500'}
mx={-1}
sx={{
'button:hover &': {
color: 'primary.600'
}
}}
/>
}
variant={'grayBase'}
border={theme.borders.base}
borderColor={'myGray.200'}
borderRadius={'sm'}
px={'10px'}
py={'6px'}
px={'8px'}
fontSize={'mini'}
color={'myGray.600'}
h={'28px'}
bg={'myGray.100'}
minH={'28px'}
h={'28px'}
>
<Box fontWeight={'medium'}>{renderTypeData.title}</Box>
{renderTypeData.title}
</Button>
}
menuList={[{ children: filterMenuList }]}

View File

@@ -1,5 +1,6 @@
import Cookies, { CookieAttributes } from 'js-cookie';
import { useTranslation } from 'next-i18next';
import { LangEnum } from '../../../projects/app/src/web/common/utils/i18n';
const setCookie = (key: string, value: string, options?: CookieAttributes) => {
Cookies.set(key, value, options);
@@ -13,11 +14,13 @@ const LANG_KEY = 'NEXT_LOCALE';
export const useI18nLng = () => {
const { i18n } = useTranslation();
const languageMap: Record<string, string> = {
zh: 'zh',
'zh-CN': 'zh',
'zh-Hans': 'zh',
en: 'en',
'en-US': 'en'
zh: LangEnum.zh_CN,
'zh-CN': LangEnum.zh_CN,
'zh-Hans': LangEnum.zh_CN,
'zh-HK': LangEnum.zh_CN,
'zh-TW': LangEnum.zh_TW,
en: LangEnum.en,
'en-US': LangEnum.en
};
const onChangeLng = (lng: string) => {

View File

@@ -188,7 +188,8 @@ export function useScrollPagination<
pageSize = 10,
params = {},
EmptyTip
EmptyTip,
showErrorToast = true
}: {
refreshDeps?: any[];
scrollLoadType?: 'top' | 'bottom';
@@ -196,6 +197,7 @@ export function useScrollPagination<
pageSize?: number;
params?: Record<string, any>;
EmptyTip?: React.JSX.Element;
showErrorToast?: boolean;
}
) {
const { t } = useTranslation();
@@ -249,10 +251,12 @@ export function useScrollPagination<
setData((prevData) => (offset === 0 ? res.list : [...prevData, ...res.list]));
}
} catch (error: any) {
toast({
title: getErrText(error, t('common:core.chat.error.data_error')),
status: 'error'
});
if (showErrorToast) {
toast({
title: getErrText(error, t('common:core.chat.error.data_error')),
status: 'error'
});
}
console.log(error);
}

View File

@@ -1,8 +1,10 @@
import { useToast as uToast, UseToastOptions } from '@chakra-ui/react';
import { CSSProperties, useCallback } from 'react';
import { useTranslation } from 'next-i18next';
export const useToast = (props?: UseToastOptions & { containerStyle?: CSSProperties }) => {
const { containerStyle, ...toastProps } = props || {};
const { t } = useTranslation();
const toast = uToast({
position: 'top',
@@ -17,7 +19,11 @@ export const useToast = (props?: UseToastOptions & { containerStyle?: CSSPropert
const myToast = useCallback(
(options?: UseToastOptions) => {
if (options?.title || options?.description) {
toast(options);
toast({
...(options.title && { title: t(options.title as any) }),
...(options.description && { description: t(options.description as any) }),
...options
});
}
},
[props]

View File

@@ -1,5 +1,5 @@
{
"Role_setting": "Role setting",
"Role_setting": "Permission",
"Run": "Execute",
"Team Tags Set": "Team tags",
"Team_Tags": "Team tags",
@@ -14,6 +14,8 @@
"app.version_past": "Previously Published",
"app.version_publish_tips": "This version will be saved to the team cloud, synchronized with the entire team, and update the app version on all release channels.",
"app_detail": "Application Details",
"auto_execute": "Automatic execution",
"auto_execute_default_prompt_placeholder": "Default questions sent when executing automatically",
"chat_debug": "Chat Preview",
"chat_logs": "Conversation Logs",
"chat_logs_tips": "Logs will record the online, shared, and API (requires chatId) conversation records of this app.",
@@ -36,10 +38,10 @@
"document_quote_tip": "Usually used to accept user-uploaded document content (requires document parsing), and can also be used to reference other string data.",
"document_upload": "Document Upload",
"edit_app": "Edit Application",
"edit_info": "Edit Information",
"edit_info": "Edit",
"execute_time": "Execution Time",
"export_config_successful": "Configuration copied, some sensitive information automatically filtered. Please check for any remaining sensitive data.",
"export_configs": "Export Configurations",
"export_configs": "Export",
"feedback_count": "User Feedback",
"file_quote_link": "Files",
"file_recover": "File will overwrite current content",
@@ -50,7 +52,7 @@
"go_to_run": "Go to Execution",
"image_upload": "Image Upload",
"image_upload_tip": "How to activate model image recognition capabilities",
"import_configs": "Import Configurations",
"import_configs": "Import",
"import_configs_failed": "Import configuration failed, please ensure the configuration is correct!",
"import_configs_success": "Import Successful",
"initial_form": "initial state",
@@ -77,6 +79,7 @@
"move.hint": "After moving, the selected application/folder will inherit the permission settings of the new folder, and the original permission settings will become invalid.",
"move_app": "Move Application",
"not_json_file": "Please select a JSON file",
"open_auto_execute": "Enable automatic execution",
"open_vision_function_tip": "Models with icon switches have image recognition capabilities. \nAfter being turned on, the model will parse the pictures in the file link and automatically parse the pictures in the user's question (user question ≤ 500 words).",
"or_drag_JSON": "or drag in JSON file",
"paste_config": "Paste Configuration",

View File

@@ -4,6 +4,7 @@
"LLM_model_response_empty": "The model flow response is empty, please check whether the model flow output is normal.",
"chat_history": "Conversation History",
"chat_input_guide_lexicon_is_empty": "Lexicon not configured yet",
"chat_test_app": "Debug-{{name}}",
"citations": "{{num}} References",
"click_contextual_preview": "Click to see contextual preview",
"config_input_guide": "Set Up Input Guide",

View File

@@ -268,9 +268,11 @@
"core.app.Api request": "API Request",
"core.app.Api request desc": "Integrate into existing systems through API, or WeChat Work, Feishu, etc.",
"core.app.App intro": "App Introduction",
"core.app.Auto execute": "Auto execute",
"core.app.Chat Variable": "Chat Variable",
"core.app.Config schedule plan": "Configure Scheduled Execution",
"core.app.Config whisper": "Configure Voice Input",
"core.app.Config_auto_execute": "Click to configure automatic execution rules",
"core.app.Interval timer config": "Scheduled Execution Configuration",
"core.app.Interval timer run": "Scheduled Execution",
"core.app.Interval timer tip": "Can Execute App on Schedule",
@@ -428,7 +430,7 @@
"core.chat.logs.online": "Online Use",
"core.chat.logs.share": "External Link Call",
"core.chat.logs.team": "Team Space Chat",
"core.chat.logs.test": "Test",
"core.chat.logs.test": "Online debugging",
"core.chat.logs.wecom": "WeChat Work",
"core.chat.markdown.Edit Question": "Edit Question",
"core.chat.markdown.Quick Question": "Click to Ask Immediately",
@@ -732,11 +734,11 @@
"core.module.template.AI function": "AI Capability",
"core.module.template.AI response switch tip": "If you want the current node not to output content, you can turn off this switch. The content output by AI will not be displayed to the user, and you can manually use 'AI Response Content' for special processing.",
"core.module.template.AI support tool tip": "Models that support function calls can better use tool calls.",
"core.module.template.Basic Node": "Basic Function",
"core.module.template.Basic Node": "Basic",
"core.module.template.Query extension": "Question Optimization",
"core.module.template.System Plugin": "System Plugin",
"core.module.template.System Plugin": "System",
"core.module.template.System input module": "System Input",
"core.module.template.Team app": "Team App",
"core.module.template.Team app": "Team",
"core.module.template.Tool module": "Tool",
"core.module.template.UnKnow Module": "Unknown Module",
"core.module.template.ai_chat": "AI conversation",

View File

@@ -14,6 +14,9 @@
"app.version_past": "发布过",
"app.version_publish_tips": "该版本将被保存至团队云端,同步给整个团队,同时更新所有发布渠道的应用版本",
"app_detail": "应用详情",
"auto_execute": "自动执行",
"auto_execute_default_prompt_placeholder": "自动执行时,发送的默认问题",
"auto_execute_tip": "开启后用户进入对话界面将自动触发工作流。执行顺序1、对话开场白2、全局变量3、自动执行。",
"chat_debug": "调试预览",
"chat_logs": "对话日志",
"chat_logs_tips": "日志会记录该应用的在线、分享和 API需填写 chatId对话记录",
@@ -77,6 +80,7 @@
"move.hint": "移动后,所选应用/文件夹将继承新文件夹的权限设置,原先的权限设置失效。",
"move_app": "移动应用",
"not_json_file": "请选择JSON文件",
"open_auto_execute": "启用自动执行",
"open_vision_function_tip": "有图示开关的模型即拥有图片识别能力。若开启模型会解析文件链接里的图片并自动解析用户问题中的图片用户问题≤500字时生效。",
"or_drag_JSON": "或拖入JSON文件",
"paste_config": "粘贴配置",

View File

@@ -4,6 +4,7 @@
"LLM_model_response_empty": "模型流响应为空,请检查模型流输出是否正常",
"chat_history": "聊天记录",
"chat_input_guide_lexicon_is_empty": "还没有配置词库",
"chat_test_app": "调试-{{name}}",
"citations": "{{num}}条引用",
"click_contextual_preview": "点击查看上下文预览",
"config_input_guide": "配置输入引导",

View File

@@ -267,9 +267,11 @@
"core.app.Api request": "API 访问",
"core.app.Api request desc": "通过 API 接入到已有系统中,或企微、飞书等",
"core.app.App intro": "应用介绍",
"core.app.Auto execute": "自动执行",
"core.app.Chat Variable": "对话框变量",
"core.app.Config schedule plan": "配置定时执行",
"core.app.Config whisper": "配置语音输入",
"core.app.Config_auto_execute": "点击配置自动执行规则",
"core.app.Interval timer config": "定时执行配置",
"core.app.Interval timer run": "定时执行",
"core.app.Interval timer tip": "可定时执行应用",
@@ -427,7 +429,7 @@
"core.chat.logs.online": "在线使用",
"core.chat.logs.share": "外部链接调用",
"core.chat.logs.team": "团队空间对话",
"core.chat.logs.test": "试",
"core.chat.logs.test": "在线调试",
"core.chat.logs.wecom": "企业微信",
"core.chat.markdown.Edit Question": "编辑问题",
"core.chat.markdown.Quick Question": "点我立即提问",

View File

@@ -0,0 +1,169 @@
{
"Role_setting": "權限設定",
"Run": "執行",
"Team Tags Set": "團隊標籤",
"Team_Tags": "團隊標籤",
"ai_settings": "AI 設定",
"all_apps": "所有應用程式",
"app.Version name": "版本名稱",
"app.modules.click to update": "點選更新",
"app.modules.has new version": "有新版本",
"app.version_current": "目前版本",
"app.version_initial": "初始版本",
"app.version_name_tips": "版本名稱不能空白",
"app.version_past": "已發布過",
"app.version_publish_tips": "此版本將儲存至團隊雲端,同步給整個團隊,同時更新所有發布通道的應用程式版本",
"app_detail": "應用程式詳細資訊",
"chat_debug": "聊天預覽",
"chat_logs": "對話紀錄",
"chat_logs_tips": "紀錄會記錄此應用程式的線上、分享和 API需填寫 chatId對話紀錄",
"config_file_upload": "點選設定檔案上傳規則",
"confirm_copy_app_tip": "系統將為您建立一個相同設定的應用程式,但權限不會複製,請確認!",
"confirm_del_app_tip": "確認刪除【{{name}}】及其所有聊天紀錄?",
"confirm_delete_folder_tip": "確認刪除這個資料夾?將會刪除它底下所有應用程式及對應的對話紀錄,請確認!",
"copy_one_app": "建立副本",
"create_copy_success": "建立副本成功",
"create_empty_app": "建立空白應用程式",
"create_empty_plugin": "建立空白外掛",
"create_empty_workflow": "建立空白工作流程",
"cron.every_day": "每天執行",
"cron.every_month": "每月執行",
"cron.every_week": "每週執行",
"cron.interval": "間隔執行",
"dataset_search_tool_description": "呼叫「語意搜尋」和「全文搜尋」功能,從「知識庫」中尋找可能與問題相關的參考內容。優先呼叫這個工具來協助回答使用者的問題。",
"day": "日",
"document_quote": "文件引用",
"document_quote_tip": "通常用於接受使用者上傳的文件內容(這需要文件解析),也可以用於引用其他字串資料。",
"document_upload": "文件上傳",
"edit_app": "編輯應用程式",
"edit_info": "編輯資訊",
"execute_time": "執行時間",
"export_config_successful": "已複製設定,自動過濾部分敏感資訊,請注意檢查是否仍有敏感資料",
"export_configs": "匯出設定",
"feedback_count": "使用者回饋",
"file_quote_link": "檔案連結",
"file_recover": "檔案將會覆蓋目前內容",
"file_upload": "檔案上傳",
"file_upload_tip": "開啟後,可以上傳文件/圖片。文件保留 7 天,圖片保留 15 天。使用這個功能可能產生較多額外費用。為了確保使用體驗,使用這個功能時,請選擇上下文長度較大的 AI 模型。",
"global_variables_desc": "變數描述",
"go_to_chat": "前往對話",
"go_to_run": "前往執行",
"image_upload": "圖片上傳",
"image_upload_tip": "如何啟用模型圖片辨識功能",
"import_configs": "匯入設定",
"import_configs_failed": "匯入設定失敗,請確認設定是否正常!",
"import_configs_success": "匯入成功",
"initial_form": "初始狀態",
"interval.12_hours": "每 12 小時",
"interval.2_hours": "每 2 小時",
"interval.3_hours": "每 3 小時",
"interval.4_hours": "每 4 小時",
"interval.6_hours": "每 6 小時",
"interval.per_hour": "每小時",
"intro": "FastGPT 是一個基於大型語言模型的知識庫平臺,提供開箱即用的資料處理、向量檢索和視覺化 AI 工作流程編排等功能,讓您可以輕鬆開發和部署複雜的問答系統,而無需繁瑣的設定或配置。",
"llm_not_support_vision": "這個模型不支援圖片辨識",
"llm_use_vision": "圖片辨識",
"llm_use_vision_tip": "點選模型選擇後,可以看到模型是否支援圖片辨識以及控制是否啟用圖片辨識的功能。啟用圖片辨識後,模型會讀取檔案連結中的圖片內容,並且如果使用者問題少於 500 字,會自動解析使用者問題中的圖片。",
"logs_chat_user": "使用者",
"logs_empty": "還沒有紀錄喔~",
"logs_message_total": "訊息總數",
"logs_title": "標題",
"mark_count": "標記答案數量",
"module.Custom Title Tip": "這個標題會顯示在對話過程中",
"module.No Modules": "找不到外掛",
"module.type": "\"{{type}}\" 類型\n{{description}}",
"modules.Title is required": "模組名稱不能空白",
"month.unit": "號",
"move.hint": "移動後,所選應用程式/資料夾將會繼承新資料夾的權限設定,原先的權限設定將會失效。",
"move_app": "移動應用程式",
"not_json_file": "請選擇 JSON 檔案",
"open_vision_function_tip": "有圖示開關的模型即擁有圖片辨識功能。若開啟,模型會解析檔案連結中的圖片,並自動解析使用者問題中的圖片(使用者問題 ≤ 500 字時生效)。",
"or_drag_JSON": "或拖曳 JSON 檔案",
"paste_config": "貼上設定",
"permission.des.manage": "在寫入權限基礎上,可以設定發布通道、檢視對話紀錄、分配這個應用程式的權限",
"permission.des.read": "可以使用這個應用程式進行對話",
"permission.des.write": "可以檢視和編輯應用程式",
"plugin_cost_per_times": "{{cost}}/次",
"plugin_dispatch": "外掛呼叫",
"plugin_dispatch_tip": "賦予模型取得外部資料的能力,具體呼叫哪些外掛,將由模型自主決定,所有外掛都將以非串流模式執行。\n若選擇了外掛知識庫呼叫將自動作為一個特殊的外掛。",
"publish_channel": "發布通道",
"publish_success": "發布成功",
"saved_success": "儲存成功",
"search_app": "搜尋應用程式",
"setting_app": "應用程式設定",
"setting_plugin": "外掛設定",
"template.hard_strict": "嚴格問答範本",
"template.hard_strict_des": "在問答範本基礎上,對模型的回答做出更嚴格的要求。",
"template.qa_template": "問答範本",
"template.qa_template_des": "適合問答結構的知識庫,可以讓 AI 較為嚴格地按照預設內容回答",
"template.simple_robot": "簡易機器人",
"template.standard_strict": "標準嚴格範本",
"template.standard_strict_des": "在標準範本基礎上,對模型的回答做出更嚴格的要求。",
"template.standard_template": "標準範本",
"template.standard_template_des": "標準提示詞,用於結構不固定的知識庫。",
"templateMarket.Search_template": "搜尋範本",
"templateMarket.Template_market": "範本市集",
"templateMarket.Use": "使用",
"templateMarket.no_intro": "還沒有介紹~",
"templateMarket.templateTags.Image_generation": "影像生成",
"templateMarket.templateTags.Office_services": "辦公服務",
"templateMarket.templateTags.Recommendation": "推薦",
"templateMarket.templateTags.Roleplay": "角色扮演",
"templateMarket.templateTags.Web_search": "網路搜尋",
"templateMarket.templateTags.Writing": "文字創作",
"template_market": "範本市集",
"template_market_description": "在範本市集探索更多玩法,設定教學與使用指引,帶您理解並上手各種應用程式",
"template_market_empty_data": "找不到合適的範本",
"time_zone": "時區",
"tool_input_param_tip": "這個外掛正常執行需要設定相關資訊",
"transition_to_workflow": "轉換成工作流程",
"transition_to_workflow_create_new_placeholder": "建立新的應用程式,而不是修改目前應用程式",
"transition_to_workflow_create_new_tip": "轉換成工作流程後,將無法轉換回簡易模式,請確認!",
"type.All": "全部",
"type.Create http plugin tip": "透過 OpenAPI Schema 批次建立外掛,相容 GPTs 格式",
"type.Create one plugin tip": "可以自訂輸入和輸出的工作流程,通常用於封裝重複使用的工作流程",
"type.Create plugin bot": "建立外掛",
"type.Create simple bot": "建立簡易應用程式",
"type.Create simple bot tip": "透過填寫表單的方式,建立簡單的 AI 應用程式,適合新手",
"type.Create workflow bot": "建立工作流程",
"type.Create workflow tip": "透過低程式碼的方式,建立邏輯複雜的多輪對話 AI 應用程式,建議進階使用者使用",
"type.Http plugin": "HTTP 外掛",
"type.Plugin": "外掛",
"type.Simple bot": "簡易應用程式",
"type.Workflow bot": "工作流程",
"upload_file_max_amount": "最大檔案數量",
"upload_file_max_amount_tip": "單輪對話中最大上傳檔案數量",
"variable.select type_desc": "可以為工作流程定義全域變數,常用於暫存。賦值的方式包括:\n1. 從對話頁面的 query 參數取得。\n2. 透過 API 的 variables 物件傳遞。\n3. 透過【變數更新】節點進行賦值。",
"variable.textarea_type_desc": "允許使用者最多輸入 4000 字的對話框。",
"version.Revert success": "復原成功",
"version_back": "回到初始狀態",
"version_copy": "副本",
"version_initial_copy": "副本 - 初始狀態",
"vision_model_title": "圖片辨識功能",
"week.Friday": "星期五",
"week.Monday": "星期一",
"week.Saturday": "星期六",
"week.Sunday": "星期日",
"week.Thursday": "星期四",
"week.Tuesday": "星期二",
"week.Wednesday": "星期三",
"workflow.Input guide": "填寫說明",
"workflow.file_url": "檔案連結",
"workflow.form_input": "表單輸入",
"workflow.form_input_description_placeholder": "例如:\n補充您的資訊",
"workflow.form_input_tip": "這個模組可以設定多種輸入,引導使用者輸入特定內容。",
"workflow.input_description_tip": "您可以新增一段說明文字,用來向使用者說明需要輸入的內容",
"workflow.read_files": "檔案解析",
"workflow.read_files_result": "檔案解析結果",
"workflow.read_files_result_desc": "檔案原文,由檔案名稱和檔案內容組成,多個檔案之間透過橫線分隔。",
"workflow.read_files_tip": "解析本輪對話上傳的檔案,並回傳對應檔案內容",
"workflow.select_description": "說明文字",
"workflow.select_description_placeholder": "例如:\n冰箱裡是否有番茄",
"workflow.select_description_tip": "您可以新增一段說明文字,用來向使用者說明每個選項代表的意義。",
"workflow.select_result": "選擇結果",
"workflow.template.communication": "通訊",
"workflow.user_file_input": "檔案連結",
"workflow.user_file_input_desc": "使用者上傳的檔案和圖片連結",
"workflow.user_select": "使用者選擇",
"workflow.user_select_tip": "這個模組可以設定多個選項,供對話時選擇。不同選項可以導向不同的工作流程支線"
}

View File

@@ -0,0 +1,50 @@
{
"AI_input_is_empty": "傳送至 AI 節點的內容為空",
"Delete_all": "清除所有詞彙",
"LLM_model_response_empty": "模型流程回應為空,請檢查模型流程輸出是否正常",
"chat_history": "對話紀錄",
"chat_input_guide_lexicon_is_empty": "尚未設定詞彙庫",
"citations": "{{num}} 筆引用",
"click_contextual_preview": "點選檢視上下文預覽",
"config_input_guide": "設定輸入導引",
"config_input_guide_lexicon": "設定詞彙庫",
"config_input_guide_lexicon_title": "設定詞彙庫",
"content_empty": "無內容",
"contextual": "{{num}} 筆上下文",
"contextual_preview": "上下文預覽 {{num}} 筆",
"csv_input_lexicon_tip": "僅支援 CSV 批次匯入,點選下載範本",
"custom_input_guide_url": "自訂詞彙庫網址",
"dataset_quote_type error": "知識庫引用類型錯誤,正確類型:{ datasetId: string }[]",
"delete_all_input_guide_confirm": "確定要清除輸入導引詞彙庫嗎?",
"empty_directory": "此目錄中已無項目可選~",
"file_amount_over": "超出檔案數量上限 {{max}}",
"file_input": "檔案輸入",
"file_input_tip": "可透過「外掛程式啟動」節點的「檔案連結」取得對應檔案的連結",
"in_progress": "進行中",
"input_guide": "輸入導引",
"input_guide_lexicon": "詞彙庫",
"input_guide_tip": "您可以設定一些預設問題。當使用者輸入問題時,系統會從這些預設問題中提供相關問題作為提示。",
"input_placeholder_phone": "請輸入問題",
"insert_input_guide,_some_data_already_exists": "偵測到重複資料,已自動過濾,共插入 {{len}} 筆資料",
"is_chatting": "對話進行中...請稍候",
"items": "筆",
"module_runtime_and": "模組執行總時間",
"multiple_AI_conversations": "多組 AI 對話",
"new_input_guide_lexicon": "新增詞彙庫",
"no_workflow_response": "無工作流程資料",
"not_select_file": "尚未選取檔案",
"plugins_output": "外掛程式輸出",
"question_tip": "由上至下,各個模組的回應順序",
"response.child total points": "子工作流程點數消耗",
"response.dataset_concat_length": "合併總數",
"response.node_inputs": "節點輸入",
"select": "選取",
"select_file": "上傳檔案",
"select_file_img": "上傳檔案 / 圖片",
"select_img": "上傳圖片",
"stream_output": "串流輸出",
"unsupported_file_type": "不支援的檔案類型",
"upload": "上傳",
"view_citations": "檢視引用",
"web_site_sync": "網站同步"
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
{
"Enable": "啟用",
"collection.Create update time": "建立/更新時間",
"collection.Training type": "分段模式",
"collection_tags": "集合標籤",
"common_dataset": "通用資料集",
"common_dataset_desc": "可透過匯入檔案、網頁連結或手動輸入的方式建立資料集",
"confirm_to_rebuild_embedding_tip": "確定要為資料集切換索引嗎?\n切換索引是一個重要的操作需要對您資料集內所有資料重新建立索引可能需要較長時間請確保帳號內剩餘點數充足。\n\n此外您還需要注意修改使用此資料集的應用程式避免與其他索引模型資料集混用。",
"custom_data_process_params": "自訂",
"custom_data_process_params_desc": "自訂資料處理規則",
"data.ideal_chunk_length": "理想分塊長度",
"data_process_params": "處理參數",
"data_process_setting": "資料處理設定",
"dataset.no_collections": "尚無資料集",
"dataset.no_tags": "尚無標籤",
"external_file": "外部檔案庫",
"external_file_dataset_desc": "可以從外部檔案庫匯入檔案建立資料集,檔案不會進行二次儲存",
"external_id": "檔案讀取識別碼",
"external_read_url": "外部預覽網址",
"external_read_url_tip": "可以設定您檔案庫的讀取網址,方便對使用者進行讀取權限驗證。目前可使用 {{fileId}} 變數來代表外部檔案識別碼。",
"external_url": "檔案存取網址",
"file_model_function_tip": "用於增強索引和問答生成",
"filename": "檔案名稱",
"folder_dataset": "資料夾",
"ideal_chunk_length": "理想分塊長度",
"ideal_chunk_length_tips": "依結束符號進行分段,並將多個分段組成一個分塊,此值決定了分塊的預估大小,可能會有上下浮動。",
"import.Auto mode Estimated Price Tips": "需呼叫文字理解模型,將消耗較多 AI 點數:{{price}} 點數 / 1K tokens",
"import.Embedding Estimated Price Tips": "僅使用索引模型,消耗少量 AI 點數:{{price}} 點數 / 1K tokens",
"move.hint": "移動後,所選資料集/資料夾將繼承新資料夾的權限設定,原先的權限設定將失效。",
"permission.des.manage": "可管理整個資料集的資料和資訊",
"permission.des.read": "可檢視資料集內容",
"permission.des.write": "可新增和變更資料集內容",
"rebuild_embedding_start_tip": "切換索引模型任務已開始",
"rebuilding_index_count": "重建中索引數量:{{count}}",
"tag.Add New": "新增",
"tag.Add_new_tag": "新增標籤",
"tag.Edit_tag": "編輯標籤",
"tag.add": "建立",
"tag.cancel": "取消",
"tag.delete_tag_confirm": "確定要刪除標籤嗎?",
"tag.manage": "標籤管理",
"tag.searchOrAddTag": "搜尋或新增標籤",
"tag.tags": "標籤",
"tag.total_tags": "共 {{total}} 個標籤",
"the_knowledge_base_has_indexes_that_are_being_trained_or_being_rebuilt": "資料集有索引正在訓練或重建中",
"training_mode": "分段模式",
"website_dataset": "網站同步",
"website_dataset_desc": "網站同步功能讓您可以直接使用網頁連結建立資料集"
}

View File

@@ -0,0 +1,18 @@
{
"bucket_chat": "對話檔案",
"bucket_file": "知識庫檔案",
"click_to_view_raw_source": "點選檢視原始來源",
"file_name": "檔案名稱",
"file_size": "檔案大小",
"release_the_mouse_to_upload_the_file": "放開滑鼠以上傳檔案",
"select_and_drag_file_tip": "點選或拖曳檔案至此處上傳",
"select_file_amount_limit": "最多可選擇 {{max}} 個檔案",
"some_file_count_exceeds_limit": "已超過 {{maxCount}} 個檔案上限,系統已自動截斷",
"some_file_size_exceeds_limit": "部分檔案超過 {{maxSize}} 大小限制,已自動過濾",
"support_file_type": "支援 {{fileType}} 格式的檔案",
"support_max_count": "最多可支援 {{maxCount}} 個檔案",
"support_max_size": "單一檔案大小上限為 {{maxSize}}",
"upload_failed": "上傳失敗",
"reached_max_file_count": "已達檔案數量上限",
"upload_error_description": "單次僅支援上傳多個檔案或一個資料夾"
}

View File

@@ -0,0 +1,19 @@
{
"Chinese_ip_tip": "偵測到您使用中國大陸 IP點選這裡前往中國大陸版本。",
"Login": "登入",
"forget_password": "忘記密碼?",
"login_failed": "登入失敗",
"login_success": "登入成功",
"no_remind": "不再提醒",
"password_condition": "密碼最多 60 個字元",
"policy_tip": "使用即代表您同意我們的",
"privacy": "隱私權政策",
"redirect": "跳轉",
"register": "註冊帳號",
"root_password_placeholder": "root 使用者密碼為環境變數 DEFAULT_ROOT_PSW 的值",
"terms": "服務條款",
"use_root_login": "使用 root 使用者登入",
"agree": "同意",
"cookies_tip": "本網站使用 cookies 提供更好的服務體驗。繼續使用即表示您同意我們的 Cookie 政策。",
"privacy_policy": "隱私權政策"
}

View File

@@ -0,0 +1,41 @@
{
"app_key_tips": "這些金鑰已與目前的應用程式連結。詳細使用方式請參閱說明文件。",
"basic_info": "基本資訊",
"config": "顯示設定",
"copy_link_hint": "請將下方連結複製到指定位置",
"create_api_key": "建立新金鑰",
"create_link": "建立連結",
"edit_api_key": "編輯金鑰細節",
"edit_feishu_bot": "編輯 Lark 聊天機器人",
"edit_link": "編輯",
"feishu_api": "Lark API",
"feishu_bot": "Lark 聊天機器人",
"feishu_bot_desc": "透過 API 直接連結 Lark 聊天機器人",
"key_alias": "金鑰別名,僅供顯示",
"key_tips": "您可以使用 API 金鑰存取特定介面(無法存取應用程式,需使用應用程式內建的 API 金鑰)",
"link_name": "分享連結名稱",
"new_feishu_bot": "新增 Lark 聊天機器人",
"official_account.create_modal_title": "建立微信公眾號整合",
"official_account.desc": "透過 API 直接連結微信公眾號",
"official_account.edit_modal_title": "編輯微信公眾號整合",
"official_account.name": "微信公眾號整合",
"official_account.params": "微信公眾號參數",
"private_config": "顯示設定",
"publish_name": "名稱",
"qpm_is_empty": "QPM 不可為空白",
"qpm_tips": "每個 IP 每分鐘最高查詢次數",
"quote_content": "引用內容",
"request_address": "請求網址",
"show_node": "即時執行狀態",
"show_origin_content": "檢視原始來源",
"show_share_link_modal_title": "開始使用",
"token_auth": "身分驗證",
"token_auth_tips": "身分驗證伺服器網址。若有提供,每次對話前將向指定伺服器傳送驗證請求。",
"token_auth_use_cases": "檢視身分驗證指南",
"wecom.api": "企業微信 API",
"wecom.bot": "企業微信聊天機器人",
"wecom.bot_desc": "透過 API 直接連結企業微信聊天機器人",
"wecom.create_modal_title": "建立企業微信聊天機器人",
"wecom.edit_modal_title": "編輯企業微信聊天機器人",
"wecom.title": "發布至企業微信聊天機器人"
}

View File

@@ -0,0 +1,116 @@
{
"bill.balance": "餘額",
"bill.buy_plan": "購買方案",
"bill.contact_customer_service": "聯絡客服",
"bill.conversion": "兌換",
"bill.convert_error": "兌換失敗",
"bill.convert_success": "兌換成功",
"bill.current_token_price": "目前點數價格",
"bill.not_need_invoice": "餘額支付無法開立發票",
"bill.price": "價格",
"bill.renew_plan": "續訂方案",
"bill.standard_valid_tip": "方案使用規則:系統會優先使用較高等級的方案,原未使用完的方案將延後生效",
"bill.token_expire_1year": "點數有效期為一年",
"bill.tokens": "點數",
"bill.use_balance": "使用餘額",
"bill.use_balance_hint": "由於系統升級,原「自動從餘額扣款續訂」模式已取消,餘額儲值入口已關閉。您的餘額可用於購買點數",
"bill.valid_time": "生效時間",
"bill.you_can_convert": "您可兌換",
"bill.yuan": "元",
"bill_and_invoices": "帳單與發票",
"bind_inform_account_error": "綁定通知帳號失敗",
"bind_inform_account_success": "綁定通知帳號成功",
"delete.admin_failed": "刪除管理員失敗",
"delete.admin_success": "刪除管理員成功",
"delete.failed": "刪除失敗",
"delete.success": "刪除成功",
"has_chosen": "已選擇",
"individuation": "個人化",
"login.error": "登入失敗",
"login.password_condition": "密碼最多可輸入 60 個字元",
"login.success": "登入成功",
"name": "名稱",
"notice": "通知",
"notification.Bind Notification Pipe Hint": "請綁定通知接收帳號,以確保您能正常接收方案到期提醒等通知,保障您的服務正常運作。",
"notification.remind_owner_bind": "請提醒建立者綁定通知帳號",
"operations": "操作",
"owner": "擁有者",
"password.code_required": "驗證碼不能空白",
"password.code_send_error": "驗證碼傳送失敗",
"password.code_sended": "驗證碼已傳送",
"password.confirm": "確認密碼",
"password.email_phone_error": "電子郵件/手機號碼格式錯誤",
"password.email_phone_void": "電子郵件/手機號碼不能空白",
"password.get_code": "取得驗證碼",
"password.get_code_again": "秒後重新取得",
"password.new_password": "新密碼4 至 20 字元)",
"password.not_match": "兩次輸入的密碼不相符",
"password.password_condition": "密碼長度需介於 4 至 20 字元之間",
"password.password_required": "密碼不能空白",
"password.retrieve": "找回密碼",
"password.retrieved": "密碼已找回",
"password.retrieved_account": "找回 {{account}} 帳號",
"password.to_login": "前往登入",
"password.verification_code": "驗證碼",
"permission.Manage": "管理員",
"permission.Manage tip": "團隊管理員,擁有完整權限",
"permission.Read": "唯讀",
"permission.Read desc": "成員僅能閱讀相關資源,無法建立新資源",
"permission.Write": "可寫入",
"permission.Write tip": "除了可讀取資源外,還可以建立新的資源",
"permission.only_collaborators": "僅協作者可存取",
"permission.team_read": "團隊可存取",
"permission.team_write": "團隊可編輯",
"permission_des.manage": "可建立資源、邀請及刪除成員",
"permission_des.read": "成員僅能閱讀相關資源,無法建立新資源",
"permission_des.write": "除了可讀取資源外,還可以建立新的資源",
"permissions": "權限",
"personal_information": "個人資料",
"personalization": "個人化",
"promotion_records": "推廣紀錄",
"register.confirm": "確認註冊",
"register.register_account": "註冊 {{account}} 帳號",
"register.success": "註冊成功",
"register.to_login": "已有帳號?前往登入",
"search_user": "搜尋使用者名稱",
"sign_out": "登出",
"synchronization.button": "立即同步",
"synchronization.placeholder": "請輸入同步標籤",
"synchronization.title": "填寫標籤同步連結,點選同步按鈕即可同步",
"team.Add manager": "新增管理員",
"team.add_collaborator": "新增協作者",
"team.add_writer": "新增可寫入成員",
"team.avatar_and_name": "頭像與名稱",
"team.belong_to_group": "所屬成員群組",
"team.group.avatar": "群組頭像",
"team.group.create": "建立群組",
"team.group.create_failed": "建立群組失敗",
"team.group.default_group": "預設群組",
"team.group.delete_confirm": "確認刪除群組?",
"team.group.edit": "編輯群組",
"team.group.edit_info": "編輯資訊",
"team.group.group": "群組",
"team.group.keep_admin": "保留管理員權限",
"team.group.manage_member": "管理成員",
"team.group.manage_tip": "可以邀請成員、刪除成員、建立群組、管理所有群組,以及為群組和成員分配權限",
"team.group.members": "成員",
"team.group.name": "群組名稱",
"team.group.permission.manage": "管理員",
"team.group.permission.write": "工作臺/知識庫建立",
"team.group.permission_tip": "單獨設定權限的成員,將依照個人權限設定,不再受群組權限影響。\n若成員屬於多個權限群組該成員的權限將會合併。",
"team.group.role.admin": "管理員",
"team.group.role.member": "成員",
"team.group.role.owner": "擁有者",
"team.group.search_placeholder": "搜尋成員/群組名稱",
"team.group.set_as_admin": "設為管理員",
"team.group.toast.can_not_delete_owner": "無法刪除擁有者,請先轉移擁有權",
"team.group.transfer_owner": "轉移擁有者",
"team.manage_collaborators": "管理協作者",
"team.no_collaborators": "目前沒有協作者",
"team.write_role_member": "可寫入權限",
"usage.feishu": "飛書",
"usage.official_account": "公眾號",
"usage.share": "分享連結",
"usage.wecom": "企業微信",
"usage_record": "使用紀錄"
}

View File

@@ -0,0 +1,198 @@
{
"Array_element": "陣列元素",
"Array_element_index": "索引",
"Code": "程式碼",
"Confirm_sync_node": "將會更新至最新的節點設定,不存在於範本中的欄位將會被刪除(包含所有自訂欄位)。\n如果欄位比較複雜建議您先複製一份節點再更新原來的節點以便複製參數。",
"Node.Open_Node_Course": "開啟節點教學課程",
"Node_variables": "節點變數",
"Quote_prompt_setting": "引用提示詞設定",
"Variable.Variable type": "變數類型",
"Variable_name": "變數名稱",
"add_new_input": "新增輸入",
"add_new_output": "新增輸出",
"append_application_reply_to_history_as_new_context": "將應用程式的回覆附加到歷史紀錄中,作為新的脈絡",
"application_call": "應用程式呼叫",
"assigned_reply": "指定回覆",
"can_not_loop": "這個節點不能迴圈。",
"choose_another_application_to_call": "選擇另一個應用程式來呼叫",
"classification_result": "分類結果",
"code.Reset template": "重設範本",
"code.Reset template confirm": "確定要重設程式碼範本嗎?這將會把所有輸入和輸出重設為範本值。請儲存您目前的程式碼。",
"code_execution": "程式碼執行",
"collection_metadata_filter": "資料集詮釋資料篩選器",
"complete_extraction_result": "完整擷取結果",
"complete_extraction_result_description": "一個 JSON 字串,例如:{\"name\":\"YY\",\"Time\":\"2023/7/2 18:00\"}",
"concatenation_result": "串接結果",
"concatenation_text": "串接文字",
"condition_checker": "條件檢查器",
"confirm_delete_field_tip": "確定要刪除這個欄位嗎?",
"contains": "包含",
"content_to_retrieve": "要擷取的內容",
"content_to_search": "要搜尋的內容",
"contextMenu.addComment": "新增註解",
"context_menu.add_comment": "新增註解",
"create_link_error": "建立連結發生錯誤",
"custom_feedback": "自訂回饋",
"custom_input": "自訂輸入",
"dataset_quote_role": "角色",
"dataset_quote_role_system_option_desc": "歷史紀錄連貫優先(建議)",
"dataset_quote_role_tip": "設定為 System 時,會將知識庫引用內容放置到系統訊息中,可以確保歷史紀錄的連貫性,但約束效果可能不佳。\n設定為 User 時,會將知識庫引用內容放置到使用者訊息中,並且需要指定 {{question}} 變數位置。會對歷史紀錄連貫性有一定影響,但通常約束效果較佳。",
"dataset_quote_role_user_option_desc": "強約束優先",
"dynamic_input_description": "接收前一個節點的輸出值作為變數,這些變數可以被 Laf 請求參數使用。",
"dynamic_input_description_concat": "可以引用其他節點的輸出作為文字串接的變數,輸入 / 叫出變數清單",
"edit_input": "編輯輸入",
"edit_output": "編輯輸出",
"end_with": "結尾為",
"enter_comment": "輸入註解",
"error_info_returns_empty_on_success": "程式碼執行錯誤資訊,成功時回傳空值",
"execute_a_simple_script_code_usually_for_complex_data_processing": "執行一段簡單的腳本程式碼,通常用於複雜的資料處理。",
"execute_different_branches_based_on_conditions": "根據條件執行不同的分支。",
"execution_error": "執行錯誤",
"extraction_requirements_description": "擷取需求描述",
"extraction_requirements_description_detail": "提供 AI 相對應的背景知識或需求描述,引導 AI 更好地完成任務。\\n這個輸入框可以使用全域變數。",
"extraction_requirements_placeholder": "例如:\\n1. 目前時間為:{{cTime}}。您是一位實驗室預約助理,您的任務是協助使用者預約實驗室,從文字中取得對應的預約資訊。\\n2. 您是 Google 搜尋助理,需要從文字中擷取出合適的搜尋詞。",
"feedback_text": "回饋文字",
"field_description": "欄位描述",
"field_description_placeholder": "描述這個輸入欄位的功能,如果是工具呼叫參數,這個描述會影響模型產生的品質",
"field_name_already_exists": "欄位名稱已存在",
"field_required": "必填",
"field_used_as_tool_input": "作為工具呼叫參數",
"filter_description": "目前支援標籤和建立時間篩選,需按照以下格式填寫:\n{\n \"tags\": {\n \"$and\": [\"標籤 1\",\"標籤 2\"],\n \"$or\": [\"當有 $and 標籤時,$and 才會生效,$or 不會生效\"]\n },\n \"createTime\": {\n \"$gte\": \"YYYY-MM-DD HH:mm 格式,資料集的建立時間大於這個時間\",\n \"$lte\": \"YYYY-MM-DD HH:mm 格式,資料集的建立時間小於這個時間,可以和 $gte 一起使用\"\n }\n}",
"form_input_result": "使用者完整輸入結果",
"form_input_result_tip": "一個包含完整結果的物件",
"full_field_extraction": "欄位完整擷取",
"full_field_extraction_description": "當所有欄位都被完整擷取時回傳 true模型擷取或使用預設值都算成功",
"full_response_data": "完整回應資料",
"greater_than": "大於",
"greater_than_or_equal_to": "大於或等於",
"http_extract_output": "輸出欄位擷取",
"http_extract_output_description": "可以透過 JSONPath 語法來擷取回應值中的指定欄位",
"http_raw_response_description": "HTTP 請求的原始回應。僅接受字串或 JSON 類型回應資料。",
"http_request": "HTTP 請求",
"http_request_error_info": "HTTP 請求錯誤資訊,成功時回傳空值",
"ifelse.Input value": "輸入值",
"ifelse.Select value": "選擇值",
"input_description": "欄位描述",
"input_variable_list": "輸入 / 叫出變數清單",
"intro_assigned_reply": "這個模組可以直接回覆指定的內容。常用於引導、提示。非字串內容傳入時,會轉換成字串輸出。",
"intro_custom_feedback": "當這個模組被觸發時,會在目前的對話紀錄中新增一條回饋。可以用於自動記錄對話效果等等。",
"intro_custom_plugin_output": "自訂設定外部輸出,使用外掛程式時,只顯示自訂設定的輸出",
"intro_http_request": "可以傳送 HTTP 請求,執行更複雜的操作(網路搜尋、資料庫查詢等等)",
"intro_knowledge_base_search_merge": "可以合併多個知識庫搜尋結果並輸出。使用 RRF 合併方法進行最終排序輸出。",
"intro_laf_function_call": "可以呼叫 Laf 帳號下的雲端函式。",
"intro_loop": "可以輸入一個陣列,陣列中的元素會各自執行迴圈主體,並將所有結果以陣列形式輸出。",
"intro_plugin_input": "可以設定外掛程式需要的輸入,並利用這些輸入來執行外掛程式",
"intro_question_classification": "根據使用者的歷史紀錄和目前問題判斷這次提問的類型。可以新增多個問題類型,以下是一個範例:\n類型 1打招呼\n類型 2關於產品「使用方式」的問題\n類型 3關於產品「購買」的問題\n類型 4其他問題",
"intro_question_optimization": "使用問題最佳化功能,可以提升知識庫連續對話時的搜尋精準度。使用這個功能後,會先利用 AI 根據脈絡建構一個或多個新的檢索詞彙,這些詞彙更有利於知識庫搜尋。這個模組已內建於知識庫搜尋模組中,如果您只進行一次知識庫搜尋,可以直接使用知識庫內建的自動完成功能。",
"intro_text_concatenation": "可以處理並輸出固定的或傳入的文字。非字串類型的資料會被轉換成字串類型。",
"intro_text_content_extraction": "可以從文字中擷取指定的資料例如SQL 敘述、搜尋關鍵字、程式碼等等",
"intro_tool_call_termination": "這個模組需要搭配工具呼叫使用。當這個模組被執行時這次的工具呼叫會被強制終止AI 不會再根據工具呼叫結果回答問題。",
"intro_tool_params_config": "這個模組需要搭配工具呼叫使用。\n您可以自訂工具呼叫參數並傳送到下游節點使用",
"is_empty": "為空",
"is_equal_to": "等於",
"is_not_empty": "不為空",
"is_not_equal": "不等於",
"is_tool_output_label": "作為工具回應",
"judgment_result": "判斷結果",
"knowledge_base_reference": "知識庫引用",
"knowledge_base_search_merge": "知識庫搜尋合併",
"laf_function_call_test": "Laf 函式呼叫(測試)",
"length_equal_to": "長度等於",
"length_greater_than": "長度大於",
"length_greater_than_or_equal_to": "長度大於或等於",
"length_less_than": "長度小於",
"length_less_than_or_equal_to": "長度小於或等於",
"length_not_equal_to": "長度不等於",
"less_than": "小於",
"less_than_or_equal_to": "小於或等於",
"loop": "批次執行",
"loop_body": "迴圈主體",
"loop_end": "迴圈結束",
"loop_input_array": "陣列",
"loop_result": "陣列執行結果",
"loop_start": "迴圈開始",
"loop_start_tip": "未輸入陣列",
"max_dialog_rounds": "最多攜帶幾輪對話紀錄",
"max_tokens": "最大 Token 數",
"mouse_priority": "滑鼠優先\n- 按下左鍵拖曳畫布\n- 按住 Shift 鍵並點選左鍵可批次選取",
"new_context": "新的脈絡",
"not_contains": "不包含",
"only_the_reference_type_is_supported": "僅支援引用類型",
"optional_value_type": "可選的資料類型",
"optional_value_type_tip": "可以指定一或多個資料類型,使用者在動態新增欄位時,只能選擇已設定的類型",
"pan_priority": "觸控板優先\n- 點選可批次選取\n- 使用兩指移動畫布",
"pass_returned_object_as_output_to_next_nodes": "將程式碼中 return 的物件作為輸出,傳遞給後續的節點。變數名稱需要對應 return 的鍵值",
"plugin.Instruction_Tip": "您可以設定一段說明來解釋這個外掛程式的用途。每次使用外掛程式前,都會顯示這段說明。支援標準 Markdown 語法。",
"plugin.Instructions": "使用說明",
"plugin.global_file_input": "檔案連結(已淘汰)",
"plugin_file_abandon_tip": "外掛程式全域檔案上傳功能已淘汰,請儘速調整。您可以透過外掛程式輸入,新增圖片類型輸入來達成相關功能。",
"plugin_input": "外掛程式輸入",
"plugin_output_tool": "外掛程式作為工具執行時,這個欄位是否作為工具的回應結果",
"question_classification": "問題分類",
"question_optimization": "問題最佳化",
"quote_content_placeholder": "可以自訂引用內容的結構,以便更好地適應不同場景。可以使用一些變數來設定範本\n{{q}} - 主要內容\n{{a}} - 輔助資料\n{{source}} - 來源名稱\n{{sourceId}} - 來源 ID\n{{index}} - 第 n 個引用",
"quote_content_tip": "可以自訂引用內容的結構,以便更好地適應不同場景。可以使用一些變數來設定範本\n{{q}} - 主要內容\n{{a}} - 輔助資料\n{{source}} - 來源名稱\n{{sourceId}} - 來源 ID\n{{index}} - 第 n 個引用\n它們都是選用的以下是預設值\n{{default}}",
"quote_num": "引用數量",
"quote_prompt_tip": "可以使用 {{quote}} 來插入引用內容範本,使用 {{question}} 來插入問題Role=user。\n以下是預設值\n{{default}}",
"quote_role_system_tip": "請注意從「引用範本提示詞」中移除 {{question}} 變數",
"quote_role_user_tip": "請注意在「引用範本提示詞」中加入 {{question}} 變數",
"raw_response": "原始回應",
"regex": "正規表達式",
"reply_text": "回覆文字",
"request_error": "請求錯誤",
"response.Code log": "程式碼日誌",
"response.Custom inputs": "自訂輸入",
"response.Custom outputs": "自訂輸出",
"response.Error": "錯誤訊息",
"response.Read file result": "檔案解析結果預覽",
"response.read files": "解析的檔案",
"select_an_application": "選擇一個應用程式",
"select_another_application_to_call": "可以選擇另一個應用程式來呼叫",
"special_array_format": "特殊陣列格式,搜尋結果為空時,回傳空陣列。",
"start_with": "開頭為",
"target_fields_description": "由「描述」和「鍵值」組成一個目標欄位,可以擷取多個目標欄位",
"template.ai_chat": "AI 對話",
"template.ai_chat_intro": "AI 大型語言模型對話",
"template.dataset_search": "知識庫搜尋",
"template.dataset_search_intro": "使用「語意搜尋」和「全文搜尋」功能,從「知識庫」中尋找可能與問題相關的參考內容",
"template.forbid_stream": "停用串流輸出",
"template.forbid_stream_desc": "強制設定巢狀執行的應用程式以非串流模式執行",
"template.plugin_output": "外掛程式輸出",
"template.plugin_start": "外掛程式啟動",
"template.system_config": "系統設定",
"template.tool_call": "工具呼叫",
"template.tool_call_intro": "透過 AI 模型自動選擇一或多個功能區塊進行呼叫,也可以呼叫外掛程式。",
"template.workflow_start": "流程開始",
"text_concatenation": "文字串接",
"text_content_extraction": "文字內容擷取",
"text_to_extract": "要擷取的文字",
"these_variables_will_be_input_parameters_for_code_execution": "這些變數會作為程式碼執行的輸入參數",
"tool_call_termination": "工具呼叫終止",
"tool_custom_field": "自訂工具變數",
"tool_field": "工具參數設定",
"tool_input": "工具參數",
"tool_params.enum_placeholder": "apple \npeach \nwatermelon",
"tool_params.enum_values": "列舉值(選用)",
"tool_params.enum_values_tip": "列出這個欄位可能的值,每行一個",
"tool_params.params_description": "參數描述",
"tool_params.params_description_placeholder": "姓名年齡SQL 敘述…",
"tool_params.params_name": "參數名稱",
"tool_params.params_name_placeholder": "name/age/sql",
"tool_params.tool_params_result": "參數設定結果",
"trigger_after_application_completion": "將會在應用程式完全結束後觸發",
"update_link_error": "更新連結發生錯誤",
"update_specified_node_output_or_global_variable": "可以更新指定節點的輸出值或更新全域變數",
"use_user_id": "使用者 ID",
"user_form_input_config": "表單設定",
"user_form_input_description": "描述",
"user_form_input_name": "標題",
"user_question": "使用者問題",
"user_question_tool_desc": "使用者輸入的問題(問題需要完善)",
"variable_description": "變數描述",
"variable_picker_tips": "可以輸入節點名稱或變數名稱搜尋",
"variable_update": "變數更新",
"workflow.My edit": "我的編輯",
"workflow.Switch_success": "切換成功",
"workflow.Team cloud": "團隊雲端",
"workflow.exit_tips": "您的變更尚未儲存,「直接結束」將不會儲存您的編輯紀錄。"
}

View File

@@ -221,7 +221,6 @@ const Button = defineStyleConfig({
boxShadow: '0px 0px 1px 0px rgba(19, 51, 107, 0.08), 0px 1px 2px 0px rgba(19, 51, 107, 0.05)',
_hover: {
color: 'red.600',
background: 'red.1',
borderColor: 'red.300'
},
_active: {
@@ -251,6 +250,16 @@ const Button = defineStyleConfig({
color: 'red.600'
}
},
grayGhost: {
color: 'myGray.500',
fontWeight: '500',
p: 0,
bg: 'transparent',
transition: 'background 0.1s',
_hover: {
bg: 'myGray.05'
}
},
transparentBase: {
color: 'myGray.800',
fontWeight: '500',
@@ -570,6 +579,43 @@ const Table = tableMultiStyle({
}
})
},
variants: {
workflow: {
table: {
bg: 'white'
},
thead: {
tr: {
th: {
p: '0',
px: 4,
bg: 'myGray.50',
borderRadius: 'none !important',
borderBottom: 'none',
height: '32px',
fontSize: 'mini',
fontWeight: 'medium'
}
}
},
tbody: {
tr: {
td: {
p: '0',
px: 4,
fontSize: 'xs',
borderBottom: 'base',
height: '40px'
},
'&:last-child': {
td: {
borderBottom: 'none'
}
}
}
}
}
},
defaultProps: {
size: 'md'
}

View File

@@ -1,13 +1,13 @@
import 'i18next';
import common from '../i18n/zh/common.json';
import dataset from '../i18n/zh/dataset.json';
import app from '../i18n/zh/app.json';
import file from '../i18n/zh/file.json';
import publish from '../i18n/zh/publish.json';
import workflow from '../i18n/zh/workflow.json';
import user from '../i18n/zh/user.json';
import chat from '../i18n/zh/chat.json';
import login from '../i18n/zh/login.json';
import common from '../i18n/zh-CN/common.json';
import dataset from '../i18n/zh-CN/dataset.json';
import app from '../i18n/zh-CN/app.json';
import file from '../i18n/zh-CN/file.json';
import publish from '../i18n/zh-CN/publish.json';
import workflow from '../i18n/zh-CN/workflow.json';
import user from '../i18n/zh-CN/user.json';
import chat from '../i18n/zh-CN/chat.json';
import login from '../i18n/zh-CN/login.json';
export interface I18nNamespaces {
common: typeof common;

View File

@@ -5,8 +5,8 @@
module.exports = {
i18n: {
defaultLocale: 'zh',
locales: ['en', 'zh'],
defaultLocale: 'zh-CN',
locales: ['en', 'zh-CN', 'zh-TW'],
localeDetection: false
},
localePath:

View File

@@ -45,8 +45,6 @@ const nextConfig = {
}
if (isServer) {
// config.externals.push('@zilliz/milvus2-sdk-node');
if (nextRuntime === 'nodejs') {
const oldEntry = config.entry;
config = {
@@ -84,8 +82,14 @@ const nextConfig = {
transpilePackages: ['@fastgpt/*', 'ahooks'],
experimental: {
// 优化 Server Components 的构建和运行,避免不必要的客户端打包。
serverComponentsExternalPackages: ['mongoose', 'pg', '@node-rs/jieba', 'duck-duck-scrape'],
outputFileTracingRoot: path.join(__dirname, '../../')
serverComponentsExternalPackages: [
'mongoose',
'pg',
'@node-rs/jieba',
'@zilliz/milvus2-sdk-node'
],
outputFileTracingRoot: path.join(__dirname, '../../'),
instrumentationHook: true
}
};

View File

@@ -1,6 +1,6 @@
{
"name": "app",
"version": "4.8.13",
"version": "4.8.14",
"private": false,
"scripts": {
"dev": "next dev",

View File

@@ -1,31 +1,23 @@
### FastGPT V4.8.11 更新说明
### FastGPT V4.8.14 更新说明
1. 新增 - 表单输入节点,允许用户在工作流中让用户输入一些信息
2. 新增 - 循环运行节点,可传入数组进行批量调用,目前最多支持 50 长度的数组串行执行
3. 新增 - 自定义工具变量节点,可以为工具调用子流程完全自定义变量。在构建复杂 Agent 时有帮助
4. 新增 - 节点支持折叠
5. 新增 - 聊天记录滚动加载,不再只加载 30 条
6. 新增 - 工作流增加触摸板优先模式,可以通过工作流右下角按键进行切换
7. 新增 - 沙盒增加字符串转 base64 全局方法(全局变量 strToBase64)。
8. 新增 - 支持 Openai o1 模型,需增加模型的 `defaultConfig` 配置,覆盖 `temperature``max_tokens``stream`配置o1 不支持 stream 模式, 详细可重新拉取 `config.json` 配置文件查看
9. 新增 - AI 对话节点知识库引用,支持配置 role=system 和 role=user已配置的过自定义提示词的节点将会保持 user 模式,其余用户将转成 system 模式
10. 新增 - 插件支持上传系统文件
11. 新增 - 子应用嵌套调用时,版本锁定。主应用未主动更新版本时,不会取最新版进行执行,保证主应用服务稳定
12. 新增 - 插件输出,支持指定字段作为工具响应
13. 新增 - 支持工作流嵌套子应用时,可以设置`非流模式`,同时简易模式也可以选择工作流作为插件了,简易模式调用子应用时,都将强制使用非流模式。
14. 新增 - 调试模式下,子应用调用,支持返回详细运行数据。
15. 新增 - 保留所有模式下子应用嵌套调用的日志
16. 新增 - 商业版支持团队成员组,后续将逐渐覆盖工作台和知识库权限
17. 优化 - 工作流嵌套层级限制 20 层,避免因编排不合理导致的无限死循环
18. 优化 - 工作流 handler 性能优化
19. 优化 - 工作流快捷键,避免调试测试时也会触发复制和回退
20. 修复 - 工作流工具调用中修改全局变量后,无法传递到后续流程。
21. 优化 - 流输出,切换浏览器 Tab 后仍可以继续输出。
22. 优化 - 完善外部文件知识库相关 API
23. 修复 - 知识库选择权限问题。
24. 修复 - 空 chatId 发起对话,首轮携带用户选择时会异常。
25. 修复 - createDataset 接口intro 为赋值。
26. 修复 - 对话框渲染性能问题。
27. 修复 - 工具调用历史记录存储不正确。
1. 新增 - 工作流支持进入聊天框/点击开始对话后,自动触发一轮对话
2. 新增 - 重写 chatContext对话测试也会有日志并且刷新后不会丢失对话
3. 新增 - 分享链接支持配置是否允许查看原文
4. 新增 - 新的 doc2x 插件
5. 新增 - 繁体中文-台湾
6. 新增 - 分析链接和 chat api 支持传入自定义 uid
7. 新增 - 微软 oauth 登录
8. 优化 - 工作流 ui 细节
9. 优化 - 应用编辑记录采用 diff 存储,避免浏览器溢出
10. 优化 - 代码入口,增加 register 入口,无需等待首次访问才执行
11. 优化 - 工作流检查,增加更多缺失值检查
12. 优化 - 增加知识库训练最大重试次数限制
13. 优化 - 图片路径问题和示意图任务
14. 优化 - Milvus description
15. 修复 - 分块策略,四级标题会被丢失。 同时新增了五级标题的支持
16. 修复 - MongoDB 知识库集合唯一索引
17. 修复 - 反选知识库引用后可能会报错
18. 修复 - 简易模式转工作流,不是使用最新编辑记录进行转移
19. 修复 - 表单输入的说明文字不显示

View File

@@ -0,0 +1,8 @@
<svg width="36" height="37" viewBox="0 0 36 37" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect y="0.617554" width="36" height="36" rx="6" fill="#F0EEFF"/>
<path d="M14.8629 19.2382L16.7322 14.679C16.7937 14.5289 16.94 14.4308 17.1023 14.4308H19.7262C20.0163 14.4308 20.2099 14.7299 20.0912 14.9946L18.9433 17.552C18.884 17.6843 18.9808 17.8339 19.1258 17.8339H21.1135C21.4463 17.8339 21.6336 18.2166 21.4294 18.4793L17.7127 23.2613C17.4643 23.5809 16.9528 23.3717 16.9996 22.9696L17.3439 20.0131C17.3577 19.8943 17.2648 19.79 17.1452 19.79H15.233C14.9485 19.79 14.755 19.5014 14.8629 19.2382Z" fill="#8774EE"/>
<path d="M10.2067 23.1292C9.73113 23.4045 9.11745 23.2438 8.89074 22.7433C7.9809 20.7346 7.7568 18.4713 8.27046 16.3077C8.86108 13.8199 10.3822 11.6529 12.5212 10.2521C14.6601 8.85118 17.2545 8.32284 19.7709 8.77564C21.9595 9.16945 23.9446 10.2794 25.4224 11.9162C25.7906 12.324 25.6927 12.9508 25.2503 13.2767C24.8079 13.6026 24.1892 13.503 23.811 13.1043C22.6426 11.8729 21.1061 11.0377 19.4185 10.734C17.4028 10.3713 15.3247 10.7945 13.6114 11.9167C11.898 13.0388 10.6796 14.7746 10.2065 16.7673C9.81043 18.4356 9.96196 20.1778 10.6239 21.741C10.8382 22.247 10.6822 22.854 10.2067 23.1292Z" fill="#8774EE"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.6398 21.7804C10.6586 21.8296 10.6739 21.8797 10.6859 21.9302C10.7953 22.3903 10.6241 22.8876 10.2067 23.1292C9.73113 23.4045 9.11745 23.2438 8.89074 22.7433C8.85672 22.6682 8.82366 22.5927 8.79156 22.5169C8.77571 22.4795 8.7601 22.442 8.74472 22.4044C7.95817 20.4821 7.78549 18.3505 8.27046 16.3077C8.86108 13.8199 10.3822 11.6529 12.5212 10.2521C14.6601 8.85118 17.2545 8.32284 19.7709 8.77564C21.8373 9.14745 23.7223 10.1576 25.1701 11.6469C25.1984 11.676 25.2265 11.7053 25.2545 11.7348C25.3112 11.7945 25.3671 11.855 25.4224 11.9162C25.7906 12.324 25.6927 12.9508 25.2503 13.2767C24.8619 13.5628 24.3377 13.521 23.9596 13.2368C23.9181 13.2056 23.8784 13.1715 23.8408 13.1346C23.8307 13.1247 23.8207 13.1146 23.811 13.1043C22.6426 11.8729 21.1061 11.0377 19.4185 10.734C17.4028 10.3713 15.3247 10.7945 13.6114 11.9167C11.898 13.0388 10.6796 14.7746 10.2065 16.7673C9.81043 18.4356 9.96196 20.1778 10.6239 21.741C10.6294 21.7541 10.6347 21.7672 10.6398 21.7804Z" fill="#8774EE"/>
<path d="M26.3355 15.2101C26.8441 15.0022 27.4302 15.2451 27.5866 15.7719C28.1567 17.6924 28.1388 19.7484 27.5225 21.6707C26.8045 23.9101 25.3203 25.8248 23.3306 27.0784C21.3408 28.3319 18.973 28.8442 16.6431 28.5251C14.6431 28.2511 12.7808 27.3797 11.2946 26.0363C10.8869 25.6678 10.9209 25.0344 11.328 24.6653C11.7351 24.2963 12.3607 24.3327 12.7774 24.691C13.9423 25.6928 15.377 26.3432 16.9131 26.5536C18.7794 26.8092 20.6761 26.3989 22.2699 25.3948C23.8636 24.3907 25.0526 22.8569 25.6277 21.0632C26.1011 19.5867 26.1337 18.0119 25.733 16.5286C25.5897 15.9981 25.8269 15.4181 26.3355 15.2101Z" fill="#8774EE"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M25.7226 16.4874C25.7258 16.5011 25.7293 16.5149 25.733 16.5286C26.1337 18.0119 26.1011 19.5867 25.6277 21.0632C25.0526 22.8569 23.8636 24.3907 22.2699 25.3948C20.6761 26.3989 18.7794 26.8092 16.9131 26.5536C15.377 26.3432 13.9423 25.6928 12.7774 24.691C12.7666 24.6817 12.7557 24.6727 12.7446 24.6639C12.7035 24.631 12.6605 24.6011 12.6161 24.5743C12.2111 24.3299 11.6854 24.3414 11.328 24.6653C10.9209 25.0344 10.8869 25.6678 11.2946 26.0363C11.3557 26.0916 11.4175 26.1461 11.48 26.1997C11.5108 26.2262 11.5417 26.2525 11.5729 26.2786C13.0103 27.4846 14.766 28.268 16.6431 28.5251C18.973 28.8442 21.3408 28.3319 23.3306 27.0784C25.3203 25.8248 26.8045 23.9101 27.5225 21.6707C28.101 19.8666 28.1523 17.9447 27.685 16.1275C27.6749 16.0882 27.6646 16.0489 27.654 16.0096C27.6325 15.9302 27.61 15.8509 27.5866 15.7719C27.4302 15.2451 26.8441 15.0022 26.3355 15.2101C25.889 15.3927 25.6517 15.8619 25.6973 16.3327C25.7023 16.3844 25.7107 16.436 25.7226 16.4874Z" fill="#8774EE"/>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Some files were not shown because too many files have changed in this diff Show More