Compare commits

..

55 Commits

Author SHA1 Message Date
Archer
09205e4666 fix: price page init data;perf: usage code;fix: reasoning tokens;fix: workflow basic node cannot upgrade (#3816)
* fix: img read

* fix: price page init data

* perf: ai model avatar

* perf: refresh in change team

* perf: null checker

* perf: usage code

* fix: reasoning tokens

* fix: workflow basic node cannot upgrade

* perf: model refresh

* perf: icon refresh
2025-02-18 20:50:25 +08:00
Finley Ge
ccf28d83b8 fix: app version addSourcemember tmbid could be empty (#3822) 2025-02-18 20:26:49 +08:00
LGiki
420aaad48e chore: fix typo in docs (#3819) 2025-02-18 20:25:51 +08:00
heheer
8ba2339890 download fetch baseurl & node select dnd (#3820) 2025-02-18 20:25:15 +08:00
Archer
e7b8934367 Update 4818.md (#3818) 2025-02-18 14:26:21 +08:00
Finley Ge
3e13397614 fix: refresh memberlist when switching account (#3814) 2025-02-18 13:54:56 +08:00
Archer
b14674cc6f fix: whisper checker;fix: img read (#3813)
* fix: img read

* fix: whisper checker

* perf: dev doc

* perf: dev doc

* remove invalid code
2025-02-18 10:08:25 +08:00
Archer
4d20274a97 feat: think tag parse (#3805) (#3808)
* feat: think tag parse

* remove some model config

* feat: parse think tag test
2025-02-17 20:57:36 +08:00
heheer
4447e40364 fix template market simple app (#3804) 2025-02-17 20:56:46 +08:00
John Chen
23949230ee fix document (#3806)
V2版本“获取集合列表”接口的path区分了大小写,使用/api/core/dataset/collection/listv2会返回404,必须使用大写V
2025-02-17 20:55:34 +08:00
saikidev
cd7a897304 chore: add ppio provider (#3789) 2025-02-14 17:04:43 +08:00
Archer
18aff8b8db update yml version (#3787) 2025-02-14 12:50:54 +08:00
Archer
d2b60ec785 fix: model check circle tip (#3786)
* model config

* feat: normalization embedding

* remove log

* version doc

* version doc

* fix: model check circle tip

* uml
2025-02-14 11:42:14 +08:00
a.e.
1226fe42a1 fix: skip thirdparty sso state verification (#3721) (#3782) 2025-02-14 11:39:34 +08:00
Finley Ge
abd375cdec fix: app/dataset list api return private flag (#3784) 2025-02-14 11:38:48 +08:00
Archer
7aacce8b0b 4.9.0 test (#3779)
* model config

* feat: normalization embedding

* remove log

* version doc

* version doc
2025-02-13 16:27:41 +08:00
heheer
686b09afd1 chatbot not overflow (#3777)
* chatbot not overflow

* add comment
2025-02-13 15:10:22 +08:00
heheer
3cfec37e9d fix embed chatbot default open (#3774) 2025-02-13 13:36:56 +08:00
Archer
d3641c877c perf: unlogin user fetch data (#3775)
* model config

* feat: normalization embedding

* perf: unlogin user fetch data
2025-02-13 13:36:33 +08:00
Archer
1094c65f2b perf: http empty params (#3773)
* model config

* feat: normalization embedding

* perf: http empty params

* doc
2025-02-13 10:35:11 +08:00
Archer
abe082b9ab i18n perf (#3770)
* model config

* feat: normalization embedding

* perf: mark ui

* perf: i18n

* fix: rerank error tip
2025-02-12 16:36:21 +08:00
heheer
132cf69372 optimize dnd drag code (#3768) 2025-02-12 15:25:31 +08:00
heheer
06a8a5e23d fix: simple mode variables dnd (#3767)
* fix: simple mode variables dnd

* optimize dnd drag
2025-02-12 14:36:04 +08:00
heheer
c42deab63b global variable & interactive node dnd (#3764) 2025-02-12 12:27:36 +08:00
Archer
58f715e878 perf: request quantity;perf: share page error circulation;perf: share chat toast (#3763)
* model config

* feat: normalization embedding

* perf: share page error circulation

* perf: request quantity

* perf: share chat toast

* perf: queue
2025-02-12 11:36:29 +08:00
Archer
116936ffa9 更新 share.md (#3757) 2025-02-11 23:54:42 +08:00
heheer
f5d045eece export csv format & log title debounce (#3754) 2025-02-11 17:36:00 +08:00
sbcyk
8ac6494e60 Update chat.md (#3746)
示例代码的json内容少了一个引号
2025-02-11 17:31:30 +08:00
heheer
f002896a24 chat logs filter & export (#3737)
* chat logs filter & export

* export chat detail
2025-02-11 16:32:47 +08:00
Archer
8738c32fb0 4.8.21 feature (#3742)
* model config

* feat: normalization embedding

* adapt unstrea  reasoning response

* remove select app

* perf: dataset search code

* fix: multiple audio video show

* perf: query extension output

* perf: link check

* perf: faq doc

* fix: ts

* feat: support reasoning text output

* feat: workflow support reasoning output
2025-02-11 13:53:08 +08:00
heheer
896a3f1472 add plugin unexist error tips (#3717)
* add plugin unexist error tips

* throw error when run plugin

* check workflow

* plugin data avoid request twice

* auth owner tmbId

* fix
2025-02-10 15:20:49 +08:00
John Chen
4284b78707 Update configuration.md (#3725)
由于4.8.20版本放弃在config.json中配置模型,在说明文档中,修正二级标题的版本号,并添加注释
2025-02-10 09:13:17 +08:00
Archer
fac5b6b50d 更新 4820.md (#3730) 2025-02-09 10:06:08 +08:00
Archer
51e17a47fa feat: normalization embedding;feat: model top_p param config (#3723)
* edit form force close image select

* model config

* feat: normalization embedding

* perf: add share page title force refresh
2025-02-08 12:16:46 +08:00
Archer
42b2046f96 4.8.21 feature (#3720)
* agent search demo

* edit form force close image select

* feat: llm params and doubao1.5

* perf: model error tip

* fix: template register path

* package
2025-02-08 10:44:33 +08:00
heheer
bb82b515e0 feat: auto adapt outlink chatwindow position (#3707) 2025-02-08 09:49:41 +08:00
clidxhk
fe688cdf2d Update utils.ts (#3699)
本地windows平台开发,加载model列表出现两次盘符导致加载失败,修改代码确保生成的路径不会包含重复的盘符,从而避免 ENOENT 错误。
2025-02-07 09:52:08 +08:00
Archer
0d35326909 fix: yml (#3709) 2025-02-06 16:03:45 +08:00
Archer
d857a391b3 4.8.20 update (#3706)
* fix: rerank auth token

* feat: check null value

* bind notify

* perf: reasoning config

* Adapt mongo 4.x index
2025-02-06 14:34:43 +08:00
Archer
772c1cde77 remove log (#3692) 2025-02-05 11:17:38 +08:00
Archer
b6e441c5eb fix: replace img host (#3691) 2025-02-05 10:21:35 +08:00
Archer
ac95828660 update doc (#3690) 2025-02-05 10:01:57 +08:00
Archer
f252918228 model config doc (#3689) 2025-02-05 09:52:03 +08:00
Archer
5c360b5ae6 doc (#3688) 2025-02-05 01:34:10 +08:00
Archer
09fa602dde readme (#3687)
* fix: doc deploy

* readme
2025-02-05 00:26:24 +08:00
Archer
db2c0a0bdb V4.8.20 feature (#3686)
* 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

* feat: usage filter & export & dashbord (#3538)

* feat: usage filter & export & dashbord

* adjust ui

* fix tmb scroll

* fix code & selecte all

* merge

* perf: usages list;perf: move components (#3654)

* perf: usages list

* team sub plan load

* perf: usage dashboard code

* perf: dashboard ui

* perf: move components

* add default model config (#3653)

* 4.8.20 test (#3656)

* provider

* perf: model config

* model perf (#3657)

* fix: model

* dataset quote

* perf: model config

* model tag

* doubao model config

* perf: config model

* feat: model test

* fix: POST 500 error on dingtalk bot (#3655)

* feat: default model (#3662)

* move model config

* feat: default model

* fix: false triggerd org selection (#3661)

* export usage csv i18n (#3660)

* export usage csv i18n

* fix build

* 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

* reload buffer (#3665)

* reload buffer

* reload buffer

* tts selector

* fix: err tip (#3666)

* fix: err tip

* perf: training queue

* doc

* fix interactive edge (#3659)

* fix interactive edge

* fix

* comment

* add gemini model

* fix: chat model select

* perf: supplement assistant empty response (#3669)

* perf: supplement assistant empty response

* check array

* perf: max_token count;feat: support resoner output;fix: member scroll (#3681)

* perf: supplement assistant empty response

* check array

* perf: max_token count

* feat: support resoner output

* member scroll

* update provider order

* i18n

* fix: stream response (#3682)

* perf: supplement assistant empty response

* check array

* fix: stream response

* fix: model config cannot set to null

* fix: reasoning response (#3684)

* perf: supplement assistant empty response

* check array

* fix: reasoning response

* fix: reasoning response

* doc (#3685)

* perf: supplement assistant empty response

* check array

* doc

* lock

* animation

* update doc

* update compose

* doc

* doc

---------

Co-authored-by: heheer <heheer@sealos.io>
Co-authored-by: a.e. <49438478+I-Info@users.noreply.github.com>
2025-02-05 00:10:47 +08:00
Ge
c393002f1d feat: support mssql in databaseConnection plugin (#3674)
* feat: support mssql in databaseConnection plugin

* feat: trust server certificate for mssql
2025-02-01 10:53:20 +08:00
Archer
16629e32a7 4819 doc (#3646) 2025-01-22 10:01:09 +08:00
a.e.
d67474170a fix: permission conflict after moving (#3639) 2025-01-21 22:35:10 +08:00
Yee
e02a7ab350 chore: add intern and moka provider (#3640)
* chore: add intern and moka provider

* fix: svg show issue
2025-01-21 22:32:49 +08:00
heheer
d491105752 fix model provider icon (#3644) 2025-01-21 22:31:52 +08:00
shilin
fe59eadcee fix: 数字输入框无法输入0 (#3641) 2025-01-21 18:56:57 +08:00
Archer
946bd20dbf fix: loal file api error (#3637)
* update doc

* fix: loal file api error

* fix: number input import

* feat: icon load
2025-01-21 16:46:49 +08:00
Archer
3c97757e4d 4.8.19-feature (#3636)
* feat: sync org from wecom, pref: member list pagination (#3549)

* feat: sync org

* chore: fe

* chore: loading

* chore: type

* pref: team member list change to pagination. Edit a sort of list apis.

* feat: member update avatar

* chore: user avatar move to tmb

* chore: init scripts move user avatar

* chore: sourceMember

* fix: list api sourceMember

* fix: member sync

* fix: pagination

* chore: adjust code

* chore: move changeOwner to pro

* chore: init v4819 script

* chore: adjust code

* chore: UserBox

* perf: scroll page code

* perf: list data

* docs:更新用户答疑 (#3576)

* docs: add custom uid docs (#3572)

* fix: pagination bug (#3577)

* 4.8.19 test (#3584)

* faet: dataset search filter

* fix: scroll page

* fix: collection list api old version (#3591)

* fix: collection list api format

* fix: type error of addSourceMemeber

* fix: scroll fetch (#3592)

* fix: yuque dataset file folder can enter (#3593)

* perf: load members;perf: yuque load;fix: workflow llm params cannot close (#3594)

* chat openapi doc

* feat: dataset openapi doc

* perf: load members

* perf: member load code

* perf: yuque load

* fix: workflow llm params cannot close

* fix: api dataset reference tag preview (#3600)

* perf: doc

* feat: chat page config

* fix: http parse (#3634)

* update doc

* fix: http parse

* fix code run node reset template (#3633)

Co-authored-by: Archer <545436317@qq.com>

* docs:faq (#3627)

* docs:faq

* docsFix

* perf: sleep plugin

* fix: selector

---------

Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com>
Co-authored-by: Jiangween <145003935+Jiangween@users.noreply.github.com>
Co-authored-by: heheer <heheer@sealos.io>
2025-01-20 19:42:33 +08:00
shilin
9f33729ca9 feat(core): 添加 sleep 插件 (#3583)
(cherry picked from commit 09bdc63977)
2025-01-20 18:31:47 +08:00
615 changed files with 14133 additions and 6420 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 && hugo -v --minify
run: cd docSite && hugo mod get -u github.com/colinwilson/lotusdocs@6d0568e && 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 && hugo -v --minify
run: cd docSite && hugo mod get -u github.com/colinwilson/lotusdocs@6d0568e && hugo -v --minify
# Step 5 - Push our generated site to Vercel
- name: Deploy to Vercel

View File

@@ -83,6 +83,7 @@ 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 && hugo -v --minify
RUN cd /app/hugo && hugo mod get -u github.com/colinwilson/lotusdocs@6d0568e && hugo -v --minify
FROM fholzer/nginx-brotli:latest

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@@ -13,8 +13,8 @@ weight: 707
下面配置文件示例中包含了系统参数和各个模型配置:
## 4.6.8+ 版本新配置文件示例
## 4.8.20+ 版本新配置文件示例
> 从4.8.20版本开始,模型在页面中进行配置。
```json
{
"feConfigs": {
@@ -25,249 +25,6 @@ weight: 707
"qaMaxProcess": 15, // 问答拆分线程数量
"tokenWorkers": 50, // Token 计算线程保持数,会持续占用内存,不能设置太大。
"pgHNSWEfSearch": 100 // 向量搜索参数。越大搜索越精确但是速度越慢。设置为100有99%+精度。
},
"llmModels": [
{
"provider": "OpenAI", // 模型提供商主要用于分类展示目前已经内置提供商包括https://github.com/labring/FastGPT/blob/main/packages/global/core/ai/provider.ts, 可 pr 提供新的提供商,或直接填写 Other
"model": "gpt-4o-mini", // 模型名(对应OneAPI中渠道的模型名)
"name": "gpt-4o-mini", // 模型别名
"maxContext": 125000, // 最大上下文
"maxResponse": 16000, // 最大回复
"quoteMaxToken": 120000, // 最大引用内容
"maxTemperature": 1.2, // 最大温度
"charsPointsPrice": 0, // n积分/1k token商业版
"censor": false, // 是否开启敏感校验(商业版)
"vision": true, // 是否支持图片输入
"datasetProcess": true, // 是否设置为文本理解模型QA务必保证至少有一个为true否则知识库会报错
"usedInClassify": true, // 是否用于问题分类务必保证至少有一个为true
"usedInExtractFields": true, // 是否用于内容提取务必保证至少有一个为true
"usedInToolCall": true, // 是否用于工具调用务必保证至少有一个为true
"usedInQueryExtension": true, // 是否用于问题优化务必保证至少有一个为true
"toolChoice": true, // 是否支持工具选择(分类,内容提取,工具调用会用到。)
"functionCall": false, // 是否支持函数调用(分类,内容提取,工具调用会用到。会优先使用 toolChoice如果为false则使用 functionCall如果仍为 false则使用提示词模式
"customCQPrompt": "", // 自定义文本分类提示词(不支持工具和函数调用的模型
"customExtractPrompt": "", // 自定义内容提取提示词
"defaultSystemChatPrompt": "", // 对话默认携带的系统提示词
"defaultConfig": {}, // 请求API时挟带一些默认配置比如 GLM4 的 top_p
"fieldMap": {} // 字段映射o1 模型需要把 max_tokens 映射为 max_completion_tokens
},
{
"provider": "OpenAI",
"model": "gpt-4o",
"name": "gpt-4o",
"maxContext": 125000,
"maxResponse": 4000,
"quoteMaxToken": 120000,
"maxTemperature": 1.2,
"charsPointsPrice": 0,
"censor": false,
"vision": true,
"datasetProcess": true,
"usedInClassify": true,
"usedInExtractFields": true,
"usedInToolCall": true,
"usedInQueryExtension": true,
"toolChoice": true,
"functionCall": false,
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"defaultConfig": {},
"fieldMap": {}
},
{
"provider": "OpenAI",
"model": "o1-mini",
"name": "o1-mini",
"maxContext": 125000,
"maxResponse": 65000,
"quoteMaxToken": 120000,
"maxTemperature": 1.2,
"charsPointsPrice": 0,
"censor": false,
"vision": false,
"datasetProcess": true,
"usedInClassify": true,
"usedInExtractFields": true,
"usedInToolCall": true,
"usedInQueryExtension": true,
"toolChoice": false,
"functionCall": false,
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"defaultConfig": {
"temperature": 1,
"max_tokens": null,
"stream": false
}
},
{
"provider": "OpenAI",
"model": "o1-preview",
"name": "o1-preview",
"maxContext": 125000,
"maxResponse": 32000,
"quoteMaxToken": 120000,
"maxTemperature": 1.2,
"charsPointsPrice": 0,
"censor": false,
"vision": false,
"datasetProcess": true,
"usedInClassify": true,
"usedInExtractFields": true,
"usedInToolCall": true,
"usedInQueryExtension": true,
"toolChoice": false,
"functionCall": false,
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"defaultConfig": {
"temperature": 1,
"max_tokens": null,
"stream": false
}
}
],
"vectorModels": [
{
"provider": "OpenAI",
"model": "text-embedding-3-small",
"name": "text-embedding-3-small",
"charsPointsPrice": 0,
"defaultToken": 512,
"maxToken": 3000,
"weight": 100
},
{
"provider": "OpenAI",
"model": "text-embedding-3-large",
"name": "text-embedding-3-large",
"charsPointsPrice": 0,
"defaultToken": 512,
"maxToken": 3000,
"weight": 100,
"defaultConfig": {
"dimensions": 1024
}
},
{
"provider": "OpenAI",
"model": "text-embedding-ada-002", // 模型名与OneAPI对应
"name": "Embedding-2", // 模型展示名
"charsPointsPrice": 0, // n积分/1k token
"defaultToken": 700, // 默认文本分割时候的 token
"maxToken": 3000, // 最大 token
"weight": 100, // 优先训练权重
"defaultConfig": {}, // 自定义额外参数。例如,如果希望使用 embedding3-large 的话,可以传入 dimensions:1024来返回1024维度的向量。目前必须小于1536维度
"dbConfig": {}, // 存储时的额外参数(非对称向量模型时候需要用到)
"queryConfig": {} // 参训时的额外参数
}
],
"reRankModels": [],
"audioSpeechModels": [
{
"provider": "OpenAI",
"model": "tts-1",
"name": "OpenAI TTS1",
"charsPointsPrice": 0,
"voices": [
{ "label": "Alloy", "value": "alloy", "bufferId": "openai-Alloy" },
{ "label": "Echo", "value": "echo", "bufferId": "openai-Echo" },
{ "label": "Fable", "value": "fable", "bufferId": "openai-Fable" },
{ "label": "Onyx", "value": "onyx", "bufferId": "openai-Onyx" },
{ "label": "Nova", "value": "nova", "bufferId": "openai-Nova" },
{ "label": "Shimmer", "value": "shimmer", "bufferId": "openai-Shimmer" }
]
}
],
"whisperModel": {
"provider": "OpenAI",
"model": "whisper-1",
"name": "Whisper1",
"charsPointsPrice": 0
}
}
```
## 内置的模型提供商ID
为了方便模型分类展示FastGPT 内置了部分模型提供商的名字和 Logo。如果你期望补充提供商可[提交 Issue](https://github.com/labring/FastGPT/issues),并提供几个信息:
1. 厂商官网地址
2. 厂商 SVG logo建议是正方形图片。
目前已支持的提供商, 复制 "-" 之前的字符串,作为 provider 的值。
- OpenAI
- Claude
- Gemini
- Meta
- MistralAI
- AliCloud - 阿里云
- Qwen - 通义千问
- Doubao - 豆包
- ChatGLM - 智谱
- DeepSeek - 深度求索
- Moonshot - 月之暗面
- MiniMax
- SparkDesk - 讯飞星火
- Hunyuan - 腾讯混元
- Baichuan - 百川
- Yi - 零一万物
- Ernie - 文心一言
- StepFun - 阶跃星辰
- Ollama
- BAAI - 智源研究院
- FishAudio
- Other - 其他
## ReRank 模型接入
由于 OneAPI 不支持 Rerank 模型,所以需要单独配置接入,这里
### 使用硅基流动的在线模型
有免费的 `bge-reranker-v2-m3` 模型可以使用。
1. [点击注册硅基流动账号](https://cloud.siliconflow.cn/i/TR9Ym0c4)
2. 进入控制台,获取 API key: https://cloud.siliconflow.cn/account/ak
3. 修改 FastGPT 配置文件
```json
{
"reRankModels": [
{
"model": "BAAI/bge-reranker-v2-m3", // 这里的model需要对应 siliconflow 的模型名
"name": "BAAI/bge-reranker-v2-m3",
"requestUrl": "https://api.siliconflow.cn/v1/rerank",
"requestAuth": "siliconflow 上申请的 key"
}
]
}
```
### 私有部署模型
请使用 4.6.6-alpha 以上版本,配置文件中的 `reRankModels` 为重排模型虽然是数组不过目前仅有第1个生效。
1. [部署 ReRank 模型](/docs/development/custom-models/bge-rerank/)
1. 找到 FastGPT 的配置文件中的 `reRankModels` 4.6.6 以前是 `ReRankModels`
2. 修改对应的值:
```json
{
"reRankModels": [
{
"model": "bge-reranker-base", // 随意
"name": "检索重排-base", // 随意
"charsPointsPrice": 0,
"requestUrl": "{{host}}/v1/rerank",
"requestAuth": "安全凭证,已自动补 Bearer"
}
]
}
```

View File

@@ -118,10 +118,17 @@ services:
```
## 接入 FastGPT
参考 [ReRank模型接入](/docs/development/configuration/#rerank-接入)host 变量为部署的域名
1. 打开 FastGPT 模型配置,新增一个重排模型
2. 填写模型配置表单:模型 ID 为`bge-reranker-base`,地址填写`{{host}}/v1/rerank`host 为你部署的域名/IP:Port。
![alt text](/imgs/image-102.png)
## QA
### 403报错
FastGPT中自定义请求 Token 和环境变量的 ACCESS_TOKEN 不一致。
### Docker 运行提示 `Bus error (core dumped)`
尝试增加 `docker-compose.yml` 配置项 `shm_size` ,以增加容器中的共享内存目录大小。

View File

@@ -144,7 +144,6 @@ curl --location --request POST 'https://<oneapi_url>/v1/chat/completions' \
"usedInClassify": true, // 是否用于问题分类务必保证至少有一个为true
"usedInExtractFields": true, // 是否用于内容提取务必保证至少有一个为true
"usedInToolCall": true, // 是否用于工具调用务必保证至少有一个为true
"usedInQueryExtension": true, // 是否用于问题优化务必保证至少有一个为true
"toolChoice": true, // 是否支持工具选择(分类,内容提取,工具调用会用到。)
"functionCall": false, // 是否支持函数调用(分类,内容提取,工具调用会用到。会优先使用 toolChoice如果为false则使用 functionCall如果仍为 false则使用提示词模式
"customCQPrompt": "", // 自定义文本分类提示词(不支持工具和函数调用的模型

View File

@@ -7,6 +7,13 @@ toc: true
weight: 707
---
## 前置知识
1. 基础的网络知识:端口,防火墙……
2. Docker 和 Docker Compose 基础知识
3. 大模型相关接口和参数
4. RAG 相关知识:向量模型,向量数据库,向量检索
## 部署架构图
![](/imgs/sealos-fastgpt.webp)
@@ -202,6 +209,12 @@ docker restart oneapi
首次运行,会自动初始化 root 用户,密码为 `1234`(与环境变量中的`DEFAULT_ROOT_PSW`一致),日志里会提示一次`MongoServerError: Unable to read from a snapshot due to pending collection catalog changes;`可忽略。
### 6. 配置模型
务必先配置至少一组模型,否则系统无法正常使用。
[点击查看模型配置教程](/docs/development/modelConfig/intro/)
## FAQ
### Mongo 副本集自动初始化失败

View File

@@ -9,26 +9,48 @@ 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)
这是索引模型的长度限制,通过任何方式部署都一样的,但不同索引模型的配置不一样,可以在后台修改参数。
### sealos怎么挂载 小程序配置文件
### 怎么挂载小程序配置文件
将验证文件,挂载到指定位置:/app/projects/app/public/xxxx.txt
然后重启。例如:
新增配置文件:/app/projects/app/public/xxxx.txt
如图
![](/imgs/faq2.png)
### 数据库3306端口被占用了启动服务失败
![](/imgs/faq3.png)
把端口映射改成 3307 之类的,例如 3307:3306。
### 本地部署的限制
具体内容参考https://fael3z0zfze.feishu.cn/wiki/OFpAw8XzAi36Guk8dfucrCKUnjg。
@@ -122,7 +144,7 @@ OneAPI 的 API Key 配置错误,需要修改`OPENAI_API_KEY`环境变量,并
## 四、常见模型问题
### 如何检查模型问题
### 如何检查模型可用性问题
1. 私有部署模型,先确认部署的模型是否正常。
2. 通过 CURL 请求,直接测试上游模型是否正常运行(云端模型或私有模型均进行测试)
@@ -395,3 +417,7 @@ curl --location --request POST 'https://oneapi.xxxx/v1/chat/completions' \
"tool_choice": "auto"
}'
```
### 向量检索得分大于 1
由于模型没有归一化导致的。目前仅支持归一化的模型。

View File

@@ -15,8 +15,8 @@ weight: 705
- [Git](http://git-scm.com/)
- [Docker](https://www.docker.com/)(构建镜像)
- [Node.js v18.17 / v20.x](http://nodejs.org)版本尽量一样可以使用nvm管理node版本
- [pnpm](https://pnpm.io/) 版本 8.6.0 (目前官方的开发环境)
- [Node.js v20.14.0](http://nodejs.org)版本尽量一样可以使用nvm管理node版本
- [pnpm](https://pnpm.io/) 推荐版本 9.4.0 (目前官方的开发环境)
- make命令: 根据不同平台,百度安装 (官方是GNU Make 4.3)
## 开始本地开发
@@ -77,8 +77,6 @@ Mongo 数据库需要注意,需要注意在连接地址中增加 `directConnec
可参考项目根目录下的 `dev.md`,第一次编译运行可能会有点慢,需要点耐心哦
```bash
# 给自动化脚本代码执行权限(非 linux 系统, 可以手动执行里面的 postinstall.sh 文件内容)
chmod -R +x ./scripts/
# 代码根目录下执行,会安装根 package、projects 和 packages 内所有依赖
# 如果提示 isolate-vm 安装失败可以参考https://github.com/laverdet/isolated-vm?tab=readme-ov-file#requirements
pnpm i

View File

@@ -0,0 +1,470 @@
---
title: 'FastGPT 模型配置说明'
description: 'FastGPT 模型配置说明'
icon: 'api'
draft: false
toc: true
weight: 744
---
在 4.8.20 版本以前FastGPT 模型配置在 `config.json` 文件中声明,你可以在 https://github.com/labring/FastGPT/blob/main/projects/app/data/model.json 中找到旧版的配置文件示例。
从 4.8.20 版本开始,你可以直接在 FastGPT 页面中进行模型配置,并且系统内置了大量模型,无需从 0 开始配置。下面介绍模型配置的基本流程:
## 配置模型
### 1. 使用 OneAPI 对接模型提供商
可以使用 [OneAPI 接入教程](/docs/development/modelconfig/one-api) 来进行模型聚合,从而可以对接更多模型提供商。你需要先在各服务商申请好 API 接入 OneAPI 后,才能在 FastGPT 中使用这些模型。示例流程如下:
![alt text](/imgs/image-95.png)
除了各模型官方的服务外,还有一些第三方服务商提供模型接入服务,当然你也可以用 Ollama 等来部署本地模型,最终都需要接入 OneAPI下面是一些第三方服务商
{{% alert icon=" " context="info" %}}
- [SiliconCloud(硅基流动)](https://cloud.siliconflow.cn/i/TR9Ym0c4): 提供开源模型调用的平台。
- [Sealos AIProxy](https://hzh.sealos.run/?openapp=system-aiproxy): 提供国内各家模型代理,无需逐一申请 api。
{{% /alert %}}
在 OneAPI 配置好模型后,你就可以打开 FastGPT 页面,启用对应模型了。
### 2. 登录 root 用户
仅 root 用户可以进行模型配置。
### 3. 进入模型配置页面
登录 root 用户后,在`账号-模型提供商-模型配置`中,你可以看到所有内置的模型和自定义模型,以及哪些模型启用了。
![alt text](/image-90.png)
### 4. 配置介绍
{{% alert icon="🤖 " context="success" %}}
注意:
1. 目前语音识别模型和重排模型仅会生效一个,所以配置时候,只需要配置一个即可。
2. 系统至少需要一个语言模型和一个索引模型才能正常使用。
{{% /alert %}}
#### 核心配置
- 模型 ID接口请求时候Body 中`model`字段的值,全局唯一。
- 自定义请求地址/Key如果需要绕过`OneAPI`,可以设置自定义请求地址和 Token。一般情况下不需要如果 OneAPI 不支持某些模型,可以使用该特性。
#### 模型类型
1. 语言模型 - 进行文本对话,多模态模型支持图片识别。
2. 索引模型 - 对文本块进行索引,用于相关文本检索。
3. 重排模型 - 对检索结果进行重排,用于优化检索排名。
4. 语音合成 - 将文本转换为语音。
5. 语音识别 - 将语音转换为文本。
#### 启用模型
系统内置了目前主流厂商的模型,如果你不熟悉配置,直接点击`启用`即可,需要注意的是,`模型 ID`需要和 OneAPI 中渠道的`模型`一致。
| | |
| --- | --- |
| ![alt text](/imgs/image-91.png) | ![alt text](/imgs/image-92.png) |
#### 修改模型配置
点击模型右侧的齿轮即可进行模型配置,不同类型模型的配置有区别。
| | |
| --- | --- |
| ![alt text](/imgs/image-93.png) | ![alt text](/imgs/image-94.png) |
## 新增自定义模型
如果系统内置的模型无法满足你的需求,你可以添加自定义模型。自定义模型中,如果`模型 ID`与系统内置的模型 ID 一致,则会被认为是修改系统模型。
| | |
| --- | --- |
| ![alt text](/imgs/image-96.png) | ![alt text](/imgs/image-97.png) |
#### 通过配置文件配置
如果你觉得通过页面配置模型比较麻烦,你也可以通过配置文件来配置模型。或者希望快速将一个系统的配置,复制到另一个系统,也可以通过配置文件来实现。
| | |
| --- | --- |
| ![alt text](/imgs/image-98.png) | ![alt text](/imgs/image-99.png) |
**语言模型字段说明:**
```json
{
"model": "模型 ID",
"metadata": {
"isCustom": true, // 是否为自定义模型
"isActive": true, // 是否启用
"provider": "OpenAI", // 模型提供商主要用于分类展示目前已经内置提供商包括https://github.com/labring/FastGPT/blob/main/packages/global/core/ai/provider.ts, 可 pr 提供新的提供商,或直接填写 Other
"model": "gpt-4o-mini", // 模型ID(对应OneAPI中渠道的模型名)
"name": "gpt-4o-mini", // 模型别名
"maxContext": 125000, // 最大上下文
"maxResponse": 16000, // 最大回复
"quoteMaxToken": 120000, // 最大引用内容
"maxTemperature": 1.2, // 最大温度
"charsPointsPrice": 0, // n积分/1k token商业版
"censor": false, // 是否开启敏感校验(商业版)
"vision": true, // 是否支持图片输入
"datasetProcess": true, // 是否设置为文本理解模型QA务必保证至少有一个为true否则知识库会报错
"usedInClassify": true, // 是否用于问题分类务必保证至少有一个为true
"usedInExtractFields": true, // 是否用于内容提取务必保证至少有一个为true
"usedInToolCall": true, // 是否用于工具调用务必保证至少有一个为true
"toolChoice": true, // 是否支持工具选择(分类,内容提取,工具调用会用到。)
"functionCall": false, // 是否支持函数调用(分类,内容提取,工具调用会用到。会优先使用 toolChoice如果为false则使用 functionCall如果仍为 false则使用提示词模式
"customCQPrompt": "", // 自定义文本分类提示词(不支持工具和函数调用的模型
"customExtractPrompt": "", // 自定义内容提取提示词
"defaultSystemChatPrompt": "", // 对话默认携带的系统提示词
"defaultConfig": {}, // 请求API时挟带一些默认配置比如 GLM4 的 top_p
"fieldMap": {} // 字段映射o1 模型需要把 max_tokens 映射为 max_completion_tokens
}
}
```
**索引模型字段说明:**
```json
{
"model": "模型 ID",
"metadata": {
"isCustom": true, // 是否为自定义模型
"isActive": true, // 是否启用
"provider": "OpenAI", // 模型提供商
"model": "text-embedding-3-small", // 模型ID
"name": "text-embedding-3-small", // 模型别名
"charsPointsPrice": 0, // n积分/1k token
"defaultToken": 512, // 默认文本分割时候的 token
"maxToken": 3000 // 最大 token
}
}
```
**重排模型字段说明:**
```json
{
"model": "模型 ID",
"metadata": {
"isCustom": true, // 是否为自定义模型
"isActive": true, // 是否启用
"provider": "BAAI", // 模型提供商
"model": "bge-reranker-v2-m3", // 模型ID
"name": "ReRanker-Base", // 模型别名
"requestUrl": "", // 自定义请求地址
"requestAuth": "", // 自定义请求认证
"type": "rerank" // 模型类型
}
}
```
**语音合成模型字段说明:**
```json
{
"model": "模型 ID",
"metadata": {
"isActive": true, // 是否启用
"isCustom": true, // 是否为自定义模型
"type": "tts", // 模型类型
"provider": "FishAudio", // 模型提供商
"model": "fishaudio/fish-speech-1.5", // 模型ID
"name": "fish-speech-1.5", // 模型别名
"voices": [ // 音色
{
"label": "fish-alex", // 音色名称
"value": "fishaudio/fish-speech-1.5:alex", // 音色ID
},
{
"label": "fish-anna", // 音色名称
"value": "fishaudio/fish-speech-1.5:anna", // 音色ID
}
],
"charsPointsPrice": 0 // n积分/1k token
}
}
```
**语音识别模型字段说明:**
```json
{
"model": "whisper-1",
"metadata": {
"isActive": true, // 是否启用
"isCustom": true, // 是否为自定义模型
"provider": "OpenAI", // 模型提供商
"model": "whisper-1", // 模型ID
"name": "whisper-1", // 模型别名
"charsPointsPrice": 0, // n积分/1k token
"type": "stt" // 模型类型
}
}
```
## 模型测试
FastGPT 页面上提供了每类模型的简单测试,可以初步检查模型是否正常工作,会实际按模板发送一个请求。
![alt text](/imgs/image-105.png)
## 特殊接入示例
### ReRank 模型接入
由于 OneAPI 不支持 Rerank 模型所以需要单独配置。FastGPT 中,模型配置支持自定义请求地址,可以绕过 OneAPI直接向提供商发起请求可以利用这个特性来接入 Rerank 模型。
#### 使用硅基流动的在线模型
有免费的 `bge-reranker-v2-m3` 模型可以使用。
1. [点击注册硅基流动账号](https://cloud.siliconflow.cn/i/TR9Ym0c4)
2. 进入控制台,获取 API key: https://cloud.siliconflow.cn/account/ak
3. 打开 FastGPT 模型配置,新增一个`BAAI/bge-reranker-v2-m3`的重排模型(如果系统内置了,也可以直接变更,无需新增)。
![alt text](/imgs/image-101.png)
#### 私有部署模型
[点击查看部署 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/#通过配置文件配置)
## 旧版模型配置说明
配置好 OneAPI 后,需要在`config.json`文件中,手动的增加模型配置,并重启。
由于环境变量不利于配置复杂的内容FastGPT 采用了 ConfigMap 的形式挂载配置文件,你可以在 `projects/app/data/config.json` 看到默认的配置文件。可以参考 [docker-compose 快速部署](/docs/development/docker/) 来挂载配置文件。
**开发环境下**,你需要将示例配置文件 `config.json` 复制成 `config.local.json` 文件才会生效。
**Docker部署**,修改`config.json` 文件,需要重启容器。
下面配置文件示例中包含了系统参数和各个模型配置:
```json
{
"feConfigs": {
"lafEnv": "https://laf.dev" // laf环境。 https://laf.run (杭州阿里云) ,或者私有化的laf环境。如果使用 Laf openapi 功能,需要最新版的 laf 。
},
"systemEnv": {
"vectorMaxProcess": 15, // 向量处理线程数量
"qaMaxProcess": 15, // 问答拆分线程数量
"tokenWorkers": 50, // Token 计算线程保持数,会持续占用内存,不能设置太大。
"pgHNSWEfSearch": 100 // 向量搜索参数。越大搜索越精确但是速度越慢。设置为100有99%+精度。
},
"llmModels": [
{
"provider": "OpenAI", // 模型提供商主要用于分类展示目前已经内置提供商包括https://github.com/labring/FastGPT/blob/main/packages/global/core/ai/provider.ts, 可 pr 提供新的提供商,或直接填写 Other
"model": "gpt-4o-mini", // 模型名(对应OneAPI中渠道的模型名)
"name": "gpt-4o-mini", // 模型别名
"maxContext": 125000, // 最大上下文
"maxResponse": 16000, // 最大回复
"quoteMaxToken": 120000, // 最大引用内容
"maxTemperature": 1.2, // 最大温度
"charsPointsPrice": 0, // n积分/1k token商业版
"censor": false, // 是否开启敏感校验(商业版)
"vision": true, // 是否支持图片输入
"datasetProcess": true, // 是否设置为文本理解模型QA务必保证至少有一个为true否则知识库会报错
"usedInClassify": true, // 是否用于问题分类务必保证至少有一个为true
"usedInExtractFields": true, // 是否用于内容提取务必保证至少有一个为true
"usedInToolCall": true, // 是否用于工具调用务必保证至少有一个为true
"toolChoice": true, // 是否支持工具选择(分类,内容提取,工具调用会用到。)
"functionCall": false, // 是否支持函数调用(分类,内容提取,工具调用会用到。会优先使用 toolChoice如果为false则使用 functionCall如果仍为 false则使用提示词模式
"customCQPrompt": "", // 自定义文本分类提示词(不支持工具和函数调用的模型
"customExtractPrompt": "", // 自定义内容提取提示词
"defaultSystemChatPrompt": "", // 对话默认携带的系统提示词
"defaultConfig": {}, // 请求API时挟带一些默认配置比如 GLM4 的 top_p
"fieldMap": {} // 字段映射o1 模型需要把 max_tokens 映射为 max_completion_tokens
},
{
"provider": "OpenAI",
"model": "gpt-4o",
"name": "gpt-4o",
"maxContext": 125000,
"maxResponse": 4000,
"quoteMaxToken": 120000,
"maxTemperature": 1.2,
"charsPointsPrice": 0,
"censor": false,
"vision": true,
"datasetProcess": true,
"usedInClassify": true,
"usedInExtractFields": true,
"usedInToolCall": true,
"toolChoice": true,
"functionCall": false,
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"defaultConfig": {},
"fieldMap": {}
},
{
"provider": "OpenAI",
"model": "o1-mini",
"name": "o1-mini",
"maxContext": 125000,
"maxResponse": 65000,
"quoteMaxToken": 120000,
"maxTemperature": 1.2,
"charsPointsPrice": 0,
"censor": false,
"vision": false,
"datasetProcess": true,
"usedInClassify": true,
"usedInExtractFields": true,
"usedInToolCall": true,
"toolChoice": false,
"functionCall": false,
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"defaultConfig": {
"temperature": 1,
"max_tokens": null,
"stream": false
}
},
{
"provider": "OpenAI",
"model": "o1-preview",
"name": "o1-preview",
"maxContext": 125000,
"maxResponse": 32000,
"quoteMaxToken": 120000,
"maxTemperature": 1.2,
"charsPointsPrice": 0,
"censor": false,
"vision": false,
"datasetProcess": true,
"usedInClassify": true,
"usedInExtractFields": true,
"usedInToolCall": true,
"toolChoice": false,
"functionCall": false,
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"defaultConfig": {
"temperature": 1,
"max_tokens": null,
"stream": false
}
}
],
"vectorModels": [
{
"provider": "OpenAI",
"model": "text-embedding-3-small",
"name": "text-embedding-3-small",
"charsPointsPrice": 0,
"defaultToken": 512,
"maxToken": 3000,
"weight": 100
},
{
"provider": "OpenAI",
"model": "text-embedding-3-large",
"name": "text-embedding-3-large",
"charsPointsPrice": 0,
"defaultToken": 512,
"maxToken": 3000,
"weight": 100,
"defaultConfig": {
"dimensions": 1024
}
},
{
"provider": "OpenAI",
"model": "text-embedding-ada-002", // 模型名与OneAPI对应
"name": "Embedding-2", // 模型展示名
"charsPointsPrice": 0, // n积分/1k token
"defaultToken": 700, // 默认文本分割时候的 token
"maxToken": 3000, // 最大 token
"weight": 100, // 优先训练权重
"defaultConfig": {}, // 自定义额外参数。例如,如果希望使用 embedding3-large 的话,可以传入 dimensions:1024来返回1024维度的向量。目前必须小于1536维度
"dbConfig": {}, // 存储时的额外参数(非对称向量模型时候需要用到)
"queryConfig": {} // 参训时的额外参数
}
],
"reRankModels": [],
"audioSpeechModels": [
{
"provider": "OpenAI",
"model": "tts-1",
"name": "OpenAI TTS1",
"charsPointsPrice": 0,
"voices": [
{ "label": "Alloy", "value": "alloy", "bufferId": "openai-Alloy" },
{ "label": "Echo", "value": "echo", "bufferId": "openai-Echo" },
{ "label": "Fable", "value": "fable", "bufferId": "openai-Fable" },
{ "label": "Onyx", "value": "onyx", "bufferId": "openai-Onyx" },
{ "label": "Nova", "value": "nova", "bufferId": "openai-Nova" },
{ "label": "Shimmer", "value": "shimmer", "bufferId": "openai-Shimmer" }
]
}
],
"whisperModel": {
"provider": "OpenAI",
"model": "whisper-1",
"name": "Whisper1",
"charsPointsPrice": 0
}
}
```

View File

@@ -94,70 +94,16 @@ CHAT_API_KEY=sk-xxxxxx
![](/imgs/oneapi-demo1.png)
### 2. 修改 FastGPT 配置文件
### 2. 修改 FastGPT 模型配置
可以在 `/projects/app/src/data/config.json` 里找到配置文件(本地开发需要复制成 config.local.json,按下面内容修改配置文件,最新/更具体的配置说明,可查看[FastGPT 配置文件说明](/docs/development/configuration)
打开 FastGPT 模型配置,启动文心千帆模型,如果希望未内置,可以通过新增模型来配置
配置模型关键点在于`model` 需要与 OneAPI 渠道中的模型一致。
```json
{
"llmModels": [ // 语言模型配置
{
"model": "ERNIE-Bot", // 这里的模型需要对应 One API 的模型
"name": "文心一言", // 对外展示的名称
"avatar": "/imgs/model/openai.svg", // 模型的logo
"maxContext": 16000, // 最大上下文
"maxResponse": 4000, // 最大回复
"quoteMaxToken": 13000, // 最大引用内容
"maxTemperature": 1.2, // 最大温度
"charsPointsPrice": 0,
"censor": false,
"vision": false, // 是否支持图片输入
"datasetProcess": true, // 是否设置为知识库处理模型
"usedInClassify": true, // 是否用于问题分类
"usedInExtractFields": true, // 是否用于字段提取
"usedInToolCall": true, // 是否用于工具调用
"usedInQueryExtension": true, // 是否用于问题优化
"toolChoice": true, // 是否支持工具选择
"functionCall": false, // 是否支持函数调用
"customCQPrompt": "", // 自定义文本分类提示词(不支持工具和函数调用的模型
"customExtractPrompt": "", // 自定义内容提取提示词
"defaultSystemChatPrompt": "", // 对话默认携带的系统提示词
"defaultConfig":{} // 请求API时挟带一些默认配置比如 GLM4 的 top_p
}
],
"vectorModels": [ // 向量模型配置
{
"model": "text-embedding-ada-002",
"name": "Embedding-2",
"avatar": "/imgs/model/openai.svg",
"charsPointsPrice": 0,
"defaultToken": 700,
"maxToken": 3000,
"weight": 100
},
]
}
```
### 3. 重启 FastGPT
**Docker 版本**
```bash
docker-compose down
docker-compose up -d
```
**Sealos 版本**
直接找到 FastGPT 服务,点击重启即可。
![alt text](/imgs/image-103.png)
## 其他服务商接入参考
这章介绍一些提供商接入 OneAPI 的教程,配置后不要忘记修改 FastGPT 配置文件
这章介绍一些提供商接入 OneAPI 的教程,配置后不要忘记 FastGPT 模型配置中启用
### 阿里通义千问

View File

@@ -27,139 +27,13 @@ OPENAI_BASE_URL=https://api.siliconflow.cn/v1
CHAT_API_KEY=sk-xxxxxx
```
## 3. 修改 FastGPT 配置文件
## 3. 修改 FastGPT 模型配置
我们选取 SiliconCloud 中的模型作为 FastGPT 配置。这里配置了 `Qwen2.5 72b` 的纯语言和视觉模型;选择 `bge-m3` 作为向量模型;选择 `bge-reranker-v2-m3` 作为重排模型。选择 `fish-speech-1.5` 作为语音模型;选择 `SenseVoiceSmall` 作为语音输入模型
系统内置了几个硅基流动的模型进行体验,如果需要其他模型,可以手动添加
注意ReRank 模型仍需配置一次 Api Key
这里启动了 `Qwen2.5 72b` 的纯语言和视觉模型;选择 `bge-m3` 作为向量模型;选择 `bge-reranker-v2-m3` 作为重排模型。选择 `fish-speech-1.5` 作为语音模型;选择 `SenseVoiceSmall` 作为语音输入模型。
```json
{
"llmModels": [
{
"provider": "Other", // 模型提供商主要用于分类展示目前已经内置提供商包括https://github.com/labring/FastGPT/blob/main/packages/global/core/ai/provider.ts, 可 pr 提供新的提供商,或直接填写 Other
"model": "Qwen/Qwen2.5-72B-Instruct", // 模型名(对应OneAPI中渠道的模型名)
"name": "Qwen2.5-72B-Instruct", // 模型别名
"maxContext": 32000, // 最大上下文
"maxResponse": 4000, // 最大回复
"quoteMaxToken": 30000, // 最大引用内容
"maxTemperature": 1, // 最大温度
"charsPointsPrice": 0, // n积分/1k token商业版
"censor": false, // 是否开启敏感校验(商业版)
"vision": false, // 是否支持图片输入
"datasetProcess": true, // 是否设置为文本理解模型QA务必保证至少有一个为true否则知识库会报错
"usedInClassify": true, // 是否用于问题分类务必保证至少有一个为true
"usedInExtractFields": true, // 是否用于内容提取务必保证至少有一个为true
"usedInToolCall": true, // 是否用于工具调用务必保证至少有一个为true
"usedInQueryExtension": true, // 是否用于问题优化务必保证至少有一个为true
"toolChoice": true, // 是否支持工具选择(分类,内容提取,工具调用会用到。)
"functionCall": false, // 是否支持函数调用(分类,内容提取,工具调用会用到。会优先使用 toolChoice如果为false则使用 functionCall如果仍为 false则使用提示词模式
"customCQPrompt": "", // 自定义文本分类提示词(不支持工具和函数调用的模型
"customExtractPrompt": "", // 自定义内容提取提示词
"defaultSystemChatPrompt": "", // 对话默认携带的系统提示词
"defaultConfig": {}, // 请求API时挟带一些默认配置比如 GLM4 的 top_p
"fieldMap": {} // 字段映射o1 模型需要把 max_tokens 映射为 max_completion_tokens
},
{
"provider": "Other",
"model": "Qwen/Qwen2-VL-72B-Instruct",
"name": "Qwen2-VL-72B-Instruct",
"maxContext": 32000,
"maxResponse": 4000,
"quoteMaxToken": 30000,
"maxTemperature": 1,
"charsPointsPrice": 0,
"censor": false,
"vision": true,
"datasetProcess": false,
"usedInClassify": false,
"usedInExtractFields": false,
"usedInToolCall": false,
"usedInQueryExtension": false,
"toolChoice": false,
"functionCall": false,
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"defaultConfig": {}
}
],
"vectorModels": [
{
"provider": "Other",
"model": "Pro/BAAI/bge-m3",
"name": "Pro/BAAI/bge-m3",
"charsPointsPrice": 0,
"defaultToken": 512,
"maxToken": 5000,
"weight": 100
}
],
"reRankModels": [
{
"model": "BAAI/bge-reranker-v2-m3", // 这里的model需要对应 siliconflow 的模型名
"name": "BAAI/bge-reranker-v2-m3",
"requestUrl": "https://api.siliconflow.cn/v1/rerank",
"requestAuth": "siliconflow 上申请的 key"
}
],
"audioSpeechModels": [
{
"model": "fishaudio/fish-speech-1.5",
"name": "fish-speech-1.5",
"voices": [
{
"label": "fish-alex",
"value": "fishaudio/fish-speech-1.5:alex",
"bufferId": "fish-alex"
},
{
"label": "fish-anna",
"value": "fishaudio/fish-speech-1.5:anna",
"bufferId": "fish-anna"
},
{
"label": "fish-bella",
"value": "fishaudio/fish-speech-1.5:bella",
"bufferId": "fish-bella"
},
{
"label": "fish-benjamin",
"value": "fishaudio/fish-speech-1.5:benjamin",
"bufferId": "fish-benjamin"
},
{
"label": "fish-charles",
"value": "fishaudio/fish-speech-1.5:charles",
"bufferId": "fish-charles"
},
{
"label": "fish-claire",
"value": "fishaudio/fish-speech-1.5:claire",
"bufferId": "fish-claire"
},
{
"label": "fish-david",
"value": "fishaudio/fish-speech-1.5:david",
"bufferId": "fish-david"
},
{
"label": "fish-diana",
"value": "fishaudio/fish-speech-1.5:diana",
"bufferId": "fish-diana"
}
]
}
],
"whisperModel": {
"model": "FunAudioLLM/SenseVoiceSmall",
"name": "SenseVoiceSmall",
"charsPointsPrice": 0
}
}
```
## 4. 重启 FastGPT
![alt text](/imgs/image-104.png)
## 5. 体验测试

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

@@ -735,7 +735,7 @@ data 为集合的 ID。
**4.8.19+**
```bash
curl --location --request POST 'http://localhost:3000/api/core/dataset/collection/listv2' \
curl --location --request POST 'http://localhost:3000/api/core/dataset/collection/listV2' \
--header 'Authorization: Bearer {{authorization}}' \
--header 'Content-Type: application/json' \
--data-raw '{

View File

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

View File

@@ -34,7 +34,7 @@ FastGPT 使用了 one-api 项目来管理模型池,其可以兼容 OpenAI 、A
<a href="https://bja.sealos.run/?openapp=system-template%3FtemplateName%3Dfastgpt" rel="external" target="_blank"><img src="https://raw.githubusercontent.com/labring-actions/templates/main/Deploy-on-Sealos.svg" alt="Deploy on Sealos"/></a>
### 开始部署
### 1. 开始部署
由于需要部署数据库,部署完后需要等待 2~4 分钟才能正常访问。默认用了最低配置,首次访问时会有些慢。
@@ -52,27 +52,19 @@ FastGPT 使用了 one-api 项目来管理模型池,其可以兼容 OpenAI 、A
![](/imgs/sealos2.png)
### 登录
### 2. 登录
用户名:`root`
密码是刚刚一键部署时设置的`root_password`
### 修改配置文件和环境变量
### 3. 配置模型
在 Sealos 中,你可以打开`应用管理`App Launchpad看到部署的 FastGPT可以打开`数据库`Database看到对应的数据库。
### 4. 配置模型
`应用管理`中,选中 FastGPT点击变更可以看到对应的环境变量和配置文件
务必先配置至少一组模型,否则系统无法正常使用
![](/imgs/fastgptonsealos1.png)
{{% alert icon="🤖 " context="success" %}}
在 Sealos 上FastGPT 一共运行了 1 个服务和 2 个数据库,如暂停和删除请注意数据库一同操作。(你可以白天启动,晚上暂停它们,省钱大法)
{{% /alert %}}
### 更新
点击变更或重启会自动拉取镜像更新,请确保镜像`tag`正确。建议不要使用`latest`,改成固定版本号。
[点击查看模型配置教程](/docs/development/modelConfig/intro/)
## 收费
@@ -88,7 +80,20 @@ FastGPT 商业版共包含了2个应用fastgpt, fastgpt-plus和2个数据
点击右侧的详情,可以查看对应应用的详细信息。
### 修改配置文件和环境变量
在 Sealos 中,你可以打开`应用管理`App Launchpad看到部署的 FastGPT可以打开`数据库`Database看到对应的数据库。
`应用管理`中,选中 FastGPT点击变更可以看到对应的环境变量和配置文件。
![](/imgs/fastgptonsealos1.png)
{{% alert icon="🤖 " context="success" %}}
在 Sealos 上FastGPT 一共运行了 1 个服务和 2 个数据库,如暂停和删除请注意数据库一同操作。(你可以白天启动,晚上暂停它们,省钱大法)
{{% /alert %}}
### 如何更新/升级 FastGPT
[升级脚本文档](https://doc.tryfastgpt.ai/docs/development/upgrading/)先看下文档,看下需要升级哪个版本。注意,不要跨版本升级!!!!!
例如目前是4.5 版本要升级到4.5.1就先把镜像版本改成v4.5.1,执行一下升级脚本,等待完成后再继续升级。如果目标版本不需要执行初始化,则可以跳过。
@@ -148,8 +153,6 @@ SYSTEM_FAVICON 可以是一个网络地址
![](/imgs/onsealos8.png)
### 管理后台(已合并到plus)
### 商业版镜像配置文件
```

View File

@@ -31,7 +31,6 @@ weight: 813
"usedInClassify": true,
"usedInExtractFields": true,
"usedInToolCall": true,
"usedInQueryExtension": true,
"toolChoice": false,
"functionCall": false,
"customCQPrompt": "",
@@ -56,7 +55,6 @@ weight: 813
"usedInClassify": true,
"usedInExtractFields": true,
"usedInToolCall": true,
"usedInQueryExtension": true,
"toolChoice": false,
"functionCall": false,
"customCQPrompt": "",

View File

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

View File

@@ -1,17 +1,46 @@
---
title: 'V4.8.19(进行中)'
title: 'V4.8.19(包含升级脚本)'
description: 'FastGPT V4.8.19 更新说明'
icon: 'upgrade'
draft: false
toc: true
weight: 806
weight: 805
---
## 更新指南
### 1. 更新镜像:
- 更新 fastgpt 镜像 tag: v4.8.19-beta
- 更新 fastgpt-pro 商业版镜像 tag: v4.8.19-beta
- Sandbox 镜像无需更新
### 2. 运行升级脚本
从任意终端,发起 1 个 HTTP 请求。其中 {{rootkey}} 替换成环境变量里的 `rootkey`{{host}} 替换成**FastGPT 域名**。
```bash
curl --location --request POST 'https://{{host}}/api/admin/initv4819' \
--header 'rootkey: {{rootkey}}' \
--header 'Content-Type: application/json'
```
迁移用户表的头像到成员表中。
## 完整更新内容
1. 新增 - 工作流知识库检索支持按知识库权限进行过滤。
2. 优化 - 成员列表分页加载
3. 优化 - 统一分页加载代码
4. 修复 - 语雀文件库导入时,嵌套文件内容无法展开的问题
5. 修复 - 工作流编排中LLM 参数无法关闭问题。
2. 新增 - 飞书/语雀知识库查看原文
3. 新增 - 流程等待插件,可以等待 n 毫秒后继续执行流程
4. 新增 - 飞书机器人接入,支持配置私有化飞书地址
5. 优化 - 成员列表分页加载。
6. 优化 - 统一分页加载代码。
7. 优化 - 对话页面加载时,可配置是否为独立页面。
8. 优化 - 成员头像迁移,移动到成员表。
9. 修复 - 语雀文件库导入时,嵌套文件内容无法展开的问题。
10. 修复 - 工作流编排中LLM 参数无法关闭问题。
11. 修复 - 工作流编排中,代码运行节点还原模板问题。
12. 修复 - HTTP 接口适配对象字符串解析。
13. 修复 - 通过 API 上传文件localFile接口图片过期标记未清除。
14. 修复 - 工作流导入编排时number input 类型无法覆盖。
15. 修复 - 部分模型提供商 logo 无法正常显示。

View File

@@ -0,0 +1,50 @@
---
title: 'V4.8.20(包含升级脚本)'
description: 'FastGPT V4.8.20 更新说明'
icon: 'upgrade'
draft: false
toc: true
weight: 804
---
## 更新指南
### 1. 做好数据库备份
### 2. 更新环境变量
如果有很早版本用户,配置了`ONEAPI_URL`的,需要统一改成`OPENAI_BASE_URL`
### 3. 更新镜像:
- 更新 fastgpt 镜像 tag: v4.8.20-fix2
- 更新 fastgpt-pro 商业版镜像 tag: v4.8.20-fix2
- Sandbox 镜像无需更新
### 4. 运行升级脚本
从任意终端,发起 1 个 HTTP 请求。其中 {{rootkey}} 替换成环境变量里的 `rootkey`{{host}} 替换成**FastGPT 域名**。
```bash
curl --location --request POST 'https://{{host}}/api/admin/initv4820' \
--header 'rootkey: {{rootkey}}' \
--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. 修复 - 工作流递归执行,部分条件下无法正常运行。

View File

@@ -0,0 +1,39 @@
---
title: 'V4.8.21'
description: 'FastGPT V4.8.21 更新说明'
icon: 'upgrade'
draft: false
toc: true
weight: 803
---
## 更新指南
### 1. 做好数据库备份
### 2. 更新镜像:
- 更新 fastgpt 镜像 tag: v4.8.21-fix
- 更新 fastgpt-pro 商业版镜像 tag: v4.8.21-fix
- 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

@@ -0,0 +1,23 @@
---
title: 'V4.8.22(进行中)'
description: 'FastGPT V4.8.22 更新说明'
icon: 'upgrade'
draft: false
toc: true
weight: 802
---
## 完整更新内容
1. 新增 - AI 对话节点解析 <think></think> 标签内容,便于各类模型进行思考链输出。
2. 优化 - 模型未配置时提示,减少冲突提示。
3. 优化 - 使用记录代码。
4. 修复 - 思考内容未进入到输出 Tokens.
5. 修复 - 思考链流输出时,有时与正文顺序偏差。
6. 修复 - API 调用工作流,如果传递的图片不支持 Head 检测时,图片会被过滤。已增加该类错误检测,避免被错误过滤。
7. 修复 - 模板市场部分模板错误。
8. 修复 - 免登录窗口无法正常判断语言识别是否开启。
9. 修复 - 对话日志导出,未兼容 sub path。
10. 修复 - list 接口在联查 member 时,存在空指针可能性。
11. 修复 - 工作流基础节点无法升级。

View File

@@ -21,6 +21,19 @@ weight: 908
定时执行会在应用发布后生效,会在后台生效。
## V4.8.18-FIX2中提到“ 1. 修复 HTTP 节点, {{}} 格式引用变量兼容问题。建议尽快替换 / 模式取变量, {{}} 语法已弃用。”替换{{}}引用格式是仅仅只有在http节点还是所有节点的都会有影响
只有 http 节点用到这个语法。
## 工作流类型的应用在运行预览可以正常提问返回,但是发布免登录窗口之后有问题。
一般是没正确发布,在工作流右上角点击【保存并发布】。
## 如何解决猜你想问使用中文回答显示
注意需要更新到V4.8.17及以上,把猜你想问的提示词改成中文。
![](/imgs/quizApp2.png)
## AI对话回答要求中的Markdown语法取消
修改知识库默认提示词, 默认用的是标准模板提示词,会要求按 Markdown 输出,可以去除该要求:

View File

@@ -24,6 +24,17 @@ xlsx等都可以上传的不止支持CSV。
统一按gpt3.5标准。
## 误删除重排模型后重排模型怎么加入到fastgpt
![](/imgs/dataset3.png)
config.json文件里面配置后就可以勾选重排模型
## 线上平台上创建了应用和知识库,到期之后如果短期内不续费,数据是否会被清理。
免费版是三十天不登录后清空知识库,应用不会动。其他付费套餐到期后自动切免费版。
![](/imgs/dataset4.png)
## 基于知识库的查询但是问题相关的答案过多。ai回答到一半就不继续回答。
FastGPT回复长度计算公式:

View File

@@ -8,4 +8,8 @@ weight: 918
## oneapi 官网是哪个
只有开源的 README没官网GitHub: https://github.com/songquanpeng/one-api
只有开源的 README没官网GitHub: https://github.com/songquanpeng/one-api
## 想做多用户
开源版未支持多用户,仅商业版支持。

View File

@@ -22,10 +22,11 @@ FastGPT v4.8.16 版本开始,商业版用户支持飞书知识库导入,用
## 2. 配置应用权限
创建应用后,进入应用可以配置相关权限,这里需要增加个权限:
创建应用后,进入应用可以配置相关权限,这里需要增加**3个权限**
1. 获取云空间文件夹下的云文档清单
2. 查看新版文档
3. 查看、评论、编辑和管理云空间中所有文件
![alt text](/imgs/image-41.png)

View File

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

View File

@@ -1,6 +1,6 @@
---
title: "循环执行"
description: "FastGPT 循环运行节点介绍和使用"
title: "批量运行"
description: "FastGPT 批量运行节点介绍和使用"
icon: "input"
draft: false
toc: true
@@ -9,15 +9,15 @@ weight: 260
## 节点概述
【**循环运行**】节点是 FastGPT V4.8.11 版本新增的一个重要功能模块。它允许工作流对数组类型的输入数据进行迭代处理,每次处理数组中的一个元素,并自动执行后续节点,直到完成整个数组的处理。
【**批量运行**】节点是 FastGPT V4.8.11 版本新增的一个重要功能模块。它允许工作流对数组类型的输入数据进行迭代处理,每次处理数组中的一个元素,并自动执行后续节点,直到完成整个数组的处理。
这个节点的设计灵感来自编程语言中的循环结构,但以可视化的方式呈现。
![循环运行节点](/imgs/fastgpt-loop-node.png)
![批量运行节点](/imgs/fastgpt-loop-node.png)
> 在程序中,节点可以理解为一个个 Function 或者接口。可以理解为它就是一个**步骤**。将多个节点一个个拼接起来,即可一步步的去实现最终的 AI 输出。
【**循环运行**】节点本质上也是一个 Function它的主要职责是自动化地重复执行特定的工作流程。
【**批量运行**】节点本质上也是一个 Function它的主要职责是自动化地重复执行特定的工作流程。
## 核心特性
@@ -41,9 +41,9 @@ weight: 260
## 应用场景
【**循环运行**】节点的主要作用是通过自动化的方式扩展工作流的处理能力,使 FastGPT 能够更好地处理批量任务和复杂的数据处理流程。特别是在处理大规模数据或需要多轮迭代的场景下,循环运行节点能显著提升工作流的效率和自动化程度。
【**批量运行**】节点的主要作用是通过自动化的方式扩展工作流的处理能力,使 FastGPT 能够更好地处理批量任务和复杂的数据处理流程。特别是在处理大规模数据或需要多轮迭代的场景下,批量运行节点能显著提升工作流的效率和自动化程度。
【**循环运行**】节点特别适合以下场景:
【**批量运行**】节点特别适合以下场景:
1. **批量数据处理**
- 批量翻译文本
@@ -64,7 +64,7 @@ weight: 260
### 输入参数设置
【**循环运行**】节点需要配置两个核心输入参数:
【**批量运行**】节点需要配置两个核心输入参数:
1. **数组 (必填)**:接收一个数组类型的输入,可以是:
- 字符串数组 (`Array<string>`)
@@ -95,7 +95,7 @@ weight: 260
### 批量处理数组
假设我们有一个包含多个文本的数组,需要对每个文本进行 AI 处理。这是循环运行节点最基础也最常见的应用场景。
假设我们有一个包含多个文本的数组,需要对每个文本进行 AI 处理。这是批量运行节点最基础也最常见的应用场景。
#### 实现步骤
@@ -114,9 +114,9 @@ weight: 260
return { textArray: texts };
```
2. 配置循环运行节点
2. 配置批量运行节点
![配置循环运行节点](/imgs/fastgpt-loop-node-example-2.png)
![配置批量运行节点](/imgs/fastgpt-loop-node-example-2.png)
- 数组输入:选择上一步代码运行节点的输出变量 `textArray`。
- 循环体内添加一个【AI 对话】节点,用于处理每个文本。这里我们输入的 prompt 为:`请将这段文本翻译成英文`。
@@ -128,7 +128,7 @@ weight: 260
![运行流程](/imgs/fastgpt-loop-node-example-3.png)
1. 【代码运行】节点执行,生成测试数组
2. 【循环运行】节点接收数组,开始遍历
2. 【批量运行】节点接收数组,开始遍历
3. 对每个数组元素:
- 【AI 对话】节点处理当前元素
- 【指定回复】节点输出翻译后的文本
@@ -144,7 +144,7 @@ weight: 260
- 需要维护上下文的连贯性
- 翻译质量需要多轮优化
【**循环运行**】节点可以很好地解决这些问题。
【**批量运行**】节点可以很好地解决这些问题。
#### 实现步骤
@@ -281,9 +281,9 @@ weight: 260
这里我们用到了 [Jina AI 开源的一个强大的正则表达式](https://x.com/JinaAI_/status/1823756993108304135),它能利用所有可能的边界线索和启发式方法来精确切分文本。
2. 配置循环运行节点
2. 配置批量运行节点
![配置循环运行节点](/imgs/fastgpt-loop-node-example-5.png)
![配置批量运行节点](/imgs/fastgpt-loop-node-example-5.png)
- 数组输入:选择上一步代码运行节点的输出变量 `chunks`。
- 循环体内添加一个【代码运行】节点,对源文本进行格式化。

View File

@@ -212,7 +212,7 @@ export default async function (ctx: FunctionContext): Promise<IResponse>{
![](/imgs/translate13.png)
## 循环执
## 批量运
长文反思翻译比较关键的一个部分,就是对多个文本块进行循环反思翻译

View File

@@ -91,9 +91,9 @@ weight: 604
这个过程不仅提高了效率,还最大限度地减少了人为错误的可能性。
## 循环执
## 批量运
为了处理整个长字幕文件,我们需要一个循环执行机制。这是通过一个简单但有效的判断模块实现的:
为了处理整个长字幕文件,我们需要一个批量运行机制。这是通过一个简单但有效的判断模块实现的:
1. 检查当前翻译的文本块是否为最后一个。
2. 如果不是,则将工作流重定向到格式化原文本块节点。

View File

@@ -20,7 +20,7 @@ weight: 502
![](/imgs/fastgpt-api1.jpg)
{{% alert icon="🍅" context="success" %}}
Tips: 安全起见,你可以设置一个额度或者过期时间,放置 key 被滥用。
Tips: 安全起见,你可以设置一个额度或者过期时间,防止 key 被滥用。
{{% /alert %}}

View File

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

View File

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

View File

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

View File

@@ -23,7 +23,6 @@ data:
"usedInClassify": true,
"usedInExtractFields": true,
"usedInToolCall": true,
"usedInQueryExtension": true,
"toolChoice": true,
"functionCall": false,
"customCQPrompt": "",
@@ -45,7 +44,6 @@ data:
"usedInClassify": true,
"usedInExtractFields": true,
"usedInToolCall": true,
"usedInQueryExtension": true,
"toolChoice": true,
"functionCall": false,
"customCQPrompt": "",
@@ -67,7 +65,6 @@ data:
"usedInClassify": true,
"usedInExtractFields": true,
"usedInToolCall": true,
"usedInQueryExtension": true,
"toolChoice": true,
"functionCall": false,
"customCQPrompt": "",
@@ -89,7 +86,6 @@ data:
"usedInClassify": false,
"usedInExtractFields": false,
"usedInToolCall": false,
"usedInQueryExtension": false,
"toolChoice": true,
"functionCall": false,
"customCQPrompt": "",

View File

@@ -7,7 +7,7 @@
"format-code": "prettier --config \"./.prettierrc.js\" --write \"./**/src/**/*.{ts,tsx,scss}\"",
"format-doc": "zhlint --dir ./docSite *.md --fix",
"gen:theme-typings": "chakra-cli tokens packages/web/styles/theme.ts --out node_modules/.pnpm/node_modules/@chakra-ui/styled-system/dist/theming.types.d.ts",
"postinstall": "sh ./scripts/postinstall.sh",
"postinstall": "pnpm gen:theme-typings",
"initIcon": "node ./scripts/icon/init.js",
"previewIcon": "node ./scripts/icon/index.js",
"api:gen": "tsc ./scripts/openapi/index.ts && node ./scripts/openapi/index.js && npx @redocly/cli build-docs ./scripts/openapi/openapi.json -o ./projects/app/public/openapi/index.html",

View File

@@ -2,12 +2,22 @@ import { ErrType } from '../errorCode';
import { i18nT } from '../../../../web/i18n/utils';
/* team: 503000 */
export enum UserErrEnum {
notUser = 'notUser',
userExist = 'userExist',
unAuthRole = 'unAuthRole',
account_psw_error = 'account_psw_error',
balanceNotEnough = 'balanceNotEnough',
unAuthSso = 'unAuthSso'
}
const errList = [
{
statusText: UserErrEnum.notUser,
message: i18nT('common:code_error.account_not_found')
},
{
statusText: UserErrEnum.userExist,
message: i18nT('common:code_error.account_exist')
},
{
statusText: UserErrEnum.account_psw_error,
message: i18nT('common:code_error.account_error')

View File

@@ -16,8 +16,8 @@ export const bucketNameMap = {
}
};
export const ReadFileBaseUrl = `${process.env.FE_DOMAIN || ''}${process.env.NEXT_PUBLIC_BASE_URL || ''}/api/common/file/read`;
export const ReadFileBaseUrl = `${process.env.FILE_DOMAIN || 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 =
'.jpg, .jpeg, .png, .gif, .bmp, .webp, .svg, .tiff, .tif, .ico, .heic, .heif, .avif';
'.jpg, .jpeg, .png, .gif, .bmp, .webp, .svg, .tiff, .tif, .ico, .heic, .heif, .avif, .raw, .cr2, .nef, .arw, .dng, .psd, .ai, .eps, .emf, .wmf, .jfif, .exif, .pgm, .ppm, .pbm, .jp2, .j2k, .jpf, .jpx, .jpm, .mj2, .xbm, .pcx';

View File

@@ -1,5 +1,5 @@
import { detect } from 'jschardet';
import { documentFileType, imageFileType } from './constants';
import { documentFileType } from './constants';
import { ChatFileTypeEnum } from '../../core/chat/constants';
import { UserChatItemValueItemType } from '../../core/chat/type';
import * as fs from 'fs';
@@ -25,6 +25,7 @@ export const detectFileEncodingByPath = async (path: string) => {
const fd = await fs.promises.open(path, 'r');
try {
// Read file head
// @ts-ignore
const { bytesRead } = await fd.read(buffer, 0, MAX_BYTES, 0);
const actualBuffer = buffer.slice(0, bytesRead);
@@ -37,40 +38,49 @@ export const detectFileEncodingByPath = async (path: string) => {
// Url => user upload file type
export const parseUrlToFileType = (url: string): UserChatItemValueItemType['file'] | undefined => {
if (typeof url !== 'string') return;
const parseUrl = new URL(url, 'https://locaohost:3000');
const filename = (() => {
// Check base64 image
if (url.startsWith('data:image/')) {
const mime = url.split(',')[0].split(':')[1].split(';')[0];
return `image.${mime.split('/')[1]}`;
}
// Old version file url: https://xxx.com/file/read?filename=xxx.pdf
const filenameQuery = parseUrl.searchParams.get('filename');
if (filenameQuery) return filenameQuery;
// Handle base64 image
if (url.startsWith('data:')) {
const matches = url.match(/^data:([^;]+);base64,/);
if (!matches) return;
// Common file https://xxx.com/xxx.pdf?xxxx=xxx
const pathname = parseUrl.pathname;
if (pathname) return pathname.split('/').pop();
})();
const mimeType = matches[1].toLowerCase();
if (!mimeType.startsWith('image/')) return;
if (!filename) return;
const extension = filename.split('.').pop()?.toLowerCase() || '';
if (!extension) return;
if (documentFileType.includes(extension)) {
const extension = mimeType.split('/')[1];
return {
type: ChatFileTypeEnum.file,
name: filename,
type: ChatFileTypeEnum.image,
name: `image.${extension}`,
url
};
}
if (imageFileType.includes(extension)) {
try {
const parseUrl = new URL(url, 'https://localhost:3000');
// Get filename from URL
const filename = parseUrl.searchParams.get('filename') || parseUrl.pathname.split('/').pop();
const extension = filename?.split('.').pop()?.toLowerCase() || '';
// If it's a document type, return as file, otherwise treat as image
if (extension && documentFileType.includes(extension)) {
return {
type: ChatFileTypeEnum.file,
name: filename || 'null',
url
};
}
// Default to image type for non-document files
return {
type: ChatFileTypeEnum.image,
name: filename,
name: filename || 'null.png',
url
};
} catch (error) {
return {
type: ChatFileTypeEnum.image,
name: 'invalid.png',
url
};
}

View File

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

View File

@@ -3,7 +3,7 @@ import type {
ChatModelItemType,
FunctionModelItemType,
LLMModelItemType,
VectorModelItemType,
EmbeddingModelItemType,
AudioSpeechModels,
STTModelType,
ReRankModelItemType
@@ -31,11 +31,13 @@ export type FastGPTConfigFileType = {
feConfigs: FastGPTFeConfigsType;
systemEnv: SystemEnvType;
subPlans?: SubPlanType;
llmModels: ChatModelItemType[];
vectorModels: VectorModelItemType[];
reRankModels: ReRankModelItemType[];
audioSpeechModels: AudioSpeechModelType[];
whisperModel: STTModelType;
// Abandon
llmModels?: ChatModelItemType[];
vectorModels?: EmbeddingModelItemType[];
reRankModels?: ReRankModelItemType[];
audioSpeechModels?: TTSModelType[];
whisperModel?: STTModelType;
};
export type FastGPTFeConfigsType = {

View File

@@ -15,15 +15,13 @@ export enum LLMModelTypeEnum {
all = 'all',
classify = 'classify',
extractFields = 'extractFields',
toolCall = 'toolCall',
queryExtension = 'queryExtension'
toolCall = 'toolCall'
}
export const llmModelTypeFilterMap = {
[LLMModelTypeEnum.all]: 'model',
[LLMModelTypeEnum.classify]: 'usedInClassify',
[LLMModelTypeEnum.extractFields]: 'usedInExtractFields',
[LLMModelTypeEnum.toolCall]: 'usedInToolCall',
[LLMModelTypeEnum.queryExtension]: 'usedInQueryExtension'
[LLMModelTypeEnum.toolCall]: 'usedInToolCall'
};
export enum EmbeddingTypeEnm {

View File

@@ -1,3 +1,4 @@
import { ModelTypeEnum } from './model';
import type { ModelProviderIdType } from './provider';
type PriceType = {
@@ -7,68 +8,80 @@ type PriceType = {
inputPrice?: number; // 1k tokens=n points
outputPrice?: number; // 1k tokens=n points
};
export type LLMModelItemType = PriceType & {
type BaseModelItemType = {
provider: ModelProviderIdType;
model: string;
name: string;
avatar?: string; // model icon, from provider
maxContext: number;
maxResponse: number;
quoteMaxToken: number;
maxTemperature: number;
censor?: boolean;
vision?: boolean;
isActive?: boolean;
isCustom?: boolean;
isDefault?: boolean;
// diff function model
datasetProcess?: boolean; // dataset
usedInClassify?: boolean; // classify
usedInExtractFields?: boolean; // extract fields
usedInToolCall?: boolean; // tool call
usedInQueryExtension?: boolean; // query extension
functionCall: boolean;
toolChoice: boolean;
customCQPrompt: string;
customExtractPrompt: string;
defaultSystemChatPrompt?: string;
defaultConfig?: Record<string, any>;
fieldMap?: Record<string, string>;
// If has requestUrl, it will request the model directly
requestUrl?: string;
requestAuth?: string;
};
export type VectorModelItemType = PriceType & {
provider: ModelProviderIdType;
model: string; // model name
name: string; // show name
avatar?: string;
defaultToken: number; // split text default token
maxToken: number; // model max token
weight: number; // training weight
hidden?: boolean; // Disallow creation
defaultConfig?: Record<string, any>; // post request config
dbConfig?: Record<string, any>; // Custom parameters for storage
queryConfig?: Record<string, any>; // Custom parameters for query
};
export type LLMModelItemType = PriceType &
BaseModelItemType & {
type: ModelTypeEnum.llm;
// Model params
maxContext: number;
maxResponse: number;
quoteMaxToken: number;
maxTemperature?: number;
export type ReRankModelItemType = PriceType & {
provider: ModelProviderIdType;
model: string;
name: string;
requestUrl: string;
requestAuth: string;
};
showTopP?: boolean;
responseFormatList?: string[];
showStopSign?: boolean;
export type AudioSpeechModelType = PriceType & {
provider: ModelProviderIdType;
model: string;
name: string;
voices: { label: string; value: string; bufferId: string }[];
};
censor?: boolean;
vision?: boolean;
reasoning?: boolean;
export type STTModelType = PriceType & {
provider: ModelProviderIdType;
model: string;
name: string;
};
// diff function model
datasetProcess?: boolean; // dataset
usedInClassify?: boolean; // classify
usedInExtractFields?: boolean; // extract fields
usedInToolCall?: boolean; // tool call
functionCall: boolean;
toolChoice: boolean;
customCQPrompt: string;
customExtractPrompt: string;
defaultSystemChatPrompt?: string;
defaultConfig?: Record<string, any>;
fieldMap?: Record<string, string>;
};
export type EmbeddingModelItemType = PriceType &
BaseModelItemType & {
type: ModelTypeEnum.embedding;
defaultToken: number; // split text default token
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
};
export type ReRankModelItemType = PriceType &
BaseModelItemType & {
type: ModelTypeEnum.rerank;
};
export type TTSModelType = PriceType &
BaseModelItemType & {
type: ModelTypeEnum.tts;
voices: { label: string; value: string }[];
};
export type STTModelType = PriceType &
BaseModelItemType & {
type: ModelTypeEnum.stt;
};

View File

@@ -1,9 +1,18 @@
import { i18nT } from '../../../web/i18n/utils';
import type { LLMModelItemType, STTModelType, VectorModelItemType } from './model.d';
import type { LLMModelItemType, STTModelType, EmbeddingModelItemType } from './model.d';
import { getModelProvider, ModelProviderIdType } from './provider';
export enum ModelTypeEnum {
llm = 'llm',
embedding = 'embedding',
tts = 'tts',
stt = 'stt',
rerank = 'rerank'
}
export const defaultQAModels: LLMModelItemType[] = [
{
type: ModelTypeEnum.llm,
provider: 'OpenAI',
model: 'gpt-4o-mini',
name: 'gpt-4o-mini',
@@ -24,8 +33,9 @@ export const defaultQAModels: LLMModelItemType[] = [
}
];
export const defaultVectorModels: VectorModelItemType[] = [
export const defaultVectorModels: EmbeddingModelItemType[] = [
{
type: ModelTypeEnum.embedding,
provider: 'OpenAI',
model: 'text-embedding-3-small',
name: 'Embedding-2',
@@ -36,18 +46,24 @@ export const defaultVectorModels: VectorModelItemType[] = [
}
];
export const defaultWhisperModel: STTModelType = {
provider: 'OpenAI',
model: 'whisper-1',
name: 'whisper-1',
charsPointsPrice: 0
};
export const defaultSTTModels: STTModelType[] = [
{
type: ModelTypeEnum.stt,
provider: 'OpenAI',
model: 'whisper-1',
name: 'whisper-1',
charsPointsPrice: 0
}
];
export const getModelFromList = (
modelList: { provider: ModelProviderIdType; name: string; model: string }[],
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,
@@ -55,15 +71,10 @@ export const getModelFromList = (
};
};
export enum ModelTypeEnum {
chat = 'chat',
embedding = 'embedding',
tts = 'tts',
stt = 'stt'
}
export const modelTypeList = [
{ label: i18nT('common:model.type.chat'), value: ModelTypeEnum.chat },
{ label: i18nT('common:model.type.chat'), value: ModelTypeEnum.llm },
{ label: i18nT('common:model.type.embedding'), value: ModelTypeEnum.embedding },
{ label: i18nT('common:model.type.tts'), value: ModelTypeEnum.tts },
{ label: i18nT('common:model.type.stt'), value: ModelTypeEnum.stt }
{ label: i18nT('common:model.type.stt'), value: ModelTypeEnum.stt },
{ label: i18nT('common:model.type.reRank'), value: ModelTypeEnum.rerank }
];

View File

@@ -7,11 +7,12 @@ export type ModelProviderIdType =
| 'Meta'
| 'MistralAI'
| 'Groq'
| 'Grok'
| 'AliCloud'
| 'Qwen'
| 'Doubao'
| 'ChatGLM'
| 'DeepSeek'
| 'ChatGLM'
| 'Ernie'
| 'Moonshot'
| 'MiniMax'
@@ -20,14 +21,18 @@ export type ModelProviderIdType =
| 'Baichuan'
| 'StepFun'
| 'Yi'
| 'Siliconflow'
| 'PPIO'
| 'Ollama'
| 'BAAI'
| 'FishAudio'
| 'Intern'
| 'Moka'
| 'Other';
export type ModelProviderType = {
id: ModelProviderIdType;
name: string;
name: any;
avatar: string;
};
@@ -57,6 +62,11 @@ export const ModelProviderList: ModelProviderType[] = [
name: 'MistralAI',
avatar: 'model/mistral'
},
{
id: 'Grok',
name: 'Grok',
avatar: 'model/grok'
},
{
id: 'Groq',
name: 'Groq',
@@ -143,6 +153,26 @@ export const ModelProviderList: ModelProviderType[] = [
name: 'FishAudio',
avatar: 'model/fishaudio'
},
{
id: 'Intern',
name: i18nT('common:model_intern'),
avatar: 'model/intern'
},
{
id: 'Moka',
name: i18nT('common:model_moka'),
avatar: 'model/moka'
},
{
id: 'Siliconflow',
name: i18nT('common:model_siliconflow'),
avatar: 'model/siliconflow'
},
{
id: 'PPIO',
name: i18nT('common:model_ppio'),
avatar: 'model/ppio'
},
{
id: 'Other',
name: i18nT('common:model_other'),
@@ -153,6 +183,7 @@ export const ModelProviderMap = Object.fromEntries(
ModelProviderList.map((item, index) => [item.id, { ...item, order: index }])
);
export const getModelProvider = (provider: ModelProviderIdType) => {
export const getModelProvider = (provider?: ModelProviderIdType) => {
if (!provider) return ModelProviderMap.Other;
return ModelProviderMap[provider] ?? ModelProviderMap.Other;
};

View File

@@ -1,14 +1,12 @@
import openai from 'openai';
import type {
ChatCompletionMessageToolCall,
ChatCompletionChunk,
ChatCompletionMessageParam as SdkChatCompletionMessageParam,
ChatCompletionToolMessageParam,
ChatCompletionContentPart as SdkChatCompletionContentPart,
ChatCompletionUserMessageParam as SdkChatCompletionUserMessageParam,
ChatCompletionToolMessageParam as SdkChatCompletionToolMessageParam,
ChatCompletionAssistantMessageParam as SdkChatCompletionAssistantMessageParam,
ChatCompletionContentPartText
ChatCompletionAssistantMessageParam as SdkChatCompletionAssistantMessageParam
} from 'openai/resources';
import { ChatMessageTypeEnum } from './constants';
import { WorkflowInteractiveResponseType } from '../workflow/template/system/interactive/type';
@@ -48,6 +46,7 @@ export type ChatCompletionMessageParam = (
| CustomChatCompletionToolMessageParam
| CustomChatCompletionAssistantMessageParam
) & {
reasoning_text?: string;
dataId?: string;
hideInUI?: boolean;
};
@@ -71,7 +70,8 @@ export type ChatCompletionMessageFunctionCall =
};
// Stream response
export type StreamChatType = Stream<ChatCompletionChunk>;
export type StreamChatType = Stream<openai.Chat.Completions.ChatCompletionChunk>;
export type UnStreamChatType = openai.Chat.Completions.ChatCompletion;
export default openai;
export * from 'openai';

View File

@@ -33,7 +33,7 @@ export const defaultWhisperConfig: AppWhisperConfigType = {
export const defaultQGConfig: AppQGConfigType = {
open: false,
model: 'gpt-4o-mini',
customPrompt: PROMPT_QUESTION_GUIDE
customPrompt: ''
};
export const defaultChatInputGuideConfig = {

View File

@@ -74,12 +74,17 @@ export type AppDetailType = AppSchema & {
export type AppSimpleEditFormType = {
// templateId: string;
aiSettings: {
model: string;
systemPrompt?: string | undefined;
temperature?: number;
maxToken?: number;
isResponseAnswerText: boolean;
[NodeInputKeyEnum.aiModel]: string;
[NodeInputKeyEnum.aiSystemPrompt]?: string | undefined;
[NodeInputKeyEnum.aiChatTemperature]?: number;
[NodeInputKeyEnum.aiChatMaxToken]?: number;
[NodeInputKeyEnum.aiChatIsResponseText]: 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;
@@ -117,6 +122,11 @@ 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,6 +7,8 @@ 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 {
@@ -16,7 +18,8 @@ export const getDefaultAppForm = (): AppSimpleEditFormType => {
temperature: 0,
isResponseAnswerText: true,
maxHistories: 6,
maxToken: 4000
maxToken: 4000,
aiChatReasoning: true
},
dataset: {
datasets: [],
@@ -116,7 +119,8 @@ export const appWorkflow2Form = ({
version: node.version,
inputs: node.inputs,
outputs: node.outputs,
templateType: FlowNodeTemplateTypeEnum.other
templateType: FlowNodeTemplateTypeEnum.other,
pluginData: node.pluginData
});
} else if (node.flowNodeType === FlowNodeTypeEnum.systemConfig) {
defaultAppForm.chatConfig = getAppChatConfig({
@@ -146,3 +150,18 @@ 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

@@ -46,7 +46,16 @@ export const chats2GPTMessages = ({
messages.forEach((item) => {
const dataId = reserveId ? item.dataId : undefined;
if (item.obj === ChatRoleEnum.Human) {
if (item.obj === ChatRoleEnum.System) {
const content = item.value?.[0]?.text?.content;
if (content) {
results.push({
dataId,
role: ChatCompletionRequestMessageRoleEnum.System,
content
});
}
} else if (item.obj === ChatRoleEnum.Human) {
const value = item.value
.map((item) => {
if (item.type === ChatItemValueTypeEnum.text) {
@@ -80,15 +89,6 @@ export const chats2GPTMessages = ({
role: ChatCompletionRequestMessageRoleEnum.User,
content: simpleUserContentPart(value)
});
} else if (item.obj === ChatRoleEnum.System) {
const content = item.value?.[0]?.text?.content;
if (content) {
results.push({
dataId,
role: ChatCompletionRequestMessageRoleEnum.System,
content
});
}
} else {
const aiResults: ChatCompletionMessageParam[] = [];
@@ -349,7 +349,7 @@ export const chatValue2RuntimePrompt = (value: ChatItemValueItemType[]): Runtime
};
value.forEach((item) => {
if (item.type === 'file' && item.file) {
prompt.files?.push(item.file);
prompt.files.push(item.file);
} else if (item.text) {
prompt.text += item.text.content;
}

View File

@@ -25,7 +25,8 @@ export enum ChatItemValueTypeEnum {
text = 'text',
file = 'file',
tool = 'tool',
interactive = 'interactive'
interactive = 'interactive',
reasoning = 'reasoning'
}
export enum ChatSourceEnum {
@@ -75,5 +76,3 @@ export enum ChatStatusEnum {
running = 'running',
finish = 'finish'
}
export const MARKDOWN_QUOTE_SIGN = 'QUOTE SIGN';

View File

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

View File

@@ -1,4 +1,4 @@
import type { LLMModelItemType, VectorModelItemType } from '../../core/ai/model.d';
import type { LLMModelItemType, EmbeddingModelItemType } from '../../core/ai/model.d';
import { PermissionTypeEnum } from '../../support/permission/constant';
import { PushDatasetDataChunkProps } from './api';
import {
@@ -152,7 +152,7 @@ export type DatasetSimpleItemType = {
_id: string;
avatar: string;
name: string;
vectorModel: VectorModelItemType;
vectorModel: EmbeddingModelItemType;
};
export type DatasetListItemType = {
_id: string;
@@ -163,14 +163,14 @@ export type DatasetListItemType = {
intro: string;
type: `${DatasetTypeEnum}`;
permission: DatasetPermission;
vectorModel: VectorModelItemType;
vectorModel: EmbeddingModelItemType;
inheritPermission: boolean;
private?: boolean;
sourceMember?: SourceMemberType;
};
export type DatasetItemType = Omit<DatasetSchemaType, 'vectorModel' | 'agentModel'> & {
vectorModel: VectorModelItemType;
vectorModel: EmbeddingModelItemType;
agentModel: LLMModelItemType;
permission: DatasetPermission;
};

View File

@@ -34,7 +34,7 @@ export function getSourceNameIcon({
}
} catch (error) {}
return 'file/fill/manual';
return 'file/fill/file';
}
/* get dataset data default index */

View File

@@ -1,4 +1,4 @@
import { VectorModelItemType } from '../ai/model.d';
import { EmbeddingModelItemType } from '../ai/model.d';
import { NodeInputKeyEnum } from './constants';
export type SelectedDatasetType = { datasetId: string }[];

View File

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

View File

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

View File

@@ -123,6 +123,7 @@ export type DispatchNodeResponseType = {
temperature?: number;
maxToken?: number;
quoteList?: SearchDataResponseItemType[];
reasoningText?: string;
historyPreview?: {
obj: `${ChatRoleEnum}`;
value: string;
@@ -133,9 +134,17 @@ export type DispatchNodeResponseType = {
limit?: number;
searchMode?: `${DatasetSearchModeEnum}`;
searchUsingReRank?: boolean;
extensionModel?: string;
extensionResult?: string;
extensionTokens?: number;
queryExtensionResult?: {
model: string;
inputTokens: number;
outputTokens: number;
query: string;
};
deepSearchResult?: {
model: string;
inputTokens: number;
outputTokens: number;
};
// dataset concat
concatLength?: number;
@@ -198,6 +207,11 @@ export type DispatchNodeResponseType = {
// tool params
toolParamsResult?: Record<string, any>;
// abandon
extensionModel?: string;
extensionResult?: string;
extensionTokens?: number;
};
export type DispatchNodeResultType<T = {}> = {
@@ -220,6 +234,11 @@ 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

@@ -10,6 +10,7 @@ import { FlowNodeOutputItemType, ReferenceValueType } from '../type/io';
import { ChatItemType, NodeOutputItemType } from '../../../core/chat/type';
import { ChatItemValueTypeEnum, ChatRoleEnum } from '../../../core/chat/constants';
import { replaceVariable, valToStr } from '../../../common/string/tools';
import { ChatCompletionChunk } from 'openai/resources';
export const getMaxHistoryLimitFromNodes = (nodes: StoreNodeItemType[]): number => {
let limit = 10;
@@ -176,6 +177,7 @@ export const checkNodeRunStatus = ({
}
visited.add(edge.source);
// 递归检测后面的 edge如果有其中一个成环则返回 true
const nextEdges = allEdges.filter((item) => item.target === edge.source);
return nextEdges.some((nextEdge) => checkIsCircular(nextEdge, new Set(visited)));
};
@@ -207,7 +209,23 @@ export const checkNodeRunStatus = ({
currentNode: node
});
// check skip(其中一组边,全 skip
// check active(其中一组边,至少有一个 active且没有 waiting 即可运行
if (
commonEdges.length > 0 &&
commonEdges.some((item) => item.status === 'active') &&
commonEdges.every((item) => item.status !== 'waiting')
) {
return 'run';
}
if (
recursiveEdges.length > 0 &&
recursiveEdges.some((item) => item.status === 'active') &&
recursiveEdges.every((item) => item.status !== 'waiting')
) {
return 'run';
}
// check skip其中一组边全是 skiped 则跳过运行)
if (commonEdges.length > 0 && commonEdges.every((item) => item.status === 'skipped')) {
return 'skip';
}
@@ -215,14 +233,6 @@ export const checkNodeRunStatus = ({
return 'skip';
}
// check active有一类边不全是 wait 即可运行)
if (commonEdges.length > 0 && commonEdges.every((item) => item.status !== 'waiting')) {
return 'run';
}
if (recursiveEdges.length > 0 && recursiveEdges.every((item) => item.status !== 'waiting')) {
return 'run';
}
return 'wait';
};
@@ -283,13 +293,12 @@ 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 (
@@ -355,12 +364,14 @@ export function replaceEditorVariable({
export const textAdaptGptResponse = ({
text,
reasoning_content,
model = '',
finish_reason = null,
extraData = {}
}: {
model?: string;
text: string | null;
text?: string | null;
reasoning_content?: string | null;
finish_reason?: null | 'stop';
extraData?: Object;
}) => {
@@ -372,10 +383,11 @@ export const textAdaptGptResponse = ({
model,
choices: [
{
delta:
text === null
? {}
: { role: ChatCompletionRequestMessageRoleEnum.Assistant, content: text },
delta: {
role: ChatCompletionRequestMessageRoleEnum.Assistant,
content: text,
...(reasoning_content && { reasoning_content })
},
index: 0,
finish_reason
}
@@ -408,3 +420,137 @@ export function rewriteNodeOutputByHistories(
};
});
}
// Parse <think></think> tags to think and answer - unstream response
export const parseReasoningContent = (text: string): [string, string] => {
const regex = /<think>([\s\S]*?)<\/think>/;
const match = text.match(regex);
if (!match) {
return ['', text];
}
const thinkContent = match[1].trim();
// Add answer (remaining text after think tag)
const answerContent = text.slice(match.index! + match[0].length);
return [thinkContent, answerContent];
};
// Parse <think></think> tags to think and answer - stream response
export const parseReasoningStreamContent = () => {
let isInThinkTag: boolean | undefined;
const startTag = '<think>';
let startTagBuffer = '';
const endTag = '</think>';
let endTagBuffer = '';
/*
parseReasoning - 只控制是否主动解析 <think></think>,如果接口已经解析了,仍然会返回 think 内容。
*/
const parsePart = (
part: {
choices: {
delta: {
content?: string;
reasoning_content?: string;
};
}[];
},
parseReasoning = false
): [string, string] => {
const content = part.choices?.[0]?.delta?.content || '';
// @ts-ignore
const reasoningContent = part.choices?.[0]?.delta?.reasoning_content || '';
if (reasoningContent || !parseReasoning) {
isInThinkTag = false;
return [reasoningContent, content];
}
if (!content) {
return ['', ''];
}
// 如果不在 think 标签中,或者有 reasoningContent(接口已解析),则返回 reasoningContent 和 content
if (isInThinkTag === false) {
return ['', content];
}
// 检测是否为 think 标签开头的数据
if (isInThinkTag === undefined) {
// Parse content think and answer
startTagBuffer += content;
// 太少内容时候,暂时不解析
if (startTagBuffer.length < startTag.length) {
return ['', ''];
}
if (startTagBuffer.startsWith(startTag)) {
isInThinkTag = true;
return [startTagBuffer.slice(startTag.length), ''];
}
// 如果未命中 think 标签,则认为不在 think 标签中,返回 buffer 内容作为 content
isInThinkTag = false;
return ['', startTagBuffer];
}
// 确认是 think 标签内容,开始返回 think 内容,并实时检测 </think>
/*
检测 </think> 方案。
存储所有疑似 </think> 的内容,直到检测到完整的 </think> 标签或超出 </think> 长度。
content 返回值包含以下几种情况:
abc - 完全未命中尾标签
abc<th - 命中一部分尾标签
abc</think> - 完全命中尾标签
abc</think>abc - 完全命中尾标签
</think>abc - 完全命中尾标签
k>abc - 命中一部分尾标签
*/
// endTagBuffer 专门用来记录疑似尾标签的内容
if (endTagBuffer) {
endTagBuffer += content;
if (endTagBuffer.includes(endTag)) {
isInThinkTag = false;
const answer = endTagBuffer.slice(endTag.length);
return ['', answer];
} else if (endTagBuffer.length >= endTag.length) {
// 缓存内容超出尾标签长度,且仍未命中 </think>,则认为本次猜测 </think> 失败,仍处于 think 阶段。
const tmp = endTagBuffer;
endTagBuffer = '';
return [tmp, ''];
}
return ['', ''];
} else if (content.includes(endTag)) {
// 返回内容,完整命中</think>,直接结束
isInThinkTag = false;
const [think, answer] = content.split(endTag);
return [think, answer];
} else {
// 无 buffer且未命中 </think>,开始疑似 </think> 检测。
for (let i = 1; i < endTag.length; i++) {
const partialEndTag = endTag.slice(0, i);
// 命中一部分尾标签
if (content.endsWith(partialEndTag)) {
const think = content.slice(0, -partialEndTag.length);
endTagBuffer += partialEndTag;
return [think, ''];
}
}
}
// 完全未命中尾标签,还是 think 阶段。
return [content, ''];
};
const getStartTagBuffer = () => startTagBuffer;
return {
parsePart,
getStartTagBuffer
};
};

View File

@@ -63,14 +63,12 @@ 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
},
@@ -91,6 +89,37 @@ 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,
@@ -101,7 +130,6 @@ 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: [
@@ -123,6 +151,20 @@ 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,5 +1,6 @@
import {
datasetQuoteValueDesc,
datasetSelectValueDesc,
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
@@ -38,7 +39,8 @@ export const DatasetSearchModule: FlowNodeTemplateType = {
label: i18nT('common:core.module.input.label.Select dataset'),
value: [],
valueType: WorkflowIOValueTypeEnum.selectDataset,
required: true
required: true,
valueDesc: datasetSelectValueDesc
},
{
key: NodeInputKeyEnum.datasetSimilarity,

View File

@@ -31,10 +31,7 @@ export const AiQueryExtension: FlowNodeTemplateType = {
showStatus: true,
version: '481',
inputs: [
{
...Input_Template_SelectAIModel,
llmModelType: LLMModelTypeEnum.queryExtension
},
Input_Template_SelectAIModel,
{
key: NodeInputKeyEnum.aiSystemPrompt,
renderTypeList: [FlowNodeInputTypeEnum.textarea, FlowNodeInputTypeEnum.reference],

View File

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

View File

@@ -43,6 +43,17 @@ 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

@@ -6,6 +6,22 @@ export type CreateTrainingUsageProps = {
datasetId: string;
};
export type GetUsageProps = {
dateStart: Date;
dateEnd: Date;
sources?: UsageSourceEnum[];
teamMemberIds?: string[];
projectName?: string;
};
export type GetUsageDashboardProps = GetUsageProps & {
unit: 'day' | 'month';
};
export type GetUsageDashboardResponseItem = {
date: Date;
totalPoints: number;
};
export type ConcatUsageProps = UsageListItemCountType & {
teamId: string;
tmbId: string;

View File

@@ -18,30 +18,30 @@ export const UsageSourceMap = {
label: i18nT('common:core.chat.logs.online')
},
[UsageSourceEnum.api]: {
label: 'Api'
label: 'API'
},
[UsageSourceEnum.shareLink]: {
label: i18nT('common:core.chat.logs.free_login')
},
[UsageSourceEnum.training]: {
label: 'dataset.Training Name'
label: i18nT('common:dataset.Training Name')
},
[UsageSourceEnum.cronJob]: {
label: i18nT('common:cron_job_run_app')
},
[UsageSourceEnum.feishu]: {
label: i18nT('user:usage.feishu')
label: i18nT('account_usage:feishu')
},
[UsageSourceEnum.official_account]: {
label: i18nT('user:usage.official_account')
label: i18nT('account_usage:official_account')
},
[UsageSourceEnum.share]: {
label: i18nT('user:usage.share')
label: i18nT('account_usage:share')
},
[UsageSourceEnum.wecom]: {
label: i18nT('user:usage.wecom')
label: i18nT('account_usage:wecom')
},
[UsageSourceEnum.dingtalk]: {
label: i18nT('user:usage.dingtalk')
label: i18nT('account_usage:dingtalk')
}
};

View File

@@ -1,3 +1,4 @@
import { SourceMemberType } from '../../../support/user/type';
import { CreateUsageProps } from './api';
import { UsageSourceEnum } from './constants';
@@ -10,6 +11,7 @@ export type UsageListItemCountType = {
// deprecated
tokens?: number;
};
export type UsageListItemType = UsageListItemCountType & {
moduleName: string;
amount: number;
@@ -28,4 +30,5 @@ export type UsageItemType = {
source: UsageSchemaType['source'];
totalPoints: number;
list: UsageSchemaType['list'];
sourceMember: SourceMemberType;
};

View File

@@ -10,6 +10,7 @@
"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

@@ -12,7 +12,8 @@ const staticPluginList = [
'DingTalkWebhook',
'WeWorkWebhook',
'google',
'bing'
'bing',
'delay'
];
// Run in worker thread (Have npm packages)
const packagePluginList = [

View File

@@ -1,5 +1,6 @@
import { Client as PgClient } from 'pg'; // PostgreSQL 客户端
import mysql from 'mysql2/promise'; // MySQL 客户端
import mssql from 'mssql'; // SQL Server 客户端
type Props = {
databaseType: string;
@@ -52,6 +53,20 @@ 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,6 +42,10 @@
{
"label": "PostgreSQL",
"value": "PostgreSQL"
},
{
"label": "Microsoft SQL Server",
"value": "Microsoft SQL Server"
}
],
"required": true

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