Compare commits

...

60 Commits

Author SHA1 Message Date
Archer
21ab855871 perf: stream response (#2813)
* perf: stream response

* fold code
2024-09-26 18:09:01 +08:00
heheer
aee5de29c7 fix: tool node fold (#2811)
* fix: tool node fold

* delete console
2024-09-26 18:04:43 +08:00
heheer
78d15c2a2f fix: form input value type & default form & ui (#2802)
* fix: form input value type & default form & ui

* variables form ui
2024-09-26 16:33:38 +08:00
Archer
54e0a0eab1 4.8.11 code perf (#2804)
* perf: support child layout

* perf: user form ui

* perf: plugin tool output code

* perf: code

* perf: node fold hook
2024-09-26 16:27:28 +08:00
papapatrick
e6bad93b32 fix: mobile history slider records disappear (#2806)
* fix: mobile history slider records disappear

* change h
2024-09-26 16:26:00 +08:00
heheer
12d7ba5d73 feat: support workflow node fold (#2797)
* feat: support workflow node fold

* fix

* fix
2024-09-26 15:44:04 +08:00
Zhenyi-Wang
5ad8c81ef3 fix: 网页抓取:正确处理//开头的超链接 (#2803)
Co-authored-by: zhenyiwang <zhenyiwang@intl.zju.edu.cn>
2024-09-26 14:53:24 +08:00
papapatrick
cb6fe9d0da feat: support select field as tool output (#2798)
* feat: support select field as tool output

* defaultOutput
2024-09-26 14:37:06 +08:00
heheer
1cf76ee7df feat: add form input node (#2773)
* add node

* dispatch

* extract InputTypeConfig component

* question tip

* fix build

* fix

* fix
2024-09-26 13:48:03 +08:00
Archer
edebfdf5ef fix: ts (#2799) 2024-09-26 13:20:05 +08:00
Archer
86436d55ff 4.8.11 test (#2794)
* perf: version list type

* perf: add node default value

* perf: snapshot status

* fix: version detail auth

* fix: export defalt
2024-09-26 11:02:09 +08:00
Archer
e31d6ec2c1 remove invalid code (#2785) 2024-09-25 09:49:51 +08:00
heheer
6bb10ca150 perf: optimize simple app history (#2782)
* simple app history

* ui

* extract context content into hooks
2024-09-24 21:09:59 +08:00
Archer
7aa75f8ee0 fix: chat page render performance (#2784)
* fix: chat page render performance

* fix: ts
2024-09-24 18:05:27 +08:00
Archer
afd2c394d8 Perf ui detail (#2775)
* perf: tool response tip

* perf: image extract

* perf: user question tool desc

* fix: simple mode load app module

* perf: simple mode plugin version

* perf: share page reload

* refresh simple mode data
2024-09-24 18:04:11 +08:00
Archer
434c03c955 Record scroll test (#2783)
* perf: history add scrollList (#2696)

* perf: chatHistorySlider add virtualList

* perf: chat records add scrollList

* delete console

* perf: ScrollData add ref props

* 优化代码

* optimize code && add line breaks

* add total records display

* finish test

* perf: ScrollComponent load data

* perf: Scroll components load

* perf: scroll code

---------

Co-authored-by: papapatrick <109422393+Patrickill@users.noreply.github.com>
2024-09-24 17:13:32 +08:00
Archer
f4d4d6516c Support simpleApp select workflow (#2772)
* fix: share page id error

* feat: simple workflow support childApp tool

* perf: aichat box animation
2024-09-23 15:43:57 +08:00
zqhong
b6833ca3ea updated: docs/docker.md,修改 config.json 的地址 (#2771)
原先 config.json 的地址是:
https://github.com/labring/FastGPT/blob/main/projects/app/data/config.json

如果没有考虑太多,直接 wget "https://github.com/labring/FastGPT/blob/main/projects/app/data/config.json",则会下载到网页版的 `config.json`。这不是一个 json 文件,而是 github 的网页。

所以,修改为 `https://raw.githubusercontent.com/labring/FastGPT/refs/heads/main/projects/app/data/config.json` 更加合理
2024-09-23 15:24:55 +08:00
Archer
3ab934771f 4.8.11 perf (#2768)
* perf: watch local

* perf: dataset list ui

* perf: Check workflow invalid edges in saved

* remove log

* perf: Forbid touch scale

* perf: rename dataset process

* feat: support child app unstream mode

* feat: Dispatch child app will record detail

* feat: Save childApp run log

* fix: share page init error

* perf: chatId reset
2024-09-23 10:17:49 +08:00
Archer
4245ea4998 Update README.md (#2769) 2024-09-22 14:40:09 +08:00
Archer
9eb02b7e38 feat: plan index;flat i18n and add variable value type (#2762)
* feat: plan index

* flat i18n and add variable value type

* fix: ts

* perf: free plan tip
2024-09-20 17:36:33 +08:00
Archer
75af549c7f Plugin support select file (#2756)
* feat: plugin support upload files (#2716)

* feat: plugin support file upload

* file history

* fix history & chattest

* chore: code

* plugin config icon & file preview padding

* perf: undefined fn

* fix: plugin file numbers & plugin template add config (#2743)

* perf: run plugin without human message (#2749)

* perf: run plugin without human message

* fix build

* fix build

* rename node

* perf: ui

* perf: plugin rerun with last params & plugin log add file (#2755)

* perf: plugin run with last params & plugin log add file

* delete console

* perf: plugin refresh code

* fix: ts

---------

Co-authored-by: heheer <heheer@sealos.io>
2024-09-20 14:12:58 +08:00
Archer
5e7c97b7b8 4.8.11 test fix (#2746)
* fix: refresh tool param

* perf: load image message

* fix: cannot remoce externalReadUrl

* perf: variables update dom

* perf: empty response tip

* fix: conflict
2024-09-20 11:28:58 +08:00
Finley Ge
6c2a7574c3 perf: app list (#2747) 2024-09-20 10:16:27 +08:00
Finley Ge
ca9f36ef9f chore: Jest Testing structure (#2707)
* deps: add jest deps

* chore: mock

* feat: use mocinggoose

* feat: jest

* chore: remove babel.config.js
2024-09-19 13:34:03 +08:00
Archer
265434799f Add externalfile api params (#2745)
* feat: external dataset api

* perf: doc
2024-09-19 13:28:55 +08:00
Archer
258de4471e Update 4810.md (#2744) 2024-09-19 11:34:33 +08:00
Archer
d83bb9d2c7 remove code (#2735) 2024-09-18 13:47:42 +08:00
Archer
093bfa2134 feat: dataset quote role support system; fix: adapt o1 model (#2733)
* feat: dataset quote support system role

* perf: adapt dataset quote role

* fix: adapt o1 model
2024-09-18 13:38:50 +08:00
Archer
539bc77934 fix: aichat response (#2728) 2024-09-17 23:07:30 +08:00
Archer
aabbe06e41 Update intro.md (#2726) 2024-09-16 16:18:05 +08:00
Archer
bb22fa6548 Update 4810.md (#2725) 2024-09-16 16:15:13 +08:00
Archer
bd2509bd41 Update doc and domain (#2722)
* feat: doc

* replace domain

* README
2024-09-16 01:39:50 +08:00
Archer
561516eeef feat: doc (#2721) 2024-09-15 23:02:52 +08:00
Archer
2bdda4638d Feat: Workflow loop node;feat: support openai o1;perf: query extension prompt;fix: intro was not delivered when the datase was created (#2719)
* feat: loop node (#2675)

* loop node frontend

* loop-node

* fix-code

* fix version

* fix

* fix

* fix

* perf: loop array code

* perf: get histories error tip

* feat: support openai o1

* perf: query extension prompt

* feat: 4811 doc

* remove log

* fix: loop node zindex & variable picker type (#2710)

* perf: performance

* perf: workflow performance

* remove uninvalid code

* perf:code

* fix: invoice table refresh

* perf: loop node data type

* fix: loop node store assistants

* perf: target connection

* feat: loop node support help line

* perf: add default icon

---------

Co-authored-by: heheer <heheer@sealos.io>
2024-09-15 22:41:05 +08:00
Finley Ge
1ebc95a282 feat: specify the api's auth type (#2715) 2024-09-15 13:06:51 +08:00
Archer
d0e8f7203c perf: plugin support files (#2708) 2024-09-14 15:11:44 +08:00
Archer
092bb9ab17 feat: sandbox support str to base64 function;feat: compiance text ui (#2702)
* feat: sandbox strToBase64 function

* feat: compiance text ui
2024-09-13 17:54:22 +08:00
Patrickill
9de8849193 优化代码 2024-09-13 17:25:45 +08:00
Patrickill
3d5da27079 add ComplianceTip for dataset&chat 2024-09-13 17:25:45 +08:00
Archer
c454fe07cb Update 4810.md 2024-09-13 15:28:56 +08:00
Patrickill
3e144c4227 remove the trailing #xx when copy 2024-09-13 13:18:08 +08:00
Archer
d8b2887625 feat: comment (#2697) 2024-09-13 11:37:32 +08:00
勤劳上班的卑微小张
ba3b3280b4 Fixed an issue where chunk splitter were lost when clicking on the link sync 2024-09-13 11:08:00 +08:00
Archer
390b8f5b86 Update index.tsx 2024-09-12 18:23:59 +08:00
Finley Ge
d74e6a47d6 fix: chat log get member info 2024-09-12 18:23:59 +08:00
shilin66
424c745cbb fix: Stream模式下使用toolChoice,toolCall的function和type可能为null 2024-09-12 18:12:17 +08:00
archer
0abbcf1401 fix: ts 2024-09-12 18:11:34 +08:00
Archer
da1126ed3c fix: share init error (#2690) 2024-09-12 18:04:31 +08:00
Archer
56281d92f2 Perf: worfklow scroll cannot wheel. Adapt wrokflow skip circle. Change tab alway output stream (#2688)
* perf: teaxtarea no wheel

* remove render error

* adapt workflow skip circle

* perf: change tab can stream output
2024-09-12 17:22:52 +08:00
Archer
fde1618af2 Workflow experience optimization (#2681)
* perf: workflow handle connect

* feat: pan drag mode

* perf: workflow keyboard and touchTable adapt

* perf: teaxtarea no wheel

* remove render error
2024-09-12 17:10:39 +08:00
Archer
22bb4c1e2e Update official_account.md (#2677) 2024-09-12 17:10:39 +08:00
Archer
6331f4b845 perf scroll components (#2676)
* perf: add scroll list && virtualist (#2665)

* perf: chatHistorySlider add virtualList

* perf: dataCard add scroll

* fix: ts

* perf: scroll list components

* perf: hook refresh

---------

Co-authored-by: papapatrick <109422393+Patrickill@users.noreply.github.com>
2024-09-11 19:53:49 +08:00
湛露先生
5101c7a6dc Fix typo location of python bge-rerank (#2674)
Signed-off-by: zhanluxianshen <zhanluxianshen@163.com>
2024-09-11 19:46:12 +08:00
Archer
02bf400bf3 Add workflow rename; Fix: userselect chatId unrefresh (#2672)
* feat: workflow node support rename

* perf: push data to training queue

* fix: userselect chatId unrefresh
2024-09-11 15:27:47 +08:00
Archer
11cbcca2d4 Update 4810.md (#2668) 2024-09-11 10:09:56 +08:00
Finley Ge
34422f9549 fix: sso (#2661) 2024-09-10 18:24:29 +08:00
Archer
aeba79267a Workflow deep and workflow connection performance (#2664)
* feat: Workflow dispatch deep

* perf: workflow connection
2024-09-10 16:57:59 +08:00
Archer
7473be5922 pay pre wrap (#2659) 2024-09-10 14:04:57 +08:00
Finley Ge
de59b3d2e5 fix: app select dataset (#2660) 2024-09-10 13:50:23 +08:00
366 changed files with 19129 additions and 10250 deletions

View File

@@ -11,7 +11,7 @@ assignees: ''
[//]: # '方框内填 x 表示打钩'
- [ ] 我已确认目前没有类似 issue
- [ ] 我已完整查看过项目 README以及[项目文档](https://doc.fastgpt.in/docs/intro/)
- [ ] 我已完整查看过项目 README以及[项目文档](https://doc.tryfastgpt.ai/docs/intro/)
- [ ] 我使用了自己的 key并确认我的 key 是可正常使用的
- [ ] 我理解并愿意跟进此 issue协助测试和提供反馈
- [x] 我理解并认可上述内容,并理解项目维护者精力有限,**不遵循规则的 issue 可能会被无视或直接关闭**

View File

@@ -1,5 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: 飞书话题群
url: https://oss.laf.run/otnvvf-imgs/1719505774252.jpg
url: https://oss.laf.run/otnvvf-imgs/feishu3.png
about: FastGPT 全是问题群

View File

@@ -50,5 +50,73 @@
"export default ContextProvider"
],
"description": "FastGPT usecontext template"
},
"Jest test template": {
"scope": "typescriptreact",
"prefix": "jesttest",
"body": [
"import '@/pages/api/__mocks__/base';",
"import { root } from '@/pages/api/__mocks__/db/init';",
"import { getTestRequest } from '@/test/utils';",
"import { AppErrEnum } from '@fastgpt/global/common/error/code/app';",
"import handler from './demo';",
"",
"// Import the schema",
"import { MongoOutLink } from '@fastgpt/service/support/outLink/schema';",
"",
"beforeAll(async () => {",
" // await MongoOutLink.create({",
" // shareId: 'aaa',",
" // appId: root.appId,",
" // tmbId: root.tmbId,",
" // teamId: root.teamId,",
" // type: 'share',",
" // name: 'aaa'",
" // })",
"});",
"",
"test('Should return a list of outLink', async () => {",
" // Mock request",
" const res = (await handler(",
" ...getTestRequest({",
" query: {",
" appId: root.appId,",
" type: 'share'",
" },",
" user: root",
" })",
" )) as any;",
"",
" expect(res.code).toBe(200);",
" expect(res.data.length).toBe(2);",
"});",
"",
"test('appId is required', async () => {",
" const res = (await handler(",
" ...getTestRequest({",
" query: {",
" type: 'share'",
" },",
" user: root",
" })",
" )) as any;",
" expect(res.code).toBe(500);",
" expect(res.error).toBe(AppErrEnum.unExist);",
"});",
"",
"test('if type is not provided, return nothing', async () => {",
" const res = (await handler(",
" ...getTestRequest({",
" query: {",
" appId: root.appId",
" },",
" user: root",
" })",
" )) as any;",
" expect(res.code).toBe(200);",
" expect(res.data.length).toBe(0);",
"});"
]
}
}

View File

@@ -21,7 +21,7 @@
"i18n-ally.namespace": true,
"i18n-ally.pathMatcher": "{locale}/{namespaces}.json",
"i18n-ally.extract.targetPickingStrategy": "most-similar-by-key",
"i18n-ally.translate.engines": ["deepl", "google"],
"i18n-ally.translate.engines": ["google"],
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}

View File

@@ -1,6 +1,6 @@
<div align="center">
<a href="https://fastgpt.in/"><img src="/.github/imgs/logo.svg" width="120" height="120" alt="fastgpt logo"></a>
<a href="https://tryfastgpt.ai/"><img src="/.github/imgs/logo.svg" width="120" height="120" alt="fastgpt logo"></a>
# FastGPT
@@ -15,13 +15,13 @@ FastGPT 是一个基于 LLM 大语言模型的知识库问答系统,提供开
</div>
<p align="center">
<a href="https://fastgpt.in/">
<a href="https://tryfastgpt.ai/">
<img height="21" src="https://img.shields.io/badge/在线使用-d4eaf7?style=flat-square&logo=spoj&logoColor=7d09f1" alt="cloud">
</a>
<a href="https://doc.fastgpt.in/docs/intro">
<a href="https://doc.tryfastgpt.ai/docs/intro">
<img height="21" src="https://img.shields.io/badge/相关文档-7d09f1?style=flat-square" alt="document">
</a>
<a href="https://doc.fastgpt.in/docs/development">
<a href="https://doc.tryfastgpt.ai/docs/development">
<img height="21" src="https://img.shields.io/badge/本地开发-%23d4eaf7?style=flat-square&logo=xcode&logoColor=7d09f1" alt="development">
</a>
<a href="/#-%E7%9B%B8%E5%85%B3%E9%A1%B9%E7%9B%AE">
@@ -36,7 +36,7 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
## 🛸 在线使用
- 🌍 海外版:[fastgpt.in](https://fastgpt.in/)
- 🌍 国际版:[tryfastgpt.ai](https://tryfastgpt.ai/)
| | |
| ---------------------------------- | ---------------------------------- |
@@ -50,22 +50,22 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
## 💡 RoadMap
`1` 应用编排能力
- [x] 提供简易模式,无需操作编排
- [x] 工作流编排
- [x] 对话工作流、插件工作流
- [x] 工具调用
- [x] 插件 - 工作流封装能力
- [x] Code sandbox
- [ ] 循环调用
- [x] 循环调用
- [x] 用户选择
- [ ] 表单输入
`2` 知识库能力
- [x] 多库复用,混用
- [x] chunk 记录修改和删除
- [x] 源文件存储
- [x] 支持手动输入直接分段QA 拆分导入
- [x] 支持 txtmdhtmlpdfdocxpptxcsvxlsx (有需要更多可 PR file loader)
- [x] 支持 url 读取、CSV 批量导入
- [x] 混合检索 & 重排
- [ ] 标签过滤
- [ ] 自定义文件读取服务
- [ ] 自定义分块服务
`3` 应用调试能力
- [x] 知识库单点搜索测试
@@ -88,7 +88,7 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
`6` 其他
- [x] 支持语音输入和输出 (可配置语音输入语音回答)
- [x] 模糊输入提示
- [ ] 模板市场
- [x] 模板市场
<a href="#readme">
<img src="https://img.shields.io/badge/-返回顶部-7d09f1.svg" alt="#" align="right">
@@ -102,15 +102,15 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
> 使用 [Sealos](https://sealos.io) 服务,无需采购服务器、无需域名,支持高并发 & 动态伸缩,并且数据库应用采用 kubeblocks 的数据库,在 IO 性能方面,远超于简单的 Docker 容器部署。
[点击查看 Sealos 一键部署 FastGPT 教程](https://doc.fastgpt.in/docs/development/sealos/)
[点击查看 Sealos 一键部署 FastGPT 教程](https://doc.tryfastgpt.ai/docs/development/sealos/)
* [快速开始本地开发](https://doc.fastgpt.in/docs/development/intro/)
* [部署 FastGPT](https://doc.fastgpt.in/docs/development/sealos)
* [系统配置文件说明](https://doc.fastgpt.in/docs/development/configuration/)
* [多模型配置](https://doc.fastgpt.in/docs/development/one-api/)
* [版本更新/升级介绍](https://doc.fastgpt.in/docs/development/upgrading)
* [OpenAPI API 文档](https://doc.fastgpt.in/docs/development/openapi/)
* [知识库结构详解](https://doc.fastgpt.in/docs/course/dataset_engine/)
* [快速开始本地开发](https://doc.tryfastgpt.ai/docs/development/intro/)
* [部署 FastGPT](https://doc.tryfastgpt.ai/docs/development/sealos)
* [系统配置文件说明](https://doc.tryfastgpt.ai/docs/development/configuration/)
* [多模型配置](https://doc.tryfastgpt.ai/docs/development/one-api/)
* [版本更新/升级介绍](https://doc.tryfastgpt.ai/docs/development/upgrading)
* [OpenAPI API 文档](https://doc.tryfastgpt.ai/docs/development/openapi/)
* [知识库结构详解](https://doc.tryfastgpt.ai/docs/course/dataset_engine/)
<a href="#readme">
<img src="https://img.shields.io/badge/-返回顶部-7d09f1.svg" alt="#" align="right">
@@ -120,7 +120,7 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
扫码加入飞书话题群 (新开,逐渐弃用微信群)
![](https://oss.laf.run/otnvvf-imgs/飞书20240806-114214.png)
![](https://oss.laf.run/otnvvf-imgs/feishu3.png)
<a href="#readme">
<img src="https://img.shields.io/badge/-返回顶部-7d09f1.svg" alt="#" align="right">
@@ -149,7 +149,7 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
## 🌿 第三方生态
- [OnWeChat 个人微信/企微机器人](https://doc.fastgpt.in/docs/use-cases/onwechat/)
- [OnWeChat 个人微信/企微机器人](https://doc.tryfastgpt.ai/docs/use-cases/onwechat/)
<a href="#readme">
<img src="https://img.shields.io/badge/-返回顶部-7d09f1.svg" alt="#" align="right">
@@ -212,4 +212,4 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
1. 允许作为后台服务直接商用,但不允许提供 SaaS 服务。
2. 未经商业授权,任何形式的商用服务均需保留相关版权信息。
3. 完整请查看 [FastGPT Open Source License](./LICENSE)
4. 联系方式Dennis@sealos.io[点击查看商业版定价策略](https://doc.fastgpt.in/docs/commercial)
4. 联系方式Dennis@sealos.io[点击查看商业版定价策略](https://doc.tryfastgpt.ai/docs/commercial)

View File

@@ -1,6 +1,6 @@
<div align="center">
<a href="https://fastgpt.in/"><img src="/.github/imgs/logo.svg" width="120" height="120" alt="fastgpt logo"></a>
<a href="https://tryfastgpt.ai/"><img src="/.github/imgs/logo.svg" width="120" height="120" alt="fastgpt logo"></a>
# FastGPT
@@ -15,13 +15,13 @@ FastGPT is a knowledge-based platform built on the LLMs, offers a comprehensive
</div>
<p align="center">
<a href="https://fastgpt.in/">
<a href="https://tryfastgpt.ai/">
<img height="21" src="https://img.shields.io/badge/Try it Online-d4eaf7?style=flat-square&logo=spoj&logoColor=7d09f1" alt="cloud">
</a>
<a href="https://doc.fastgpt.in/docs/intro">
<a href="https://doc.tryfastgpt.ai/docs/intro">
<img height="21" src="https://img.shields.io/badge/Documents-7d09f1?style=flat-square" alt="document">
</a>
<a href="https://doc.fastgpt.in/docs/development">
<a href="https://doc.tryfastgpt.ai/docs/development">
<img height="21" src="https://img.shields.io/badge/Local Development-%23d4eaf7?style=flat-square&logo=xcode&logoColor=7d09f1" alt="development">
</a>
<a href="https://github.com/labring/FastGPT/blob/main/LICENSE">
@@ -39,7 +39,7 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
## 🛸 Use Cloud Services
Cloud: [fastgpt.in](https://fastgpt.in/)
Cloud: [tryfastgpt.ai](https://tryfastgpt.ai/)
| | |
| ---------------------------------- | ---------------------------------- |
@@ -113,16 +113,16 @@ Project tech stack: NextJs + TS + ChakraUI + Mongo + Postgres (Vector plugin)
Give it a 2-4 minute wait after deployment as it sets up the database. Initially, it might be a tad slow since we're using the basic settings.
- [Getting Started with Local Development](https://doc.fastgpt.in/docs/development)
- [Deploying FastGPT](https://doc.fastgpt.in/docs/installation)
- [Guide on System Configs](https://doc.fastgpt.in/docs/installation/reference)
- [Configuring Multiple Models](https://doc.fastgpt.in/docs/installation/reference/models)
- [Version Updates & Upgrades](https://doc.fastgpt.in/docs/installation/upgrading)
- [Getting Started with Local Development](https://doc.tryfastgpt.ai/docs/development)
- [Deploying FastGPT](https://doc.tryfastgpt.ai/docs/installation)
- [Guide on System Configs](https://doc.tryfastgpt.ai/docs/installation/reference)
- [Configuring Multiple Models](https://doc.tryfastgpt.ai/docs/installation/reference/models)
- [Version Updates & Upgrades](https://doc.tryfastgpt.ai/docs/installation/upgrading)
## 🏘️ Community & support
+ 🌐 Visit the [FastGPT website](https://fastgpt.in/) for full documentation and useful links.
+ 🌐 Visit the [FastGPT website](https://tryfastgpt.ai/) for full documentation and useful links.
+ 💬 Join our [Discord server](https://discord.gg/mp68xkZn2Q) is to chat with FastGPT developers and other FastGPT users. This is a good place to learn about FastGPT, ask questions, and share your experiences.
+ 🐞 Create [GitHub Issues](https://github.com/labring/FastGPT/issues/new/choose) for bug reports and feature requests.

View File

@@ -1,6 +1,6 @@
<div align="center">
<a href="https://fastgpt.in/"><img src="/.github/imgs/logo.svg" width="120" height="120" alt="fastgpt logo"></a>
<a href="https://tryfastgpt.ai/"><img src="/.github/imgs/logo.svg" width="120" height="120" alt="fastgpt logo"></a>
# FastGPT
@@ -15,13 +15,13 @@ FastGPT は、LLM 上 に 構築 された 知識 ベースの Q&A システム
</div>
<p align="center">
<a href="https://fastgpt.in/">
<a href="https://tryfastgpt.ai/">
<img height="21" src="https://img.shields.io/badge/在线使用-d4eaf7?style=flat-square&logo=spoj&logoColor=7d09f1" alt="cloud">
</a>
<a href="https://doc.fastgpt.in/docs/intro">
<a href="https://doc.tryfastgpt.ai/docs/intro">
<img height="21" src="https://img.shields.io/badge/相关文档-7d09f1?style=flat-square" alt="document">
</a>
<a href="https://doc.fastgpt.in/docs/development">
<a href="https://doc.tryfastgpt.ai/docs/development">
<img height="21" src="https://img.shields.io/badge/本地开发-%23d4eaf7?style=flat-square&logo=xcode&logoColor=7d09f1" alt="development">
</a>
<a href="/#-%E7%9B%B8%E5%85%B3%E9%A1%B9%E7%9B%AE">
@@ -36,7 +36,7 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
## 🛸 クラウドサービスの 利用
[fastgpt.in](https://fastgpt.in/)
[tryfastgpt.ai](https://tryfastgpt.ai/)
| | |
| ---------------------------------- | ---------------------------------- |
@@ -98,11 +98,11 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
デプロイ 後、データベースをセットアップするので、24分待 ってください。基本設定 を 使 っているので、最初 は 少 し 遅 いかもしれません。
- [ローカル 開発入門](https://doc.fastgpt.in/docs/development)
- [FastGPT のデプロイ](https://doc.fastgpt.in/docs/installation)
- [システム 設定 ガイド](https://doc.fastgpt.in/docs/installation/reference)
- [複数 モデルの 設定](https://doc.fastgpt.in/docs/installation/reference/models)
- [バージョン 更新 とアップグレード](https://doc.fastgpt.in/docs/installation/upgrading)
- [ローカル 開発入門](https://doc.tryfastgpt.ai/docs/development)
- [FastGPT のデプロイ](https://doc.tryfastgpt.ai/docs/installation)
- [システム 設定 ガイド](https://doc.tryfastgpt.ai/docs/installation/reference)
- [複数 モデルの 設定](https://doc.tryfastgpt.ai/docs/installation/reference/models)
- [バージョン 更新 とアップグレード](https://doc.tryfastgpt.ai/docs/installation/upgrading)
<!-- ## :point_right: ロードマップ
- [FastGPT ロードマップ](https://kjqvjse66l.feishu.cn/docx/RVUxdqE2WolDYyxEKATcM0XXnte) -->

4
dev.md
View File

@@ -29,6 +29,10 @@ Note: If the Node version is >= 20, you need to pass the `--no-node-snapshot` pa
NODE_OPTIONS=--no-node-snapshot pnpm i
```
### Jest
https://fael3z0zfze.feishu.cn/docx/ZOI1dABpxoGhS7xzhkXcKPxZnDL
## I18N
### Install i18n-ally Plugin

View File

@@ -11,7 +11,7 @@ FastGPT 项目在 Apache License 2.0 许可下开源,同时包含以下附加
+ FastGPT 允许被用于商业化,例如作为其他应用的“后端即服务”使用,或者作为应用开发平台提供给企业。然而,当满足以下条件时,必须联系作者获得商业许可:
+ 多租户 SaaS 服务:除非获得 FastGPT 的明确书面授权,否则不得使用 fastgpt.in 的源码来运营与 fastgpt.in 服务类似的多租户 SaaS 服务。
+ 多租户 SaaS 服务:除非获得 FastGPT 的明确书面授权,否则不得使用 tryfastgpt.ai 的源码来运营与 tryfastgpt.ai 服务类似的多租户 SaaS 服务。
+ LOGO 及版权信息:在使用 FastGPT 的过程中,不得移除或修改 FastGPT 控制台内的 LOGO 或版权信息。
请通过电子邮件 yujinlong@sealos.io 联系我们咨询许可事宜。

View File

@@ -114,7 +114,7 @@ ${content}
它接收一个`string`类型的输入,除了可以引用文档解析结果外,还可以实现自定义内容引用,最终会进行提示词拼接,放置在 role=system 的消息中。提示词模板如下:
```
将 <Quote></Quote> 中的内容作为你的知识:
将 <Quote></Quote> 中的内容作为本次对话的参考:
<Quote>
{{quote}}
</Quote>

View File

@@ -36,7 +36,7 @@ weight: 113
私有部署的用户可自行查阅自己的 IP 地址。
海外版用户fastgpt.in)可以填写下面的 IP 白名单:
海外版用户(cloud.tryfastgpt.ai)可以填写下面的 IP 白名单:
```
34.87.20.17

View File

@@ -27,7 +27,7 @@ Tips: 安全起见,你可以设置一个额度或者过期时间,放置 key
## 替换三方应用的变量
```bash
OPENAI_API_BASE_URL: https://api.fastgpt.in/api (改成自己部署的域名)
OPENAI_API_BASE_URL: https://api.tryfastgpt.ai/api (改成自己部署的域名)
OPENAI_API_KEY = 上一步获取到的密钥
```

View File

@@ -18,7 +18,7 @@ Web 站点同步利用爬虫的技术,可以通过一个入口网站,自动
Tips: 国内的媒体站点基本不可用公众号、csdn、知乎等。可以通过终端发送`curl`请求检测是否为静态站点,例如:
```bash
curl https://doc.fastgpt.in/docs/intro/
curl https://doc.tryfastgpt.ai/docs/intro/
```
## 如何使用

View File

@@ -13,9 +13,7 @@ weight: 708
这个配置文件中包含了系统参数和各个模型配置:
## 4.6.8+ 版本新配置文件
llm模型全部合并
## 4.6.8+ 版本新配置文件示例
```json
{
@@ -29,16 +27,16 @@ llm模型全部合并
},
"llmModels": [
{
"model": "gpt-3.5-turbo", // 模型名(对应OneAPI中渠道的模型名)
"name": "gpt-3.5-turbo", // 别名
"model": "gpt-4o-mini", // 模型名(对应OneAPI中渠道的模型名)
"name": "gpt-4o-mini", // 模型别名
"avatar": "/imgs/model/openai.svg", // 模型的logo
"maxContext": 16000, // 最大上下文
"maxResponse": 4000, // 最大回复
"quoteMaxToken": 13000, // 最大引用内容
"maxContext": 125000, // 最大上下文
"maxResponse": 16000, // 最大回复
"quoteMaxToken": 120000, // 最大引用内容
"maxTemperature": 1.2, // 最大温度
"charsPointsPrice": 0, // n积分/1k token商业版
"charsPointsPrice": 0, // n积分/1k token商业版
"censor": false, // 是否开启敏感校验(商业版)
"vision": false, // 是否支持图片输入
"vision": true, // 是否支持图片输入
"datasetProcess": true, // 是否设置为知识库处理模型QA务必保证至少有一个为true否则知识库会报错
"usedInClassify": true, // 是否用于问题分类务必保证至少有一个为true
"usedInExtractFields": true, // 是否用于内容提取务必保证至少有一个为true
@@ -49,20 +47,20 @@ llm模型全部合并
"customCQPrompt": "", // 自定义文本分类提示词(不支持工具和函数调用的模型
"customExtractPrompt": "", // 自定义内容提取提示词
"defaultSystemChatPrompt": "", // 对话默认携带的系统提示词
"defaultConfig":{} // 请求API时挟带一些默认配置比如 GLM4 的 top_p
"defaultConfig": {} // 请求API时挟带一些默认配置比如 GLM4 的 top_p
},
{
"model": "gpt-4-0125-preview",
"name": "gpt-4-turbo",
"model": "gpt-4o",
"name": "gpt-4o",
"avatar": "/imgs/model/openai.svg",
"maxContext": 125000,
"maxResponse": 4000,
"quoteMaxToken": 100000,
"quoteMaxToken": 120000,
"maxTemperature": 1.2,
"charsPointsPrice": 0,
"censor": false,
"vision": false,
"datasetProcess": false,
"vision": true,
"datasetProcess": true,
"usedInClassify": true,
"usedInExtractFields": true,
"usedInToolCall": true,
@@ -72,30 +70,61 @@ llm模型全部合并
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"defaultConfig":{}
"defaultConfig": {}
},
{
"model": "gpt-4-vision-preview",
"name": "gpt-4-vision",
"model": "o1-mini",
"name": "o1-mini",
"avatar": "/imgs/model/openai.svg",
"maxContext": 128000,
"maxContext": 125000,
"maxResponse": 4000,
"quoteMaxToken": 100000,
"quoteMaxToken": 120000,
"maxTemperature": 1.2,
"charsPointsPrice": 0,
"censor": false,
"vision": true,
"datasetProcess": false,
"usedInClassify": false,
"usedInExtractFields": false,
"usedInToolCall": false,
"usedInQueryExtension": false,
"toolChoice": true,
"vision": false,
"datasetProcess": true,
"usedInClassify": true,
"usedInExtractFields": true,
"usedInToolCall": true,
"usedInQueryExtension": true,
"toolChoice": false,
"functionCall": false,
"customCQPrompt": "",
"customExtractPrompt": "",
"defaultSystemChatPrompt": "",
"defaultConfig":{}
"defaultConfig": {
"temperature": 1,
"max_tokens": null,
"stream": false
}
},
{
"model": "o1-preview",
"name": "o1-preview",
"avatar": "/imgs/model/openai.svg",
"maxContext": 125000,
"maxResponse": 4000,
"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": [
@@ -107,9 +136,30 @@ llm模型全部合并
"defaultToken": 700, // 默认文本分割时候的 token
"maxToken": 3000, // 最大 token
"weight": 100, // 优先训练权重
"defaultConfig":{}, // 自定义额外参数。例如,如果希望使用 embedding3-large 的话,可以传入 dimensions:1024来返回1024维度的向量。目前必须小于1536维度
"defaultConfig": {}, // 自定义额外参数。例如,如果希望使用 embedding3-large 的话,可以传入 dimensions:1024来返回1024维度的向量。目前必须小于1536维度
"dbConfig": {}, // 存储时的额外参数(非对称向量模型时候需要用到)
"queryConfig": {} // 参训时的额外参数
},
{
"model": "text-embedding-3-large",
"name": "text-embedding-3-large",
"avatar": "/imgs/model/openai.svg",
"charsPointsPrice": 0,
"defaultToken": 512,
"maxToken": 3000,
"weight": 100,
"defaultConfig": {
"dimensions": 1024
}
},
{
"model": "text-embedding-3-small",
"name": "text-embedding-3-small",
"avatar": "/imgs/model/openai.svg",
"charsPointsPrice": 0,
"defaultToken": 512,
"maxToken": 3000,
"weight": 100
}
],
"reRankModels": [],

View File

@@ -110,7 +110,7 @@ brew install orbstack
非 Linux 环境或无法访问外网环境,可手动创建一个目录,并下载配置文件和对应版本的`docker-compose.yml`在这个文件夹中依据下载的配置文件运行docker若作为本地开发使用推荐`docker-compose-pgvector`版本,并且自行拉取并运行`sandbox``fastgpt`并在docker配置文件中注释掉`sandbox``fastgpt`的部分
- [config.json](https://github.com/labring/FastGPT/blob/main/projects/app/data/config.json)
- [config.json](https://raw.githubusercontent.com/labring/FastGPT/refs/heads/main/projects/app/data/config.json)
- [docker-compose.yml](https://github.com/labring/FastGPT/blob/main/files/docker) (注意,不同向量库版本的文件不一样)
{{% alert icon="🤖" context="success" %}}

View File

@@ -121,4 +121,148 @@ OneAPI 的 API Key 配置错误,需要修改`OPENAI_API_KEY`环境变量,并
1. 模型服务不可用
2. 模型接口参数异常温度、max token等可能不适配
3. ....
3. ....
## 四、常见模型问题
### 报错 - 模型响应为空
该错误是由于 stream 模式下oneapi 直接结束了流请求,并且未返回任何内容导致。
4.8.10 版本新增了错误日志,报错时,会在日志中打印出实际发送的 Body 参数,可以复制该参数后,通过 curl 向 oneapi 发起请求测试。
由于 oneapi 在 stream 模式下,无法正确捕获错误,可以设置成 `stream=false` 后进行测试。
### 如何测试模型是否支持工具调用
需要模型提供商和 oneapi 同时支持工具调用才可使用,测试方法如下:
1. 通过 `curl``oneapi` 发起第一轮 stream 模式的 tool 测试。
```bash
curl --location --request POST 'https://oneapi.xxx/v1/chat/completions' \
--header 'Authorization: Bearer sk-xxxx' \
--header 'Content-Type: application/json' \
--data-raw '{
"model": "gpt-4o-mini",
"temperature": 0.01,
"max_tokens": 8000,
"stream": true,
"messages": [
{
"role": "user",
"content": "几点了"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "hCVbIY",
"description": "获取用户当前时区的时间。",
"parameters": {
"type": "object",
"properties": {},
"required": []
}
}
}
],
"tool_choice": "auto"
}'
```
2. 检查响应参数
如果能正常调用工具,会返回对应 `tool_calls` 参数。
```json
{
"id": "chatcmpl-A7kwo1rZ3OHYSeIFgfWYxu8X2koN3",
"object": "chat.completion.chunk",
"created": 1726412126,
"model": "gpt-4o-mini-2024-07-18",
"system_fingerprint": "fp_483d39d857",
"choices": [
{
"index": 0,
"delta": {
"role": "assistant",
"content": null,
"tool_calls": [
{
"index": 0,
"id": "call_0n24eiFk8OUyIyrdEbLdirU7",
"type": "function",
"function": {
"name": "mEYIcFl84rYC",
"arguments": ""
}
}
],
"refusal": null
},
"logprobs": null,
"finish_reason": null
}
],
"usage": null
}
```
3. 通过 `curl``oneapi` 发起第二轮 stream 模式的 tool 测试。
第二轮请求是把工具结果发送给模型。发起后会得到模型回答的结果。
```bash
curl --location --request POST 'https://oneapi.xxxx/v1/chat/completions' \
--header 'Authorization: Bearer sk-xxx' \
--header 'Content-Type: application/json' \
--data-raw '{
"model": "gpt-4o-mini",
"temperature": 0.01,
"max_tokens": 8000,
"stream": true,
"messages": [
{
"role": "user",
"content": "几点了"
},
{
"role": "assistant",
"tool_calls": [
{
"id": "kDia9S19c4RO",
"type": "function",
"function": {
"name": "hCVbIY",
"arguments": "{}"
}
}
]
},
{
"tool_call_id": "kDia9S19c4RO",
"role": "tool",
"name": "hCVbIY",
"content": "{\n \"time\": \"2024-09-14 22:59:21 Sunday\"\n}"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "hCVbIY",
"description": "获取用户当前时区的时间。",
"parameters": {
"type": "object",
"properties": {},
"required": []
}
}
}
],
"tool_choice": "auto"
}'
```

View File

@@ -7,11 +7,11 @@ toc: true
weight: 705
---
本文档介绍了如何设置开发环境以构建和测试 [FastGPT](https://fastgpt.in),。
本文档介绍了如何设置开发环境以构建和测试 [FastGPT](https://tryfastgpt.ai),。
## 前置依赖项
您需要在计算机上安装和配置以下依赖项才能构建 [FastGPT](https://fastgpt.in)
您需要在计算机上安装和配置以下依赖项才能构建 [FastGPT](https://tryfastgpt.ai)
- [Git](http://git-scm.com/)
- [Docker](https://www.docker.com/)(构建镜像)

View File

@@ -135,7 +135,7 @@ CHAT_API_KEY=sk-xxxxxx
"charsPointsPrice": 0,
"censor": false,
"vision": false, // 是否支持图片输入
"datasetProcess": false, // 是否设置为知识库处理模型
"datasetProcess": true, // 是否设置为知识库处理模型
"usedInClassify": true, // 是否用于问题分类
"usedInExtractFields": true, // 是否用于字段提取
"usedInToolCall": true, // 是否用于工具调用

View File

@@ -32,7 +32,7 @@ FastGPT 的 API Key **有 2 类**,一类是全局通用的 key (无法直接
OpenAPI 中,所有的接口都通过 Header.Authorization 进行鉴权。
```
baseUrl: "https://api.fastgpt.in/api"
baseUrl: "https://api.tryfastgpt.ai/api"
headers: {
Authorization: "Bearer {{apikey}}"
}
@@ -41,7 +41,7 @@ headers: {
**发起应用对话示例**
```sh
curl --location --request POST 'https://api.fastgpt.in/api/v1/chat/completions' \
curl --location --request POST 'https://api.tryfastgpt.ai/api/v1/chat/completions' \
--header 'Authorization: Bearer fastgpt-xxxxxx' \
--header 'Content-Type: application/json' \
--data-raw '{

View File

@@ -29,7 +29,7 @@ weight: 852
{{< markdownify >}}
```bash
curl --location --request POST 'https://api.fastgpt.in/api/v1/chat/completions' \
curl --location --request POST 'https://api.tryfastgpt.ai/api/v1/chat/completions' \
--header 'Authorization: Bearer fastgpt-xxxxxx' \
--header 'Content-Type: application/json' \
--data-raw '{
@@ -332,7 +332,7 @@ curl --location --request POST 'http://localhost:3000/api/v1/chat/completions' \
},
{
"nodeId": "pluginOutput",
"moduleName": "自定义插件输出",
"moduleName": "插件输出",
"moduleType": "pluginOutput",
"totalPoints": 0,
"pluginOutput": {
@@ -430,7 +430,7 @@ event: answer
data: [DONE]
event: flowResponses
data: [{"nodeId":"fdDgXQ6SYn8v","moduleName":"AI 对话","moduleType":"chatNode","totalPoints":0.033,"model":"FastAI-3.5","tokens":33,"query":"你好","maxToken":2000,"historyPreview":[{"obj":"Human","value":"你好"},{"obj":"AI","value":"你好!有什么可以帮助你的吗?"}],"contextTotalLen":2,"runningTime":1.42},{"nodeId":"pluginOutput","moduleName":"自定义插件输出","moduleType":"pluginOutput","totalPoints":0,"pluginOutput":{"result":"你好!有什么可以帮助你的吗?"},"runningTime":0}]
data: [{"nodeId":"fdDgXQ6SYn8v","moduleName":"AI 对话","moduleType":"chatNode","totalPoints":0.033,"model":"FastAI-3.5","tokens":33,"query":"你好","maxToken":2000,"historyPreview":[{"obj":"Human","value":"你好"},{"obj":"AI","value":"你好!有什么可以帮助你的吗?"}],"contextTotalLen":2,"runningTime":1.42},{"nodeId":"pluginOutput","moduleName":"插件输出","moduleType":"pluginOutput","totalPoints":0,"pluginOutput":{"result":"你好!有什么可以帮助你的吗?"},"runningTime":0}]
```
{{< /markdownify >}}

View File

@@ -22,7 +22,7 @@ weight: 853
**新例子**
```bash
curl --location --request POST 'https://api.fastgpt.in/api/support/wallet/usage/createTrainingUsage' \
curl --location --request POST 'https://api.tryfastgpt.ai/api/support/wallet/usage/createTrainingUsage' \
--header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \
--data-raw '{
@@ -34,7 +34,7 @@ curl --location --request POST 'https://api.fastgpt.in/api/support/wallet/usage/
**x例子**
```bash
curl --location --request POST 'https://api.fastgpt.in/api/support/wallet/bill/createTrainingBill' \
curl --location --request POST 'https://api.tryfastgpt.ai/api/support/wallet/bill/createTrainingBill' \
--header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \
--data-raw '{
@@ -312,6 +312,8 @@ curl --location --request DELETE 'http://localhost:3000/api/core/dataset/delete?
| chunkSize | 预估块大小 | |
| chunkSplitter | 自定义最高优先分割符号 | |
| qaPrompt | qa拆分提示词 | |
| tags | 集合标签(字符串数组) | |
| createTime | 文件创建时间Date / String | |
**出参**
@@ -466,7 +468,7 @@ curl --location --request POST 'http://localhost:3000/api/core/dataset/collectio
--header 'Authorization: Bearer {{authorization}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"link":"https://doc.fastgpt.in/docs/course/quick-start/",
"link":"https://doc.tryfastgpt.ai/docs/course/quick-start/",
"datasetId":"6593e137231a2be9c5603ba7",
"parentId": null,
@@ -604,9 +606,11 @@ curl --location --request POST 'http://localhost:3000/api/proApi/core/dataset/co
--data-raw '{
"externalFileUrl":"https://image.xxxxx.com/fastgpt-dev/%E6%91%82.pdf",
"externalFileId":"1111",
"filename":"自定义文件名",
"createTime": "2024-05-01T00:00:00.000Z",
"filename":"自定义文件名.pdf",
"datasetId":"6642d105a5e9d2b00255b27b",
"parentId": null,
"tags": ["tag1","tag2"],
"trainingType": "chunk",
"chunkSize":512,
@@ -625,7 +629,8 @@ curl --location --request POST 'http://localhost:3000/api/proApi/core/dataset/co
| --- | --- | --- |
| externalFileUrl | 文件访问链接(可以是临时链接) | ✅ |
| externalFileId | 外部文件ID | |
| filename | 自定义文件名 | |
| filename | 自定义文件名,需要带后缀 | |
| createTime | 文件创建时间Date ISO 字符串都 ok | |
{{< /markdownify >}}
@@ -710,7 +715,21 @@ curl --location --request POST 'http://localhost:3000/api/core/dataset/collectio
"updateTime": "2099-01-01T00:00:00.000Z",
"dataAmount": 3,
"trainingAmount": 0,
"canWrite": true
"externalFileId": "1111",
"tags": [
"11",
"测试的"
],
"forbid": false,
"trainingType": "chunk",
"permission": {
"value": 4294967295,
"isOwner": true,
"hasManagePer": true,
"hasWritePer": true,
"hasReadPer": true
}
},
{
"_id": "65abd0ad9d1448617cba6031",
@@ -718,11 +737,23 @@ curl --location --request POST 'http://localhost:3000/api/core/dataset/collectio
"tmbId": "65422be6aa44b7da77729ec9",
"type": "link",
"name": "快速上手 | FastGPT",
"rawLink": "https://doc.fastgpt.in/docs/course/quick-start/",
"rawLink": "https://doc.tryfastgpt.ai/docs/course/quick-start/",
"updateTime": "2024-01-20T13:54:53.031Z",
"dataAmount": 3,
"trainingAmount": 0,
"canWrite": true
"externalFileId": "222",
"tags": [
"测试的"
],
"forbid": false,
"trainingType": "chunk",
"permission": {
"value": 4294967295,
"isOwner": true,
"hasManagePer": true,
"hasWritePer": true,
"hasReadPer": true
}
}
],
"total": 93
@@ -813,14 +844,36 @@ curl --location --request GET 'http://localhost:3000/api/core/dataset/collection
{{< tab tabName="请求示例" >}}
{{< markdownify >}}
**通过集合 ID 修改集合信息**
```bash
curl --location --request PUT 'http://localhost:3000/api/core/dataset/collection/update' \
--header 'Authorization: Bearer {{authorization}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"id":"65abcfab9d1448617cba5f0d",
"parentId":null,
"name":"测2222试"
"parentId": null,
"name": "测2222试",
"tags": ["tag1", "tag2"],
"forbid": false,
"createTime": "2024-01-01T00:00:00.000Z"
}'
```
**通过外部文件 ID 修改集合信息** 只需要把 id 换成 datasetId 和 externalFileId。
```bash
curl --location --request PUT 'http://localhost:3000/api/core/dataset/collection/update' \
--header 'Authorization: Bearer {{authorization}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"datasetId":"6593e137231a2be9c5603ba7",
"externalFileId":"1111",
"parentId": null,
"name": "测2222试",
"tags": ["tag1", "tag2"],
"forbid": false,
"createTime": "2024-01-01T00:00:00.000Z"
}'
```
@@ -834,6 +887,9 @@ curl --location --request PUT 'http://localhost:3000/api/core/dataset/collection
- id: 集合的ID
- parentId: 修改父级ID可选
- name: 修改集合名称(可选)
- tags: 修改集合标签(可选)
- forbid: 修改集合禁用状态(可选)
- createTime: 修改集合创建时间(可选)
{{% /alert %}}
{{< /markdownify >}}
@@ -935,7 +991,7 @@ curl --location --request DELETE 'http://localhost:3000/api/core/dataset/collect
{{< markdownify >}}
```bash
curl --location --request POST 'https://api.fastgpt.in/api/core/dataset/data/pushData' \
curl --location --request POST 'https://api.tryfastgpt.ai/api/core/dataset/data/pushData' \
--header 'Authorization: Bearer apikey' \
--header 'Content-Type: application/json' \
--data-raw '{
@@ -1272,7 +1328,7 @@ curl --location --request DELETE 'http://localhost:3000/api/core/dataset/data/de
{{< markdownify >}}
```bash
curl --location --request POST 'https://api.fastgpt.in/api/core/dataset/searchTest' \
curl --location --request POST 'https://api.tryfastgpt.ai/api/core/dataset/searchTest' \
--header 'Authorization: Bearer fastgpt-xxxxx' \
--header 'Content-Type: application/json' \
--data-raw '{

View File

@@ -53,9 +53,9 @@ weight: 860
在分享链接的地址中,增加一个额外的参数: authToken。例如
原始的链接:`https://share.fastgpt.in/chat/share?shareId=648aaf5ae121349a16d62192`
原始的链接:`https://share.tryfastgpt.ai/chat/share?shareId=648aaf5ae121349a16d62192`
完整链接: `https://share.fastgpt.in/chat/share?shareId=648aaf5ae121349a16d62192&authToken=userid12345`
完整链接: `https://share.tryfastgpt.ai/chat/share?shareId=648aaf5ae121349a16d62192&authToken=userid12345`
这个`authToken`通常是你系统生成的用户唯一凭证Token之类的。FastGPT 会在鉴权接口的`body`中携带 token={{authToken}} 的参数。
@@ -227,7 +227,7 @@ curl --location --request POST '{{host}}/shareAuth/finish' \
"historyPreview": [
{
"obj": "Human",
"value": "使用 <Data></Data> 标记中的内容作为你的知识:\n\n<Data>\n导演是谁\n电影《铃芽之旅》的导演是新海诚。\n------\n电影《铃芽之旅》的编剧是谁22\n新海诚是本片的编剧。\n------\n电影《铃芽之旅》的女主角是谁\n电影的女主角是铃芽。\n------\n电影《铃芽之旅》的制作团队中有哪位著名人士2\n川村元气是本片的制作团队成员之一。\n------\n你是谁\n我是电影《铃芽之旅》助手\n------\n电影《铃芽之旅》男主角是谁\n电影《铃芽之旅》男主角是宗像草太由松村北斗配音。\n------\n电影《铃芽之旅》的作者新海诚写了一本小说叫什么名字\n小说名字叫《铃芽之旅》。\n------\n电影《铃芽之旅》的女主角是谁\n电影《铃芽之旅》的女主角是岩户铃芽由原菜乃华配音。\n------\n电影《铃芽之旅》的故事背景是什么\n日本\n------\n谁担任电影《铃芽之旅》中岩户环的配音\n深津绘里担任电影《铃芽之旅》中岩户环的配音。\n</Data>\n\n回答要求\n- 如果你不清楚答案,你需要澄清。\n- 避免提及你是从 <Data></Data> 获取的知识。\n- 保持答案与 <Data></Data> 中描述的一致。\n- 使用 Markdown 语法优化回答格式。\n- 使用与问题相同的语言回答。\n\n问题:\"\"\"导演是谁\"\"\""
"value": "使用 <Data></Data> 标记中的内容作为本次对话的参考:\n\n<Data>\n导演是谁\n电影《铃芽之旅》的导演是新海诚。\n------\n电影《铃芽之旅》的编剧是谁22\n新海诚是本片的编剧。\n------\n电影《铃芽之旅》的女主角是谁\n电影的女主角是铃芽。\n------\n电影《铃芽之旅》的制作团队中有哪位著名人士2\n川村元气是本片的制作团队成员之一。\n------\n你是谁\n我是电影《铃芽之旅》助手\n------\n电影《铃芽之旅》男主角是谁\n电影《铃芽之旅》男主角是宗像草太由松村北斗配音。\n------\n电影《铃芽之旅》的作者新海诚写了一本小说叫什么名字\n小说名字叫《铃芽之旅》。\n------\n电影《铃芽之旅》的女主角是谁\n电影《铃芽之旅》的女主角是岩户铃芽由原菜乃华配音。\n------\n电影《铃芽之旅》的故事背景是什么\n日本\n------\n谁担任电影《铃芽之旅》中岩户环的配音\n深津绘里担任电影《铃芽之旅》中岩户环的配音。\n</Data>\n\n回答要求\n- 如果你不清楚答案,你需要澄清。\n- 避免提及你是从 <Data></Data> 获取的知识。\n- 保持答案与 <Data></Data> 中描述的一致。\n- 使用 Markdown 语法优化回答格式。\n- 使用与问题相同的语言回答。\n\n问题:\"\"\"导演是谁\"\"\""
},
{
"obj": "AI",
@@ -387,9 +387,9 @@ export default async function (ctx: FunctionContext) {
### 3. 修改分享链接参数
源分享链接:`https://share.fastgpt.in/chat/share?shareId=64be36376a438af0311e599c`
源分享链接:`https://share.tryfastgpt.ai/chat/share?shareId=64be36376a438af0311e599c`
修改后:`https://share.fastgpt.in/chat/share?shareId=64be36376a438af0311e599c&authToken=fastgpt`
修改后:`https://share.tryfastgpt.ai/chat/share?shareId=64be36376a438af0311e599c&authToken=fastgpt`
### 4. 测试效果

View File

@@ -89,7 +89,7 @@ FastGPT 商业版共包含了2个应用fastgpt, fastgpt-plus和2个数据
点击右侧的详情,可以查看对应应用的详细信息。
### 如何更新/升级 FastGPT
[升级脚本文档](https://doc.fastgpt.in/docs/development/upgrading/)先看下文档,看下需要升级哪个版本。注意,不要跨版本升级!!!!!
[升级脚本文档](https://doc.tryfastgpt.ai/docs/development/upgrading/)先看下文档,看下需要升级哪个版本。注意,不要跨版本升级!!!!!
例如目前是4.5 版本要升级到4.5.1就先把镜像版本改成v4.5.1,执行一下升级脚本,等待完成后再继续升级。如果目标版本不需要执行初始化,则可以跳过。
@@ -124,7 +124,7 @@ FastGPT 商业版共包含了2个应用fastgpt, fastgpt-plus和2个数据
![](/imgs/onsealos5.png)
[配置文件参考](https://doc.fastgpt.in/docs/development/configuration/)
[配置文件参考](https://doc.tryfastgpt.ai/docs/development/configuration/)
### 修改站点名称以及 favicon
修改应用的环境变量,增加

View File

@@ -1,5 +1,5 @@
---
title: 'V4.8.10'
title: 'V4.8.10(需要初始化)'
description: 'FastGPT V4.8.10 更新说明'
icon: 'upgrade'
draft: false
@@ -24,8 +24,8 @@ STORE_LOG_LEVEL=warn
### 3. 修改镜像tag
- 更新 FastGPT 镜像 tag: v4.8.10
- 更新 FastGPT 商业版镜像 tag: v4.8.10
- 更新 FastGPT 镜像 tag: v4.8.10-fix2
- 更新 FastGPT 商业版镜像 tag: v4.8.10-fix
- Sandbox 镜像,可以不更新
## 4. 执行初始化

View File

@@ -11,14 +11,98 @@ weight: 813
### 1. 做好数据备份
### 2. 修改配置文件
如需增加 openai o1 模型,可添加如下配置:
```json
{
"model": "o1-mini",
"name": "o1-mini",
"avatar": "/imgs/model/openai.svg",
"maxContext": 125000,
"maxResponse": 4000,
"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,
"stream": false
},
"fieldMap": {
"max_tokens": "max_completion_tokens"
}
},
{
"model": "o1-preview",
"name": "o1-preview",
"avatar": "/imgs/model/openai.svg",
"maxContext": 125000,
"maxResponse": 4000,
"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,
"stream": false
},
"fieldMap": {
"max_tokens": "max_completion_tokens"
}
}
```
-------
## V4.8.11 更新预告
### 3. 修改镜像 tag 并重启
1.
2. 新增 - 工作流循环执行节点。
3. 新增 - 工作流用户表单输入节点。
4. 新增 - 插件输出,支持指定某些字段为工具调用结果。
5. 新增 - 插件支持配置使用引导、全局变量和文件输入
6. 新增 - 简易模式支持新的版本管理方式
7. 新增 - 聊天记录滚动加载,不再只加载 30 条。
## V4.8.11 更新说明
1. 新增 - 表单输入节点,允许用户在工作流中让用户输入一些信息
2. 新增 - 循环运行节点,可传入数组进行批量调用,目前最多支持 50 长度的数组串行执行
3. 新增 - 节点支持折叠。
4. 新增 - 聊天记录滚动加载,不再只加载 30 条。
5. 新增 - 工作流增加触摸板优先模式,可以通过工作流右下角按键进行切换。
6. 新增 - 沙盒增加字符串转 base64 全局方法(全局变量 strToBase64)。
7. 新增 - 支持 Openai o1 模型,需增加模型的 `defaultConfig` 配置,覆盖 `temperature``max_tokens``stream`配置o1 不支持 stream 模式, 详细可重新拉取 `config.json` 配置文件查看。
8. 新增 - AI 对话节点知识库引用,支持配置 role=system 和 role=user已配置的过自定义提示词的节点将会保持 user 模式,其余用户将转成 system 模式。
9. 新增 - 插件支持上传系统文件。
10. 新增 - 插件输出,支持指定字段作为工具响应。
11. 新增 - 支持工作流嵌套子应用时,可以设置`非流模式`,同时简易模式也可以选择工作流作为插件了,简易模式调用子应用时,都将强制使用非流模式。
12. 新增 - 调试模式下,子应用调用,支持返回详细运行数据。
13. 新增 - 保留所有模式下子应用嵌套调用的日志。
14. 优化 - 工作流嵌套层级限制 20 层,避免因编排不合理导致的无限死循环。
15. 优化 - 工作流 handler 性能优化。
16. 优化 - 工作流快捷键,避免调试测试时也会触发复制和回退。
17. 优化 - 流输出,切换浏览器 Tab 后仍可以继续输出。
18. 优化 - 完善外部文件知识库相关 API
19. 修复 - 知识库选择权限问题。
20. 修复 - 空 chatId 发起对话,首轮携带用户选择时会异常。
21. 修复 - createDataset 接口intro 为赋值。
22. 修复 - 对话框渲染性能问题。

View File

@@ -60,6 +60,11 @@ docker-compose up -d
## QA
### 为什么需要初始化
数据表出现大幅度变更,无法通过设置默认值,或复杂度较高时,会通过初始化来更新部分数据表字段。
严格按初始化步骤进行操作,不会造成旧数据丢失。但在初始化过程中,如果数据量大,需要初始化的时间较长,这段时间可能会造成服务无法正常使用。
### {{host}} 是什么
{{}} 代表变量, {{host}}代表一个名为 host 的变量。指的是你服务器的域名或 IP。
@@ -85,4 +90,4 @@ sealos 中可以从上图左侧的环境变量中获取。
4. 修改镜像到4.6,执行初始化
5. .....
逐一升级
逐一升级

View File

@@ -10,7 +10,7 @@ weight: -10
FastGPT 是一个基于 LLM 大语言模型的知识库问答系统,提供开箱即用的数据处理、模型调用等能力。同时可以通过 Flow 可视化进行工作流编排,从而实现复杂的问答场景!
{{% alert icon="🤖 " context="success" %}}
FastGPT 在线使用:[https://fastgpt.in](https://fastgpt.in)
FastGPT 在线使用:[https://tryfastgpt.ai](https://tryfastgpt.ai)
{{% /alert %}}
| | |

View File

@@ -6,7 +6,7 @@ draft: false
toc: true
weight: 1200
type: redirect
target: https://cloud.fastgpt.in/price
target: https://cloud.tryfastgpt.ai/price
---
线上版价格请查看:[https://cloud.fastgpt.in/price](https://cloud.fastgpt.in/price)
线上版价格请查看:[https://cloud.tryfastgpt.ai/price](https://cloud.tryfastgpt.ai/price)

View File

@@ -26,7 +26,7 @@ weight: 504
## 3. 创建 docker-compose.yml 文件
只需要修改 `OPEN_AI_API_KEY``OPEN_AI_API_BASE` 两个环境变量即可。其中 `OPEN_AI_API_KEY` 为第一步获取的密钥,`OPEN_AI_API_BASE` 为 FastGPT 的 OpenAPI 地址,例如:`https://api.fastgpt.in/api/v1`
只需要修改 `OPEN_AI_API_KEY``OPEN_AI_API_BASE` 两个环境变量即可。其中 `OPEN_AI_API_KEY` 为第一步获取的密钥,`OPEN_AI_API_BASE` 为 FastGPT 的 OpenAPI 地址,例如:`https://api.tryfastgpt.ai/api/v1`
随便找一个目录,创建一个 docker-compose.yml 文件,将下面的代码复制进去。
@@ -40,7 +40,7 @@ services:
- seccomp:unconfined
environment:
OPEN_AI_API_KEY: 'fastgpt-z51pkjqm9nrk03a1rx2funoy'
OPEN_AI_API_BASE: 'https://api.fastgpt.in/api/v1'
OPEN_AI_API_BASE: 'https://api.tryfastgpt.ai/api/v1'
MODEL: 'gpt-3.5-turbo'
CHANNEL_TYPE: 'wx'
PROXY: ''

View File

@@ -965,7 +965,7 @@ export default async function (ctx: FunctionContext) {
"required": true,
"description": "",
"canEdit": false,
"value": "请使用下面<data> </data>中的数据作为你的知识。请直接输出答案,不要提及你是从<data> </data>中获取的知识。\n\n当前时间:{{cTime}}\n\n<data>\n{{response}}\n</data>\n\n我的问题:\"{{q}}\"",
"value": "请使用下面<data> </data>中的数据作为本次对话的参考。请直接输出答案,不要提及你是从<data> </data>中获取的知识。\n\n当前时间:{{cTime}}\n\n<data>\n{{response}}\n</data>\n\n我的问题:\"{{q}}\"",
"editField": {
"key": true
},

View File

@@ -70,7 +70,7 @@ HTTP 模块会向对应的地址发送一个 `HTTP` 请求,实际操作与 Pos
"array": [1, 2, 3],
"obj": {
"name": "FastGPT",
"url": "https://fastgpt.in"
"url": "https://tryfastgpt.ai"
}
}
```
@@ -109,7 +109,7 @@ HTTP 模块会向对应的地址发送一个 `HTTP` 请求,实际操作与 Pos
"array2": [1, 2, 3],
"object": {
"name": "FastGPT",
"url": "https://fastgpt.in"
"url": "https://tryfastgpt.ai"
}
}
```

View File

@@ -113,7 +113,7 @@ defaultContentLanguageInSubdir = false
# Link behaviour
intLinkTooltip = true # Enable a tooltip for internal links that displays info about the destination? default false
# extLinkNewTab = false # Open external links in a new Tab? default true
logoLinkURL = "https://fastgpt.in/" # Set a custom URL destination for the top header logo link.
logoLinkURL = "https://tryfastgpt.ai/" # Set a custom URL destination for the top header logo link.
[params.flexsearch] # Parameters for FlexSearch
# enabled = true

View File

View File

@@ -19,7 +19,7 @@ data:
"charsPointsPrice": 0,
"censor": false,
"vision": false,
"datasetProcess": false,
"datasetProcess": true,
"usedInClassify": true,
"usedInExtractFields": true,
"usedInToolCall": true,
@@ -63,7 +63,7 @@ data:
"charsPointsPrice": 0,
"censor": false,
"vision": false,
"datasetProcess": false,
"datasetProcess": true,
"usedInClassify": true,
"usedInExtractFields": true,
"usedInToolCall": true,
@@ -85,7 +85,7 @@ data:
"charsPointsPrice": 0,
"censor": false,
"vision": true,
"datasetProcess": false,
"datasetProcess": true,
"usedInClassify": false,
"usedInExtractFields": false,
"usedInToolCall": false,

View File

@@ -91,6 +91,13 @@ ${mdSplitString}
};
};
/*
1. 自定义分隔符:不需要重叠
2. Markdown 标题:不需要重叠;标题嵌套共享。
3. 特殊 markdown 语法:不需要重叠
4. 段落:尽可能保证它是一个完整的段落。
5. 标点分割:重叠
*/
const commonSplit = (props: SplitProps): SplitResponse => {
let { text = '', chunkLen, overlapRatio = 0.2, customReg = [] } = props;

View File

@@ -34,6 +34,7 @@ export type FastGPTFeConfigsType = {
show_openai_account?: boolean;
show_promotion?: boolean;
show_team_chat?: boolean;
show_compliance_copywriting?: boolean;
concatMd?: string;
docUrl?: string;

View File

@@ -7,3 +7,7 @@ export type RequireOnlyOne<T, Keys extends keyof T = keyof T> = Omit<T, Keys> &
{
[K in Keys]-?: Required<Pick<T, K>> & Partial<Record<Exclude<Keys, K>, undefined>>;
}[Keys];
export type DeepPartial<T> = {
[P in keyof T]?: DeepPartial<T[P]>;
};

View File

@@ -27,6 +27,7 @@ export type LLMModelItemType = {
defaultSystemChatPrompt?: string;
defaultConfig?: Record<string, any>;
fieldMap?: Record<string, string>;
};
export type VectorModelItemType = {

View File

@@ -1,11 +1,16 @@
import { PromptTemplateItem } from '../type.d';
import { i18nT } from '../../../../web/i18n/utils';
export const Prompt_QuoteTemplateList: PromptTemplateItem[] = [
{
title: i18nT('app:template.standard_template'),
desc: i18nT('app:template.standard_template_des'),
value: `{{q}}
{{a}}`
value: `{
"sourceName": "{{source}}",
"updateTime": "{{updateTime}}",
"content": "{{q}}\n{{a}}"
}
`
},
{
title: i18nT('app:template.qa_template'),
@@ -20,8 +25,12 @@ export const Prompt_QuoteTemplateList: PromptTemplateItem[] = [
{
title: i18nT('app:template.standard_strict'),
desc: i18nT('app:template.standard_strict_des'),
value: `{{q}}
{{a}}`
value: `{
"sourceName": "{{source}}",
"updateTime": "{{updateTime}}",
"content": "{{q}}\n{{a}}"
}
`
},
{
title: i18nT('app:template.hard_strict'),
@@ -35,20 +44,20 @@ export const Prompt_QuoteTemplateList: PromptTemplateItem[] = [
}
];
export const Prompt_QuotePromptList: PromptTemplateItem[] = [
export const Prompt_userQuotePromptList: PromptTemplateItem[] = [
{
title: i18nT('app:template.standard_template'),
desc: '',
value: `使用 <Data></Data> 标记中的内容作为你的知识:
value: `使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
<Data>
<Reference>
{{quote}}
</Data>
</Reference>
回答要求:
- 如果你不清楚答案,你需要澄清。
- 避免提及你是从 <Data></Data> 获取的知识。
- 保持答案与 <Data></Data> 中描述的一致。
- 避免提及你是从 <Reference></Reference> 获取的知识。
- 保持答案与 <Reference></Reference> 中描述的一致。
- 使用 Markdown 语法优化回答格式。
- 使用与问题相同的语言回答。
@@ -74,20 +83,20 @@ export const Prompt_QuotePromptList: PromptTemplateItem[] = [
{
title: i18nT('app:template.standard_strict'),
desc: '',
value: `忘记你已有的知识,仅使用 <Data></Data> 标记中的内容作为你的知识:
value: `忘记你已有的知识,仅使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
<Data>
<Reference>
{{quote}}
</Data>
</Reference>
思考流程:
1. 判断问题是否与 <Data></Data> 标记中的内容有关。
1. 判断问题是否与 <Reference></Reference> 标记中的内容有关。
2. 如果有关,你按下面的要求回答。
3. 如果无关,你直接拒绝回答本次问题。
回答要求:
- 避免提及你是从 <Data></Data> 获取的知识。
- 保持答案与 <Data></Data> 中描述的一致。
- 避免提及你是从 <Reference></Reference> 获取的知识。
- 保持答案与 <Reference></Reference> 中描述的一致。
- 使用 Markdown 语法优化回答格式。
- 使用与问题相同的语言回答。
@@ -120,9 +129,86 @@ export const Prompt_QuotePromptList: PromptTemplateItem[] = [
}
];
// Document quote prompt
export const Prompt_DocumentQuote = `将 <Quote></Quote> 中的内容作为你的知识:
<Quote>
export const Prompt_systemQuotePromptList: PromptTemplateItem[] = [
{
title: i18nT('app:template.standard_template'),
desc: '',
value: `使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
<Reference>
{{quote}}
</Quote>
</Reference>
回答要求:
- 如果你不清楚答案,你需要澄清。
- 避免提及你是从 <Reference></Reference> 获取的知识。
- 保持答案与 <Reference></Reference> 中描述的一致。
- 使用 Markdown 语法优化回答格式。
- 使用与问题相同的语言回答。`
},
{
title: i18nT('app:template.qa_template'),
desc: '',
value: `使用 <QA></QA> 标记中的问答对进行回答。
<QA>
{{quote}}
</QA>
回答要求:
- 选择其中一个或多个问答对进行回答。
- 回答的内容应尽可能与 <答案></答案> 中的内容一致。
- 如果没有相关的问答对,你需要澄清。
- 避免提及你是从 QA 获取的知识,只需要回复答案。`
},
{
title: i18nT('app:template.standard_strict'),
desc: '',
value: `忘记你已有的知识,仅使用 <Reference></Reference> 标记中的内容作为本次对话的参考:
<Reference>
{{quote}}
</Reference>
思考流程:
1. 判断问题是否与 <Reference></Reference> 标记中的内容有关。
2. 如果有关,你按下面的要求回答。
3. 如果无关,你直接拒绝回答本次问题。
回答要求:
- 避免提及你是从 <Reference></Reference> 获取的知识。
- 保持答案与 <Reference></Reference> 中描述的一致。
- 使用 Markdown 语法优化回答格式。
- 使用与问题相同的语言回答。`
},
{
title: i18nT('app:template.hard_strict'),
desc: '',
value: `忘记你已有的知识,仅使用 <QA></QA> 标记中的问答对进行回答。
<QA>
{{quote}}
</QA>
思考流程:
1. 判断问题是否与 <QA></QA> 标记中的内容有关。
2. 如果无关,你直接拒绝回答本次问题。
3. 判断是否有相近或相同的问题。
4. 如果有相同的问题,直接输出对应答案。
5. 如果只有相近的问题,请把相近的问题和答案一起输出。
回答要求:
- 如果没有相关的问答对,你需要澄清。
- 回答的内容应尽可能与 <QA></QA> 标记中的内容一致。
- 避免提及你是从 QA 获取的知识,只需要回复答案。
- 使用 Markdown 语法优化回答格式。
- 使用与问题相同的语言回答。`
}
];
// Document quote prompt
export const Prompt_DocumentQuote = `将 <Reference></Reference> 中的内容作为本次对话的参考:
<Reference>
{{quote}}
</Reference>
`;

View File

@@ -9,8 +9,7 @@ import type {
ChatCompletionUserMessageParam as SdkChatCompletionUserMessageParam
} from 'openai/resources';
import { ChatMessageTypeEnum } from './constants';
import { InteractiveNodeResponseItemType } from '../workflow/template/system/userSelect/type';
import { InteractiveNodeResponseItemType } from '../workflow/template/system/interactive/type';
export * from 'openai/resources';
// Extension of ChatCompletionMessageParam, Add file url type

View File

@@ -97,7 +97,10 @@ export const appWorkflow2Form = ({
node.inputs,
NodeInputKeyEnum.datasetSearchExtensionBg
);
} else if (node.flowNodeType === FlowNodeTypeEnum.pluginModule) {
} else if (
node.flowNodeType === FlowNodeTypeEnum.pluginModule ||
node.flowNodeType === FlowNodeTypeEnum.appModule
) {
if (!node.pluginId) return;
defaultAppForm.selectedTools.push({
@@ -108,7 +111,7 @@ export const appWorkflow2Form = ({
intro: node.intro || '',
flowNodeType: node.flowNodeType,
showStatus: node.showStatus,
version: '481',
version: node.version,
inputs: node.inputs,
outputs: node.outputs,
templateType: FlowNodeTemplateTypeEnum.other

View File

@@ -12,3 +12,12 @@ export type AppVersionSchemaType = {
versionName: string;
tmbId: string;
};
export type VersionListItemType = {
_id: string;
appId: string;
versionName: string;
time: Date;
isPublish: boolean | undefined;
tmbId: string;
};

View File

@@ -344,7 +344,7 @@ export const runtimePrompt2ChatsValue = (
return value;
};
export const getSystemPrompt = (prompt?: string): ChatItemType[] => {
export const getSystemPrompt_ChatItemType = (prompt?: string): ChatItemType[] => {
if (!prompt) return [];
return [
{

View File

@@ -15,7 +15,7 @@ import type { AppSchema as AppType } from '@fastgpt/global/core/app/type.d';
import { DatasetSearchModeEnum } from '../dataset/constants';
import { DispatchNodeResponseType } from '../workflow/runtime/type.d';
import { ChatBoxInputType } from '../../../../projects/app/src/components/core/chat/ChatContainer/ChatBox/type';
import { InteractiveNodeResponseItemType } from '../workflow/template/system/userSelect/type';
import { InteractiveNodeResponseItemType } from '../workflow/template/system/interactive/type';
export type ChatSchema = {
_id: string;

View File

@@ -178,6 +178,7 @@ export type DatasetDataItemType = {
id: string;
teamId: string;
datasetId: string;
updateTime: Date;
collectionId: string;
sourceName: string;
sourceId?: string;

View File

@@ -24,6 +24,7 @@ export enum WorkflowIOValueTypeEnum {
arrayNumber = 'arrayNumber',
arrayBoolean = 'arrayBoolean',
arrayObject = 'arrayObject',
arrayAny = 'arrayAny',
any = 'any',
chatHistory = 'chatHistory',
@@ -69,6 +70,7 @@ export enum NodeInputKeyEnum {
anyInput = 'system_anyInput',
textareaInput = 'system_textareaInput',
addInputParam = 'system_addInputParam',
forbidStream = 'system_forbid_stream',
// history
historyMaxAmount = 'maxContext',
@@ -78,6 +80,7 @@ export enum NodeInputKeyEnum {
aiChatMaxToken = 'maxToken',
aiChatSettingModal = 'aiSettings',
aiChatIsResponseText = 'isResponseAnswerText',
aiChatQuoteRole = 'aiChatQuoteRole',
aiChatQuoteTemplate = 'quoteTemplate',
aiChatQuotePrompt = 'quotePrompt',
aiChatDatasetQuote = 'quoteQA',
@@ -135,7 +138,20 @@ export enum NodeInputKeyEnum {
fileUrlList = 'fileUrlList',
// user select
userSelectOptions = 'userSelectOptions'
userSelectOptions = 'userSelectOptions',
// loop
loopInputArray = 'loopInputArray',
childrenNodeIdList = 'childrenNodeIdList',
nodeWidth = 'nodeWidth',
nodeHeight = 'nodeHeight',
// loop start
loopStartInput = 'loopStartInput',
// loop end
loopEndInput = 'loopEndInput',
// form input
userInputForms = 'userInputForms'
}
export enum NodeOutputKeyEnum {
@@ -178,7 +194,16 @@ export enum NodeOutputKeyEnum {
ifElseResult = 'ifElseResult',
//user select
selectResult = 'selectResult'
selectResult = 'selectResult',
// loop
loopArray = 'loopArray',
// loop start
loopStartInput = 'loopStartInput',
// form input
formInputResult = 'formInputResult'
}
export enum VariableInputEnum {

View File

@@ -125,7 +125,11 @@ export enum FlowNodeTypeEnum {
textEditor = 'textEditor',
customFeedback = 'customFeedback',
readFiles = 'readFiles',
userSelect = 'userSelect'
userSelect = 'userSelect',
loop = 'loop',
loopStart = 'loopStart',
loopEnd = 'loopEnd',
formInput = 'formInput'
}
// node IO value type
@@ -162,6 +166,10 @@ export const FlowValueTypeMap = {
label: 'array<object>',
value: WorkflowIOValueTypeEnum.arrayObject
},
[WorkflowIOValueTypeEnum.arrayAny]: {
label: 'array',
value: WorkflowIOValueTypeEnum.arrayAny
},
[WorkflowIOValueTypeEnum.any]: {
label: 'any',
value: WorkflowIOValueTypeEnum.any

View File

@@ -24,7 +24,8 @@ export enum DispatchNodeResponseKeyEnum {
assistantResponses = 'assistantResponses', // assistant response
rewriteHistories = 'rewriteHistories', // If have the response, workflow histories will be rewrite
interactive = 'INTERACTIVE' // is interactive
interactive = 'INTERACTIVE', // is interactive
runTimes = 'runTimes' // run times
}
export const needReplaceReferenceInputTypeList = [

View File

@@ -20,6 +20,7 @@ import { RuntimeEdgeItemType } from './edge';
import { ReadFileNodeResponse } from '../template/system/readFiles/type';
import { UserSelectOptionType } from '../template/system/userSelect/type';
import { WorkflowResponseType } from '../../../../service/core/workflow/dispatch/type';
import { AiChatQuoteRoleType } from '../template/system/aiChat/type';
/* workflow props */
export type ChatDispatchProps = {
@@ -45,6 +46,7 @@ export type ChatDispatchProps = {
maxRunTimes: number;
isToolCall?: boolean;
workflowStreamResponse?: WorkflowResponseType;
workflowDispatchDeep?: number;
};
export type ModuleDispatchProps<T> = ChatDispatchProps & {
@@ -171,6 +173,18 @@ export type DispatchNodeResponseType = {
// update var
updateVarResult?: any[];
// loop
loopResult?: any[];
loopInput?: any[];
loopDetail?: ChatHistoryItemResType[];
// loop start
loopInputValue?: any;
// loop end
loopOutputValue?: any;
// form input
formInputResult?: string;
};
export type DispatchNodeResultType<T = {}> = {
@@ -181,6 +195,7 @@ export type DispatchNodeResultType<T = {}> = {
[DispatchNodeResponseKeyEnum.toolResponses]?: ToolRunResponseItemType; // Tool response
[DispatchNodeResponseKeyEnum.assistantResponses]?: AIChatItemValueItemType[]; // Assistant response(Store to db)
[DispatchNodeResponseKeyEnum.rewriteHistories]?: ChatItemType[];
[DispatchNodeResponseKeyEnum.runTimes]?: number;
} & T;
/* Single node props */
@@ -190,6 +205,7 @@ export type AIChatNodeProps = {
[NodeInputKeyEnum.aiChatTemperature]: number;
[NodeInputKeyEnum.aiChatMaxToken]: number;
[NodeInputKeyEnum.aiChatIsResponseText]: boolean;
[NodeInputKeyEnum.aiChatQuoteRole]?: AiChatQuoteRoleType;
[NodeInputKeyEnum.aiChatQuoteTemplate]?: string;
[NodeInputKeyEnum.aiChatQuotePrompt]?: string;
[NodeInputKeyEnum.aiChatVision]?: boolean;

View File

@@ -54,6 +54,11 @@ export const getLastInteractiveValue = (histories: ChatItemType[]) => {
) {
return lastValue.interactive;
}
// Check is user input
if (lastValue.interactive.type === 'userInput' && !lastValue.interactive.params.submitted) {
return lastValue.interactive;
}
}
return null;

View File

@@ -27,8 +27,12 @@ import { VariableUpdateNode } from './system/variableUpdate';
import { CodeNode } from './system/sandbox';
import { TextEditorNode } from './system/textEditor';
import { CustomFeedbackNode } from './system/customFeedback';
import { ReadFilesNodes } from './system/readFiles';
import { UserSelectNode } from './system/userSelect/index';
import { ReadFilesNode } from './system/readFiles';
import { UserSelectNode } from './system/interactive/userSelect';
import { LoopNode } from './system/loop/loop';
import { LoopStartNode } from './system/loop/loopStart';
import { LoopEndNode } from './system/loop/loopEnd';
import { FormInputNode } from './system/interactive/formInput';
const systemNodes: FlowNodeTemplateType[] = [
AiChatModule,
@@ -40,13 +44,14 @@ const systemNodes: FlowNodeTemplateType[] = [
StopToolNode,
ClassifyQuestionModule,
ContextExtractModule,
ReadFilesNodes,
ReadFilesNode,
HttpNode468,
AiQueryExtension,
LafModule,
IfElseNode,
VariableUpdateNode,
CodeNode
CodeNode,
LoopNode
];
/* app flow module templates */
export const appSystemModuleTemplates: FlowNodeTemplateType[] = [
@@ -54,7 +59,8 @@ export const appSystemModuleTemplates: FlowNodeTemplateType[] = [
WorkflowStart,
...systemNodes,
CustomFeedbackNode,
UserSelectNode
UserSelectNode,
FormInputNode
];
/* plugin flow module templates */
export const pluginSystemModuleTemplates: FlowNodeTemplateType[] = [
@@ -74,5 +80,7 @@ export const moduleTemplatesFlat: FlowNodeTemplateType[] = [
EmptyNode,
RunPluginModule,
RunAppNode,
RunAppModule
RunAppModule,
LoopStartNode,
LoopEndNode
];

View File

@@ -23,6 +23,7 @@ export const Input_Template_UserChatInput: FlowNodeInputItemType = {
renderTypeList: [FlowNodeInputTypeEnum.reference, FlowNodeInputTypeEnum.textarea],
valueType: WorkflowIOValueTypeEnum.string,
label: i18nT('workflow:user_question'),
toolDescription: i18nT('workflow:user_question_tool_desc'),
required: true
};
@@ -83,3 +84,34 @@ export const Input_Template_File_Link: FlowNodeInputItemType = {
description: i18nT('app:workflow.user_file_input_desc'),
valueType: WorkflowIOValueTypeEnum.arrayString
};
export const Input_Template_Children_Node_List: FlowNodeInputItemType = {
key: NodeInputKeyEnum.childrenNodeIdList,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.arrayString,
label: '',
value: []
};
export const Input_Template_Node_Width: FlowNodeInputItemType = {
key: NodeInputKeyEnum.nodeWidth,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.number,
label: '',
value: 900
};
export const Input_Template_Node_Height: FlowNodeInputItemType = {
key: NodeInputKeyEnum.nodeHeight,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.number,
label: '',
value: 900
};
export const Input_Template_Stream_MODE: FlowNodeInputItemType = {
key: NodeInputKeyEnum.forbidStream,
renderTypeList: [FlowNodeInputTypeEnum.switch],
valueType: WorkflowIOValueTypeEnum.boolean,
label: i18nT('workflow:template.forbid_stream'),
description: i18nT('workflow:template.forbid_stream_desc'),
value: false
};

View File

@@ -3,14 +3,14 @@ import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/node';
} from '../../../node/constant';
import { FlowNodeTemplateType } from '../../../type/node';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
} from '../../../constants';
import {
Input_Template_SettingAiModel,
Input_Template_Dataset_Quote,
@@ -18,10 +18,30 @@ import {
Input_Template_System_Prompt,
Input_Template_UserChatInput,
Input_Template_Text_Quote
} from '../input';
import { chatNodeSystemPromptTip } from '../tip';
import { getHandleConfig } from '../utils';
import { i18nT } from '../../../../../web/i18n/utils';
} from '../../input';
import { chatNodeSystemPromptTip } from '../../tip';
import { getHandleConfig } from '../../utils';
import { i18nT } from '../../../../../../web/i18n/utils';
export const AiChatQuoteRole = {
key: NodeInputKeyEnum.aiChatQuoteRole,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string,
value: 'system' // user or system
};
export const AiChatQuoteTemplate = {
key: NodeInputKeyEnum.aiChatQuoteTemplate,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string
};
export const AiChatQuotePrompt = {
key: NodeInputKeyEnum.aiChatQuotePrompt,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string
};
export const AiChatModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.chatNode,
@@ -52,6 +72,7 @@ export const AiChatModule: FlowNodeTemplateType = {
value: 2000,
valueType: WorkflowIOValueTypeEnum.number
},
{
key: NodeInputKeyEnum.aiChatIsResponseText,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
@@ -59,18 +80,9 @@ export const AiChatModule: FlowNodeTemplateType = {
value: true,
valueType: WorkflowIOValueTypeEnum.boolean
},
{
key: NodeInputKeyEnum.aiChatQuoteTemplate,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string
},
{
key: NodeInputKeyEnum.aiChatQuotePrompt,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
label: '',
valueType: WorkflowIOValueTypeEnum.string
},
AiChatQuoteRole,
AiChatQuoteTemplate,
AiChatQuotePrompt,
{
key: NodeInputKeyEnum.aiChatVision,
renderTypeList: [FlowNodeInputTypeEnum.hidden],

View File

@@ -0,0 +1 @@
export type AiChatQuoteRoleType = 'user' | 'system';

View File

@@ -0,0 +1,55 @@
import { i18nT } from '../../../../../../web/i18n/utils';
import {
FlowNodeTemplateTypeEnum,
NodeInputKeyEnum,
NodeOutputKeyEnum,
WorkflowIOValueTypeEnum
} from '../../../constants';
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../../node/constant';
import { FlowNodeTemplateType } from '../../../type/node';
import { getHandleConfig } from '../../utils';
export const FormInputNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.formInput,
templateType: FlowNodeTemplateTypeEnum.interactive,
flowNodeType: FlowNodeTypeEnum.formInput,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
avatar: 'core/workflow/template/formInput',
name: i18nT('app:workflow.form_input'),
intro: i18nT(`app:workflow.form_input_tip`),
showStatus: true,
version: '4811',
inputs: [
{
key: NodeInputKeyEnum.description,
renderTypeList: [FlowNodeInputTypeEnum.textarea],
valueType: WorkflowIOValueTypeEnum.string,
label: i18nT('app:workflow.select_description'),
description: i18nT('app:workflow.input_description_tip'),
placeholder: i18nT('app:workflow.form_input_description_placeholder')
},
{
key: NodeInputKeyEnum.userInputForms,
renderTypeList: [FlowNodeInputTypeEnum.custom],
valueType: WorkflowIOValueTypeEnum.any,
label: '',
value: []
}
],
outputs: [
{
id: NodeOutputKeyEnum.formInputResult,
key: NodeOutputKeyEnum.formInputResult,
required: true,
label: i18nT('workflow:form_input_result'),
description: i18nT('workflow:form_input_result_tip'),
valueType: WorkflowIOValueTypeEnum.object,
type: FlowNodeOutputTypeEnum.static
}
]
};

View File

@@ -0,0 +1,56 @@
import { NodeOutputItemType } from '../../../../chat/type';
import { FlowNodeOutputItemType } from '../../../type/io';
import { RuntimeEdgeItemType } from '../../../runtime/type';
import { FlowNodeInputTypeEnum } from 'core/workflow/node/constant';
import { WorkflowIOValueTypeEnum } from 'core/workflow/constants';
export type UserSelectOptionItemType = {
key: string;
value: string;
};
export type UserInputFormItemType = {
type: FlowNodeInputTypeEnum;
key: string;
label: string;
value: any;
valueType: WorkflowIOValueTypeEnum;
description?: string;
defaultValue?: any;
required: boolean;
// input & textarea
maxLength?: number;
// numberInput
max?: number;
min?: number;
// select
list?: { label: string; value: string }[];
};
type InteractiveBasicType = {
entryNodeIds: string[];
memoryEdges: RuntimeEdgeItemType[];
nodeOutputs: NodeOutputItemType[];
};
type UserSelectInteractive = {
type: 'userSelect';
params: {
description: string;
userSelectOptions: UserSelectOptionItemType[];
userSelectedVal?: string;
};
};
type UserInputInteractive = {
type: 'userInput';
params: {
description: string;
inputForm: UserInputFormItemType[];
submitted?: boolean;
};
};
export type InteractiveNodeResponseItemType = InteractiveBasicType &
(UserSelectInteractive | UserInputInteractive);

View File

@@ -0,0 +1,54 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../../node/constant';
import { FlowNodeTemplateType } from '../../../type/node';
import {
FlowNodeTemplateTypeEnum,
NodeInputKeyEnum,
NodeOutputKeyEnum,
WorkflowIOValueTypeEnum
} from '../../../constants';
import { getHandleConfig } from '../../utils';
import { i18nT } from '../../../../../../web/i18n/utils';
import {
Input_Template_Children_Node_List,
Input_Template_Node_Height,
Input_Template_Node_Width
} from '../../input';
export const LoopNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.loop,
templateType: FlowNodeTemplateTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.loop,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
avatar: 'core/workflow/template/loop',
name: i18nT('workflow:loop'),
intro: i18nT('workflow:intro_loop'),
showStatus: true,
version: '4811',
inputs: [
{
key: NodeInputKeyEnum.loopInputArray,
renderTypeList: [FlowNodeInputTypeEnum.reference],
valueType: WorkflowIOValueTypeEnum.arrayAny,
required: true,
label: i18nT('workflow:loop_input_array'),
value: []
},
Input_Template_Children_Node_List,
Input_Template_Node_Width,
Input_Template_Node_Height
],
outputs: [
{
id: NodeOutputKeyEnum.loopArray,
key: NodeOutputKeyEnum.loopArray,
label: i18nT('workflow:loop_result'),
type: FlowNodeOutputTypeEnum.static,
valueType: WorkflowIOValueTypeEnum.arrayAny
}
]
};

View File

@@ -0,0 +1,34 @@
import { i18nT } from '../../../../../../web/i18n/utils';
import {
FlowNodeTemplateTypeEnum,
NodeInputKeyEnum,
WorkflowIOValueTypeEnum
} from '../../../constants';
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '../../../node/constant';
import { FlowNodeTemplateType } from '../../../type/node';
import { getHandleConfig } from '../../utils';
export const LoopEndNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.loopEnd,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowNodeType: FlowNodeTypeEnum.loopEnd,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(false, false, false, true),
unique: true,
forbidDelete: true,
avatar: 'core/workflow/template/loopEnd',
name: i18nT('workflow:loop_end'),
showStatus: false,
version: '4811',
inputs: [
{
key: NodeInputKeyEnum.loopEndInput,
renderTypeList: [FlowNodeInputTypeEnum.reference],
valueType: WorkflowIOValueTypeEnum.any,
label: '',
required: true,
value: []
}
],
outputs: []
};

View File

@@ -0,0 +1,34 @@
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '../../../node/constant';
import { FlowNodeTemplateType } from '../../../type/node.d';
import {
FlowNodeTemplateTypeEnum,
NodeInputKeyEnum,
WorkflowIOValueTypeEnum
} from '../../../constants';
import { getHandleConfig } from '../../utils';
import { i18nT } from '../../../../../../web/i18n/utils';
export const LoopStartNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.loopStart,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowNodeType: FlowNodeTypeEnum.loopStart,
sourceHandle: getHandleConfig(false, true, false, false),
targetHandle: getHandleConfig(false, false, false, false),
avatar: 'core/workflow/template/loopStart',
name: i18nT('workflow:loop_start'),
unique: true,
forbidDelete: true,
showStatus: false,
version: '4811',
inputs: [
{
key: NodeInputKeyEnum.loopStartInput,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
valueType: WorkflowIOValueTypeEnum.any,
label: '',
required: true,
value: ''
}
],
outputs: []
};

View File

@@ -13,7 +13,7 @@ export const PluginOutputModule: FlowNodeTemplateType = {
unique: true,
forbidDelete: true,
avatar: 'core/workflow/template/pluginOutput',
name: i18nT('workflow:custom_plugin_output'),
name: i18nT('workflow:template.plugin_output'),
intro: i18nT('workflow:intro_custom_plugin_output'),
showStatus: false,
version: '481',

View File

@@ -13,7 +13,7 @@ import {
import { FlowNodeTemplateType } from '../../../type/node';
import { getHandleConfig } from '../../utils';
export const ReadFilesNodes: FlowNodeTemplateType = {
export const ReadFilesNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.readFiles,
templateType: FlowNodeTemplateTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.readFiles,

View File

@@ -1,24 +0,0 @@
import { NodeOutputItemType } from '../../../../chat/type';
import { FlowNodeOutputItemType } from '../../../type/io';
import { RuntimeEdgeItemType } from '../../../runtime/type';
export type UserSelectOptionItemType = {
key: string;
value: string;
};
type InteractiveBasicType = {
entryNodeIds: string[];
memoryEdges: RuntimeEdgeItemType[];
nodeOutputs: NodeOutputItemType[];
};
type UserSelectInteractive = {
type: 'userSelect';
params: {
description: string;
userSelectOptions: UserSelectOptionItemType[];
userSelectedVal?: string;
};
};
export type InteractiveNodeResponseItemType = InteractiveBasicType & UserSelectInteractive;

View File

@@ -54,6 +54,7 @@ export type FlowNodeInputItemType = InputComponentPropsType & {
// render components params
canEdit?: boolean; // dynamic inputs
isPro?: boolean; // Pro version field
isToolOutput?: boolean;
};
export type FlowNodeOutputItemType = {

View File

@@ -95,6 +95,7 @@ export type NodeTemplateListType = {
// react flow node type
export type FlowNodeItemType = FlowNodeTemplateType & {
nodeId: string;
parentNodeId?: string;
isError?: boolean;
debugResult?: {
status: 'running' | 'success' | 'skipped' | 'failed';
@@ -103,6 +104,7 @@ export type FlowNodeItemType = FlowNodeTemplateType & {
response?: ChatHistoryItemResType;
isExpired?: boolean;
};
isFolded?: boolean;
};
// store node type

View File

@@ -31,8 +31,17 @@ import {
import { IfElseResultEnum } from './template/system/ifElse/constant';
import { RuntimeNodeItemType } from './runtime/type';
import { getReferenceVariableValue } from './runtime/utils';
import { Input_Template_History, Input_Template_UserChatInput } from './template/input';
import {
Input_Template_History,
Input_Template_Stream_MODE,
Input_Template_UserChatInput
} from './template/input';
import { i18nT } from '../../../web/i18n/utils';
import { RuntimeUserPromptType, UserChatItemType } from '../../core/chat/type';
import { getNanoid } from '../../common/string/tools';
import { ChatRoleEnum } from '../../core/chat/constants';
import { runtimePrompt2ChatsValue } from '../../core/chat/adapt';
import { getPluginRunContent } from '../../core/app/plugin/utils';
export const getHandleId = (nodeId: string, type: 'source' | 'target', key: string) => {
return `${nodeId}-${type}-${key}`;
@@ -174,17 +183,21 @@ export const pluginData2FlowNodeIO = ({
const pluginOutput = nodes.find((node) => node.flowNodeType === FlowNodeTypeEnum.pluginOutput);
return {
inputs:
pluginInput?.inputs.map((item) => ({
...item,
...getModuleInputUiField(item),
value: getOrInitModuleInputValue(item),
canEdit: false,
renderTypeList:
item.renderTypeList[0] === FlowNodeInputTypeEnum.customVariable
? [FlowNodeInputTypeEnum.reference, FlowNodeInputTypeEnum.input]
: item.renderTypeList
})) || [],
inputs: pluginInput
? [
Input_Template_Stream_MODE,
...pluginInput?.inputs.map((item) => ({
...item,
...getModuleInputUiField(item),
value: getOrInitModuleInputValue(item),
canEdit: false,
renderTypeList:
item.renderTypeList[0] === FlowNodeInputTypeEnum.customVariable
? [FlowNodeInputTypeEnum.reference, FlowNodeInputTypeEnum.input]
: item.renderTypeList
}))
]
: [],
outputs: pluginOutput
? [
...pluginOutput.inputs.map((item) => ({
@@ -245,6 +258,7 @@ export const appData2FlowNodeIO = ({
return {
inputs: [
Input_Template_Stream_MODE,
Input_Template_History,
Input_Template_UserChatInput,
// ...(showFileLink ? [Input_Template_File_Link] : []),
@@ -395,3 +409,26 @@ export function replaceEditorVariable({
}
return text || '';
}
/* Get plugin runtime input user query */
export const getPluginRunUserQuery = ({
pluginInputs,
variables,
files = []
}: {
pluginInputs: FlowNodeInputItemType[];
variables: Record<string, any>;
files?: RuntimeUserPromptType['files'];
}): UserChatItemType & { dataId: string } => {
return {
dataId: getNanoid(24),
obj: ChatRoleEnum.Human,
value: runtimePrompt2ChatsValue({
text: getPluginRunContent({
pluginInputs: pluginInputs,
variables
}),
files
})
};
};

View File

@@ -11,7 +11,7 @@
"jschardet": "3.1.1",
"nanoid": "^4.0.1",
"next": "14.2.5",
"openai": "4.57.0",
"openai": "4.61.0",
"openapi-types": "^12.1.3",
"timezones-list": "^3.0.2"
},

View File

@@ -13,16 +13,30 @@
"workflow": {
"nodes": [
{
"nodeId": "pluginConfig",
"name": "common:core.module.template.system_config",
"intro": "",
"avatar": "core/workflow/template/systemConfig",
"flowNodeType": "pluginConfig",
"position": {
"x": -90.53591960393504,
"y": -17.580286776561252
},
"version": "4811",
"inputs": [],
"outputs": []
},
{
"nodeId": "pluginInput",
"name": "自定义插件输入",
"name": "插件开始",
"intro": "可以配置插件需要哪些输入,利用这些输入来运行插件",
"avatar": "core/workflow/template/workflowStart",
"flowNodeType": "pluginInput",
"showStatus": false,
"position": {
"x": 362.9862638626885,
"y": 6.16353826540589
"x": 368.6800424053505,
"y": -17.580286776561252
},
"version": "481",
"inputs": [
@@ -107,14 +121,14 @@
},
{
"nodeId": "pluginOutput",
"name": "自定义插件输出",
"name": "插件输出",
"intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出",
"avatar": "core/workflow/template/pluginOutput",
"flowNodeType": "pluginOutput",
"showStatus": false,
"position": {
"x": 1661.4708279314577,
"y": 23.877720915480012
"x": 1796.2235867744578,
"y": 6.419713223438748
},
"version": "481",
"inputs": [
@@ -167,7 +181,7 @@
"valueType": "dynamic",
"label": "",
"required": false,
"description": "core.module.input.description.HTTP Dynamic Input",
"description": "common:core.module.input.description.HTTP Dynamic Input",
"customInputConfig": {
"selectValueTypeList": [
"string",
@@ -178,6 +192,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -187,7 +202,9 @@
],
"showDescription": false,
"showDefaultValue": true
}
},
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpMethod",
@@ -195,17 +212,33 @@
"valueType": "string",
"label": "",
"value": "POST",
"required": true
"required": true,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpTimeout",
"renderTypeList": ["custom"],
"valueType": "number",
"label": "",
"value": 30,
"min": 5,
"max": 600,
"required": true,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpReqUrl",
"renderTypeList": ["hidden"],
"valueType": "string",
"label": "",
"description": "core.module.input.description.Http Request Url",
"description": "common:core.module.input.description.Http Request Url",
"placeholder": "https://api.ai.com/getInventory",
"required": false,
"value": "Doc2X/FileImg2text"
"value": "Doc2X/FileImg2text",
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpHeader",
@@ -213,9 +246,11 @@
"valueType": "any",
"value": [],
"label": "",
"description": "core.module.input.description.Http Request Header",
"placeholder": "core.module.input.description.Http Request Header",
"required": false
"description": "common:core.module.input.description.Http Request Header",
"placeholder": "common:core.module.input.description.Http Request Header",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpParams",
@@ -223,7 +258,9 @@
"valueType": "any",
"value": [],
"label": "",
"required": false
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpJsonBody",
@@ -231,7 +268,29 @@
"valueType": "any",
"value": "{\n \"apikey\": \"{{apikey}}\",\n \"files\": {{files}},\n \"img_correction\": {{img_correction}},\n \"formula\": {{formula}}\n}",
"label": "",
"required": false
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpFormBody",
"renderTypeList": ["hidden"],
"valueType": "any",
"value": [],
"label": "",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpContentType",
"renderTypeList": ["hidden"],
"valueType": "string",
"value": "json",
"label": "",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"renderTypeList": ["reference"],
@@ -249,6 +308,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -278,6 +338,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -307,6 +368,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -336,6 +398,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -354,7 +417,7 @@
{
"id": "error",
"key": "error",
"label": "请求错误",
"label": "workflow:request_error",
"description": "HTTP请求错误信息成功时返回空",
"valueType": "object",
"type": "static"
@@ -362,8 +425,8 @@
{
"id": "httpRawResponse",
"key": "httpRawResponse",
"label": "原始响应",
"required": true,
"label": "workflow:raw_response",
"description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。",
"valueType": "any",
"type": "static"

View File

@@ -13,16 +13,30 @@
"workflow": {
"nodes": [
{
"nodeId": "pluginConfig",
"name": "common:core.module.template.system_config",
"intro": "",
"avatar": "core/workflow/template/systemConfig",
"flowNodeType": "pluginConfig",
"position": {
"x": -30.474351356537454,
"y": -101.45216221730038
},
"version": "4811",
"inputs": [],
"outputs": []
},
{
"nodeId": "pluginInput",
"name": "自定义插件输入",
"name": "插件开始",
"intro": "可以配置插件需要哪些输入,利用这些输入来运行插件",
"avatar": "core/workflow/template/workflowStart",
"flowNodeType": "pluginInput",
"showStatus": false,
"position": {
"x": 388.243055058894,
"y": -75.09744210499466
"x": 407.2817920483865,
"y": -101.45216221730038
},
"version": "481",
"inputs": [
@@ -88,14 +102,14 @@
},
{
"nodeId": "pluginOutput",
"name": "自定义插件输出",
"name": "插件输出",
"intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出",
"avatar": "core/workflow/template/pluginOutput",
"flowNodeType": "pluginOutput",
"showStatus": false,
"position": {
"x": 1649.7796447278438,
"y": -96.05331527115042
"x": 1842.070888321717,
"y": -101.45216221730038
},
"version": "481",
"inputs": [
@@ -148,7 +162,7 @@
"valueType": "dynamic",
"label": "",
"required": false,
"description": "core.module.input.description.HTTP Dynamic Input",
"description": "common:core.module.input.description.HTTP Dynamic Input",
"customInputConfig": {
"selectValueTypeList": [
"string",
@@ -159,6 +173,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -168,7 +183,9 @@
],
"showDescription": false,
"showDefaultValue": true
}
},
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpMethod",
@@ -176,17 +193,33 @@
"valueType": "string",
"label": "",
"value": "POST",
"required": true
"required": true,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpTimeout",
"renderTypeList": ["custom"],
"valueType": "number",
"label": "",
"value": 30,
"min": 5,
"max": 600,
"required": true,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpReqUrl",
"renderTypeList": ["hidden"],
"valueType": "string",
"label": "",
"description": "core.module.input.description.Http Request Url",
"description": "common:core.module.input.description.Http Request Url",
"placeholder": "https://api.ai.com/getInventory",
"required": false,
"value": "Doc2X/FilePDF2text"
"value": "Doc2X/FilePDF2text",
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpHeader",
@@ -194,9 +227,11 @@
"valueType": "any",
"value": [],
"label": "",
"description": "core.module.input.description.Http Request Header",
"placeholder": "core.module.input.description.Http Request Header",
"required": false
"description": "common:core.module.input.description.Http Request Header",
"placeholder": "common:core.module.input.description.Http Request Header",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpParams",
@@ -204,7 +239,9 @@
"valueType": "any",
"value": [],
"label": "",
"required": false
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpJsonBody",
@@ -212,7 +249,29 @@
"valueType": "any",
"value": "{\n \"apikey\": \"{{apikey}}\",\n \"files\": {{files}},\n \"ocr\": {{ocr}}\n}",
"label": "",
"required": false
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpFormBody",
"renderTypeList": ["hidden"],
"valueType": "any",
"value": [],
"label": "",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpContentType",
"renderTypeList": ["hidden"],
"valueType": "string",
"value": "json",
"label": "",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"renderTypeList": ["reference"],
@@ -230,6 +289,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -259,6 +319,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -288,6 +349,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -306,7 +368,7 @@
{
"id": "error",
"key": "error",
"label": "请求错误",
"label": "workflow:request_error",
"description": "HTTP请求错误信息成功时返回空",
"valueType": "object",
"type": "static"
@@ -314,8 +376,8 @@
{
"id": "httpRawResponse",
"key": "httpRawResponse",
"label": "原始响应",
"required": true,
"label": "workflow:raw_response",
"description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。",
"valueType": "any",
"type": "static"

View File

@@ -15,13 +15,13 @@
"nodes": [
{
"nodeId": "pluginInput",
"name": "自定义插件输入",
"name": "插件开始",
"intro": "可以配置插件需要哪些输入,利用这些输入来运行插件",
"avatar": "core/workflow/template/workflowStart",
"flowNodeType": "pluginInput",
"showStatus": false,
"position": {
"x": 388.243055058894,
"x": 353.91678143999377,
"y": -75.09744210499466
},
"version": "481",
@@ -107,14 +107,14 @@
},
{
"nodeId": "pluginOutput",
"name": "自定义插件输出",
"name": "插件输出",
"intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出",
"avatar": "core/workflow/template/pluginOutput",
"flowNodeType": "pluginOutput",
"showStatus": false,
"position": {
"x": 1654.8021754314786,
"y": -22.243376051504086
"x": 1703.581616889916,
"y": -14.097442104994656
},
"version": "481",
"inputs": [
@@ -147,8 +147,8 @@
"flowNodeType": "httpRequest468",
"showStatus": true,
"position": {
"x": 1081.967607938733,
"y": -426.08028677656125
"x": 1000.6685388413375,
"y": -457.0974421049947
},
"version": "481",
"inputs": [
@@ -158,7 +158,7 @@
"valueType": "dynamic",
"label": "",
"required": false,
"description": "core.module.input.description.HTTP Dynamic Input",
"description": "common:core.module.input.description.HTTP Dynamic Input",
"customInputConfig": {
"selectValueTypeList": [
"string",
@@ -169,6 +169,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -178,7 +179,9 @@
],
"showDescription": false,
"showDefaultValue": true
}
},
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpMethod",
@@ -186,17 +189,33 @@
"valueType": "string",
"label": "",
"value": "POST",
"required": true
"required": true,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpTimeout",
"renderTypeList": ["custom"],
"valueType": "number",
"label": "",
"value": 30,
"min": 5,
"max": 600,
"required": true,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpReqUrl",
"renderTypeList": ["hidden"],
"valueType": "string",
"label": "",
"description": "core.module.input.description.Http Request Url",
"description": "common:core.module.input.description.Http Request Url",
"placeholder": "https://api.ai.com/getInventory",
"required": false,
"value": "Doc2X/URLImg2text"
"value": "Doc2X/URLImg2text",
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpHeader",
@@ -204,9 +223,11 @@
"valueType": "any",
"value": [],
"label": "",
"description": "core.module.input.description.Http Request Header",
"placeholder": "core.module.input.description.Http Request Header",
"required": false
"description": "common:core.module.input.description.Http Request Header",
"placeholder": "common:core.module.input.description.Http Request Header",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpParams",
@@ -214,7 +235,9 @@
"valueType": "any",
"value": [],
"label": "",
"required": false
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpJsonBody",
@@ -222,7 +245,29 @@
"valueType": "any",
"value": "{\n \"apikey\": \"{{apikey}}\",\n \"url\": \"{{url}}\",\n \"img_correction\": {{img_correction}},\n \"formula\": {{formula}}\n}",
"label": "",
"required": false
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpFormBody",
"renderTypeList": ["hidden"],
"valueType": "any",
"value": [],
"label": "",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpContentType",
"renderTypeList": ["hidden"],
"valueType": "string",
"value": "json",
"label": "",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"renderTypeList": ["reference"],
@@ -240,6 +285,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -269,6 +315,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -298,6 +345,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -327,6 +375,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -345,7 +394,7 @@
{
"id": "error",
"key": "error",
"label": "请求错误",
"label": "workflow:request_error",
"description": "HTTP请求错误信息成功时返回空",
"valueType": "object",
"type": "static"
@@ -353,8 +402,8 @@
{
"id": "httpRawResponse",
"key": "httpRawResponse",
"label": "原始响应",
"required": true,
"label": "workflow:raw_response",
"description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。",
"valueType": "any",
"type": "static"
@@ -401,6 +450,20 @@
"label": "success"
}
]
},
{
"nodeId": "sWEDDSeuI9ar",
"name": "系统配置",
"intro": "",
"avatar": "core/workflow/template/systemConfig",
"flowNodeType": "pluginConfig",
"position": {
"x": -117.03701176267538,
"y": -75.09744210499466
},
"version": "4811",
"inputs": [],
"outputs": []
}
],
"edges": [

View File

@@ -15,7 +15,7 @@
"nodes": [
{
"nodeId": "pluginInput",
"name": "自定义插件输入",
"name": "插件开始",
"intro": "可以配置插件需要哪些输入,利用这些输入来运行插件",
"avatar": "core/workflow/template/workflowStart",
"flowNodeType": "pluginInput",
@@ -88,14 +88,14 @@
},
{
"nodeId": "pluginOutput",
"name": "自定义插件输出",
"name": "插件输出",
"intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出",
"avatar": "core/workflow/template/pluginOutput",
"flowNodeType": "pluginOutput",
"showStatus": false,
"position": {
"x": 1654.8021754314786,
"y": -22.243376051504086
"x": 1665.6420513111314,
"y": -40.597442104994656
},
"version": "481",
"inputs": [
@@ -128,8 +128,8 @@
"flowNodeType": "httpRequest468",
"showStatus": true,
"position": {
"x": 1081.967607938733,
"y": -426.08028677656125
"x": 966.3422652224374,
"y": -446.5974421049947
},
"version": "481",
"inputs": [
@@ -139,7 +139,7 @@
"valueType": "dynamic",
"label": "",
"required": false,
"description": "core.module.input.description.HTTP Dynamic Input",
"description": "common:core.module.input.description.HTTP Dynamic Input",
"customInputConfig": {
"selectValueTypeList": [
"string",
@@ -150,6 +150,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -159,7 +160,9 @@
],
"showDescription": false,
"showDefaultValue": true
}
},
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpMethod",
@@ -167,17 +170,33 @@
"valueType": "string",
"label": "",
"value": "POST",
"required": true
"required": true,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpTimeout",
"renderTypeList": ["custom"],
"valueType": "number",
"label": "",
"value": 30,
"min": 5,
"max": 600,
"required": true,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpReqUrl",
"renderTypeList": ["hidden"],
"valueType": "string",
"label": "",
"description": "core.module.input.description.Http Request Url",
"description": "common:core.module.input.description.Http Request Url",
"placeholder": "https://api.ai.com/getInventory",
"required": false,
"value": "Doc2X/URLPDF2text"
"value": "Doc2X/URLPDF2text",
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpHeader",
@@ -185,9 +204,11 @@
"valueType": "any",
"value": [],
"label": "",
"description": "core.module.input.description.Http Request Header",
"placeholder": "core.module.input.description.Http Request Header",
"required": false
"description": "common:core.module.input.description.Http Request Header",
"placeholder": "common:core.module.input.description.Http Request Header",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpParams",
@@ -195,7 +216,9 @@
"valueType": "any",
"value": [],
"label": "",
"required": false
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpJsonBody",
@@ -203,7 +226,29 @@
"valueType": "any",
"value": "{\n \"apikey\": \"{{apikey}}\",\n \"url\": \"{{url}}\",\n \"ocr\": {{ocr}}\n}",
"label": "",
"required": false
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpFormBody",
"renderTypeList": ["hidden"],
"valueType": "any",
"value": [],
"label": "",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpContentType",
"renderTypeList": ["hidden"],
"valueType": "string",
"value": "json",
"label": "",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"renderTypeList": ["reference"],
@@ -221,6 +266,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -250,6 +296,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -279,6 +326,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -297,7 +345,7 @@
{
"id": "error",
"key": "error",
"label": "请求错误",
"label": "workflow:request_error",
"description": "HTTP请求错误信息成功时返回空",
"valueType": "object",
"type": "static"
@@ -305,8 +353,8 @@
{
"id": "httpRawResponse",
"key": "httpRawResponse",
"label": "原始响应",
"required": true,
"label": "workflow:raw_response",
"description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。",
"valueType": "any",
"type": "static"
@@ -353,6 +401,20 @@
"label": "success"
}
]
},
{
"nodeId": "rZmLfANEyyJe",
"name": "系统配置",
"intro": "",
"avatar": "core/workflow/template/systemConfig",
"flowNodeType": "pluginConfig",
"position": {
"x": -93.55061402342784,
"y": -55.907069101622824
},
"version": "4811",
"inputs": [],
"outputs": []
}
],
"edges": [

View File

@@ -14,14 +14,14 @@
"nodes": [
{
"nodeId": "pluginInput",
"name": "自定义插件输入",
"name": "插件开始",
"intro": "可以配置插件需要哪些输入,利用这些输入来运行插件",
"avatar": "/imgs/workflow/input.png",
"avatar": "core/workflow/template/workflowStart",
"flowNodeType": "pluginInput",
"showStatus": false,
"position": {
"x": 393.68844551739926,
"y": -58.80666875994541
"x": 484.02074451450517,
"y": -79.06127656499825
},
"version": "481",
"inputs": [
@@ -49,14 +49,14 @@
},
{
"nodeId": "pluginOutput",
"name": "自定义插件输出",
"name": "插件输出",
"intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出",
"avatar": "/imgs/workflow/output.png",
"avatar": "core/workflow/template/pluginOutput",
"flowNodeType": "pluginOutput",
"showStatus": false,
"position": {
"x": 1795.6509902691012,
"y": -47.04550785550961
"x": 1759.5180706702588,
"y": -60.56127656499825
},
"version": "481",
"inputs": [
@@ -76,7 +76,7 @@
"nodeId": "hjnVuJAOwyXV",
"name": "HTTP 请求",
"intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)",
"avatar": "/imgs/workflow/http.png",
"avatar": "core/workflow/template/httpRequest",
"flowNodeType": "httpRequest468",
"showStatus": true,
"position": {
@@ -91,7 +91,7 @@
"valueType": "dynamic",
"label": "",
"required": false,
"description": "core.module.input.description.HTTP Dynamic Input",
"description": "common:core.module.input.description.HTTP Dynamic Input",
"customInputConfig": {
"selectValueTypeList": [
"string",
@@ -102,6 +102,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -111,7 +112,9 @@
],
"showDescription": false,
"showDefaultValue": true
}
},
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpMethod",
@@ -119,17 +122,33 @@
"valueType": "string",
"label": "",
"value": "POST",
"required": true
"required": true,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpTimeout",
"renderTypeList": ["custom"],
"valueType": "number",
"label": "",
"value": 30,
"min": 5,
"max": 600,
"required": true,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpReqUrl",
"renderTypeList": ["hidden"],
"valueType": "string",
"label": "",
"description": "core.module.input.description.Http Request Url",
"description": "common:core.module.input.description.Http Request Url",
"placeholder": "https://api.ai.com/getInventory",
"required": false,
"value": "duckduckgo/search"
"value": "duckduckgo/search",
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpHeader",
@@ -137,9 +156,11 @@
"valueType": "any",
"value": [],
"label": "",
"description": "core.module.input.description.Http Request Header",
"placeholder": "core.module.input.description.Http Request Header",
"required": false
"description": "common:core.module.input.description.Http Request Header",
"placeholder": "common:core.module.input.description.Http Request Header",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpParams",
@@ -147,7 +168,9 @@
"valueType": "any",
"value": [],
"label": "",
"required": false
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpJsonBody",
@@ -155,7 +178,29 @@
"valueType": "any",
"value": "{\n \"query\": \"{{query}}\"\n}",
"label": "",
"required": false
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpFormBody",
"renderTypeList": ["hidden"],
"valueType": "any",
"value": [],
"label": "",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpContentType",
"renderTypeList": ["hidden"],
"valueType": "string",
"value": "json",
"label": "",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"renderTypeList": ["reference"],
@@ -173,6 +218,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -188,6 +234,23 @@
}
],
"outputs": [
{
"id": "error",
"key": "error",
"label": "workflow:request_error",
"description": "HTTP请求错误信息成功时返回空",
"valueType": "object",
"type": "static"
},
{
"id": "httpRawResponse",
"key": "httpRawResponse",
"required": true,
"label": "workflow:raw_response",
"description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。",
"valueType": "any",
"type": "static"
},
{
"id": "system_addOutputParam",
"key": "system_addOutputParam",
@@ -215,23 +278,6 @@
"showDefaultValue": false
}
},
{
"id": "error",
"key": "error",
"label": "请求错误",
"description": "HTTP请求错误信息成功时返回空",
"valueType": "object",
"type": "static"
},
{
"id": "httpRawResponse",
"key": "httpRawResponse",
"label": "原始响应",
"required": true,
"description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。",
"valueType": "any",
"type": "static"
},
{
"id": "lEyy5QqyIBrK",
"valueType": "string",
@@ -240,6 +286,20 @@
"label": "result"
}
]
},
{
"nodeId": "f1mRh1D85H2D",
"name": "系统配置",
"intro": "",
"avatar": "core/workflow/template/systemConfig",
"flowNodeType": "pluginConfig",
"position": {
"x": -28.511358745511643,
"y": -103.56127656499825
},
"version": "4811",
"inputs": [],
"outputs": []
}
],
"edges": [

View File

@@ -14,14 +14,14 @@
"nodes": [
{
"nodeId": "pluginInput",
"name": "自定义插件输入",
"name": "插件开始",
"intro": "可以配置插件需要哪些输入,利用这些输入来运行插件",
"avatar": "/imgs/workflow/input.png",
"avatar": "core/workflow/template/workflowStart",
"flowNodeType": "pluginInput",
"showStatus": false,
"position": {
"x": 393.68844551739926,
"y": -58.80666875994541
"x": 422.59478119647315,
"y": -79.06127656499825
},
"version": "481",
"inputs": [
@@ -49,14 +49,14 @@
},
{
"nodeId": "pluginOutput",
"name": "自定义插件输出",
"name": "插件输出",
"intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出",
"avatar": "/imgs/workflow/output.png",
"avatar": "core/workflow/template/pluginOutput",
"flowNodeType": "pluginOutput",
"showStatus": false,
"position": {
"x": 1795.6509902691012,
"y": -47.04550785550961
"x": 1777.58453046968,
"y": -60.56127656499825
},
"version": "481",
"inputs": [
@@ -76,7 +76,7 @@
"nodeId": "hjnVuJAOwyXV",
"name": "HTTP 请求",
"intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)",
"avatar": "/imgs/workflow/http.png",
"avatar": "core/workflow/template/httpRequest",
"flowNodeType": "httpRequest468",
"showStatus": true,
"position": {
@@ -91,7 +91,7 @@
"valueType": "dynamic",
"label": "",
"required": false,
"description": "core.module.input.description.HTTP Dynamic Input",
"description": "common:core.module.input.description.HTTP Dynamic Input",
"customInputConfig": {
"selectValueTypeList": [
"string",
@@ -102,6 +102,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -111,7 +112,9 @@
],
"showDescription": false,
"showDefaultValue": true
}
},
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpMethod",
@@ -119,17 +122,33 @@
"valueType": "string",
"label": "",
"value": "POST",
"required": true
"required": true,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpTimeout",
"renderTypeList": ["custom"],
"valueType": "number",
"label": "",
"value": 30,
"min": 5,
"max": 600,
"required": true,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpReqUrl",
"renderTypeList": ["hidden"],
"valueType": "string",
"label": "",
"description": "core.module.input.description.Http Request Url",
"description": "common:core.module.input.description.Http Request Url",
"placeholder": "https://api.ai.com/getInventory",
"required": false,
"value": "duckduckgo/searchImg"
"value": "duckduckgo/searchImg",
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpHeader",
@@ -137,9 +156,11 @@
"valueType": "any",
"value": [],
"label": "",
"description": "core.module.input.description.Http Request Header",
"placeholder": "core.module.input.description.Http Request Header",
"required": false
"description": "common:core.module.input.description.Http Request Header",
"placeholder": "common:core.module.input.description.Http Request Header",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpParams",
@@ -147,7 +168,9 @@
"valueType": "any",
"value": [],
"label": "",
"required": false
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpJsonBody",
@@ -155,7 +178,29 @@
"valueType": "any",
"value": "{\n \"query\": \"{{query}}\"\n}",
"label": "",
"required": false
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpFormBody",
"renderTypeList": ["hidden"],
"valueType": "any",
"value": [],
"label": "",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpContentType",
"renderTypeList": ["hidden"],
"valueType": "string",
"value": "json",
"label": "",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"renderTypeList": ["reference"],
@@ -173,6 +218,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -188,6 +234,23 @@
}
],
"outputs": [
{
"id": "error",
"key": "error",
"label": "workflow:request_error",
"description": "HTTP请求错误信息成功时返回空",
"valueType": "object",
"type": "static"
},
{
"id": "httpRawResponse",
"key": "httpRawResponse",
"required": true,
"label": "workflow:raw_response",
"description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。",
"valueType": "any",
"type": "static"
},
{
"id": "system_addOutputParam",
"key": "system_addOutputParam",
@@ -215,23 +278,6 @@
"showDefaultValue": false
}
},
{
"id": "error",
"key": "error",
"label": "请求错误",
"description": "HTTP请求错误信息成功时返回空",
"valueType": "object",
"type": "static"
},
{
"id": "httpRawResponse",
"key": "httpRawResponse",
"label": "原始响应",
"required": true,
"description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。",
"valueType": "any",
"type": "static"
},
{
"id": "lEyy5QqyIBrK",
"valueType": "string",
@@ -240,6 +286,20 @@
"label": "result"
}
]
},
{
"nodeId": "y3A7CnUp4VOH",
"name": "系统配置",
"intro": "",
"avatar": "core/workflow/template/systemConfig",
"flowNodeType": "pluginConfig",
"position": {
"x": -35.73794266528006,
"y": -103.56127656499825
},
"version": "4811",
"inputs": [],
"outputs": []
}
],
"edges": [

View File

@@ -14,14 +14,14 @@
"nodes": [
{
"nodeId": "pluginInput",
"name": "自定义插件输入",
"name": "插件开始",
"intro": "可以配置插件需要哪些输入,利用这些输入来运行插件",
"avatar": "/imgs/workflow/input.png",
"avatar": "core/workflow/template/workflowStart",
"flowNodeType": "pluginInput",
"showStatus": false,
"position": {
"x": 393.68844551739926,
"y": -58.80666875994541
"x": 476.7941605947366,
"y": -79.06127656499825
},
"version": "481",
"inputs": [
@@ -49,14 +49,14 @@
},
{
"nodeId": "pluginOutput",
"name": "自定义插件输出",
"name": "插件输出",
"intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出",
"avatar": "/imgs/workflow/output.png",
"avatar": "core/workflow/template/pluginOutput",
"flowNodeType": "pluginOutput",
"showStatus": false,
"position": {
"x": 1795.6509902691012,
"y": -47.04550785550961
"x": 1761.324716650201,
"y": -60.56127656499825
},
"version": "481",
"inputs": [
@@ -76,7 +76,7 @@
"nodeId": "hjnVuJAOwyXV",
"name": "HTTP 请求",
"intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)",
"avatar": "/imgs/workflow/http.png",
"avatar": "core/workflow/template/httpRequest",
"flowNodeType": "httpRequest468",
"showStatus": true,
"position": {
@@ -91,7 +91,7 @@
"valueType": "dynamic",
"label": "",
"required": false,
"description": "core.module.input.description.HTTP Dynamic Input",
"description": "common:core.module.input.description.HTTP Dynamic Input",
"customInputConfig": {
"selectValueTypeList": [
"string",
@@ -102,6 +102,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -111,7 +112,9 @@
],
"showDescription": false,
"showDefaultValue": true
}
},
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpMethod",
@@ -119,17 +122,33 @@
"valueType": "string",
"label": "",
"value": "POST",
"required": true
"required": true,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpTimeout",
"renderTypeList": ["custom"],
"valueType": "number",
"label": "",
"value": 30,
"min": 5,
"max": 600,
"required": true,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpReqUrl",
"renderTypeList": ["hidden"],
"valueType": "string",
"label": "",
"description": "core.module.input.description.Http Request Url",
"description": "common:core.module.input.description.Http Request Url",
"placeholder": "https://api.ai.com/getInventory",
"required": false,
"value": "duckduckgo/searchNews"
"value": "duckduckgo/searchNews",
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpHeader",
@@ -137,9 +156,11 @@
"valueType": "any",
"value": [],
"label": "",
"description": "core.module.input.description.Http Request Header",
"placeholder": "core.module.input.description.Http Request Header",
"required": false
"description": "common:core.module.input.description.Http Request Header",
"placeholder": "common:core.module.input.description.Http Request Header",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpParams",
@@ -147,7 +168,9 @@
"valueType": "any",
"value": [],
"label": "",
"required": false
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpJsonBody",
@@ -155,7 +178,29 @@
"valueType": "any",
"value": "{\n \"query\": \"{{query}}\"\n}",
"label": "",
"required": false
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpFormBody",
"renderTypeList": ["hidden"],
"valueType": "any",
"value": [],
"label": "",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpContentType",
"renderTypeList": ["hidden"],
"valueType": "string",
"value": "json",
"label": "",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"renderTypeList": ["reference"],
@@ -173,6 +218,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -188,6 +234,23 @@
}
],
"outputs": [
{
"id": "error",
"key": "error",
"label": "workflow:request_error",
"description": "HTTP请求错误信息成功时返回空",
"valueType": "object",
"type": "static"
},
{
"id": "httpRawResponse",
"key": "httpRawResponse",
"required": true,
"label": "workflow:raw_response",
"description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。",
"valueType": "any",
"type": "static"
},
{
"id": "system_addOutputParam",
"key": "system_addOutputParam",
@@ -215,23 +278,6 @@
"showDefaultValue": false
}
},
{
"id": "error",
"key": "error",
"label": "请求错误",
"description": "HTTP请求错误信息成功时返回空",
"valueType": "object",
"type": "static"
},
{
"id": "httpRawResponse",
"key": "httpRawResponse",
"label": "原始响应",
"required": true,
"description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。",
"valueType": "any",
"type": "static"
},
{
"id": "lEyy5QqyIBrK",
"valueType": "string",
@@ -240,6 +286,20 @@
"label": "result"
}
]
},
{
"nodeId": "dG0Prv5FaR8e",
"name": "系统配置",
"intro": "",
"avatar": "core/workflow/template/systemConfig",
"flowNodeType": "pluginConfig",
"position": {
"x": -32.12465070539588,
"y": -103.56127656499825
},
"version": "4811",
"inputs": [],
"outputs": []
}
],
"edges": [

View File

@@ -14,14 +14,14 @@
"nodes": [
{
"nodeId": "pluginInput",
"name": "自定义插件输入",
"name": "插件开始",
"intro": "可以配置插件需要哪些输入,利用这些输入来运行插件",
"avatar": "/imgs/workflow/input.png",
"avatar": "core/workflow/template/workflowStart",
"flowNodeType": "pluginInput",
"showStatus": false,
"position": {
"x": 393.68844551739926,
"y": -58.80666875994541
"x": 429.8213651162415,
"y": -79.06127656499825
},
"version": "481",
"inputs": [
@@ -49,14 +49,14 @@
},
{
"nodeId": "pluginOutput",
"name": "自定义插件输出",
"name": "插件输出",
"intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出",
"avatar": "/imgs/workflow/output.png",
"avatar": "core/workflow/template/pluginOutput",
"flowNodeType": "pluginOutput",
"showStatus": false,
"position": {
"x": 1795.6509902691012,
"y": -47.04550785550961
"x": 1781.1978224295642,
"y": -60.56127656499825
},
"version": "481",
"inputs": [
@@ -76,7 +76,7 @@
"nodeId": "hjnVuJAOwyXV",
"name": "HTTP 请求",
"intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)",
"avatar": "/imgs/workflow/http.png",
"avatar": "core/workflow/template/httpRequest",
"flowNodeType": "httpRequest468",
"showStatus": true,
"position": {
@@ -91,7 +91,7 @@
"valueType": "dynamic",
"label": "",
"required": false,
"description": "core.module.input.description.HTTP Dynamic Input",
"description": "common:core.module.input.description.HTTP Dynamic Input",
"customInputConfig": {
"selectValueTypeList": [
"string",
@@ -102,6 +102,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -111,7 +112,9 @@
],
"showDescription": false,
"showDefaultValue": true
}
},
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpMethod",
@@ -119,17 +122,33 @@
"valueType": "string",
"label": "",
"value": "POST",
"required": true
"required": true,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpTimeout",
"renderTypeList": ["custom"],
"valueType": "number",
"label": "",
"value": 30,
"min": 5,
"max": 600,
"required": true,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpReqUrl",
"renderTypeList": ["hidden"],
"valueType": "string",
"label": "",
"description": "core.module.input.description.Http Request Url",
"description": "common:core.module.input.description.Http Request Url",
"placeholder": "https://api.ai.com/getInventory",
"required": false,
"value": "duckduckgo/searchVideo"
"value": "duckduckgo/searchVideo",
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpHeader",
@@ -137,9 +156,11 @@
"valueType": "any",
"value": [],
"label": "",
"description": "core.module.input.description.Http Request Header",
"placeholder": "core.module.input.description.Http Request Header",
"required": false
"description": "common:core.module.input.description.Http Request Header",
"placeholder": "common:core.module.input.description.Http Request Header",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpParams",
@@ -147,7 +168,9 @@
"valueType": "any",
"value": [],
"label": "",
"required": false
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpJsonBody",
@@ -155,7 +178,29 @@
"valueType": "any",
"value": "{\n \"query\": \"{{query}}\"\n}",
"label": "",
"required": false
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpFormBody",
"renderTypeList": ["hidden"],
"valueType": "any",
"value": [],
"label": "",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpContentType",
"renderTypeList": ["hidden"],
"valueType": "string",
"value": "json",
"label": "",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"renderTypeList": ["reference"],
@@ -173,6 +218,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -188,6 +234,23 @@
}
],
"outputs": [
{
"id": "error",
"key": "error",
"label": "workflow:request_error",
"description": "HTTP请求错误信息成功时返回空",
"valueType": "object",
"type": "static"
},
{
"id": "httpRawResponse",
"key": "httpRawResponse",
"required": true,
"label": "workflow:raw_response",
"description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。",
"valueType": "any",
"type": "static"
},
{
"id": "system_addOutputParam",
"key": "system_addOutputParam",
@@ -215,23 +278,6 @@
"showDefaultValue": false
}
},
{
"id": "error",
"key": "error",
"label": "请求错误",
"description": "HTTP请求错误信息成功时返回空",
"valueType": "object",
"type": "static"
},
{
"id": "httpRawResponse",
"key": "httpRawResponse",
"label": "原始响应",
"required": true,
"description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。",
"valueType": "any",
"type": "static"
},
{
"id": "lEyy5QqyIBrK",
"valueType": "string",
@@ -240,6 +286,20 @@
"label": "result"
}
]
},
{
"nodeId": "iyF6yGGXuyWn",
"name": "系统配置",
"intro": "",
"avatar": "core/workflow/template/systemConfig",
"flowNodeType": "pluginConfig",
"position": {
"x": -8.638252966148258,
"y": -103.56127656499825
},
"version": "4811",
"inputs": [],
"outputs": []
}
],
"edges": [

View File

@@ -15,14 +15,14 @@
"nodes": [
{
"nodeId": "pluginInput",
"name": "自定义插件输入",
"name": "插件开始",
"intro": "可以配置插件需要哪些输入,利用这些输入来运行插件",
"avatar": "core/workflow/template/workflowStart",
"flowNodeType": "pluginInput",
"showStatus": false,
"position": {
"x": 156.37657136084977,
"y": 90.73380846709256
"x": 194.3171058153904,
"y": 125.65095361549629
},
"version": "481",
"inputs": [
@@ -68,14 +68,14 @@
},
{
"nodeId": "pluginOutput",
"name": "自定义插件输出",
"name": "插件输出",
"intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出",
"avatar": "core/workflow/template/pluginOutput",
"flowNodeType": "pluginOutput",
"showStatus": false,
"position": {
"x": 2110.7223589692912,
"y": 120.17602722162474
"x": 2128.4279417147436,
"y": 170.6509536154963
},
"version": "481",
"inputs": [
@@ -110,7 +110,7 @@
"valueType": "dynamic",
"label": "",
"required": false,
"description": "core.module.input.description.HTTP Dynamic Input",
"description": "common:core.module.input.description.HTTP Dynamic Input",
"customInputConfig": {
"selectValueTypeList": [
"string",
@@ -121,6 +121,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -130,7 +131,9 @@
],
"showDescription": false,
"showDefaultValue": true
}
},
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpMethod",
@@ -138,17 +141,33 @@
"valueType": "string",
"label": "",
"value": "POST",
"required": true
"required": true,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpTimeout",
"renderTypeList": ["custom"],
"valueType": "number",
"label": "",
"value": 30,
"min": 5,
"max": 600,
"required": true,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpReqUrl",
"renderTypeList": ["hidden"],
"valueType": "string",
"label": "",
"description": "core.module.input.description.Http Request Url",
"description": "common:core.module.input.description.Http Request Url",
"placeholder": "https://api.ai.com/getInventory",
"required": false,
"value": "{{url}}"
"value": "{{url}}",
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpHeader",
@@ -156,9 +175,11 @@
"valueType": "any",
"value": [],
"label": "",
"description": "core.module.input.description.Http Request Header",
"placeholder": "core.module.input.description.Http Request Header",
"required": false
"description": "common:core.module.input.description.Http Request Header",
"placeholder": "common:core.module.input.description.Http Request Header",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpParams",
@@ -166,7 +187,9 @@
"valueType": "any",
"value": [],
"label": "",
"required": false
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpJsonBody",
@@ -174,7 +197,29 @@
"valueType": "any",
"value": "{{content}}",
"label": "",
"required": false
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpFormBody",
"renderTypeList": ["hidden"],
"valueType": "any",
"value": [],
"label": "",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"key": "system_httpContentType",
"renderTypeList": ["hidden"],
"valueType": "string",
"value": "json",
"label": "",
"required": false,
"debugLabel": "",
"toolDescription": ""
},
{
"renderTypeList": ["reference"],
@@ -192,6 +237,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -221,6 +267,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -239,7 +286,7 @@
{
"id": "error",
"key": "error",
"label": "请求错误",
"label": "workflow:request_error",
"description": "HTTP请求错误信息成功时返回空",
"valueType": "object",
"type": "static"
@@ -247,8 +294,8 @@
{
"id": "httpRawResponse",
"key": "httpRawResponse",
"label": "原始响应",
"required": true,
"label": "workflow:raw_response",
"description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。",
"valueType": "any",
"type": "static"
@@ -290,8 +337,8 @@
"flowNodeType": "code",
"showStatus": true,
"position": {
"x": 805.8169457909617,
"y": -159.52218926716316
"x": 833.6400043909581,
"y": -127.34904638450371
},
"version": "482",
"inputs": [
@@ -301,7 +348,7 @@
"valueType": "dynamic",
"label": "",
"required": false,
"description": "这些变量会作为代码的运行的输入参数",
"description": "workflow:these_variables_will_be_input_parameters_for_code_execution",
"customInputConfig": {
"selectValueTypeList": [
"string",
@@ -312,6 +359,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -321,19 +369,25 @@
],
"showDescription": false,
"showDefaultValue": true
}
},
"debugLabel": "",
"toolDescription": ""
},
{
"key": "codeType",
"renderTypeList": ["hidden"],
"label": "",
"value": "js"
"value": "js",
"debugLabel": "",
"toolDescription": ""
},
{
"key": "code",
"renderTypeList": ["custom"],
"label": "",
"value": "function main({data1}){\n try{\n const parseData = JSON.parse(data1)\n if(typeof parseData === 'object') {\n return parseData\n }\n return {\n \"msg_type\": \"text\",\n content: {\n \"text\": data1\n }\n }\n } catch(err) {\n return {\n \"msg_type\": \"text\",\n content: {\n \"text\": data1\n }\n }\n }\n}"
"value": "function main({data1}){\n try{\n const parseData = JSON.parse(data1)\n if(typeof parseData === 'object') {\n return parseData\n }\n return {\n \"msg_type\": \"text\",\n content: {\n \"text\": data1\n }\n }\n } catch(err) {\n return {\n \"msg_type\": \"text\",\n content: {\n \"text\": data1\n }\n }\n }\n}",
"debugLabel": "",
"toolDescription": ""
},
{
"renderTypeList": ["reference"],
@@ -351,6 +405,7 @@
"arrayNumber",
"arrayBoolean",
"arrayObject",
"arrayAny",
"any",
"chatHistory",
"datasetQuote",
@@ -369,14 +424,15 @@
{
"id": "system_rawResponse",
"key": "system_rawResponse",
"label": "完整响应数据",
"label": "workflow:full_response_data",
"valueType": "object",
"type": "static"
"type": "static",
"description": ""
},
{
"id": "error",
"key": "error",
"label": "运行错误",
"label": "workflow:execution_error",
"description": "代码运行错误信息,成功时返回空",
"valueType": "object",
"type": "static"
@@ -417,6 +473,20 @@
"label": "content"
}
]
},
{
"nodeId": "xDvVyZbQIrPg",
"name": "系统配置",
"intro": "",
"avatar": "core/workflow/template/systemConfig",
"flowNodeType": "pluginConfig",
"position": {
"x": -272.2181157945658,
"y": 125.65095361549629
},
"version": "4811",
"inputs": [],
"outputs": []
}
],
"edges": [

View File

@@ -14,7 +14,7 @@
"nodes": [
{
"nodeId": "lmpb9v2lo2lk",
"name": "自定义插件输入",
"name": "插件开始",
"intro": "自定义配置外部输入,使用插件时,仅暴露自定义配置的输入",
"avatar": "/imgs/workflow/input.png",
"flowNodeType": "pluginInput",
@@ -48,7 +48,7 @@
},
{
"nodeId": "i7uow4wj2wdp",
"name": "自定义插件输出",
"name": "插件输出",
"intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出",
"avatar": "/imgs/workflow/output.png",
"flowNodeType": "pluginOutput",

View File

@@ -12,7 +12,7 @@
"nodes": [
{
"nodeId": "lmpb9v2lo2lk",
"name": "自定义插件输入",
"name": "插件开始",
"intro": "自定义配置外部输入,使用插件时,仅暴露自定义配置的输入",
"avatar": "/imgs/workflow/input.png",
"flowNodeType": "pluginInput",
@@ -27,7 +27,7 @@
},
{
"nodeId": "i7uow4wj2wdp",
"name": "自定义插件输出",
"name": "插件输出",
"intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出",
"avatar": "/imgs/workflow/output.png",
"flowNodeType": "pluginOutput",

View File

@@ -48,7 +48,7 @@
},
{
"nodeId": "sowtxkCPjvb7",
"name": "自定义插件输出",
"name": "插件输出",
"intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出",
"avatar": "/imgs/workflow/output.png",
"flowNodeType": "pluginOutput",

View File

@@ -14,6 +14,7 @@ export const cheerioToHtml = ({
}) => {
// get origin url
const originUrl = new URL(fetchUrl).origin;
const protocol = new URL(fetchUrl).protocol; // http: or https:
const usedSelector = selector || 'body';
const selectDom = $(usedSelector);
@@ -32,14 +33,22 @@ export const cheerioToHtml = ({
// if link,img startWith /, add origin url
selectDom.find('a').each((i, el) => {
const href = $(el).attr('href');
if (href && href.startsWith('/')) {
$(el).attr('href', originUrl + href);
if (href) {
if (href.startsWith('//')) {
$(el).attr('href', protocol + href);
} else if (href.startsWith('/')) {
$(el).attr('href', originUrl + href);
}
}
});
selectDom.find('img').each((i, el) => {
const src = $(el).attr('src');
if (src && src.startsWith('/')) {
$(el).attr('src', originUrl + src);
if (src) {
if (src.startsWith('//')) {
$(el).attr('src', protocol + src);
} else if (src.startsWith('/')) {
$(el).attr('src', originUrl + src);
}
}
});

View File

@@ -2,8 +2,13 @@ import type { ChatCompletionMessageParam } from '@fastgpt/global/core/ai/type.d'
import { getAIApi } from '../config';
import { countGptMessagesTokens } from '../../../common/string/tiktoken/index';
import { loadRequestMessages } from '../../chat/utils';
import { llmCompletionsBodyFormat } from '../utils';
export const Prompt_QuestionGuide = `你是一个AI智能助手可以回答和解决我的问题。请结合前面的对话记录,帮我生成 3 个问题引导我继续提问生成问题的语言要与原问题相同。问题的长度应小于20个字符按 JSON 格式返回: ["问题1", "问题2", "问题3"]`;
export const Prompt_QuestionGuide = `你是一个AI智能助手你的任务是结合对话记录,推测我下一步的问题。
你需要生成 3 个可能的问题,引导我继续提问,生成的问题要求:
1. 生成问题的语言,与最后一个用户提问语言一致。
2. 问题的长度应小于20个字符。
3. 按 JSON 格式返回: ["question1", "question2", "question3"]。`;
export async function createQuestionGuide({
messages,
@@ -23,16 +28,21 @@ export async function createQuestionGuide({
const ai = getAIApi({
timeout: 480000
});
const data = await ai.chat.completions.create({
model: model,
temperature: 0.1,
max_tokens: 200,
messages: await loadRequestMessages({
messages: concatMessages,
useVision: false
}),
stream: false
});
const data = await ai.chat.completions.create(
llmCompletionsBodyFormat(
{
model,
temperature: 0.1,
max_tokens: 200,
messages: await loadRequestMessages({
messages: concatMessages,
useVision: false
}),
stream: false
},
model
)
);
const answer = data.choices?.[0]?.message?.content || '';

View File

@@ -2,15 +2,20 @@ import { replaceVariable } from '@fastgpt/global/common/string/tools';
import { getAIApi } from '../config';
import { ChatItemType } from '@fastgpt/global/core/chat/type';
import { countGptMessagesTokens } from '../../../common/string/tiktoken/index';
import { ChatCompletionMessageParam } from '@fastgpt/global/core/ai/type';
import { ChatCompletion, ChatCompletionMessageParam } from '@fastgpt/global/core/ai/type';
import { chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt';
import { getLLMModel } from '../model';
import { llmCompletionsBodyFormat } from '../utils';
/*
query extension - 问题扩展
可以根据上下文,消除指代性问题以及扩展问题,利于检索。
*/
const defaultPrompt = `作为一个向量检索助手,你的任务是结合历史记录,从不同角度,为“原问题”生成个不同版本的“检索词”,从而提高向量检索的语义丰富度,提高向量检索的精度。生成的问题要求指向对象清晰明确,并与“原问题语言相同”。
const title = global.feConfigs?.systemTitle || 'FastAI';
const defaultPrompt = `作为一个向量检索助手,你的任务是结合历史记录,从不同角度,为“原问题”生成个不同版本的“检索词”,从而提高向量检索的语义丰富度,提高向量检索的精度。
生成的问题要求指向对象清晰明确,并与“原问题语言相同”。
参考 <Example></Example> 标中的示例来完成任务。
<Example>
@@ -49,49 +54,50 @@ A: 护产假的天数根据员工所在的城市而定。请提供您所在的
历史记录:
"""
Q: 作者是谁?
A: FastGPT 的作者是 labring。
A: ${title} 的作者是 labring。
"""
原问题: Tell me about him
检索词: ["Introduce labring, the author of FastGPT." ," Background information on author labring." "," Why does labring do FastGPT?"]
检索词: ["Introduce labring, the author of ${title}." ," Background information on author labring." "," Why does labring do ${title}?"]
----------------
历史记录:
"""
Q: 对话背景。
A: 关于 FatGPT 的介绍和使用等问题。
A: 关于 ${title} 的介绍和使用等问题。
"""
原问题: 你好。
检索词: ["你好"]
----------------
历史记录:
"""
Q: FastGPT 如何收费?
A: FastGPT 收费可以参考……
Q: ${title} 如何收费?
A: ${title} 收费可以参考……
"""
原问题: 你知道 laf 么?
检索词: ["laf 的官网地址是多少?","laf 的使用教程。","laf 有什么特点和优势。"]
----------------
历史记录:
"""
Q: FastGPT 的优势
Q: ${title} 的优势
A: 1. 开源
2. 简便
3. 扩展性强
"""
原问题: 介绍下第2点。
检索词: ["介绍下 FastGPT 简便的优势", "从哪些方面,可以体现出 FastGPT 的简便"]。
检索词: ["介绍下 ${title} 简便的优势", "从哪些方面,可以体现出 ${title} 的简便"]。
----------------
历史记录:
"""
Q: 什么是 FastGPT
A: FastGPT 是一个 RAG 平台。
Q: 什么是 ${title}
A: ${title} 是一个 RAG 平台。
Q: 什么是 Laf
A: Laf 是一个云函数开发平台。
"""
原问题: 它们有什么关系?
检索词: ["FastGPT和Laf有什么关系","介绍下FastGPT","介绍下Laf"]
检索词: ["${title}和Laf有什么关系","介绍下${title}","介绍下Laf"]
</Example>
----------------
-----
下面是正式的任务:
历史记录:
@@ -130,6 +136,8 @@ A: ${chatBg}
.join('\n');
const concatFewShot = `${systemFewShot}${historyFewShot}`.trim();
const modelData = getLLMModel(model);
const ai = getAIApi({
timeout: 480000
});
@@ -143,13 +151,19 @@ A: ${chatBg}
})
}
] as ChatCompletionMessageParam[];
const result = await ai.chat.completions.create({
model: model,
temperature: 0.01,
// @ts-ignore
messages,
stream: false
});
const result = (await ai.chat.completions.create(
llmCompletionsBodyFormat(
{
stream: false,
model: modelData.model,
temperature: 0.01,
// @ts-ignore
messages
},
modelData
)
)) as ChatCompletion;
let answer = result.choices?.[0]?.message?.content || '';
if (!answer) {
@@ -161,6 +175,8 @@ A: ${chatBg}
};
}
// Intercept the content of [] and retain []
answer = answer.match(/\[.*?\]/)?.[0] || '';
answer = answer.replace(/\\"/g, '"');
try {

View File

@@ -1,6 +1,11 @@
import { LLMModelItemType } from '@fastgpt/global/core/ai/model.d';
import { ChatCompletionMessageParam } from '@fastgpt/global/core/ai/type';
import {
ChatCompletionCreateParamsNonStreaming,
ChatCompletionCreateParamsStreaming,
ChatCompletionMessageParam
} from '@fastgpt/global/core/ai/type';
import { countGptMessagesTokens } from '../../common/string/tiktoken';
import { getLLMModel } from './model';
export const computedMaxToken = async ({
maxToken,
@@ -32,8 +37,49 @@ export const computedTemperature = ({
model: LLMModelItemType;
temperature: number;
}) => {
if (temperature < 1) return temperature;
temperature = +(model.maxTemperature * (temperature / 10)).toFixed(2);
temperature = Math.max(temperature, 0.01);
return temperature;
};
type CompletionsBodyType =
| ChatCompletionCreateParamsNonStreaming
| ChatCompletionCreateParamsStreaming;
export const llmCompletionsBodyFormat = <T extends CompletionsBodyType>(
body: T,
model: string | LLMModelItemType
) => {
const modelData = typeof model === 'string' ? getLLMModel(model) : model;
if (!modelData) {
return body;
}
const requestBody: T = {
...body,
temperature: body.temperature
? computedTemperature({
model: modelData,
temperature: body.temperature
})
: undefined,
...modelData?.defaultConfig
};
// field map
if (modelData.fieldMap) {
Object.entries(modelData.fieldMap).forEach(([sourceKey, targetKey]) => {
// @ts-ignore
requestBody[targetKey] = body[sourceKey];
// @ts-ignore
delete requestBody[sourceKey];
});
}
// console.log(requestBody);
return requestBody;
};

View File

@@ -34,7 +34,7 @@ export async function splitCombinePluginId(id: string) {
return { source, pluginId: id };
}
const getPluginTemplateById = async (
const getChildAppTemplateById = async (
id: string
): Promise<SystemPluginTemplateItemType & { teamId?: string }> => {
const { source, pluginId } = await splitCombinePluginId(id);
@@ -69,44 +69,48 @@ const getPluginTemplateById = async (
};
/* format plugin modules to plugin preview module */
export async function getPluginPreviewNode({ id }: { id: string }): Promise<FlowNodeTemplateType> {
const plugin = await getPluginTemplateById(id);
const isPlugin = !!plugin.workflow.nodes.find(
export async function getChildAppPreviewNode({
id
}: {
id: string;
}): Promise<FlowNodeTemplateType> {
const app = await getChildAppTemplateById(id);
const isPlugin = !!app.workflow.nodes.find(
(node) => node.flowNodeType === FlowNodeTypeEnum.pluginInput
);
return {
id: getNanoid(),
pluginId: plugin.id,
templateType: plugin.templateType,
pluginId: app.id,
templateType: app.templateType,
flowNodeType: isPlugin ? FlowNodeTypeEnum.pluginModule : FlowNodeTypeEnum.appModule,
avatar: plugin.avatar,
name: plugin.name,
intro: plugin.intro,
inputExplanationUrl: plugin.inputExplanationUrl,
showStatus: plugin.showStatus,
isTool: isPlugin,
version: plugin.version,
avatar: app.avatar,
name: app.name,
intro: app.intro,
inputExplanationUrl: app.inputExplanationUrl,
showStatus: app.showStatus,
isTool: true,
version: app.version,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
...(isPlugin
? pluginData2FlowNodeIO({ nodes: plugin.workflow.nodes })
: appData2FlowNodeIO({ chatConfig: plugin.workflow.chatConfig }))
? pluginData2FlowNodeIO({ nodes: app.workflow.nodes })
: appData2FlowNodeIO({ chatConfig: app.workflow.chatConfig }))
};
}
/* run plugin time */
export async function getPluginRuntimeById(id: string): Promise<PluginRuntimeType> {
const plugin = await getPluginTemplateById(id);
export async function getChildAppRuntimeById(id: string): Promise<PluginRuntimeType> {
const app = await getChildAppTemplateById(id);
return {
id: plugin.id,
teamId: plugin.teamId,
name: plugin.name,
avatar: plugin.avatar,
showStatus: plugin.showStatus,
currentCost: plugin.currentCost,
nodes: plugin.workflow.nodes,
edges: plugin.workflow.edges
id: app.id,
teamId: app.teamId,
name: app.name,
avatar: app.avatar,
showStatus: app.showStatus,
currentCost: app.currentCost,
nodes: app.workflow.nodes,
edges: app.workflow.edges
};
}

View File

@@ -13,6 +13,7 @@ export const computedPluginUsage = async (
) => {
const { source } = await splitCombinePluginId(plugin.id);
// Commercial plugin: n points per times
if (source === PluginSourceEnum.commercial) {
return plugin.currentCost ?? 0;
}

View File

@@ -9,23 +9,24 @@ import { MongoChat } from './chatSchema';
export async function getChatItems({
appId,
chatId,
limit = 30,
offset,
limit,
field
}: {
appId: string;
chatId?: string;
limit?: number;
offset: number;
limit: number;
field: string;
}): Promise<{ histories: ChatItemType[] }> {
}): Promise<{ histories: ChatItemType[]; total: number }> {
if (!chatId) {
return { histories: [] };
return { histories: [], total: 0 };
}
const histories = await MongoChatItem.find({ appId, chatId }, field)
.sort({ _id: -1 })
.limit(limit)
.lean();
const [histories, total] = await Promise.all([
MongoChatItem.find({ chatId, appId }, field).sort({ _id: -1 }).skip(offset).limit(limit).lean(),
MongoChatItem.countDocuments({ chatId, appId })
]);
histories.reverse();
histories.forEach((item) => {
@@ -33,7 +34,7 @@ export async function getChatItems({
item.value = adaptStringValue(item.value);
});
return { histories };
return { histories, total };
}
/* Temporary adaptation for old conversation records */

View File

@@ -121,7 +121,7 @@ export const updateInteractiveChat = async ({
appId,
teamId,
tmbId,
userSelectedVal,
userInteractiveVal,
aiResponse,
newVariables,
newTitle
@@ -130,7 +130,7 @@ export const updateInteractiveChat = async ({
appId: string;
teamId: string;
tmbId: string;
userSelectedVal: string;
userInteractiveVal: string;
aiResponse: AIChatItemType & { dataId?: string };
newVariables?: Record<string, any>;
newTitle: string;
@@ -153,13 +153,38 @@ export const updateInteractiveChat = async ({
return;
}
interactiveValue.interactive = {
...interactiveValue.interactive,
params: {
...interactiveValue.interactive.params,
userSelectedVal
const parsedUserInteractiveVal = (() => {
try {
return JSON.parse(userInteractiveVal);
} catch (err) {
return userInteractiveVal;
}
};
})();
interactiveValue.interactive =
interactiveValue.interactive.type === 'userSelect'
? {
...interactiveValue.interactive,
params: {
...interactiveValue.interactive.params,
userSelectedVal: userInteractiveVal
}
}
: {
...interactiveValue.interactive,
params: {
...interactiveValue.interactive.params,
inputForm: interactiveValue.interactive.params.inputForm.map((item) => {
const itemValue = parsedUserInteractiveVal[item.label];
return itemValue !== undefined
? {
...item,
value: itemValue
}
: item;
}),
submitted: true
}
};
if (aiResponse.customFeedbacks) {
chatItem.customFeedbacks = chatItem.customFeedbacks

View File

@@ -8,6 +8,8 @@ import axios from 'axios';
import { ChatCompletionRequestMessageRoleEnum } from '@fastgpt/global/core/ai/constants';
import { getFileContentTypeFromHeader, guessBase64ImageType } from '../../common/file/utils';
import { serverRequestBaseUrl } from '../../common/api/serverRequest';
import { i18nT } from '../../../web/i18n/utils';
import { addLog } from '../../common/system/log';
/* slice chat context by tokens */
const filterEmptyMessages = (messages: ChatCompletionMessageParam[]) => {
@@ -111,20 +113,62 @@ export const loadRequestMessages = async ({
useVision?: boolean;
origin?: string;
}) => {
// Load image to base64
const loadImageToBase64 = async (messages: ChatCompletionContentPart[]) => {
return Promise.all(
messages.map(async (item) => {
if (item.type === 'image_url') {
// Remove url origin
const imgUrl = (() => {
if (origin && item.image_url.url.startsWith(origin)) {
return item.image_url.url.replace(origin, '');
}
return item.image_url.url;
})();
// If imgUrl is a local path, load image from local, and set url to base64
if (imgUrl.startsWith('/') || process.env.VISION_FOCUS_BASE64 === 'true') {
addLog.debug('Load image from local server', {
baseUrl: serverRequestBaseUrl,
requestUrl: imgUrl
});
const response = await axios.get(imgUrl, {
baseURL: serverRequestBaseUrl,
responseType: 'arraybuffer',
proxy: false
});
const base64 = Buffer.from(response.data, 'binary').toString('base64');
const imageType =
getFileContentTypeFromHeader(response.headers['content-type']) ||
guessBase64ImageType(base64);
return {
...item,
image_url: {
...item.image_url,
url: `data:${imageType};base64,${base64}`
}
};
}
}
return item;
})
);
};
// Split question text and image
function parseStringWithImages(input: string): ChatCompletionContentPart[] {
const parseStringWithImages = (input: string): ChatCompletionContentPart[] => {
if (!useVision) {
return [{ type: 'text', text: input || '' }];
}
// 正则表达式匹配图片URL
const imageRegex =
/(https?:\/\/[^\s/$.?#].[^\s]*\.(?:png|jpe?g|gif|webp|bmp|tiff?|svg|ico|heic|avif))/i;
/(https?:\/\/[^\s/$.?#].[^\s]*\.(?:png|jpe?g|gif|webp|bmp|tiff?|svg|ico|heic|avif))/gi;
const result: ChatCompletionContentPart[] = [];
// 提取所有HTTPS图片URL并添加到result开头
const httpsImages = input.match(imageRegex) || [];
const httpsImages = [...new Set(Array.from(input.matchAll(imageRegex), (m) => m[0]))];
httpsImages.forEach((url) => {
result.push({
type: 'image_url',
@@ -134,57 +178,35 @@ export const loadRequestMessages = async ({
});
});
// Too many images or too long text, return text
if (httpsImages.length > 4 || input.length > 1000) {
return [{ type: 'text', text: input || '' }];
}
// 添加原始input作为文本
result.push({ type: 'text', text: input });
return result;
}
// Load image
};
// Parse user content(text and img)
const parseUserContent = async (content: string | ChatCompletionContentPart[]) => {
if (typeof content === 'string') {
return parseStringWithImages(content);
return loadImageToBase64(parseStringWithImages(content));
}
const result = await Promise.all(
content.map(async (item) => {
if (item.type === 'text') return parseStringWithImages(item.text);
if (item.type === 'file_url') return;
if (item.type === 'file_url') return; // LLM not support file_url
if (!item.image_url.url) return item;
// Remove url origin
const imgUrl = (() => {
if (origin && item.image_url.url.startsWith(origin)) {
return item.image_url.url.replace(origin, '');
}
return item.image_url.url;
})();
/* Load local image */
if (imgUrl.startsWith('/')) {
const response = await axios.get(imgUrl, {
baseURL: serverRequestBaseUrl,
responseType: 'arraybuffer'
});
const base64 = Buffer.from(response.data, 'binary').toString('base64');
const imageType =
getFileContentTypeFromHeader(response.headers['content-type']) ||
guessBase64ImageType(base64);
return {
...item,
image_url: {
...item.image_url,
url: `data:${imageType};base64,${base64}`
}
};
}
return item;
})
);
return result.flat().filter(Boolean);
return loadImageToBase64(result.flat().filter(Boolean) as ChatCompletionContentPart[]);
};
// format GPT messages, concat text messages
const clearInvalidMessages = (messages: ChatCompletionMessageParam[]) => {
return messages
@@ -247,7 +269,7 @@ export const loadRequestMessages = async ({
};
if (messages.length === 0) {
return Promise.reject('core.chat.error.Messages empty');
return Promise.reject(i18nT('common:core.chat.error.Messages empty'));
}
// filter messages file
@@ -275,6 +297,7 @@ export const loadRequestMessages = async ({
content: await parseUserContent(item.content)
};
} else if (item.role === ChatCompletionRequestMessageRoleEnum.Assistant) {
// remove invalid field
return {
role: item.role,
content: item.content,

View File

@@ -45,7 +45,10 @@ export async function createOneCollection({
[key: string]: any;
session?: ClientSession;
}) {
// Create collection tags
const collectionTags = await createOrGetCollectionTags({ tags, teamId, datasetId, session });
// Create collection
const [collection] = await MongoDatasetCollection.create(
[
{

View File

@@ -111,6 +111,17 @@ try {
DatasetCollectionSchema.index({ teamId: 1, datasetId: 1, tags: 1 });
// create time filter
DatasetCollectionSchema.index({ teamId: 1, datasetId: 1, createTime: 1 });
// Get collection by external file id
DatasetCollectionSchema.index(
{ datasetId: 1, externalFileId: 1 },
{
unique: true,
partialFilterExpression: {
externalFileId: { $exists: true }
}
}
);
} catch (error) {
console.log(error);
}

View File

@@ -1,6 +1,5 @@
import type { CollectionWithDatasetType } from '@fastgpt/global/core/dataset/type.d';
import { MongoDatasetCollection } from './schema';
import type { ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type.d';
import { splitText2Chunks } from '@fastgpt/global/common/string/textSplitter';
import { MongoDatasetTraining } from '../training/schema';
import { urlsFetch } from '../../../common/string/cheerio';
@@ -12,6 +11,7 @@ import { hashStr } from '@fastgpt/global/common/string/tools';
import { ClientSession } from '../../../common/mongo';
import { PushDatasetDataResponse } from '@fastgpt/global/core/dataset/api';
import { MongoDatasetCollectionTags } from '../tag/schema';
import { readFromSecondary } from '../../../common/mongo/utils';
/**
* get all collection by top collectionId
@@ -160,7 +160,7 @@ export const reloadCollectionChunks = async ({
const { chunks } = splitText2Chunks({
text: newRawText,
chunkLen: col.chunkSize || 512,
customReg: col.chunkSplitter ? [col.chunkSplitter] : [],
customReg: col.chunkSplitter ? [col.chunkSplitter] : []
});
// insert to training queue
@@ -204,7 +204,7 @@ export const reloadCollectionChunks = async ({
};
export const createOrGetCollectionTags = async ({
tags = [],
tags,
datasetId,
teamId,
session
@@ -213,13 +213,20 @@ export const createOrGetCollectionTags = async ({
datasetId: string;
teamId: string;
session?: ClientSession;
}): Promise<string[]> => {
if (!tags.length) return [];
const existingTags = await MongoDatasetCollectionTags.find({
teamId,
datasetId,
$expr: { $in: ['$tag', tags] }
});
}) => {
if (!tags) return undefined;
if (tags.length === 0) return [];
const existingTags = await MongoDatasetCollectionTags.find(
{
teamId,
datasetId,
tag: { $in: tags }
},
undefined,
{ session }
).lean();
const existingTagContents = existingTags.map((tag) => tag.tag);
const newTagContents = tags.filter((tag) => !existingTagContents.includes(tag));
@@ -235,3 +242,29 @@ export const createOrGetCollectionTags = async ({
return [...existingTags.map((tag) => tag._id), ...newTags.map((tag) => tag._id)];
};
export const collectionTagsToTagLabel = async ({
datasetId,
tags
}: {
datasetId: string;
tags?: string[];
}) => {
if (!tags) return undefined;
if (tags.length === 0) return;
// Get all the tags
const collectionTags = await MongoDatasetCollectionTags.find({ datasetId }, undefined, {
...readFromSecondary
}).lean();
const tagsMap = new Map<string, string>();
collectionTags.forEach((tag) => {
tagsMap.set(String(tag._id), tag.tag);
});
return tags
.map((tag) => {
return tagsMap.get(tag) || '';
})
.filter(Boolean);
};

View File

@@ -271,7 +271,7 @@ export async function searchDatasetData(props: SearchDatasetDataProps) {
collectionId: { $in: Array.from(new Set(results.map((item) => item.collectionId))) },
'indexes.dataId': { $in: results.map((item) => item.id?.trim()) }
},
'datasetId collectionId q a chunkIndex indexes'
'datasetId collectionId updateTime q a chunkIndex indexes'
)
.populate('collectionId', 'name fileId rawLink externalFileId externalFileUrl')
.lean()) as DatasetDataWithCollectionType[];
@@ -299,6 +299,7 @@ export async function searchDatasetData(props: SearchDatasetDataProps) {
const result: SearchDataResponseItemType = {
id: String(data._id),
updateTime: data.updateTime,
q: data.q,
a: data.a,
chunkIndex: data.chunkIndex,
@@ -396,6 +397,7 @@ export async function searchDatasetData(props: SearchDatasetDataProps) {
_id: 1,
datasetId: 1,
collectionId: 1,
updateTime: 1,
q: 1,
a: 1,
chunkIndex: 1,
@@ -425,6 +427,7 @@ export async function searchDatasetData(props: SearchDatasetDataProps) {
id: String(item._id),
datasetId: String(item.datasetId),
collectionId: String(item.collectionId),
updateTime: item.updateTime,
...getCollectionSourceData(collection),
q: item.q,
a: item.a,

View File

@@ -10,6 +10,7 @@ import { ClientSession } from '../../../common/mongo';
import { getLLMModel, getVectorModel } from '../../ai/model';
import { addLog } from '../../../common/system/log';
import { getCollectionWithDataset } from '../controller';
import { mongoSessionRun } from '../../../common/mongo/sessionRun';
export const lockTrainingDataByTeamId = async (teamId: string): Promise<any> => {
try {
@@ -64,7 +65,7 @@ export async function pushDataListToTrainingQueue({
vectorModel: string;
session?: ClientSession;
} & PushDatasetDataProps): Promise<PushDatasetDataResponse> {
const checkModelValid = async () => {
const { model, maxToken, weight } = await (async () => {
const agentModelData = getLLMModel(agentModel);
if (!agentModelData) {
return Promise.reject(`File model ${agentModel} is inValid`);
@@ -91,9 +92,16 @@ export async function pushDataListToTrainingQueue({
}
return Promise.reject(`Training mode "${trainingMode}" is inValid`);
};
})();
const { model, maxToken, weight } = await checkModelValid();
// filter repeat or equal content
const set = new Set();
const filterResult: Record<string, PushDatasetDataChunkProps[]> = {
success: [],
overToken: [],
repeat: [],
error: []
};
// format q and a, remove empty char
data.forEach((item) => {
@@ -108,19 +116,8 @@ export async function pushDataListToTrainingQueue({
};
})
.filter(Boolean);
});
// filter repeat or equal content
const set = new Set();
const filterResult: Record<string, PushDatasetDataChunkProps[]> = {
success: [],
overToken: [],
repeat: [],
error: []
};
// filter repeat content
data.forEach((item) => {
// filter repeat content
if (!item.q) {
filterResult.error.push(item);
return;
@@ -150,40 +147,55 @@ export async function pushDataListToTrainingQueue({
const failedDocuments: PushDatasetDataChunkProps[] = [];
// 使用 insertMany 批量插入
try {
await MongoDatasetTraining.insertMany(
filterResult.success.map((item) => ({
teamId,
tmbId,
datasetId,
collectionId,
billId,
mode: trainingMode,
prompt,
model,
q: item.q,
a: item.a,
chunkIndex: item.chunkIndex ?? 0,
weight: weight ?? 0,
indexes: item.indexes
})),
{
session,
ordered: false
}
);
} catch (error: any) {
addLog.error(`Insert error`, error);
// 如果有错误,将失败的文档添加到失败列表中
error.writeErrors?.forEach((writeError: any) => {
failedDocuments.push(data[writeError.index]);
});
console.log('failed', failedDocuments);
}
const batchSize = 200;
const insertData = async (startIndex: number, session: ClientSession) => {
const list = filterResult.success.slice(startIndex, startIndex + batchSize);
// 对于失败的文档,尝试单独插入
for await (const item of failedDocuments) {
await MongoDatasetTraining.create(item);
if (list.length === 0) return;
try {
await MongoDatasetTraining.insertMany(
list.map((item) => ({
teamId,
tmbId,
datasetId,
collectionId,
billId,
mode: trainingMode,
prompt,
model,
q: item.q,
a: item.a,
chunkIndex: item.chunkIndex ?? 0,
weight: weight ?? 0,
indexes: item.indexes
})),
{
session,
ordered: true
}
);
} catch (error: any) {
addLog.error(`Insert error`, error);
// 如果有错误,将失败的文档添加到失败列表中
error.writeErrors?.forEach((writeError: any) => {
failedDocuments.push(data[writeError.index]);
});
console.log('failed', failedDocuments);
}
// 对于失败的文档,尝试单独插入
await MongoDatasetTraining.create(failedDocuments, { session });
return insertData(startIndex + batchSize, session);
};
if (session) {
await insertData(0, session);
} else {
await mongoSessionRun(async (session) => {
await insertData(0, session);
});
}
delete filterResult.success;

View File

@@ -0,0 +1,3 @@
export const WORKFLOW_MAX_RUN_TIMES = process.env.WORKFLOW_MAX_RUN_TIMES
? parseInt(process.env.WORKFLOW_MAX_RUN_TIMES)
: 500;

View File

@@ -93,6 +93,7 @@ export const dispatchAppRequest = async (props: Props): Promise<Response> => {
const { text } = chatValue2RuntimePrompt(assistantResponses);
return {
assistantResponses,
[DispatchNodeResponseKeyEnum.nodeResponse]: {
moduleLogo: appData.avatar,
query: userChatInput,

View File

@@ -17,6 +17,7 @@ import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/ty
import { chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt';
import { getHandleId } from '@fastgpt/global/core/workflow/utils';
import { loadRequestMessages } from '../../../chat/utils';
import { llmCompletionsBodyFormat } from '../../../ai/utils';
type Props = ModuleDispatchProps<{
[NodeInputKeyEnum.aiModel]: string;
@@ -103,10 +104,10 @@ const completions = async ({
systemPrompt: systemPrompt || 'null',
typeList: agents
.map((item) => `{"类型ID":"${item.key}", "问题类型":"${item.value}"}`)
.join('------'),
.join('\n------\n'),
history: histories
.map((item) => `${item.obj}:${chatValue2RuntimePrompt(item.value).text}`)
.join('------'),
.join('\n------\n'),
question: userChatInput
})
}
@@ -124,12 +125,17 @@ const completions = async ({
timeout: 480000
});
const data = await ai.chat.completions.create({
model: cqModel.model,
temperature: 0.01,
messages: requestMessages,
stream: false
});
const data = await ai.chat.completions.create(
llmCompletionsBodyFormat(
{
model: cqModel.model,
temperature: 0.01,
messages: requestMessages,
stream: false
},
cqModel
)
);
const answer = data.choices?.[0].message?.content || '';
// console.log(JSON.stringify(chats2GPTMessages({ messages, reserveId: false }), null, 2));

View File

@@ -26,6 +26,7 @@ import {
import { ChatCompletionRequestMessageRoleEnum } from '@fastgpt/global/core/ai/constants';
import { DispatchNodeResultType } from '@fastgpt/global/core/workflow/runtime/type';
import { chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt';
import { llmCompletionsBodyFormat } from '../../../ai/utils';
type Props = ModuleDispatchProps<{
[NodeInputKeyEnum.history]?: ChatItemType[];
@@ -161,7 +162,7 @@ ${description ? `- ${description}` : ''}
- 需要结合前面的对话内容,一起生成合适的参数。
"""
本次输入内容: ${content}
本次输入内容: """${content}"""
`
}
}
@@ -226,13 +227,18 @@ const toolChoice = async (props: ActionProps) => {
timeout: 480000
});
const response = await ai.chat.completions.create({
model: extractModel.model,
temperature: 0.01,
messages: filterMessages,
tools,
tool_choice: { type: 'function', function: { name: agentFunName } }
});
const response = await ai.chat.completions.create(
llmCompletionsBodyFormat(
{
model: extractModel.model,
temperature: 0.01,
messages: filterMessages,
tools,
tool_choice: { type: 'function', function: { name: agentFunName } }
},
extractModel
)
);
const arg: Record<string, any> = (() => {
try {
@@ -271,15 +277,20 @@ const functionCall = async (props: ActionProps) => {
timeout: 480000
});
const response = await ai.chat.completions.create({
model: extractModel.model,
temperature: 0.01,
messages: filterMessages,
function_call: {
name: agentFunName
},
functions
});
const response = await ai.chat.completions.create(
llmCompletionsBodyFormat(
{
model: extractModel.model,
temperature: 0.01,
messages: filterMessages,
function_call: {
name: agentFunName
},
functions
},
extractModel
)
);
try {
const arg = JSON.parse(response?.choices?.[0]?.message?.function_call?.arguments || '');
@@ -311,7 +322,7 @@ const completions = async ({
extractModel,
user,
histories,
params: { content, extractKeys, description }
params: { content, extractKeys, description = 'No special requirements' }
}: ActionProps) => {
const messages: ChatItemType[] = [
{
@@ -351,12 +362,17 @@ Human: ${content}`
userKey: user.openaiAccount,
timeout: 480000
});
const data = await ai.chat.completions.create({
model: extractModel.model,
temperature: 0.01,
messages: requestMessages,
stream: false
});
const data = await ai.chat.completions.create(
llmCompletionsBodyFormat(
{
model: extractModel.model,
temperature: 0.01,
messages: requestMessages,
stream: false
},
extractModel
)
);
const answer = data.choices?.[0].message?.content || '';
// parse response

View File

@@ -24,7 +24,7 @@ import { getNanoid, sliceStrStartEnd } from '@fastgpt/global/common/string/tools
import { AIChatItemType } from '@fastgpt/global/core/chat/type';
import { GPTMessages2Chats } from '@fastgpt/global/core/chat/adapt';
import { updateToolInputValue } from './utils';
import { computedMaxToken, computedTemperature } from '../../../../ai/utils';
import { computedMaxToken, llmCompletionsBodyFormat } from '../../../../ai/utils';
type FunctionRunResponseType = {
toolRunResponse: DispatchFlowResponse;
@@ -110,19 +110,18 @@ export const runToolWithFunctionCall = async (
filterMessages
})
]);
const requestBody: any = {
...toolModel?.defaultConfig,
model: toolModel.model,
temperature: computedTemperature({
model: toolModel,
temperature
}),
max_tokens,
stream,
messages: requestMessages,
functions,
function_call: 'auto'
};
const requestBody = llmCompletionsBodyFormat(
{
model: toolModel.model,
temperature,
max_tokens,
stream,
messages: requestMessages,
functions,
function_call: 'auto'
},
toolModel
);
// console.log(JSON.stringify(requestBody, null, 2));
/* Run llm */
@@ -256,17 +255,6 @@ export const runToolWithFunctionCall = async (
];
// console.log(tokens, 'tool');
// Run tool status
if (node.showStatus) {
workflowStreamResponse?.({
event: SseResponseEventEnum.flowNodeStatus,
data: {
status: 'running',
name: node.name
}
});
}
// tool assistant
const toolAssistants = toolsRunResponse
.map((item) => {
@@ -298,7 +286,10 @@ export const runToolWithFunctionCall = async (
dispatchFlowResponse,
totalTokens: response?.totalTokens ? response.totalTokens + tokens : tokens,
completeMessages: filterMessages,
assistantResponses: toolNodeAssistants
assistantResponses: toolNodeAssistants,
runTimes:
(response?.runTimes || 0) +
flatToolsResponseData.reduce((sum, item) => sum + item.runTimes, 0)
};
}
@@ -310,7 +301,10 @@ export const runToolWithFunctionCall = async (
{
dispatchFlowResponse,
totalTokens: response?.totalTokens ? response.totalTokens + tokens : tokens,
assistantResponses: toolNodeAssistants
assistantResponses: toolNodeAssistants,
runTimes:
(response?.runTimes || 0) +
flatToolsResponseData.reduce((sum, item) => sum + item.runTimes, 0)
}
);
} else {
@@ -330,7 +324,8 @@ export const runToolWithFunctionCall = async (
dispatchFlowResponse: response?.dispatchFlowResponse || [],
totalTokens: response?.totalTokens ? response.totalTokens + tokens : tokens,
completeMessages,
assistantResponses: [...assistantResponses, ...toolNodeAssistant.value]
assistantResponses: [...assistantResponses, ...toolNodeAssistant.value],
runTimes: (response?.runTimes || 0) + 1
};
}
};

View File

@@ -14,7 +14,7 @@ import {
GPTMessages2Chats,
chatValue2RuntimePrompt,
chats2GPTMessages,
getSystemPrompt,
getSystemPrompt_ChatItemType,
runtimePrompt2ChatsValue
} from '@fastgpt/global/core/chat/adapt';
import { formatModelChars2Points } from '../../../../../support/wallet/usage/utils';
@@ -95,7 +95,8 @@ export const dispatchRunTools = async (props: DispatchToolModuleProps): Promise<
});
const messages: ChatItemType[] = [
...getSystemPrompt(systemPrompt),
...getSystemPrompt_ChatItemType(toolModel.defaultSystemChatPrompt),
...getSystemPrompt_ChatItemType(systemPrompt),
// Add file input prompt to histories
...chatHistories.map((item) => {
if (item.obj === ChatRoleEnum.Human) {
@@ -125,7 +126,8 @@ export const dispatchRunTools = async (props: DispatchToolModuleProps): Promise<
dispatchFlowResponse, // tool flow response
totalTokens,
completeMessages = [], // The actual message sent to AI(just save text)
assistantResponses = [] // FastGPT system store assistant.value response
assistantResponses = [], // FastGPT system store assistant.value response
runTimes
} = await (async () => {
const adaptMessages = chats2GPTMessages({ messages, reserveId: false });
@@ -195,6 +197,7 @@ export const dispatchRunTools = async (props: DispatchToolModuleProps): Promise<
const previewAssistantResponses = filterToolResponseToPreview(assistantResponses);
return {
[DispatchNodeResponseKeyEnum.runTimes]: runTimes,
[NodeOutputKeyEnum.answerText]: previewAssistantResponses
.filter((item) => item.text?.content)
.map((item) => item.text?.content || '')

View File

@@ -25,7 +25,7 @@ import {
import { AIChatItemType } from '@fastgpt/global/core/chat/type';
import { GPTMessages2Chats } from '@fastgpt/global/core/chat/adapt';
import { updateToolInputValue } from './utils';
import { computedMaxToken, computedTemperature } from '../../../../ai/utils';
import { computedMaxToken, llmCompletionsBodyFormat } from '../../../../ai/utils';
import { WorkflowResponseType } from '../../type';
type FunctionCallCompletion = {
@@ -113,17 +113,16 @@ export const runToolWithPromptCall = async (
filterMessages
})
]);
const requestBody = {
...toolModel?.defaultConfig,
model: toolModel.model,
temperature: computedTemperature({
model: toolModel,
temperature
}),
max_tokens,
stream,
messages: requestMessages
};
const requestBody = llmCompletionsBodyFormat(
{
model: toolModel.model,
temperature,
max_tokens,
stream,
messages: requestMessages
},
toolModel
);
// console.log(JSON.stringify(requestBody, null, 2));
/* Run llm */
@@ -135,9 +134,13 @@ export const runToolWithPromptCall = async (
Accept: 'application/json, text/plain, */*'
}
});
const isStreamResponse =
typeof aiResponse === 'object' &&
aiResponse !== null &&
('iterator' in aiResponse || 'controller' in aiResponse);
const answer = await (async () => {
if (res && stream) {
if (res && isStreamResponse) {
const { answer } = await streamResponse({
res,
toolNodes,
@@ -164,6 +167,17 @@ export const runToolWithPromptCall = async (
})
});
}
// 不支持 stream 模式的模型的流失响应
if (stream && !isStreamResponse) {
workflowStreamResponse?.({
event: SseResponseEventEnum.fastAnswer,
data: textAdaptGptResponse({
text: replaceAnswer
})
});
}
// No tool is invoked, indicating that the process is over
const gptAssistantResponse: ChatCompletionAssistantMessageParam = {
role: ChatCompletionRequestMessageRoleEnum.Assistant,
@@ -180,7 +194,8 @@ export const runToolWithPromptCall = async (
dispatchFlowResponse: response?.dispatchFlowResponse || [],
totalTokens: response?.totalTokens ? response.totalTokens + tokens : tokens,
completeMessages,
assistantResponses: [...assistantResponses, ...toolNodeAssistant.value]
assistantResponses: [...assistantResponses, ...toolNodeAssistant.value],
runTimes: (response?.runTimes || 0) + 1
};
}
@@ -260,17 +275,6 @@ export const runToolWithPromptCall = async (
};
})();
// Run tool status
if (node.showStatus) {
workflowStreamResponse?.({
event: SseResponseEventEnum.flowNodeStatus,
data: {
status: 'running',
name: node.name
}
});
}
// 合并工具调用的结果,使用 functionCall 格式存储。
const assistantToolMsgParams: ChatCompletionAssistantMessageParam = {
role: ChatCompletionRequestMessageRoleEnum.Assistant,
@@ -318,7 +322,8 @@ ANSWER: `;
dispatchFlowResponse,
totalTokens: response?.totalTokens ? response.totalTokens + tokens : tokens,
completeMessages: filterMessages,
assistantResponses: toolNodeAssistants
assistantResponses: toolNodeAssistants,
runTimes: (response?.runTimes || 0) + toolsRunResponse.moduleRunResponse.runTimes
};
}
@@ -330,7 +335,8 @@ ANSWER: `;
{
dispatchFlowResponse,
totalTokens: response?.totalTokens ? response.totalTokens + tokens : tokens,
assistantResponses: toolNodeAssistants
assistantResponses: toolNodeAssistants,
runTimes: (response?.runTimes || 0) + toolsRunResponse.moduleRunResponse.runTimes
}
);
};

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