Compare commits

..

16 Commits

Author SHA1 Message Date
archer
8af3d85b8a add gemini model 2025-01-25 14:25:10 +08:00
archer
fcf14af64d comment 2025-01-25 14:21:21 +08:00
heheer
991fbe254c fix interactive edge (#3659)
* fix interactive edge

* fix
2025-01-25 14:12:12 +08:00
Archer
ab0fc517dc fix: err tip (#3666)
* fix: err tip

* perf: training queue

* doc
2025-01-25 14:10:56 +08:00
Archer
92105e9a0b reload buffer (#3665)
* reload buffer

* reload buffer

* tts selector
2025-01-25 13:12:21 +08:00
Archer
d2948d7e57 feat: markdown extension (#3663)
* feat: markdown extension

* media cros

* rerank test

* default price

* perf: default model

* fix: cannot custom provider

* fix: default model select

* update bg

* perf: default model selector

* fix: usage export

* i18n

* fix: rerank

* update init extension

* perf: ip limit check

* doubao model order

* web default modle

* perf: tts selector

* perf: tts error

* qrcode package
2025-01-24 23:42:04 +08:00
heheer
02fcb6a61e export usage csv i18n (#3660)
* export usage csv i18n

* fix build
2025-01-24 19:09:08 +08:00
a.e.
4f5a12f33b fix: false triggerd org selection (#3661) 2025-01-24 19:07:36 +08:00
Archer
38efa3e050 feat: default model (#3662)
* move model config

* feat: default model
2025-01-24 18:44:43 +08:00
a.e.
5ce889942a fix: POST 500 error on dingtalk bot (#3655) 2025-01-24 14:10:40 +08:00
Archer
60c72d05d1 model perf (#3657)
* fix: model

* dataset quote

* perf: model config

* model tag

* doubao model config

* perf: config model

* feat: model test
2025-01-24 14:10:14 +08:00
Archer
99ce976b06 4.8.20 test (#3656)
* provider

* perf: model config
2025-01-23 18:32:45 +08:00
heheer
2c03abc6e1 add default model config (#3653) 2025-01-23 18:19:57 +08:00
Archer
34b510cba1 perf: usages list;perf: move components (#3654)
* perf: usages list

* team sub plan load

* perf: usage dashboard code

* perf: dashboard ui

* perf: move components
2025-01-23 17:29:39 +08:00
heheer
0c05add8b2 feat: usage filter & export & dashbord (#3538)
* feat: usage filter & export & dashbord

* adjust ui

* fix tmb scroll

* fix code & selecte all

* merge
2025-01-23 10:54:30 +08:00
Archer
e009be51e7 Aiproxy (#3649)
* model config

* feat: model config ui

* perf: rename variable

* feat: custom request url

* perf: model buffer

* perf: init model

* feat: json model config

* auto login

* fix: ts

* update packages

* package

* fix: dockerfile
2025-01-22 22:59:28 +08:00
198 changed files with 1703 additions and 4490 deletions

View File

@@ -58,7 +58,7 @@ jobs:
# Step 4 - Builds the site using Hugo
- name: Build
run: cd docSite && hugo mod get -u github.com/colinwilson/lotusdocs@6d0568e && hugo -v --minify
run: cd docSite && hugo mod get -u github.com/colinwilson/lotusdocs && hugo -v --minify
# Step 5 - Push our generated site to Vercel
- name: Deploy to Vercel

View File

@@ -58,7 +58,7 @@ jobs:
# Step 4 - Builds the site using Hugo
- name: Build
run: cd docSite && hugo mod get -u github.com/colinwilson/lotusdocs@6d0568e && hugo -v --minify
run: cd docSite && hugo mod get -u github.com/colinwilson/lotusdocs && hugo -v --minify
# Step 5 - Push our generated site to Vercel
- name: Deploy to Vercel

View File

@@ -83,7 +83,6 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
- [x] 统一查阅对话记录,并对数据进行标注
`6` 其他
- [x] 可视化模型配置。
- [x] 支持语音输入和输出 (可配置语音输入语音回答)
- [x] 模糊输入提示
- [x] 模板市场

View File

@@ -3,7 +3,7 @@ FROM hugomods/hugo:0.117.0 AS builder
WORKDIR /app
ADD ./docSite hugo
RUN cd /app/hugo && hugo mod get -u github.com/colinwilson/lotusdocs@6d0568e && hugo -v --minify
RUN cd /app/hugo && hugo mod get -u github.com/colinwilson/lotusdocs && hugo -v --minify
FROM fholzer/nginx-brotli:latest

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 KiB

View File

@@ -13,8 +13,8 @@ weight: 707
下面配置文件示例中包含了系统参数和各个模型配置:
## 4.8.20+ 版本新配置文件示例
> 从4.8.20版本开始,模型在页面中进行配置。
## 4.6.8+ 版本新配置文件示例
```json
{
"feConfigs": {
@@ -27,4 +27,4 @@ weight: 707
"pgHNSWEfSearch": 100 // 向量搜索参数。越大搜索越精确但是速度越慢。设置为100有99%+精度。
}
}
```
```

View File

@@ -7,13 +7,6 @@ toc: true
weight: 707
---
## 前置知识
1. 基础的网络知识:端口,防火墙……
2. Docker 和 Docker Compose 基础知识
3. 大模型相关接口和参数
4. RAG 相关知识:向量模型,向量数据库,向量检索
## 部署架构图
![](/imgs/sealos-fastgpt.webp)
@@ -211,8 +204,6 @@ docker restart oneapi
### 6. 配置模型
务必先配置至少一组模型,否则系统无法正常使用。
[点击查看模型配置教程](/docs/development/modelConfig/intro/)
## FAQ

View File

@@ -9,31 +9,17 @@ images: []
## 一、错误排查方式
可以先找找[Issue](https://github.com/labring/FastGPT/issues),或新提 Issue私有部署错误务必提供详细的操作步骤、日志、截图否则很难排查。
### 获取后端错误
遇到问题先按下面方式排查。
1. `docker ps -a` 查看所有容器运行状态,检查是否全部 running如有异常尝试`docker logs 容器名`查看对应日志。
2. 容器都运行正常的,`docker logs 容器名` 查看报错日志
3. 带有`requestId`的,都是 OneAPI 提示错误,大部分都是因为模型接口报错。
4. 无法解决时,可以找找[Issue](https://github.com/labring/FastGPT/issues),或新提 Issue私有部署错误务必提供详细的日志否则很难排查。
### 前端错误
前端报错时,页面会出现崩溃,并提示检查控制台日志。可以打开浏览器控制台,并查看`console`中的 log 日志。还可以点击对应 log 的超链接,会提示到具体错误文件,可以把这些详细错误信息提供,方便排查。
### OneAPI 错误
带有`requestId`的,都是 OneAPI 提示错误,大部分都是因为模型接口报错。可以参考 [OneAPI 常见错误](/docs/development/faq/#三常见的-oneapi-错误)
## 二、通用问题
### 前端页面崩溃
1. 90% 情况是模型配置不正确:确保每类模型都至少有一个启用;检查模型中一些`对象`参数是否异常(数组和对象),如果为空,可以尝试给个空数组或空对象。
2. 少部分是由于浏览器兼容问题,由于项目中包含一些高阶语法,可能低版本浏览器不兼容,可以将具体操作步骤和控制台中错误信息提供 issue。
3. 关闭浏览器翻译功能,如果浏览器开启了翻译,可能会导致页面崩溃。
### 通过sealos部署的话是否没有本地部署的一些限制
![](/imgs/faq1.png)
这是索引模型的长度限制,通过任何方式部署都一样的,但不同索引模型的配置不一样,可以在后台修改参数。
@@ -144,7 +130,7 @@ OneAPI 的 API Key 配置错误,需要修改`OPENAI_API_KEY`环境变量,并
## 四、常见模型问题
### 如何检查模型可用性问题
### 如何检查模型问题
1. 私有部署模型,先确认部署的模型是否正常。
2. 通过 CURL 请求,直接测试上游模型是否正常运行(云端模型或私有模型均进行测试)
@@ -417,7 +403,3 @@ curl --location --request POST 'https://oneapi.xxxx/v1/chat/completions' \
"tool_choice": "auto"
}'
```
### 向量检索得分大于 1
由于模型没有归一化导致的。目前仅支持归一化的模型。

View File

@@ -11,9 +11,7 @@ weight: 744
从 4.8.20 版本开始,你可以直接在 FastGPT 页面中进行模型配置,并且系统内置了大量模型,无需从 0 开始配置。下面介绍模型配置的基本流程:
## 配置模型
### 1. 使用 OneAPI 对接模型提供商
## 1. 使用 OneAPI 对接模型提供商
可以使用 [OneAPI 接入教程](/docs/development/modelconfig/one-api) 来进行模型聚合,从而可以对接更多模型提供商。你需要先在各服务商申请好 API 接入 OneAPI 后,才能在 FastGPT 中使用这些模型。示例流程如下:
@@ -28,46 +26,44 @@ weight: 744
在 OneAPI 配置好模型后,你就可以打开 FastGPT 页面,启用对应模型了。
### 2. 登录 root 用户
## 2. 登录 root 用户
仅 root 用户可以进行模型配置。
### 3. 进入模型配置页面
## 3. 进入模型配置页面
登录 root 用户后,在`账号-模型提供商-模型配置`中,你可以看到所有内置的模型和自定义模型,以及哪些模型启用了。
![alt text](/image-90.png)
### 4. 配置介绍
## 4. 配置介绍
{{% alert icon="🤖 " context="success" %}}
注意:
1. 目前语音识别模型和重排模型仅会生效一个,所以配置时候,只需要配置一个即可。
2. 系统至少需要一个语言模型和一个索引模型才能正常使用。
注意:目前语音识别模型和重排模型仅会生效一个,所以配置时候,只需要配置一个即可。
{{% /alert %}}
#### 核心配置
### 核心配置
- 模型 ID接口请求时候Body 中`model`字段的值,全局唯一。
- 自定义请求地址/Key:如果需要绕过`OneAPI`,可以设置自定义请求地址和 Token。一般情况下不需要如果 OneAPI 不支持某些模型,可以使用该特性。
- 模型 ID实际发出请求的`model`值,全局唯一。
- 自定义请求地址/Token:如果需要绕过`OneAPI`,可以设置自定义请求地址和 Token。一般情况下不需要如果 OneAPI 不支持某些模型,可以使用该特性。
#### 模型类型
### 模型类型
1. 语言模型 - 进行文本对话,多模态模型支持图片识别。
2. 索引模型 - 对文本块进行索引,用于相关文本检索。
3. 重排模型 - 对检索结果进行重排,用于优化检索排名
4. 语音合成 - 将文本转换为语音
5. 语音识别 - 将语音转换为文本
3. 语音合成 - 将文本转换为语音
4. 语音识别 - 将语音转换为文本
5. 重排模型 - 对文本进行重排,用于优化文本质量
#### 启用模型
### 启用模型
系统内置了目前主流厂商的模型,如果你不熟悉配置,直接点击`启用`即可,需要注意是,`模型 ID`需要和 OneAPI 中渠道的`模型`一致。
系统内置了目前主流厂商的模型,如果你不熟悉配置,直接点击`启用`即可,需要注意是,模型 ID 需要和 OneAPI 中渠道的`模型`一致。
| | |
| --- | --- |
| ![alt text](/imgs/image-91.png) | ![alt text](/imgs/image-92.png) |
#### 修改模型配置
### 修改模型配置
点击模型右侧的齿轮即可进行模型配置,不同类型模型的配置有区别。
@@ -75,7 +71,7 @@ weight: 744
| --- | --- |
| ![alt text](/imgs/image-93.png) | ![alt text](/imgs/image-94.png) |
## 新增自定义模型
### 新增自定义模型
如果系统内置的模型无法满足你的需求,你可以添加自定义模型。自定义模型中,如果`模型 ID`与系统内置的模型 ID 一致,则会被认为是修改系统模型。
@@ -83,7 +79,7 @@ weight: 744
| --- | --- |
| ![alt text](/imgs/image-96.png) | ![alt text](/imgs/image-97.png) |
#### 通过配置文件配置
### 通过配置文件配置
如果你觉得通过页面配置模型比较麻烦,你也可以通过配置文件来配置模型。或者希望快速将一个系统的配置,复制到另一个系统,也可以通过配置文件来实现。
@@ -210,7 +206,7 @@ FastGPT 页面上提供了每类模型的简单测试,可以初步检查模型
![alt text](/imgs/image-105.png)
## 特殊接入示例
## 模型接入示例
### ReRank 模型接入
@@ -231,60 +227,6 @@ FastGPT 页面上提供了每类模型的简单测试,可以初步检查模型
[点击查看部署 ReRank 模型教程](/docs/development/custom-models/bge-rerank/)
### 接入语音识别模型
OneAPI 的语言识别接口,无法正确的识别其他模型(会始终识别成 whisper-1所以如果想接入其他模型可以通过自定义请求地址来实现。例如接入硅基流动的 `FunAudioLLM/SenseVoiceSmall` 模型,可以参考如下配置:
点击模型编辑:
![alt text](/imgs/image-106.png)
填写硅基流动的地址:`https://api.siliconflow.cn/v1/audio/transcriptions`,并填写硅基流动的 API Key。
![alt text](/imgs/image-107.png)
## 其他配置项说明
### 自定义请求地址
如果填写了该值,则可以允许你绕过 OneAPI直接向自定义请求地址发起请求。需要填写完整的请求地址例如
- LLM: {{host}}/v1/chat/completions
- Embedding: {{host}}/v1/embeddings
- STT: {{host}}/v1/audio/transcriptions
- TTS: {{host}}/v1/audio/speech
- Rerank: {{host}}/v1/rerank
自定义请求 Key则是向自定义请求地址发起请求时候携带请求头Authorization: Bearer xxx 进行请求。
所有接口均遵循 OpenAI 提供的模型格式,可参考 [OpenAI API 文档](https://platform.openai.com/docs/api-reference/introduction) 进行配置。
由于 OpenAI 没有提供 ReRank 模型,遵循的是 Cohere 的格式。[点击查看接口请求示例](/docs/development/faq/#如何检查模型问题)
### 模型价格配置
商业版用户可以通过配置模型价格,来进行账号计费。系统包含两种计费模式:按总 tokens 计费和输入输出 Tokens 分开计费。
如果需要配置`输入输出 Tokens 分开计费模式`,则填写`模型输入价格``模型输出价格`两个值。
如果需要配置`按总 tokens 计费模式`,则填写`模型综合价格`一个值。
## 如何提交内置模型
由于模型更新非常频繁,官方不一定及时更新,如果未能找到你期望的内置模型,你可以[提交 Issue](https://github.com/labring/FastGPT/issues),提供模型的名字和对应官网。或者直接[提交 PR](https://github.com/labring/FastGPT/pulls),提供模型配置。
### 添加模型提供商
如果你需要添加模型提供商,需要修改以下代码:
1. FastGPT/packages/web/components/common/Icon/icons/model - 在此目录下,添加模型提供商的 svg 头像地址。
2. 在 FastGPT 根目录下,运行`pnpm initIcon`,将图片加载到配置文件中。
3. FastGPT/packages/global/core/ai/provider.ts - 在此文件中,追加模型提供商的配置。
### 添加模型
你可以在`FastGPT/packages/service/core/ai/config/provider`目录下,找对应模型提供商的配置文件,并追加模型配置。请自行全文检查,`model`字段,必须在所有模型中唯一。具体配置字段说明,参考[模型配置字段说明](/docs/development/modelconfig/intro/#通过配置文件配置)
## 旧版模型配置说明

View File

@@ -672,7 +672,7 @@ curl --location --request POST 'http://localhost:3000/api/core/chat/getHistories
"appId": "appId",
"offset": 0,
"pageSize": 20,
"source": "api"
"source: "api"
}'
```

View File

@@ -11,7 +11,7 @@ weight: 860
在 FastGPT V4.6.4 中,我们修改了分享链接的数据读取方式,为每个用户生成一个 localId用于标识用户从云端拉取对话记录。但是这种方式仅能保障用户在同一设备同一浏览器中使用如果切换设备或者清空浏览器缓存则会丢失这些记录。这种方式存在一定的风险因此我们仅允许用户拉取近`30天``20条`记录。
分享链接身份鉴权设计的目的在于,将 FastGPT 的对话框快速、安全的接入到你现有的系统中,仅需 2 个接口即可实现。该功能目前只在商业版中提供。
分享链接身份鉴权设计的目的在于,将 FastGPT 的对话框快速、安全的接入到你现有的系统中,仅需 2 个接口即可实现。
## 使用说明

View File

@@ -60,10 +60,6 @@ FastGPT 使用了 one-api 项目来管理模型池,其可以兼容 OpenAI 、A
### 3. 配置模型
### 4. 配置模型
务必先配置至少一组模型,否则系统无法正常使用。
[点击查看模型配置教程](/docs/development/modelConfig/intro/)
## 收费

View File

@@ -1,5 +1,5 @@
---
title: 'V4.8.19(包含升级脚本)'
title: 'V4.8.19(进行中)'
description: 'FastGPT V4.8.19 更新说明'
icon: 'upgrade'
draft: false

View File

@@ -1,5 +1,5 @@
---
title: 'V4.8.20(包含升级脚本)'
title: 'V4.8.20(进行中)'
description: 'FastGPT V4.8.20 更新说明'
icon: 'upgrade'
draft: false
@@ -9,19 +9,14 @@ weight: 804
## 更新指南
### 1. 做好数据库备份
### 2. 更新环境变量
### 1. 更新环境变量
如果有很早版本用户,配置了`ONEAPI_URL`的,需要统一改成`OPENAI_BASE_URL`
### 3. 更新镜像:
### 1. 更新镜像:
- 更新 fastgpt 镜像 tag: v4.8.20-fix2
- 更新 fastgpt-pro 商业版镜像 tag: v4.8.20-fix2
- Sandbox 镜像无需更新
### 4. 运行升级脚本
### 2. 运行升级脚本
从任意终端,发起 1 个 HTTP 请求。其中 {{rootkey}} 替换成环境变量里的 `rootkey`{{host}} 替换成**FastGPT 域名**。
@@ -31,20 +26,13 @@ curl --location --request POST 'https://{{host}}/api/admin/initv4820' \
--header 'Content-Type: application/json'
```
脚本会自动把原配置文件的模型加载到新版模型配置中
自动把原配置文件的模型加载到新版模型配置中
## 完整更新内容
1. 新增 - 可视化模型参数配置,取代原配置文件配置模型。预设超过 100 个模型配置。同时支持所有类型模型的一键测试。(预计下个版本会完全支持在页面上配置渠道)。
2. 新增 - DeepSeek resoner 模型支持输出思考过程
3. 新增 - 使用记录导出和仪表盘
4. 新增 - markdown 语法扩展,支持音视频(代码块 audio 和 video
5. 新增 - 调整 max_tokens 计算逻辑。优先保证 max_tokens 为配置值,如超出最大上下文,则减少历史记录。例如:如果申请 8000 的 max_tokens则上下文长度会减少 8000
6. 优化 - 问题优化增加上下文过滤,避免超出上下文。
7. 优化 - 页面组件抽离,减少页面组件路由。
8. 优化 - 全文检索,忽略大小写。
9. 优化 - 问答生成和增强索引改成流输出,避免部分模型超时。
10. 优化 - 自动给 assistant 空 content补充 null同时合并连续的 text assistant避免部分模型抛错。
11. 优化 - 调整图片 Host 取消上传时补充 FE_DOMAIN改成发送对话前补充避免替换域名后原图片无法正常使用。
12. 修复 - 部分场景成员列表无法触底加载。
13. 修复 - 工作流递归执行,部分条件下无法正常运行。
1. 新增 - 可视化模型参数配置。预设超过 100 个模型配置。同时支持所有类型模型的一键测试。(预计下个版本会完全支持在页面上配置渠道)。
2. 新增 - 使用记录导出和仪表盘
3. 新增 - markdown 语法扩展,支持音视频(代码块 audio 和 video
4. 优化 - 页面组件抽离,减少页面组件路由
5. 优化 - 全文检索,忽略大小写
6. 优化 - 问答生成和增强索引改成流输出,避免部分模型超时。

View File

@@ -1,39 +0,0 @@
---
title: 'V4.8.21'
description: 'FastGPT V4.8.21 更新说明'
icon: 'upgrade'
draft: false
toc: true
weight: 803
---
## 更新指南
### 1. 做好数据库备份
### 2. 更新镜像:
- 更新 fastgpt 镜像 tag: v4.8.21
- 更新 fastgpt-pro 商业版镜像 tag: v4.8.21
- Sandbox 镜像无需更新
## 完整更新内容
1. 新增 - 弃用/已删除的插件提示。
2. 新增 - 对话日志按来源分类、标题检索、导出功能。
3. 新增 - 全局变量支持拖拽排序。
4. 新增 - LLM 模型支持 top_p, response_format, json_schema 参数。
5. 新增 - Doubao1.5 模型预设。阿里 embedding3 预设。
6. 新增 - 向量模型支持归一化配置,以便适配未归一化的向量模型,例如 Doubao 的 embedding 模型。
6. 新增 - AI 对话节点,支持输出思考过程结果,可用于其他节点引用。
7. 优化 - 网站嵌入式聊天窗口,增加窗口位置适配。
8. 优化 - 模型未配置时错误提示。
9. 优化 - 适配非 Stream 模式思考输出。
10. 优化 - 增加 TTS voice 未配置时的空指针保护。
11. 优化 - Markdown 链接解析分割规则,改成严格匹配模式,牺牲兼容多种情况,减少误解析。
12. 优化 - 减少未登录用户的数据获取范围,提高系统隐私性。
13. 修复 - 简易模式,切换到其他非视觉模型时候,会强制关闭图片识别。
14. 修复 - o1,o3 模型,在测试时候字段映射未生效导致报错。
15. 修复 - 公众号对话空指针异常。
16. 修复 - 多个音频/视频文件展示异常。
17. 修复 - 分享链接鉴权报错后无限循环。

View File

@@ -7,7 +7,7 @@ toc: true
weight: 234
---
知识库搜索具体参数说明,以及内部逻辑请移步:[FastGPT知识库搜索方案](/docs/guide/knowledge_base/rag/)
知识库搜索具体参数说明,以及内部逻辑请移步:[FastGPT知识库搜索方案](/docs/course/data_search/)
## 特点
@@ -27,7 +27,7 @@ weight: 234
### 输入 - 搜索参数
[点击查看参数介绍](/docs/guide/knowledge_base/dataset_engine/#搜索参数)
[点击查看参数介绍](/docs/course/data_search/#搜索参数)
### 输出 - 引用内容

View File

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

View File

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

View File

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

View File

@@ -16,7 +16,7 @@ export const bucketNameMap = {
}
};
export const ReadFileBaseUrl = `${process.env.FILE_DOMAIN || process.env.FE_DOMAIN || ''}${process.env.NEXT_PUBLIC_BASE_URL || ''}/api/common/file/read`;
export const ReadFileBaseUrl = `${process.env.FE_DOMAIN || ''}${process.env.NEXT_PUBLIC_BASE_URL || ''}/api/common/file/read`;
export const documentFileType = '.txt, .docx, .csv, .xlsx, .pdf, .md, .html, .pptx';
export const imageFileType =

View File

@@ -26,7 +26,7 @@ export const simpleText = (text = '') => {
};
export const valToStr = (val: any) => {
if (val === undefined) return '';
if (val === undefined) return 'undefined';
if (val === null) return 'null';
if (typeof val === 'object') return JSON.stringify(val);

View File

@@ -26,19 +26,13 @@ type BaseModelItemType = {
export type LLMModelItemType = PriceType &
BaseModelItemType & {
type: ModelTypeEnum.llm;
// Model params
maxContext: number;
maxResponse: number;
quoteMaxToken: number;
maxTemperature?: number;
showTopP?: boolean;
responseFormatList?: string[];
showStopSign?: boolean;
maxTemperature: number;
censor?: boolean;
vision?: boolean;
reasoning?: boolean;
// diff function model
datasetProcess?: boolean; // dataset
@@ -64,7 +58,6 @@ export type EmbeddingModelItemType = PriceType &
maxToken: number; // model max token
weight: number; // training weight
hidden?: boolean; // Disallow creation
normalization?: boolean; // normalization processing
defaultConfig?: Record<string, any>; // post request config
dbConfig?: Record<string, any>; // Custom parameters for storage
queryConfig?: Record<string, any>; // Custom parameters for query

View File

@@ -61,9 +61,6 @@ export const getModelFromList = (
model: string
) => {
const modelData = modelList.find((item) => item.model === model) ?? modelList[0];
if (!modelData) {
throw new Error('No Key model is configured');
}
const provider = getModelProvider(modelData.provider);
return {
...modelData,

View File

@@ -11,8 +11,8 @@ export type ModelProviderIdType =
| 'AliCloud'
| 'Qwen'
| 'Doubao'
| 'DeepSeek'
| 'ChatGLM'
| 'DeepSeek'
| 'Ernie'
| 'Moonshot'
| 'MiniMax'

View File

@@ -74,17 +74,12 @@ export type AppDetailType = AppSchema & {
export type AppSimpleEditFormType = {
// templateId: string;
aiSettings: {
[NodeInputKeyEnum.aiModel]: string;
[NodeInputKeyEnum.aiSystemPrompt]?: string | undefined;
[NodeInputKeyEnum.aiChatTemperature]?: number;
[NodeInputKeyEnum.aiChatMaxToken]?: number;
[NodeInputKeyEnum.aiChatIsResponseText]: boolean;
model: string;
systemPrompt?: string | undefined;
temperature?: number;
maxToken?: number;
isResponseAnswerText: boolean;
maxHistories: number;
[NodeInputKeyEnum.aiChatReasoning]?: boolean; // Is open reasoning mode
[NodeInputKeyEnum.aiChatTopP]?: number;
[NodeInputKeyEnum.aiChatStopSign]?: string;
[NodeInputKeyEnum.aiChatResponseFormat]?: string;
[NodeInputKeyEnum.aiChatJsonSchema]?: string;
};
dataset: {
datasets: SelectedDatasetType;
@@ -122,11 +117,6 @@ export type SettingAIDataType = {
isResponseAnswerText?: boolean;
maxHistories?: number;
[NodeInputKeyEnum.aiChatVision]?: boolean; // Is open vision mode
[NodeInputKeyEnum.aiChatReasoning]?: boolean; // Is open reasoning mode
[NodeInputKeyEnum.aiChatTopP]?: number;
[NodeInputKeyEnum.aiChatStopSign]?: string;
[NodeInputKeyEnum.aiChatResponseFormat]?: string;
[NodeInputKeyEnum.aiChatJsonSchema]?: string;
};
// variable

View File

@@ -7,8 +7,6 @@ import { StoreNodeItemType } from '../workflow/type/node';
import { DatasetSearchModeEnum } from '../dataset/constants';
import { WorkflowTemplateBasicType } from '../workflow/type';
import { AppTypeEnum } from './constants';
import { AppErrEnum } from '../../common/error/code/app';
import { PluginErrEnum } from '../../common/error/code/plugin';
export const getDefaultAppForm = (): AppSimpleEditFormType => {
return {
@@ -18,8 +16,7 @@ export const getDefaultAppForm = (): AppSimpleEditFormType => {
temperature: 0,
isResponseAnswerText: true,
maxHistories: 6,
maxToken: 4000,
aiChatReasoning: true
maxToken: 4000
},
dataset: {
datasets: [],
@@ -119,8 +116,7 @@ export const appWorkflow2Form = ({
version: node.version,
inputs: node.inputs,
outputs: node.outputs,
templateType: FlowNodeTemplateTypeEnum.other,
pluginData: node.pluginData
templateType: FlowNodeTemplateTypeEnum.other
});
} else if (node.flowNodeType === FlowNodeTypeEnum.systemConfig) {
defaultAppForm.chatConfig = getAppChatConfig({
@@ -150,18 +146,3 @@ export const getAppType = (config?: WorkflowTemplateBasicType | AppSimpleEditFor
}
return '';
};
export const checkAppUnExistError = (error?: string) => {
const unExistError: Array<string> = [
AppErrEnum.unAuthApp,
AppErrEnum.unExist,
PluginErrEnum.unAuth,
PluginErrEnum.unExist
];
if (!!error && unExistError.includes(error)) {
return error;
} else {
return undefined;
}
};

View File

@@ -25,8 +25,7 @@ export enum ChatItemValueTypeEnum {
text = 'text',
file = 'file',
tool = 'tool',
interactive = 'interactive',
reasoning = 'reasoning'
interactive = 'interactive'
}
export enum ChatSourceEnum {

View File

@@ -70,23 +70,14 @@ export type SystemChatItemType = {
obj: ChatRoleEnum.System;
value: SystemChatItemValueItemType[];
};
export type AIChatItemValueItemType = {
type:
| ChatItemValueTypeEnum.text
| ChatItemValueTypeEnum.reasoning
| ChatItemValueTypeEnum.tool
| ChatItemValueTypeEnum.interactive;
type: ChatItemValueTypeEnum.text | ChatItemValueTypeEnum.tool | ChatItemValueTypeEnum.interactive;
text?: {
content: string;
};
reasoning?: {
content: string;
};
tools?: ToolModuleResponseItemType[];
interactive?: WorkflowInteractiveResponseType;
};
export type AIChatItemType = {
obj: ChatRoleEnum.AI;
value: AIChatItemValueItemType[];

View File

@@ -33,10 +33,8 @@ export enum WorkflowIOValueTypeEnum {
dynamic = 'dynamic',
// plugin special type
selectDataset = 'selectDataset',
// abandon
selectApp = 'selectApp'
selectApp = 'selectApp',
selectDataset = 'selectDataset'
}
export const toolValueTypeList = [
@@ -143,11 +141,6 @@ export enum NodeInputKeyEnum {
aiChatDatasetQuote = 'quoteQA',
aiChatVision = 'aiChatVision',
stringQuoteText = 'stringQuoteText',
aiChatReasoning = 'aiChatReasoning',
aiChatTopP = 'aiChatTopP',
aiChatStopSign = 'aiChatStopSign',
aiChatResponseFormat = 'aiChatResponseFormat',
aiChatJsonSchema = 'aiChatJsonSchema',
// dataset
datasetSelectList = 'datasets',
@@ -160,10 +153,6 @@ export enum NodeInputKeyEnum {
datasetSearchExtensionBg = 'datasetSearchExtensionBg',
collectionFilterMatch = 'collectionFilterMatch',
authTmbId = 'authTmbId',
datasetDeepSearch = 'datasetDeepSearch',
datasetDeepSearchModel = 'datasetDeepSearchModel',
datasetDeepSearchMaxTimes = 'datasetDeepSearchMaxTimes',
datasetDeepSearchBg = 'datasetDeepSearchBg',
// concat dataset
datasetQuoteList = 'system_datasetQuoteList',
@@ -231,8 +220,7 @@ export enum NodeOutputKeyEnum {
// common
userChatInput = 'userChatInput',
history = 'history',
answerText = 'answerText', // node answer. the value will be show and save to history
reasoningText = 'reasoningText', // node reasoning. the value will be show but not save to history
answerText = 'answerText', // module answer. the value will be show and save to history
success = 'success',
failed = 'failed',
error = 'error',

View File

@@ -140,14 +140,7 @@ export enum FlowNodeTypeEnum {
}
// node IO value type
export const FlowValueTypeMap: Record<
WorkflowIOValueTypeEnum,
{
label: string;
value: WorkflowIOValueTypeEnum;
abandon?: boolean;
}
> = {
export const FlowValueTypeMap = {
[WorkflowIOValueTypeEnum.string]: {
label: 'String',
value: WorkflowIOValueTypeEnum.string
@@ -196,6 +189,10 @@ export const FlowValueTypeMap: Record<
label: i18nT('common:core.workflow.Dataset quote'),
value: WorkflowIOValueTypeEnum.datasetQuote
},
[WorkflowIOValueTypeEnum.selectApp]: {
label: i18nT('common:plugin.App'),
value: WorkflowIOValueTypeEnum.selectApp
},
[WorkflowIOValueTypeEnum.selectDataset]: {
label: i18nT('common:core.chat.Select dataset'),
value: WorkflowIOValueTypeEnum.selectDataset
@@ -203,11 +200,6 @@ export const FlowValueTypeMap: Record<
[WorkflowIOValueTypeEnum.dynamic]: {
label: i18nT('common:core.workflow.dynamic_input'),
value: WorkflowIOValueTypeEnum.dynamic
},
[WorkflowIOValueTypeEnum.selectApp]: {
label: 'selectApp',
value: WorkflowIOValueTypeEnum.selectApp,
abandon: true
}
};
@@ -227,6 +219,3 @@ export const datasetQuoteValueDesc = `{
q: string;
a: string
}[]`;
export const datasetSelectValueDesc = `{
datasetId: string;
}[]`;

View File

@@ -123,7 +123,6 @@ export type DispatchNodeResponseType = {
temperature?: number;
maxToken?: number;
quoteList?: SearchDataResponseItemType[];
reasoningText?: string;
historyPreview?: {
obj: `${ChatRoleEnum}`;
value: string;
@@ -134,17 +133,9 @@ export type DispatchNodeResponseType = {
limit?: number;
searchMode?: `${DatasetSearchModeEnum}`;
searchUsingReRank?: boolean;
queryExtensionResult?: {
model: string;
inputTokens: number;
outputTokens: number;
query: string;
};
deepSearchResult?: {
model: string;
inputTokens: number;
outputTokens: number;
};
extensionModel?: string;
extensionResult?: string;
extensionTokens?: number;
// dataset concat
concatLength?: number;
@@ -207,11 +198,6 @@ export type DispatchNodeResponseType = {
// tool params
toolParamsResult?: Record<string, any>;
// abandon
extensionModel?: string;
extensionResult?: string;
extensionTokens?: number;
};
export type DispatchNodeResultType<T = {}> = {
@@ -234,11 +220,6 @@ export type AIChatNodeProps = {
[NodeInputKeyEnum.aiChatMaxToken]?: number;
[NodeInputKeyEnum.aiChatIsResponseText]: boolean;
[NodeInputKeyEnum.aiChatVision]?: boolean;
[NodeInputKeyEnum.aiChatReasoning]?: boolean;
[NodeInputKeyEnum.aiChatTopP]?: number;
[NodeInputKeyEnum.aiChatStopSign]?: string;
[NodeInputKeyEnum.aiChatResponseFormat]?: string;
[NodeInputKeyEnum.aiChatJsonSchema]?: string;
[NodeInputKeyEnum.aiChatQuoteRole]?: AiChatQuoteRoleType;
[NodeInputKeyEnum.aiChatQuoteTemplate]?: string;

View File

@@ -292,12 +292,13 @@ export const getReferenceVariableValue = ({
export const formatVariableValByType = (val: any, valueType?: WorkflowIOValueTypeEnum) => {
if (!valueType) return val;
if (val === undefined || val === null) return;
// Value type check, If valueType invalid, return undefined
if (valueType.startsWith('array') && !Array.isArray(val)) return undefined;
if (valueType === WorkflowIOValueTypeEnum.boolean) return Boolean(val);
if (valueType === WorkflowIOValueTypeEnum.number) return Number(val);
if (valueType === WorkflowIOValueTypeEnum.string) {
if (val === undefined) return 'undefined';
if (val === null) return 'null';
return typeof val === 'object' ? JSON.stringify(val) : String(val);
}
if (
@@ -363,14 +364,12 @@ export function replaceEditorVariable({
export const textAdaptGptResponse = ({
text,
reasoning_content,
model = '',
finish_reason = null,
extraData = {}
}: {
model?: string;
text?: string | null;
reasoning_content?: string | null;
text: string | null;
finish_reason?: null | 'stop';
extraData?: Object;
}) => {
@@ -382,11 +381,10 @@ export const textAdaptGptResponse = ({
model,
choices: [
{
delta: {
role: ChatCompletionRequestMessageRoleEnum.Assistant,
content: text,
...(reasoning_content && { reasoning_content })
},
delta:
text === null
? {}
: { role: ChatCompletionRequestMessageRoleEnum.Assistant, content: text },
index: 0,
finish_reason
}

View File

@@ -63,12 +63,14 @@ export const AiChatModule: FlowNodeTemplateType = {
key: NodeInputKeyEnum.aiChatTemperature,
renderTypeList: [FlowNodeInputTypeEnum.hidden], // Set in the pop-up window
label: '',
value: 0,
valueType: WorkflowIOValueTypeEnum.number
},
{
key: NodeInputKeyEnum.aiChatMaxToken,
renderTypeList: [FlowNodeInputTypeEnum.hidden], // Set in the pop-up window
label: '',
value: 2000,
valueType: WorkflowIOValueTypeEnum.number
},
@@ -89,37 +91,6 @@ export const AiChatModule: FlowNodeTemplateType = {
valueType: WorkflowIOValueTypeEnum.boolean,
value: true
},
{
key: NodeInputKeyEnum.aiChatReasoning,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.boolean,
value: true
},
{
key: NodeInputKeyEnum.aiChatTopP,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.number
},
{
key: NodeInputKeyEnum.aiChatStopSign,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string
},
{
key: NodeInputKeyEnum.aiChatResponseFormat,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string
},
{
key: NodeInputKeyEnum.aiChatJsonSchema,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string
},
// settings modal ---
{
...Input_Template_System_Prompt,
@@ -130,6 +101,7 @@ export const AiChatModule: FlowNodeTemplateType = {
Input_Template_History,
Input_Template_Dataset_Quote,
Input_Template_File_Link_Prompt,
{ ...Input_Template_UserChatInput, toolDescription: i18nT('workflow:user_question') }
],
outputs: [
@@ -151,20 +123,6 @@ export const AiChatModule: FlowNodeTemplateType = {
description: i18nT('common:core.module.output.description.Ai response content'),
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static
},
{
id: NodeOutputKeyEnum.reasoningText,
key: NodeOutputKeyEnum.reasoningText,
required: false,
label: i18nT('workflow:reasoning_text'),
valueType: WorkflowIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.static,
invalid: true,
invalidCondition: ({ inputs, llmModelList }) => {
const model = inputs.find((item) => item.key === NodeInputKeyEnum.aiModel)?.value;
const modelItem = llmModelList.find((item) => item.model === model);
return modelItem?.reasoning !== true;
}
}
]
};

View File

@@ -1,6 +1,5 @@
import {
datasetQuoteValueDesc,
datasetSelectValueDesc,
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
@@ -39,8 +38,7 @@ export const DatasetSearchModule: FlowNodeTemplateType = {
label: i18nT('common:core.module.input.label.Select dataset'),
value: [],
valueType: WorkflowIOValueTypeEnum.selectDataset,
required: true,
valueDesc: datasetSelectValueDesc
required: true
},
{
key: NodeInputKeyEnum.datasetSimilarity,

View File

@@ -43,12 +43,14 @@ export const ToolModule: FlowNodeTemplateType = {
key: NodeInputKeyEnum.aiChatTemperature,
renderTypeList: [FlowNodeInputTypeEnum.hidden], // Set in the pop-up window
label: '',
value: 0,
valueType: WorkflowIOValueTypeEnum.number
},
{
key: NodeInputKeyEnum.aiChatMaxToken,
renderTypeList: [FlowNodeInputTypeEnum.hidden], // Set in the pop-up window
label: '',
value: 2000,
valueType: WorkflowIOValueTypeEnum.number
},
{
@@ -58,30 +60,6 @@ export const ToolModule: FlowNodeTemplateType = {
valueType: WorkflowIOValueTypeEnum.boolean,
value: true
},
{
key: NodeInputKeyEnum.aiChatTopP,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.number
},
{
key: NodeInputKeyEnum.aiChatStopSign,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string
},
{
key: NodeInputKeyEnum.aiChatResponseFormat,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string
},
{
key: NodeInputKeyEnum.aiChatJsonSchema,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string
},
{
...Input_Template_System_Prompt,

View File

@@ -1,4 +1,3 @@
import { LLMModelItemType } from '../../ai/model.d';
import { LLMModelTypeEnum } from '../../ai/constants';
import { WorkflowIOValueTypeEnum, NodeInputKeyEnum, NodeOutputKeyEnum } from '../constants';
import { FlowNodeInputTypeEnum, FlowNodeOutputTypeEnum } from '../node/constant';
@@ -78,12 +77,6 @@ export type FlowNodeOutputItemType = {
defaultValue?: any;
required?: boolean;
invalid?: boolean;
invalidCondition?: (e: {
inputs: FlowNodeInputItemType[];
llmModelList: LLMModelItemType[];
}) => boolean;
// component params
customFieldConfig?: CustomFieldConfigType;
};

View File

@@ -43,17 +43,6 @@ export type FlowNodeCommonType = {
pluginId?: string;
isFolder?: boolean;
// pluginType?: AppTypeEnum;
pluginData?: PluginDataType;
};
export type PluginDataType = {
version: string;
diagram?: string;
userGuide?: string;
courseUrl?: string;
name?: string;
avatar?: string;
error?: string;
};
type HandleType = {

View File

@@ -10,7 +10,6 @@
"echarts": "5.4.1",
"expr-eval": "^2.0.2",
"lodash": "^4.17.21",
"mssql": "^11.0.1",
"mysql2": "^3.11.3",
"json5": "^2.2.3",
"pg": "^8.10.0",

View File

@@ -1,6 +1,5 @@
import { Client as PgClient } from 'pg'; // PostgreSQL 客户端
import mysql from 'mysql2/promise'; // MySQL 客户端
import mssql from 'mssql'; // SQL Server 客户端
type Props = {
databaseType: string;
@@ -53,20 +52,6 @@ const main = async ({
const [rows] = await connection.execute(sql);
result = rows;
await connection.end();
} else if (databaseType === 'Microsoft SQL Server') {
const pool = await mssql.connect({
server: host,
port: parseInt(port, 10),
database: databaseName,
user,
password,
options: {
trustServerCertificate: true
}
});
result = await pool.query(sql);
await pool.close();
}
return {
result

View File

@@ -42,10 +42,6 @@
{
"label": "PostgreSQL",
"value": "PostgreSQL"
},
{
"label": "Microsoft SQL Server",
"value": "Microsoft SQL Server"
}
],
"required": true

View File

@@ -5,7 +5,6 @@ import { ClientSession, Types } from '../../../common/mongo';
import { guessBase64ImageType } from '../utils';
import { readFromSecondary } from '../../mongo/utils';
import { addHours } from 'date-fns';
import { imageFileType } from '@fastgpt/global/common/file/constants';
export const maxImgSize = 1024 * 1024 * 12;
const base64MimeRegex = /data:image\/([^\)]+);base64/;
@@ -33,10 +32,6 @@ export async function uploadMongoImg({
const binary = Buffer.from(base64Data, 'base64');
const extension = mime.split('/')[1];
if (!imageFileType.includes(`.${extension}`)) {
return Promise.reject('Invalid image file type');
}
const { _id } = await MongoImage.create({
teamId,
binary,
@@ -45,7 +40,7 @@ export async function uploadMongoImg({
expiredTime: forever ? undefined : addHours(new Date(), 1)
});
return `${process.env.NEXT_PUBLIC_BASE_URL || ''}${imageBaseUrl}${String(_id)}.${extension}`;
return `${process.env.FE_DOMAIN || ''}${process.env.NEXT_PUBLIC_BASE_URL || ''}${imageBaseUrl}${String(_id)}.${extension}`;
}
const getIdFromPath = (path?: string) => {

View File

@@ -63,13 +63,6 @@ export const getMongoModel = <T>(name: string, schema: mongoose.Schema) => {
const model = connectionMongo.model<T>(name, schema);
// Sync index
syncMongoIndex(model);
return model;
};
const syncMongoIndex = async (model: Model<any>) => {
if (process.env.SYNC_INDEX !== '0' && process.env.NODE_ENV !== 'test') {
try {
model.syncIndexes({ background: true });
@@ -77,6 +70,8 @@ const syncMongoIndex = async (model: Model<any>) => {
addLog.error('Create index error', error);
}
}
return model;
};
export const ReadPreference = connectionMongo.mongo.ReadPreference;

View File

@@ -24,7 +24,7 @@ export const aiTranscriptions = async ({
? { url: modelData.requestUrl }
: {
baseURL: aiAxiosConfig.baseUrl,
url: '/audio/transcriptions'
url: modelData.requestUrl || '/audio/transcriptions'
}),
headers: {
Authorization: modelData.requestAuth

View File

@@ -8,12 +8,6 @@
"maxResponse": 4000,
"quoteMaxToken": 120000,
"maxTemperature": 0.99,
"showTopP": true,
"responseFormatList": [
"text",
"json_object"
],
"showStopSign": true,
"vision": false,
"toolChoice": true,
"functionCall": false,
@@ -36,12 +30,6 @@
"maxResponse": 4000,
"quoteMaxToken": 120000,
"maxTemperature": 0.99,
"showTopP": true,
"responseFormatList": [
"text",
"json_object"
],
"showStopSign": true,
"vision": false,
"toolChoice": true,
"functionCall": false,
@@ -64,12 +52,6 @@
"maxResponse": 4000,
"quoteMaxToken": 900000,
"maxTemperature": 0.99,
"showTopP": true,
"responseFormatList": [
"text",
"json_object"
],
"showStopSign": true,
"vision": false,
"toolChoice": false,
"functionCall": false,
@@ -92,12 +74,6 @@
"maxResponse": 4000,
"quoteMaxToken": 120000,
"maxTemperature": 0.99,
"showTopP": true,
"responseFormatList": [
"text",
"json_object"
],
"showStopSign": true,
"vision": false,
"toolChoice": true,
"functionCall": false,
@@ -120,8 +96,6 @@
"maxResponse": 1000,
"quoteMaxToken": 6000,
"maxTemperature": 0.99,
"showTopP": true,
"showStopSign": true,
"vision": true,
"toolChoice": false,
"functionCall": false,
@@ -144,8 +118,6 @@
"maxResponse": 1000,
"quoteMaxToken": 6000,
"maxTemperature": 0.99,
"showTopP": true,
"showStopSign": true,
"vision": true,
"toolChoice": false,
"functionCall": false,

View File

@@ -8,8 +8,6 @@
"maxResponse": 8000,
"quoteMaxToken": 100000,
"maxTemperature": 1,
"showTopP": true,
"showStopSign": true,
"vision": false,
"toolChoice": true,
"functionCall": false,
@@ -32,8 +30,6 @@
"maxResponse": 8000,
"quoteMaxToken": 100000,
"maxTemperature": 1,
"showTopP": true,
"showStopSign": true,
"vision": true,
"toolChoice": true,
"functionCall": false,
@@ -56,8 +52,6 @@
"maxResponse": 8000,
"quoteMaxToken": 100000,
"maxTemperature": 1,
"showTopP": true,
"showStopSign": true,
"vision": true,
"toolChoice": true,
"functionCall": false,
@@ -80,8 +74,6 @@
"maxResponse": 4096,
"quoteMaxToken": 100000,
"maxTemperature": 1,
"showTopP": true,
"showStopSign": true,
"vision": true,
"toolChoice": true,
"functionCall": false,

View File

@@ -5,12 +5,9 @@
"model": "deepseek-chat",
"name": "Deepseek-chat",
"maxContext": 64000,
"maxResponse": 8000,
"maxResponse": 4096,
"quoteMaxToken": 60000,
"maxTemperature": 1,
"showTopP": true,
"responseFormatList": ["text", "json_object"],
"showStopSign": true,
"maxTemperature": 1.5,
"vision": false,
"toolChoice": true,
"functionCall": false,
@@ -28,11 +25,10 @@
"model": "deepseek-reasoner",
"name": "Deepseek-reasoner",
"maxContext": 64000,
"maxResponse": 8000,
"maxResponse": 4096,
"quoteMaxToken": 60000,
"maxTemperature": null,
"maxTemperature": 1.5,
"vision": false,
"reasoning": true,
"toolChoice": false,
"functionCall": false,
"defaultSystemChatPrompt": "",
@@ -43,11 +39,11 @@
"usedInQueryExtension": true,
"customExtractPrompt": "",
"usedInToolCall": true,
"defaultConfig": {},
"defaultConfig": {
"temperature": null
},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
}
]
}
}

View File

@@ -1,102 +1,6 @@
{
"provider": "Doubao",
"list": [
{
"model": "Doubao-1.5-lite-32k",
"name": "Doubao-1.5-lite-32k",
"maxContext": 32000,
"maxResponse": 4000,
"quoteMaxToken": 32000,
"maxTemperature": 1,
"showTopP": true,
"showStopSign": true,
"vision": false,
"toolChoice": true,
"functionCall": false,
"defaultSystemChatPrompt": "",
"datasetProcess": true,
"usedInClassify": true,
"customCQPrompt": "",
"usedInExtractFields": true,
"usedInQueryExtension": true,
"customExtractPrompt": "",
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm"
},
{
"model": "Doubao-1.5-pro-32k",
"name": "Doubao-1.5-pro-32k",
"maxContext": 32000,
"maxResponse": 4000,
"quoteMaxToken": 32000,
"maxTemperature": 1,
"showTopP": true,
"showStopSign": true,
"vision": false,
"toolChoice": true,
"functionCall": false,
"defaultSystemChatPrompt": "",
"datasetProcess": true,
"usedInClassify": true,
"customCQPrompt": "",
"usedInExtractFields": true,
"usedInQueryExtension": true,
"customExtractPrompt": "",
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm"
},
{
"model": "Doubao-1.5-pro-256k",
"name": "Doubao-1.5-pro-256k",
"maxContext": 256000,
"maxResponse": 12000,
"quoteMaxToken": 256000,
"maxTemperature": 1,
"showTopP": true,
"showStopSign": true,
"vision": false,
"toolChoice": true,
"functionCall": false,
"defaultSystemChatPrompt": "",
"datasetProcess": true,
"usedInClassify": true,
"customCQPrompt": "",
"usedInExtractFields": true,
"usedInQueryExtension": true,
"customExtractPrompt": "",
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm"
},
{
"model": "Doubao-1.5-vision-pro-32k",
"name": "Doubao-1.5-vision-pro-32k",
"maxContext": 32000,
"maxResponse": 4000,
"quoteMaxToken": 32000,
"maxTemperature": 1,
"showTopP": true,
"showStopSign": true,
"vision": true,
"toolChoice": true,
"functionCall": false,
"defaultSystemChatPrompt": "",
"datasetProcess": true,
"usedInClassify": true,
"customCQPrompt": "",
"usedInExtractFields": true,
"usedInQueryExtension": true,
"customExtractPrompt": "",
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm"
},
{
"model": "Doubao-lite-4k",
"name": "Doubao-lite-4k",
@@ -104,8 +8,6 @@
"maxResponse": 4000,
"quoteMaxToken": 4000,
"maxTemperature": 1,
"showTopP": true,
"showStopSign": true,
"vision": false,
"toolChoice": true,
"functionCall": false,
@@ -128,8 +30,6 @@
"maxResponse": 4000,
"quoteMaxToken": 32000,
"maxTemperature": 1,
"showTopP": true,
"showStopSign": true,
"vision": false,
"toolChoice": true,
"functionCall": false,
@@ -165,9 +65,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "Doubao-vision-lite-32k",
@@ -189,9 +87,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "Doubao-pro-4k",
@@ -213,9 +109,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "Doubao-pro-32k",
@@ -237,9 +131,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "Doubao-pro-128k",
@@ -261,9 +153,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "Doubao-vision-pro-32k",
@@ -285,25 +175,21 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "Doubao-embedding-large",
"name": "Doubao-embedding-large",
"defaultToken": 512,
"maxToken": 4096,
"type": "embedding",
"normalization": true
"type": "embedding"
},
{
"model": "Doubao-embedding",
"name": "Doubao-embedding",
"defaultToken": 512,
"maxToken": 4096,
"type": "embedding",
"normalization": true
"type": "embedding"
}
]
}

View File

@@ -21,9 +21,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "ERNIE-4.0-Turbo-8K",
@@ -45,9 +43,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "ERNIE-Lite-8K",
@@ -69,9 +65,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "ERNIE-Speed-128K",
@@ -93,9 +87,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "Embedding-V1",

View File

@@ -21,9 +21,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "gemini-1.5-pro",
@@ -45,9 +43,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "gemini-2.0-flash-exp",
@@ -69,9 +65,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "gemini-2.0-flash-thinking-exp-1219",
@@ -93,9 +87,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "gemini-2.0-flash-thinking-exp-01-21",
@@ -117,9 +109,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "gemini-exp-1206",
@@ -141,9 +131,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "text-embedding-004",
@@ -153,4 +141,4 @@
"type": "embedding"
}
]
}
}

View File

@@ -20,9 +20,7 @@
"customExtractPrompt": "",
"usedInToolCall": true,
"defaultConfig": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "llama-3.3-70b-versatile",
@@ -43,9 +41,7 @@
"customExtractPrompt": "",
"usedInToolCall": true,
"defaultConfig": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
}
]
}

View File

@@ -21,9 +21,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "hunyuan-lite",
@@ -45,9 +43,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "hunyuan-pro",
@@ -69,9 +65,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "hunyuan-standard",
@@ -93,9 +87,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "hunyuan-turbo-vision",
@@ -117,9 +109,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "hunyuan-turbo",
@@ -141,9 +131,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "hunyuan-vision",
@@ -165,9 +153,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "hunyuan-embedding",

View File

@@ -21,9 +21,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "internlm3-8b-instruct",
@@ -45,9 +43,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
}
]
}

View File

@@ -21,9 +21,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "abab6.5s-chat",
@@ -45,9 +43,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "speech-01-turbo",
@@ -241,4 +237,4 @@
"type": "tts"
}
]
}
}

View File

@@ -21,9 +21,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "ministral-8b-latest",
@@ -45,9 +43,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "mistral-large-latest",
@@ -69,9 +65,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "mistral-small-latest",
@@ -93,9 +87,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
}
]
}

View File

@@ -21,10 +21,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true,
"responseFormatList": ["text", "json_object"]
"type": "llm"
},
{
"model": "moonshot-v1-32k",
@@ -46,10 +43,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true,
"responseFormatList": ["text", "json_object"]
"type": "llm"
},
{
"model": "moonshot-v1-128k",
@@ -71,10 +65,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true,
"responseFormatList": ["text", "json_object"]
"type": "llm"
}
]
}

View File

@@ -8,13 +8,6 @@
"maxResponse": 16000,
"quoteMaxToken": 60000,
"maxTemperature": 1.2,
"showTopP": true,
"responseFormatList": [
"text",
"json_object",
"json_schema"
],
"showStopSign": true,
"vision": true,
"toolChoice": true,
"functionCall": true,
@@ -36,13 +29,6 @@
"maxResponse": 4000,
"quoteMaxToken": 60000,
"maxTemperature": 1.2,
"showTopP": true,
"responseFormatList": [
"text",
"json_object",
"json_schema"
],
"showStopSign": true,
"vision": true,
"toolChoice": true,
"functionCall": true,
@@ -58,44 +44,16 @@
"fieldMap": {},
"type": "llm"
},
{
"model": "o3-mini",
"name": "o3-mini",
"maxContext": 200000,
"maxResponse": 100000,
"quoteMaxToken": 120000,
"maxTemperature": null,
"vision": false,
"toolChoice": true,
"functionCall": false,
"defaultSystemChatPrompt": "",
"datasetProcess": true,
"usedInClassify": true,
"customCQPrompt": "",
"usedInExtractFields": true,
"usedInQueryExtension": true,
"customExtractPrompt": "",
"usedInToolCall": true,
"defaultConfig": {
"stream": false
},
"fieldMap": {
"max_tokens": "max_completion_tokens"
},
"type": "llm",
"showTopP": true,
"showStopSign": true
},
{
"model": "o1-mini",
"name": "o1-mini",
"maxContext": 128000,
"maxResponse": 4000,
"quoteMaxToken": 120000,
"maxTemperature": null,
"maxTemperature": 1.2,
"vision": false,
"toolChoice": false,
"functionCall": false,
"functionCall": true,
"defaultSystemChatPrompt": "",
"datasetProcess": true,
"usedInClassify": true,
@@ -105,42 +63,10 @@
"customExtractPrompt": "",
"usedInToolCall": true,
"defaultConfig": {
"stream": false
"temperature": 1,
"max_tokens": null
},
"fieldMap": {
"max_tokens": "max_completion_tokens"
},
"type": "llm",
"showTopP": true,
"showStopSign": true
},
{
"model": "o1",
"name": "o1",
"maxContext": 195000,
"maxResponse": 8000,
"quoteMaxToken": 120000,
"maxTemperature": null,
"vision": true,
"toolChoice": false,
"functionCall": false,
"defaultSystemChatPrompt": "",
"datasetProcess": true,
"usedInClassify": true,
"customCQPrompt": "",
"usedInExtractFields": true,
"usedInQueryExtension": true,
"customExtractPrompt": "",
"usedInToolCall": true,
"defaultConfig": {
"stream": false
},
"fieldMap": {
"max_tokens": "max_completion_tokens"
},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "o1-preview",
@@ -148,10 +74,10 @@
"maxContext": 128000,
"maxResponse": 4000,
"quoteMaxToken": 120000,
"maxTemperature": null,
"maxTemperature": 1.2,
"vision": false,
"toolChoice": false,
"functionCall": false,
"functionCall": true,
"defaultSystemChatPrompt": "",
"datasetProcess": true,
"usedInClassify": true,
@@ -161,14 +87,36 @@
"customExtractPrompt": "",
"usedInToolCall": true,
"defaultConfig": {
"temperature": 1,
"max_tokens": null,
"stream": false
},
"fieldMap": {
"max_tokens": "max_completion_tokens"
"type": "llm"
},
{
"model": "o1",
"name": "o1",
"maxContext": 195000,
"maxResponse": 8000,
"quoteMaxToken": 120000,
"maxTemperature": 1.2,
"vision": false,
"toolChoice": false,
"functionCall": true,
"defaultSystemChatPrompt": "",
"datasetProcess": true,
"usedInClassify": true,
"customCQPrompt": "",
"usedInExtractFields": true,
"usedInQueryExtension": true,
"customExtractPrompt": "",
"usedInToolCall": true,
"defaultConfig": {
"temperature": 1,
"max_tokens": null,
"stream": false
},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "gpt-3.5-turbo",
@@ -177,8 +125,6 @@
"maxResponse": 4000,
"quoteMaxToken": 13000,
"maxTemperature": 1.2,
"showTopP": true,
"showStopSign": true,
"vision": false,
"toolChoice": true,
"functionCall": true,
@@ -199,8 +145,6 @@
"maxResponse": 4000,
"quoteMaxToken": 60000,
"maxTemperature": 1.2,
"showTopP": true,
"showStopSign": true,
"vision": true,
"toolChoice": true,
"functionCall": true,
@@ -275,4 +219,4 @@
"type": "stt"
}
]
}
}

View File

@@ -21,10 +21,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true,
"responseFormatList": ["text", "json_object"]
"type": "llm"
},
{
"model": "qwen-plus",
@@ -46,10 +43,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true,
"responseFormatList": ["text", "json_object"]
"type": "llm"
},
{
"model": "qwen-vl-plus",
@@ -69,9 +63,7 @@
"usedInQueryExtension": true,
"customExtractPrompt": "",
"usedInToolCall": true,
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "qwen-max",
@@ -93,10 +85,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true,
"responseFormatList": ["text", "json_object"]
"type": "llm"
},
{
"model": "qwen-vl-max",
@@ -118,9 +107,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "qwen-coder-turbo",
@@ -142,9 +129,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "qwen2.5-7b-instruct",
@@ -166,10 +151,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true,
"responseFormatList": ["text", "json_object"]
"type": "llm"
},
{
"model": "qwen2.5-14b-instruct",
@@ -191,10 +173,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true,
"responseFormatList": ["text", "json_object"]
"type": "llm"
},
{
"model": "qwen2.5-32b-instruct",
@@ -216,10 +195,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true,
"responseFormatList": ["text", "json_object"]
"type": "llm"
},
{
"model": "qwen2.5-72b-instruct",
@@ -241,17 +217,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true,
"responseFormatList": ["text", "json_object"]
},
{
"model": "text-embedding-v3",
"name": "text-embedding-v3",
"defaultToken": 512,
"maxToken": 8000,
"type": "embedding"
"type": "llm"
}
]
}

View File

@@ -21,9 +21,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "Qwen/Qwen2-VL-72B-Instruct",
@@ -44,9 +42,7 @@
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"defaultConfig": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "deepseek-ai/DeepSeek-V2.5",
@@ -68,9 +64,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "BAAI/bge-m3",
@@ -207,4 +201,4 @@
"type": "rerank"
}
]
}
}

View File

@@ -19,9 +19,7 @@
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "generalv3",
@@ -41,9 +39,7 @@
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "pro-128k",
@@ -63,9 +59,7 @@
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "generalv3.5",
@@ -85,9 +79,7 @@
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "max-32k",
@@ -109,9 +101,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "4.0Ultra",
@@ -133,9 +123,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
}
]
}
}

View File

@@ -19,9 +19,7 @@
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "step-1-8k",
@@ -41,9 +39,7 @@
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "step-1-32k",
@@ -63,9 +59,7 @@
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "step-1-128k",
@@ -85,9 +79,7 @@
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "step-1-256k",
@@ -107,9 +99,7 @@
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "step-1o-vision-32k",
@@ -129,9 +119,7 @@
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "step-1v-8k",
@@ -151,9 +139,7 @@
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "step-1v-32k",
@@ -173,9 +159,7 @@
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "step-2-mini",
@@ -195,9 +179,7 @@
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "step-2-16k",
@@ -217,9 +199,7 @@
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "step-2-16k-exp",
@@ -239,9 +219,7 @@
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "step-tts-mini",
@@ -327,4 +305,4 @@
"type": "tts"
}
]
}
}

View File

@@ -21,9 +21,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
},
{
"model": "yi-vision-v2",
@@ -45,9 +43,7 @@
"usedInToolCall": true,
"defaultConfig": {},
"fieldMap": {},
"type": "llm",
"showTopP": true,
"showStopSign": true
"type": "llm"
}
]
}

View File

@@ -11,11 +11,7 @@ import {
ReRankModelItemType
} from '@fastgpt/global/core/ai/model.d';
import { debounce } from 'lodash';
import {
getModelProvider,
ModelProviderIdType,
ModelProviderType
} from '@fastgpt/global/core/ai/provider';
import { ModelProviderType } from '@fastgpt/global/core/ai/provider';
import { findModelFromAlldata } from '../model';
import {
reloadFastGPTConfigBuffer,
@@ -31,12 +27,7 @@ import { delay } from '@fastgpt/global/common/system/utils';
export const loadSystemModels = async (init = false) => {
const getProviderList = () => {
const currentFileUrl = new URL(import.meta.url);
const filePath = decodeURIComponent(
process.platform === 'win32'
? currentFileUrl.pathname.substring(1) // Remove leading slash on Windows
: currentFileUrl.pathname
);
const modelsPath = path.join(path.dirname(filePath), 'provider');
const modelsPath = path.join(path.dirname(currentFileUrl.pathname), 'provider');
return fs.readdirSync(modelsPath) as string[];
};
@@ -100,7 +91,7 @@ export const loadSystemModels = async (init = false) => {
await Promise.all(
providerList.map(async (name) => {
const fileContent = (await import(`./provider/${name}`))?.default as {
provider: ModelProviderIdType;
provider: ModelProviderType;
list: SystemModelItemType[];
};
@@ -110,7 +101,7 @@ export const loadSystemModels = async (init = false) => {
const modelData: any = {
...fileModel,
...dbModel?.metadata,
provider: getModelProvider(dbModel?.metadata?.provider || fileContent.provider).id,
provider: dbModel?.metadata?.provider || fileContent.provider,
type: dbModel?.metadata?.type || fileModel.type,
isCustom: false
};
@@ -152,7 +143,6 @@ export const loadSystemModels = async (init = false) => {
console.error('Load models error', error);
// @ts-ignore
global.systemModelList = undefined;
return Promise.reject(error);
}
};

View File

@@ -32,14 +32,12 @@ export async function getVectorsByText({ model, input, type }: GetVectorProps) {
model: model.model,
input: [input]
},
model.requestUrl
model.requestUrl && model.requestAuth
? {
path: model.requestUrl,
headers: model.requestAuth
? {
Authorization: `Bearer ${model.requestAuth}`
}
: undefined
headers: {
Authorization: `Bearer ${model.requestAuth}`
}
}
: {}
)
@@ -56,14 +54,7 @@ export async function getVectorsByText({ model, input, type }: GetVectorProps) {
const [tokens, vectors] = await Promise.all([
countPromptTokens(input),
Promise.all(
res.data
.map((item) => unityDimensional(item.embedding))
.map((item) => {
if (model.normalization) return normalization(item);
return item;
})
)
Promise.all(res.data.map((item) => unityDimensional(item.embedding)))
]);
return {
@@ -94,15 +85,3 @@ function unityDimensional(vector: number[]) {
return resultVector.concat(zeroVector);
}
// normalization processing
function normalization(vector: number[]) {
if (vector.some((item) => item > 1)) {
// Calculate the Euclidean norm (L2 norm)
const norm = Math.sqrt(vector.reduce((sum, val) => sum + val * val, 0));
// Normalize the vector by dividing each component by the norm
return vector.map((val) => val / norm);
}
return vector;
}

View File

@@ -2,12 +2,10 @@ import { replaceVariable } from '@fastgpt/global/common/string/tools';
import { createChatCompletion } from '../config';
import { ChatItemType } from '@fastgpt/global/core/chat/type';
import { countGptMessagesTokens, countPromptTokens } from '../../../common/string/tiktoken/index';
import { chats2GPTMessages } from '@fastgpt/global/core/chat/adapt';
import { chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt';
import { getLLMModel } from '../model';
import { llmCompletionsBodyFormat } from '../utils';
import { addLog } from '../../../common/system/log';
import { filterGPTMessageByMaxContext } from '../../chat/utils';
import json5 from 'json5';
/*
query extension - 问题扩展
@@ -15,73 +13,72 @@ import json5 from 'json5';
*/
const title = global.feConfigs?.systemTitle || 'FastAI';
const defaultPrompt = `## 你的任务
你作为一个向量检索助手,你的任务是结合历史记录,从不同角度,为“原问题”生成个不同版本的“检索词”,从而提高向量检索的语义丰富度,提高向量检索的精度。
const defaultPrompt = `作为一个向量检索助手,你的任务是结合历史记录,从不同角度,为“原问题”生成个不同版本的“检索词”,从而提高向量检索的语义丰富度,提高向量检索的精度。
生成的问题要求指向对象清晰明确,并与“原问题语言相同”。
## 参考示例
参考 <Example></Example> 标中的示例来完成任务。
<Example>
历史记录:
"""
null
"""
原问题: 介绍下剧情。
检索词: ["介绍下故事的背景。","故事的主题是什么?","介绍下故事的主要人物。"]
----------------
历史记录:
"""
user: 对话背景。
assistant: 当前对话是关于 Nginx 的介绍和使用等。
Q: 对话背景。
A: 当前对话是关于 Nginx 的介绍和使用等。
"""
原问题: 怎么下载
检索词: ["Nginx 如何下载?","下载 Nginx 需要什么条件?","有哪些渠道可以下载 Nginx"]
----------------
历史记录:
"""
user: 对话背景。
assistant: 当前对话是关于 Nginx 的介绍和使用等。
user: 报错 "no connection"
assistant: 报错"no connection"可能是因为……
Q: 对话背景。
A: 当前对话是关于 Nginx 的介绍和使用等。
Q: 报错 "no connection"
A: 报错"no connection"可能是因为……
"""
原问题: 怎么解决
检索词: ["Nginx报错"no connection"如何解决?","造成'no connection'报错的原因。","Nginx提示'no connection',要怎么办?"]
----------------
历史记录:
"""
user: How long is the maternity leave?
assistant: The number of days of maternity leave depends on the city in which the employee is located. Please provide your city so that I can answer your questions.
Q: 护产假多少天?
A: 护产假的天数根据员工所在的城市而定。请提供您所在的城市,以便我回答您的问题。
"""
原问题: ShenYang
检索词: ["How many days is maternity leave in Shenyang?","Shenyang's maternity leave policy.","The standard of maternity leave in Shenyang."]
原问题: 沈阳
检索词: ["沈阳的护产假多少天?","沈阳的护产假政策。","沈阳的护产假标准。"]
----------------
历史记录:
"""
user: 作者是谁?
assistant: ${title} 的作者是 labring。
Q: 作者是谁?
A: ${title} 的作者是 labring。
"""
原问题: Tell me about him
检索词: ["Introduce labring, the author of ${title}." ," Background information on author labring." "," Why does labring do ${title}?"]
----------------
历史记录:
"""
user: 对话背景。
assistant: 关于 ${title} 的介绍和使用等问题。
Q: 对话背景。
A: 关于 ${title} 的介绍和使用等问题。
"""
原问题: 你好。
检索词: ["你好"]
----------------
历史记录:
"""
user: ${title} 如何收费?
assistant: ${title} 收费可以参考……
Q: ${title} 如何收费?
A: ${title} 收费可以参考……
"""
原问题: 你知道 laf 么?
检索词: ["laf 的官网地址是多少?","laf 的使用教程。","laf 有什么特点和优势。"]
----------------
历史记录:
"""
user: ${title} 的优势
assistant: 1. 开源
Q: ${title} 的优势
A: 1. 开源
2. 简便
3. 扩展性强
"""
@@ -90,20 +87,18 @@ assistant: 1. 开源
----------------
历史记录:
"""
user: 什么是 ${title}
assistant: ${title} 是一个 RAG 平台。
user: 什么是 Laf
assistant: Laf 是一个云函数开发平台。
Q: 什么是 ${title}
A: ${title} 是一个 RAG 平台。
Q: 什么是 Laf
A: Laf 是一个云函数开发平台。
"""
原问题: 它们有什么关系?
检索词: ["${title}和Laf有什么关系","介绍下${title}","介绍下Laf"]
</Example>
## 输出要求
-----
1. 输出格式为 JSON 数组,数组中每个元素为字符串。无需对输出进行任何解释。
2. 输出语言与原问题相同。原问题为中文则输出中文;原问题为英文则输出英文。
## 开始任务
下面是正式的任务:
历史记录:
"""
@@ -130,39 +125,26 @@ export const queryExtension = async ({
outputTokens: number;
}> => {
const systemFewShot = chatBg
? `user: 对话背景。
assistant: ${chatBg}
? `Q: 对话背景。
A: ${chatBg}
`
: '';
const modelData = getLLMModel(model);
const filterHistories = await filterGPTMessageByMaxContext({
messages: chats2GPTMessages({ messages: histories, reserveId: false }),
maxContext: modelData.maxContext - 1000
});
const historyFewShot = filterHistories
const historyFewShot = histories
.map((item) => {
const role = item.role;
const content = item.content;
if ((role === 'user' || role === 'assistant') && content) {
if (typeof content === 'string') {
return `${role}: ${content}`;
} else {
return `${role}: ${content.map((item) => (item.type === 'text' ? item.text : '')).join('\n')}`;
}
}
const role = item.obj === 'Human' ? 'Q' : 'A';
return `${role}: ${chatValue2RuntimePrompt(item.value).text}`;
})
.filter(Boolean)
.join('\n');
const concatFewShot = `${systemFewShot}${historyFewShot}`.trim();
const modelData = getLLMModel(model);
const messages = [
{
role: 'user',
content: replaceVariable(defaultPrompt, {
query: `${query}`,
histories: concatFewShot || 'null'
histories: concatFewShot
})
}
] as any;
@@ -172,7 +154,7 @@ assistant: ${chatBg}
{
stream: false,
model: modelData.model,
temperature: 0.1,
temperature: 0.01,
messages
},
modelData
@@ -190,41 +172,22 @@ assistant: ${chatBg}
};
}
const start = answer.indexOf('[');
const end = answer.lastIndexOf(']');
if (start === -1 || end === -1) {
addLog.warn('Query extension failed, not a valid JSON', {
answer
});
return {
rawQuery: query,
extensionQueries: [],
model,
inputTokens: 0,
outputTokens: 0
};
}
// Intercept the content of [] and retain []
const jsonStr = answer
.substring(start, end + 1)
.replace(/(\\n|\\)/g, '')
.replace(/ /g, '');
answer = answer.match(/\[.*?\]/)?.[0] || '';
answer = answer.replace(/\\"/g, '"');
try {
const queries = json5.parse(jsonStr) as string[];
const queries = JSON.parse(answer) as string[];
return {
rawQuery: query,
extensionQueries: (Array.isArray(queries) ? queries : []).slice(0, 5),
extensionQueries: Array.isArray(queries) ? queries : [],
model,
inputTokens: await countGptMessagesTokens(messages),
outputTokens: await countPromptTokens(answer)
};
} catch (error) {
addLog.warn('Query extension failed, not a valid JSON', {
answer
});
addLog.error(`Query extension error`, error);
return {
rawQuery: query,
extensionQueries: [],

View File

@@ -25,11 +25,8 @@ export function reRankRecall({
if (!model) {
return Promise.reject('no rerank model');
}
if (documents.length === 0) {
return Promise.resolve([]);
}
const { baseUrl, authorization } = getAxiosConfig();
const { baseUrl, authorization } = getAxiosConfig({});
let start = Date.now();
return POST<PostReRankResponse>(
@@ -41,7 +38,7 @@ export function reRankRecall({
},
{
headers: {
Authorization: model.requestAuth ? `Bearer ${model.requestAuth}` : authorization
Authorization: model.requestAuth ? model.requestAuth : authorization
},
timeout: 30000
}

View File

@@ -2,23 +2,33 @@ import { LLMModelItemType } from '@fastgpt/global/core/ai/model.d';
import {
ChatCompletionCreateParamsNonStreaming,
ChatCompletionCreateParamsStreaming,
ChatCompletionMessageParam,
StreamChatType
} from '@fastgpt/global/core/ai/type';
import { countGptMessagesTokens } from '../../common/string/tiktoken';
import { getLLMModel } from './model';
/*
Count response max token
*/
export const computedMaxToken = ({
export const computedMaxToken = async ({
maxToken,
model
model,
filterMessages = []
}: {
maxToken?: number;
model: LLMModelItemType;
filterMessages: ChatCompletionMessageParam[];
}) => {
if (maxToken === undefined) return;
maxToken = Math.min(maxToken, model.maxResponse);
const tokensLimit = model.maxContext;
/* count response max token */
const promptsToken = await countGptMessagesTokens(filterMessages);
maxToken = promptsToken + maxToken > tokensLimit ? tokensLimit - promptsToken : maxToken;
if (maxToken <= 0) {
maxToken = 200;
}
return maxToken;
};
@@ -30,21 +40,15 @@ export const computedTemperature = ({
model: LLMModelItemType;
temperature: number;
}) => {
if (typeof model.maxTemperature !== 'number') return undefined;
temperature = +(model.maxTemperature * (temperature / 10)).toFixed(2);
temperature = Math.max(temperature, 0.01);
return temperature;
};
type CompletionsBodyType = (
type CompletionsBodyType =
| ChatCompletionCreateParamsNonStreaming
| ChatCompletionCreateParamsStreaming
) & {
response_format?: any;
json_schema?: string;
stop?: string;
};
| ChatCompletionCreateParamsStreaming;
type InferCompletionsBody<T> = T extends { stream: true }
? ChatCompletionCreateParamsStreaming
: ChatCompletionCreateParamsNonStreaming;
@@ -58,10 +62,6 @@ export const llmCompletionsBodyFormat = <T extends CompletionsBodyType>(
return body as InferCompletionsBody<T>;
}
const response_format = body.response_format;
const json_schema = body.json_schema ?? undefined;
const stop = body.stop ?? undefined;
const requestBody: T = {
...body,
temperature:
@@ -71,14 +71,7 @@ export const llmCompletionsBodyFormat = <T extends CompletionsBodyType>(
temperature: body.temperature
})
: undefined,
...modelData?.defaultConfig,
response_format: response_format
? {
type: response_format,
json_schema
}
: undefined,
stop: stop?.split('|')
...modelData?.defaultConfig
};
// field map

View File

@@ -88,7 +88,7 @@ try {
ChatSchema.index({ appId: 1, chatId: 1 });
// get chat logs;
ChatSchema.index({ teamId: 1, appId: 1, updateTime: -1, sources: 1 });
ChatSchema.index({ teamId: 1, appId: 1, updateTime: -1 });
// get share chat history
ChatSchema.index({ shareId: 1, outLinkUid: 1, updateTime: -1 });

View File

@@ -1,9 +1,6 @@
import { countGptMessagesTokens } from '../../common/string/tiktoken/index';
import type {
ChatCompletionAssistantMessageParam,
ChatCompletionContentPart,
ChatCompletionContentPartRefusal,
ChatCompletionContentPartText,
ChatCompletionMessageParam,
SdkChatCompletionMessageParam
} from '@fastgpt/global/core/ai/type.d';
@@ -14,19 +11,36 @@ import { serverRequestBaseUrl } from '../../common/api/serverRequest';
import { i18nT } from '../../../web/i18n/utils';
import { addLog } from '../../common/system/log';
export const filterGPTMessageByMaxContext = async ({
export const filterGPTMessageByMaxTokens = async ({
messages = [],
maxContext
maxTokens
}: {
messages: ChatCompletionMessageParam[];
maxContext: number;
maxTokens: number;
}) => {
if (!Array.isArray(messages)) {
return [];
}
const rawTextLen = messages.reduce((sum, item) => {
if (typeof item.content === 'string') {
return sum + item.content.length;
}
if (Array.isArray(item.content)) {
return (
sum +
item.content.reduce((sum, item) => {
if (item.type === 'text') {
return sum + item.text.length;
}
return sum;
}, 0)
);
}
return sum;
}, 0);
// If the text length is less than half of the maximum token, no calculation is required
if (messages.length < 4) {
if (rawTextLen < maxTokens * 0.5) {
return messages;
}
@@ -38,7 +52,7 @@ export const filterGPTMessageByMaxContext = async ({
const chatPrompts: ChatCompletionMessageParam[] = messages.slice(chatStartIndex);
// reduce token of systemPrompt
maxContext -= await countGptMessagesTokens(systemPrompts);
maxTokens -= await countGptMessagesTokens(systemPrompts);
// Save the last chat prompt(question)
const question = chatPrompts.pop();
@@ -56,9 +70,9 @@ export const filterGPTMessageByMaxContext = async ({
}
const tokens = await countGptMessagesTokens([assistant, user]);
maxContext -= tokens;
maxTokens -= tokens;
/* 整体 tokens 超出范围,截断 */
if (maxContext < 0) {
if (maxTokens < 0) {
break;
}
@@ -88,327 +102,223 @@ export const loadRequestMessages = async ({
useVision?: boolean;
origin?: string;
}) => {
const replaceLinkUrl = (text: string) => {
const baseURL = process.env.FE_DOMAIN;
if (!baseURL) return text;
// 匹配 /api/system/img/xxx.xx 的图片链接,并追加 baseURL
return text.replace(
/(?<!https?:\/\/[^\s]*)(?:\/api\/system\/img\/[^\s.]*\.[^\s]*)/g,
(match) => `${baseURL}${match}`
);
// Load image to base64
const loadImageToBase64 = async (messages: ChatCompletionContentPart[]) => {
return Promise.all(
messages.map(async (item) => {
if (item.type === 'image_url') {
// Remove url origin
const imgUrl = (() => {
if (origin && item.image_url.url.startsWith(origin)) {
return item.image_url.url.replace(origin, '');
}
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('/') || process.env.MULTIPLE_DATA_TO_BASE64 === 'true') {
addLog.debug('Load image from local server', {
baseUrl: serverRequestBaseUrl,
requestUrl: imgUrl
});
const response = await axios.get(imgUrl, {
baseURL: serverRequestBaseUrl,
responseType: 'arraybuffer',
proxy: false
});
const base64 = Buffer.from(response.data, 'binary').toString('base64');
const imageType =
getFileContentTypeFromHeader(response.headers['content-type']) ||
guessBase64ImageType(base64);
return {
...item,
image_url: {
...item.image_url,
url: `data:${imageType};base64,${base64}`
}
};
}
// 检查下这个图片是否可以被访问,如果不行的话,则过滤掉
const response = await axios.head(imgUrl, {
timeout: 10000
});
if (response.status < 200 || response.status >= 400) {
addLog.info(`Filter invalid image: ${imgUrl}`);
return;
}
} catch (error) {
return;
}
}
return item;
})
).then((res) => res.filter(Boolean) as ChatCompletionContentPart[]);
};
const parseSystemMessage = (
content: string | ChatCompletionContentPartText[]
): string | ChatCompletionContentPartText[] | undefined => {
if (typeof content === 'string') {
if (!content) return;
return replaceLinkUrl(content);
// Split question text and image
const parseStringWithImages = (input: string): ChatCompletionContentPart[] => {
if (!useVision || input.length > 500) {
return [{ type: 'text', text: input || '' }];
}
const arrayContent = content
.filter((item) => item.text)
.map((item) => ({ ...item, text: replaceLinkUrl(item.text) }));
if (arrayContent.length === 0) return;
return arrayContent;
// 正则表达式匹配图片URL
const imageRegex =
/(https?:\/\/[^\s/$.?#].[^\s]*\.(?:png|jpe?g|gif|webp|bmp|tiff?|svg|ico|heic|avif))/gi;
const result: ChatCompletionContentPart[] = [];
// 提取所有HTTPS图片URL并添加到result开头
const httpsImages = [...new Set(Array.from(input.matchAll(imageRegex), (m) => m[0]))];
httpsImages.forEach((url) => {
result.push({
type: 'image_url',
image_url: {
url: url
}
});
});
// Too many images return text
if (httpsImages.length > 4) {
return [{ type: 'text', text: input || '' }];
}
// 添加原始input作为文本
result.push({ type: 'text', text: input });
return result;
};
// Parse user content(text and img) Store history => api messages
const parseUserContent = async (content: string | ChatCompletionContentPart[]) => {
// Split question text and image
const parseStringWithImages = (input: string): ChatCompletionContentPart[] => {
if (!useVision || input.length > 500) {
return [{ type: 'text', text: input }];
}
// 正则表达式匹配图片URL
const imageRegex =
/(https?:\/\/[^\s/$.?#].[^\s]*\.(?:png|jpe?g|gif|webp|bmp|tiff?|svg|ico|heic|avif))/gi;
const result: ChatCompletionContentPart[] = [];
// 提取所有HTTPS图片URL并添加到result开头
const httpsImages = [...new Set(Array.from(input.matchAll(imageRegex), (m) => m[0]))];
httpsImages.forEach((url) => {
result.push({
type: 'image_url',
image_url: {
url: url
}
});
});
// Too many images return text
if (httpsImages.length > 4) {
return [{ type: 'text', text: input }];
}
// 添加原始input作为文本
result.push({ type: 'text', text: input });
return result;
};
// Load image to base64
const loadUserContentImage = async (content: ChatCompletionContentPart[]) => {
return Promise.all(
content.map(async (item) => {
if (item.type === 'image_url') {
// Remove url origin
const imgUrl = (() => {
if (origin && item.image_url.url.startsWith(origin)) {
return item.image_url.url.replace(origin, '');
}
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('/') || process.env.MULTIPLE_DATA_TO_BASE64 === 'true') {
addLog.debug('Load image from local server', {
baseUrl: serverRequestBaseUrl,
requestUrl: imgUrl
});
const response = await axios.get(imgUrl, {
baseURL: serverRequestBaseUrl,
responseType: 'arraybuffer',
proxy: false
});
const base64 = Buffer.from(response.data, 'binary').toString('base64');
const imageType =
getFileContentTypeFromHeader(response.headers['content-type']) ||
guessBase64ImageType(base64);
return {
...item,
image_url: {
...item.image_url,
url: `data:${imageType};base64,${base64}`
}
};
}
// 检查下这个图片是否可以被访问,如果不行的话,则过滤掉
const response = await axios.head(imgUrl, {
timeout: 10000
});
if (response.status < 200 || response.status >= 400) {
addLog.info(`Filter invalid image: ${imgUrl}`);
return;
}
} catch (error) {
return;
}
}
return item;
})
).then((res) => res.filter(Boolean) as ChatCompletionContentPart[]);
};
if (content === undefined) return;
if (typeof content === 'string') {
if (content === '') return;
const loadImageContent = await loadUserContentImage(parseStringWithImages(content));
if (loadImageContent.length === 0) return;
return loadImageContent;
return loadImageToBase64(parseStringWithImages(content));
}
const result = (
await Promise.all(
content.map(async (item) => {
if (item.type === 'text') {
if (item.text) return parseStringWithImages(item.text);
return;
}
if (item.type === 'file_url') return; // LLM not support file_url
if (item.type === 'image_url') {
// close vision, remove image_url
if (!useVision) return;
// remove empty image_url
if (!item.image_url.url) return;
const result = await Promise.all(
content.map(async (item) => {
if (item.type === 'text') return parseStringWithImages(item.text);
if (item.type === 'file_url') return; // LLM not support file_url
if (!item.image_url.url) return item;
return item;
})
);
return loadImageToBase64(result.flat().filter(Boolean) as ChatCompletionContentPart[]);
};
// format GPT messages, concat text messages
const clearInvalidMessages = (messages: ChatCompletionMessageParam[]) => {
return messages
.map((item) => {
if (item.role === ChatCompletionRequestMessageRoleEnum.System && !item.content) {
return;
}
if (item.role === ChatCompletionRequestMessageRoleEnum.User) {
if (item.content === undefined) return;
if (typeof item.content === 'string') {
return {
...item,
content: item.content.trim()
};
}
return item;
})
)
)
.flat()
.filter(Boolean) as ChatCompletionContentPart[];
// array
if (item.content.length === 0) return;
if (item.content.length === 1 && item.content[0].type === 'text') {
return {
...item,
content: item.content[0].text
};
}
}
if (item.role === ChatCompletionRequestMessageRoleEnum.Assistant) {
if (item.content === undefined && !item.tool_calls && !item.function_call) return;
}
const loadImageContent = await loadUserContentImage(result);
if (loadImageContent.length === 0) return;
return loadImageContent;
return item;
})
.filter(Boolean) as ChatCompletionMessageParam[];
};
const formatAssistantItem = (item: ChatCompletionAssistantMessageParam) => {
return {
role: item.role,
content: item.content,
function_call: item.function_call,
name: item.name,
refusal: item.refusal,
tool_calls: item.tool_calls
};
};
const parseAssistantContent = (
content:
| string
| (ChatCompletionContentPartText | ChatCompletionContentPartRefusal)[]
| null
| undefined
) => {
if (typeof content === 'string') {
return content || '';
}
// 交互节点
if (!content) return '';
const result = content.filter((item) => item?.type === 'text');
if (result.length === 0) return '';
return result.map((item) => item.text).join('\n');
};
if (messages.length === 0) {
return Promise.reject(i18nT('common:core.chat.error.Messages empty'));
}
// 合并相邻 role 的内容,只保留一个 role content 变成数组。 assistant 的话,工具调用不合并。
const mergeMessages = ((messages: ChatCompletionMessageParam[]): ChatCompletionMessageParam[] => {
/*
Merge data for some consecutive roles
1. Contiguous assistant and both have content, merge content
*/
const mergeConsecutiveMessages = (
messages: ChatCompletionMessageParam[]
): ChatCompletionMessageParam[] => {
return messages.reduce((mergedMessages: ChatCompletionMessageParam[], currentMessage) => {
const lastMessage = mergedMessages[mergedMessages.length - 1];
if (!lastMessage) {
return [currentMessage];
}
if (
lastMessage.role === ChatCompletionRequestMessageRoleEnum.System &&
currentMessage.role === ChatCompletionRequestMessageRoleEnum.System
) {
const lastContent: ChatCompletionContentPartText[] = Array.isArray(lastMessage.content)
? lastMessage.content
: [{ type: 'text', text: lastMessage.content || '' }];
const currentContent: ChatCompletionContentPartText[] = Array.isArray(
currentMessage.content
)
? currentMessage.content
: [{ type: 'text', text: currentMessage.content || '' }];
lastMessage.content = [...lastContent, ...currentContent];
} // Handle user messages
else if (
lastMessage.role === ChatCompletionRequestMessageRoleEnum.User &&
currentMessage.role === ChatCompletionRequestMessageRoleEnum.User
) {
const lastContent: ChatCompletionContentPart[] = Array.isArray(lastMessage.content)
? lastMessage.content
: [{ type: 'text', text: lastMessage.content }];
const currentContent: ChatCompletionContentPart[] = Array.isArray(currentMessage.content)
? currentMessage.content
: [{ type: 'text', text: currentMessage.content }];
lastMessage.content = [...lastContent, ...currentContent];
} else if (
lastMessage &&
currentMessage.role === ChatCompletionRequestMessageRoleEnum.Assistant &&
lastMessage.role === ChatCompletionRequestMessageRoleEnum.Assistant &&
currentMessage.role === ChatCompletionRequestMessageRoleEnum.Assistant
typeof lastMessage.content === 'string' &&
typeof currentMessage.content === 'string'
) {
// Content 不为空的对象,或者是交互节点
if (
(typeof lastMessage.content === 'string' ||
Array.isArray(lastMessage.content) ||
lastMessage.interactive) &&
(typeof currentMessage.content === 'string' ||
Array.isArray(currentMessage.content) ||
currentMessage.interactive)
) {
const lastContent: (ChatCompletionContentPartText | ChatCompletionContentPartRefusal)[] =
Array.isArray(lastMessage.content)
? lastMessage.content
: [{ type: 'text', text: lastMessage.content || '' }];
const currentContent: (
| ChatCompletionContentPartText
| ChatCompletionContentPartRefusal
)[] = Array.isArray(currentMessage.content)
? currentMessage.content
: [{ type: 'text', text: currentMessage.content || '' }];
lastMessage.content = [...lastContent, ...currentContent];
} else {
// 有其中一个没有 content说明不是连续的文本输出
mergedMessages.push(currentMessage);
}
lastMessage.content += currentMessage ? `\n${currentMessage.content}` : '';
} else {
mergedMessages.push(currentMessage);
}
return mergedMessages;
}, []);
})(messages);
};
const loadMessages = (
await Promise.all(
mergeMessages.map(async (item, i) => {
if (item.role === ChatCompletionRequestMessageRoleEnum.System) {
const content = parseSystemMessage(item.content);
if (!content) return;
return {
...item,
content
};
} else if (item.role === ChatCompletionRequestMessageRoleEnum.User) {
const content = await parseUserContent(item.content);
if (!content) {
return {
...item,
content: 'null'
};
}
if (messages.length === 0) {
return Promise.reject(i18nT('common:core.chat.error.Messages empty'));
}
const formatContent = (() => {
if (Array.isArray(content) && content.length === 1 && content[0].type === 'text') {
return content[0].text;
}
return content;
})();
// filter messages file
const filterMessages = messages.map((item) => {
// If useVision=false, only retain text.
if (
item.role === ChatCompletionRequestMessageRoleEnum.User &&
Array.isArray(item.content) &&
!useVision
) {
return {
...item,
content: item.content.filter((item) => item.type === 'text')
};
}
return {
...item,
content: formatContent
};
} else if (item.role === ChatCompletionRequestMessageRoleEnum.Assistant) {
if (item.tool_calls || item.function_call) {
return formatAssistantItem(item);
}
return item;
});
const parseContent = parseAssistantContent(item.content);
const loadMessages = (await Promise.all(
filterMessages.map(async (item) => {
if (item.role === ChatCompletionRequestMessageRoleEnum.User) {
return {
...item,
content: await parseUserContent(item.content)
};
} else if (item.role === ChatCompletionRequestMessageRoleEnum.Assistant) {
// remove invalid field
return {
role: item.role,
content: item.content,
function_call: item.function_call,
name: item.name,
refusal: item.refusal,
tool_calls: item.tool_calls
};
} else {
return item;
}
})
)) as ChatCompletionMessageParam[];
// 如果内容为空,且前后不再是 assistant需要补充成 null避免丢失 user-assistant 的交互
const formatContent = (() => {
const lastItem = mergeMessages[i - 1];
const nextItem = mergeMessages[i + 1];
if (
parseContent === '' &&
(lastItem?.role === ChatCompletionRequestMessageRoleEnum.Assistant ||
nextItem?.role === ChatCompletionRequestMessageRoleEnum.Assistant)
) {
return;
}
return parseContent || 'null';
})();
if (!formatContent) return;
return {
...formatAssistantItem(item),
content: formatContent
};
} else {
return item;
}
})
)
).filter(Boolean) as ChatCompletionMessageParam[];
return loadMessages as SdkChatCompletionMessageParam[];
return mergeConsecutiveMessages(
clearInvalidMessages(loadMessages)
) as SdkChatCompletionMessageParam[];
};

View File

@@ -37,7 +37,12 @@ try {
{ teamId: 1, datasetId: 1, fullTextToken: 'text' },
{
name: 'teamId_1_datasetId_1_fullTextToken_text',
default_language: 'none'
default_language: 'none',
collation: {
locale: 'simple', // 使用简单匹配规则
strength: 2, // 忽略大小写
caseLevel: false // 进一步确保大小写不敏感
}
}
);
DatasetDataTextSchema.index({ dataId: 1 }, { unique: true });

View File

@@ -5,7 +5,7 @@ import {
} from '@fastgpt/global/core/dataset/constants';
import { recallFromVectorStore } from '../../../common/vectorStore/controller';
import { getVectorsByText } from '../../ai/embedding';
import { getEmbeddingModel, getDefaultRerankModel, getLLMModel } from '../../ai/model';
import { getEmbeddingModel, getDefaultRerankModel } from '../../ai/model';
import { MongoDatasetData } from '../data/schema';
import {
DatasetDataTextSchemaType,
@@ -23,24 +23,18 @@ import json5 from 'json5';
import { MongoDatasetCollectionTags } from '../tag/schema';
import { readFromSecondary } from '../../../common/mongo/utils';
import { MongoDatasetDataText } from '../data/dataTextSchema';
import { ChatItemType } from '@fastgpt/global/core/chat/type';
import { POST } from '../../../common/api/plusRequest';
import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import { datasetSearchQueryExtension } from './utils';
export type SearchDatasetDataProps = {
histories: ChatItemType[];
type SearchDatasetDataProps = {
teamId: string;
model: string;
similarity?: number; // min distance
limit: number; // max Token limit
datasetIds: string[];
searchMode?: `${DatasetSearchModeEnum}`;
usingReRank?: boolean;
reRankQuery: string;
queries: string[];
[NodeInputKeyEnum.datasetSimilarity]?: number; // min distance
[NodeInputKeyEnum.datasetMaxTokens]: number; // max Token limit
[NodeInputKeyEnum.datasetSearchMode]?: `${DatasetSearchModeEnum}`;
[NodeInputKeyEnum.datasetSearchUsingReRank]?: boolean;
/*
{
tags: {
@@ -56,96 +50,7 @@ export type SearchDatasetDataProps = {
collectionFilterMatch?: string;
};
export type SearchDatasetDataResponse = {
searchRes: SearchDataResponseItemType[];
tokens: number;
searchMode: `${DatasetSearchModeEnum}`;
limit: number;
similarity: number;
usingReRank: boolean;
usingSimilarityFilter: boolean;
queryExtensionResult?: {
model: string;
inputTokens: number;
outputTokens: number;
query: string;
};
deepSearchResult?: { model: string; inputTokens: number; outputTokens: number };
};
export const datasetDataReRank = async ({
data,
query
}: {
data: SearchDataResponseItemType[];
query: string;
}): Promise<SearchDataResponseItemType[]> => {
const results = await reRankRecall({
query,
documents: data.map((item) => ({
id: item.id,
text: `${item.q}\n${item.a}`
}))
});
if (results.length === 0) {
return Promise.reject('Rerank error');
}
// add new score to data
const mergeResult = results
.map((item, index) => {
const target = data.find((dataItem) => dataItem.id === item.id);
if (!target) return null;
const score = item.score || 0;
return {
...target,
score: [{ type: SearchScoreTypeEnum.reRank, value: score, index }]
};
})
.filter(Boolean) as SearchDataResponseItemType[];
return mergeResult;
};
export const filterDatasetDataByMaxTokens = async (
data: SearchDataResponseItemType[],
maxTokens: number
) => {
const filterMaxTokensResult = await (async () => {
// Count tokens
const tokensScoreFilter = await Promise.all(
data.map(async (item) => ({
...item,
tokens: await countPromptTokens(item.q + item.a)
}))
);
const results: SearchDataResponseItemType[] = [];
let totalTokens = 0;
for await (const item of tokensScoreFilter) {
totalTokens += item.tokens;
if (totalTokens > maxTokens + 500) {
break;
}
results.push(item);
if (totalTokens > maxTokens) {
break;
}
}
return results.length === 0 ? data.slice(0, 1) : results;
})();
return filterMaxTokensResult;
};
export async function searchDatasetData(
props: SearchDatasetDataProps
): Promise<SearchDatasetDataResponse> {
export async function searchDatasetData(props: SearchDatasetDataProps) {
let {
teamId,
reRankQuery,
@@ -550,6 +455,47 @@ export async function searchDatasetData(
tokenLen: 0
};
};
const reRankSearchResult = async ({
data,
query
}: {
data: SearchDataResponseItemType[];
query: string;
}): Promise<SearchDataResponseItemType[]> => {
try {
const results = await reRankRecall({
query,
documents: data.map((item) => ({
id: item.id,
text: `${item.q}\n${item.a}`
}))
});
if (results.length === 0) {
usingReRank = false;
return [];
}
// add new score to data
const mergeResult = results
.map((item, index) => {
const target = data.find((dataItem) => dataItem.id === item.id);
if (!target) return null;
const score = item.score || 0;
return {
...target,
score: [{ type: SearchScoreTypeEnum.reRank, value: score, index }]
};
})
.filter(Boolean) as SearchDataResponseItemType[];
return mergeResult;
} catch (error) {
usingReRank = false;
return [];
}
};
const multiQueryRecall = async ({
embeddingLimit,
fullTextLimit
@@ -634,15 +580,10 @@ export async function searchDatasetData(
set.add(str);
return true;
});
try {
return await datasetDataReRank({
query: reRankQuery,
data: filterSameDataResults
});
} catch (error) {
usingReRank = false;
return [];
}
return reRankSearchResult({
query: reRankQuery,
data: filterSameDataResults
});
})();
// embedding recall and fullText recall rrf concat
@@ -687,7 +628,31 @@ export async function searchDatasetData(
})();
// token filter
const filterMaxTokensResult = await filterDatasetDataByMaxTokens(scoreFilter, maxTokens);
const filterMaxTokensResult = await (async () => {
const tokensScoreFilter = await Promise.all(
scoreFilter.map(async (item) => ({
...item,
tokens: await countPromptTokens(item.q + item.a)
}))
);
const results: SearchDataResponseItemType[] = [];
let totalTokens = 0;
for await (const item of tokensScoreFilter) {
totalTokens += item.tokens;
if (totalTokens > maxTokens + 500) {
break;
}
results.push(item);
if (totalTokens > maxTokens) {
break;
}
}
return results.length === 0 ? scoreFilter.slice(0, 1) : results;
})();
return {
searchRes: filterMaxTokensResult,
@@ -699,53 +664,3 @@ export async function searchDatasetData(
usingSimilarityFilter
};
}
export type DefaultSearchDatasetDataProps = SearchDatasetDataProps & {
[NodeInputKeyEnum.datasetSearchUsingExtensionQuery]?: boolean;
[NodeInputKeyEnum.datasetSearchExtensionModel]?: string;
[NodeInputKeyEnum.datasetSearchExtensionBg]?: string;
};
export const defaultSearchDatasetData = async ({
datasetSearchUsingExtensionQuery,
datasetSearchExtensionModel,
datasetSearchExtensionBg,
...props
}: DefaultSearchDatasetDataProps): Promise<SearchDatasetDataResponse> => {
const query = props.queries[0];
const extensionModel = datasetSearchUsingExtensionQuery
? getLLMModel(datasetSearchExtensionModel)
: undefined;
const { concatQueries, rewriteQuery, aiExtensionResult } = await datasetSearchQueryExtension({
query,
extensionModel,
extensionBg: datasetSearchExtensionBg
});
const result = await searchDatasetData({
...props,
reRankQuery: rewriteQuery,
queries: concatQueries
});
return {
...result,
queryExtensionResult: aiExtensionResult
? {
model: aiExtensionResult.model,
inputTokens: aiExtensionResult.inputTokens,
outputTokens: aiExtensionResult.outputTokens,
query: concatQueries.join('\n')
}
: undefined
};
};
export type DeepRagSearchProps = SearchDatasetDataProps & {
[NodeInputKeyEnum.datasetDeepSearchModel]?: string;
[NodeInputKeyEnum.datasetDeepSearchMaxTimes]?: number;
[NodeInputKeyEnum.datasetDeepSearchBg]?: string;
};
export const deepRagSearch = (data: DeepRagSearchProps) =>
POST<SearchDatasetDataResponse>('/core/dataset/deepRag', data);

View File

@@ -1,5 +1,45 @@
import { DatasetTrainingSchemaType } from '@fastgpt/global/core/dataset/type';
import { addLog } from '../../../common/system/log';
import { getErrText } from '@fastgpt/global/common/error/utils';
import { MongoDatasetTraining } from './schema';
import Papa from 'papaparse';
export const checkInvalidChunkAndLock = async ({
err,
errText,
data
}: {
err: any;
errText: string;
data: DatasetTrainingSchemaType;
}) => {
if (err?.response) {
addLog.error(`openai error: ${errText}`, {
status: err.response?.status,
statusText: err.response?.statusText,
data: err.response?.data
});
} else {
addLog.error(getErrText(err, errText), err);
}
if (
err?.message === 'invalid message format' ||
err?.type === 'invalid_request_error' ||
err?.code === 500
) {
addLog.error('Lock training data', err);
try {
await MongoDatasetTraining.findByIdAndUpdate(data._id, {
lockTime: new Date('2998/5/5')
});
} catch (error) {}
return true;
}
return false;
};
export const parseCsvTable2Chunks = (rawText: string) => {
const csvArr = Papa.parse(rawText).data as string[][];

View File

@@ -1,5 +1,5 @@
import { chats2GPTMessages } from '@fastgpt/global/core/chat/adapt';
import { filterGPTMessageByMaxContext, loadRequestMessages } from '../../../chat/utils';
import { filterGPTMessageByMaxTokens, loadRequestMessages } from '../../../chat/utils';
import type { ChatItemType } from '@fastgpt/global/core/chat/type.d';
import {
countMessagesTokens,
@@ -175,9 +175,9 @@ ${description ? `- ${description}` : ''}
}
];
const adaptMessages = chats2GPTMessages({ messages, reserveId: false });
const filterMessages = await filterGPTMessageByMaxContext({
const filterMessages = await filterGPTMessageByMaxTokens({
messages: adaptMessages,
maxContext: extractModel.maxContext
maxTokens: extractModel.maxContext
});
const requestMessages = await loadRequestMessages({
messages: filterMessages,

View File

@@ -1,5 +1,5 @@
import { createChatCompletion } from '../../../../ai/config';
import { filterGPTMessageByMaxContext, loadRequestMessages } from '../../../../chat/utils';
import { filterGPTMessageByMaxTokens, loadRequestMessages } from '../../../../chat/utils';
import {
ChatCompletion,
StreamChatType,
@@ -46,15 +46,7 @@ export const runToolWithFunctionCall = async (
externalProvider,
stream,
workflowStreamResponse,
params: {
temperature,
maxToken,
aiChatVision,
aiChatTopP,
aiChatStopSign,
aiChatResponseFormat,
aiChatJsonSchema
}
params: { temperature, maxToken, aiChatVision }
} = workflowProps;
// Interactive
@@ -180,14 +172,10 @@ export const runToolWithFunctionCall = async (
};
});
const max_tokens = computedMaxToken({
model: toolModel,
maxToken
});
const filterMessages = (
await filterGPTMessageByMaxContext({
await filterGPTMessageByMaxTokens({
messages,
maxContext: toolModel.maxContext - (max_tokens || 0) // filter token. not response maxToken
maxTokens: toolModel.maxContext - 300 // filter token. not response maxToken
})
).map((item) => {
if (item.role === ChatCompletionRequestMessageRoleEnum.Assistant && item.function_call) {
@@ -202,28 +190,27 @@ export const runToolWithFunctionCall = async (
}
return item;
});
const [requestMessages] = await Promise.all([
const [requestMessages, max_tokens] = await Promise.all([
loadRequestMessages({
messages: filterMessages,
useVision: toolModel.vision && aiChatVision,
origin: requestOrigin
}),
computedMaxToken({
model: toolModel,
maxToken,
filterMessages
})
]);
const requestBody = llmCompletionsBodyFormat(
{
model: toolModel.model,
temperature,
max_tokens,
stream,
messages: requestMessages,
functions,
function_call: 'auto',
temperature,
max_tokens,
top_p: aiChatTopP,
stop: aiChatStopSign,
response_format: aiChatResponseFormat,
json_schema: aiChatJsonSchema
function_call: 'auto'
},
toolModel
);

View File

@@ -1,5 +1,5 @@
import { createChatCompletion } from '../../../../ai/config';
import { filterGPTMessageByMaxContext, loadRequestMessages } from '../../../../chat/utils';
import { filterGPTMessageByMaxTokens, loadRequestMessages } from '../../../../chat/utils';
import {
ChatCompletion,
StreamChatType,
@@ -54,15 +54,7 @@ export const runToolWithPromptCall = async (
externalProvider,
stream,
workflowStreamResponse,
params: {
temperature,
maxToken,
aiChatVision,
aiChatTopP,
aiChatStopSign,
aiChatResponseFormat,
aiChatJsonSchema
}
params: { temperature, maxToken, aiChatVision }
} = workflowProps;
if (interactiveEntryToolParams) {
@@ -204,33 +196,30 @@ export const runToolWithPromptCall = async (
return Promise.reject('Prompt call invalid input');
}
const max_tokens = computedMaxToken({
model: toolModel,
maxToken
});
const filterMessages = await filterGPTMessageByMaxContext({
const filterMessages = await filterGPTMessageByMaxTokens({
messages,
maxContext: toolModel.maxContext - (max_tokens || 0) // filter token. not response maxToken
maxTokens: toolModel.maxContext - 500 // filter token. not response maxToken
});
const [requestMessages] = await Promise.all([
const [requestMessages, max_tokens] = await Promise.all([
loadRequestMessages({
messages: filterMessages,
useVision: toolModel.vision && aiChatVision,
origin: requestOrigin
}),
computedMaxToken({
model: toolModel,
maxToken,
filterMessages
})
]);
const requestBody = llmCompletionsBodyFormat(
{
model: toolModel.model,
stream,
messages: requestMessages,
temperature,
max_tokens,
top_p: aiChatTopP,
stop: aiChatStopSign,
response_format: aiChatResponseFormat,
json_schema: aiChatJsonSchema
stream,
messages: requestMessages
},
toolModel
);

View File

@@ -1,5 +1,5 @@
import { createChatCompletion } from '../../../../ai/config';
import { filterGPTMessageByMaxContext, loadRequestMessages } from '../../../../chat/utils';
import { filterGPTMessageByMaxTokens, loadRequestMessages } from '../../../../chat/utils';
import {
ChatCompletion,
ChatCompletionMessageToolCall,
@@ -93,15 +93,7 @@ export const runToolWithToolChoice = async (
stream,
externalProvider,
workflowStreamResponse,
params: {
temperature,
maxToken,
aiChatVision,
aiChatTopP,
aiChatStopSign,
aiChatResponseFormat,
aiChatJsonSchema
}
params: { temperature, maxToken, aiChatVision }
} = workflowProps;
if (maxRunToolTimes <= 0 && response) {
@@ -236,16 +228,11 @@ export const runToolWithToolChoice = async (
};
});
const max_tokens = computedMaxToken({
model: toolModel,
maxToken
});
// Filter histories by maxToken
const filterMessages = (
await filterGPTMessageByMaxContext({
await filterGPTMessageByMaxTokens({
messages,
maxContext: toolModel.maxContext - (max_tokens || 0) // filter token. not response maxToken
maxTokens: toolModel.maxContext - 300 // filter token. not response maxToken
})
).map((item) => {
if (item.role === 'assistant' && item.tool_calls) {
@@ -261,30 +248,31 @@ export const runToolWithToolChoice = async (
return item;
});
const [requestMessages] = await Promise.all([
const [requestMessages, max_tokens] = await Promise.all([
loadRequestMessages({
messages: filterMessages,
useVision: toolModel.vision && aiChatVision,
origin: requestOrigin
}),
computedMaxToken({
model: toolModel,
maxToken,
filterMessages
})
]);
const requestBody = llmCompletionsBodyFormat(
{
model: toolModel.model,
temperature,
max_tokens,
stream,
messages: requestMessages,
tools,
tool_choice: 'auto',
temperature,
max_tokens,
top_p: aiChatTopP,
stop: aiChatStopSign,
response_format: aiChatResponseFormat,
json_schema: aiChatJsonSchema
tool_choice: 'auto'
},
toolModel
);
// console.log(JSON.stringify(requestMessages, null, 2), '==requestBody');
// console.log(JSON.stringify(requestBody, null, 2), '==requestBody');
/* Run llm */
const {
response: aiResponse,

View File

@@ -16,16 +16,12 @@ export type DispatchToolModuleProps = ModuleDispatchProps<{
[NodeInputKeyEnum.history]?: ChatItemType[];
[NodeInputKeyEnum.userChatInput]: string;
[NodeInputKeyEnum.fileUrlList]?: string[];
[NodeInputKeyEnum.aiModel]: string;
[NodeInputKeyEnum.aiSystemPrompt]: string;
[NodeInputKeyEnum.aiChatTemperature]: number;
[NodeInputKeyEnum.aiChatMaxToken]: number;
[NodeInputKeyEnum.aiChatVision]?: boolean;
[NodeInputKeyEnum.aiChatTopP]?: number;
[NodeInputKeyEnum.aiChatStopSign]?: string;
[NodeInputKeyEnum.aiChatResponseFormat]?: string;
[NodeInputKeyEnum.aiChatJsonSchema]?: string;
[NodeInputKeyEnum.fileUrlList]?: string[];
}> & {
messages: ChatCompletionMessageParam[];
toolNodes: ToolNodeItemType[];

View File

@@ -1,5 +1,5 @@
import type { NextApiResponse } from 'next';
import { filterGPTMessageByMaxContext, loadRequestMessages } from '../../../chat/utils';
import { filterGPTMessageByMaxTokens, loadRequestMessages } from '../../../chat/utils';
import type { ChatItemType, UserChatItemValueItemType } from '@fastgpt/global/core/chat/type.d';
import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
import { SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/constants';
@@ -51,14 +51,13 @@ import { ModelTypeEnum } from '@fastgpt/global/core/ai/model';
export type ChatProps = ModuleDispatchProps<
AIChatNodeProps & {
[NodeInputKeyEnum.userChatInput]?: string;
[NodeInputKeyEnum.userChatInput]: string;
[NodeInputKeyEnum.history]?: ChatItemType[] | number;
[NodeInputKeyEnum.aiChatDatasetQuote]?: SearchDataResponseItemType[];
}
>;
export type ChatResponse = DispatchNodeResultType<{
[NodeOutputKeyEnum.answerText]: string;
[NodeOutputKeyEnum.reasoningText]?: string;
[NodeOutputKeyEnum.history]: ChatItemType[];
}>;
@@ -81,36 +80,29 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise<ChatResp
maxToken,
history = 6,
quoteQA,
userChatInput = '',
userChatInput,
isResponseAnswerText = true,
systemPrompt = '',
aiChatQuoteRole = 'system',
quoteTemplate,
quotePrompt,
aiChatVision,
aiChatReasoning = true,
aiChatTopP,
aiChatStopSign,
aiChatResponseFormat,
aiChatJsonSchema,
fileUrlList: fileLinks, // node quote file links
stringQuoteText //abandon
}
} = props;
const { files: inputFiles } = chatValue2RuntimePrompt(query); // Chat box input files
stream = stream && isResponseAnswerText;
const chatHistories = getHistories(history, histories);
quoteQA = checkQuoteQAValue(quoteQA);
const modelConstantsData = getLLMModel(model);
if (!modelConstantsData) {
return Promise.reject('The chat model is undefined, you need to select a chat model.');
}
aiChatVision = modelConstantsData.vision && aiChatVision;
aiChatReasoning = !!aiChatReasoning && !!modelConstantsData.reasoning;
const chatHistories = getHistories(history, histories);
quoteQA = checkQuoteQAValue(quoteQA);
const [{ datasetQuoteText }, { documentQuoteText, userFiles }] = await Promise.all([
filterDatasetQuote({
quoteQA,
@@ -132,15 +124,9 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise<ChatResp
return Promise.reject(i18nT('chat:AI_input_is_empty'));
}
const max_tokens = computedMaxToken({
model: modelConstantsData,
maxToken
});
const [{ filterMessages }] = await Promise.all([
getChatMessages({
model: modelConstantsData,
maxTokens: max_tokens,
histories: chatHistories,
useDatasetQuote: quoteQA !== undefined,
datasetQuoteText,
@@ -151,8 +137,8 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise<ChatResp
userFiles,
documentQuoteText
}),
// Censor = true and system key, will check content
(() => {
// censor model and system key
if (modelConstantsData.censor && !externalProvider.openaiAccount?.key) {
return postTextCensor({
text: `${systemPrompt}
@@ -163,23 +149,26 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise<ChatResp
})()
]);
const requestMessages = await loadRequestMessages({
messages: filterMessages,
useVision: aiChatVision,
origin: requestOrigin
});
const [requestMessages, max_tokens] = await Promise.all([
loadRequestMessages({
messages: filterMessages,
useVision: modelConstantsData.vision && aiChatVision,
origin: requestOrigin
}),
computedMaxToken({
model: modelConstantsData,
maxToken,
filterMessages
})
]);
const requestBody = llmCompletionsBodyFormat(
{
model: modelConstantsData.model,
stream,
messages: requestMessages,
temperature,
max_tokens,
top_p: aiChatTopP,
stop: aiChatStopSign,
response_format: aiChatResponseFormat as any,
json_schema: aiChatJsonSchema
stream,
messages: requestMessages
},
modelConstantsData
);
@@ -194,50 +183,34 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise<ChatResp
}
});
const { answerText, reasoningText } = await (async () => {
const { answerText } = await (async () => {
if (res && isStreamResponse) {
// sse response
const { answer, reasoning } = await streamResponse({
const { answer } = await streamResponse({
res,
stream: response,
aiChatReasoning,
isResponseAnswerText,
workflowStreamResponse
});
return {
answerText: answer,
reasoningText: reasoning
answerText: answer
};
} else {
const unStreamResponse = response as ChatCompletion;
const answer = unStreamResponse.choices?.[0]?.message?.content || '';
// @ts-ignore
const reasoning = unStreamResponse.choices?.[0]?.message?.reasoning_content || '';
// Some models do not support streaming
if (stream) {
if (isResponseAnswerText && answer) {
workflowStreamResponse?.({
event: SseResponseEventEnum.fastAnswer,
data: textAdaptGptResponse({
text: answer
})
});
}
if (aiChatReasoning && reasoning) {
workflowStreamResponse?.({
event: SseResponseEventEnum.fastAnswer,
data: textAdaptGptResponse({
reasoning_content: reasoning
})
});
}
// Some models do not support streaming
workflowStreamResponse?.({
event: SseResponseEventEnum.fastAnswer,
data: textAdaptGptResponse({
text: answer
})
});
}
return {
answerText: answer,
reasoningText: reasoning
answerText: answer
};
}
})();
@@ -268,7 +241,6 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise<ChatResp
return {
answerText,
reasoningText,
[DispatchNodeResponseKeyEnum.nodeResponse]: {
totalPoints: externalProvider.openaiAccount?.key ? 0 : totalPoints,
model: modelName,
@@ -277,8 +249,11 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise<ChatResp
outputTokens: outputTokens,
query: `${userChatInput}`,
maxToken: max_tokens,
reasoningText,
historyPreview: getHistoryPreview(chatCompleteMessages, 10000, aiChatVision),
historyPreview: getHistoryPreview(
chatCompleteMessages,
10000,
modelConstantsData.vision && aiChatVision
),
contextTotalLen: completeMessages.length
},
[DispatchNodeResponseKeyEnum.nodeDispatchUsages]: [
@@ -392,7 +367,6 @@ async function getMultiInput({
async function getChatMessages({
model,
maxTokens = 0,
aiChatQuoteRole,
datasetQuotePrompt = '',
datasetQuoteText,
@@ -404,7 +378,6 @@ async function getChatMessages({
documentQuoteText
}: {
model: LLMModelItemType;
maxTokens?: number;
// dataset quote
aiChatQuoteRole: AiChatQuoteRoleType; // user: replace user prompt; system: replace system prompt
datasetQuotePrompt?: string;
@@ -471,9 +444,9 @@ async function getChatMessages({
const adaptMessages = chats2GPTMessages({ messages, reserveId: false });
const filterMessages = await filterGPTMessageByMaxContext({
const filterMessages = await filterGPTMessageByMaxTokens({
messages: adaptMessages,
maxContext: model.maxContext - maxTokens // filter token. not response maxToken
maxTokens: model.maxContext - 300 // filter token. not response maxToken
});
return {
@@ -484,52 +457,33 @@ async function getChatMessages({
async function streamResponse({
res,
stream,
workflowStreamResponse,
aiChatReasoning,
isResponseAnswerText
workflowStreamResponse
}: {
res: NextApiResponse;
stream: StreamChatType;
workflowStreamResponse?: WorkflowResponseType;
aiChatReasoning?: boolean;
isResponseAnswerText?: boolean;
}) {
const write = responseWriteController({
res,
readStream: stream
});
let answer = '';
let reasoning = '';
for await (const part of stream) {
if (res.closed) {
stream.controller?.abort();
break;
}
const content = part.choices?.[0]?.delta?.content || '';
answer += content;
if (isResponseAnswerText && content) {
workflowStreamResponse?.({
write,
event: SseResponseEventEnum.answer,
data: textAdaptGptResponse({
text: content
})
});
}
const reasoningContent = part.choices?.[0]?.delta?.reasoning_content || '';
reasoning += reasoningContent;
if (aiChatReasoning && reasoningContent) {
workflowStreamResponse?.({
write,
event: SseResponseEventEnum.answer,
data: textAdaptGptResponse({
reasoning_content: reasoningContent
})
});
}
workflowStreamResponse?.({
write,
event: SseResponseEventEnum.answer,
data: textAdaptGptResponse({
text: content
})
});
}
return { answer, reasoning };
return { answer };
}

View File

@@ -6,11 +6,13 @@ import { formatModelChars2Points } from '../../../../support/wallet/usage/utils'
import type { SelectedDatasetType } from '@fastgpt/global/core/workflow/api.d';
import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type';
import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type';
import { getEmbeddingModel } from '../../../ai/model';
import { deepRagSearch, defaultSearchDatasetData } from '../../../dataset/search/controller';
import { getLLMModel, getEmbeddingModel } from '../../../ai/model';
import { searchDatasetData } from '../../../dataset/search/controller';
import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constants';
import { getHistories } from '../utils';
import { datasetSearchQueryExtension } from '../../../dataset/search/utils';
import { ChatNodeUsageType } from '@fastgpt/global/support/wallet/bill/type';
import { checkTeamReRankPermission } from '../../../../support/permission/teamLimit';
import { MongoDataset } from '../../../dataset/schema';
@@ -23,19 +25,13 @@ type DatasetSearchProps = ModuleDispatchProps<{
[NodeInputKeyEnum.datasetSimilarity]: number;
[NodeInputKeyEnum.datasetMaxTokens]: number;
[NodeInputKeyEnum.datasetSearchMode]: `${DatasetSearchModeEnum}`;
[NodeInputKeyEnum.userChatInput]?: string;
[NodeInputKeyEnum.userChatInput]: string;
[NodeInputKeyEnum.datasetSearchUsingReRank]: boolean;
[NodeInputKeyEnum.collectionFilterMatch]: string;
[NodeInputKeyEnum.authTmbId]?: boolean;
[NodeInputKeyEnum.datasetSearchUsingExtensionQuery]: boolean;
[NodeInputKeyEnum.datasetSearchExtensionModel]: string;
[NodeInputKeyEnum.datasetSearchExtensionBg]: string;
[NodeInputKeyEnum.datasetDeepSearch]?: boolean;
[NodeInputKeyEnum.datasetDeepSearchModel]?: string;
[NodeInputKeyEnum.datasetDeepSearchMaxTimes]?: number;
[NodeInputKeyEnum.datasetDeepSearchBg]?: string;
[NodeInputKeyEnum.collectionFilterMatch]: string;
[NodeInputKeyEnum.authTmbId]: boolean;
}>;
export type DatasetSearchResponse = DispatchNodeResultType<{
[NodeOutputKeyEnum.datasetQuoteQA]: SearchDataResponseItemType[];
@@ -55,18 +51,13 @@ export async function dispatchDatasetSearch(
limit = 1500,
usingReRank,
searchMode,
userChatInput = '',
authTmbId = false,
collectionFilterMatch,
userChatInput,
datasetSearchUsingExtensionQuery,
datasetSearchExtensionModel,
datasetSearchExtensionBg,
datasetDeepSearch,
datasetDeepSearchModel,
datasetDeepSearchMaxTimes,
datasetDeepSearchBg
collectionFilterMatch,
authTmbId = false
}
} = props as DatasetSearchProps;
@@ -94,12 +85,25 @@ export async function dispatchDatasetSearch(
return emptyResult;
}
const datasetIds = authTmbId
? await filterDatasetsByTmbId({
datasetIds: datasets.map((item) => item.datasetId),
tmbId
})
: await Promise.resolve(datasets.map((item) => item.datasetId));
// query extension
const extensionModel = datasetSearchUsingExtensionQuery
? getLLMModel(datasetSearchExtensionModel)
: undefined;
const [{ concatQueries, rewriteQuery, aiExtensionResult }, datasetIds] = await Promise.all([
datasetSearchQueryExtension({
query: userChatInput,
extensionModel,
extensionBg: datasetSearchExtensionBg,
histories: getHistories(6, histories)
}),
authTmbId
? filterDatasetsByTmbId({
datasetIds: datasets.map((item) => item.datasetId),
tmbId
})
: Promise.resolve(datasets.map((item) => item.datasetId))
]);
if (datasetIds.length === 0) {
return emptyResult;
@@ -112,11 +116,15 @@ export async function dispatchDatasetSearch(
);
// start search
const searchData = {
histories,
const {
searchRes,
tokens,
usingSimilarityFilter,
usingReRank: searchUsingReRank
} = await searchDatasetData({
teamId,
reRankQuery: userChatInput,
queries: [userChatInput],
reRankQuery: `${rewriteQuery}`,
queries: concatQueries,
model: vectorModel.model,
similarity,
limit,
@@ -124,106 +132,59 @@ export async function dispatchDatasetSearch(
searchMode,
usingReRank: usingReRank && (await checkTeamReRankPermission(teamId)),
collectionFilterMatch
};
const {
searchRes,
tokens,
usingSimilarityFilter,
usingReRank: searchUsingReRank,
queryExtensionResult,
deepSearchResult
} = datasetDeepSearch
? await deepRagSearch({
...searchData,
datasetDeepSearchModel,
datasetDeepSearchMaxTimes,
datasetDeepSearchBg
})
: await defaultSearchDatasetData({
...searchData,
datasetSearchUsingExtensionQuery,
datasetSearchExtensionModel,
datasetSearchExtensionBg
});
});
// count bill results
const nodeDispatchUsages: ChatNodeUsageType[] = [];
// vector
const { totalPoints: embeddingTotalPoints, modelName: embeddingModelName } =
formatModelChars2Points({
model: vectorModel.model,
inputTokens: tokens,
modelType: ModelTypeEnum.embedding
});
nodeDispatchUsages.push({
totalPoints: embeddingTotalPoints,
moduleName: node.name,
model: embeddingModelName,
inputTokens: tokens
const { totalPoints, modelName } = formatModelChars2Points({
model: vectorModel.model,
inputTokens: tokens,
modelType: ModelTypeEnum.embedding
});
// Query extension
const { totalPoints: queryExtensionTotalPoints } = (() => {
if (queryExtensionResult) {
const { totalPoints, modelName } = formatModelChars2Points({
model: queryExtensionResult.model,
inputTokens: queryExtensionResult.inputTokens,
outputTokens: queryExtensionResult.outputTokens,
modelType: ModelTypeEnum.llm
});
nodeDispatchUsages.push({
totalPoints,
moduleName: i18nT('common:core.module.template.Query extension'),
model: modelName,
inputTokens: queryExtensionResult.inputTokens,
outputTokens: queryExtensionResult.outputTokens
});
return {
totalPoints
};
}
return {
totalPoints: 0
};
})();
// Deep search
const { totalPoints: deepSearchTotalPoints } = (() => {
if (deepSearchResult) {
const { totalPoints, modelName } = formatModelChars2Points({
model: deepSearchResult.model,
inputTokens: deepSearchResult.inputTokens,
outputTokens: deepSearchResult.outputTokens,
modelType: ModelTypeEnum.llm
});
nodeDispatchUsages.push({
totalPoints,
moduleName: i18nT('common:deep_rag_search'),
model: modelName,
inputTokens: deepSearchResult.inputTokens,
outputTokens: deepSearchResult.outputTokens
});
return {
totalPoints
};
}
return {
totalPoints: 0
};
})();
const totalPoints = embeddingTotalPoints + queryExtensionTotalPoints + deepSearchTotalPoints;
const responseData: DispatchNodeResponseType & { totalPoints: number } = {
totalPoints,
query: userChatInput,
model: vectorModel.model,
query: concatQueries.join('\n'),
model: modelName,
inputTokens: tokens,
similarity: usingSimilarityFilter ? similarity : undefined,
limit,
searchMode,
searchUsingReRank: searchUsingReRank,
quoteList: searchRes,
queryExtensionResult,
deepSearchResult
quoteList: searchRes
};
const nodeDispatchUsages: ChatNodeUsageType[] = [
{
totalPoints,
moduleName: node.name,
model: modelName,
inputTokens: tokens
}
];
if (aiExtensionResult) {
const { totalPoints, modelName } = formatModelChars2Points({
model: aiExtensionResult.model,
inputTokens: aiExtensionResult.inputTokens,
outputTokens: aiExtensionResult.outputTokens,
modelType: ModelTypeEnum.llm
});
responseData.totalPoints += totalPoints;
responseData.inputTokens = aiExtensionResult.inputTokens;
responseData.outputTokens = aiExtensionResult.outputTokens;
responseData.extensionModel = modelName;
responseData.extensionResult =
aiExtensionResult.extensionQueries?.join('\n') ||
JSON.stringify(aiExtensionResult.extensionQueries);
nodeDispatchUsages.push({
totalPoints,
moduleName: 'core.module.template.Query extension',
model: modelName,
inputTokens: aiExtensionResult.inputTokens,
outputTokens: aiExtensionResult.outputTokens
});
}
return {
quoteQA: searchRes,

View File

@@ -204,7 +204,6 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
{ inputs = [] }: RuntimeNodeItemType,
{
answerText = '',
reasoningText,
responseData,
nodeDispatchUsages,
toolResponses,
@@ -214,7 +213,6 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
}: Omit<
DispatchNodeResultType<{
[NodeOutputKeyEnum.answerText]?: string;
[NodeOutputKeyEnum.reasoningText]?: string;
[DispatchNodeResponseKeyEnum.nodeResponse]?: ChatHistoryItemResType;
}>,
'nodeResponse'
@@ -241,28 +239,18 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
// Histories store
if (assistantResponses) {
chatAssistantResponse = chatAssistantResponse.concat(assistantResponses);
} else {
if (reasoningText) {
} else if (answerText) {
// save assistant text response
const isResponseAnswerText =
inputs.find((item) => item.key === NodeInputKeyEnum.aiChatIsResponseText)?.value ?? true;
if (isResponseAnswerText) {
chatAssistantResponse.push({
type: ChatItemValueTypeEnum.reasoning,
reasoning: {
content: reasoningText
type: ChatItemValueTypeEnum.text,
text: {
content: answerText
}
});
}
if (answerText) {
// save assistant text response
const isResponseAnswerText =
inputs.find((item) => item.key === NodeInputKeyEnum.aiChatIsResponseText)?.value ?? true;
if (isResponseAnswerText) {
chatAssistantResponse.push({
type: ChatItemValueTypeEnum.text,
text: {
content: answerText
}
});
}
}
}
if (rewriteHistories) {

View File

@@ -38,10 +38,10 @@ type HttpRequestProps = ModuleDispatchProps<{
[NodeInputKeyEnum.abandon_httpUrl]: string;
[NodeInputKeyEnum.httpMethod]: string;
[NodeInputKeyEnum.httpReqUrl]: string;
[NodeInputKeyEnum.httpHeaders]?: PropsArrType[];
[NodeInputKeyEnum.httpParams]?: PropsArrType[];
[NodeInputKeyEnum.httpJsonBody]?: string;
[NodeInputKeyEnum.httpFormBody]?: PropsArrType[];
[NodeInputKeyEnum.httpHeaders]: PropsArrType[];
[NodeInputKeyEnum.httpParams]: PropsArrType[];
[NodeInputKeyEnum.httpJsonBody]: string;
[NodeInputKeyEnum.httpFormBody]: PropsArrType[];
[NodeInputKeyEnum.httpContentType]: ContentTypes;
[NodeInputKeyEnum.addInputParam]: Record<string, any>;
[NodeInputKeyEnum.httpTimeout]?: number;
@@ -76,10 +76,10 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
params: {
system_httpMethod: httpMethod = 'POST',
system_httpReqUrl: httpReqUrl,
system_httpHeader: httpHeader = [],
system_httpHeader: httpHeader,
system_httpParams: httpParams = [],
system_httpJsonBody: httpJsonBody = '',
system_httpFormBody: httpFormBody = [],
system_httpJsonBody: httpJsonBody,
system_httpFormBody: httpFormBody,
system_httpContentType: httpContentType = ContentTypes.json,
system_httpTimeout: httpTimeout = 60,
[NodeInputKeyEnum.addInputParam]: dynamicInput,
@@ -244,6 +244,7 @@ export const dispatchHttp468Request = async (props: HttpRequestProps): Promise<H
if (!httpJsonBody) return {};
if (httpContentType === ContentTypes.json) {
httpJsonBody = replaceJsonBodyString(httpJsonBody);
console.log(httpJsonBody);
return json5.parse(httpJsonBody);
}

View File

@@ -142,7 +142,7 @@ export const checkQuoteQAValue = (quoteQA?: SearchDataResponseItemType[]) => {
if (quoteQA.length === 0) {
return [];
}
if (quoteQA.some((item) => typeof item !== 'object' || !item.q)) {
if (quoteQA.some((item) => !item.q)) {
return undefined;
}
return quoteQA;

View File

@@ -56,15 +56,14 @@ export const readPdfFile = async ({ buffer }: ReadRawTextByBuffer): Promise<Read
}
};
// @ts-ignore
const loadingTask = pdfjs.getDocument(buffer.buffer);
const doc = await loadingTask.promise;
// Avoid OOM.
let result = '';
const pageArr = Array.from({ length: doc.numPages }, (_, i) => i + 1);
for (let i = 0; i < pageArr.length; i++) {
result += await readPDFPage(doc, i + 1);
for await (const pageNo of pageArr) {
result += await readPDFPage(doc, pageNo);
}
loadingTask.destroy();

View File

@@ -120,7 +120,7 @@ export class WorkerPool<Props = Record<string, any>, Response = any> {
run(data: Props) {
// watch memory
// addLog.debug(`${this.name} worker queueLength: ${this.workerQueue.length}`);
addLog.debug(`${this.name} worker queueLength: ${this.workerQueue.length}`);
return new Promise<Response>((resolve, reject) => {
/*

View File

@@ -7,12 +7,7 @@ import { AppTemplateSchemaType } from '@fastgpt/global/core/app/type';
const getTemplateNameList = () => {
const currentFileUrl = new URL(import.meta.url);
const filePath = decodeURIComponent(
process.platform === 'win32'
? currentFileUrl.pathname.substring(1) // Remove leading slash on Windows
: currentFileUrl.pathname
);
const templatesPath = path.join(path.dirname(filePath), 'src');
const templatesPath = path.join(path.dirname(currentFileUrl.pathname), 'src');
return fs.readdirSync(templatesPath) as string[];
};

View File

@@ -1,31 +1,23 @@
import { Box, Tbody } from '@chakra-ui/react';
import React, { ReactElement, ReactNode, useState } from 'react';
import { Box } from '@chakra-ui/react';
import React, { useState } from 'react';
import {
DragDropContext,
DroppableProps,
Droppable,
DraggableChildrenFn,
DragStart,
DropResult,
DroppableProvided,
DroppableStateSnapshot
DropResult
} from 'react-beautiful-dnd';
export * from 'react-beautiful-dnd';
type Props<T = any> = {
onDragEndCb: (result: T[]) => void;
renderClone?: DraggableChildrenFn;
children: ({
provided,
snapshot
}: {
provided: DroppableProvided;
snapshot: DroppableStateSnapshot;
}) => ReactElement<HTMLElement, string>;
children: DroppableProps['children'];
dataList: T[];
zoom?: number;
};
function DndDrag<T>({ children, renderClone, onDragEndCb, dataList, zoom = 1 }: Props<T>) {
function DndDrag<T>({ children, renderClone, onDragEndCb, dataList }: Props<T>) {
const [draggingItemHeight, setDraggingItemHeight] = useState(0);
const onDragStart = (start: DragStart) => {
@@ -52,12 +44,14 @@ function DndDrag<T>({ children, renderClone, onDragEndCb, dataList, zoom = 1 }:
return (
<DragDropContext onDragStart={onDragStart} onDragEnd={onDragEnd}>
<Droppable droppableId="droppable" renderClone={renderClone}>
{(provided, snapshot) => (
<>
{children({ provided, snapshot })}
{snapshot.isDraggingOver && <Box height={`${draggingItemHeight / zoom}px`} />}
</>
)}
{(provided, snapshot) => {
return (
<Box {...provided.droppableProps} ref={provided.innerRef}>
{children(provided, snapshot)}
{snapshot.isDraggingOver && <Box height={`${draggingItemHeight}px`} />}
</Box>
);
}}
</Droppable>
</DragDropContext>
);

View File

@@ -178,7 +178,6 @@ export const iconPaths = {
'core/chat/sideLine': () => import('./icons/core/chat/sideLine.svg'),
'core/chat/speaking': () => import('./icons/core/chat/speaking.svg'),
'core/chat/stopSpeech': () => import('./icons/core/chat/stopSpeech.svg'),
'core/chat/think': () => import('./icons/core/chat/think.svg'),
'core/dataset/commonDataset': () => import('./icons/core/dataset/commonDataset.svg'),
'core/dataset/commonDatasetColor': () => import('./icons/core/dataset/commonDatasetColor.svg'),
'core/dataset/commonDatasetOutline': () =>

View File

@@ -1,5 +1,6 @@
<svg viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.187134" width="16" height="16" rx="8" fill="#F04438"/>
<path d="M8.18717 4.78638C7.81898 4.78638 7.52051 5.08485 7.52051 5.45304V8.44501C7.52051 8.8132 7.81898 9.11168 8.18717 9.11168C8.55536 9.11168 8.85384 8.8132 8.85384 8.44501V5.45304C8.85384 5.08485 8.55536 4.78638 8.18717 4.78638Z" fill="white"/>
<path d="M8.18717 9.76652C7.81898 9.76652 7.52051 10.065 7.52051 10.4332C7.52051 10.8014 7.81898 11.0998 8.18717 11.0998C8.55536 11.0998 8.85384 10.8014 8.85384 10.4332C8.85384 10.065 8.55536 9.76652 8.18717 9.76652Z" fill="white"/>
</svg>
<svg t="1705054369902" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3174"
width="128" height="128">
<path
d="M512 0C229.205333 0 0 229.205333 0 512s229.205333 512 512 512 512-229.205333 512-512S794.794667 0 512 0z m0 796.458667A56.917333 56.917333 0 1 1 511.957333 682.666667 56.917333 56.917333 0 0 1 512 796.458667z m54.186667-227.797334h0.128a60.501333 60.501333 0 0 1-53.802667 55.893334c2.048 0.256 3.882667 1.152 5.973333 1.152h-11.818666c2.048 0 3.84-0.981333 5.845333-1.109334a59.093333 59.093333 0 0 1-53.162667-55.893333l-13.056-284.16a54.314667 54.314667 0 0 1 54.613334-57.045333h26.282666a52.992 52.992 0 0 1 54.186667 57.002666l-15.146667 284.16z"
fill="#D92D20" p-id="3175"></path>
</svg>

Before

Width:  |  Height:  |  Size: 628 B

After

Width:  |  Height:  |  Size: 774 B

View File

@@ -1 +0,0 @@
<svg t="1737983662269" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6134" width="64" height="64"><path d="M512 512m-91.264 0a91.264 91.264 0 1 0 182.528 0 91.264 91.264 0 1 0-182.528 0Z" fill="" p-id="6135"></path><path d="M256.341333 693.546667l-20.138666-5.12C86.101333 650.496 0 586.112 0 511.829333s86.101333-138.666667 236.202667-176.597333l20.138666-5.077333 5.674667 19.968a1003.946667 1003.946667 0 0 0 58.154667 152.661333l4.309333 9.088-4.309333 9.088a994.432 994.432 0 0 0-58.154667 152.661333l-5.674667 19.925334zM226.858667 381.866667c-114.090667 32.042667-184.106667 81.066667-184.106667 129.962666 0 48.853333 70.016 97.877333 184.106667 129.962667a1064.533333 1064.533333 0 0 1 50.432-129.962667A1056.085333 1056.085333 0 0 1 226.858667 381.866667z m540.8 311.68l-5.674667-20.010667a996.565333 996.565333 0 0 0-58.197333-152.618667l-4.309334-9.088 4.309334-9.088a999.253333 999.253333 0 0 0 58.197333-152.661333l5.674667-19.968 20.181333 5.077333c150.058667 37.930667 236.16 102.314667 236.16 176.64s-86.101333 138.666667-236.16 176.597334l-20.181333 5.12z m-20.949334-181.717334c20.48 44.330667 37.418667 87.893333 50.432 129.962667 114.133333-32.085333 184.106667-81.109333 184.106667-129.962667 0-48.896-70.016-97.877333-184.106667-129.962666a1057.621333 1057.621333 0 0 1-50.432 129.962666z" fill="" p-id="6136"></path><path d="M226.56 381.653333l-5.674667-19.925333C178.688 212.992 191.488 106.410667 256 69.205333c63.274667-36.522667 164.864 6.613333 271.317333 115.882667l14.506667 14.890667-14.506667 14.890666a1004.885333 1004.885333 0 0 0-103.338666 126.592l-5.76 8.234667-10.026667 0.853333a1009.365333 1009.365333 0 0 0-161.493333 26.026667l-20.138667 5.077333z m80.896-282.88c-11.434667 0-21.546667 2.474667-30.08 7.381334-42.410667 24.448-49.92 109.44-20.693333 224.128a1071.872 1071.872 0 0 1 137.941333-21.376 1060.138667 1060.138667 0 0 1 87.552-108.544c-66.56-64.810667-129.578667-101.589333-174.72-101.589334z m409.130667 868.778667c-0.042667 0-0.042667 0 0 0-60.8 0-138.88-45.781333-219.904-128.981333l-14.506667-14.890667 14.506667-14.890667a1003.946667 1003.946667 0 0 0 103.296-126.634666l5.76-8.234667 9.984-0.853333a1008.213333 1008.213333 0 0 0 161.578666-25.984l20.138667-5.077334 5.717333 19.968c42.112 148.650667 29.354667 255.274667-35.157333 292.437334a101.546667 101.546667 0 0 1-51.413333 13.141333z m-174.762667-144.256c66.56 64.810667 129.578667 101.589333 174.72 101.589333h0.042667c11.392 0 21.546667-2.474667 30.037333-7.381333 42.410667-24.448 49.962667-109.482667 20.693333-224.170667a1067.52 1067.52 0 0 1-137.984 21.376 1052.757333 1052.757333 0 0 1-87.509333 108.586667z" fill="" p-id="6137"></path><path d="M797.44 381.653333l-20.138667-5.077333a1001.770667 1001.770667 0 0 0-161.578666-26.026667l-9.984-0.853333-5.76-8.234667a998.997333 998.997333 0 0 0-103.296-126.592l-14.506667-14.890666 14.506667-14.890667C603.093333 75.861333 704.64 32.725333 768 69.205333c64.512 37.205333 77.312 143.786667 35.157333 292.48l-5.717333 19.968zM629.333333 308.906667c48.725333 4.437333 95.018667 11.648 137.984 21.376 29.269333-114.688 21.717333-199.68-20.693333-224.128-42.154667-24.362667-121.386667 12.970667-204.8 94.208A1060.224 1060.224 0 0 1 629.333333 308.906667zM307.456 967.552A101.546667 101.546667 0 0 1 256 954.410667c-64.512-37.162667-77.312-143.744-35.114667-292.437334l5.632-19.968 20.138667 5.077334c49.28 12.416 103.637333 21.162667 161.493333 25.984l10.026667 0.853333 5.717333 8.234667a1006.762667 1006.762667 0 0 0 103.338667 126.634666l14.506667 14.890667-14.506667 14.890667c-80.981333 83.2-159.061333 128.981333-219.776 128.981333z m-50.773333-274.218667c-29.269333 114.688-21.717333 199.722667 20.693333 224.170667 42.112 24.021333 121.301333-13.013333 204.8-94.208a1066.581333 1066.581333 0 0 1-87.552-108.586667 1065.642667 1065.642667 0 0 1-137.941333-21.376z" fill="" p-id="6138"></path><path d="M512 720.128c-35.114667 0-71.210667-1.536-107.349333-4.522667l-10.026667-0.853333-5.76-8.234667a1296.554667 1296.554667 0 0 1-57.6-90.538666 1295.104 1295.104 0 0 1-49.749333-95.061334l-4.266667-9.088 4.266667-9.088a1292.8 1292.8 0 0 1 49.749333-95.061333c17.664-30.549333 37.077333-61.013333 57.6-90.538667l5.76-8.234666 10.026667-0.853334a1270.826667 1270.826667 0 0 1 214.741333 0l9.984 0.853334 5.717333 8.234666a1280.256 1280.256 0 0 1 107.392 185.6l4.309334 9.088-4.309334 9.088a1262.933333 1262.933333 0 0 1-107.392 185.6l-5.717333 8.234667-9.984 0.853333c-36.138667 2.986667-72.277333 4.522667-107.392 4.522667z m-93.738667-46.250667c63.146667 4.736 124.330667 4.736 187.52 0a1237.589333 1237.589333 0 0 0 93.696-162.048 1219.626667 1219.626667 0 0 0-93.738666-162.048 1238.656 1238.656 0 0 0-187.477334 0 1215.018667 1215.018667 0 0 0-93.738666 162.048 1242.197333 1242.197333 0 0 0 93.738666 162.048z" p-id="6139"></path></svg>

Before

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -27,7 +27,7 @@ const InputSlider = ({
valLen * 0.8 + min,
valLen * 0.985 + min
];
}, [max, min]);
}, []);
return (
<HStack zIndex={10} spacing={3}>

View File

@@ -66,6 +66,12 @@ const NodeInputSelect = ({
title: t('common:core.workflow.inputType.dynamicTargetInput')
},
{
type: FlowNodeInputTypeEnum.selectApp,
icon: FlowNodeInputMap[FlowNodeInputTypeEnum.selectApp].icon,
title: t('common:core.workflow.inputType.Manual select')
},
{
type: FlowNodeInputTypeEnum.selectLLMModel,
icon: FlowNodeInputMap[FlowNodeInputTypeEnum.selectLLMModel].icon,

View File

@@ -53,7 +53,7 @@ export function usePagination<DataT, ResT = {}>(
const isEmpty = total === 0 && !isLoading;
const noMore = data.length >= totalDataLength;
const fetchData = useMemoizedFn(
const fetchData = useLockFn(
async (num: number = pageNum, ScrollContainerRef?: RefObject<HTMLDivElement>) => {
if (noMore && num !== 1) return;
setTrue();
@@ -99,12 +99,11 @@ export function usePagination<DataT, ResT = {}>(
onChange?.(num);
} catch (error: any) {
if (error.code !== 'ERR_CANCELED') {
toast({
title: getErrText(error, t('common:core.chat.error.data_error')),
status: 'error'
});
}
toast({
title: getErrText(error, t('common:core.chat.error.data_error')),
status: 'error'
});
console.log(error);
}
setFalse();
@@ -247,6 +246,7 @@ export function usePagination<DataT, ResT = {}>(
// Reload data
const { runAsync: refresh } = useRequest(
async () => {
setData([]);
defaultRequest && fetchData(1);
},
{

View File

@@ -304,7 +304,7 @@ export function useScrollPagination<
);
return (
<MyBox ref={ref} h={'100%'} overflow={'auto'} isLoading={isLoading} {...props}>
<MyBox {...props} ref={ref} overflow={'overlay'} isLoading={isLoading}>
{scrollLoadType === 'top' && total > 0 && isLoading && (
<Box mt={2} fontSize={'xs'} color={'blackAlpha.500'} textAlign={'center'}>
{t('common:common.is_requesting')}

View File

@@ -20,9 +20,9 @@
"model.charsPointsPrice": "Chars Price",
"model.charsPointsPrice_tip": "Combine the model input and output for Token billing. If the language model is configured with input and output billing separately, the input and output will be calculated separately.",
"model.custom_cq_prompt": "Custom question classification prompt words",
"model.custom_cq_prompt_tip": "Override the system's default question classification prompt words, which default to:\n\"\"\"\n{{prompt}}\n\"\"\"",
"model.custom_cq_prompt_tip": "Override the system's default question classification prompt words, which default to:\n\"\"\"\n请帮我执行一个“问题分类”任务,将问题分类为以下几种类型之一:\n\n\"\"\"\n{{typeList}}\n\"\"\"\n\n## 背景知识\n{{systemPrompt}}\n\n## 对话记录\n{{history}}\n\n## 开始任务\n\n现在我们开始分类我会给你一个\"问题\"请结合背景知识和对话记录将问题分类到对应的类型中并返回类型ID。\n\n问题\"{{question}}\"\n类型ID=\n\"\"\"",
"model.custom_extract_prompt": "Custom content extraction prompt words",
"model.custom_extract_prompt_tip": "The reminder word of the coverage of the system, the default:\n\"\"\"\n{{prompt}}\n\"\"\"",
"model.custom_extract_prompt_tip": "Override system prompt word, default is:\n\"\"\"\n你可以从 <对话记录></对话记录> 中提取指定 Json 信息,你仅需返回 Json 字符串,无需回答问题。\n<提取要求>\n{{description}}\n</提取要求>\n\n<提取规则>\n- 本次需提取的 json 字符串,需符合 JsonSchema 的规则。\n- type 代表数据类型; key 代表字段名; description 代表字段的描述; enum 是枚举值,代表可选的 value。\n- 如果没有可提取的内容,忽略该字段。\n</提取规则>\n\n<JsonSchema>\n{{json}}\n</JsonSchema>\n\n<对话记录>\n{{text}}\n</对话记录>\n\n提取的 json 字符串:\n\"\"\"",
"model.dataset_process": "Dataset file parse",
"model.defaultConfig": "Additional Body parameters",
"model.defaultConfig_tip": "Each request will carry this additional Body parameter.",
@@ -46,20 +46,13 @@
"model.max_temperature": "Max temperature",
"model.model_id": "Model ID",
"model.model_id_tip": "The unique identifier of the model, that is, the value of the actual request to the service provider model, needs to correspond to the model in the OneAPI channel.",
"model.normalization": "Normalization processing",
"model.normalization_tip": "If the Embedding API does not normalize vector values, the switch can be enabled and the system will normalize.\n\nUnnormalized APIs, which are represented by the vector search score greater than 1.",
"model.output_price": "Output price",
"model.output_price_tip": "The language model output price. If this item is configured, the model comprehensive price will be invalid.",
"model.param_name": "Parameter name",
"model.reasoning": "Support output thinking",
"model.reasoning_tip": "For example, Deepseek-reasoner can output the thinking process.",
"model.request_auth": "Custom key",
"model.request_auth": "Custom token",
"model.request_auth_tip": "When making a request to a custom request address, carry the request header: Authorization: Bearer xxx to make the request.",
"model.request_url": "Custom url",
"model.request_url_tip": "If you fill in this value, you will initiate a request directly without passing. \nYou need to follow the API format of Openai and fill in the full request address, such as\n\nLLM: {Host}}/v1/Chat/Completions\n\nEmbedding: {host}}/v1/embeddings\n\nSTT: {Host}/v1/Audio/Transcriptions\n\nTTS: {Host}}/v1/Audio/Speech\n\nRERARARARARARARANK: {Host}}/v1/RERARARARARARARARARARANK",
"model.response_format": "Response format",
"model.show_stop_sign": "Display stop sequence parameters",
"model.show_top_p": "Show Top-p parameters",
"model.request_url_tip": "If this value is filled in, a request will be made directly to this address without going through OneAPI",
"model.test_model": "Model testing",
"model.tool_choice": "Tool choice",
"model.tool_choice_tag": "ToolCall",

View File

@@ -7,12 +7,8 @@
"ai_settings": "AI Configuration",
"all_apps": "All Applications",
"app.Version name": "Version Name",
"app.error.publish_unExist_app": "Release failed, please check whether the tool call is normal",
"app.error.unExist_app": "Some components are missing, please delete them",
"app.modules.click to update": "Click to Refresh",
"app.modules.has new version": "New Version Available",
"app.modules.not_found": "Not Found",
"app.modules.not_found_tips": "This component cannot be found in the system, please delete it, otherwise the process will not run normally",
"app.version_current": "Current Version",
"app.version_initial": "Initial Version",
"app.version_name_tips": "Version name cannot be empty",
@@ -81,10 +77,7 @@
"llm_use_vision_tip": "After clicking on the model selection, you can see whether the model supports image recognition and the ability to control whether to start image recognition. \nAfter starting image recognition, the model will read the image content in the file link, and if the user question is less than 500 words, it will automatically parse the image in the user question.",
"logs_chat_user": "user",
"logs_empty": "No logs yet~",
"logs_export_confirm_tip": "There are a total of {{total}} dialogue records, confirm the export?",
"logs_export_title": "Time, source, user, title, total number of messages, user feedback, custom feedback, number of labeled answers, conversation details",
"logs_message_total": "Total Messages",
"logs_source": "source",
"logs_title": "Title",
"look_ai_point_price": "View all model billing standards",
"mark_count": "Number of Marked Answers",
@@ -116,17 +109,12 @@
"publish_channel": "Publish",
"publish_success": "Publish Successful",
"question_guide_tip": "After the conversation, 3 guiding questions will be generated for you.",
"reasoning_response": "Output thinking",
"response_format": "Response format",
"saved_success": "Saved successfully! \nTo use this version externally, click Save and Publish",
"search_app": "Search apps",
"setting_app": "Workflow",
"setting_plugin": "Workflow",
"show_top_p_tip": "An alternative method of temperature sampling, called Nucleus sampling, the model considers the results of tokens with TOP_P probability mass quality. \nTherefore, 0.1 means that only tokens containing the highest probability quality are considered. \nThe default is 1.",
"simple_tool_tips": "This plugin contains special inputs and is not currently supported for invocation by simple applications.",
"source_updateTime": "Update time",
"stop_sign": "Stop",
"stop_sign_placeholder": "Multiple serial numbers are separated by |, for example: aaa|stop",
"stream_response": "Stream",
"stream_response_tip": "Turning this switch off forces the model to use non-streaming mode and will not output content directly. \nIn the output of the AI reply, the content output by this model can be obtained for secondary processing.",
"temperature": "Temperature",

View File

@@ -2,7 +2,6 @@
"AI_input_is_empty": "The content passed to the AI node is empty",
"Delete_all": "Clear All Lexicon",
"LLM_model_response_empty": "The model flow response is empty, please check whether the model flow output is normal.",
"ai_reasoning": "Thinking process",
"chat_history": "Conversation History",
"chat_input_guide_lexicon_is_empty": "Lexicon not configured yet",
"chat_test_app": "Debug-{{name}}",
@@ -37,10 +36,7 @@
"not_query": "Missing query content",
"not_select_file": "No file selected",
"plugins_output": "Plugin Output",
"query_extension_IO_tokens": "Problem Optimization Input/Output Tokens",
"query_extension_result": "Problem optimization results",
"question_tip": "From top to bottom, the response order of each module",
"reasoning_text": "Thinking process",
"response.child total points": "Sub-workflow point consumption",
"response.dataset_concat_length": "Combined total",
"response.node_inputs": "Node Inputs",

View File

@@ -23,9 +23,7 @@
"Move": "Move",
"Name": "Name",
"None": "None",
"Operation": "Operation",
"Rename": "Rename",
"Required_input": "Required",
"Resume": "Resume",
"Running": "Running",
"Select_all": "Select all",
@@ -167,6 +165,7 @@
"common.Not open": "Not Open",
"common.OK": "OK",
"common.Open": "Open",
"common.Operation": "Operation",
"common.Other": "Other",
"common.Output": "Output",
"common.Params": "Parameters",
@@ -180,6 +179,7 @@
"common.Remove": "Remove",
"common.Rename": "Rename",
"common.Request Error": "Request Error",
"common.Require Input": "Required",
"common.Reset": "Reset",
"common.Restart": "Restart",
"common.Role": "Permission",
@@ -448,7 +448,6 @@
"core.chat.markdown.Edit Question": "Edit Question",
"core.chat.markdown.Quick Question": "Click to Ask Immediately",
"core.chat.markdown.Send Question": "Send Question",
"core.chat.module_unexist": "Running failed: Application missing components",
"core.chat.quote.Quote Tip": "Only the actual quoted content is displayed here. If the data is updated, it will not be updated in real-time here.",
"core.chat.quote.Read Quote": "View Quote",
"core.chat.response.Complete Response": "Complete Response",
@@ -788,7 +787,7 @@
"core.view_chat_detail": "View Chat Details",
"core.workflow.Can not delete node": "This Node Cannot Be Deleted",
"core.workflow.Change input type tip": "Changing the input type will clear the filled values, please confirm!",
"core.workflow.Check Failed": "Workflow verification failed, please check whether the value is missing, and whether the connection is normal.",
"core.workflow.Check Failed": "Workflow Validation Failed, Please Check If the Nodes Are Correctly Filled and the Connections Are Normal",
"core.workflow.Confirm stop debug": "Confirm to Stop Debugging? Debug Information Will Not Be Retained.",
"core.workflow.Copy node": "Node Copied",
"core.workflow.Custom inputs": "Custom Inputs",
@@ -876,16 +875,13 @@
"dataset.dataset_name": "Dataset Name",
"dataset.deleteFolderTips": "Confirm to Delete This Folder and All Its Contained Datasets? Data Cannot Be Recovered After Deletion, Please Confirm!",
"dataset.test.noResult": "No Search Results",
"deep_rag_search": "In-depth search",
"delete_api": "Are you sure you want to delete this API key? \nAfter deletion, the key will become invalid immediately and the corresponding conversation log will not be deleted. Please confirm!",
"embedding_model_not_config": "No index model is detected",
"error.Create failed": "Create failed",
"error.code_error": "Verification code error",
"error.fileNotFound": "File not found~",
"error.inheritPermissionError": "Inherit permission Error",
"error.invalid_params": "Invalid parameter",
"error.missingParams": "Insufficient parameters",
"error.send_auth_code_too_frequently": "Please do not obtain verification code frequently",
"error.too_many_request": "Too many request",
"error.upload_file_error_filename": "{{name}} Upload Failed",
"error.upload_image_error": "File upload failed",
@@ -915,7 +911,6 @@
"item_name": "Field Name",
"just_now": "just",
"key_repetition": "Key Repetition",
"llm_model_not_config": "No language model was detected",
"max_quote_tokens": "Quote cap",
"max_quote_tokens_tips": "The maximum number of tokens in a single search, about 1 character in Chinese = 1.7 tokens, and about 1 character in English = 1 token",
"min_similarity": "lowest correlation",

View File

@@ -1,8 +1,6 @@
{
"Chinese_ip_tip": "It is detected that you are a mainland Chinese IP, click to jump to visit the mainland China version.",
"Login": "Login",
"agree": "agree",
"cookies_tip": " This website uses cookies to provide a better service experience. By continuing to use the site, you agree to our Cookie Policy.",
"forget_password": "Find Password",
"login_failed": "Login failed",
"login_success": "Login successful",
@@ -11,10 +9,12 @@
"password_tip": "Password must be at least 6 characters long and contain at least two combinations: numbers, letters, or special characters",
"policy_tip": "By using this service, you agree to our",
"privacy": "Privacy Policy",
"privacy_policy": "Privacy Policy",
"redirect": "Jump",
"register": "Register",
"root_password_placeholder": "The root user password is the value of the environment variable DEFAULT_ROOT_PSW",
"terms": "Terms",
"use_root_login": "Log in as root user"
"use_root_login": "Log in as root user",
"agree": "agree",
"cookies_tip": " This website uses cookies to provide a better service experience. By continuing to use the site, you agree to our Cookie Policy.",
"privacy_policy": "Privacy Policy"
}

View File

@@ -139,7 +139,6 @@
"quote_role_system_tip": "Please note that the {{question}} variable is removed from the \"Quote Template Prompt Words\"",
"quote_role_user_tip": "Please pay attention to adding the {{question}} variable in the \"Quote Template Prompt Word\"",
"raw_response": "Raw Response",
"reasoning_text": "Thinking text",
"regex": "Regex",
"reply_text": "Reply Text",
"request_error": "Request Error",

View File

@@ -20,9 +20,9 @@
"model.charsPointsPrice": "模型综合价格",
"model.charsPointsPrice_tip": "将模型输入和输出合并起来进行 Token 计费,语言模型如果单独配置了输入和输出计费,则按输入和输出分别计算",
"model.custom_cq_prompt": "自定义问题分类提示词",
"model.custom_cq_prompt_tip": "覆盖系统默认的问题分类提示词,默认为:\n\"\"\"\n{{prompt}}\n\"\"\"",
"model.custom_cq_prompt_tip": "覆盖系统默认的问题分类提示词,默认为:\n",
"model.custom_extract_prompt": "自定义内容提取提示词",
"model.custom_extract_prompt_tip": "覆盖系统的提示词,默认为:\n\"\"\"\n{{prompt}}\n\"\"\"",
"model.custom_extract_prompt_tip": "覆盖系统的提示词,默认为:\n\"\"\"\n你可以从 <对话记录></对话记录> 中提取指定 Json 信息,你仅需返回 Json 字符串,无需回答问题。\n<提取要求>\n{{description}}\n</提取要求>\n\n<提取规则>\n- 本次需提取的 json 字符串,需符合 JsonSchema 的规则。\n- type 代表数据类型; key 代表字段名; description 代表字段的描述; enum 是枚举值,代表可选的 value。\n- 如果没有可提取的内容,忽略该字段。\n</提取规则>\n\n<JsonSchema>\n{{json}}\n</JsonSchema>\n\n<对话记录>\n{{text}}\n</对话记录>\n\n提取的 json 字符串:\n\"\"\"",
"model.dataset_process": "用于知识库文件处理",
"model.defaultConfig": "额外 Body 参数",
"model.defaultConfig_tip": "每次请求时候,都会携带该额外 Body 参数",
@@ -46,20 +46,13 @@
"model.max_temperature": "最大温度",
"model.model_id": "模型ID",
"model.model_id_tip": "模型的唯一标识也就是实际请求到服务商model 的值,需要与 OneAPI 渠道中的模型对应。",
"model.normalization": "归一化处理",
"model.normalization_tip": "如果Embedding API 未对向量值进行归一化,可以启用该开关,系统会进行归一化处理。\n未归一化的 API表现为向量检索得分会大于 1。",
"model.output_price": "模型输出价格",
"model.output_price_tip": "语言模型输出价格,如果配置了该项,则模型综合价格会失效",
"model.param_name": "参数名",
"model.reasoning": "支持输出思考",
"model.reasoning_tip": "例如 Deepseek-reasoner可以输出思考过程。",
"model.request_auth": "自定义请求 Key",
"model.request_auth": "自定义请求 Tokens",
"model.request_auth_tip": "向自定义请求地址发起请求时候携带请求头Authorization: Bearer xxx 进行请求",
"model.request_url": "自定义请求地址",
"model.request_url_tip": "如果填写该值,则会直接向该地址发起请求,不经过 OneAPI。需要遵循 OpenAI 的 API格式并填写完整请求地址例如\nLLM: {{host}}/v1/chat/completions\nEmbedding: {{host}}/v1/embeddings\nSTT: {{host}}/v1/audio/transcriptions\nTTS: {{host}}/v1/audio/speech\nRerank: {{host}}/v1/rerank",
"model.response_format": "响应格式",
"model.show_stop_sign": "展示停止序列参数",
"model.show_top_p": "展示 Top-p 参数",
"model.request_url_tip": "如果填写该值,则会直接向该地址发起请求,不经过 OneAPI",
"model.test_model": "模型测试",
"model.tool_choice": "支持工具调用",
"model.tool_choice_tag": "工具调用",

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