Compare commits

..

29 Commits

Author SHA1 Message Date
Archer
3d80eb288b lock (#2079) 2024-07-18 10:13:47 +08:00
Archer
5cb196535f 4.8.7 fix (#2076) 2024-07-17 19:06:37 +08:00
jingyang
982325d066 fix i18next.d.ts (#2064)
* fix i18next.d.ts

* feat: packages web i18n

* delete file
2024-07-17 15:27:51 +08:00
Archer
36f8755d09 lock (#2063)
* lock

* perf: init data

* perf: vision model url

* fix: chat index
2024-07-17 00:16:57 +08:00
jingyang
fc96bb99cc feat: optimize i18n implementation for better localization (#2062)
* feat: optimize i18n implementation for better localization

* delete i18n-ally-custom-framework.yml

* update common key
2024-07-16 17:56:27 +08:00
papapatrick
1e4ffc2481 docs: 完善本地开发教程 (#2061) 2024-07-16 17:38:11 +08:00
Archer
ee7496467b 4.8.7 test (#2058)
* fix: query extension id;App page change type invalid

* prettier
2024-07-16 16:55:12 +08:00
Archer
b5c98a4f63 Plugin runtime (#2050)
* feat: plugin run (#1950)

* feat: plugin run

* fix

* ui

* fix

* change user input type

* fix

* fix

* temp

* split out plugin chat

* perf: chatbox

* perf: chatbox

* fix: plugin runtime (#2032)

* fix: plugin runtime

* fix

* fix build

* fix build

* perf: chat send prompt

* perf: chat log ux

* perf: chatbox context and share page plugin runtime

* perf: plugin run time config

* fix: ts

* feat: doc

* perf: isPc check

* perf: variable input render

* feat: app search

* fix: response box height

* fix: phone ui

* perf: lock

* perf: plugin route

* fix: chat (#2049)

---------

Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
2024-07-15 22:50:48 +08:00
Zong
090c880860 feat(image): metadata support image mime type (#2026) 2024-07-14 23:25:16 +08:00
Archer
dd2a9bdee5 Update 486.md 2024-07-11 14:43:34 +08:00
Archer
8d60ef505f Update 486.md 2024-07-11 14:41:48 +08:00
Archer
b14514c105 4.8.6 sandbox (#2020)
* fix: openapi doc

* update doc
2024-07-11 14:36:27 +08:00
Archer
11ffaaf2c5 4.8.6 sandbox (#2017)
* fix: openapi doc

* update doc
2024-07-11 10:34:59 +08:00
Archer
e2ae571d15 4.8.6 fix (#1970)
* fix: full text search match query

* perf: mongo schema import, Avoid duplicate import

* feat: mongo log store

* doc

* fix: sandbox outputs

* perf: desc color

* fix: node init

* perf code

* perf: chat header
2024-07-10 15:52:39 +08:00
Zong
f548e24e7d fix(env): typo template (#1990) 2024-07-08 15:05:23 +08:00
Archer
5605f1a892 4.8.6 fix (#1963)
* feat: log store

* fix: full text search match query

* perf: mongo schema import, Avoid duplicate import
2024-07-05 17:37:42 +08:00
Archer
88d10451c9 perf: collection created response (#1947)
* perf: collection created response

* update openapi doc

* remove default collection

* perf: chat ui

* fix: system prompt concat

* perf: published check

* perf: update app
2024-07-05 10:27:38 +08:00
Zong
8a7bd689ae fix(prompt): typo extra content (#1942)
* fix(prompt): typo extra content

* refactor(prompt): AIChat template
2024-07-04 19:08:26 +08:00
Archer
a9cdece341 4.8.6 merge (#1943)
* Dataset collection forbid (#1885)

* perf: tool call support same id

* feat: collection forbid

* feat: collection forbid

* Inheritance Permission for apps (#1897)

* feat: app schema define

chore: references of authapp

* feat: authApp method inheritance

* feat: create and update api

* feat: update

* feat: inheritance Permission controller for app.

* feat: abstract version of inheritPermission

* feat: ancestorId for apps

* chore: update app

* fix: inheritPermission abstract version

* feat: update folder defaultPermission

* feat: app update api

* chore: inheritance frontend

* chore: app list api

* feat: update defaultPermission in app deatil

* feat: backend api finished

* feat: app inheritance permission fe

* fix: app update defaultpermission causes collaborator miss

* fix: ts error

* chore: adjust the codes

* chore: i18n

chore: i18n

* chore: fe adjust and i18n

* chore: adjust the code

* feat: resume api;
chore: rewrite update api and inheritPermission methods

* chore: something

* chore: fe code adjusting

* feat: frontend adjusting

* chore: fe code adjusting

* chore: adjusting the code

* perf: fe loading

* format

* Inheritance fix (#1908)

* fix: SlideCard

* fix: authapp did not return parent app for inheritance app

* fix: fe adjusting

* feat: fe adjusing

* perf: inherit per ux

* doc

* fix: ts errors (#1916)

* perf: inherit permission

* fix: permission inherit

* Workflow type (#1938)

* perf: workflow type

tmp workflow

perf: workflow type

feat: custom field config

* perf: dynamic input

* perf: node classify

* perf: node classify

* perf: node classify

* perf: node classify

* fix: workflow custom input

* feat: text editor and customFeedback move to basic nodes

* feat: community system plugin

* fix: ts

* feat: exprEval plugin

* perf: workflow type

* perf: plugin important

* fix: default templates

* perf: markdown hr css

* lock

* perf: fetch url

* perf: new plugin version

* fix: chat histories update

* fix: collection paths invalid

* perf: app card ui

---------

Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com>
2024-07-04 17:42:09 +08:00
Zong
babf03c218 fix(prompt): typo template tag (#1918) 2024-07-04 14:53:46 +08:00
wh0amI
9e169a48e3 Update docker.md (#1910)
* Update docker.md

Fix typo: AUX --> AVX

* Update docker.md

'v' in 'AvX' should be upper case.
2024-07-02 15:43:51 +08:00
江晚
e223390231 添加AI对话时隐藏头部的功能,主要是适配移动端 (#1874) 2024-07-01 11:32:02 +08:00
Archer
3257744c76 Update intro.md 2024-06-30 10:14:02 +08:00
Archer
e1e112eaff Update intro.md 2024-06-30 09:45:59 +08:00
Archer
5c37d29451 Update config.yml 2024-06-28 00:34:25 +08:00
Archer
3a16f1a21c Update README.md 2024-06-28 00:33:14 +08:00
Archer
fa7b73f942 Update 485.md 2024-06-27 15:53:12 +08:00
Archer
f8610d750d Update 484.md 2024-06-27 15:52:53 +08:00
Archer
96a03e9927 4.8.5 test (#1869)
* update upgrade doc

* update upgrade doc
2024-06-27 12:21:05 +08:00
581 changed files with 24062 additions and 17642 deletions

View File

@@ -1,5 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: 微信交流
url: https://oss.laf.run/htr4n1-images/fastgpt-qr-code.jpg
- name: 飞书话题
url: https://oss.laf.run/otnvvf-imgs/1719505774252.jpg
about: FastGPT 全是问题群

1
.npmrc
View File

@@ -1,2 +1,3 @@
public-hoist-pattern[]=*tiktoken*
public-hoist-pattern[]=*@zilliz/milvus2-sdk-node*
registry=https://registry.npmjs.org/

View File

@@ -1,5 +0,0 @@
{
"recommendations": [
"inlang.vs-code-extension"
]
}

View File

@@ -1,46 +0,0 @@
# .vscode/i18n-ally-custom-framework.yml
# An array of strings which contain Language Ids defined by VS Code
# You can check available language ids here: https://code.visualstudio.com/docs/languages/identifiers
languageIds:
- javascript
- typescript
- javascriptreact
- typescriptreact
# An array of RegExes to find the key usage. **The key should be captured in the first match group**.
# You should unescape RegEx strings in order to fit in the YAML file
# To help with this, you can use https://www.freeformatter.com/json-escape.html
usageMatchRegex:
# The following example shows how to detect `t("your.i18n.keys")`
# the `{key}` will be placed by a proper keypath matching regex,
# you can ignore it and use your own matching rules as well
- "[^\\w\\d]t\\(['\"`]({key})['\"`]"
- "[^\\w\\d]commonT\\(['\"`]({key})['\"`]"
# 支持 appT("your.i18n.keys")
- "[^\\w\\d]appT\\(['\"`]({key})['\"`]"
# 支持 datasetT("your.i18n.keys")
- "[^\\w\\d]datasetT\\(['\"`]({key})['\"`]"
- "[^\\w\\d]fileT\\(['\"`]({key})['\"`]"
- "[^\\w\\d]publishT\\(['\"`]({key})['\"`]"
- "[^\\w\\d]workflowT\\(['\"`]({key})['\"`]"
- "[^\\w\\d]userT\\(['\"`]({key})['\"`]"
- "[^\\w\\d]chatT\\(['\"`]({key})['\"`]"
# A RegEx to set a custom scope range. This scope will be used as a prefix when detecting keys
# and works like how the i18next framework identifies the namespace scope from the
# useTranslation() hook.
# You should unescape RegEx strings in order to fit in the YAML file
# To help with this, you can use https://www.freeformatter.com/json-escape.html
scopeRangeRegex: "useTranslation\\(\\s*\\[?\\s*['\"`](.*?)['\"`]"
# An array of strings containing refactor templates.
# The "$1" will be replaced by the keypath specified.
# Optional: uncomment the following two lines to use
# refactorTemplates:
# - i18n.get("$1")
# If set to true, only enables this custom framework (will disable all built-in frameworks)
monopoly: true

11
.vscode/settings.json vendored
View File

@@ -2,16 +2,23 @@
"editor.formatOnSave": true,
"editor.mouseWheelZoom": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"prettier.prettierPath": "../node_modules/prettier",
"prettier.prettierPath": "node_modules/prettier",
"typescript.tsdk": "node_modules/typescript/lib",
"i18n-ally.localesPaths": [
"packages/web/i18n",
],
"i18n-ally.enabledParsers": ["json", "yaml", "js", "ts"],
"i18n-ally.enabledParsers": [
"json",
"yaml",
"js",
"ts"
],
"i18n-ally.keystyle": "nested",
"i18n-ally.sortKeys": true,
"i18n-ally.keepFulfilled": false,
"i18n-ally.sourceLanguage": "zh", // 根据此语言文件翻译其他语言文件的变量和内容
"i18n-ally.displayLanguage": "zh", // 显示语言
"i18n-ally.namespace": true,
"i18n-ally.pathMatcher": "{locale}/{namespaces}.json",
"i18n-ally.extract.targetPickingStrategy": "most-similar-by-key"
}

View File

@@ -120,9 +120,9 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
## 🏘️ 社区交流群
wx 扫一下加入
扫码加入飞书话题群 (新开,逐渐弃用微信群)
![](https://oss.laf.run/htr4n1-images/wechat-qr-code.jpg)
![](https://oss.laf.run/otnvvf-imgs/1719505774252.jpg)
<a href="#readme">
<img src="https://img.shields.io/badge/-返回顶部-7d09f1.svg" alt="#" align="right">

View File

@@ -19,13 +19,15 @@ FastGPT 商业版是基于 FastGPT 开源版的增强版本,增加了一些独
| 应用管理与高级编排 | ✅ | ✅ | ✅ |
| 文档知识库 | ✅ | ✅ | ✅ |
| 外部使用 | ✅ | ✅ | ✅ |
| 最大应用数量 | 500 | 无限制 | 由付费套餐决定 |
| 最大知识库数量(单个知识库内容无限制) | 30 | 无限制 | 由付费套餐决定 |
| 自定义版权信息 | ❌ | ✅ | 设计中 |
| 多租户与支付 | ❌ | ✅ | ✅ |
| 团队空间 | ❌ | ✅ | ✅ |
| 应用发布安全配置 | ❌ | ✅ | ✅ |
| 内容审核 | ❌ | ✅ | ✅ |
| web站点同步 | ❌ | ✅ | ✅ |
| 管理后台 | ❌ | ✅ | |
| 管理后台 | ❌ | ✅ | 不需要 |
| 增强训练模式 | ❌ | ✅ | ✅ |
| 图片知识库 | ❌ | 设计中 | 设计中 |
| 自动规划召回 | ❌ | 设计中 | 设计中 |

View File

@@ -11,7 +11,6 @@ weight: 707
![](/imgs/sealos-fastgpt.webp)
{{% alert icon="🤖" context="success" %}}
- MongoDB用于存储除了向量外的各类数据
@@ -105,20 +104,18 @@ brew install orbstack
{{< /tab >}}
{{< /tabs >}}
## 开始部署
### 1. 下载 docker-compose.yml
非 Linux 环境或无法访问外网环境,可手动创建一个目录,并下载配置文件和对应版本的`docker-compose.yml`
非 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)
- [docker-compose.yml](https://github.com/labring/FastGPT/blob/main/files/docker) (注意,不同向量库版本的文件不一样)
{{% alert icon="🤖" context="success" %}}
所有 `docker-compose.yml` 配置文件中 `MongoDB` 为 5.x需要用到AUX指令集部分 CPU 不支持,需手动更改其镜像版本为 4.4.24**需要自己在docker hub下载阿里云镜像没做备份
所有 `docker-compose.yml` 配置文件中 `MongoDB` 为 5.x需要用到AVX指令集部分 CPU 不支持,需手动更改其镜像版本为 4.4.24**需要自己在docker hub下载阿里云镜像没做备份
{{% /alert %}}
@@ -271,7 +268,6 @@ rs.status()
默认是写了OneAPi的连接地址和密钥可以通过修改`docker-compose.yml`fastgpt容器的环境变量实现。
`OPENAI_BASE_URL`API 接口的地址,需要加/v1
`CHAT_API_KEY`API 接口的凭证)。
@@ -315,8 +311,7 @@ docker-compose up -d
1. `docker exec -it fastgpt sh` 进入 FastGPT 容器。
2. 直接输入`env`命令查看所有环境变量。
### 为什么无法连接`本地模型`镜像。
### 为什么无法连接`本地模型`镜像
`docker-compose.yml`中使用了桥接的模式建立了`fastgpt`网络如想通过0.0.0.0或镜像名访问其它镜像,需将其它镜像也加入到网络中。
@@ -368,9 +363,9 @@ mongo连接失败查看mongo的运行状态**对应日志**。
由于服务初始化错误,系统重启导致。
* 90%是由于配置文件写不对,导致 JSON 解析报错
* 剩下的基本是因为向量数据库连不上
- 90%是由于配置文件写不对,导致 JSON 解析报错
- 剩下的基本是因为向量数据库连不上
### 如何修改密码
修改`docker-compose.yml`文件中`DEFAULT_ROOT_PSW`并重启即可,密码会自动更新。
修改`docker-compose.yml`文件中`DEFAULT_ROOT_PSW`并重启即可,密码会自动更新。

View File

@@ -7,8 +7,7 @@ toc: true
weight: 705
---
本文档介绍了如何设置开发环境以构建和测试 [FastGPT](https://fastgpt.in)。
本文档介绍了如何设置开发环境以构建和测试 [FastGPT](https://fastgpt.in)
## 前置依赖项
@@ -16,13 +15,14 @@ weight: 705
- [Git](http://git-scm.com/)
- [Docker](https://www.docker.com/)(构建镜像)
- [Node.js v18.17 / v20.x](http://nodejs.org)
- [Node.js v18.17 / v20.x](http://nodejs.org)版本尽量一样可以使用nvm管理node版本
- [pnpm](https://pnpm.io/) 版本 8.6.0 (目前官方的开发环境)
- make命令: 根据不同平台,百度安装 (官方是GNU Make 4.3)
## 开始本地开发
{{% alert context="success" %}}
1. 用户默认的时区为 `Asia/Shanghai`,非 linux 环境时候,获取系统时间会异常,本地开发时候,可以将用户的时区调整成 UTC+0
2. 建议先服务器装好**数据库**,再进行本地开发。
{{% /alert %}}
@@ -47,9 +47,10 @@ git clone git@github.com:<github_username>/FastGPT.git
### 3. 安装数据库
第一次开发,需要先部署数据库,建议本地开发可以随便找一台 2C2G 的轻量小数据库实践。数据库部署教程:[Docker 快速部署](/docs/development/docker/)。部署完了,可以本地访问其数据库。
第一次开发,需要先部署数据库,建议本地开发可以随便找一台 2C2G 的轻量小数据库实践或者新建文件夹并配置相关文件用以运行docker。数据库部署教程:[Docker 快速部署](/docs/development/docker/)。部署完了,可以本地访问其数据库。
{{% alert context="warning" %}}
Mongo 数据库需要注意,需要注意在连接地址中增加 `directConnection=true` 参数,才能连接上副本集的数据库。
{{% /alert %}}
### 4. 初始配置
@@ -57,7 +58,7 @@ Mongo 数据库需要注意,需要注意在连接地址中增加 `directConnec
**1. 环境变量**
复制`.env.template`文件,在同级目录下生成一个`.env.local` 文件,修改`.env.local` 里内容才是有效的变量。变量说明见 .env.template
复制`.env.template`文件,在同级目录下生成一个`.env.local` 文件,修改`.env.local` 里内容才是有效的变量。变量说明见 .env.template,主要需要修改`API_KEY`和数据库的地址与端口以及数据库账号的用户名和密码具体配置需要和docker配置文件相同其中用户名和密码如需修改需要修改docker配置文件、数据库和`.env.local`文件,不能只改一处。
**2. config 配置文件**
@@ -73,7 +74,7 @@ Mongo 数据库需要注意,需要注意在连接地址中增加 `directConnec
### 5. 运行
可参考项目根目录下的 `dev.md`
可参考项目根目录下的 `dev.md`,第一次编译运行可能会有点慢,需要点耐心哦
```bash
# 给自动化脚本代码执行权限(非 linux 系统, 可以手动执行里面的 postinstall.sh 文件内容)
@@ -114,7 +115,6 @@ make build name=app image=registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8
如果遇到问题,比如合并冲突或不知道如何打开拉取请求,请查看 GitHub 的[拉取请求教程](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests),了解如何解决合并冲突和其他问题。一旦您的 PR 被合并,您将自豪地被列为[贡献者表](https://github.com/labring/FastGPT/graphs/contributors)中的一员。
## QA
### 本地数据库无法连接
@@ -130,6 +130,7 @@ make build name=app image=registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8
FastGPT 在`pnpm i`后会执行`postinstall`脚本,用于自动生成`ChakraUI``Type`。如果没有权限,可以先执行`chmod -R +x ./scripts/`,再执行`pnpm i`
仍不可行的话,可以手动执行`./scripts/postinstall.sh`里的内容。
*如果是Windows下的话可以使用git bash给`postinstall`脚本添加执行权限并执行sh脚本*
### TypeError: Cannot read properties of null (reading 'useMemo' )
@@ -141,6 +142,9 @@ FastGPT 在`pnpm i`后会执行`postinstall`脚本,用于自动生成`ChakraUI
4. `cd projects/app`
5. `pnpm dev`
### Error response from daemon: error while creating mount source path 'XXX': mkdir XXX: file exists
这个错误可能是之前停止容器时有文件残留导致的首先需要确认相关镜像都全部关闭然后手动删除相关文件或者重启docker即可
## 加入社区
@@ -155,6 +159,7 @@ FastGPT 在`pnpm i`后会执行`postinstall`脚本,用于自动生成`ChakraUI
FastGPT 使用了 nextjs 的 page route 作为框架。为了区分好前后端代码,在目录分配上会分成 global, service, web 3个自目录分别对应着 `前后端共用``后端专用``前端专用`的代码。
### monorepo
FastGPT 采用 pnpm workspace 方式构建 monorepo 项目,主要分为两个部分:
- projects/app - FastGPT 主项目
@@ -173,6 +178,7 @@ support - 支撑功能(用户体系,计费,鉴权等)
common - 基础功能(日志管理,文件读写等)
{{% details title="代码结构说明" closed="true" %}}
```
.
├── .github // github 相关配置
@@ -200,4 +206,5 @@ common - 基础功能(日志管理,文件读写等)
├── README_ja.md
├── dev.md
```
{{% /details %}}

View File

@@ -7,18 +7,22 @@ toc: true
weight: 852
---
## 发起对话
{{% alert icon="🤖 " context="success" %}}
该接口的 API Key 需使用`应用特定的 key`,否则会报错。
有些包调用时,`BaseUrl`需要添加`v1`路径有些不需要如果出现404情况可补充`v1`重试。
{{% /alert %}}
## 发起对话(简易应用和工作流)
**对话接口兼容`GPT`的接口!如果你的项目使用的是标准的`GPT`官方接口,可以直接通过修改`BaseUrl`和 `Authorization`来访问 FastGpt 应用**
对话接口兼容`GPT`的接口!如果你的项目使用的是标准的`GPT`官方接口,可以直接通过修改`BaseUrl``Authorization`来访问 FastGpt 应用,不过需要注意下面几个规则:
## 请求
{{% alert icon="🤖 " context="success" %}}
* 传入的`model``temperature`等参数字段均无效,这些字段由编排决定。
* 不会返回实际消耗`Token`值,如果需要,可以设置`detail=true`,并手动计算 `responseData` 里的`tokens`值。
{{% /alert %}}
### 请求
{{< tabs tabTotal="2" >}}
{{< tab tabName="请求示例" >}}
@@ -67,7 +71,7 @@ curl --location --request POST 'https://api.fastgpt.in/api/v1/chat/completions'
{{< /tab >}}
{{< /tabs >}}
## 响应
### 响应
{{< tabs tabTotal="5" >}}
{{< tab tabName="detail=false,stream=false 响应" >}}
@@ -245,7 +249,7 @@ data: [{"moduleName":"知识库搜索","moduleType":"datasetSearchNode","running
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="detail=true,stream=true 时,event值" >}}
{{< tab tabName="event值" >}}
{{< markdownify >}}
event取值
@@ -265,6 +269,192 @@ event取值
{{< /tabs >}}
## 请求插件
插件的接口与对话接口一致,仅请求参数略有区别,有以下规定:
* 调用插件类型的应用时,接口默认为`detail`模式。
* 无需传入 `chatId`,因为插件只能运行一轮。
* 无需传入`messages`
* 通过传递`variables`来代表插件的输入。
* 通过获取`pluginData`来获取插件输出。
### 请求示例
```bash
curl --location --request POST 'http://localhost:3000/api/v1/chat/completions' \
--header 'Authorization: Bearer test-xxxxx' \
--header 'Content-Type: application/json' \
--data-raw '{
"stream": false,
"chatId": "test",
"variables": {
"query":"你好" # 我的插件输入有一个参数,变量名叫 query
}
}'
```
### 响应示例
{{< tabs tabTotal="3" >}}
{{< tab tabName="detail=true,stream=false 响应" >}}
{{< markdownify >}}
* 插件的输出可以通过查找`responseData`中, `moduleType=pluginOutput`的元素,其`pluginOutput`是插件的输出。
* 流输出,仍可以通过`choices`进行获取。
```json
{
"responseData": [
{
"nodeId": "fdDgXQ6SYn8v",
"moduleName": "AI 对话",
"moduleType": "chatNode",
"totalPoints": 0.685,
"model": "FastAI-3.5",
"tokens": 685,
"query": "你好",
"maxToken": 2000,
"historyPreview": [
{
"obj": "Human",
"value": "你好"
},
{
"obj": "AI",
"value": "你好!有什么可以帮助你的吗?欢迎向我提问。"
}
],
"contextTotalLen": 14,
"runningTime": 1.73
},
{
"nodeId": "pluginOutput",
"moduleName": "自定义插件输出",
"moduleType": "pluginOutput",
"totalPoints": 0,
"pluginOutput": {
"result": "你好!有什么可以帮助你的吗?欢迎向我提问。"
},
"runningTime": 0
}
],
"newVariables": {
"query": "你好"
},
"id": "safsafsa",
"model": "",
"usage": {
"prompt_tokens": 1,
"completion_tokens": 1,
"total_tokens": 1
},
"choices": [
{
"message": {
"role": "assistant",
"content": "你好!有什么可以帮助你的吗?欢迎向我提问。"
},
"finish_reason": "stop",
"index": 0
}
]
}
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="detail=true,stream=true 响应" >}}
{{< markdownify >}}
* 插件的输出可以通过获取`event=flowResponses`中的字符串,并将其反序列化后得到一个数组。同样的,查找 `moduleType=pluginOutput`的元素,其`pluginOutput`是插件的输出。
* 流输出,仍和对话接口一样获取。
```bash
event: flowNodeStatus
data: {"status":"running","name":"AI 对话"}
event: answer
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":""},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"你"},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"好"},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":""},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"有"},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"什"},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"么"},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"可以"},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"帮"},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"助"},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"你"},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"的"},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"吗"},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":""},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":""},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{},"index":0,"finish_reason":"stop"}]}
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}]
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="输出获取" >}}
{{< markdownify >}}
event取值
- answer: 返回给客户端的文本(最终会算作回答)
- fastAnswer: 指定回复返回给客户端的文本(最终会算作回答)
- toolCall: 执行工具
- toolParams: 工具参数
- toolResponse: 工具返回
- flowNodeStatus: 运行到的节点状态
- flowResponses: 节点完整响应
- updateVariables: 更新变量
- error: 报错
{{< /markdownify >}}
{{< /tab >}}
{{< /tabs >}}
## 使用案例
- [接入 NextWeb/ChatGPT web 等应用](/docs/use-cases/openapi)

View File

@@ -13,7 +13,7 @@ weight: 853
## 创建训练订单(4.6.9地址发生改动)
## 创建训练订单
{{< tabs tabTotal="2" >}}
{{< tab tabName="请求示例" >}}
@@ -26,6 +26,7 @@ curl --location --request POST 'https://api.fastgpt.in/api/support/wallet/usage/
--header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"datasetId": "知识库 ID",
"name": "可选,自定义订单名称,例如:文档训练-fastgpt.docx"
}'
```
@@ -127,8 +128,12 @@ curl --location --request POST 'http://localhost:3000/api/core/dataset/create' \
{{< markdownify >}}
```bash
curl --location --request GET 'http://localhost:3000/api/core/dataset/list?parentId=' \
--header 'Authorization: Bearer {{authorization}}' \
curl --location --request POST 'http://localhost:3000/api/core/dataset/list?parentId=' \
--header 'Authorization: Bearer xxxx' \
--header 'Content-Type: application/json' \
--data-raw '{
"parentId":""
}'
```
{{< /markdownify >}}
@@ -138,7 +143,7 @@ curl --location --request GET 'http://localhost:3000/api/core/dataset/list?paren
{{< markdownify >}}
{{% alert icon=" " context="success" %}}
- parentId - 父级ID不传或为空,代表获取根目录下的知识库
- parentId - 父级ID传空字符串或者null,代表获取根目录下的知识库
{{% /alert %}}
{{< /markdownify >}}

View File

@@ -1,5 +1,5 @@
---
title: 'V4.8.4'
title: 'V4.8.4(需要初始化)'
description: 'FastGPT V4.8.4 更新说明'
icon: 'upgrade'
draft: false
@@ -35,4 +35,4 @@ curl --location --request POST 'https://{{host}}/api/admin/init/484' \
6. 修复 - 定时执行初始化错误。
7. 修复 - 应用调用传参异常。
8. 修复 - ctrl + cv 复杂节点时nodeId错误。
9. 调整组件库全局theme。
9. 调整组件库全局theme。

View File

@@ -1,5 +1,5 @@
---
title: 'V4.8.5(进行中)'
title: 'V4.8.5(需要初始化)'
description: 'FastGPT V4.8.5 更新说明'
icon: 'upgrade'
draft: false
@@ -13,8 +13,8 @@ weight: 819
### 2. 修改镜像
- fastgpt 镜像 tag 修改成 v4.8.5-alpha
- 商业版镜像 tag 修改成 v4.8.5 -alpha
- fastgpt 镜像 tag 修改成 v4.8.5
- 商业版镜像 tag 修改成 v4.8.5
### 3. 执行初始化
@@ -54,9 +54,8 @@ curl --location --request POST 'https://{{host}}/api/admin/init/485' \
8. 优化 - 文件夹读取,支持单个文件夹超出 100 个文件
9. 优化 - 问答拆分/手动录入,当有`a`字段时,自动将`q`作为补充索引。
10. 优化 - 对话框页面代码
11. 修复 - SSR渲染
12. 优化 - 工作流新节点自动增加序号名
13. 修复 - 定时任务无法实际关闭
14. 修复 - 输入引导特殊字符导致正则报错
15. 修复 - 文件包含特殊字符`%`,且为转义时会导致页面崩溃
16. 修复 - 自定义输入选择知识库引用时页面崩溃
11. 优化 - 工作流新节点自动增加序号名
12. 修复 - 定时任务无法实际关闭
13. 修复 - 输入引导特殊字符导致正则报错
14. 修复 - 文件包含特殊字符`%`,且为转义时会导致页面崩溃
15. 修复 - 自定义输入选择知识库引用时页面崩溃

View File

@@ -0,0 +1,51 @@
---
title: 'V4.8.6(需要初始化)'
description: 'FastGPT V4.8.6 更新说明'
icon: 'upgrade'
draft: false
toc: true
weight: 818
---
## 升级指南
### 1. 做好数据库备份
### 2. 修改镜像
- fastgpt 镜像 tag 修改成 v4.8.6
- fastgpt-sandbox 镜像 tag 修改成 v4.8.6
- 商业版镜像 tag 修改成 v4.8.6
### 3. 执行初始化
从任意终端,发起 1 个 HTTP 请求。其中 {{rootkey}} 替换成环境变量里的 `rootkey`{{host}} 替换成**FastGPT 域名**。
```bash
curl --location --request POST 'https://{{host}}/api/admin/initv486' \
--header 'rootkey: {{rootkey}}' \
--header 'Content-Type: application/json'
```
会初始化应用的继承权限
-------
## V4.8.6 更新说明
1. 新增 - 应用权限继承
2. 新增 - 知识库支持单个集合禁用功能
3. 新增 - 系统插件模式变更,新增链接读取和数学计算器插件,正式版会更新如何自定义系统插件
4. 新增 - 代码沙盒运行参数
5. 新增 - AI对话时隐藏头部的功能主要是适配移动端
6. 优化 - 文件读取Mongo 默认使用从节点,减轻主节点压力
7. 优化 - 提示词模板
8. 优化 - Mongo model 重复加载
9. 修复 - 创建链接集合未返回 id
10. 修复 - 文档接口说明
11. 修复 - api system 提示合并
12. 修复 - 团队插件目录内的内容无法加载
13. 修复 - 知识库集合目录面包屑无法加载
14. 修复 - Markdown 导出对话异常
15. 修复 - 提示模板结束标签错误
16. 修复 - 文档描述

View File

@@ -0,0 +1,29 @@
---
title: 'V4.8.7(进行中)'
description: 'FastGPT V4.8.7 更新说明'
icon: 'upgrade'
draft: false
toc: true
weight: 817
---
## 升级指南
### 1. 做好数据库备份
### 2. 修改镜像
- fastgpt 镜像 tag 修改成 v4.8.7-alpha
- 商业版镜像 tag 修改成 v4.8.7-alpha
-------
## V4.8.7 更新说明
1. 新增 - 插件支持独立运行,发布和日志查看
2. 新增 - 应用搜索
3. 优化 - 对话框代码
4. 优化 - 升级 Dockerfile node 和 pnpm 版本
5. 优化 - local 域名部署,也可以正常使用 vision 模式
6. 修复 - 简易模式无法变更全局变量
7. 修复 - gpt4o 无法同时使用工具和图片

View File

@@ -78,7 +78,7 @@ weight: 404
},
{
"nodeId": "u6IAOEssxoZT",
"name": "工具调用(实验)",
"name": "工具调用",
"intro": "通过AI模型自动选择一个或多个功能块进行调用也可以对插件进行调用。",
"avatar": "/imgs/workflow/tool.svg",
"flowNodeType": "tools",
@@ -201,7 +201,7 @@ weight: 404
"x": 1623.9214305901633,
"y": 22.777089001645862
},
"version": "481",
"version": "486",
"inputs": [
{
"key": "system_addInputParam",

View File

@@ -192,7 +192,7 @@ export default async function (ctx: FunctionContext) {
},
{
"nodeId": "NOgbnBzUwDgT",
"name": "工具调用(实验)",
"name": "工具调用",
"intro": "通过AI模型自动选择一个或多个功能块进行调用也可以对插件进行调用。",
"avatar": "/imgs/workflow/tool.svg",
"flowNodeType": "tools",

View File

@@ -436,7 +436,7 @@ HTTP模块中需要设置 3 个工具参数:
},
{
"nodeId": "fYxwWym8flYL",
"name": "工具调用(实验)",
"name": "工具调用",
"intro": "通过AI模型自动选择一个或多个功能块进行调用也可以对插件进行调用。",
"avatar": "/imgs/workflow/tool.svg",
"flowNodeType": "tools",

View File

@@ -114,15 +114,15 @@ services:
# fastgpt
sandbox:
container_name: sandbox
image: ghcr.io/labring/fastgpt-sandbox:v4.8.4 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.4 # 阿里云
image: ghcr.io/labring/fastgpt-sandbox:latest # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:latest # 阿里云
networks:
- fastgpt
restart: always
fastgpt:
container_name: fastgpt
image: ghcr.io/labring/fastgpt:v4.8.4 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.4 # 阿里云
image: ghcr.io/labring/fastgpt:v4.8.6 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.6 # 阿里云
ports:
- 3000:3000
networks:
@@ -156,6 +156,7 @@ services:
- SANDBOX_URL=http://sandbox:3000
# 日志等级: debug, info, warn, error
- LOG_LEVEL=info
- STORE_LOG_LEVEL=warn
volumes:
- ./config.json:/app/data/config.json

View File

@@ -72,15 +72,15 @@ services:
# fastgpt
sandbox:
container_name: sandbox
image: ghcr.io/labring/fastgpt-sandbox:v4.8.4 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.4 # 阿里云
image: ghcr.io/labring/fastgpt-sandbox:latest # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:latest # 阿里云
networks:
- fastgpt
restart: always
fastgpt:
container_name: fastgpt
image: ghcr.io/labring/fastgpt:v4.8.4 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.4 # 阿里云
image: ghcr.io/labring/fastgpt:v4.8.6 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.6 # 阿里云
ports:
- 3000:3000
networks:
@@ -113,13 +113,14 @@ services:
- SANDBOX_URL=http://sandbox:3000
# 日志等级: debug, info, warn, error
- LOG_LEVEL=info
- STORE_LOG_LEVEL=warn
volumes:
- ./config.json:/app/data/config.json
# oneapi
mysql:
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/mysql:8.0.36 # 阿里云
# image: mysql:8.0.36
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/mysql:8.0.36 # 阿里云
image: mysql:8.0.36
container_name: mysql
restart: always
ports:

View File

@@ -53,15 +53,15 @@ services:
wait $$!
sandbox:
container_name: sandbox
image: ghcr.io/labring/fastgpt-sandbox:v4.8.4 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.4 # 阿里云
image: ghcr.io/labring/fastgpt-sandbox:latest # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:latest # 阿里云
networks:
- fastgpt
restart: always
fastgpt:
container_name: fastgpt
image: ghcr.io/labring/fastgpt:v4.8.4 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.4 # 阿里云
image: ghcr.io/labring/fastgpt:v4.8.6 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.6 # 阿里云
ports:
- 3000:3000
networks:
@@ -94,6 +94,7 @@ services:
- SANDBOX_URL=http://sandbox:3000
# 日志等级: debug, info, warn, error
- LOG_LEVEL=info
- STORE_LOG_LEVEL=warn
volumes:
- ./config.json:/app/data/config.json

View File

@@ -14,11 +14,11 @@
"devDependencies": {
"@chakra-ui/cli": "^2.4.1",
"husky": "^8.0.3",
"i18next": "23.10.0",
"lint-staged": "^13.3.0",
"next-i18next": "15.2.0",
"i18next": "23.11.5",
"next-i18next": "15.3.0",
"react-i18next": "14.1.2",
"prettier": "3.2.4",
"react-i18next": "13.5.0",
"zhlint": "^0.7.4"
},
"lint-staged": {
@@ -26,7 +26,7 @@
"./docSite/**/**/*.md": "npm run format-doc"
},
"engines": {
"node": ">=18.0.0",
"pnpm": ">=8.6.0"
"node": ">=18.16.0",
"pnpm": ">=9.0.0"
}
}
}

View File

@@ -5,7 +5,8 @@ const startCode = 507000;
export enum CommonErrEnum {
fileNotFound = 'fileNotFound',
unAuthFile = 'unAuthFile',
missingParams = 'missingParams'
missingParams = 'missingParams',
inheritPermissionError = 'inheritPermissionError'
}
const datasetErr = [
{
@@ -19,6 +20,10 @@ const datasetErr = [
{
statusText: CommonErrEnum.missingParams,
message: 'error.missingParams'
},
{
statusText: CommonErrEnum.inheritPermissionError,
message: 'error.inheritPermissionError'
}
];
export default datasetErr.reduce((acc, cur, index) => {

View File

@@ -9,6 +9,7 @@ export type MongoImageSchemaType = {
type: `${MongoImageTypeEnum}`;
metadata?: {
mime?: string; // image mime type.
relatedId?: string; // This id is associated with a set of images
};
};

View File

@@ -1,6 +1,7 @@
import dayjs from 'dayjs';
import cronParser from 'cron-parser';
export const formatTime2YMDHMW = (time?: Date) => dayjs(time).format('YYYY-MM-DD HH:mm:ss dddd');
export const formatTime2YMDHM = (time?: Date) =>
time ? dayjs(time).format('YYYY-MM-DD HH:mm') : '';
export const formatTime2YMD = (time?: Date) => (time ? dayjs(time).format('YYYY-MM-DD') : '');

View File

@@ -70,9 +70,3 @@ export type SystemEnvType = {
oneapiUrl?: string;
chatApiKey?: string;
};
// declare global {
// var feConfigs: FastGPTFeConfigsType;
// var systemEnv: SystemEnvType;
// var systemInitd: boolean;
// }

View File

@@ -100,7 +100,7 @@ export const Prompt_QuotePromptList: PromptTemplateItem[] = [
<QA>
{{quote}}
</QA>}
</QA>
思考流程:
1. 判断问题是否与 <QA></QA> 标记中的内容有关。
@@ -109,7 +109,12 @@ export const Prompt_QuotePromptList: PromptTemplateItem[] = [
4. 如果有相同的问题,直接输出对应答案。
5. 如果只有相近的问题,请把相近的问题和答案一起输出。
最后,避免提及你是从 QA 获取的知识,只需要回复答案。
回答要求:
- 如果没有相关的问答对,你需要澄清。
- 回答的内容应尽可能与 <QA></QA> 标记中的内容一致。
- 避免提及你是从 QA 获取的知识,只需要回复答案。
- 使用 Markdown 语法优化回答格式。
- 使用与问题相同的语言回答。
问题:"""{{question}}"""`
}

View File

@@ -20,7 +20,7 @@ A2:
<Context>
{{text}}
<Context/>
</Context>
`
};

View File

@@ -8,6 +8,8 @@ export enum AppTypeEnum {
httpPlugin = 'httpPlugin'
}
export const AppFolderTypeList = [AppTypeEnum.folder, AppTypeEnum.httpPlugin];
export const defaultTTSConfig: AppTTSConfigType = { type: 'web' };
export const defaultWhisperConfig: AppWhisperConfigType = {

View File

@@ -4,12 +4,12 @@ import yaml from 'js-yaml';
import { OpenAPIV3 } from 'openapi-types';
import { FlowNodeInputItemType, FlowNodeOutputItemType } from '../../workflow/type/io';
import { FlowNodeInputTypeEnum, FlowNodeOutputTypeEnum } from '../../workflow/node/constant';
import { NodeInputKeyEnum, WorkflowIOValueTypeEnum } from '../../workflow/constants';
import { WorkflowIOValueTypeEnum } from '../../workflow/constants';
import { PluginInputModule } from '../../workflow/template/system/pluginInput';
import { PluginOutputModule } from '../../workflow/template/system/pluginOutput';
import { HttpModule468 } from '../../workflow/template/system/http468';
import { HttpNode468 } from '../../workflow/template/system/http468';
import { HttpParamAndHeaderItemType } from '../../workflow/api';
import { StoreNodeItemType } from '../../workflow/type';
import { StoreNodeItemType } from '../../workflow/type/node';
import { HttpImgUrl } from '../../../common/file/image/constants';
import SwaggerParser from '@apidevtools/swagger-parser';
import { getHandleId } from '../../workflow/utils';
@@ -116,16 +116,7 @@ export const httpApiSchema2Plugins = async ({
required: param.required,
description: param.description,
toolDescription: param.description,
canEdit: true,
editField: {
key: true,
name: true,
description: true,
required: true,
dataType: true,
inputType: true,
isToolInput: true
}
canEdit: true
};
}) || []),
...(propsKeys?.map((key) => {
@@ -138,16 +129,7 @@ export const httpApiSchema2Plugins = async ({
required: false,
description: prop.description,
toolDescription: prop.description,
canEdit: true,
editField: {
key: true,
name: true,
description: true,
required: true,
dataType: true,
inputType: true,
isToolInput: true
}
canEdit: true
};
}) || [])
];
@@ -186,10 +168,6 @@ export const httpApiSchema2Plugins = async ({
label: param.name,
renderTypeList: [FlowNodeInputTypeEnum.reference],
canEdit: true,
editField: {
key: true,
valueType: true
},
value: [pluginInputId, inputIdMap.get(param.name)]
};
}) || []),
@@ -200,10 +178,6 @@ export const httpApiSchema2Plugins = async ({
label: key,
renderTypeList: [FlowNodeInputTypeEnum.reference],
canEdit: true,
editField: {
key: true,
valueType: true
},
value: [pluginInputId, inputIdMap.get(key)]
};
}) || [])
@@ -271,7 +245,7 @@ export const httpApiSchema2Plugins = async ({
}
/* Combine complete modules */
const modules: StoreNodeItemType[] = [
const nodes: StoreNodeItemType[] = [
{
nodeId: pluginInputId,
name: PluginInputModule.name,
@@ -280,8 +254,8 @@ export const httpApiSchema2Plugins = async ({
flowNodeType: PluginInputModule.flowNodeType,
showStatus: PluginInputModule.showStatus,
position: {
x: 616.4226348688949,
y: -165.05298493910115
x: 473.55206291900333,
y: -145.65080850146154
},
version: PluginInputModule.version,
inputs: pluginInputs,
@@ -295,8 +269,8 @@ export const httpApiSchema2Plugins = async ({
flowNodeType: PluginOutputModule.flowNodeType,
showStatus: PluginOutputModule.showStatus,
position: {
x: 1607.7142331269126,
y: -151.8669210746189
x: 1847.5956872650024,
y: 5.114324648101558
},
version: PluginOutputModule.version,
inputs: [
@@ -308,11 +282,6 @@ export const httpApiSchema2Plugins = async ({
required: false,
description: '',
canEdit: true,
editField: {
key: true,
description: true,
valueType: true
},
value: [httpId, 'httpRawResponse']
}
],
@@ -328,29 +297,18 @@ export const httpApiSchema2Plugins = async ({
},
{
nodeId: httpId,
name: HttpModule468.name,
intro: HttpModule468.intro,
avatar: HttpModule468.avatar,
flowNodeType: HttpModule468.flowNodeType,
name: HttpNode468.name,
intro: HttpNode468.intro,
avatar: HttpNode468.avatar,
flowNodeType: HttpNode468.flowNodeType,
showStatus: true,
position: {
x: 1042.549746602742,
y: -447.77496332641647
x: 1188.947986995841,
y: -473.52694296182904
},
version: HttpModule468.version,
version: HttpNode468.version,
inputs: [
{
key: NodeInputKeyEnum.addInputParam,
renderTypeList: [FlowNodeInputTypeEnum.addInputParam],
valueType: WorkflowIOValueTypeEnum.dynamic,
label: '',
required: false,
description: 'core.module.input.description.HTTP Dynamic Input',
editField: {
key: true,
valueType: true
}
},
HttpNode468.inputs[0],
...httpInputs,
{
key: 'system_httpMethod',
@@ -397,7 +355,7 @@ export const httpApiSchema2Plugins = async ({
required: false
}
],
outputs: HttpModule468.outputs
outputs: HttpNode468.outputs
}
];
@@ -422,7 +380,7 @@ export const httpApiSchema2Plugins = async ({
intro: item.description,
parentId,
type: AppTypeEnum.plugin,
modules,
modules: nodes,
edges,
pluginData: {
pluginUniId: item.name

View File

@@ -0,0 +1,10 @@
import { StoreNodeItemType } from '../../workflow/type/node';
import { FlowNodeInputItemType } from '../../workflow/type/io';
import { FlowNodeTypeEnum } from '../../workflow/node/constant';
export const getPluginInputsFromStoreNodes = (nodes: StoreNodeItemType[]) => {
return nodes.find((node) => node.flowNodeType === FlowNodeTypeEnum.pluginInput)?.inputs || [];
};
export const getPluginRunContent = (e: { pluginInputs: FlowNodeInputItemType[] }) => {
return JSON.stringify(e);
};

View File

@@ -1,4 +1,4 @@
import type { FlowNodeTemplateType, StoreNodeItemType } from '../workflow/type';
import type { FlowNodeTemplateType, StoreNodeItemType } from '../workflow/type/node';
import { AppTypeEnum } from './constants';
import { PermissionTypeEnum } from '../../support/permission/constant';
import { VariableInputEnum } from '../workflow/constants';
@@ -6,7 +6,7 @@ import { SelectedDatasetType } from '../workflow/api';
import { DatasetSearchModeEnum } from '../dataset/constants';
import { TeamTagSchema as TeamTagsSchemaType } from '@fastgpt/global/support/user/team/type.d';
import { StoreEdgeItemType } from '../workflow/type/edge';
import { PermissionValueType } from '../../support/permission/type';
import { PermissionSchemaType, PermissionValueType } from '../../support/permission/type';
import { AppPermission } from '../../support/permission/app/controller';
import { ParentIdType } from '../../common/parentFolder/type';
@@ -21,6 +21,7 @@ export type AppSchema = {
name: string;
avatar: string;
intro: string;
updateTime: Date;
modules: StoreNodeItemType[];
@@ -39,8 +40,7 @@ export type AppSchema = {
inited?: boolean;
teamTags: string[];
defaultPermission: PermissionValueType;
};
} & PermissionSchemaType;
export type AppListItemType = {
_id: string;
@@ -50,10 +50,9 @@ export type AppListItemType = {
intro: string;
type: AppTypeEnum;
updateTime: Date;
defaultPermission: PermissionValueType;
permission: AppPermission;
pluginData?: AppSchema['pluginData'];
};
permission: AppPermission;
} & PermissionSchemaType;
export type AppDetailType = AppSchema & {
permission: AppPermission;

View File

@@ -3,7 +3,7 @@ import { FlowNodeTypeEnum } from '../workflow/node/constant';
import { NodeInputKeyEnum, FlowNodeTemplateTypeEnum } from '../workflow/constants';
import type { FlowNodeInputItemType } from '../workflow/type/io.d';
import { getAppChatConfig } from '../workflow/utils';
import { StoreNodeItemType } from '../workflow/type';
import { StoreNodeItemType } from '../workflow/type/node';
import { DatasetSearchModeEnum } from '../dataset/constants';
export const getDefaultAppForm = (): AppSimpleEditFormType => ({

View File

@@ -1,4 +1,3 @@
import { StoreNodeItemType } from '../workflow/type';
import { StoreEdgeItemType } from '../workflow/type/edge';
import { AppChatConfigType, AppSchema } from './type';

View File

@@ -56,7 +56,10 @@ export const chats2GPTMessages = ({
text: item.text?.content || ''
};
}
if (item.type === 'file' && item.file?.type === ChatFileTypeEnum.image) {
if (
item.type === ChatItemValueTypeEnum.file &&
item.file?.type === ChatFileTypeEnum.image
) {
return {
type: 'image_url',
image_url: {
@@ -64,7 +67,6 @@ export const chats2GPTMessages = ({
}
};
}
return;
})
.filter(Boolean) as ChatCompletionContentPart[];
@@ -166,7 +168,7 @@ export const GPTMessages2Chats = (
} else if (item.type === 'image_url') {
value.push({
//@ts-ignore
type: 'file',
type: ChatItemValueTypeEnum.file,
file: {
type: ChatFileTypeEnum.image,
name: '',
@@ -175,7 +177,6 @@ export const GPTMessages2Chats = (
});
}
});
// @ts-ignore
}
} else if (
obj === ChatRoleEnum.AI &&

View File

@@ -56,7 +56,4 @@ export enum ChatStatusEnum {
finish = 'finish'
}
export const IMG_BLOCK_KEY = 'img-block';
export const FILE_BLOCK_KEY = 'file-block';
export const MARKDOWN_QUOTE_SIGN = 'QUOTE SIGN';

View File

@@ -1,4 +1,4 @@
import { ClassifyQuestionAgentItemType } from '../workflow/type';
import { ClassifyQuestionAgentItemType } from '../workflow/template/system/classifyQuestion/type';
import { SearchDataResponseItemType } from '../dataset/type';
import {
ChatFileTypeEnum,
@@ -13,8 +13,8 @@ import { DispatchNodeResponseKeyEnum } from '../workflow/runtime/constants';
import { AppChatConfigType, AppSchema, VariableItemType } from '../app/type';
import type { AppSchema as AppType } from '@fastgpt/global/core/app/type.d';
import { DatasetSearchModeEnum } from '../dataset/constants';
import { ChatBoxInputType } from '../../../../projects/app/src/components/ChatBox/type';
import { DispatchNodeResponseType } from '../workflow/runtime/type.d';
import { ChatBoxInputType } from '../../../../projects/app/src/components/core/chat/ChatContainer/ChatBox/type';
export type ChatSchema = {
_id: string;
@@ -115,6 +115,7 @@ export type ChatSiteItemType = (UserChatItemType | SystemChatItemType | AIChatIt
status: `${ChatStatusEnum}`;
moduleName?: string;
ttsBuffer?: Uint8Array;
responseData?: ChatHistoryItemResType[];
} & ChatBoxInputType;
/* --------- team chat --------- */

View File

@@ -3,6 +3,17 @@ import { FlowNodeTypeEnum } from '../workflow/node/constant';
import { ChatItemValueTypeEnum, ChatRoleEnum } from './constants';
import { ChatHistoryItemResType, ChatItemType, UserChatItemValueItemType } from './type.d';
// Concat 2 -> 1, and sort by role
export const concatHistories = (histories1: ChatItemType[], histories2: ChatItemType[]) => {
const newHistories = [...histories1, ...histories2];
return newHistories.sort((a, b) => {
if (a.obj === ChatRoleEnum.System) {
return -1;
}
return 1;
});
};
export const getChatTitleFromChatMessage = (message?: ChatItemType, defaultValue = '新对话') => {
// @ts-ignore
const textMsg = message?.value.find((item) => item.type === ChatItemValueTypeEnum.text);
@@ -54,11 +65,12 @@ export const filterPublicNodeResponseData = ({
}: {
flowResponses?: ChatHistoryItemResType[];
}) => {
const filedList = ['quoteList', 'moduleType'];
const filedList = ['quoteList', 'moduleType', 'pluginOutput'];
const filterModuleTypeList: any[] = [
FlowNodeTypeEnum.pluginModule,
FlowNodeTypeEnum.datasetSearchNode,
FlowNodeTypeEnum.tools
FlowNodeTypeEnum.tools,
FlowNodeTypeEnum.pluginOutput
];
return flowResponses
@@ -78,14 +90,22 @@ export const filterPublicNodeResponseData = ({
});
};
export const removeEmptyUserInput = (input: UserChatItemValueItemType[]) => {
return input.filter((item) => {
if (item.type === ChatItemValueTypeEnum.text && !item.text?.content?.trim()) {
return false;
}
if (item.type === ChatItemValueTypeEnum.file && !item.file?.url) {
return false;
}
return true;
});
export const removeEmptyUserInput = (input?: UserChatItemValueItemType[]) => {
return (
input?.filter((item) => {
if (item.type === ChatItemValueTypeEnum.text && !item.text?.content?.trim()) {
return false;
}
if (item.type === ChatItemValueTypeEnum.file && !item.file?.url) {
return false;
}
return true;
}) || []
);
};
export const getPluginOutputsFromChatResponses = (responses: ChatHistoryItemResType[]) => {
const outputs =
responses.find((item) => item.moduleType === FlowNodeTypeEnum.pluginOutput)?.pluginOutput ?? {};
return outputs;
};

View File

@@ -1,3 +1,4 @@
import { DatasetCollectionTypeEnum, TrainingModeEnum, TrainingTypeMap } from '../constants';
import { CollectionWithDatasetType, DatasetCollectionSchemaType } from '../type';
export const getCollectionSourceData = (
@@ -12,3 +13,13 @@ export const getCollectionSourceData = (
sourceName: collection?.name || ''
};
};
export const checkCollectionIsFolder = (type: DatasetCollectionTypeEnum) => {
return type === DatasetCollectionTypeEnum.folder || type === DatasetCollectionTypeEnum.virtual;
};
export const getTrainingTypeLabel = (type?: TrainingModeEnum) => {
if (!type) return '';
if (!TrainingTypeMap[type]) return '';
return TrainingTypeMap[type].label;
};

View File

@@ -27,7 +27,7 @@ export type DatasetSchemaType = {
intro: string;
type: DatasetTypeEnum;
status: `${DatasetStatusEnum}`;
permission: DatasetPermission;
// permission: DatasetPermission;
// metadata
websiteConfig?: {
@@ -48,6 +48,7 @@ export type DatasetCollectionSchemaType = {
type: DatasetCollectionTypeEnum;
createTime: Date;
updateTime: Date;
forbid?: boolean;
trainingType: TrainingModeEnum;
chunkSize: number;
@@ -89,6 +90,7 @@ export type DatasetDataSchemaType = {
updateTime: Date;
q: string; // large chunks or question
a: string; // answer or custom content
forbid?: boolean;
fullTextToken: string;
indexes: DatasetDataIndexItemType[];
rebuilding?: boolean;
@@ -144,6 +146,7 @@ export type DatasetListItemType = {
export type DatasetItemType = Omit<DatasetSchemaType, 'vectorModel' | 'agentModel'> & {
vectorModel: VectorModelItemType;
agentModel: LLMModelItemType;
permission: DatasetPermission;
};
/* ================= collection ===================== */

View File

@@ -1,5 +1,3 @@
import { StoreNodeItemType } from '../workflow/type';
export enum PluginTypeEnum {
folder = 'folder',
custom = 'custom',

View File

@@ -1,5 +1,5 @@
import { StoreEdgeItemType } from 'core/workflow/type/edge';
import type { StoreNodeItemType } from '../workflow/type';
import type { StoreNodeItemType } from '../workflow/type/node';
import { PluginTypeEnum } from './constants';
import { HttpAuthMethodType } from '../app/httpPlugin/type';

View File

@@ -1,8 +1,9 @@
import { StoreEdgeItemType } from 'core/workflow/type/edge';
import { ModuleTemplateTypeEnum } from '../workflow/constants';
import type { FlowModuleTemplateType, StoreNodeItemType } from '../workflow/type';
import type { StoreNodeItemType } from '../workflow/type/node';
import { PluginSourceEnum, PluginTypeEnum } from './constants';
import { MethodType } from './controller';
import { FlowNodeTemplateType } from '../workflow/type/node';
export type PluginItemSchema = {
_id: string;

View File

@@ -4,7 +4,7 @@ import { NodeInputKeyEnum } from './constants';
export type SelectedDatasetType = { datasetId: string }[];
export type HttpBodyType<T = Record<string, any>> = {
[NodeInputKeyEnum.addInputParam]: Record<string, any>;
// [NodeInputKeyEnum.addInputParam]: Record<string, any>;
} & T;
export type HttpQueryType = {
appId: string;

View File

@@ -1,13 +1,11 @@
export enum FlowNodeTemplateTypeEnum {
systemInput = 'systemInput',
ai = 'ai',
function = 'function',
tools = 'tools',
textAnswer = 'textAnswer',
functionCall = 'functionCall',
externalCall = 'externalCall',
personalPlugin = 'personalPlugin',
other = 'other'
other = 'other',
teamApp = 'teamApp'
}
export enum WorkflowIOValueTypeEnum {
@@ -84,6 +82,9 @@ export enum NodeInputKeyEnum {
datasetSearchExtensionModel = 'datasetSearchExtensionModel',
datasetSearchExtensionBg = 'datasetSearchExtensionBg',
// concat dataset
datasetQuoteList = 'system_datasetQuoteList',
// context extract
contextExtractInput = 'content',
extractKeys = 'extractKeys',
@@ -180,8 +181,6 @@ export const variableMap = {
}
};
export const DYNAMIC_INPUT_REFERENCE_KEY = 'DYNAMIC_INPUT_REFERENCE_KEY';
/* run time */
export enum RuntimeEdgeStatusEnum {
'waiting' = 'waiting',
@@ -190,3 +189,4 @@ export enum RuntimeEdgeStatusEnum {
}
export const VARIABLE_NODE_ID = 'VARIABLE_NODE_ID';
export const DYNAMIC_INPUT_REFERENCE_KEY = 'DYNAMIC_INPUT_REFERENCE_KEY';

View File

@@ -1,8 +1,11 @@
import { WorkflowIOValueTypeEnum } from '../constants';
export enum FlowNodeInputTypeEnum { // render ui
reference = 'reference', // reference to other node output
input = 'input', // one line input
numberInput = 'numberInput',
switch = 'switch', // true/false
select = 'select',
// editor
textarea = 'textarea',
@@ -22,8 +25,6 @@ export enum FlowNodeInputTypeEnum { // render ui
selectDatasetParamsModal = 'selectDatasetParamsModal',
settingDatasetQuotePrompt = 'settingDatasetQuotePrompt',
select = 'select',
hidden = 'hidden',
custom = 'custom'
}
@@ -114,8 +115,97 @@ export enum FlowNodeTypeEnum {
lafModule = 'lafModule',
ifElseNode = 'ifElseNode',
variableUpdate = 'variableUpdate',
code = 'code'
code = 'code',
textEditor = 'textEditor',
customFeedback = 'customFeedback'
}
// node IO value type
export const FlowValueTypeMap = {
[WorkflowIOValueTypeEnum.string]: {
label: 'string',
value: WorkflowIOValueTypeEnum.string,
description: ''
},
[WorkflowIOValueTypeEnum.number]: {
label: 'number',
value: WorkflowIOValueTypeEnum.number,
description: ''
},
[WorkflowIOValueTypeEnum.boolean]: {
label: 'boolean',
value: WorkflowIOValueTypeEnum.boolean,
description: ''
},
[WorkflowIOValueTypeEnum.object]: {
label: 'object',
value: WorkflowIOValueTypeEnum.object,
description: ''
},
[WorkflowIOValueTypeEnum.arrayString]: {
label: 'array<string>',
value: WorkflowIOValueTypeEnum.arrayString,
description: ''
},
[WorkflowIOValueTypeEnum.arrayNumber]: {
label: 'array<number>',
value: WorkflowIOValueTypeEnum.arrayNumber,
description: ''
},
[WorkflowIOValueTypeEnum.arrayBoolean]: {
label: 'array<boolean>',
value: WorkflowIOValueTypeEnum.arrayBoolean,
description: ''
},
[WorkflowIOValueTypeEnum.arrayObject]: {
label: 'array<object>',
value: WorkflowIOValueTypeEnum.arrayObject,
description: ''
},
[WorkflowIOValueTypeEnum.any]: {
label: 'any',
value: WorkflowIOValueTypeEnum.any,
description: ''
},
[WorkflowIOValueTypeEnum.chatHistory]: {
label: '历史记录',
value: WorkflowIOValueTypeEnum.chatHistory,
description: `{
obj: System | Human | AI;
value: string;
}[]`
},
[WorkflowIOValueTypeEnum.datasetQuote]: {
label: '知识库引用',
value: WorkflowIOValueTypeEnum.datasetQuote,
description: `{
id: string;
datasetId: string;
collectionId: string;
sourceName: string;
sourceId?: string;
q: string;
a: string
}[]`
},
[WorkflowIOValueTypeEnum.selectApp]: {
label: '选择应用',
value: WorkflowIOValueTypeEnum.selectApp,
description: ''
},
[WorkflowIOValueTypeEnum.selectDataset]: {
label: '选择知识库',
value: WorkflowIOValueTypeEnum.selectDataset,
description: `{
datasetId: string;
}`
},
[WorkflowIOValueTypeEnum.dynamic]: {
label: '动态输入',
value: WorkflowIOValueTypeEnum.dynamic,
description: ''
}
};
export const EDGE_TYPE = 'default';
export const defaultNodeVersion = '481';

View File

@@ -0,0 +1,17 @@
import { FlowNodeInputItemType } from '../../type/io';
export const getInputComponentProps = (input: FlowNodeInputItemType) => {
return {
referencePlaceholder: input.referencePlaceholder,
placeholder: input.placeholder,
maxLength: input.maxLength,
list: input.list,
markList: input.markList,
step: input.step,
max: input.max,
min: input.min,
defaultValue: input.defaultValue,
llmModelType: input.llmModelType,
customInputConfig: input.customInputConfig
};
};

View File

@@ -1,39 +0,0 @@
/*
react flow type
*/
import { FlowNodeInputTypeEnum, FlowNodeOutputTypeEnum, FlowNodeTypeEnum } from './constant';
import { WorkflowIOValueTypeEnum, NodeInputKeyEnum, NodeOutputKeyEnum } from '../constants';
import { SelectedDatasetType } from '../api';
import { LLMModelTypeEnum } from '../../ai/constants';
/* --------------- edit field ------------------- */
export type EditInputFieldMapType = EditOutputFieldMapType & {
inputType?: boolean;
};
export type EditOutputFieldMapType = {
key?: boolean;
description?: boolean;
valueType?: boolean; // output
required?: boolean;
defaultValue?: boolean;
};
export type EditNodeFieldType = {
inputType?: FlowNodeInputTypeEnum; // input type
valueType?: WorkflowIOValueTypeEnum;
required?: boolean;
key?: string;
label?: string;
description?: string;
isToolInput?: boolean;
defaultValue?: string;
maxLength?: number;
max?: number;
min?: number;
editField?: EditInputFieldMapType;
dynamicParamDefaultValue?: {
inputType?: FlowNodeInputTypeEnum; // input type
valueType?: WorkflowIOValueTypeEnum;
required?: boolean;
};
};

View File

@@ -1,11 +1,56 @@
import { ChatNodeUsageType } from '../../../support/wallet/bill/type';
import { ChatItemValueItemType, ToolRunResponseItemType } from '../../chat/type';
import {
ChatItemType,
UserChatItemValueItemType,
ChatItemValueItemType,
ToolRunResponseItemType
} from '../../chat/type';
import { FlowNodeInputItemType, FlowNodeOutputItemType } from '../type/io.d';
import { StoreNodeItemType } from '../type';
import { StoreNodeItemType } from '../type/node';
import { DispatchNodeResponseKeyEnum } from './constants';
import { StoreEdgeItemType } from '../type/edge';
import { NodeInputKeyEnum } from '../constants';
import { ClassifyQuestionAgentItemType } from '../template/system/classifyQuestion/type';
import { NextApiResponse } from 'next';
import { UserModelSchema } from '../../../support/user/type';
import { AppDetailType, AppSchema } from '../../app/type';
import { RuntimeNodeItemType } from '../runtime/type';
import { RuntimeEdgeItemType } from './edge';
/* workflow props */
export type ChatDispatchProps = {
res?: NextApiResponse;
mode: 'test' | 'chat' | 'debug';
teamId: string;
tmbId: string;
user: UserModelSchema;
app: AppDetailType | AppSchema;
chatId?: string;
responseChatItemId?: string;
histories: ChatItemType[];
variables: Record<string, any>; // global variable
query: UserChatItemValueItemType[]; // trigger query
stream: boolean;
detail: boolean; // response detail
maxRunTimes: number;
isToolCall?: boolean;
};
export type ModuleDispatchProps<T> = ChatDispatchProps & {
node: RuntimeNodeItemType;
runtimeNodes: RuntimeNodeItemType[];
runtimeEdges: RuntimeEdgeItemType[];
params: T;
};
export type SystemVariablesType = {
appId: string;
chatId?: string;
responseChatItemId?: string;
histories: ChatItemType[];
};
/* node props */
export type RuntimeNodeItemType = {
nodeId: StoreNodeItemType['nodeId'];
name: StoreNodeItemType['name'];
@@ -21,6 +66,16 @@ export type RuntimeNodeItemType = {
pluginId?: string;
};
export type PluginRuntimeType = {
teamId?: string;
name: string;
avatar: string;
showStatus?: boolean;
isTool?: boolean;
nodes: StoreNodeItemType[];
edges: StoreEdgeItemType[];
};
export type RuntimeEdgeItemType = StoreEdgeItemType & {
status: 'waiting' | 'active' | 'skipped';
};
@@ -87,6 +142,9 @@ export type DispatchNodeResponseType = {
// code
codeLog?: string;
// plugin
pluginOutput?: Record<string, any>;
};
export type DispatchNodeResultType<T> = {

View File

@@ -1,7 +1,7 @@
import { ChatCompletionRequestMessageRoleEnum } from '../../ai/constants';
import { NodeInputKeyEnum, NodeOutputKeyEnum } from '../constants';
import { FlowNodeTypeEnum } from '../node/constant';
import { StoreNodeItemType } from '../type';
import { StoreNodeItemType } from '../type/node';
import { StoreEdgeItemType } from '../type/edge';
import { RuntimeEdgeItemType, RuntimeNodeItemType } from './type';
import { VARIABLE_NODE_ID } from '../constants';
@@ -123,6 +123,7 @@ export const checkNodeRunStatus = ({
(item) => item.target === node.nodeId
);
// Entry
if (workflowEdges.length === 0) {
return 'run';
}

View File

@@ -5,47 +5,51 @@ import { AiChatModule } from './system/aiChat';
import { DatasetSearchModule } from './system/datasetSearch';
import { DatasetConcatModule } from './system/datasetConcat';
import { AssignedAnswerModule } from './system/assignedAnswer';
import { ClassifyQuestionModule } from './system/classifyQuestion';
import { ContextExtractModule } from './system/contextExtract';
import { HttpModule468 } from './system/http468';
import { ClassifyQuestionModule } from './system/classifyQuestion/index';
import { ContextExtractModule } from './system/contextExtract/index';
import { HttpNode468 } from './system/http468';
import { ToolModule } from './system/tools';
import { StopToolNode } from './system/stopTool';
import { RunAppModule } from './system/runApp';
import { RunAppModule } from './system/runApp/index';
import { PluginInputModule } from './system/pluginInput';
import { PluginOutputModule } from './system/pluginOutput';
import { RunPluginModule } from './system/runPlugin';
import { AiQueryExtension } from './system/queryExtension';
import type { FlowNodeTemplateType } from '../type';
import type { FlowNodeTemplateType } from '../type/node';
import { LafModule } from './system/laf';
import { IfElseNode } from './system/ifElse/index';
import { VariableUpdateNode } from './system/variableUpdate';
import { CodeNode } from './system/sandbox';
import { TextEditorNode } from './system/textEditor';
import { CustomFeedbackNode } from './system/customFeedback';
const systemNodes: FlowNodeTemplateType[] = [
AiChatModule,
TextEditorNode,
AssignedAnswerModule,
DatasetSearchModule,
DatasetConcatModule,
RunAppModule,
ToolModule,
StopToolNode,
ClassifyQuestionModule,
ContextExtractModule,
HttpModule468,
HttpNode468,
AiQueryExtension,
LafModule,
IfElseNode,
VariableUpdateNode,
CodeNode
CodeNode,
RunAppModule
];
/* app flow module templates */
export const appSystemModuleTemplates: FlowNodeTemplateType[] = [
SystemConfigNode,
WorkflowStart,
...systemNodes
...systemNodes,
CustomFeedbackNode
];
/* plugin flow module templates */
export const pluginSystemModuleTemplates: FlowNodeTemplateType[] = [
@@ -56,11 +60,11 @@ export const pluginSystemModuleTemplates: FlowNodeTemplateType[] = [
/* all module */
export const moduleTemplatesFlat: FlowNodeTemplateType[] = [
...systemNodes,
...appSystemModuleTemplates.concat(
pluginSystemModuleTemplates.filter(
(item) => !appSystemModuleTemplates.find((app) => app.id === item.id)
)
),
EmptyNode,
SystemConfigNode,
WorkflowStart,
PluginInputModule,
PluginOutputModule,
RunPluginModule
];

View File

@@ -9,9 +9,9 @@ export const Output_Template_AddOutput: FlowNodeOutputItemType = {
type: FlowNodeOutputTypeEnum.dynamic,
valueType: WorkflowIOValueTypeEnum.dynamic,
label: '',
editField: {
key: true,
valueType: true
customFieldConfig: {
selectValueTypeList: Object.values(WorkflowIOValueTypeEnum),
showDescription: false,
showDefaultValue: false
}
};

View File

@@ -3,7 +3,7 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
import { FlowNodeTemplateType } from '../../type/node';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
@@ -22,7 +22,7 @@ import { getHandleConfig } from '../utils';
export const AiChatModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.chatNode,
templateType: FlowNodeTemplateTypeEnum.textAnswer,
templateType: FlowNodeTemplateTypeEnum.ai,
flowNodeType: FlowNodeTypeEnum.chatNode,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),

View File

@@ -1,5 +1,5 @@
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/index.d';
import { FlowNodeTemplateType } from '../../type/node.d';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
@@ -9,7 +9,7 @@ import { getHandleConfig } from '../utils';
export const AssignedAnswerModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.answerNode,
templateType: FlowNodeTemplateTypeEnum.textAnswer,
templateType: FlowNodeTemplateTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.answerNode,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),

View File

@@ -2,26 +2,26 @@ import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
} from '../../../node/constant';
import { FlowNodeTemplateType } from '../../../type/node';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
FlowNodeTemplateTypeEnum,
NodeOutputKeyEnum
} from '../../constants';
} from '../../../constants';
import {
Input_Template_SelectAIModel,
Input_Template_History,
Input_Template_UserChatInput
} from '../input';
import { Input_Template_System_Prompt } from '../input';
import { LLMModelTypeEnum } from '../../../ai/constants';
import { getHandleConfig } from '../utils';
} from '../../input';
import { Input_Template_System_Prompt } from '../../input';
import { LLMModelTypeEnum } from '../../../../ai/constants';
import { getHandleConfig } from '../../utils';
export const ClassifyQuestionModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.classifyQuestion,
templateType: FlowNodeTemplateTypeEnum.functionCall,
templateType: FlowNodeTemplateTypeEnum.ai,
flowNodeType: FlowNodeTypeEnum.classifyQuestion,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(true, false, true, true),

View File

@@ -0,0 +1,4 @@
export type ClassifyQuestionAgentItemType = {
value: string;
key: string;
};

View File

@@ -2,21 +2,21 @@ import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
} from '../../../node/constant';
import { FlowNodeTemplateType } from '../../../type/node';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import { Input_Template_SelectAIModel, Input_Template_History } from '../input';
import { LLMModelTypeEnum } from '../../../ai/constants';
import { getHandleConfig } from '../utils';
} from '../../../constants';
import { Input_Template_SelectAIModel, Input_Template_History } from '../../input';
import { LLMModelTypeEnum } from '../../../../ai/constants';
import { getHandleConfig } from '../../utils';
export const ContextExtractModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.contentExtract,
templateType: FlowNodeTemplateTypeEnum.functionCall,
templateType: FlowNodeTemplateTypeEnum.ai,
flowNodeType: FlowNodeTypeEnum.contentExtract,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),

View File

@@ -0,0 +1,8 @@
export type ContextExtractAgentItemType = {
valueType: 'string' | 'number' | 'boolean';
desc: string;
key: string;
required: boolean;
defaultValue?: string;
enum?: string;
};

View File

@@ -0,0 +1,30 @@
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/node.d';
import {
WorkflowIOValueTypeEnum,
FlowNodeTemplateTypeEnum,
NodeInputKeyEnum
} from '../../constants';
import { getHandleConfig } from '../utils';
export const CustomFeedbackNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.customFeedback,
templateType: FlowNodeTemplateTypeEnum.other,
flowNodeType: FlowNodeTypeEnum.customFeedback,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
avatar: '/imgs/workflow/customFeedback.svg',
name: '自定义反馈',
intro: '该模块被触发时,会给当前的对话记录增加一条反馈。可用于自动记录对话效果等。',
version: '486',
inputs: [
{
key: NodeInputKeyEnum.textareaInput,
renderTypeList: [FlowNodeInputTypeEnum.textarea, FlowNodeInputTypeEnum.reference],
valueType: WorkflowIOValueTypeEnum.string,
required: true,
label: '反馈的文本'
}
],
outputs: []
};

View File

@@ -3,7 +3,7 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
import { FlowNodeTemplateType } from '../../type/node';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
@@ -27,8 +27,7 @@ export const getOneQuoteInputTemplate = ({
renderTypeList: [FlowNodeInputTypeEnum.reference],
label: `引用${index}`,
debugLabel: '知识库引用',
canEdit: key !== defaultQuoteKey,
description: '',
canEdit: true,
valueType: WorkflowIOValueTypeEnum.datasetQuote
});
@@ -42,7 +41,7 @@ export const DatasetConcatModule: FlowNodeTemplateType = {
name: '知识库搜索引用合并',
intro: '可以将多个知识库搜索结果进行合并输出。使用 RRF 的合并方式进行最终排序输出。',
showStatus: false,
version: '481',
version: '486',
inputs: [
{
key: NodeInputKeyEnum.datasetMaxTokens,
@@ -52,11 +51,11 @@ export const DatasetConcatModule: FlowNodeTemplateType = {
valueType: WorkflowIOValueTypeEnum.number
},
{
key: 'customComponent',
key: NodeInputKeyEnum.datasetQuoteList,
renderTypeList: [FlowNodeInputTypeEnum.custom],
label: ''
},
getOneQuoteInputTemplate({ key: defaultQuoteKey, index: 1 })
}
// getOneQuoteInputTemplate({ key: defaultQuoteKey, index: 1 })
],
outputs: [
{

View File

@@ -3,7 +3,7 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
import { FlowNodeTemplateType } from '../../type/node';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
@@ -19,7 +19,7 @@ export const Dataset_SEARCH_DESC =
export const DatasetSearchModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.datasetSearchNode,
templateType: FlowNodeTemplateTypeEnum.functionCall,
templateType: FlowNodeTemplateTypeEnum.ai,
flowNodeType: FlowNodeTypeEnum.datasetSearchNode,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),

View File

@@ -1,5 +1,5 @@
import { FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
import { FlowNodeTemplateType } from '../../type/node';
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { getHandleConfig } from '../utils';

View File

@@ -3,7 +3,7 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/index.d';
import { FlowNodeTemplateType } from '../../type/node.d';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
@@ -14,9 +14,9 @@ import { Input_Template_DynamicInput } from '../input';
import { Output_Template_AddOutput } from '../output';
import { getHandleConfig } from '../utils';
export const HttpModule468: FlowNodeTemplateType = {
export const HttpNode468: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.httpRequest468,
templateType: FlowNodeTemplateTypeEnum.externalCall,
templateType: FlowNodeTemplateTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.httpRequest468,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
@@ -30,9 +30,10 @@ export const HttpModule468: FlowNodeTemplateType = {
{
...Input_Template_DynamicInput,
description: 'core.module.input.description.HTTP Dynamic Input',
editField: {
key: true,
valueType: true
customInputConfig: {
selectValueTypeList: Object.values(WorkflowIOValueTypeEnum),
showDescription: false,
showDefaultValue: true
}
},
{
@@ -80,7 +81,9 @@ export const HttpModule468: FlowNodeTemplateType = {
}
],
outputs: [
Output_Template_AddOutput,
{
...Output_Template_AddOutput
},
{
id: NodeOutputKeyEnum.error,
key: NodeOutputKeyEnum.error,

View File

@@ -9,7 +9,7 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../../node/constant';
import { FlowNodeTemplateType } from '../../../type';
import { FlowNodeTemplateType } from '../../../type/node';
import { getHandleConfig } from '../../utils';
export const IfElseNode: FlowNodeTemplateType = {

View File

@@ -3,7 +3,7 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/index.d';
import { FlowNodeTemplateType } from '../../type/node.d';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
@@ -14,9 +14,15 @@ import { Input_Template_DynamicInput } from '../input';
import { Output_Template_AddOutput } from '../output';
import { getHandleConfig } from '../utils';
export const nodeLafCustomInputConfig = {
selectValueTypeList: Object.values(WorkflowIOValueTypeEnum),
showDescription: false,
showDefaultValue: true
};
export const LafModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.lafModule,
templateType: FlowNodeTemplateTypeEnum.externalCall,
templateType: FlowNodeTemplateTypeEnum.other,
flowNodeType: FlowNodeTypeEnum.lafModule,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
@@ -30,10 +36,7 @@ export const LafModule: FlowNodeTemplateType = {
{
...Input_Template_DynamicInput,
description: '接收前方节点的输出值作为变量,这些变量可以被 Laf 请求参数使用。',
editField: {
key: true,
valueType: true
}
customInputConfig: nodeLafCustomInputConfig
},
{
key: NodeInputKeyEnum.httpReqUrl,

View File

@@ -1,6 +1,6 @@
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
import { FlowNodeTemplateType } from '../../type/node';
import { getHandleConfig } from '../utils';
export const PluginInputModule: FlowNodeTemplateType = {
@@ -12,8 +12,8 @@ export const PluginInputModule: FlowNodeTemplateType = {
unique: true,
forbidDelete: true,
avatar: '/imgs/workflow/input.png',
name: '自定义插件输入',
intro: '自定义配置外部输入,使用插件时,仅暴露自定义配置的输入',
name: '插件输入',
intro: '可以配置插件需要哪些输入,利用这些输入来运行插件',
showStatus: false,
version: '481',
inputs: [],

View File

@@ -1,6 +1,6 @@
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
import { FlowNodeTemplateType } from '../../type/node';
import { getHandleConfig } from '../utils';
export const PluginOutputModule: FlowNodeTemplateType = {

View File

@@ -3,7 +3,7 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/index.d';
import { FlowNodeTemplateType } from '../../type/node.d';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
@@ -19,7 +19,7 @@ import { LLMModelTypeEnum } from '../../../ai/constants';
import { getHandleConfig } from '../utils';
export const AiQueryExtension: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.chatNode,
id: FlowNodeTypeEnum.queryExtension,
templateType: FlowNodeTemplateTypeEnum.other,
flowNodeType: FlowNodeTypeEnum.queryExtension,
sourceHandle: getHandleConfig(true, true, true, true),

View File

@@ -2,20 +2,20 @@ import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/index.d';
} from '../../../node/constant';
import { FlowNodeTemplateType } from '../../../type/node.d';
import {
WorkflowIOValueTypeEnum,
NodeInputKeyEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import { Input_Template_History, Input_Template_UserChatInput } from '../input';
import { getHandleConfig } from '../utils';
} from '../../../constants';
import { Input_Template_History, Input_Template_UserChatInput } from '../../input';
import { getHandleConfig } from '../../utils';
export const RunAppModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.runApp,
templateType: FlowNodeTemplateTypeEnum.externalCall,
templateType: FlowNodeTemplateTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.runApp,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),

View File

@@ -0,0 +1,5 @@
export type SelectAppItemType = {
id: string;
// name: string;
// logo?: string;
};

View File

@@ -1,11 +1,11 @@
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
import { FlowNodeTemplateType } from '../../type/node';
import { getHandleConfig } from '../utils';
export const RunPluginModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.pluginModule,
templateType: FlowNodeTemplateTypeEnum.externalCall,
templateType: FlowNodeTemplateTypeEnum.other,
flowNodeType: FlowNodeTypeEnum.pluginModule,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),

View File

@@ -9,7 +9,7 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../../node/constant';
import { FlowNodeTemplateType } from '../../../type';
import { FlowNodeTemplateType } from '../../../type/node';
import { getHandleConfig } from '../../utils';
import { Input_Template_DynamicInput } from '../../input';
import { Output_Template_AddOutput } from '../../output';
@@ -30,11 +30,38 @@ export const CodeNode: FlowNodeTemplateType = {
{
...Input_Template_DynamicInput,
description: '这些变量会作为代码的运行的输入参数',
editField: {
key: true,
valueType: true
customInputConfig: {
selectValueTypeList: Object.values(WorkflowIOValueTypeEnum),
showDescription: false,
showDefaultValue: true
}
},
{
renderTypeList: [FlowNodeInputTypeEnum.reference],
valueType: WorkflowIOValueTypeEnum.string,
canEdit: true,
key: 'data1',
label: 'data1',
customInputConfig: {
selectValueTypeList: Object.values(WorkflowIOValueTypeEnum),
showDescription: false,
showDefaultValue: true
},
required: true
},
{
renderTypeList: [FlowNodeInputTypeEnum.reference],
valueType: WorkflowIOValueTypeEnum.string,
canEdit: true,
key: 'data2',
label: 'data2',
customInputConfig: {
selectValueTypeList: Object.values(WorkflowIOValueTypeEnum),
showDescription: false,
showDefaultValue: true
},
required: true
},
{
key: NodeInputKeyEnum.codeType,
renderTypeList: [FlowNodeInputTypeEnum.hidden],
@@ -51,7 +78,7 @@ export const CodeNode: FlowNodeTemplateType = {
outputs: [
{
...Output_Template_AddOutput,
description: '将代码中 return 的对象作为输出,传递给后续的节点'
description: '将代码中 return 的对象作为输出,传递给后续的节点。变量名需要对应 return 的 key'
},
{
id: NodeOutputKeyEnum.rawResponse,

View File

@@ -1,11 +1,11 @@
import { FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type';
import { FlowNodeTemplateType } from '../../type/node';
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { getHandleConfig } from '../utils';
export const StopToolNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.stopTool,
templateType: FlowNodeTemplateTypeEnum.functionCall,
templateType: FlowNodeTemplateTypeEnum.ai,
flowNodeType: FlowNodeTypeEnum.stopTool,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(true, true, true, true),

View File

@@ -1,5 +1,5 @@
import { FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/index.d';
import { FlowNodeTemplateType } from '../../type/node.d';
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { getHandleConfig } from '../utils';

View File

@@ -0,0 +1,54 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/node.d';
import {
WorkflowIOValueTypeEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum,
NodeInputKeyEnum
} from '../../constants';
import { getHandleConfig } from '../utils';
import { Input_Template_DynamicInput } from '../input';
export const TextEditorNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.textEditor,
templateType: FlowNodeTemplateTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.textEditor,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
avatar: '/imgs/workflow/textEditor.svg',
name: '文本拼接',
intro: '可对固定或传入的文本进行加工后输出,非字符串类型数据最终会转成字符串类型。',
version: '486',
inputs: [
{
...Input_Template_DynamicInput,
description: '可以引用其他节点的输出,作为文本拼接的变量,通过 {{字段名}} 来引用变量',
customInputConfig: {
selectValueTypeList: Object.values(WorkflowIOValueTypeEnum),
showDescription: false,
showDefaultValue: false
}
},
{
key: NodeInputKeyEnum.textareaInput,
renderTypeList: [FlowNodeInputTypeEnum.textarea],
valueType: WorkflowIOValueTypeEnum.string,
required: true,
label: '拼接文本',
placeholder: '可通过 {{字段名}} 来引用变量'
}
],
outputs: [
{
id: NodeOutputKeyEnum.text,
key: NodeOutputKeyEnum.text,
label: '拼接结果',
type: FlowNodeOutputTypeEnum.static,
valueType: WorkflowIOValueTypeEnum.string
}
]
};

View File

@@ -3,7 +3,7 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/index.d';
import { FlowNodeTemplateType } from '../../type/node.d';
import {
WorkflowIOValueTypeEnum,
NodeOutputKeyEnum,
@@ -23,11 +23,11 @@ import { getHandleConfig } from '../utils';
export const ToolModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.tools,
templateType: FlowNodeTemplateTypeEnum.functionCall,
templateType: FlowNodeTemplateTypeEnum.ai,
sourceHandle: getHandleConfig(true, true, false, true),
targetHandle: getHandleConfig(true, true, false, true),
avatar: '/imgs/workflow/tool.svg',
name: '工具调用(实验)',
name: '工具调用',
intro: '通过AI模型自动选择一个或多个功能块进行调用也可以对插件进行调用。',
showStatus: true,
version: '481',

View File

@@ -1,5 +1,5 @@
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '../../../node/constant';
import { FlowNodeTemplateType } from '../../../type/index.d';
import { FlowNodeTemplateType } from '../../../type/node.d';
import {
FlowNodeTemplateTypeEnum,
NodeInputKeyEnum,
@@ -25,10 +25,6 @@ export const VariableUpdateNode: FlowNodeTemplateType = {
valueType: WorkflowIOValueTypeEnum.any,
label: '',
renderTypeList: [FlowNodeInputTypeEnum.hidden],
editField: {
key: true,
valueType: true
},
value: [
{
variable: ['', ''],

View File

@@ -1,5 +1,5 @@
import { FlowNodeOutputTypeEnum, FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/index.d';
import { FlowNodeTemplateType } from '../../type/node.d';
import {
WorkflowIOValueTypeEnum,
NodeOutputKeyEnum,
@@ -31,3 +31,6 @@ export const WorkflowStart: FlowNodeTemplateType = {
}
]
};
export const isWorkflowStartOutput = (key?: string) =>
!!WorkflowStart.outputs.find((output) => output.key === key);

View File

@@ -1,3 +1,5 @@
import { FlowNodeInputItemType, FlowNodeOutputItemType } from './io';
export type FlowNodeChangeProps = { nodeId: string } & (
| {
type: 'attr'; // key: attr, value: new value
@@ -7,16 +9,16 @@ export type FlowNodeChangeProps = { nodeId: string } & (
| {
type: 'updateInput'; // key: update input key, value: new input value
key: string;
value: any;
value: FlowNodeInputItemType;
}
| {
type: 'replaceInput'; // key: old input key, value: new input value
key: string;
value: any;
value: FlowNodeInputItemType;
}
| {
type: 'addInput'; // key: null, value: new input value
value: any;
value: FlowNodeInputItemType;
index?: number;
}
| {
@@ -26,16 +28,16 @@ export type FlowNodeChangeProps = { nodeId: string } & (
| {
type: 'updateOutput'; // key: update output key, value: new output value
key: string;
value: any;
value: FlowNodeOutputItemType;
}
| {
type: 'replaceOutput'; // key: old output key, value: new output value
key: string;
value: any;
value: FlowNodeOutputItemType;
}
| {
type: 'addOutput'; // key: null, value: new output value
value: any;
value: FlowNodeOutputItemType;
index?: number;
}
| {

View File

@@ -6,148 +6,53 @@ import {
VariableInputEnum
} from '../constants';
import { DispatchNodeResponseKeyEnum } from '../runtime/constants';
import { FlowNodeInputItemType, FlowNodeOutputItemType } from './io.d';
import { UserModelSchema } from '../../../support/user/type';
import { CustomInputItemType, FlowNodeInputItemType, FlowNodeOutputItemType } from './io.d';
import {
ChatHistoryItemResType,
ChatItemType,
ChatItemValueItemType,
ToolRunResponseItemType,
UserChatItemValueItemType
ToolRunResponseItemType
} from '../../chat/type';
import { ChatNodeUsageType } from '../../../support/wallet/bill/type';
import { RuntimeNodeItemType } from '../runtime/type';
import { PluginTypeEnum } from '../../plugin/constants';
import { RuntimeEdgeItemType, StoreEdgeItemType } from './edge';
import { NextApiResponse } from 'next';
import { AppDetailType, AppSchema } from '../../app/type';
import { StoreEdgeItemType } from './edge';
import { AppChatConfigType } from '../../app/type';
import { ParentIdType } from 'common/parentFolder/type';
import { AppTypeEnum } from 'core/app/constants';
import { FlowNodeTemplateType, StoreNodeItemType } from './node';
export type FlowNodeCommonType = {
flowNodeType: FlowNodeTypeEnum; // render node card
export type WorkflowTemplateBasicType = {
nodes: StoreNodeItemType[];
edges: StoreEdgeItemType[];
chatConfigs?: AppChatConfigType;
};
export type WorkflowTemplateType = {
id: string;
parentId?: string;
isFolder?: boolean;
avatar?: string;
name: string;
intro?: string; // template list intro
showStatus?: boolean; // chatting response step status
avatar: string;
intro?: string;
author?: string;
version: string;
// data
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
showStatus?: boolean;
weight?: number;
// plugin data
pluginId?: string;
pluginType?: AppTypeEnum;
// parentId: ParentIdType;
workflow: WorkflowTemplateBasicType;
};
export type FlowNodeTemplateType = FlowNodeCommonType & {
id: string; // node id, unique
templateType: `${FlowNodeTemplateTypeEnum}`;
// show handle
sourceHandle?: {
left: boolean;
right: boolean;
top: boolean;
bottom: boolean;
};
targetHandle?: {
left: boolean;
right: boolean;
top: boolean;
bottom: boolean;
};
// info
isTool?: boolean; // can be connected by tool
// action
forbidDelete?: boolean; // forbid delete
unique?: boolean;
// template market
export type TemplateMarketItemType = WorkflowTemplateType & {
tags?: { id: string; label: string }[];
};
export type FlowNodeItemType = FlowNodeTemplateType & {
nodeId: string;
isError?: boolean;
debugResult?: {
status: 'running' | 'success' | 'skipped' | 'failed';
message?: string;
showResult?: boolean; // show and hide result modal
response?: ChatHistoryItemResType;
isExpired?: boolean;
};
};
export type nodeTemplateListType = {
type: `${FlowNodeTemplateTypeEnum}`;
label: string;
list: FlowNodeTemplateType[];
}[];
// system plugin
export type SystemPluginTemplateItemType = WorkflowTemplateType & {
templateType: FlowNodeTemplateTypeEnum;
isTool?: boolean;
// store node type
export type StoreNodeItemType = FlowNodeCommonType & {
nodeId: string;
position?: {
x: number;
y: number;
};
};
originCost: number; // n points/one time
currentCost: number;
/* connection type */
export type NodeTargetNodeItemType = {
nodeId: string;
sourceHandle: string;
targetHandle: string;
};
export type NodeSourceNodeItemType = {
nodeId: string;
};
/* --------------- function type -------------------- */
export type SelectAppItemType = {
id: string;
// name: string;
// logo?: string;
};
/* agent */
export type ClassifyQuestionAgentItemType = {
value: string;
key: string;
};
export type ContextExtractAgentItemType = {
valueType: 'string' | 'number' | 'boolean';
desc: string;
key: string;
required: boolean;
defaultValue?: string;
enum?: string;
};
/* -------------- running module -------------- */
export type ChatDispatchProps = {
res?: NextApiResponse;
mode: 'test' | 'chat' | 'debug';
teamId: string;
tmbId: string;
user: UserModelSchema;
app: AppDetailType | AppSchema;
chatId?: string;
responseChatItemId?: string;
histories: ChatItemType[];
variables: Record<string, any>; // global variable
query: UserChatItemValueItemType[]; // trigger query
stream: boolean;
detail: boolean; // response detail
maxRunTimes: number;
isToolCall?: boolean;
};
export type ModuleDispatchProps<T> = ChatDispatchProps & {
node: RuntimeNodeItemType;
runtimeNodes: RuntimeNodeItemType[];
runtimeEdges: RuntimeEdgeItemType[];
params: T;
workflow: WorkflowTemplateBasicType;
};

View File

@@ -1,9 +1,43 @@
import { LLMModelTypeEnum } from '../../ai/constants';
import { WorkflowIOValueTypeEnum, NodeInputKeyEnum, NodeOutputKeyEnum } from '../constants';
import { FlowNodeInputTypeEnum, FlowNodeOutputTypeEnum } from '../node/constant';
import { EditInputFieldMapType, EditNodeFieldType, EditOutputFieldMapType } from '../node/type';
export type FlowNodeInputItemType = {
// Dynamic input field configuration
export type CustomFieldConfigType = {
// selectInputTypeList: FlowNodeInputTypeEnum[]; // 可以选哪些输入类型, 只有1个话,则默认选择
// reference
selectValueTypeList?: WorkflowIOValueTypeEnum[]; // 可以选哪个数据类型, 只有1个的话,则默认选择
// showIsToolParam?: boolean; // 是否作为工具参数
// showRequired?: boolean;
// defaultRequired?: boolean;
showDefaultValue?: boolean;
showDescription?: boolean;
};
export type InputComponentPropsType = {
referencePlaceholder?: string;
placeholder?: string; // input,textarea
maxLength?: number; // input,textarea
list?: { label: string; value: string }[]; // select
markList?: { label: string; value: number }[]; // slider
step?: number; // slider
max?: number; // slider, number input
min?: number; // slider, number input
defaultValue?: string;
llmModelType?: `${LLMModelTypeEnum}`;
// dynamic input
customInputConfig?: CustomFieldConfigType;
};
export type FlowNodeInputItemType = InputComponentPropsType & {
selectedTypeIndex?: number;
renderTypeList: FlowNodeInputTypeEnum[]; // Node Type. Decide on a render style
@@ -16,29 +50,8 @@ export type FlowNodeInputItemType = {
required?: boolean;
toolDescription?: string; // If this field is not empty, it is entered as a tool
maxLength?: number; // input,textarea
// edit
canEdit?: boolean;
// render components params
referencePlaceholder?: string;
placeholder?: string; // input,textarea
list?: { label: string; value: any }[]; // select
markList?: { label: string; value: any }[]; // slider
step?: number; // slider
max?: number; // slider, number input
min?: number; // slider, number input
defaultValue?: string;
// dynamic input
editField?: EditNodeFieldType['editField'];
dynamicParamDefaultValue?: EditNodeFieldType['dynamicParamDefaultValue'];
llmModelType?: `${LLMModelTypeEnum}`;
canEdit?: boolean; // dynamic inputs
};
export type FlowNodeOutputItemType = {
@@ -54,8 +67,7 @@ export type FlowNodeOutputItemType = {
required?: boolean;
// component params
canEdit?: boolean;
editField?: EditOutputFieldMapType; // 添加
customFieldConfig?: CustomFieldConfigType;
};
export type ReferenceValueProps = [string, string | undefined];

View File

@@ -0,0 +1,111 @@
import { FlowNodeTypeEnum } from '../node/constant';
import {
WorkflowIOValueTypeEnum,
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum,
VariableInputEnum
} from '../constants';
import { DispatchNodeResponseKeyEnum } from '../runtime/constants';
import { FlowNodeInputItemType, FlowNodeOutputItemType } from './io.d';
import { UserModelSchema } from '../../../support/user/type';
import {
ChatHistoryItemResType,
ChatItemType,
ChatItemValueItemType,
ToolRunResponseItemType,
UserChatItemValueItemType
} from '../../chat/type';
import { ChatNodeUsageType } from '../../../support/wallet/bill/type';
import { RuntimeNodeItemType } from '../runtime/type';
import { PluginTypeEnum } from '../../plugin/constants';
import { RuntimeEdgeItemType, StoreEdgeItemType } from './edge';
import { NextApiResponse } from 'next';
import { AppDetailType, AppSchema } from '../../app/type';
import { ParentIdType } from 'common/parentFolder/type';
import { AppTypeEnum } from 'core/app/constants';
export type FlowNodeCommonType = {
flowNodeType: FlowNodeTypeEnum; // render node card
abandon?: boolean; // abandon node
avatar?: string;
name: string;
intro?: string; // template list intro
showStatus?: boolean; // chatting response step status
version: string;
// data
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
// plugin data
pluginId?: string;
isFolder?: boolean;
// pluginType?: AppTypeEnum;
};
type HandleType = {
left: boolean;
right: boolean;
top: boolean;
bottom: boolean;
};
// system template
export type FlowNodeTemplateType = FlowNodeCommonType & {
id: string; // node id, unique
templateType: FlowNodeTemplateTypeEnum;
// show handle
sourceHandle?: HandleType;
targetHandle?: HandleType;
// info
isTool?: boolean; // can be connected by tool
// action
forbidDelete?: boolean; // forbid delete
unique?: boolean;
};
export type NodeTemplateListItemType = {
id: string; // 系统节点-系统节点的 id 系统插件-插件的 id团队应用的 id
flowNodeType: FlowNodeTypeEnum; // render node card
parentId?: string;
isFolder?: boolean;
templateType: FlowNodeTemplateTypeEnum;
avatar?: string;
name: string;
intro?: string; // template list intro
isTool?: boolean;
author?: string;
unique?: boolean; // 唯一的
};
export type NodeTemplateListType = {
type: FlowNodeTemplateTypeEnum;
label: string;
list: NodeTemplateListItemType[];
}[];
// react flow node type
export type FlowNodeItemType = FlowNodeTemplateType & {
nodeId: string;
isError?: boolean;
debugResult?: {
status: 'running' | 'success' | 'skipped' | 'failed';
message?: string;
showResult?: boolean; // show and hide result modal
response?: ChatHistoryItemResType;
isExpired?: boolean;
};
};
// store node type
export type StoreNodeItemType = FlowNodeCommonType & {
nodeId: string;
// isEntry: boolean;
position?: {
x: number;
y: number;
};
};

View File

@@ -6,7 +6,7 @@ import {
variableMap
} from './constants';
import { FlowNodeInputItemType, FlowNodeOutputItemType } from './type/io.d';
import { StoreNodeItemType } from './type';
import { StoreNodeItemType } from './type/node';
import type {
VariableItemType,
AppTTSConfigType,
@@ -22,6 +22,7 @@ import {
defaultWhisperConfig
} from '../app/constants';
import { IfElseResultEnum } from './template/system/ifElse/constant';
import { RuntimeNodeItemType } from './runtime/type';
export const getHandleId = (nodeId: string, type: 'source' | 'target', key: string) => {
return `${nodeId}-${type}-${key}`;
@@ -190,3 +191,38 @@ export const isReferenceValue = (value: any): boolean => {
export const getElseIFLabel = (i: number) => {
return i === 0 ? IfElseResultEnum.IF : `${IfElseResultEnum.ELSE_IF} ${i}`;
};
// add value to plugin input node when run plugin
export const updatePluginInputByVariables = (
nodes: RuntimeNodeItemType[],
variables: Record<string, any>
) => {
return nodes.map((node) =>
node.flowNodeType === FlowNodeTypeEnum.pluginInput
? {
...node,
inputs: node.inputs.map((input) => {
const parseValue = (() => {
try {
if (
input.valueType === WorkflowIOValueTypeEnum.string ||
input.valueType === WorkflowIOValueTypeEnum.number ||
input.valueType === WorkflowIOValueTypeEnum.boolean
)
return variables[input.key];
return JSON.parse(variables[input.key]);
} catch (e) {
return variables[input.key];
}
})();
return {
...input,
value: parseValue ?? input.value
};
})
}
: node
);
};

View File

@@ -10,13 +10,13 @@
"js-yaml": "^4.1.0",
"jschardet": "3.1.1",
"nanoid": "^4.0.1",
"next": "14.2.3",
"next": "14.2.5",
"openai": "4.28.0",
"openapi-types": "^12.1.3",
"timezones-list": "^3.0.2"
},
"devDependencies": {
"@types/js-yaml": "^4.0.9",
"@types/node": "^20.14.2"
"@types/node": "20.14.0"
}
}

View File

@@ -37,3 +37,8 @@ export type ResourcePermissionType = {
export type ResourcePerWithTmbWithUser = Omit<ResourcePermissionType, 'tmbId'> & {
tmbId: TeamMemberWithUserSchema;
};
export type PermissionSchemaType = {
defaultPermission: PermissionValueType;
inheritPermission: boolean;
};

View File

@@ -1,5 +1,5 @@
import { TeamMemberRoleEnum } from '../user/team/constant';
import { PermissionTypeEnum } from './constant';
import { PermissionValueType } from './type';
import { NullPermission, PermissionTypeEnum } from './constant';
import { Permission } from './controller';
/* team public source, or owner source in team */
@@ -28,3 +28,17 @@ export function mongoOwnerPermission({ teamId, tmbId }: { teamId: string; tmbId:
tmbId
};
}
// return permission-related schema to define the schema of resources
export function getPermissionSchema(defaultPermission: PermissionValueType = NullPermission) {
return {
defaultPermission: {
type: Number,
default: defaultPermission
},
inheritPermission: {
type: Boolean,
default: true
}
};
}

View File

@@ -1,7 +1,7 @@
import { BillTypeEnum } from './constants';
export type CreateBillProps = {
type: `${BillTypeEnum}`;
type: BillTypeEnum;
// balance
balance?: number; // read

View File

@@ -9,7 +9,7 @@ export type BillSchemaType = {
createTime: Date;
orderId: string;
status: 'SUCCESS' | 'REFUND' | 'NOTPAY' | 'CLOSED';
type: `${BillTypeEnum}`;
type: BillTypeEnum;
price: number;
hasInvoice: boolean;
metadata: {

View File

@@ -21,6 +21,6 @@ export type CreateUsageProps = {
appId?: string;
pluginId?: string;
totalPoints: number;
source: `${UsageSourceEnum}`;
source: UsageSourceEnum;
list: UsageListItemType[];
};

View File

@@ -1,5 +1,5 @@
{
"extends":"../../tsconfig.json",
"extends": "../../tsconfig.json",
"compilerOptions": {
"baseUrl": "."
},

View File

@@ -0,0 +1,3 @@
# Package 说明
该 package 存放工作流系统插件。

View File

@@ -1,10 +1,12 @@
{
"name": "@fastgpt/plugins",
"version": "1.0.0",
"dependencies": {},
"dependencies": {
"expr-eval": "^2.0.2"
},
"devDependencies": {
"@types/node": "^20.14.2",
"@fastgpt/global": "workspace:*",
"@fastgpt/service": "workspace:*"
"@fastgpt/service": "workspace:*",
"@types/node": "20.14.0"
}
}

View File

@@ -0,0 +1,57 @@
import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants';
import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constants';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import { SystemPluginResponseType } from './type';
import { NodeTemplateListItemType } from '@fastgpt/global/core/workflow/type/node';
import { isProduction } from '../service/common/system/constants';
let list = ['getTime', 'fetchUrl', 'mathExprVal'];
export const getCommunityPlugins = () => {
if (isProduction && global.communitySystemPlugins) return global.communitySystemPlugins;
global.communitySystemPlugins = list.map((name) => ({
...require(`./src/${name}/template.json`),
id: `${PluginSourceEnum.community}-${name}`
}));
return global.communitySystemPlugins;
};
export const getCommunityPluginsTemplateList = () => {
return getCommunityPlugins().map<NodeTemplateListItemType>((plugin) => ({
id: plugin.id,
templateType: plugin.templateType ?? FlowNodeTemplateTypeEnum.other,
flowNodeType: FlowNodeTypeEnum.pluginModule,
avatar: plugin.avatar,
name: plugin.name,
intro: plugin.intro,
isTool: plugin.isTool
}));
};
export const getCommunityCb = async () => {
if (isProduction && global.communitySystemPluginCb) return global.communitySystemPluginCb;
// Do not modify the following code
const loadModule = async (name: string) => {
const module = await import(`./src/${name}/index`);
return module.default;
};
const result = await Promise.all(
list.map(async (name) => ({
name,
cb: await loadModule(name)
}))
);
global.communitySystemPluginCb = result.reduce<
Record<string, (e: any) => SystemPluginResponseType>
>((acc, { name, cb }) => {
acc[name] = cb;
return acc;
}, {});
return global.communitySystemPluginCb;
};

View File

@@ -0,0 +1,30 @@
import { urlsFetch } from '@fastgpt/service/common/string/cheerio';
type Props = {
url: string;
};
type Response = Promise<{
result: any;
}>;
const main = async ({ url }: Props): Response => {
try {
const result = await urlsFetch({
urlList: [url],
selector: 'body'
});
const title = result[0]?.title;
const content = result[0]?.content;
return {
result: `${title ? `# ${title}\n\n` : ''}${content}`
};
} catch (error) {
return {
result: 'Fetch error'
};
}
};
export default main;

View File

@@ -0,0 +1,265 @@
{
"author": "FastGPT",
"version": "486",
"name": "网页内容抓取",
"avatar": "/imgs/workflow/fetchUrl.svg",
"intro": "可获取一个网页链接内容,并以 Markdown 格式输出,仅支持获取静态网站。",
"showStatus": true,
"weight": 10,
"isTool": true,
"templateType": "tools",
"workflow": {
"nodes": [
{
"nodeId": "lmpb9v2lo2lk",
"name": "自定义插件输入",
"intro": "自定义配置外部输入,使用插件时,仅暴露自定义配置的输入",
"avatar": "/imgs/workflow/input.png",
"flowNodeType": "pluginInput",
"showStatus": false,
"position": {
"x": 487.2485939481787,
"y": -159.13661665265613
},
"version": "481",
"inputs": [
{
"renderTypeList": ["reference"],
"selectedTypeIndex": 0,
"valueType": "string",
"key": "url",
"label": "url",
"description": "需要读取的网页链接",
"required": true,
"toolDescription": "需要读取的网页链接"
}
],
"outputs": [
{
"id": "url",
"valueType": "string",
"key": "url",
"label": "url",
"type": "hidden"
}
]
},
{
"nodeId": "i7uow4wj2wdp",
"name": "自定义插件输出",
"intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出",
"avatar": "/imgs/workflow/output.png",
"flowNodeType": "pluginOutput",
"showStatus": false,
"position": {
"x": 1607.7142331269129,
"y": -150.8808596935447
},
"version": "481",
"inputs": [
{
"key": "result",
"valueType": "string",
"label": "result",
"renderTypeList": ["reference"],
"required": false,
"description": "",
"canEdit": true,
"editField": {
"key": true,
"description": true,
"valueType": true
},
"value": ["ebLCxU43hHuZ", "rH4tMV02robs"]
}
],
"outputs": []
},
{
"nodeId": "ebLCxU43hHuZ",
"name": "HTTP 请求",
"intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)",
"avatar": "/imgs/workflow/http.png",
"flowNodeType": "httpRequest468",
"showStatus": true,
"position": {
"x": 1050.9890727421412,
"y": -415.2085119990912
},
"version": "481",
"inputs": [
{
"key": "system_addInputParam",
"renderTypeList": ["addInputParam"],
"valueType": "dynamic",
"label": "",
"required": false,
"description": "core.module.input.description.HTTP Dynamic Input",
"customInputConfig": {
"selectValueTypeList": [
"string",
"number",
"boolean",
"object",
"arrayString",
"arrayNumber",
"arrayBoolean",
"arrayObject",
"any",
"chatHistory",
"datasetQuote",
"dynamic",
"selectApp",
"selectDataset"
],
"showDescription": false,
"showDefaultValue": true
}
},
{
"key": "system_httpMethod",
"renderTypeList": ["custom"],
"valueType": "string",
"label": "",
"value": "POST",
"required": true
},
{
"key": "system_httpReqUrl",
"renderTypeList": ["hidden"],
"valueType": "string",
"label": "",
"description": "core.module.input.description.Http Request Url",
"placeholder": "https://api.ai.com/getInventory",
"required": false,
"value": "fetchUrl"
},
{
"key": "system_httpHeader",
"renderTypeList": ["custom"],
"valueType": "any",
"value": [],
"label": "",
"description": "core.module.input.description.Http Request Header",
"placeholder": "core.module.input.description.Http Request Header",
"required": false
},
{
"key": "system_httpParams",
"renderTypeList": ["hidden"],
"valueType": "any",
"value": [],
"label": "",
"required": false
},
{
"key": "system_httpJsonBody",
"renderTypeList": ["hidden"],
"valueType": "any",
"value": "{\n \"url\": \"{{url}}\"\n}",
"label": "",
"required": false
},
{
"renderTypeList": ["reference"],
"valueType": "string",
"canEdit": true,
"key": "url",
"label": "url",
"customInputConfig": {
"selectValueTypeList": [
"string",
"number",
"boolean",
"object",
"arrayString",
"arrayNumber",
"arrayBoolean",
"arrayObject",
"any",
"chatHistory",
"datasetQuote",
"dynamic",
"selectApp",
"selectDataset"
],
"showDescription": false,
"showDefaultValue": true
},
"required": true,
"value": ["lmpb9v2lo2lk", "url"]
}
],
"outputs": [
{
"id": "system_addOutputParam",
"key": "system_addOutputParam",
"type": "dynamic",
"valueType": "dynamic",
"label": "",
"customFieldConfig": {
"selectValueTypeList": [
"string",
"number",
"boolean",
"object",
"arrayString",
"arrayNumber",
"arrayBoolean",
"arrayObject",
"any",
"chatHistory",
"datasetQuote",
"dynamic",
"selectApp",
"selectDataset"
],
"showDescription": false,
"showDefaultValue": true
}
},
{
"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": "rH4tMV02robs",
"valueType": "string",
"type": "dynamic",
"key": "result",
"label": "result"
}
]
}
],
"edges": [
{
"source": "lmpb9v2lo2lk",
"target": "ebLCxU43hHuZ",
"sourceHandle": "lmpb9v2lo2lk-source-right",
"targetHandle": "ebLCxU43hHuZ-target-left"
},
{
"source": "ebLCxU43hHuZ",
"target": "i7uow4wj2wdp",
"sourceHandle": "ebLCxU43hHuZ-source-right",
"targetHandle": "i7uow4wj2wdp-target-left"
}
]
}
}

View File

@@ -0,0 +1,14 @@
type Props = {
time: string;
};
type Response = Promise<{
time: string;
}>;
const main = async ({ time }: Props): Response => {
return {
time
};
};
export default main;

View File

@@ -0,0 +1,215 @@
{
"author": "FastGPT Team",
"version": "481",
"templateType": "tools",
"name": "获取当前时间",
"avatar": "/imgs/workflow/getCurrentTime.svg",
"intro": "获取用户当前时区的时间。",
"showStatus": false,
"isTool": true,
"weight": 10,
"workflow": {
"nodes": [
{
"nodeId": "lmpb9v2lo2lk",
"name": "自定义插件输入",
"intro": "自定义配置外部输入,使用插件时,仅暴露自定义配置的输入",
"avatar": "/imgs/workflow/input.png",
"flowNodeType": "pluginInput",
"showStatus": false,
"position": {
"x": 616.4226348688949,
"y": -165.05298493910115
},
"version": "481",
"inputs": [],
"outputs": []
},
{
"nodeId": "i7uow4wj2wdp",
"name": "自定义插件输出",
"intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出",
"avatar": "/imgs/workflow/output.png",
"flowNodeType": "pluginOutput",
"showStatus": false,
"position": {
"x": 1607.7142331269129,
"y": -150.8808596935447
},
"version": "481",
"inputs": [
{
"key": "time",
"valueType": "string",
"label": "time",
"renderTypeList": ["reference"],
"required": false,
"description": "",
"canEdit": true,
"editField": {
"key": true,
"description": true,
"valueType": true
},
"value": ["ebLCxU43hHuZ", "rH4tMV02robs"]
}
],
"outputs": []
},
{
"nodeId": "ebLCxU43hHuZ",
"name": "HTTP 请求",
"intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)",
"avatar": "/imgs/workflow/http.png",
"flowNodeType": "httpRequest468",
"showStatus": true,
"position": {
"x": 1050.9890727421412,
"y": -415.2085119990912
},
"version": "481",
"inputs": [
{
"key": "system_addInputParam",
"renderTypeList": ["addInputParam"],
"valueType": "dynamic",
"label": "",
"required": false,
"description": "core.module.input.description.HTTP Dynamic Input",
"customInputConfig": {
"selectValueTypeList": [
"string",
"number",
"boolean",
"object",
"arrayString",
"arrayNumber",
"arrayBoolean",
"arrayObject",
"any",
"chatHistory",
"datasetQuote",
"dynamic",
"selectApp",
"selectDataset"
],
"showDescription": false,
"showDefaultValue": true
}
},
{
"key": "system_httpMethod",
"renderTypeList": ["custom"],
"valueType": "string",
"label": "",
"value": "POST",
"required": true
},
{
"key": "system_httpReqUrl",
"renderTypeList": ["hidden"],
"valueType": "string",
"label": "",
"description": "core.module.input.description.Http Request Url",
"placeholder": "https://api.ai.com/getInventory",
"required": false,
"value": "getTime"
},
{
"key": "system_httpHeader",
"renderTypeList": ["custom"],
"valueType": "any",
"value": [],
"label": "",
"description": "core.module.input.description.Http Request Header",
"placeholder": "core.module.input.description.Http Request Header",
"required": false
},
{
"key": "system_httpParams",
"renderTypeList": ["hidden"],
"valueType": "any",
"value": [],
"label": "",
"required": false
},
{
"key": "system_httpJsonBody",
"renderTypeList": ["hidden"],
"valueType": "any",
"value": "{\n \"time\": \"{{cTime}}\"\n}",
"label": "",
"required": false
}
],
"outputs": [
{
"id": "system_addOutputParam",
"key": "system_addOutputParam",
"type": "dynamic",
"valueType": "dynamic",
"label": "",
"customFieldConfig": {
"selectValueTypeList": [
"string",
"number",
"boolean",
"object",
"arrayString",
"arrayNumber",
"arrayBoolean",
"arrayObject",
"any",
"chatHistory",
"datasetQuote",
"dynamic",
"selectApp",
"selectDataset"
],
"showDescription": false,
"showDefaultValue": true
}
},
{
"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": "rH4tMV02robs",
"valueType": "string",
"type": "dynamic",
"key": "time",
"label": "time"
}
]
}
],
"edges": [
{
"source": "lmpb9v2lo2lk",
"target": "ebLCxU43hHuZ",
"sourceHandle": "lmpb9v2lo2lk-source-right",
"targetHandle": "ebLCxU43hHuZ-target-left"
},
{
"source": "ebLCxU43hHuZ",
"target": "i7uow4wj2wdp",
"sourceHandle": "ebLCxU43hHuZ-source-right",
"targetHandle": "i7uow4wj2wdp-target-left"
}
]
}
}

View File

@@ -0,0 +1,40 @@
import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import { Parser } from 'expr-eval';
type Props = {
expr: string;
};
// Response type same as HTTP outputs
type Response = Promise<{
result: string;
}>;
const replaceSpecialChar = (expr: string) => {
// replace ** to ^
let result = expr.replace(/\*\*/g, '^');
return result;
};
const main = async ({ expr }: Props): Response => {
if (typeof expr !== 'string') {
return {
result: `${expr} is not a string`
};
}
try {
const parser = new Parser();
const exprParser = parser.parse(replaceSpecialChar(expr));
return {
result: exprParser.evaluate()
};
} catch (error) {
return {
result: `${expr} is not a valid math expression. Error: ${error}`
};
}
};
export default main;

View File

@@ -0,0 +1,253 @@
{
"author": "FastGPT",
"version": "486",
"name": "数学公式执行",
"avatar": "/imgs/workflow/mathExprEval.svg",
"intro": "用于执行数学表达式的工具,通过 js 的 expr-eval 库运行表达式并返回结果。",
"showStatus": false,
"weight": 10,
"isTool": true,
"templateType": "tools",
"workflow": {
"nodes": [
{
"nodeId": "ioNyiO62aWcG",
"name": "插件输入",
"intro": "可以配置插件需要哪些输入,利用这些输入来运行插件",
"avatar": "/imgs/workflow/input.png",
"flowNodeType": "pluginInput",
"showStatus": false,
"position": {
"x": 494.7780128195933,
"y": -145.65080850146154
},
"version": "481",
"inputs": [
{
"renderTypeList": ["reference"],
"selectedTypeIndex": 0,
"valueType": "string",
"key": "数学表达式",
"label": "数学表达式",
"description": "需要执行的数学表达式",
"required": true,
"toolDescription": "需要执行的数学表达式"
}
],
"outputs": [
{
"id": "数学表达式",
"valueType": "string",
"key": "数学表达式",
"label": "数学表达式",
"type": "hidden"
}
]
},
{
"nodeId": "sowtxkCPjvb7",
"name": "自定义插件输出",
"intro": "自定义配置外部输出,使用插件时,仅暴露自定义配置的输出",
"avatar": "/imgs/workflow/output.png",
"flowNodeType": "pluginOutput",
"showStatus": false,
"position": {
"x": 1850.4258139184146,
"y": -147.7125146361461
},
"version": "481",
"inputs": [
{
"key": "result",
"valueType": "string",
"label": "result",
"renderTypeList": ["reference"],
"required": false,
"description": "",
"canEdit": true,
"value": ["hzO1JnuLrKpK", "vJnW9JVLOJFT"]
}
],
"outputs": [
{
"id": "sowtxkCPjvb7",
"key": "result",
"valueType": "string",
"label": "result",
"type": "static"
}
]
},
{
"nodeId": "hzO1JnuLrKpK",
"name": "HTTP 请求",
"intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)",
"avatar": "/imgs/workflow/http.png",
"flowNodeType": "httpRequest468",
"showStatus": true,
"position": {
"x": 1188.947986995841,
"y": -473.52694296182904
},
"version": "481",
"inputs": [
{
"key": "system_addInputParam",
"renderTypeList": ["addInputParam"],
"valueType": "dynamic",
"label": "",
"required": false,
"description": "core.module.input.description.HTTP Dynamic Input",
"customInputConfig": {
"selectValueTypeList": [
"string",
"number",
"boolean",
"object",
"arrayString",
"arrayNumber",
"arrayBoolean",
"arrayObject",
"any",
"chatHistory",
"datasetQuote",
"dynamic",
"selectApp",
"selectDataset"
],
"showDescription": false,
"showDefaultValue": true
}
},
{
"key": "system_httpMethod",
"renderTypeList": ["custom"],
"valueType": "string",
"label": "",
"value": "POST",
"required": true
},
{
"key": "system_httpReqUrl",
"renderTypeList": ["hidden"],
"valueType": "string",
"label": "",
"description": "core.module.input.description.Http Request Url",
"placeholder": "https://api.ai.com/getInventory",
"required": false,
"value": "mathExprVal"
},
{
"key": "system_httpHeader",
"renderTypeList": ["custom"],
"valueType": "any",
"value": [
{
"key": "Authorization",
"type": "string",
"value": "Bearer fb968ed1-b1dd-4fc1-8409-c9339cbeb14f"
}
],
"label": "",
"description": "core.module.input.description.Http Request Header",
"placeholder": "core.module.input.description.Http Request Header",
"required": false
},
{
"key": "system_httpParams",
"renderTypeList": ["hidden"],
"valueType": "any",
"value": [],
"label": "",
"required": false
},
{
"key": "system_httpJsonBody",
"renderTypeList": ["hidden"],
"valueType": "any",
"value": "{\n \"expr\":\"{{expr}}\"\n}",
"label": "",
"required": false
},
{
"key": "expr",
"valueType": "string",
"label": "expr",
"renderTypeList": ["reference"],
"canEdit": true,
"value": ["ioNyiO62aWcG", "数学表达式"]
}
],
"outputs": [
{
"id": "system_addOutputParam",
"key": "system_addOutputParam",
"type": "dynamic",
"valueType": "dynamic",
"label": "",
"customFieldConfig": {
"selectValueTypeList": [
"string",
"number",
"boolean",
"object",
"arrayString",
"arrayNumber",
"arrayBoolean",
"arrayObject",
"any",
"chatHistory",
"datasetQuote",
"dynamic",
"selectApp",
"selectDataset"
],
"showDescription": false,
"showDefaultValue": true
}
},
{
"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": "vJnW9JVLOJFT",
"valueType": "string",
"type": "dynamic",
"key": "result",
"label": "result"
}
]
}
],
"edges": [
{
"source": "ioNyiO62aWcG",
"target": "hzO1JnuLrKpK",
"sourceHandle": "ioNyiO62aWcG-source-right",
"targetHandle": "hzO1JnuLrKpK-target-left"
},
{
"source": "hzO1JnuLrKpK",
"target": "sowtxkCPjvb7",
"sourceHandle": "hzO1JnuLrKpK-source-right",
"targetHandle": "sowtxkCPjvb7-target-left"
}
]
}
}

View File

@@ -0,0 +1,21 @@
import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
type Props = {
text: string;
};
// Response type same as HTTP outputs
type Response = Promise<{
[NodeInputKeyEnum.answerText]: string;
responseText: string;
}>;
const main = async ({ text }: Props): Response => {
return {
// This output object needs to correspond to the content of the plug-in output
[NodeInputKeyEnum.answerText]: 'AnswerText', // This is a special field, and returning this field will return a message to the client
responseText: `text: ${text}`
};
};
export default main;

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