Compare commits

..

16 Commits

Author SHA1 Message Date
Archer
e860c56b77 perf: delete dataset (#3949)
* fix: collection list count

* fix: collection list count

* ai proxy ui

* perf: delete dataset

* perf: add dataset text index

* update doc
2025-03-03 12:49:13 +08:00
Archer
efac5312b4 fix: rerank model cannot use ai proxy (#3945)
* fix: collection list count

* fix: collection list count

* fix: rerank model cannot use ai proxy

* mongo init
2025-03-03 11:49:35 +08:00
Finley Ge
4bc7f21182 fix: add order:true to all create transactions (#3948) 2025-03-03 11:37:51 +08:00
gggaaallleee
113e8f711f add env proxypool (#3939) 2025-03-02 17:50:03 +08:00
Archer
abc6dffb41 4.8.23 dev (#3932)
* fix: collection list count

* fix: collection list count

* update doc

* perf: init log

* yml
2025-02-28 19:18:12 +08:00
gggaaallleee
f7b2a57ca3 1 (#3924) 2025-02-28 19:00:58 +08:00
Archer
cf0aaa1091 fix: invalid dataset data clear (#3927)
* fix: collection list count

* fix: collection list count

* fix: invalid dataset data clear

* update ts

* perf: cron clear invalid data

* perf: init

* perf: clear invalid code

* update init

* perf: clear invalid code

* perf: clear invalid code

* perf: init count

* batch init

* batch init

* batch init

* batch init

* add comment

* perf: init

* fix: api proxy type
2025-02-28 17:49:20 +08:00
Archer
ac4255ea0c 4.8.23 dev (#3926)
* fix: collection list count

* fix: collection list count

* fix: ts
2025-02-28 12:33:09 +08:00
Archer
df4d6f86ce fix: delete dataset field error (#3925)
* fix: collection list count

* fix: collection list count

* update doc

* perf: tts selector ui

* fix: delete dataset field error

* doc
2025-02-28 12:29:18 +08:00
heheer
e697fda82f fix: export chat log - chat detail order (#3923) 2025-02-28 11:33:46 +08:00
Archer
1aa319e7aa Update package.json (#3919) 2025-02-27 22:25:26 +08:00
Archer
fc9e614f88 4.8.23 dev (#3917)
* fix: icon refresh

* fix: aiproxy http request

* fix: collection list count

* fix: collection list count

* fix: tts selector name

* update action
2025-02-27 22:15:48 +08:00
Archer
1121ea33bd 更新 docker.md (#3913) 2025-02-27 17:02:06 +08:00
Finley Ge
9bbee60cde fix: ts error (#3911) 2025-02-27 16:31:14 +08:00
Finley Ge
9f57ad0017 fix: mongoose strictquery to false (#3906) 2025-02-27 11:25:29 +08:00
Archer
c3d3b30d7e update code positon (#3907) 2025-02-27 10:30:43 +08:00
201 changed files with 8215 additions and 871 deletions

View File

@@ -68,14 +68,3 @@ jobs:
SEALOS_TYPE: 'pr_comment' SEALOS_TYPE: 'pr_comment'
SEALOS_FILENAME: 'report.md' SEALOS_FILENAME: 'report.md'
SEALOS_REPLACE_TAG: 'DEFAULT_REPLACE_DEPLOY' SEALOS_REPLACE_TAG: 'DEFAULT_REPLACE_DEPLOY'
helm-check:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Helm Check
run: |
helm dependency update files/helm/fastgpt
helm lint files/helm/fastgpt
helm package files/helm/fastgpt

View File

@@ -24,6 +24,6 @@ jobs:
export APP_VERSION=${{ steps.vars.outputs.tag }} export APP_VERSION=${{ steps.vars.outputs.tag }}
export HELM_VERSION=${{ steps.vars.outputs.tag }} export HELM_VERSION=${{ steps.vars.outputs.tag }}
export HELM_REPO=ghcr.io/${{ github.repository_owner }} export HELM_REPO=ghcr.io/${{ github.repository_owner }}
helm dependency update files/helm/fastgpt helm dependency update deploy/helm/fastgpt
helm package files/helm/fastgpt --version ${HELM_VERSION}-helm --app-version ${APP_VERSION} -d bin helm package deploy/helm/fastgpt --version ${HELM_VERSION}-helm --app-version ${APP_VERSION} -d bin
helm push bin/fastgpt-${HELM_VERSION}-helm.tgz oci://${HELM_REPO} helm push bin/fastgpt-${HELM_VERSION}-helm.tgz oci://${HELM_REPO}

View File

@@ -58,7 +58,7 @@
"body": [ "body": [
"import '@/pages/api/__mocks__/base';", "import '@/pages/api/__mocks__/base';",
"import { root } from '@/pages/api/__mocks__/db/init';", "import { root } from '@/pages/api/__mocks__/db/init';",
"import { getTestRequest } from '@/test/utils';", "import { getTestRequest } from '@fastgpt/service/test/utils'; ;",
"import { AppErrEnum } from '@fastgpt/global/common/error/code/app';", "import { AppErrEnum } from '@fastgpt/global/common/error/code/app';",
"import handler from './demo';", "import handler from './demo';",
"", "",

View File

@@ -114,15 +114,15 @@ services:
# fastgpt # fastgpt
sandbox: sandbox:
container_name: sandbox container_name: sandbox
image: ghcr.io/labring/fastgpt-sandbox:v4.8.22 # git image: ghcr.io/labring/fastgpt-sandbox:v4.8.23-fix # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.22 # 阿里云 # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.23-fix # 阿里云
networks: networks:
- fastgpt - fastgpt
restart: always restart: always
fastgpt: fastgpt:
container_name: fastgpt container_name: fastgpt
image: ghcr.io/labring/fastgpt:v4.8.22 # git image: ghcr.io/labring/fastgpt:v4.8.23-fix # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.22 # 阿里云 # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.23-fix # 阿里云
ports: ports:
- 3000:3000 - 3000:3000
networks: networks:

View File

@@ -72,15 +72,15 @@ services:
# fastgpt # fastgpt
sandbox: sandbox:
container_name: sandbox container_name: sandbox
image: ghcr.io/labring/fastgpt-sandbox:v4.8.22 # git image: ghcr.io/labring/fastgpt-sandbox:v4.8.23-fix # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.22 # 阿里云 # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.23-fix # 阿里云
networks: networks:
- fastgpt - fastgpt
restart: always restart: always
fastgpt: fastgpt:
container_name: fastgpt container_name: fastgpt
image: ghcr.io/labring/fastgpt:v4.8.22 # git image: ghcr.io/labring/fastgpt:v4.8.23-fix # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.22 # 阿里云 # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.23-fix # 阿里云
ports: ports:
- 3000:3000 - 3000:3000
networks: networks:

View File

@@ -53,15 +53,15 @@ services:
wait $$! wait $$!
sandbox: sandbox:
container_name: sandbox container_name: sandbox
image: ghcr.io/labring/fastgpt-sandbox:v4.8.22 # git image: ghcr.io/labring/fastgpt-sandbox:v4.8.23-fix # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.22 # 阿里云 # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.23-fix # 阿里云
networks: networks:
- fastgpt - fastgpt
restart: always restart: always
fastgpt: fastgpt:
container_name: fastgpt container_name: fastgpt
image: ghcr.io/labring/fastgpt:v4.8.22 # git image: ghcr.io/labring/fastgpt:v4.8.23-fix # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.22 # 阿里云 # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.23-fix # 阿里云
ports: ports:
- 3000:3000 - 3000:3000
networks: networks:

View File

@@ -31,9 +31,9 @@ weight: 920
3 个模型代码分别为: 3 个模型代码分别为:
1. [https://github.com/labring/FastGPT/tree/main/python/bge-rerank/bge-reranker-base](https://github.com/labring/FastGPT/tree/main/python/bge-rerank/bge-reranker-base) 1. [https://github.com/labring/FastGPT/tree/main/plugins/rerank-bge/bge-reranker-base](https://github.com/labring/FastGPT/tree/main/plugins/rerank-bge/bge-reranker-base)
2. [https://github.com/labring/FastGPT/tree/main/python/bge-rerank/bge-reranker-large](https://github.com/labring/FastGPT/tree/main/python/bge-rerank/bge-reranker-large) 2. [https://github.com/labring/FastGPT/tree/main/plugins/rerank-bge/bge-reranker-large](https://github.com/labring/FastGPT/tree/main/plugins/rerank-bge/bge-reranker-large)
3. [https://github.com/labring/FastGPT/tree/main/python/bge-rerank/bge-reranker-v2-m3](https://github.com/labring/FastGPT/tree/main/python/bge-rerank/bge-reranker-v2-m3) 3. [https://github.com/labring/FastGPT/tree/main/plugins/rerank-bge/bge-reranker-v2-m3](https://github.com/labring/FastGPT/tree/main/plugins/rerank-bge/bge-reranker-v2-m3)
### 3. 安装依赖 ### 3. 安装依赖

View File

@@ -19,7 +19,7 @@ PDF 是一个相对复杂的文件格式,在 FastGPT 内置的 pdf 解析器
### 1. 按照 Marker ### 1. 按照 Marker
参考文档 [Marker 安装教程](https://github.com/labring/FastGPT/tree/main/python/pdf-marker),安装 Marker 模型。封装的 API 已经适配了 FastGPT 自定义解析服务。 参考文档 [Marker 安装教程](https://github.com/labring/FastGPT/tree/main/plugins/model/pdf-marker),安装 Marker 模型。封装的 API 已经适配了 FastGPT 自定义解析服务。
这里介绍快速 Docker 安装的方法: 这里介绍快速 Docker 安装的方法:

View File

@@ -118,7 +118,7 @@ brew install orbstack
非 Linux 环境或无法访问外网环境,可手动创建一个目录,并下载配置文件和对应版本的`docker-compose.yml`在这个文件夹中依据下载的配置文件运行docker若作为本地开发使用推荐`docker-compose-pgvector`版本,并且自行拉取并运行`sandbox``fastgpt`并在docker配置文件中注释掉`sandbox``fastgpt`的部分 非 Linux 环境或无法访问外网环境,可手动创建一个目录,并下载配置文件和对应版本的`docker-compose.yml`在这个文件夹中依据下载的配置文件运行docker若作为本地开发使用推荐`docker-compose-pgvector`版本,并且自行拉取并运行`sandbox``fastgpt`并在docker配置文件中注释掉`sandbox``fastgpt`的部分
- [config.json](https://raw.githubusercontent.com/labring/FastGPT/refs/heads/main/projects/app/data/config.json) - [config.json](https://raw.githubusercontent.com/labring/FastGPT/refs/heads/main/projects/app/data/config.json)
- [docker-compose.yml](https://github.com/labring/FastGPT/blob/main/files/docker) (注意,不同向量库版本的文件不一样) - [docker-compose.yml](https://github.com/labring/FastGPT/blob/main/deploy/docker) (注意,不同向量库版本的文件不一样)
{{% alert icon="🤖" context="success" %}} {{% alert icon="🤖" context="success" %}}
@@ -134,11 +134,11 @@ cd fastgpt
curl -O https://raw.githubusercontent.com/labring/FastGPT/main/projects/app/data/config.json curl -O https://raw.githubusercontent.com/labring/FastGPT/main/projects/app/data/config.json
# pgvector 版本(测试推荐,简单快捷) # pgvector 版本(测试推荐,简单快捷)
curl -o docker-compose.yml https://raw.githubusercontent.com/labring/FastGPT/main/files/docker/docker-compose-pgvector.yml curl -o docker-compose.yml https://raw.githubusercontent.com/labring/FastGPT/main/deploy/docker/docker-compose-pgvector.yml
# milvus 版本 # milvus 版本
# curl -o docker-compose.yml https://raw.githubusercontent.com/labring/FastGPT/main/files/docker/docker-compose-milvus.yml # curl -o docker-compose.yml https://raw.githubusercontent.com/labring/FastGPT/main/deploy/docker/docker-compose-milvus.yml
# zilliz 版本 # zilliz 版本
# curl -o docker-compose.yml https://raw.githubusercontent.com/labring/FastGPT/main/files/docker/docker-compose-zilliz.yml # curl -o docker-compose.yml https://raw.githubusercontent.com/labring/FastGPT/main/deploy/docker/docker-compose-zilliz.yml
``` ```
### 2. 修改环境变量 ### 2. 修改环境变量
@@ -201,6 +201,8 @@ docker restart oneapi
在OneApi中添加合适的AI模型渠道。[点击查看相关教程](/docs/development/modelconfig/one-api/) 在OneApi中添加合适的AI模型渠道。[点击查看相关教程](/docs/development/modelconfig/one-api/)
只需要添加模型即可模板已经配置好了oneapi的连接地址和令牌无需变更。
### 5. 访问 FastGPT ### 5. 访问 FastGPT
目前可以通过 `ip:3000` 直接访问(注意防火墙)。登录用户名为 `root`,密码为`docker-compose.yml`环境变量里设置的 `DEFAULT_ROOT_PSW` 目前可以通过 `ip:3000` 直接访问(注意防火墙)。登录用户名为 `root`,密码为`docker-compose.yml`环境变量里设置的 `DEFAULT_ROOT_PSW`
@@ -211,7 +213,7 @@ docker restart oneapi
### 6. 配置模型 ### 6. 配置模型
务必先配置至少一组模型,否则系统无法正常使用。 登录FastGPT后进入模型配置页面务必先配置至少一个语言模型和一个向量模型,否则系统无法正常使用。
[点击查看模型配置教程](/docs/development/modelConfig/intro/) [点击查看模型配置教程](/docs/development/modelConfig/intro/)

View File

@@ -20,7 +20,7 @@ SANDBOX_URL=内网地址
## Docker 部署 ## Docker 部署
可以拉取最新 [docker-compose.yml](https://github.com/labring/FastGPT/blob/main/files/docker/docker-compose.yml) 文件参考 可以拉取最新 [docker-compose.yml](https://github.com/labring/FastGPT/blob/main/deploy/docker/docker-compose.yml) 文件参考
1. 新增一个容器 `sandbox` 1. 新增一个容器 `sandbox`
2. fastgpt 和 fastgpt-pro(商业版) 容器新增环境变量: `SANDBOX_URL` 2. fastgpt 和 fastgpt-pro(商业版) 容器新增环境变量: `SANDBOX_URL`

View File

@@ -1,5 +1,5 @@
--- ---
title: 'V4.8.23(进行中)' title: 'V4.8.23'
description: 'FastGPT V4.8.23 更新说明' description: 'FastGPT V4.8.23 更新说明'
icon: 'upgrade' icon: 'upgrade'
draft: false draft: false
@@ -7,11 +7,33 @@ toc: true
weight: 802 weight: 802
--- ---
## 更新指南
### 1. 做好数据库备份
### 2. 更新镜像:
- 更新 fastgpt 镜像 tag: v4.8.23-fix
- 更新 fastgpt-pro 商业版镜像 tag: v4.8.23-fix
- Sandbox 镜像无需更新
### 3. 运行升级脚本
从任意终端,发起 1 个 HTTP 请求。其中 {{rootkey}} 替换成环境变量里的 `rootkey`{{host}} 替换成**FastGPT 域名**。
```bash
curl --location --request POST 'https://{{host}}/api/admin/initv4823' \
--header 'rootkey: {{rootkey}}' \
--header 'Content-Type: application/json'
```
脚本会清理一些知识库脏数据,主要是多余的全文索引。
## 🚀 新增内容 ## 🚀 新增内容
1. 增加默认“知识库文本理解模型”配置 1. 增加默认“知识库文本理解模型”配置
2. AI proxy V1版可替换 OneAPI使用同时提供完整模型调用日志便于排查问题。 2. AI proxy V1版可替换 OneAPI使用同时提供完整模型调用日志便于排查问题。
3. 增加工单入口支持。
## ⚙️ 优化 ## ⚙️ 优化
@@ -27,4 +49,6 @@ weight: 802
1. 标签过滤时,子文件夹未成功过滤。 1. 标签过滤时,子文件夹未成功过滤。
2. 暂时移除 md 阅读优化,避免链接分割错误。 2. 暂时移除 md 阅读优化,避免链接分割错误。
3. 离开团队时,未刷新成员列表。 3. 离开团队时,未刷新成员列表。
4. PPTX 编码错误,导致解析失败。 4. PPTX 编码错误,导致解析失败。
5. 删除知识库单条数据时,全文索引未跟随删除。
6. 修复 Mongo Dataset text 索引在查询数据时未生效。

View File

@@ -15,7 +15,7 @@ weight: 821
## V4.8.3 更新说明 ## V4.8.3 更新说明
1. 新增 - 支持 Milvus 数据库, 可参考最新的 [docker-compose-milvus.yml](https://github.com/labring/FastGPT/blob/main/files/docker/docker-compose-milvus.yml). 1. 新增 - 支持 Milvus 数据库, 可参考最新的 [docker-compose-milvus.yml](https://github.com/labring/FastGPT/blob/main/deploy/docker/docker-compose-milvus.yml).
2. 新增 - 给 chat 接口 empty answer 增加 log便于排查模型问题。 2. 新增 - 给 chat 接口 empty answer 增加 log便于排查模型问题。
3. 新增 - ifelse判断器字符串支持正则。 3. 新增 - ifelse判断器字符串支持正则。
4. 新增 - 代码运行支持 console.log 输出调试。 4. 新增 - 代码运行支持 console.log 输出调试。

3
packages/README.md Normal file
View File

@@ -0,0 +1,3 @@
# 目录说明
该目录为 FastGPT 的依赖包,多端复用。

View File

@@ -4,6 +4,7 @@ import { ErrType } from '../errorCode';
/* dataset: 501000 */ /* dataset: 501000 */
export enum DatasetErrEnum { export enum DatasetErrEnum {
unExist = 'unExistDataset', unExist = 'unExistDataset',
unExistCollection = 'unExistCollection',
unAuthDataset = 'unAuthDataset', unAuthDataset = 'unAuthDataset',
unCreateCollection = 'unCreateCollection', unCreateCollection = 'unCreateCollection',
unAuthDatasetCollection = 'unAuthDatasetCollection', unAuthDatasetCollection = 'unAuthDatasetCollection',
@@ -28,6 +29,10 @@ const datasetErr = [
statusText: DatasetErrEnum.unExist, statusText: DatasetErrEnum.unExist,
message: 'core.dataset.error.unExistDataset' message: 'core.dataset.error.unExistDataset'
}, },
{
statusText: DatasetErrEnum.unExistCollection,
message: i18nT('common:error_collection_not_exist')
},
{ {
statusText: DatasetErrEnum.unAuthDataset, statusText: DatasetErrEnum.unAuthDataset,
message: 'core.dataset.error.unAuthDataset' message: 'core.dataset.error.unAuthDataset'

View File

@@ -420,137 +420,3 @@ export function rewriteNodeOutputByHistories(
}; };
}); });
} }
// Parse <think></think> tags to think and answer - unstream response
export const parseReasoningContent = (text: string): [string, string] => {
const regex = /<think>([\s\S]*?)<\/think>/;
const match = text.match(regex);
if (!match) {
return ['', text];
}
const thinkContent = match[1].trim();
// Add answer (remaining text after think tag)
const answerContent = text.slice(match.index! + match[0].length);
return [thinkContent, answerContent];
};
// Parse <think></think> tags to think and answer - stream response
export const parseReasoningStreamContent = () => {
let isInThinkTag: boolean | undefined;
const startTag = '<think>';
let startTagBuffer = '';
const endTag = '</think>';
let endTagBuffer = '';
/*
parseReasoning - 只控制是否主动解析 <think></think>,如果接口已经解析了,仍然会返回 think 内容。
*/
const parsePart = (
part: {
choices: {
delta: {
content?: string;
reasoning_content?: string;
};
}[];
},
parseReasoning = false
): [string, string] => {
const content = part.choices?.[0]?.delta?.content || '';
// @ts-ignore
const reasoningContent = part.choices?.[0]?.delta?.reasoning_content || '';
if (reasoningContent || !parseReasoning) {
isInThinkTag = false;
return [reasoningContent, content];
}
if (!content) {
return ['', ''];
}
// 如果不在 think 标签中,或者有 reasoningContent(接口已解析),则返回 reasoningContent 和 content
if (isInThinkTag === false) {
return ['', content];
}
// 检测是否为 think 标签开头的数据
if (isInThinkTag === undefined) {
// Parse content think and answer
startTagBuffer += content;
// 太少内容时候,暂时不解析
if (startTagBuffer.length < startTag.length) {
return ['', ''];
}
if (startTagBuffer.startsWith(startTag)) {
isInThinkTag = true;
return [startTagBuffer.slice(startTag.length), ''];
}
// 如果未命中 think 标签,则认为不在 think 标签中,返回 buffer 内容作为 content
isInThinkTag = false;
return ['', startTagBuffer];
}
// 确认是 think 标签内容,开始返回 think 内容,并实时检测 </think>
/*
检测 </think> 方案。
存储所有疑似 </think> 的内容,直到检测到完整的 </think> 标签或超出 </think> 长度。
content 返回值包含以下几种情况:
abc - 完全未命中尾标签
abc<th - 命中一部分尾标签
abc</think> - 完全命中尾标签
abc</think>abc - 完全命中尾标签
</think>abc - 完全命中尾标签
k>abc - 命中一部分尾标签
*/
// endTagBuffer 专门用来记录疑似尾标签的内容
if (endTagBuffer) {
endTagBuffer += content;
if (endTagBuffer.includes(endTag)) {
isInThinkTag = false;
const answer = endTagBuffer.slice(endTag.length);
return ['', answer];
} else if (endTagBuffer.length >= endTag.length) {
// 缓存内容超出尾标签长度,且仍未命中 </think>,则认为本次猜测 </think> 失败,仍处于 think 阶段。
const tmp = endTagBuffer;
endTagBuffer = '';
return [tmp, ''];
}
return ['', ''];
} else if (content.includes(endTag)) {
// 返回内容,完整命中</think>,直接结束
isInThinkTag = false;
const [think, answer] = content.split(endTag);
return [think, answer];
} else {
// 无 buffer且未命中 </think>,开始疑似 </think> 检测。
for (let i = 1; i < endTag.length; i++) {
const partialEndTag = endTag.slice(0, i);
// 命中一部分尾标签
if (content.endsWith(partialEndTag)) {
const think = content.slice(0, -partialEndTag.length);
endTagBuffer += partialEndTag;
return [think, ''];
}
}
}
// 完全未命中尾标签,还是 think 阶段。
return [content, ''];
};
const getStartTagBuffer = () => startTagBuffer;
return {
parsePart,
getStartTagBuffer
};
};

View File

@@ -118,7 +118,7 @@ export async function delImgByRelatedId({
}: { }: {
teamId: string; teamId: string;
relateIds: string[]; relateIds: string[];
session: ClientSession; session?: ClientSession;
}) { }) {
if (relateIds.length === 0) return; if (relateIds.length === 0) return;

View File

@@ -38,10 +38,12 @@ const addCommonMiddleware = (schema: mongoose.Schema) => {
schema.post(op, function (this: any, result: any, next) { schema.post(op, function (this: any, result: any, next) {
if (this._startTime) { if (this._startTime) {
const duration = Date.now() - this._startTime; const duration = Date.now() - this._startTime;
const warnLogData = { const warnLogData = {
query: this._query, collectionName: this.collection?.name,
op, op: this.op,
...(this._query && { query: this._query }),
...(this._update && { update: this._update }),
...(this._delete && { delete: this._delete }),
duration duration
}; };

View File

@@ -16,16 +16,30 @@ export async function connectMongo(): Promise<Mongoose> {
console.log('mongo start connect'); console.log('mongo start connect');
try { try {
connectionMongo.set('strictQuery', true); // Remove existing listeners to prevent duplicates
connectionMongo.connection.removeAllListeners('error');
connectionMongo.connection.removeAllListeners('disconnected');
connectionMongo.set('strictQuery', false);
connectionMongo.connection.on('error', async (error) => { connectionMongo.connection.on('error', async (error) => {
console.log('mongo error', error); console.log('mongo error', error);
await connectionMongo.disconnect(); try {
await delay(1000); if (connectionMongo.connection.readyState !== 0) {
connectMongo(); await connectionMongo.disconnect();
await delay(1000);
await connectMongo();
}
} catch (error) {}
}); });
connectionMongo.connection.on('disconnected', () => { connectionMongo.connection.on('disconnected', async () => {
console.log('mongo disconnected'); console.log('mongo disconnected');
try {
if (connectionMongo.connection.readyState !== 0) {
await connectionMongo.disconnect();
await delay(1000);
await connectMongo();
}
} catch (error) {}
}); });
await connectionMongo.connect(process.env.MONGODB_URI as string, { await connectionMongo.connect(process.env.MONGODB_URI as string, {

View File

@@ -35,7 +35,7 @@ export const getAxiosConfig = (props?: { userKey?: OpenaiAccountType }) => {
const { userKey } = props || {}; const { userKey } = props || {};
const baseUrl = userKey?.baseUrl || global?.systemEnv?.oneapiUrl || openaiBaseUrl; const baseUrl = userKey?.baseUrl || global?.systemEnv?.oneapiUrl || openaiBaseUrl;
const apiKey = userKey?.key || global?.systemEnv?.chatApiKey || process.env.CHAT_API_KEY || ''; const apiKey = userKey?.key || global?.systemEnv?.chatApiKey || openaiBaseKey;
return { return {
baseUrl, baseUrl,

View File

@@ -1,4 +1,10 @@
{ {
"provider": "AliCloud", "provider": "AliCloud",
"list": [] "list": [
} {
"model": "SenseVoiceSmall",
"name": "SenseVoiceSmall",
"type": "stt"
}
]
}

View File

@@ -95,11 +95,145 @@ export const llmCompletionsBodyFormat = <T extends CompletionsBodyType>(
return requestBody as unknown as InferCompletionsBody<T>; return requestBody as unknown as InferCompletionsBody<T>;
}; };
export const llmStreamResponseToText = async (response: StreamChatType) => { export const llmStreamResponseToAnswerText = async (response: StreamChatType) => {
let answer = ''; let answer = '';
for await (const part of response) { for await (const part of response) {
const content = part.choices?.[0]?.delta?.content || ''; const content = part.choices?.[0]?.delta?.content || '';
answer += content; answer += content;
} }
return answer; return parseReasoningContent(answer)[1];
};
// Parse <think></think> tags to think and answer - unstream response
export const parseReasoningContent = (text: string): [string, string] => {
const regex = /<think>([\s\S]*?)<\/think>/;
const match = text.match(regex);
if (!match) {
return ['', text];
}
const thinkContent = match[1].trim();
// Add answer (remaining text after think tag)
const answerContent = text.slice(match.index! + match[0].length);
return [thinkContent, answerContent];
};
// Parse <think></think> tags to think and answer - stream response
export const parseReasoningStreamContent = () => {
let isInThinkTag: boolean | undefined;
const startTag = '<think>';
let startTagBuffer = '';
const endTag = '</think>';
let endTagBuffer = '';
/*
parseReasoning - 只控制是否主动解析 <think></think>,如果接口已经解析了,仍然会返回 think 内容。
*/
const parsePart = (
part: {
choices: {
delta: {
content?: string;
reasoning_content?: string;
};
}[];
},
parseReasoning = false
): [string, string] => {
const content = part.choices?.[0]?.delta?.content || '';
// @ts-ignore
const reasoningContent = part.choices?.[0]?.delta?.reasoning_content || '';
if (reasoningContent || !parseReasoning) {
isInThinkTag = false;
return [reasoningContent, content];
}
if (!content) {
return ['', ''];
}
// 如果不在 think 标签中,或者有 reasoningContent(接口已解析),则返回 reasoningContent 和 content
if (isInThinkTag === false) {
return ['', content];
}
// 检测是否为 think 标签开头的数据
if (isInThinkTag === undefined) {
// Parse content think and answer
startTagBuffer += content;
// 太少内容时候,暂时不解析
if (startTagBuffer.length < startTag.length) {
return ['', ''];
}
if (startTagBuffer.startsWith(startTag)) {
isInThinkTag = true;
return [startTagBuffer.slice(startTag.length), ''];
}
// 如果未命中 think 标签,则认为不在 think 标签中,返回 buffer 内容作为 content
isInThinkTag = false;
return ['', startTagBuffer];
}
// 确认是 think 标签内容,开始返回 think 内容,并实时检测 </think>
/*
检测 </think> 方案。
存储所有疑似 </think> 的内容,直到检测到完整的 </think> 标签或超出 </think> 长度。
content 返回值包含以下几种情况:
abc - 完全未命中尾标签
abc<th - 命中一部分尾标签
abc</think> - 完全命中尾标签
abc</think>abc - 完全命中尾标签
</think>abc - 完全命中尾标签
k>abc - 命中一部分尾标签
*/
// endTagBuffer 专门用来记录疑似尾标签的内容
if (endTagBuffer) {
endTagBuffer += content;
if (endTagBuffer.includes(endTag)) {
isInThinkTag = false;
const answer = endTagBuffer.slice(endTag.length);
return ['', answer];
} else if (endTagBuffer.length >= endTag.length) {
// 缓存内容超出尾标签长度,且仍未命中 </think>,则认为本次猜测 </think> 失败,仍处于 think 阶段。
const tmp = endTagBuffer;
endTagBuffer = '';
return [tmp, ''];
}
return ['', ''];
} else if (content.includes(endTag)) {
// 返回内容,完整命中</think>,直接结束
isInThinkTag = false;
const [think, answer] = content.split(endTag);
return [think, answer];
} else {
// 无 buffer且未命中 </think>,开始疑似 </think> 检测。
for (let i = 1; i < endTag.length; i++) {
const partialEndTag = endTag.slice(0, i);
// 命中一部分尾标签
if (content.endsWith(partialEndTag)) {
const think = content.slice(0, -partialEndTag.length);
endTagBuffer += partialEndTag;
return [think, ''];
}
}
}
// 完全未命中尾标签,还是 think 阶段。
return [content, ''];
};
const getStartTagBuffer = () => startTagBuffer;
return {
parsePart,
getStartTagBuffer
};
}; };

View File

@@ -25,6 +25,7 @@ import { MongoImage } from '../../../common/file/image/schema';
import { hashStr } from '@fastgpt/global/common/string/tools'; import { hashStr } from '@fastgpt/global/common/string/tools';
import { addDays } from 'date-fns'; import { addDays } from 'date-fns';
import { MongoDatasetDataText } from '../data/dataTextSchema'; import { MongoDatasetDataText } from '../data/dataTextSchema';
import { delay, retryFn } from '@fastgpt/global/common/system/utils';
export const createCollectionAndInsertData = async ({ export const createCollectionAndInsertData = async ({
dataset, dataset,
@@ -216,7 +217,7 @@ export async function createOneCollection({
nextSyncTime nextSyncTime
} }
], ],
{ session } { session, ordered: true }
); );
return collection; return collection;
@@ -227,8 +228,14 @@ export const delCollectionRelatedSource = async ({
collections, collections,
session session
}: { }: {
collections: DatasetCollectionSchemaType[]; collections: {
session: ClientSession; teamId: string;
fileId?: string;
metadata?: {
relatedImgId?: string;
};
}[];
session?: ClientSession;
}) => { }) => {
if (collections.length === 0) return; if (collections.length === 0) return;
@@ -259,11 +266,13 @@ export const delCollectionRelatedSource = async ({
export async function delCollection({ export async function delCollection({
collections, collections,
session, session,
delRelatedSource delImg = true,
delFile = true
}: { }: {
collections: DatasetCollectionSchemaType[]; collections: DatasetCollectionSchemaType[];
session: ClientSession; session: ClientSession;
delRelatedSource: boolean; delImg: boolean;
delFile: boolean;
}) { }) {
if (collections.length === 0) return; if (collections.length === 0) return;
@@ -274,83 +283,55 @@ export async function delCollection({
const datasetIds = Array.from(new Set(collections.map((item) => String(item.datasetId)))); const datasetIds = Array.from(new Set(collections.map((item) => String(item.datasetId))));
const collectionIds = collections.map((item) => String(item._id)); const collectionIds = collections.map((item) => String(item._id));
// Delete training data await retryFn(async () => {
await MongoDatasetTraining.deleteMany({ await Promise.all([
teamId, // Delete training data
datasetIds: { $in: datasetIds }, MongoDatasetTraining.deleteMany({
collectionId: { $in: collectionIds } teamId,
datasetId: { $in: datasetIds },
collectionId: { $in: collectionIds }
}),
// Delete dataset_data_texts
MongoDatasetDataText.deleteMany({
teamId,
datasetId: { $in: datasetIds },
collectionId: { $in: collectionIds }
}),
// Delete dataset_datas
MongoDatasetData.deleteMany({
teamId,
datasetId: { $in: datasetIds },
collectionId: { $in: collectionIds }
}),
...(delImg
? [
delImgByRelatedId({
teamId,
relateIds: collections
.map((item) => item?.metadata?.relatedImgId || '')
.filter(Boolean)
})
]
: []),
...(delFile
? [
delFileByFileIdList({
bucketName: BucketNameEnum.dataset,
fileIdList: collections.map((item) => item?.fileId || '').filter(Boolean)
})
]
: []),
// Delete vector data
deleteDatasetDataVector({ teamId, datasetIds, collectionIds })
]);
// delete collections
await MongoDatasetCollection.deleteMany(
{
teamId,
_id: { $in: collectionIds }
},
{ session }
);
}); });
/* file and imgs */
if (delRelatedSource) {
await delCollectionRelatedSource({ collections, session });
}
// Delete dataset_datas
await MongoDatasetData.deleteMany(
{ teamId, datasetIds: { $in: datasetIds }, collectionId: { $in: collectionIds } },
{ session }
);
// Delete dataset_data_texts
await MongoDatasetDataText.deleteMany(
{ teamId, datasetIds: { $in: datasetIds }, collectionId: { $in: collectionIds } },
{ session }
);
// delete collections
await MongoDatasetCollection.deleteMany(
{
teamId,
_id: { $in: collectionIds }
},
{ session }
);
// no session delete: delete files, vector data
await deleteDatasetDataVector({ teamId, datasetIds, collectionIds });
}
/**
* delete delOnlyCollection
*/
export async function delOnlyCollection({
collections,
session
}: {
collections: DatasetCollectionSchemaType[];
session: ClientSession;
}) {
if (collections.length === 0) return;
const teamId = collections[0].teamId;
if (!teamId) return Promise.reject('teamId is not exist');
const datasetIds = Array.from(new Set(collections.map((item) => String(item.datasetId))));
const collectionIds = collections.map((item) => String(item._id));
// delete training data
await MongoDatasetTraining.deleteMany({
teamId,
datasetIds: { $in: datasetIds },
collectionId: { $in: collectionIds }
});
// delete dataset.datas
await MongoDatasetData.deleteMany(
{ teamId, datasetIds: { $in: datasetIds }, collectionId: { $in: collectionIds } },
{ session }
);
// delete collections
await MongoDatasetCollection.deleteMany(
{
teamId,
_id: { $in: collectionIds }
},
{ session }
);
// no session delete: delete files, vector data
await deleteDatasetDataVector({ teamId, datasetIds, collectionIds });
} }

View File

@@ -97,7 +97,7 @@ export const createOrGetCollectionTags = async ({
datasetId, datasetId,
tag: tagContent tag: tagContent
})), })),
{ session } { session, ordered: true }
); );
return [...existingTags.map((tag) => tag._id), ...newTags.map((tag) => tag._id)]; return [...existingTags.map((tag) => tag._id), ...newTags.map((tag) => tag._id)];
@@ -174,6 +174,14 @@ export const syncCollection = async (collection: CollectionWithDatasetType) => {
} }
await mongoSessionRun(async (session) => { await mongoSessionRun(async (session) => {
// Delete old collection
await delCollection({
collections: [collection],
delImg: false,
delFile: false,
session
});
// Create new collection // Create new collection
await createCollectionAndInsertData({ await createCollectionAndInsertData({
session, session,
@@ -208,13 +216,6 @@ export const syncCollection = async (collection: CollectionWithDatasetType) => {
updateTime: new Date() updateTime: new Date()
} }
}); });
// Delete old collection
await delCollection({
collections: [collection],
delRelatedSource: false,
session
});
}); });
return DatasetCollectionSyncResultEnum.success; return DatasetCollectionSyncResultEnum.success;

View File

@@ -7,6 +7,8 @@ import { MongoDatasetTraining } from './training/schema';
import { MongoDatasetData } from './data/schema'; import { MongoDatasetData } from './data/schema';
import { deleteDatasetDataVector } from '../../common/vectorStore/controller'; import { deleteDatasetDataVector } from '../../common/vectorStore/controller';
import { MongoDatasetDataText } from './data/dataTextSchema'; import { MongoDatasetDataText } from './data/dataTextSchema';
import { DatasetErrEnum } from '@fastgpt/global/common/error/code/dataset';
import { retryFn } from '@fastgpt/global/common/system/utils';
/* ============= dataset ========== */ /* ============= dataset ========== */
/* find all datasetId by top datasetId */ /* find all datasetId by top datasetId */
@@ -54,7 +56,7 @@ export async function getCollectionWithDataset(collectionId: string) {
.populate<{ dataset: DatasetSchemaType }>('dataset') .populate<{ dataset: DatasetSchemaType }>('dataset')
.lean(); .lean();
if (!data) { if (!data) {
return Promise.reject('Collection is not exist'); return Promise.reject(DatasetErrEnum.unExistCollection);
} }
return data; return data;
} }
@@ -77,40 +79,39 @@ export async function delDatasetRelevantData({
const datasetIds = datasets.map((item) => item._id); const datasetIds = datasets.map((item) => item._id);
// delete training data
await MongoDatasetTraining.deleteMany({
teamId,
datasetId: { $in: datasetIds }
});
// Get _id, teamId, fileId, metadata.relatedImgId for all collections // Get _id, teamId, fileId, metadata.relatedImgId for all collections
const collections = await MongoDatasetCollection.find( const collections = await MongoDatasetCollection.find(
{ {
teamId, teamId,
datasetId: { $in: datasetIds } datasetId: { $in: datasetIds }
}, },
'_id teamId datasetId fileId metadata', '_id teamId datasetId fileId metadata'
{ session }
).lean(); ).lean();
// Delete Image and file await retryFn(async () => {
await delCollectionRelatedSource({ collections, session }); await Promise.all([
// delete training data
MongoDatasetTraining.deleteMany({
teamId,
datasetId: { $in: datasetIds }
}),
//Delete dataset_data_texts
MongoDatasetDataText.deleteMany({
teamId,
datasetId: { $in: datasetIds }
}),
//delete dataset_datas
MongoDatasetData.deleteMany({ teamId, datasetId: { $in: datasetIds } }),
// Delete Image and file
delCollectionRelatedSource({ collections }),
// Delete vector data
deleteDatasetDataVector({ teamId, datasetIds })
]);
});
// delete collections // delete collections
await MongoDatasetCollection.deleteMany({ await MongoDatasetCollection.deleteMany({
teamId, teamId,
datasetId: { $in: datasetIds } datasetId: { $in: datasetIds }
}).session(session); }).session(session);
// No session delete:
// Delete dataset_data_texts
await MongoDatasetDataText.deleteMany({
teamId,
datasetId: { $in: datasetIds }
});
// delete dataset_datas
await MongoDatasetData.deleteMany({ teamId, datasetId: { $in: datasetIds } });
// Delete vector data
await deleteDatasetDataVector({ teamId, datasetIds });
} }

View File

@@ -1,6 +1,6 @@
import { connectionMongo, getMongoModel } from '../../../common/mongo'; import { connectionMongo, getMongoModel } from '../../../common/mongo';
const { Schema } = connectionMongo; const { Schema } = connectionMongo;
import { DatasetDataSchemaType } from '@fastgpt/global/core/dataset/type.d'; import { DatasetDataTextSchemaType } from '@fastgpt/global/core/dataset/type.d';
import { TeamCollectionName } from '@fastgpt/global/support/user/team/constant'; import { TeamCollectionName } from '@fastgpt/global/support/user/team/constant';
import { DatasetCollectionName } from '../schema'; import { DatasetCollectionName } from '../schema';
import { DatasetColCollectionName } from '../collection/schema'; import { DatasetColCollectionName } from '../collection/schema';
@@ -40,12 +40,13 @@ try {
default_language: 'none' default_language: 'none'
} }
); );
DatasetDataTextSchema.index({ teamId: 1, datasetId: 1, collectionId: 1 });
DatasetDataTextSchema.index({ dataId: 1 }, { unique: true }); DatasetDataTextSchema.index({ dataId: 1 }, { unique: true });
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
export const MongoDatasetDataText = getMongoModel<DatasetDataSchemaType>( export const MongoDatasetDataText = getMongoModel<DatasetDataTextSchemaType>(
DatasetDataTextCollectionName, DatasetDataTextCollectionName,
DatasetDataTextSchema DatasetDataTextSchema
); );

View File

@@ -3,11 +3,8 @@ import { filterGPTMessageByMaxContext, loadRequestMessages } from '../../../chat
import type { ChatItemType, UserChatItemValueItemType } from '@fastgpt/global/core/chat/type.d'; import type { ChatItemType, UserChatItemValueItemType } from '@fastgpt/global/core/chat/type.d';
import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants'; import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
import { SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/constants'; import { SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/constants';
import { import { textAdaptGptResponse } from '@fastgpt/global/core/workflow/runtime/utils';
parseReasoningContent, import { parseReasoningContent, parseReasoningStreamContent } from '../../../ai/utils';
parseReasoningStreamContent,
textAdaptGptResponse
} from '@fastgpt/global/core/workflow/runtime/utils';
import { createChatCompletion } from '../../../ai/config'; import { createChatCompletion } from '../../../ai/config';
import type { ChatCompletionMessageParam, StreamChatType } from '@fastgpt/global/core/ai/type.d'; import type { ChatCompletionMessageParam, StreamChatType } from '@fastgpt/global/core/ai/type.d';
import { formatModelChars2Points } from '../../../../support/wallet/usage/utils'; import { formatModelChars2Points } from '../../../../support/wallet/usage/utils';

View File

@@ -196,7 +196,8 @@ export async function syncCollaborators({
permission: item.permission permission: item.permission
})), })),
{ {
session session,
ordered: true
} }
); );
} }

View File

@@ -1,5 +1,5 @@
import { AppDetailType } from '@fastgpt/global/core/app/type'; import { AppDetailType } from '@fastgpt/global/core/app/type';
import { OutLinkSchema } from '@fastgpt/global/support/outLink/type'; import { OutlinkAppType, OutLinkSchema } from '@fastgpt/global/support/outLink/type';
import { parseHeaderCert } from '../controller'; import { parseHeaderCert } from '../controller';
import { MongoOutLink } from '../../outLink/schema'; import { MongoOutLink } from '../../outLink/schema';
import { OutLinkErrEnum } from '@fastgpt/global/common/error/code/outLink'; import { OutLinkErrEnum } from '@fastgpt/global/common/error/code/outLink';
@@ -54,11 +54,15 @@ export async function authOutLinkCrud({
} }
/* outLink exist and it app exist */ /* outLink exist and it app exist */
export async function authOutLinkValid({ shareId }: { shareId?: string }) { export async function authOutLinkValid<T extends OutlinkAppType = any>({
shareId
}: {
shareId?: string;
}) {
if (!shareId) { if (!shareId) {
return Promise.reject(OutLinkErrEnum.linkUnInvalid); return Promise.reject(OutLinkErrEnum.linkUnInvalid);
} }
const outLinkConfig = await MongoOutLink.findOne({ shareId }).lean(); const outLinkConfig = await MongoOutLink.findOne({ shareId }).lean<OutLinkSchema<T>>();
if (!outLinkConfig) { if (!outLinkConfig) {
return Promise.reject(OutLinkErrEnum.linkUnInvalid); return Promise.reject(OutLinkErrEnum.linkUnInvalid);
@@ -66,6 +70,6 @@ export async function authOutLinkValid({ shareId }: { shareId?: string }) {
return { return {
appId: outLinkConfig.appId, appId: outLinkConfig.appId,
outLinkConfig outLinkConfig: outLinkConfig
}; };
} }

View File

@@ -100,7 +100,7 @@ export const initTeamFreePlan = async ({
surplusPoints: freePoints surplusPoints: freePoints
} }
], ],
{ session } { session, ordered: true }
); );
}; };

View File

@@ -160,7 +160,7 @@ export const createTrainingUsage = async ({
] ]
} }
], ],
{ session } { session, ordered: true }
); );
return { billId: String(_id) }; return { billId: String(_id) };

View File

@@ -1,4 +1,4 @@
import React, { useEffect } from 'react'; import React, { useEffect, useState } from 'react';
import type { IconProps } from '@chakra-ui/react'; import type { IconProps } from '@chakra-ui/react';
import { Box, Icon } from '@chakra-ui/react'; import { Box, Icon } from '@chakra-ui/react';
import { iconPaths } from './constants'; import { iconPaths } from './constants';
@@ -8,7 +8,7 @@ import { useRefresh } from '../../../hooks/useRefresh';
const iconCache: Record<string, any> = {}; const iconCache: Record<string, any> = {};
const MyIcon = ({ name, w = 'auto', h = 'auto', ...props }: { name: IconNameType } & IconProps) => { const MyIcon = ({ name, w = 'auto', h = 'auto', ...props }: { name: IconNameType } & IconProps) => {
const { refresh } = useRefresh(); const [, setUpdate] = useState(0);
useEffect(() => { useEffect(() => {
if (iconCache[name]) { if (iconCache[name]) {
@@ -20,7 +20,7 @@ const MyIcon = ({ name, w = 'auto', h = 'auto', ...props }: { name: IconNameType
const component = { as: icon.default }; const component = { as: icon.default };
// Store in cache // Store in cache
iconCache[name] = component; iconCache[name] = component;
refresh(); setUpdate((prev) => prev + 1); // force update
}) })
.catch((error) => console.log(error)); .catch((error) => console.log(error));
}, [name]); }, [name]);

View File

@@ -217,7 +217,7 @@ export function useScrollPagination<
const offset = init ? 0 : data.length; const offset = init ? 0 : data.length;
setTrue(); setTrue();
console.log(offset);
try { try {
const res = await api({ const res = await api({
offset, offset,

View File

@@ -24,6 +24,7 @@
"key_type": "API key format:", "key_type": "API key format:",
"log": "Call log", "log": "Call log",
"log_detail": "Log details", "log_detail": "Log details",
"log_request_id_search": "Search by requestId",
"log_status": "Status", "log_status": "Status",
"mapping": "Model Mapping", "mapping": "Model Mapping",
"mapping_tip": "A valid Json is required. \nThe model can be mapped when sending a request to the actual address. \nFor example:\n{\n \n \"gpt-4o\": \"gpt-4o-test\"\n\n}\n\nWhen FastGPT requests the gpt-4o model, the gpt-4o-test model is sent to the actual address, instead of gpt-4o.", "mapping_tip": "A valid Json is required. \nThe model can be mapped when sending a request to the actual address. \nFor example:\n{\n \n \"gpt-4o\": \"gpt-4o-test\"\n\n}\n\nWhen FastGPT requests the gpt-4o model, the gpt-4o-test model is sent to the actual address, instead of gpt-4o.",

View File

@@ -888,6 +888,7 @@
"error.upload_file_error_filename": "{{name}} Upload Failed", "error.upload_file_error_filename": "{{name}} Upload Failed",
"error.upload_image_error": "File upload failed", "error.upload_image_error": "File upload failed",
"error.username_empty": "Account cannot be empty", "error.username_empty": "Account cannot be empty",
"error_collection_not_exist": "The collection does not exist",
"extraction_results": "Extraction Results", "extraction_results": "Extraction Results",
"field_name": "Field Name", "field_name": "Field Name",
"free": "Free", "free": "Free",

View File

@@ -24,6 +24,7 @@
"key_type": "API key 格式: ", "key_type": "API key 格式: ",
"log": "调用日志", "log": "调用日志",
"log_detail": "日志详情", "log_detail": "日志详情",
"log_request_id_search": "根据 requestId 搜索",
"log_status": "状态", "log_status": "状态",
"mapping": "模型映射", "mapping": "模型映射",
"mapping_tip": "需填写一个有效 Json。可在向实际地址发送请求时对模型进行映射。例如\n{\n \"gpt-4o\": \"gpt-4o-test\"\n}\n当 FastGPT 请求 gpt-4o 模型时,会向实际地址发送 gpt-4o-test 的模型,而不是 gpt-4o。", "mapping_tip": "需填写一个有效 Json。可在向实际地址发送请求时对模型进行映射。例如\n{\n \"gpt-4o\": \"gpt-4o-test\"\n}\n当 FastGPT 请求 gpt-4o 模型时,会向实际地址发送 gpt-4o-test 的模型,而不是 gpt-4o。",

View File

@@ -891,6 +891,7 @@
"error.upload_file_error_filename": "{{name}} 上传失败", "error.upload_file_error_filename": "{{name}} 上传失败",
"error.upload_image_error": "上传文件失败", "error.upload_image_error": "上传文件失败",
"error.username_empty": "账号不能为空", "error.username_empty": "账号不能为空",
"error_collection_not_exist": "集合不存在",
"extraction_results": "提取结果", "extraction_results": "提取结果",
"field_name": "字段名", "field_name": "字段名",
"free": "免费", "free": "免费",

View File

@@ -22,6 +22,7 @@
"key_type": "API key 格式:", "key_type": "API key 格式:",
"log": "調用日誌", "log": "調用日誌",
"log_detail": "日誌詳情", "log_detail": "日誌詳情",
"log_request_id_search": "根據 requestId 搜索",
"log_status": "狀態", "log_status": "狀態",
"mapping": "模型映射", "mapping": "模型映射",
"mapping_tip": "需填寫一個有效 Json。\n可在向實際地址發送請求時對模型進行映射。\n例如\n{\n \n \"gpt-4o\": \"gpt-4o-test\"\n\n}\n\n當 FastGPT 請求 gpt-4o 模型時,會向實際地址發送 gpt-4o-test 的模型,而不是 gpt-4o。", "mapping_tip": "需填寫一個有效 Json。\n可在向實際地址發送請求時對模型進行映射。\n例如\n{\n \n \"gpt-4o\": \"gpt-4o-test\"\n\n}\n\n當 FastGPT 請求 gpt-4o 模型時,會向實際地址發送 gpt-4o-test 的模型,而不是 gpt-4o。",

View File

@@ -888,6 +888,7 @@
"error.upload_file_error_filename": "{{name}} 上傳失敗", "error.upload_file_error_filename": "{{name}} 上傳失敗",
"error.upload_image_error": "上傳文件失敗", "error.upload_image_error": "上傳文件失敗",
"error.username_empty": "帳號不能為空", "error.username_empty": "帳號不能為空",
"error_collection_not_exist": "集合不存在",
"extraction_results": "提取結果", "extraction_results": "提取結果",
"field_name": "欄位名稱", "field_name": "欄位名稱",
"free": "免費", "free": "免費",

5
plugins/README.md Normal file
View File

@@ -0,0 +1,5 @@
# 目录说明
该目录为 FastGPT 辅助子项目,非必须。
- model 私有化模型

View File

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 91 KiB

View File

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 86 KiB

View File

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 77 KiB

View File

Before

Width:  |  Height:  |  Size: 293 KiB

After

Width:  |  Height:  |  Size: 293 KiB

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