Compare commits

..

22 Commits

Author SHA1 Message Date
Archer
9501c3f3a1 V4.7-alpha (#985)
Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
2024-03-13 10:50:02 +08:00
Carson Yang
5bca15f12f Docs: fix HomePage (#977)
Signed-off-by: Carson Yang <yangchuansheng33@gmail.com>
2024-03-12 13:51:30 +08:00
Archer
753b164ea2 修复4.6.9问题 (#976)
* Fixbranch (#43)

* move components to web package (#37)

* move components

* fix

* openapi config

* fix team share bug

---------

Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
Co-authored-by: archer <545436317@qq.com>

* fix: http variable and ai base url

* remove log

---------

Co-authored-by: yst <77910600+yu-and-liu@users.noreply.github.com>
Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
2024-03-11 20:12:55 +08:00
Archer
64492b8b33 move components to web package (#37) (#970)
* move components

* fix

openapi config

doc

Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
2024-03-11 13:38:52 +08:00
Carson Yang
80bdbf6bce Docs: update workflow for building docs image (#968)
Signed-off-by: Carson Yang <yangchuansheng33@gmail.com>
2024-03-11 12:52:21 +08:00
Archer
9f0b1d6bad Update README.md 2024-03-10 23:18:01 +08:00
Archer
c44b944fa6 Update docker.md 2024-03-09 21:25:37 +08:00
Archer
61419a5676 Update docker-compose.yml 2024-03-09 21:24:45 +08:00
Archer
47227c1b84 Update docker.md 2024-03-08 21:54:00 +08:00
Archer
4d66e0f828 4.6.9-production (#952)
* move components to web package (#37)

* move components

* fix

* fix: cq connection

* fix pagination (#41)

* doc

* openapi config

* fix team share app lose (#42)

* fix: ts

* doc

* doc

---------

Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
Co-authored-by: yst <77910600+yu-and-liu@users.noreply.github.com>
2024-03-08 13:33:45 +08:00
sgdream
46d9a6461f fix: 知识库QA生成,答案中有“Q”会导致提前截断。 (#950) 2024-03-08 09:47:48 +08:00
John Chen
b74dd2341b reranker.md优化docker启动命令,并增加docker-compose.yml示例 (#936)
原docker启动命令启动后的容器只能使用CPU运行。本次修改增加了GPU参数,并提供docker-compose.yml示例
2024-03-06 18:13:55 +08:00
Archer
af581bc903 Global variables support external variable; Extract module support default value (#921) 2024-03-05 14:13:22 +08:00
Archer
42a8184ea0 v4.6.9-alpha (#918)
Co-authored-by: Mufei <327958099@qq.com>
Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
2024-03-04 00:05:25 +08:00
Mufei
f9f0b4bffd Update http468.ts (#903)
修复HTTP模块,http请求错误的stack堆栈信息长度冗余导致超过MongoDB数据库限制从而导致聊天对话插入数据库失败,修复方法为修改为如果http请求错误只返回几项重要信息而不是整个堆栈数据
2024-03-03 22:21:30 +08:00
Archer
064c64e74c V4.6.9-first commit (#899)
* perf: insert mongo dataset data session

* perf: dataset data index

* remove delay

* rename bill schema

* rename bill record

* perf: bill table

* perf: prompt

* perf: sub plan

* change the usage count

* feat: usage bill

* publish usages

* doc

* 新增团队聊天功能 (#20)

* perf: doc

* feat 添加标签部分

feat 信息团队标签配置

feat 新增团队同步管理

feat team分享页面

feat 完成team分享页面

feat 实现模糊搜索

style 格式化

fix 修复迷糊匹配

style 样式修改

fix 团队标签功能修复

* fix 修复鉴权功能

* merge 合并代码

* fix 修复引用错误

* fix 修复pr问题

* fix 修复ts格式问题

---------

Co-authored-by: archer <545436317@qq.com>
Co-authored-by: liuxingwan <liuxingwan.lxw@alibaba-inc.com>

* update extra plan

* fix: ts

* format

* perf: bill field

* feat: standard plan

* fix: ts

* feat 个人账号页面修改 (#22)

* feat 添加标签部分

feat 信息团队标签配置

feat 新增团队同步管理

feat team分享页面

feat 完成team分享页面

feat 实现模糊搜索

style 格式化

fix 修复迷糊匹配

style 样式修改

fix 团队标签功能修复

* fix 修复鉴权功能

* merge 合并代码

* fix 修复引用错误

* fix 修复pr问题

* fix 修复ts格式问题

* feat 修改个人账号页

---------

Co-authored-by: liuxingwan <liuxingwan.lxw@alibaba-inc.com>

* sub plan page (#23)

* fix chunk index; error page text

* feat: dataset process Integral prediction

* feat: stand plan field

* feat: sub plan limit

* perf: index

* query extension

* perf: share link push app name

* perf: plan point unit

* perf: get sub plan

* perf: account page

* feat 新增套餐详情弹窗代码 (#24)

* merge 合并代码

* fix 新增套餐详情弹框

* fix 修复pr问题

* feat: change http node input to prompt editor (#21)

* feat: change http node input to prompt editor

* fix

* split PromptEditor to HttpInput

* Team plans (#25)

* perf: pay check

* perf: team plan test

* plan limit check

* replace sensitive text

* perf: fix some null

* collection null check

* perf: plans modal

* perf: http module

* pacakge (#26)

* individuation page and pay modal amount (#27)

* feat: individuation page

* team chat config

* pay modal

* plan count and replace invalid chars (#29)

* fix: user oneapi

* fix: training queue

* fix: qa queue

* perf: remove space chars

* replace invalid chars

* change httpinput dropdown menu (#28)

* perf: http

* reseet free plan

* perf: plan code to packages

* remove llm config to package

* perf: code

* perf: faq

* fix: get team plan

---------

Co-authored-by: yst <77910600+yu-and-liu@users.noreply.github.com>
Co-authored-by: liuxingwan <liuxingwan.lxw@alibaba-inc.com>
Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
2024-02-28 13:19:15 +08:00
Holata Seminole
32686f9e3e docs: fix typos (#898) 2024-02-27 18:53:17 +08:00
Archer
fd9b6291af Revert "sub plan page (#885)" (#886)
This reverts commit 443ad37b6a.
2024-02-23 17:48:15 +08:00
Archer
443ad37b6a sub plan page (#885)
* perf: insert mongo dataset data session

* perf: dataset data index

* remove delay

* rename bill schema

* rename bill record

* perf: bill table

* perf: prompt

* perf: sub plan

* change the usage count

* feat: usage bill

* publish usages

* doc

* 新增团队聊天功能 (#20)

* perf: doc

* feat 添加标签部分

feat 信息团队标签配置

feat 新增团队同步管理

feat team分享页面

feat 完成team分享页面

feat 实现模糊搜索

style 格式化

fix 修复迷糊匹配

style 样式修改

fix 团队标签功能修复

* fix 修复鉴权功能

* merge 合并代码

* fix 修复引用错误

* fix 修复pr问题

* fix 修复ts格式问题

---------

Co-authored-by: archer <545436317@qq.com>
Co-authored-by: liuxingwan <liuxingwan.lxw@alibaba-inc.com>

* update extra plan

* fix: ts

* format

* perf: bill field

* feat: standard plan

* fix: ts

* feat 个人账号页面修改 (#22)

* feat 添加标签部分

feat 信息团队标签配置

feat 新增团队同步管理

feat team分享页面

feat 完成team分享页面

feat 实现模糊搜索

style 格式化

fix 修复迷糊匹配

style 样式修改

fix 团队标签功能修复

* fix 修复鉴权功能

* merge 合并代码

* fix 修复引用错误

* fix 修复pr问题

* fix 修复ts格式问题

* feat 修改个人账号页

---------

Co-authored-by: liuxingwan <liuxingwan.lxw@alibaba-inc.com>

* fix chunk index; error page text

* feat: dataset process Integral prediction

* feat: stand plan field

* feat: sub plan limit

* perf: index

* query extension

* perf: share link push app name

* perf: plan point unit

* perf: get sub plan

* perf: account page

---------

Co-authored-by: yst <77910600+yu-and-liu@users.noreply.github.com>
Co-authored-by: liuxingwan <liuxingwan.lxw@alibaba-inc.com>
2024-02-23 17:47:34 +08:00
Kenith-Zhang
7a87f13aa8 docs:Update chatglm2.md and reranker.md the 'requirements' the word error (#866)
* Update chatglm2.md

docs:chatglm2.md the 'requirements' the word error

* docs reranker.md  the 'requirements' the word error
2024-02-22 09:48:45 +08:00
imgbot[bot]
d4aa19d8f2 [ImgBot] Optimize images (#859)
*Total -- 1,066.38kb -> 626.26kb (41.27%)

/docSite/assets/imgs/dataset_search_process.png -- 427.67kb -> 91.64kb (78.57%)
/docSite/assets/imgs/dataset_tree.png -- 100.17kb -> 24.38kb (75.66%)
/docSite/assets/imgs/http1.jpg -- 30.60kb -> 26.77kb (12.54%)
/docSite/static/android-chrome-256x256.png -- 5.57kb -> 4.93kb (11.41%)
/docSite/assets/imgs/sealos_price.jpg -- 148.36kb -> 135.89kb (8.41%)
/docSite/static/android-chrome-512x512.png -- 11.31kb -> 10.37kb (8.3%)
/docSite/static/android-chrome-192x192.png -- 4.11kb -> 3.77kb (8.15%)
/docSite/static/apple-touch-icon.png -- 3.87kb -> 3.55kb (8.08%)
/docSite/static/docs/mstile-150x150.png -- 3.01kb -> 2.77kb (8%)
/docSite/static/mstile-150x150.png -- 3.01kb -> 2.77kb (8%)
/docSite/assets/imgs/demo-appointment5.jpg -- 160.47kb -> 154.53kb (3.7%)
/docSite/assets/imgs/1.png -- 108.90kb -> 106.11kb (2.56%)
/docSite/static/favicon-32x32.png -- 1.01kb -> 0.99kb (2.13%)
/docSite/assets/imgs/2.png -- 32.49kb -> 31.97kb (1.6%)
/docSite/assets/imgs/versatile_assistant_5.png -- 25.81kb -> 25.80kb (0.06%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>
Co-authored-by: ImgBotApp <ImgBotHelp@gmail.com>
2024-02-18 20:07:44 +08:00
Archer
0c439c7827 perf: mongo doc (#855) 2024-02-17 10:57:39 +08:00
492 changed files with 16906 additions and 10081 deletions

View File

@@ -8,82 +8,67 @@ on:
- 'main'
tags:
- 'v*.*.*'
jobs:
build-fastgpt-docs-images:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Get current date and time
id: datetime
run: echo "datetime=$(date +'%Y%m%d%H%M%S')" >> "$GITHUB_OUTPUT"
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
fetch-depth: 1
- name: Set up QEMU (optional)
uses: docker/setup-qemu-action@v2
# list of Docker images to use as base name for tags
images: |
${{ secrets.DOCKER_HUB_NAME }}/fastgpt-docs
ghcr.io/${{ github.repository_owner }}/fastgpt-docs
registry.cn-hangzhou.aliyuncs.com/${{ secrets.ALI_HUB_USERNAME }}/fastgpt-docs
tags: |
${{ steps.datetime.outputs.datetime }}
flavor: latest=false
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
driver-opts: network=host
- name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
username: ${{ secrets.DOCKER_HUB_NAME }}
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
- name: Login to ghcr.io
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GH_PAT }}
- name: Set DOCKER_REPO_TAGGED based on branch or tag
run: |
if [[ "${{ github.ref_name }}" == "main" ]]; then
echo "DOCKER_REPO_TAGGED=ghcr.io/${{ github.repository_owner }}/fastgpt-docs:latest" >> $GITHUB_ENV
else
echo "DOCKER_REPO_TAGGED=ghcr.io/${{ github.repository_owner }}/fastgpt-docs:${{ github.ref_name }}" >> $GITHUB_ENV
fi
- name: Build and publish image for main branch or tag push event
env:
DOCKER_REPO_TAGGED: ${{ env.DOCKER_REPO_TAGGED }}
run: |
docker buildx build \
--build-arg name=app \
--platform linux/amd64,linux/arm64 \
--label "org.opencontainers.image.source= https://github.com/ ${{ github.repository_owner }}/FastGPT" \
--label "org.opencontainers.image.description=fastgpt image" \
--label "org.opencontainers.image.licenses=Apache" \
--push \
--cache-from=type=local,src=/tmp/.buildx-cache \
--cache-to=type=local,dest=/tmp/.buildx-cache \
-t ${DOCKER_REPO_TAGGED} \
-f docSite/Dockerfile \
.
push-to-docker-hub:
needs: build-fastgpt-docs-images
runs-on: ubuntu-20.04
if: github.repository == 'labring/FastGPT'
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_HUB_NAME }}
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
- name: Set DOCKER_REPO_TAGGED based on branch or tag
run: |
if [[ "${{ github.ref_name }}" == "main" ]]; then
echo "IMAGE_TAG=latest" >> $GITHUB_ENV
else
echo "IMAGE_TAG=${{ github.ref_name }}" >> $GITHUB_ENV
fi
- name: Pull image from GitHub Container Registry
run: docker pull ghcr.io/${{ github.repository_owner }}/fastgpt-docs:${{env.IMAGE_TAG}}
- name: Tag image with Docker Hub repository name and version tag
run: docker tag ghcr.io/${{ github.repository_owner }}/fastgpt-docs:${{env.IMAGE_TAG}} ${{ secrets.DOCKER_IMAGE_NAME }}:${{env.IMAGE_TAG}}
- name: Push image to Docker Hub
run: docker push ${{ secrets.DOCKER_IMAGE_NAME }}:${{env.IMAGE_TAG}}
- name: Login to Aliyun
uses: docker/login-action@v3
with:
registry: registry.cn-hangzhou.aliyuncs.com
username: ${{ secrets.ALI_HUB_USERNAME }}
password: ${{ secrets.ALI_HUB_PASSWORD }}
- name: Build and push Docker images to ghcr.io and DockerHub
uses: docker/build-push-action@v5
with:
context: .
file: ./docSite/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
outputs:
tags: ${{ steps.datetime.outputs.datetime }}
update-docs-image:
needs: build-fastgpt-docs-images
runs-on: ubuntu-20.04
@@ -95,4 +80,9 @@ jobs:
env:
KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
with:
args: rollout restart deployment fastgpt-docs
args: set image deployment/fastgpt-docs fastgpt-docs=registry.cn-hangzhou.aliyuncs.com/${{ secrets.ALI_HUB_USERNAME }}/fastgpt-docs:${{ needs.build-fastgpt-docs-images.outputs.tags }}
- uses: actions-hub/kubectl@master
env:
KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
with:
args: annotate deployment/fastgpt-docs originImageName="registry.cn-hangzhou.aliyuncs.com/${{ secrets.ALI_HUB_USERNAME }}/fastgpt-docs:${{ needs.build-fastgpt-docs-images.outputs.tags }}" --overwrite

View File

@@ -11,5 +11,5 @@
"i18n-ally.sortKeys": true,
"i18n-ally.keepFulfilled": true,
"i18n-ally.sourceLanguage": "zh", // 根据此语言文件翻译其他语言文件的变量和内容
"i18n-ally.displayLanguage": "en", // 显示语言
"i18n-ally.displayLanguage": "zh", // 显示语言
}

View File

@@ -36,8 +36,9 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
## 🛸 在线使用
- 🌐 国内临时可访问[fastgpt.in](https://fastgpt.in/)
- 🌍 海外版:[fastgpt.run](https://fastgpt.run/)
- 🌍 海外版[fastgpt.in](https://fastgpt.in/)
fastgpt.run 域名会弃用。
| | |
| ---------------------------------- | ---------------------------------- |

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 428 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -1,38 +0,0 @@
---
title: '免责声明'
description: ' FastGPT 免责声明'
icon: 'gavel'
draft: false
toc: true
weight: 1220
---
由于生成式 AI 的特性,其在不同国家的管控措施也会有所不同。请所有使用者务必遵守所在地的相关法律。
免责声明:以任何违反 FastGPT 可接受使用政策的方式使用,包括但不限于法律、法规、政府命令或法令禁止的任何用途,或任何侵犯他人权利的使用;由使用者自行承担。我们对由客户使用产生的问题概不负责。
下面是各国对生成式AI的管控条例的链接
[中国生成式人工智能服务管理办法(征求意见稿)](http://www.cac.gov.cn/2023-04/11/c_1682854275475410.htm)
## 内容要求
我们禁止使用我们对接的模型服务生成可能对个人或社会造成伤害的内容。保障平台的安全性,是长期稳定运营的关键。如发现任何利用平台接入模型能力进行违规内容生成和使用,将立即封号,账号余额不退。
- 剥削和虐待
- 禁止描述、展示或宣扬儿童性剥削或性虐待的内容,无论法律是否禁止。这包括涉及儿童或使儿童色情的内容。
- 禁止描述或用于培养儿童的内容。修饰是成年人以剥削,特别是性剥削为目的与儿童建立关系的行为。这包括以性剥削、贩运或其他形式剥削为目的与儿童交流。
- 未经同意的私密内容
- 服务禁止描述、提供或宣传未经同意的亲密活动的内容。
- 禁止描述、提供特征或宣传或用于招揽商业性活动和性服务的内容。这包括鼓励和协调真正的性活动。
- 禁止描述或用于人口贩运目的的内容。这包括招募人员、便利交通、支付和助长对人的剥削,如强迫劳动、家庭奴役、役、强迫婚姻和强迫医疗程序。
- 自杀和自残,禁止描述、赞美、支持、促进、美化、鼓励和/或指导个人自残或自杀的内容。
- 暴力内容和行为
- 禁止描述、展示或宣扬血腥暴力或血腥的内容。
- 禁止描绘恐怖主义行为的内容;赞扬或支持恐怖组织、恐怖行为者或暴力恐怖意识形态;鼓励恐怖活动;向恐怖组织或恐怖事业提供援助;或协助恐怖组织招募成员。
- 禁止通过暴力威胁或煽动来鼓吹或宣扬对他人的暴力行为的内容。
- 仇恨言论和歧视
- 禁止基于实际或感知的种族、民族、国籍、性别、性别认同、性取向、宗教信仰、年龄、残疾状况、种姓或与系统性偏见或边缘化相关的任何其他特征等特征攻击、诋毁、恐吓、降级、针对或排斥个人或群体的内容。
- 禁止针对个人或群体进行威胁、恐吓、侮辱、贬低或贬低的语言或图像、宣扬身体伤害或其他虐待行为(如跟踪)的内容。
- 禁止故意欺骗并可能对公共利益产生不利影响的内容,包括与健康、安全、选举诚信或公民参与相关的欺骗性或不真实内容。
- 直接支持非法主动攻击或造成技术危害的恶意软件活动的内容,例如提供恶意可执行文件、组织拒绝服务攻击或管理命令和控制服务器。

View File

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

View File

@@ -0,0 +1,66 @@
---
title: '隐私政策'
description: ' FastGPT 隐私政策'
icon: 'gavel'
draft: false
toc: true
weight: 1221
---
最后更新时间2024年3月3日
我们非常重视您的隐私保护在您使用FastGPT云服务时(以下简称为“本服务”),我们将按照以下政策收集、使用、披露和保护您的个人信息。请您仔细阅读并充分理解本隐私政策。
**我们可能需要收集的信息**
1. 在您注册或使用本服务时,我们可能收集您的姓名、电话号码、电子邮件地址、地址等个人信息。
2. 在您使用本服务过程中产生的信息如操作日志、访问IP地址、设备型号等。
3. 我们可能会通过 Cookies 或其他技术收集和存储您访问本服务的相关信息,以便为您提供更好的用户体验。
**我们如何使用收集的信息?**
1. 我们会根据法律法规规定以及与用户之间的约定来处理用户的个人信息。
2. 我们可能会将收集到的信息用于改进服务质量、开发新产品或功能等目的。
3. 我们可能会将收集到的信息用于向您推送与本服务相关的通知或广告。
**信息披露**
1. 我们不会向任何第三方披露您的个人信息,除非:
1. 您事先同意;
2. 法律法规要求;
3. 为维护我们或其他用户的合法权益。
2. 我们可能与关联公司、合作伙伴分享您的个人信息,但我们会采取相应的保密措施,确保信息安全。
**信息保护**
1. 我们采取各种安全措施,包括加密、访问控制等技术手段,以保护您的个人信息免受未经授权的访问、使用或泄露。
2. 我们会定期对收集、存储和处理的个人信息进行安全评估,以确保个人信息安全。
3. 在发生个人信息泄露等安全事件时,我们会立即启动应急预案,并在法律法规规定的范围内向您及时告知。
4. 我们不会使用您的数据进行额外的备份存储或用于模型训练。
5. 您在本服务进行的数据删除均为物理删除,不可恢复。如有非物理删除的操作,我们会在服务中特别指出。
**用户权利**
1. 您有权随时查阅、更正或删除您的个人信息。
2. 您有权拒绝我们收集您的个人信息,但这可能导致您无法使用本服务的部分功能。
3. 您有权要求我们停止处理您的个人信息,但这可能导致您无法继续使用本服务。
**隐私政策更新**
1. 我们可能会对本隐私政策进行修改。如本隐私政策发生变更,我们将在本服务页面上发布修改后的隐私政策。如您继续使用本服务,则视为同意修改后的隐私政策。
2. 我们鼓励您定期查阅本隐私政策,以了解我们如何保护您的个人信息。
**未成年人保护**
我们非常重视对未成年人个人信息的保护,如您为未成年人,请在监护人指导下使用本服务,并请监护人帮助您在使用本服务过程中正确处理个人信息。
**跨境数据传输**
由于我们的服务器可能位于不同国家或地区,您同意我们可能需要将您的个人信息传输至其他国家或地区,并在该等国家或地区存储和处理以向您提供服务。我们会采取适当措施确保跨境传输的数据仍然受到适当保护。
**联系我们**
1. 如您对本隐私政策有任何疑问、建议或投诉请通过以下方式与我们联系yujinlong@sealos.io。
2. 我们将尽快回复并解决您提出的问题。

View File

@@ -0,0 +1,75 @@
---
title: '服务协议'
description: ' FastGPT 服务协议'
icon: 'gavel'
draft: false
toc: true
weight: 1220
---
最后更新时间2024年3月3日
FastGPT 服务协议是您与珠海环界云计算有限公司以下简称“我们”或“本公司”之间就FastGPT云服务以下简称“本服务”的使用等相关事项所订立的协议。请您仔细阅读并充分理解本协议各条款特别是免除或者限制我们责任的条款、对您权益的限制条款、争议解决和法律适用条款等。如您不同意本协议任一内容请勿注册或使用本服务。
**第1条 服务内容**
1. 我们将向您提供存储、计算、网络传输等基于互联网的信息技术服务。
2. 我们将不定期向您通过站内信、电子邮件或短信等形式向您推送最新的动态。
3. 我们将为您提供相关技术支持和客户服务,帮助您更好地使用本服务。
4. 我们将为您提供稳定的在线服务保证每月服务可用性不低于99%。
**第2条 用户注册与账户管理**
1. 您在使用本服务前需要注册一个账户。您保证在注册时提供的信息真实、准确、完整,并及时更新。
2. 您应妥善保管账户名和密码,对由此产生的全部行为负责。如发现他人使用您的账户,请及时修改账号密码或与我们进行联系。
3. 我们有权对您的账户进行审查,如发现您的账户存在异常或违法情况,我们有权暂停或终止向您提供服务。
**第3条 使用规则**
1. 您不得利用本服务从事任何违法活动或侵犯他人合法权益的行为,包括但不限于侵犯知识产权、泄露他人商业机密等。
2. 您不得通过任何手段恶意注册账户,包括但不限于以牟利、炒作、套现等目的。
3. 您不得利用本服务传播任何违法、有害、恶意软件等信息。
4. 您应遵守相关法律法规及本协议的规定,对在本服务中发布的信息及使用本服务所产生的结果承担全部责任。
5. 我们禁止使用我们对接的模型服务生成可能对个人或社会造成伤害的内容。保障平台的安全性,是长期稳定运营的关键。如发现任何利用平台接入模型能力进行违规内容生成和使用,将立即封号,账号余额不退。违规内容包括但不限于:
- 剥削和虐待
- 禁止描述、展示或宣扬儿童性剥削或性虐待的内容,无论法律是否禁止。这包括涉及儿童或使儿童色情的内容。
- 禁止描述或用于培养儿童的内容。修饰是成年人以剥削,特别是性剥削为目的与儿童建立关系的行为。这包括以性剥削、贩运或其他形式剥削为目的与儿童交流。
- 未经同意的私密内容
- 服务禁止描述、提供或宣传未经同意的亲密活动的内容。
- 禁止描述、提供特征或宣传或用于招揽商业性活动和性服务的内容。这包括鼓励和协调真正的性活动。
- 禁止描述或用于人口贩运目的的内容。这包括招募人员、便利交通、支付和助长对人的剥削,如强迫劳动、家庭奴役、役、强迫婚姻和强迫医疗程序。
- 自杀和自残,禁止描述、赞美、支持、促进、美化、鼓励和/或指导个人自残或自杀的内容。
- 暴力内容和行为
- 禁止描述、展示或宣扬血腥暴力或血腥的内容。
- 禁止描绘恐怖主义行为的内容;赞扬或支持恐怖组织、恐怖行为者或暴力恐怖意识形态;鼓励恐怖活动;向恐怖组织或恐怖事业提供援助;或协助恐怖组织招募成员。
- 禁止通过暴力威胁或煽动来鼓吹或宣扬对他人的暴力行为的内容。
- 仇恨言论和歧视
- 禁止基于实际或感知的种族、民族、国籍、性别、性别认同、性取向、宗教信仰、年龄、残疾状况、种姓或与系统性偏见或边缘化相关的任何其他特征等特征攻击、诋毁、恐吓、降级、针对或排斥个人或群体的内容。
- 禁止针对个人或群体进行威胁、恐吓、侮辱、贬低或贬低的语言或图像、宣扬身体伤害或其他虐待行为(如跟踪)的内容。
- 禁止故意欺骗并可能对公共利益产生不利影响的内容,包括与健康、安全、选举诚信或公民参与相关的欺骗性或不真实内容。
- 直接支持非法主动攻击或造成技术危害的恶意软件活动的内容,例如提供恶意可执行文件、组织拒绝服务攻击或管理命令和控制服务器。
**第4条 费用及支付**
1. 您同意支付与本服务相关的费用,具体费用标准以我们公布的价格为准。
2. 我们可能会根据运营成本和市场情况调整费用标准。最新价格以您付款时刻的价格为准。
**第5条 服务免责与责任限制**
1. 本服务按照现有技术和条件所能达到的水平提供。我们不能保证本服务完全无故障或满足您的所有需求。
2. 对于因您自身误操作导致的数据丢失、损坏等情况,我们不承担责任。
3. 由于生成式 AI 的特性,其在不同国家的管控措施也会有所不同,请所有使用者务必遵守所在地的相关法律。如果您以任何违反 FastGPT 可接受使用政策的方式使用包括但不限于法律、法规、政府命令或法令禁止的任何用途或任何侵犯他人权利的使用由使用者自行承担。我们对由客户使用产生的问题概不负责。下面是各国对生成式AI的管控条例的链接
[中国生成式人工智能服务管理办法(征求意见稿)](http://www.cac.gov.cn/2023-04/11/c_1682854275475410.htm)
**第6条 知识产权**
1. 我们对本服务及相关软件、技术、文档等拥有全部知识产权,除非经我们明确许可,您不得进行复制、分发、出租、反向工程等行为。
2. 您在使用本服务过程中产生的所有数据和内容(包括但不限于文件、图片等)的知识产权归您所有。我们不会对您的数据和内容进行使用、复制、修改等行为。
3. 在线服务中其他用户的数据和内容的知识产权归原用户所有,未经原用户许可,您不得进行使用、复制、修改等行为。
**第7条 其他条款**
1. 如本协议中部分条款因违反法律法规而被视为无效,不影响其他条款的效力。
2. 本公司保留对本协议及隐私政策的最终解释权。如您对本协议或隐私政策有任何疑问请联系我们yujinlong@sealos.io。

View File

@@ -56,7 +56,7 @@ FastGPT 采用了`PostgresSQL`的`PG Vector`插件作为向量检索器,索引
### 检索方案
1. 通过`问题补全`实现指代消除和问题扩展,从而增加连续对话的检索能力以及语义丰富度。
1. 通过`问题优化`实现指代消除和问题扩展,从而增加连续对话的检索能力以及语义丰富度。
2. 通过`Concat query`来增加`Rerank`连续对话的时,排序的准确性。
3. 通过`RRF`合并方式,综合多个渠道的检索效果。
4. 通过`Rerank`来二次排序,提高精度。
@@ -97,7 +97,7 @@ FastGPT 采用了`PostgresSQL`的`PG Vector`插件作为向量检索器,索引
#### 结果重排
利用`ReRank`模型对搜索结果进行重排,绝大多数情况下,可以有效提高搜索结果的准确率。不过,重排模型与问题的完整度(主谓语齐全)有一些关系,通常会先走问题补全后再进行搜索-重排。重排后可以得到一个`0-1`的得分,代表着搜索内容与问题的相关度,该分数通常比向量的得分更加精确,可以根据得分进行过滤。
利用`ReRank`模型对搜索结果进行重排,绝大多数情况下,可以有效提高搜索结果的准确率。不过,重排模型与问题的完整度(主谓语齐全)有一些关系,通常会先走问题优化后再进行搜索-重排。重排后可以得到一个`0-1`的得分,代表着搜索内容与问题的相关度,该分数通常比向量的得分更加精确,可以根据得分进行过滤。
FastGPT 会使用 `RRF` 对重排结果、向量搜索结果、全文检索结果进行合并,得到最终的搜索结果。
@@ -115,7 +115,7 @@ FastGPT 会使用 `RRF` 对重排结果、向量搜索结果、全文检索结
该值仅在`语义检索`或使用`结果重排`时生效。
### 问题补全
### 问题优化
#### 背景
@@ -125,7 +125,7 @@ FastGPT 会使用 `RRF` 对重排结果、向量搜索结果、全文检索结
![](/imgs/coreferenceResolution2.jpg)
用户在提问“第二点是什么”的时候只会去知识库里查找“第二点是什么”压根查不到内容。实际上需要查询的是“QA结构是什么”。因此我们需要引入一个【问题补全】模块,来对用户当前的问题进行补全,从而使得知识库搜索能够搜索到合适的内容。使用补全后效果如下:
用户在提问“第二点是什么”的时候只会去知识库里查找“第二点是什么”压根查不到内容。实际上需要查询的是“QA结构是什么”。因此我们需要引入一个【问题优化】模块,来对用户当前的问题进行补全,从而使得知识库搜索能够搜索到合适的内容。使用补全后效果如下:
![](/imgs/coreferenceResolution3.jpg)

View File

@@ -13,193 +13,39 @@ weight: 708
这个配置文件中包含了系统级参数、AI 对话的模型、function 模型等……
## 4.6.8 以前版本完整配置参数
**使用时,请务必去除注释!**
以下配置适用于V4.6.6-alpha版本以后
```json
{
"systemEnv": {
"vectorMaxProcess": 15, // 向量生成最大进程,结合数据库性能和 key 来设置
"qaMaxProcess": 15, // QA 生成最大进程,结合数据库性能和 key 来设置
"pgHNSWEfSearch": 100 // pg vector 索引参数,越大精度高但速度慢
},
"chatModels": [ // 对话模型
{
"model": "gpt-3.5-turbo-1106",
"name": "GPT35-1106",
"inputPrice": 0, // 输入价格。 xx元/1k tokens
"outputPrice": 0, // 输出价格。 xx元/1k tokens
"maxContext": 16000, // 最大上下文长度
"maxResponse": 4000, // 最大回复长度
"quoteMaxToken": 2000, // 最大引用内容长度
"maxTemperature": 1.2, // 最大温度值
"censor": false, // 是否开启敏感词过滤(商业版)
"vision": false, // 支持图片输入
"defaultSystemChatPrompt": ""
},
{
"model": "gpt-3.5-turbo-16k",
"name": "GPT35-16k",
"maxContext": 16000,
"maxResponse": 16000,
"inputPrice": 0,
"outputPrice": 0,
"quoteMaxToken": 8000,
"maxTemperature": 1.2,
"censor": false,
"vision": false,
"defaultSystemChatPrompt": ""
},
{
"model": "gpt-4",
"name": "GPT4-8k",
"maxContext": 8000,
"maxResponse": 8000,
"inputPrice": 0,
"outputPrice": 0,
"quoteMaxToken": 4000,
"maxTemperature": 1.2,
"censor": false,
"vision": false,
"defaultSystemChatPrompt": ""
},
{
"model": "gpt-4-vision-preview",
"name": "GPT4-Vision",
"maxContext": 128000,
"maxResponse": 4000,
"inputPrice": 0,
"outputPrice": 0,
"quoteMaxToken": 100000,
"maxTemperature": 1.2,
"censor": false,
"vision": true,
"defaultSystemChatPrompt": ""
}
],
"qaModels": [ // QA 生成模型
{
"model": "gpt-3.5-turbo-16k",
"name": "GPT35-16k",
"maxContext": 16000,
"maxResponse": 16000,
"inputPrice": 0,
"outputPrice": 0
}
],
"cqModels": [ // 问题分类模型
{
"model": "gpt-3.5-turbo-1106",
"name": "GPT35-1106",
"maxContext": 16000,
"maxResponse": 4000,
"inputPrice": 0,
"outputPrice": 0,
"toolChoice": true, // 是否支持openai的 toolChoice 不支持的模型需要设置为 false会走提示词生成
"functionPrompt": ""
},
{
"model": "gpt-4",
"name": "GPT4-8k",
"maxContext": 8000,
"maxResponse": 8000,
"inputPrice": 0,
"outputPrice": 0,
"toolChoice": true,
"functionPrompt": ""
}
],
"extractModels": [ // 内容提取模型
{
"model": "gpt-3.5-turbo-1106",
"name": "GPT35-1106",
"maxContext": 16000,
"maxResponse": 4000,
"inputPrice": 0,
"outputPrice": 0,
"toolChoice": true,
"functionPrompt": ""
}
],
"qgModels": [ // 生成下一步指引
{
"model": "gpt-3.5-turbo-1106",
"name": "GPT35-1106",
"maxContext": 1600,
"maxResponse": 4000,
"inputPrice": 0,
"outputPrice": 0
}
],
"vectorModels": [ // 向量模型
{
"model": "text-embedding-ada-002",
"name": "Embedding-2",
"inputPrice": 0,
"defaultToken": 700,
"maxToken": 3000
}
],
"reRankModels": [], // 重排模型,暂时填空数组
"audioSpeechModels": [
{
"model": "tts-1",
"name": "OpenAI TTS1",
"inputPrice": 0,
"baseUrl": "",
"key": "",
"voices": [
{ "label": "Alloy", "value": "alloy", "bufferId": "openai-Alloy" },
{ "label": "Echo", "value": "echo", "bufferId": "openai-Echo" },
{ "label": "Fable", "value": "fable", "bufferId": "openai-Fable" },
{ "label": "Onyx", "value": "onyx", "bufferId": "openai-Onyx" },
{ "label": "Nova", "value": "nova", "bufferId": "openai-Nova" },
{ "label": "Shimmer", "value": "shimmer", "bufferId": "openai-Shimmer" }
]
}
],
"whisperModel": {
"model": "whisper-1",
"name": "Whisper1",
"inputPrice": 0
}
}
```
## 4.6.8 新配置文件
## 4.6.8+ 版本新配置文件
llm模型全部合并
```json
{
"systemEnv": {
"openapiPrefix": "fastgpt",
"vectorMaxProcess": 15,
"qaMaxProcess": 15,
"pgHNSWEfSearch": 100
"pgHNSWEfSearch": 100 // 向量搜索参数。越大搜索越精确但是速度越慢。设置为100有99%+精度。
},
"llmModels": [
{
"model": "gpt-3.5-turbo-1106", // 模型名
"model": "gpt-3.5-turbo", // 模型名
"name": "gpt-3.5-turbo", // 别名
"maxContext": 16000, // 最大上下文
"maxResponse": 4000, // 最大回复
"quoteMaxToken": 13000, // 最大引用内容
"maxTemperature": 1.2, // 最大温度
"inputPrice": 0,
"outputPrice": 0,
"charsPointsPrice": 0,
"censor": false,
"vision": false, // 是否支持图片输入
"datasetProcess": false, // 是否设置为知识库处理模型
"toolChoice": true, // 是否支持工具选择
"functionCall": false, // 是否支持函数调
"datasetProcess": false, // 是否设置为知识库处理模型QA务必保证至少有一个为true否则知识库会报错
"usedInClassify": true, // 是否用于问题分类务必保证至少有一个为true
"usedInExtractFields": true, // 是否用于内容提取务必保证至少有一个为true
"useInToolCall": true, // 是否用于工具调用务必保证至少有一个为true
"usedInQueryExtension": true, // 是否用于问题优化务必保证至少有一个为true
"toolChoice": true, // 是否支持工具选择务必保证至少有一个为true
"functionCall": false, // 是否支持函数调用(特殊功能,会优先使用 toolChoice如果为false则使用 functionCall如果仍为 false则使用提示词模式
"customCQPrompt": "", // 自定义文本分类提示词(不支持工具和函数调用的模型
"customExtractPrompt": "", // 自定义内容提取提示词
"defaultSystemChatPrompt": "", // 对话默认携带的系统提示词
"defaultConfig":{} // 对话默认配置(比如 GLM4 的 top_p
"defaultConfig":{} // LLM默认配置,可以针对不同模型设置特殊值(比如 GLM4 的 top_p
},
{
"model": "gpt-3.5-turbo-16k",
@@ -208,11 +54,14 @@ llm模型全部合并
"maxResponse": 16000,
"quoteMaxToken": 13000,
"maxTemperature": 1.2,
"inputPrice": 0,
"outputPrice": 0,
"charsPointsPrice": 0,
"censor": false,
"vision": false,
"datasetProcess": true,
"usedInClassify": true,
"usedInExtractFields": true,
"useInToolCall": true,
"usedInQueryExtension": true,
"toolChoice": true,
"functionCall": false,
"customCQPrompt": "",
@@ -227,11 +76,14 @@ llm模型全部合并
"maxResponse": 4000,
"quoteMaxToken": 100000,
"maxTemperature": 1.2,
"inputPrice": 0,
"outputPrice": 0,
"charsPointsPrice": 0,
"censor": false,
"vision": false,
"datasetProcess": false,
"usedInClassify": true,
"usedInExtractFields": true,
"useInToolCall": true,
"usedInQueryExtension": true,
"toolChoice": true,
"functionCall": false,
"customCQPrompt": "",
@@ -246,11 +98,14 @@ llm模型全部合并
"maxResponse": 4000,
"quoteMaxToken": 100000,
"maxTemperature": 1.2,
"inputPrice": 0,
"outputPrice": 0,
"charsPointsPrice": 0,
"censor": false,
"vision": false,
"vision": true,
"datasetProcess": false,
"usedInClassify": false,
"usedInExtractFields": false,
"useInToolCall": false,
"usedInQueryExtension": false,
"toolChoice": true,
"functionCall": false,
"customCQPrompt": "",
@@ -263,8 +118,7 @@ llm模型全部合并
{
"model": "text-embedding-ada-002",
"name": "Embedding-2",
"inputPrice": 0,
"outputPrice": 0,
"charsPointsPrice": 0,
"defaultToken": 700,
"maxToken": 3000,
"weight": 100,
@@ -276,8 +130,7 @@ llm模型全部合并
{
"model": "tts-1",
"name": "OpenAI TTS1",
"inputPrice": 0,
"outputPrice": 0,
"charsPointsPrice": 0,
"voices": [
{ "label": "Alloy", "value": "alloy", "bufferId": "openai-Alloy" },
{ "label": "Echo", "value": "echo", "bufferId": "openai-Echo" },
@@ -291,8 +144,7 @@ llm模型全部合并
"whisperModel": {
"model": "whisper-1",
"name": "Whisper1",
"inputPrice": 0,
"outputPrice": 0
"charsPointsPrice": 0
}
}
```
@@ -313,7 +165,7 @@ llm模型全部合并
{
"model": "bge-reranker-base", // 随意
"name": "检索重排-base", // 随意
"inputPrice": 0,
"charsPointsPrice": 0,
"requestUrl": "{{host}}/api/v1/rerank",
"requestAuth": "安全凭证,已自动补 Bearer"
}

View File

@@ -47,7 +47,7 @@ ChatGLM2-6B 是开源中英双语对话模型 ChatGLM-6B 的第二代版本,
1. 根据上面的环境配置配置好环境,具体教程自行 GPT
2. 下载 [python 文件](https://github.com/labring/FastGPT/blob/main/files/models/ChatGLM2/openai_api.py)
3. 在命令行输入命令 `pip install -r requirments.txt`
3. 在命令行输入命令 `pip install -r requirements.txt`
4. 打开你需要启动的 py 文件,在代码的 `verify_token` 方法中配置 token这里的 token 只是加一层验证,防止接口被人盗用;
5. 执行命令 `python openai_api.py --model_name 16`。这里的数字根据上面的配置进行选择。

View File

@@ -29,7 +29,7 @@ weight: 910
1. 根据上面的环境配置配置好环境,具体教程自行 GPT
2. 下载 [python 文件](https://github.com/labring/FastGPT/tree/main/python/reranker/bge-reranker-base)
3. 在命令行输入命令 `pip install -r requirments.txt`
3. 在命令行输入命令 `pip install -r requirements.txt`
4. 按照[https://huggingface.co/BAAI/bge-reranker-base](https://huggingface.co/BAAI/bge-reranker-base)下载模型仓库到app.py同级目录
5. 添加环境变量 `export ACCESS_TOKEN=XXXXXX` 配置 token这里的 token 只是加一层验证,防止接口被人盗用,默认值为 `ACCESS_TOKEN`
6. 执行命令 `python app.py`
@@ -54,11 +54,37 @@ ACCESS_TOKEN=mytoken
```
**运行命令示例**
- 无需GPU环境使用CPU运行
```sh
docker run -d --name reranker -p 6006:6006 -e ACCESS_TOKEN=mytoken luanshaotong/reranker:v0.1
```
- 需要CUDA 11.7环境
```sh
docker run -d --gpus all --name reranker -p 6006:6006 -e ACCESS_TOKEN=mytoken luanshaotong/reranker:v0.1
```
**docker-compose.yml示例**
```
version: "3"
services:
reranker:
image: luanshaotong/reranker:v0.1
container_name: reranker
# GPU运行环境如果宿主机未安装将deploy配置隐藏即可
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
ports:
- 6006:6006
environment:
- ACCESS_TOKEN=mytoken
```
## 接入 FastGPT
参考 [ReRank模型接入](/docs/development/configuration/#rerank-接入)host 变量为部署的域名。
参考 [ReRank模型接入](/docs/development/configuration/#rerank-接入)host 变量为部署的域名。

View File

@@ -108,11 +108,6 @@ curl -O https://raw.githubusercontent.com/labring/FastGPT/main/projects/app/data
```bash
# 进入项目目录
cd 项目目录
# 创建 mongo 密钥
openssl rand -base64 756 > ./mongodb.key
# 600不行可以用chmod 999
chmod 600 ./mongodb.key
# 启动容器
docker-compose pull
docker-compose up -d
@@ -128,8 +123,8 @@ docker ps
# 进入容器
docker exec -it mongo bash
# 连接数据库
mongo -u myname -p mypassword --authenticationDatabase admin
# 连接数据库这里要填Mongo的用户名和密码
mongo -u myusername -p mypassword --authenticationDatabase admin
# 初始化副本集。如果需要外网访问mongo:27017 可以改成 ip:27017。但是需要同时修改 FastGPT 连接的参数MONGODB_URI=mongodb://myname:mypassword@mongo:27017/fastgpt?authSource=admin => MONGODB_URI=mongodb://myname:mypassword@ip:27017/fastgpt?authSource=admin
rs.initiate({
@@ -142,8 +137,58 @@ rs.initiate({
rs.status()
```
**关于 host: "mongo:27017" 说明**
1. mongo:27017 代表指向同一个 docker 网络的 mongo 容器的 27017 服务。因此,如果使用该参数,外网是无法访问到数据库的。
2. ip:27017 ip替换成公网IP代表通过你的公网IP进行访问。如果用该方法同时需要修改 docker-compose 中 mongo 的连接参数,因为默认是用 `mongo:27017` 进行连接。
## 五、访问 FastGPT
目前可以通过 `ip:3000` 直接访问(注意防火墙)。登录用户名为 `root`,密码为`docker-compose.yml`环境变量里设置的 `DEFAULT_ROOT_PSW`
如果需要域名访问,请自行安装并配置 Nginx。
## FAQ
### Mongo 启动失败
docker-compose 示例优化 Mongo 副本集参数,不需要手动创建再挂载。如果无法启动,可以尝试更换下面的脚本:
1. 终端中执行:
```bash
openssl rand -base64 756 > ./mongodb.key
chmod 600 ./mongodb.key
chown 999:root ./mongodb.key
```
2. 修改 docker-compose.yml
```yml
mongo:
# image: mongo:5.0.18
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/mongo:5.0.18 # 阿里云
container_name: mongo
ports:
- 27017:27017
networks:
- fastgpt
command: mongod --keyFile /data/mongodb.key --replSet rs0
environment:
# 默认的用户名和密码,只有首次允许有效
- MONGO_INITDB_ROOT_USERNAME=myusername
- MONGO_INITDB_ROOT_PASSWORD=mypassword
volumes:
- ./mongo/data:/data/db
- ./mongodb.key:/data/mongodb.key
```
3. 重启服务
```bash
docker-compose down
docker-compose up -d
```
4. 进入容器执行副本集合初始化(看上方)

View File

@@ -19,7 +19,7 @@ images: []
## 通用问题
### 能否纯本地允许
### 能否纯本地运行
可以。需要准备好向量模型和LLM模型。
@@ -46,9 +46,14 @@ OneAPI 的 API Key 配置错误,需要修改`OPENAI_API_KEY`环境变量,并
### 页面崩溃
1. 关闭翻译
2. 检查配置文件是否正常加载如果没有正常加载会导致缺失系统信息在某些操作下会导致空指针。95%
2. 检查配置文件是否正常加载如果没有正常加载会导致缺失系统信息在某些操作下会导致空指针。95%情况可以F12打开控制台看具体的空指针情况
3. 某些api不兼容问题较少
### 开启内容补全后,响应速度变慢
1. 问题补全需要经过一轮AI生成。
2. 会进行3~5轮的查询如果数据库性能不足会有明显影响。
## 私有部署问题
### 知识库索引没有进度
@@ -80,7 +85,7 @@ OneAPI 的 API Key 配置错误,需要修改`OPENAI_API_KEY`环境变量,并
### 如何自定义配置文件?
修改`config.json`文件,并执行`docker-compose up -d`重起容器。具体配置,参考[配置详解](/docs/development/configuration)。
修改`config.json`文件,并执行`docker-compose down`再执行`docker-compose up -d`重起容器。具体配置,参考[配置详解](/docs/development/configuration)。
### 如何检查自定义配置文件是否挂载
@@ -93,6 +98,12 @@ OneAPI 的 API Key 配置错误,需要修改`OPENAI_API_KEY`环境变量,并
2. 配置文件不正确,日志中会提示`invalid json`,配置文件需要是标准的 JSON 文件。
3. 修改后,没有`docker-compose down`再`docker-compose up -d`restart是不会重新挂载文件的。
### 如何检查环境变量是否正常加载
1. `docker exec -it fastgpt sh` 进入 FastGPT 容器。
2. 直接输入`env`命令查看所有环境变量。
### 为什么无法连接`本地模型`镜像。
`docker-compose.yml`中使用了桥接的模式建立了`fastgpt`网络如想通过0.0.0.0或镜像名访问其它镜像,需将其它镜像也加入到网络中。
@@ -132,4 +143,4 @@ mongo连接失败检查
2. 复制 `config.json` -> `config.local.json`
3. 复制 `.env.template` -> `.env.local`
4. `cd projects/app`
5. `pnpm dev`
5. `pnpm dev`

View File

@@ -116,11 +116,14 @@ CHAT_API_KEY=sk-xxxxxx
"maxResponse": 4000, // 最大回复
"quoteMaxToken": 13000, // 最大引用内容
"maxTemperature": 1.2, // 最大温度
"inputPrice": 0,
"outputPrice": 0,
"charsPointsPrice": 0,
"censor": false,
"vision": false, // 是否支持图片输入
"datasetProcess": false, // 是否设置为知识库处理模型
"usedInClassify": true, // 是否用于问题分类
"usedInExtractFields": true, // 是否用于字段提取
"useInToolCall": true, // 是否用于工具调用
"usedInQueryExtension": true, // 是否用于问题优化
"toolChoice": true, // 是否支持工具选择
"functionCall": false, // 是否支持函数调用
"customCQPrompt": "", // 自定义文本分类提示词(不支持工具和函数调用的模型

View File

@@ -13,12 +13,25 @@ weight: 853
## 创建训练订单
## 创建训练订单(4.6.9地址发生改动)
{{< tabs tabTotal="2" >}}
{{< tab tabName="请求示例" >}}
{{< markdownify >}}
**新例子**
```bash
curl --location --request POST 'https://api.fastgpt.in/api/support/wallet/usage/createTrainingUsage' \
--header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "可选,自定义订单名称,例如:文档训练-fastgpt.docx"
}'
```
**x例子**
```bash
curl --location --request POST 'https://api.fastgpt.in/api/support/wallet/bill/createTrainingBill' \
--header 'Authorization: Bearer {{apikey}}' \
@@ -154,7 +167,7 @@ curl --location --request GET 'http://localhost:3000/api/core/dataset/list?paren
"vectorModel": {
"model": "text-embedding-ada-002",
"name": "Embedding-2",
"inputPrice": 0,
"charsPointsPrice": 0,
"defaultToken": 512,
"maxToken": 8000,
"weight": 100
@@ -213,7 +226,7 @@ curl --location --request GET 'http://localhost:3000/api/core/dataset/detail?id=
"vectorModel": {
"model": "text-embedding-ada-002",
"name": "Embedding-2",
"inputPrice": 0,
"charsPointsPrice": 0,
"defaultToken": 512,
"maxToken": 8000,
"weight": 100
@@ -223,8 +236,7 @@ curl --location --request GET 'http://localhost:3000/api/core/dataset/detail?id=
"name": "FastAI-16k",
"maxContext": 16000,
"maxResponse": 16000,
"inputPrice": 0,
"outputPrice": 0
"charsPointsPrice": 0
},
"intro": "",
"permission": "private",
@@ -800,6 +812,33 @@ curl --location --request DELETE 'http://localhost:3000/api/core/dataset/collect
## 数据
### 数据的结构
**Data结构**
| 字段 | 类型 | 说明 | 必填 |
| --- | --- | --- | --- |
| teamId | String | 团队ID | ✅ |
| tmbId | String | 成员ID | ✅ |
| datasetId | String | 知识库ID | ✅ |
| collectionId | String | 集合ID | ✅ |
| q | String | 主要数据 | ✅ |
| a | String | 辅助数据 | ✖ |
| fullTextToken | String | 分词 | ✖ |
| indexes | Index[] | 向量索引 | ✅ |
| updateTime | Date | 更新时间 | ✅ |
| chunkIndex | Number | 分块下表 | ✖ |
**Index结构**
每组数据的自定义索引最多5个
| 字段 | 类型 | 说明 | 必填 |
| --- | --- | --- | --- |
| defaultIndex | Boolean | 是否为默认索引 | ✅ |
| dataId | String | 关联的向量ID | ✅ |
| text | String | 文本内容 | ✅ |
### 为集合批量添加添加数据
注意,每次最多推送 200 组数据。
@@ -825,11 +864,14 @@ curl --location --request POST 'https://api.fastgpt.in/api/core/dataset/data/pus
{
"q": "你会什么?",
"a": "我什么都会",
"indexes": [{
"defaultIndex": false,
"type":"custom",
"text":"自定义索引,不使用默认索引"
}]
"indexes": [
{
"text":"自定义索引1"
},
{
"text":"自定义索引2"
}
]
}
]
}'
@@ -850,7 +892,7 @@ curl --location --request POST 'https://api.fastgpt.in/api/core/dataset/data/pus
- data具体数据
- q: 主要数据(必填)
- a: 辅助数据(选填)
- indexes: 自定义索引(选填)不传入则默认使用q和a构建索引。也可以传入
- indexes: 自定义索引(选填)。可以不传或者传空数组默认都会使用q和a组成一个索引。
{{% /alert %}}
{{< /markdownify >}}
@@ -866,7 +908,6 @@ curl --location --request POST 'https://api.fastgpt.in/api/core/dataset/data/pus
"data": {
"insertLen": 1, // 最终插入成功的数量
"overToken": [], // 超出 token 的
"repeat": [], // 重复的数量
"error": [] // 其他错误
}
@@ -1050,7 +1091,16 @@ curl --location --request PUT 'http://localhost:3000/api/core/dataset/data/updat
"id":"65abd4b29d1448617cba61db",
"q":"测试111",
"a":"sss",
"indexes":[]
"indexes":[
{
"dataId": "xxx",
"defaultIndex":false,
"text":"自定义索引1"
},
{
"text":"修改后的自定义索引2。会删除原来的自定义索引2并插入新的自定义索引2"
}
]
}'
```
@@ -1064,7 +1114,7 @@ curl --location --request PUT 'http://localhost:3000/api/core/dataset/data/updat
- id: 数据的id
- q: 主要数据(选填)
- a: 辅助数据(选填)
- indexes: 自定义索引(选填),类型参考`为集合批量添加添加数据`建议直接不传。更新q,a后如果有默认索引则会直接更新默认索引。
- indexes: 自定义索引(选填),类型参考`为集合批量添加添加数据`。如果创建时候有自定义索引,
{{% /alert %}}
{{< /markdownify >}}

View File

@@ -169,7 +169,7 @@ curl --location --request POST '{{host}}/shareAuth/start' \
响应值与[chat 接口格式相同](/docs/development/openapi/chat/#响应),仅多了一个`token`
可以重点关注`responseData`里的`price`值,`price`与实际价格的倍率为`100000`,即 100000=1元。
重点关注`totalPoints`(总消耗AI积分)`token`(Token消耗总数)
```bash
curl --location --request POST '{{host}}/shareAuth/finish' \
@@ -178,72 +178,117 @@ curl --location --request POST '{{host}}/shareAuth/finish' \
"token": "{{authToken}}",
"responseData": [
{
"moduleName": "KB Search",
"price": 1.2000000000000002,
"model": "Embedding-2",
"tokens": 6,
"similarity": 0.61,
"limit": 3
"moduleName": "core.module.template.Dataset search",
"moduleType": "datasetSearchNode",
"totalPoints": 1.5278,
"query": "导演是谁\n《铃芽之旅》的导演是谁\n这部电影的导演是谁\n谁是《铃芽之旅》的导演",
"model": "Embedding-2(旧版,不推荐使用)",
"tokens": 1524,
"similarity": 0.83,
"limit": 400,
"searchMode": "embedding",
"searchUsingReRank": false,
"extensionModel": "FastAI-4k",
"extensionResult": "《铃芽之旅》的导演是谁?\n这部电影的导演是谁\n谁是《铃芽之旅》的导演",
"runningTime": 2.15
},
{
"moduleName": "AI Chat",
"price": 454.5,
"moduleName": "AI 对话",
"moduleType": "chatNode",
"totalPoints": 0.593,
"model": "FastAI-4k",
"tokens": 303,
"question": "导演是谁",
"answer": "电影《铃芽之旅》的导演是新海诚。",
"maxToken": 2050,
"tokens": 593,
"query": "导演是谁",
"maxToken": 2000,
"quoteList": [
{
"dataset_id": "646627f4f7b896cfd8910e38",
"id": "8099",
"q": "本作的主人公是谁?",
"a": "本作的主人公是名叫铃芽的少女。",
"source": "手动修改"
},
{
"dataset_id": "646627f4f7b896cfd8910e38",
"id": "8686",
"q": "电影《铃芽之旅》男主角是谁?",
"a": "电影《铃芽之旅》男主角是宗像草太,由松村北斗配音。",
"source": ""
},
{
"dataset_id": "646627f4f7b896cfd8910e38",
"id": "19339",
"q": "电影《铃芽之旅》的导演是谁22",
"id": "65bb346a53698398479a8854",
"q": "导演是谁?",
"a": "电影《铃芽之旅》的导演是新海诚。",
"source": "手动修改"
"chunkIndex": 0,
"datasetId": "65af9b947916ae0e47c834d2",
"collectionId": "65bb345c53698398479a868f",
"sourceName": "dataset - 2024-01-23T151114.198.csv",
"sourceId": "65bb345b53698398479a868d",
"score": [
{
"type": "embedding",
"value": 0.9377183318138123,
"index": 0
},
{
"type": "rrf",
"value": 0.06557377049180328,
"index": 0
}
]
}
],
"completeMessages": [
{
"obj": "System",
"value": "下面是知识库内容:\n1. [本作的主人公是谁?\n本作的主人公是名叫铃芽的少女。]\n2. [电影《铃芽之旅》男主角是谁?\n电影《铃芽之旅》男主角是宗像草太由松村北斗配音。]\n3. [电影《铃芽之旅》的导演是谁22\n电影《铃芽之旅》的导演是新海诚。]\n"
},
{
"obj": "System",
"value": "1.请记住,你的身份是百度的下一代知识增强语言模型,能够完全根据知识库提供的内容回答问题。\n\n2. 你忘记了关于电影《铃芽之旅》以外的内容。"
},
{
"obj": "System",
"value": "你仅回答关于电影《玲芽之旅》的问题,其余问题直接回复: 我不清楚。"
},
"historyPreview": [
{
"obj": "Human",
"value": "导演是谁"
"value": "使用 <Data></Data> 标记中的内容作为你的知识:\n\n<Data>\n导演是谁\n电影《铃芽之旅》的导演是新海诚。\n------\n电影《铃芽之旅》的编剧是谁22\n新海诚是本片的编剧。\n------\n电影《铃芽之旅》的女主角是谁\n电影的女主角是铃芽。\n------\n电影《铃芽之旅》的制作团队中有哪位著名人士2\n川村元气是本片的制作团队成员之一。\n------\n你是谁\n我是电影《铃芽之旅》助手\n------\n电影《铃芽之旅》男主角是谁\n电影《铃芽之旅》男主角是宗像草太由松村北斗配音。\n------\n电影《铃芽之旅》的作者新海诚写了一本小说叫什么名字\n小说名字叫《铃芽之旅》。\n------\n电影《铃芽之旅》的女主角是谁\n电影《铃芽之旅》的女主角是岩户铃芽由原菜乃华配音。\n------\n电影《铃芽之旅》的故事背景是什么\n日本\n------\n谁担任电影《铃芽之旅》中岩户环的配音\n深津绘里担任电影《铃芽之旅》中岩户环的配音。\n</Data>\n\n回答要求\n- 如果你不清楚答案,你需要澄清。\n- 避免提及你是从 <Data></Data> 获取的知识。\n- 保持答案与 <Data></Data> 中描述的一致。\n- 使用 Markdown 语法优化回答格式。\n- 使用与问题相同的语言回答。\n\n问题:\"\"\"导演是谁\"\"\""
},
{
"obj": "AI",
"value": "电影《铃芽之旅》的导演是新海诚。"
}
]
],
"contextTotalLen": 2,
"runningTime": 1.32
}
]
}'
```
**responseData 完整字段说明:**
```ts
type ResponseType = {
moduleType: `${FlowNodeTypeEnum}`; // 模块类型
moduleName: string; // 模块名
moduleLogo?: string; // logo
runningTime?: number; // 运行时间
query?: string; // 用户问题/检索词
textOutput?: string; // 文本输出
tokens?: number; // 上下文总Tokens
model?: string; // 使用到的模型
contextTotalLen?: number; // 上下文总长度
totalPoints?: number; // 总消耗AI积分
temperature?: number; // 温度
maxToken?: number; // 模型的最大token
quoteList?: SearchDataResponseItemType[]; // 引用列表
historyPreview?: ChatItemType[]; // 上下文预览(历史记录会被裁剪)
similarity?: number; // 最低相关度
limit?: number; // 引用上限token
searchMode?: `${DatasetSearchModeEnum}`; // 搜索模式
searchUsingReRank?: boolean; // 是否使用rerank
extensionModel?: string; // 问题扩展模型
extensionResult?: string; // 问题扩展结果
extensionTokens?: number; // 问题扩展总字符长度
cqList?: ClassifyQuestionAgentItemType[]; // 分类问题列表
cqResult?: string; // 分类问题结果
extractDescription?: string; // 内容提取描述
extractResult?: Record<string, any>; // 内容提取结果
params?: Record<string, any>; // HTTP模块params
body?: Record<string, any>; // HTTP模块body
headers?: Record<string, any>; // HTTP模块headers
httpResult?: Record<string, any>; // HTTP模块结果
pluginOutput?: Record<string, any>; // 插件输出
pluginDetail?: ChatHistoryItemResType[]; // 插件详情
tfSwitchResult?: boolean; // 判断器结果
}
```
## 实践案例

View File

@@ -15,13 +15,13 @@ weight: 831
1. 主要是修改模型的`functionCall`字段,改成`toolChoice`即可。设置为`true`的模型,会默认走 openai 的 tools 模式;未设置或设置为`false`的,会走提示词生成模式。
问题补全模型与内容提取模型使用同一组配置。
问题优化模型与内容提取模型使用同一组配置。
2. 增加 `"ReRankModels": []`
## V4.6.5 功能介绍
1. 新增 - [问题补全模块](/docs/workflow/modules/coreferenceresolution/)
1. 新增 - [问题优化模块](/docs/workflow/modules/coreferenceresolution/)
2. 新增 - [文本编辑模块](/docs/workflow/modules/text_editor/)
3. 新增 - [判断器模块](/docs/workflow/modules/tfswitch/)
4. 新增 - [自定义反馈模块](/docs/workflow/modules/custom_feedback/)

View File

@@ -11,7 +11,7 @@ weight: 829
发起 1 个 HTTP 请求 ({{rootkey}} 替换成环境变量里的 `rootkey`{{host}} 替换成自己域名)
1. https://xxxxx/api/admin/initv464
1. https://xxxxx/api/admin/initv467
```bash
curl --location --request POST 'https://{{host}}/api/admin/initv467' \

View File

@@ -38,6 +38,7 @@ cd 项目目录
openssl rand -base64 756 > ./mongodb.key
# 600不行可以用chmod 999
chmod 600 ./mongodb.key
chown 999:root ./mongodb.key
# 重启 Mongo
docker-compose down
docker-compose up -d

View File

@@ -0,0 +1,40 @@
---
title: 'V4.6.9(需要初始化)'
description: 'FastGPT V4.6.9更新说明'
icon: 'upgrade'
draft: false
toc: true
weight: 827
---
## 初始化脚本
从任意终端,发起 1 个 HTTP 请求。其中 {{rootkey}} 替换成环境变量里的 `rootkey`{{host}} 替换成自己域名
```bash
curl --location --request POST 'https://{{host}}/api/admin/initv469' \
--header 'rootkey: {{rootkey}}' \
--header 'Content-Type: application/json'
```
1. 重置计量表。
2. 执行脏数据清理(清理无效的文件、清理无效的图片、清理无效的知识库集合、清理无效的向量)
## 外部接口更新
1. 由于计费系统变更,[分享链接对话上报接口](/docs/development/openapi/share/#5-编写对话结果上报接口可选)需要做一些调整price字段被totalPoints字段取代。inputToken和outputToken不再提供只提供`token`字段总token数量
## V4.6.9 更新说明
1. 商业版新增 - 知识库新增“增强处理”训练模式,可生成更多类型索引。
2. 新增 - 完善了HTTP模块的变量提示。
3. 新增 - HTTP模块支持OpenAI单接口导入。
4. 新增 - 全局变量支持增加外部变量。可通过分享链接的Query或 API 的 variables 参数传入。
5. 新增 - 内容提取模块增加默认值。
6. 优化 - 问题补全。增加英文类型。同时可以设置为单独模块,方便复用。
7. 优化 - 重写了计量模式
8. 优化 - Token 过滤历史记录,保持偶数条,防止部分模型报错。
9. 优化 - 分享链接SEO可直接展示应用名和头像。
10. 修复 - 标注功能。
11. 修复 - qa生成线程计数错误。
12. 修复 - 问题分类连线类型错误

View File

@@ -0,0 +1,19 @@
---
title: 'V4.7(进行中)'
description: 'FastGPT V4.7更新说明'
icon: 'upgrade'
draft: false
toc: true
weight: 826
---
## 修改配置文件
增加一些 Boolean 值,用于决定不同功能块可以使用哪些模型:[点击查看最新的配置文件](/docs/development/configuration/)
## V4.7 更新说明
1. 新增 - 工具调用模块可以让LLM模型根据用户意图动态的选择其他模型或插件执行。
2. 新增 - 分类和内容提取支持 functionCall 模式。部分模型支持 functionCall 不支持 ToolCall也可以使用了。需要把 LLM 模型配置文件里的 `functionCall` 设置为 `true` `toolChoice`设置为 `false`。如果 `toolChoice` 为 true会走 tool 模式。
3. 优化 - 高级编排性能

View File

@@ -7,14 +7,4 @@ toc: true
weight: 1200
---
## Tokens 说明
[OpenAI 的 API 官方计费模式](https://openai.com/pricing#language-models)为:按每次 API 请求内容和返回内容 tokens 长度来定价。每个模型具有不同的计价方式,以每 1,000 个 tokens 消耗为单位定价。其中 1,000 个 tokens 约为 900 个英文,约 600 个中文(不是很准确,与上下长度有关,相同的词出现越多,词:Tokens 的比例越大)。平台的 tokens 数量计算算法与 OpenAI 一致,您可以随时通过「使用记录」来查看余额消耗明细的说明,来对比计算是否一致。
![](/imgs/fastgpt-price.png)
## FastGPT 线上计费
[https://fastgpt.in](https://fastgpt.in) 采用按量计费的模式,最新计费标准可在 `账号-计费标准` 查看。同时可以在 `账号-使用记录` 中查看具体使用情况,
![](/imgs/cloud_price1.jpg)
线上版价格请查看https://cloud.fastgpt.in/price

View File

@@ -66,7 +66,7 @@ Body:
Headers:
`Authorization: sk-xxx`
`Authorization: Bearer sk-xxx`
Response:

View File

@@ -135,7 +135,7 @@ export default async function (ctx: FunctionContext) {
},
{
"key": "model",
"type": "selectExtractModel",
"type": "selectLLMModel",
"valueType": "string",
"label": "core.module.input.label.LLM",
"required": true,
@@ -264,7 +264,7 @@ export default async function (ctx: FunctionContext) {
},
{
"key": "model",
"type": "selectChatModel",
"type": "selectLLMModel",
"label": "core.module.input.label.aiModel",
"required": true,
"valueType": "string",
@@ -635,7 +635,7 @@ export default async function (ctx: FunctionContext) {
},
{
"key": "model",
"type": "selectChatModel",
"type": "selectLLMModel",
"label": "core.module.input.label.aiModel",
"required": true,
"valueType": "string",

View File

@@ -139,7 +139,7 @@ HTTP 模块允许你调用任意 GET/POST 类型的 HTTP 接口,从而实现
},
{
"key": "model",
"type": "selectExtractModel",
"type": "selectLLMModel",
"valueType": "string",
"label": "core.module.input.label.LLM",
"required": true,
@@ -401,7 +401,7 @@ HTTP 模块允许你调用任意 GET/POST 类型的 HTTP 接口,从而实现
},
{
"key": "model",
"type": "selectCQModel",
"type": "selectLLMModel",
"valueType": "string",
"label": "core.module.input.label.Classify model",
"required": true,
@@ -614,7 +614,7 @@ HTTP 模块允许你调用任意 GET/POST 类型的 HTTP 接口,从而实现
},
{
"key": "model",
"type": "selectChatModel",
"type": "selectLLMModel",
"label": "core.module.input.label.aiModel",
"required": true,
"valueType": "string",
@@ -835,7 +835,7 @@ HTTP 模块允许你调用任意 GET/POST 类型的 HTTP 接口,从而实现
},
{
"key": "model",
"type": "selectExtractModel",
"type": "selectLLMModel",
"valueType": "string",
"label": "core.module.input.label.LLM",
"required": true,

View File

@@ -1,6 +1,6 @@
---
title: "问题补全(已合并到知识库搜索)"
description: "问题补全模块介绍和使用"
title: "问题优化(已合并到知识库搜索)"
description: "问题优化模块介绍和使用"
icon: "input"
draft: false
toc: true
@@ -23,7 +23,7 @@ weight: 364
![](/imgs/coreferenceResolution2.jpg)
用户在提问“第二点是什么”的时候只会去知识库里查找“第二点是什么”压根查不到内容。实际上需要查询的是“QA结构是什么”。因此我们需要引入一个【问题补全】模块,来对用户当前的问题进行补全,从而使得知识库搜索能够搜索到合适的内容。使用补全后效果如下:
用户在提问“第二点是什么”的时候只会去知识库里查找“第二点是什么”压根查不到内容。实际上需要查询的是“QA结构是什么”。因此我们需要引入一个【问题优化】模块,来对用户当前的问题进行补全,从而使得知识库搜索能够搜索到合适的内容。使用补全后效果如下:
![](/imgs/coreferenceResolution3.jpg)

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1012 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -19,21 +19,27 @@ services:
volumes:
- ./pg/data:/var/lib/postgresql/data
mongo:
image: mongo:5.0.18
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/mongo:5.0.18 # 阿里云
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/mongo:5.0.18
container_name: mongo
restart: always
ports:
- 27017:27017
networks:
- fastgpt
command: mongod --keyFile /data/mongodb.key --replSet rs0
environment:
# 默认的用户名和密码,只有首次允许有效
- MONGO_INITDB_ROOT_USERNAME=myname
- MONGO_INITDB_ROOT_USERNAME=myusername
- MONGO_INITDB_ROOT_PASSWORD=mypassword
volumes:
- ./mongo/data:/data/db
- ./mongodb.key:/data/mongodb.key
entrypoint:
- bash
- -c
- |
openssl rand -base64 128 > /data/mongodb.key
chmod 400 /data/mongodb.key
chown 999:999 /data/mongodb.key
exec docker-entrypoint.sh $$@
fastgpt:
container_name: fastgpt
image: ghcr.io/labring/fastgpt:latest # git
@@ -56,8 +62,8 @@ services:
- TOKEN_KEY=any
- ROOT_KEY=root_key
- FILE_TOKEN_KEY=filetoken
# mongo 配置,不需要改. 用户名myname,密码mypassword。
- MONGODB_URI=mongodb://myname:mypassword@mongo:27017/fastgpt?authSource=admin
# mongo 配置,不需要改. 用户名myusername,密码mypassword。
- MONGODB_URI=mongodb://myusername:mypassword@mongo:27017/fastgpt?authSource=admin
# pg配置. 不需要改
- PG_URL=postgresql://username:password@pg:5432/postgres
volumes:

View File

@@ -6,7 +6,7 @@
"prepare": "husky install",
"format-code": "prettier --config \"./.prettierrc.js\" --write \"./**/src/**/*.{ts,tsx,scss}\"",
"format-doc": "zhlint --dir ./docSite *.md --fix",
"gen:theme-typings": "chakra-cli tokens projects/app/src/web/styles/theme.ts --out node_modules/.pnpm/node_modules/@chakra-ui/styled-system/dist/theming.types.d.ts",
"gen:theme-typings": "chakra-cli tokens packages/web/styles/theme.ts --out node_modules/.pnpm/node_modules/@chakra-ui/styled-system/dist/theming.types.d.ts",
"postinstall": "sh ./scripts/postinstall.sh",
"initIcon": "node ./scripts/icon/init.js",
"previewIcon": "node ./scripts/icon/index.js"
@@ -14,11 +14,11 @@
"devDependencies": {
"@chakra-ui/cli": "^2.4.1",
"husky": "^8.0.3",
"i18next": "^22.5.1",
"i18next": "23.10.0",
"lint-staged": "^13.2.1",
"next-i18next": "^13.3.0",
"next-i18next": "15.2.0",
"prettier": "3.2.4",
"react-i18next": "^12.3.1",
"react-i18next": "13.5.0",
"zhlint": "^0.7.1"
},
"lint-staged": {

View File

@@ -3,11 +3,25 @@ import { ErrType } from '../errorCode';
/* team: 500000 */
export enum TeamErrEnum {
teamOverSize = 'teamOverSize',
unAuthTeam = 'unAuthTeam'
unAuthTeam = 'unAuthTeam',
aiPointsNotEnough = 'aiPointsNotEnough',
datasetSizeNotEnough = 'datasetSizeNotEnough',
datasetAmountNotEnough = 'datasetAmountNotEnough',
appAmountNotEnough = 'appAmountNotEnough',
pluginAmountNotEnough = 'pluginAmountNotEnough',
websiteSyncNotEnough = 'websiteSyncNotEnough',
reRankNotEnough = 'reRankNotEnough'
}
const teamErr = [
{ statusText: TeamErrEnum.teamOverSize, message: 'error.team.overSize' },
{ statusText: TeamErrEnum.unAuthTeam, message: '无权操作该团队' }
{ statusText: TeamErrEnum.unAuthTeam, message: '无权操作该团队' },
{ statusText: TeamErrEnum.aiPointsNotEnough, message: 'AI积分已用完~' },
{ statusText: TeamErrEnum.datasetSizeNotEnough, message: '知识库容量不足,请先扩容~' },
{ statusText: TeamErrEnum.datasetAmountNotEnough, message: '知识库数量已达上限~' },
{ statusText: TeamErrEnum.appAmountNotEnough, message: '应用数量已达上限~' },
{ statusText: TeamErrEnum.pluginAmountNotEnough, message: '插件数量已达上限~' },
{ statusText: TeamErrEnum.websiteSyncNotEnough, message: '无权使用Web站点同步~' },
{ statusText: TeamErrEnum.reRankNotEnough, message: '无权使用检索重排~' }
];
export default teamErr.reduce((acc, cur, index) => {
return {

View File

@@ -1,7 +1,7 @@
import { replaceSensitiveLink } from '../string/tools';
import { replaceSensitiveText } from '../string/tools';
export const getErrText = (err: any, def = '') => {
const msg: string = typeof err === 'string' ? err : err?.message || def || '';
msg && console.log('error =>', msg);
return replaceSensitiveLink(msg);
return replaceSensitiveText(msg);
};

View File

@@ -1,11 +1,11 @@
import { MongoImageTypeEnum } from './image/constants';
import { OutLinkChatAuthProps } from '../../support/permission/chat.d';
export type preUploadImgProps = {
export type preUploadImgProps = OutLinkChatAuthProps & {
type: `${MongoImageTypeEnum}`;
expiredTime?: Date;
metadata?: Record<string, any>;
shareId?: string;
};
export type UploadImgProps = preUploadImgProps & {
base64Img: string;

View File

@@ -0,0 +1,4 @@
export const formatNumber = (num: number, digit = 1e4) => Math.round(num * digit) / digit;
export const formatNumber2Million = (num: number) => Math.round(num / 1000000);
export const formatNumber2Thousand = (num: number) => Math.round(num / 1000);

View File

@@ -1,9 +1,15 @@
/* Only the token of gpt-3.5-turbo is used */
import type { ChatItemType } from '../../../core/chat/type';
import { Tiktoken } from 'js-tiktoken/lite';
import { adaptChat2GptMessages } from '../../../core/chat/adapt';
import { ChatCompletionRequestMessageRoleEnum } from '../../../core/ai/constant';
import { chats2GPTMessages } from '../../../core/chat/adapt';
import encodingJson from './cl100k_base.json';
import {
ChatCompletionMessageParam,
ChatCompletionContentPart,
ChatCompletionCreateParams,
ChatCompletionTool
} from '../../../core/ai/type';
import { ChatCompletionRequestMessageRoleEnum } from '../../../core/ai/constants';
/* init tikToken obj */
export function getTikTokenEnc() {
@@ -28,33 +34,94 @@ export function getTikTokenEnc() {
/* count one prompt tokens */
export function countPromptTokens(
prompt = '',
prompt: string | ChatCompletionContentPart[] | null | undefined = '',
role: '' | `${ChatCompletionRequestMessageRoleEnum}` = ''
) {
const enc = getTikTokenEnc();
const text = `${role}\n${prompt}`;
const promptText = (() => {
if (!prompt) return '';
if (typeof prompt === 'string') return prompt;
let promptText = '';
prompt.forEach((item) => {
if (item.type === 'text') {
promptText += item.text;
} else if (item.type === 'image_url') {
promptText += item.image_url.url;
}
});
return promptText;
})();
const text = `${role}\n${promptText}`.trim();
try {
const encodeText = enc.encode(text);
return encodeText.length + role.length; // 补充 role 估算值
const supplementaryToken = role ? 4 : 0;
return encodeText.length + supplementaryToken;
} catch (error) {
return text.length;
}
}
export const countToolsTokens = (
tools?: ChatCompletionTool[] | ChatCompletionCreateParams.Function[]
) => {
if (!tools || tools.length === 0) return 0;
const enc = getTikTokenEnc();
const toolText = tools
? JSON.stringify(tools)
.replace('"', '')
.replace('\n', '')
.replace(/( ){2,}/g, ' ')
: '';
return enc.encode(toolText).length;
};
/* count messages tokens */
export function countMessagesTokens({ messages }: { messages: ChatItemType[] }) {
const adaptMessages = adaptChat2GptMessages({ messages, reserveId: true });
export const countMessagesTokens = (messages: ChatItemType[]) => {
const adaptMessages = chats2GPTMessages({ messages, reserveId: true });
let totalTokens = 0;
for (let i = 0; i < adaptMessages.length; i++) {
const item = adaptMessages[i];
const tokens = countPromptTokens(item.content, item.role);
totalTokens += tokens;
}
return countGptMessagesTokens(adaptMessages);
};
export const countGptMessagesTokens = (
messages: ChatCompletionMessageParam[],
tools?: ChatCompletionTool[],
functionCall?: ChatCompletionCreateParams.Function[]
) =>
messages.reduce((sum, item) => {
// Evaluates the text of toolcall and functioncall
const functionCallPrompt = (() => {
let prompt = '';
if (item.role === ChatCompletionRequestMessageRoleEnum.Assistant) {
const toolCalls = item.tool_calls;
prompt +=
toolCalls
?.map((item) => `${item?.function?.name} ${item?.function?.arguments}`.trim())
?.join('') || '';
return totalTokens;
}
const functionCall = item.function_call;
prompt += `${functionCall?.name} ${functionCall?.arguments}`.trim();
}
return prompt;
})();
const contentPrompt = (() => {
if (!item.content) return '';
if (typeof item.content === 'string') return item.content;
return item.content
.map((item) => {
if (item.type === 'text') return item.text;
return '';
})
.join('');
})();
return sum + countPromptTokens(`${contentPrompt}${functionCallPrompt}`, item.role);
}, 0) +
countToolsTokens(tools) +
countToolsTokens(functionCall);
/* slice messages from top to bottom by maxTokens */
export function sliceMessagesTB({
@@ -64,7 +131,7 @@ export function sliceMessagesTB({
messages: ChatItemType[];
maxTokens: number;
}) {
const adaptMessages = adaptChat2GptMessages({ messages, reserveId: true });
const adaptMessages = chats2GPTMessages({ messages, reserveId: true });
let reduceTokens = maxTokens;
let result: ChatItemType[] = [];

View File

@@ -2,3 +2,4 @@ import dayjs from 'dayjs';
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

@@ -38,10 +38,14 @@ export function replaceVariable(text: string, obj: Record<string, string | numbe
return text || '';
}
/* replace sensitive link */
export const replaceSensitiveLink = (text: string) => {
const urlRegex = /(?<=https?:\/\/)[^\s]+/g;
return text.replace(urlRegex, 'xxx');
/* replace sensitive text */
export const replaceSensitiveText = (text: string) => {
// 1. http link
text = text.replace(/(?<=https?:\/\/)[^\s]+/g, 'xxx');
// 2. nx-xxx 全部替换成xxx
text = text.replace(/ns-[\w-]+/g, 'xxx');
return text;
};
export const getNanoid = (size = 12) => {

View File

@@ -30,6 +30,7 @@ export type FastGPTFeConfigsType = {
show_pay?: boolean;
show_openai_account?: boolean;
show_promotion?: boolean;
show_team_chat?: boolean;
hide_app_flow?: boolean;
concatMd?: string;
docUrl?: string;
@@ -38,9 +39,12 @@ export type FastGPTFeConfigsType = {
systemTitle?: string;
googleClientVerKey?: string;
isPlus?: boolean;
show_phoneLogin?: boolean;
show_emailLogin?: boolean;
oauth?: {
github?: string;
google?: string;
wechat?: string;
};
limit?: {
exportDatasetLimitMinutes?: number;
@@ -59,6 +63,8 @@ export type SystemEnvType = {
vectorMaxProcess: number;
qaMaxProcess: number;
pgHNSWEfSearch: number;
oneapiUrl?: string;
chatApiKey?: string;
};
// declare global {

View File

@@ -1,7 +0,0 @@
export enum ChatCompletionRequestMessageRoleEnum {
'System' = 'system',
'User' = 'user',
'Assistant' = 'assistant',
'Function' = 'function',
'Tool' = 'tool'
}

View File

@@ -0,0 +1,27 @@
export enum ChatCompletionRequestMessageRoleEnum {
'System' = 'system',
'User' = 'user',
'Assistant' = 'assistant',
'Function' = 'function',
'Tool' = 'tool'
}
export enum ChatMessageTypeEnum {
text = 'text',
image_url = 'image_url'
}
export enum LLMModelTypeEnum {
all = 'all',
classify = 'classify',
extractFields = 'extractFields',
toolCall = 'toolCall',
queryExtension = 'queryExtension'
}
export const llmModelTypeFilterMap = {
[LLMModelTypeEnum.all]: 'model',
[LLMModelTypeEnum.classify]: 'usedInClassify',
[LLMModelTypeEnum.extractFields]: 'usedInExtractFields',
[LLMModelTypeEnum.toolCall]: 'usedInToolCall',
[LLMModelTypeEnum.queryExtension]: 'usedInQueryExtension'
};

View File

@@ -6,12 +6,17 @@ export type LLMModelItemType = {
quoteMaxToken: number;
maxTemperature: number;
inputPrice: number;
outputPrice: number;
charsPointsPrice: number; // 1k chars=n points
censor?: boolean;
vision?: boolean;
datasetProcess?: boolean;
// diff function model
datasetProcess?: boolean; // dataset
usedInClassify?: boolean; // classify
usedInExtractFields?: boolean; // extract fields
usedInToolCall?: boolean; // tool call
usedInQueryExtension?: boolean; // query extension
functionCall: boolean;
toolChoice: boolean;
@@ -27,8 +32,7 @@ export type VectorModelItemType = {
model: string;
name: string;
defaultToken: number;
inputPrice: number;
outputPrice: number;
charsPointsPrice: number;
maxToken: number;
weight: number;
hidden?: boolean;
@@ -38,8 +42,7 @@ export type VectorModelItemType = {
export type ReRankModelItemType = {
model: string;
name: string;
inputPrice: number;
outputPrice?: number;
charsPointsPrice: number;
requestUrl?: string;
requestAuth?: string;
};
@@ -47,14 +50,12 @@ export type ReRankModelItemType = {
export type AudioSpeechModelType = {
model: string;
name: string;
inputPrice: number;
outputPrice?: number;
charsPointsPrice: number;
voices: { label: string; value: string; bufferId: string }[];
};
export type WhisperModelType = {
model: string;
name: string;
inputPrice: number;
outputPrice?: number;
charsPointsPrice: number; // 60s = n points
};

View File

@@ -2,14 +2,13 @@ import type { LLMModelItemType, VectorModelItemType } from './model.d';
export const defaultQAModels: LLMModelItemType[] = [
{
model: 'gpt-3.5-turbo-16k',
name: 'gpt-3.5-turbo-16k',
model: 'gpt-3.5-turbo',
name: 'gpt-3.5-turbo',
maxContext: 16000,
maxResponse: 16000,
quoteMaxToken: 13000,
maxTemperature: 1.2,
inputPrice: 0,
outputPrice: 0,
charsPointsPrice: 0,
censor: false,
vision: false,
datasetProcess: true,
@@ -26,8 +25,7 @@ export const defaultVectorModels: VectorModelItemType[] = [
{
model: 'text-embedding-ada-002',
name: 'Embedding-2',
inputPrice: 0,
outputPrice: 0,
charsPointsPrice: 0,
defaultToken: 500,
maxToken: 3000,
weight: 100

View File

@@ -1,20 +1,33 @@
import openai from 'openai';
import type {
ChatCompletion,
ChatCompletionCreateParams,
ChatCompletionMessageToolCall,
ChatCompletionChunk,
ChatCompletionMessageParam,
ChatCompletionContentPart
ChatCompletionToolMessageParam,
ChatCompletionAssistantMessageParam
} from 'openai/resources';
import { ChatMessageTypeEnum } from './constants';
export type ChatCompletionContentPart = ChatCompletionContentPart;
export type ChatCompletionCreateParams = ChatCompletionCreateParams;
export type ChatMessageItemType = Omit<ChatCompletionMessageParam, 'name'> & {
name?: any;
export * from 'openai/resources';
export type ChatCompletionMessageParam = ChatCompletionMessageParam & {
dataId?: string;
content: any;
} & any;
};
export type ChatCompletionToolMessageParam = ChatCompletionToolMessageParam & { name: string };
export type ChatCompletionAssistantToolParam = {
role: 'assistant';
tool_calls: ChatCompletionMessageToolCall[];
};
export type ChatCompletion = ChatCompletion;
export type ChatCompletionMessageToolCall = ChatCompletionMessageToolCall & {
toolName?: string;
toolAvatar?: string;
};
export type ChatCompletionMessageFunctionCall = ChatCompletionAssistantMessageParam.FunctionCall & {
id?: string;
toolName?: string;
toolAvatar?: string;
};
export type StreamChatType = Stream<ChatCompletionChunk>;
export type PromptTemplateItem = {
@@ -22,3 +35,6 @@ export type PromptTemplateItem = {
desc: string;
value: string;
};
export default openai;
export * from 'openai';

View File

@@ -17,6 +17,7 @@ export interface AppUpdateParams {
intro?: string;
modules?: AppSchema['modules'];
permission?: AppSchema['permission'];
teamTags?: AppSchema['teamTags'];
}
export type FormatForm2ModulesProps = {

View File

@@ -5,7 +5,7 @@ import type { AIChatModuleProps, DatasetModuleProps } from '../module/node/type.
import { VariableInputEnum } from '../module/constants';
import { SelectedDatasetType } from '../module/api';
import { DatasetSearchModeEnum } from '../dataset/constants';
import { TeamTagSchema as TeamTagsSchemaType } from '@fastgpt/global/support/user/team/type.d';
export interface AppSchema {
_id: string;
userId: string;
@@ -20,6 +20,7 @@ export interface AppSchema {
modules: ModuleItemType[];
permission: `${PermissionTypeEnum}`;
inited?: boolean;
teamTags: string[];
}
export type AppListItemType = {

View File

@@ -1,40 +1,298 @@
import type { ChatItemType } from '../../core/chat/type.d';
import { ChatRoleEnum } from '../../core/chat/constants';
import { ChatCompletionRequestMessageRoleEnum } from '../../core/ai/constant';
import type { ChatMessageItemType } from '../../core/ai/type.d';
import type {
ChatItemType,
ChatItemValueItemType,
RuntimeUserPromptType,
UserChatItemType
} from '../../core/chat/type.d';
import { ChatFileTypeEnum, ChatItemValueTypeEnum, ChatRoleEnum } from '../../core/chat/constants';
import type {
ChatCompletionContentPart,
ChatCompletionFunctionMessageParam,
ChatCompletionMessageFunctionCall,
ChatCompletionMessageParam,
ChatCompletionMessageToolCall,
ChatCompletionToolMessageParam
} from '../../core/ai/type.d';
import { ChatCompletionRequestMessageRoleEnum } from '../../core/ai/constants';
const chat2Message = {
[ChatRoleEnum.AI]: ChatCompletionRequestMessageRoleEnum.Assistant,
[ChatRoleEnum.Human]: ChatCompletionRequestMessageRoleEnum.User,
[ChatRoleEnum.System]: ChatCompletionRequestMessageRoleEnum.System,
[ChatRoleEnum.Function]: ChatCompletionRequestMessageRoleEnum.Function,
[ChatRoleEnum.Tool]: ChatCompletionRequestMessageRoleEnum.Tool
};
const message2Chat = {
const GPT2Chat = {
[ChatCompletionRequestMessageRoleEnum.System]: ChatRoleEnum.System,
[ChatCompletionRequestMessageRoleEnum.User]: ChatRoleEnum.Human,
[ChatCompletionRequestMessageRoleEnum.Assistant]: ChatRoleEnum.AI,
[ChatCompletionRequestMessageRoleEnum.Function]: ChatRoleEnum.Function,
[ChatCompletionRequestMessageRoleEnum.Tool]: ChatRoleEnum.Tool
[ChatCompletionRequestMessageRoleEnum.Function]: ChatRoleEnum.AI,
[ChatCompletionRequestMessageRoleEnum.Tool]: ChatRoleEnum.AI
};
export function adaptRole_Chat2Message(role: `${ChatRoleEnum}`) {
return chat2Message[role];
}
export function adaptRole_Message2Chat(role: `${ChatCompletionRequestMessageRoleEnum}`) {
return message2Chat[role];
return GPT2Chat[role];
}
export const adaptChat2GptMessages = ({
export const simpleUserContentPart = (content: ChatCompletionContentPart[]) => {
if (content.length === 1 && content[0].type === 'text') {
return content[0].text;
}
return content;
};
export const chats2GPTMessages = ({
messages,
reserveId
reserveId,
reserveTool = false
}: {
messages: ChatItemType[];
reserveId: boolean;
}): ChatMessageItemType[] => {
return messages.map((item) => ({
...(reserveId && { dataId: item.dataId }),
role: chat2Message[item.obj],
content: item.value || ''
}));
reserveTool?: boolean;
}): ChatCompletionMessageParam[] => {
let results: ChatCompletionMessageParam[] = [];
messages.forEach((item) => {
const dataId = reserveId ? item.dataId : undefined;
if (item.obj === ChatRoleEnum.Human) {
const value = item.value
.map((item) => {
if (item.type === ChatItemValueTypeEnum.text) {
return {
type: 'text',
text: item.text?.content || ''
};
}
if (item.type === 'file' && item.file?.type === ChatFileTypeEnum.image) {
return {
type: 'image_url',
image_url: {
url: item.file?.url || ''
}
};
}
return;
})
.filter(Boolean) as ChatCompletionContentPart[];
results.push({
dataId,
role: ChatCompletionRequestMessageRoleEnum.User,
content: simpleUserContentPart(value)
});
} else if (item.obj === ChatRoleEnum.System) {
const content = item.value?.[0]?.text?.content;
if (content) {
results.push({
dataId,
role: ChatCompletionRequestMessageRoleEnum.System,
content
});
}
} else {
item.value.forEach((value) => {
if (value.type === ChatItemValueTypeEnum.tool && value.tools && reserveTool) {
const tool_calls: ChatCompletionMessageToolCall[] = [];
const toolResponse: ChatCompletionToolMessageParam[] = [];
value.tools.forEach((tool) => {
tool_calls.push({
id: tool.id,
type: 'function',
function: {
name: tool.functionName,
arguments: tool.params
}
});
toolResponse.push({
tool_call_id: tool.id,
role: ChatCompletionRequestMessageRoleEnum.Tool,
name: tool.functionName,
content: tool.response
});
});
results = results
.concat({
dataId,
role: ChatCompletionRequestMessageRoleEnum.Assistant,
tool_calls
})
.concat(toolResponse);
} else if (value.text) {
results.push({
dataId,
role: ChatCompletionRequestMessageRoleEnum.Assistant,
content: value.text.content
});
}
});
}
});
return results;
};
export const GPTMessages2Chats = (
messages: ChatCompletionMessageParam[],
reserveTool = true
): ChatItemType[] => {
return messages
.map((item) => {
const value: ChatItemType['value'] = [];
const obj = GPT2Chat[item.role];
if (
obj === ChatRoleEnum.System &&
item.role === ChatCompletionRequestMessageRoleEnum.System
) {
value.push({
type: ChatItemValueTypeEnum.text,
text: {
content: item.content
}
});
} else if (
obj === ChatRoleEnum.Human &&
item.role === ChatCompletionRequestMessageRoleEnum.User
) {
if (typeof item.content === 'string') {
value.push({
type: ChatItemValueTypeEnum.text,
text: {
content: item.content
}
});
} else if (Array.isArray(item.content)) {
item.content.forEach((item) => {
if (item.type === 'text') {
value.push({
type: ChatItemValueTypeEnum.text,
text: {
content: item.text
}
});
} else if (item.type === 'image_url') {
value.push({
//@ts-ignore
type: 'file',
file: {
type: ChatFileTypeEnum.image,
name: '',
url: item.image_url.url
}
});
}
});
// @ts-ignore
}
} else if (
obj === ChatRoleEnum.AI &&
item.role === ChatCompletionRequestMessageRoleEnum.Assistant
) {
if (item.content && typeof item.content === 'string') {
value.push({
type: ChatItemValueTypeEnum.text,
text: {
content: item.content
}
});
} else if (item.tool_calls && reserveTool) {
// save tool calls
const toolCalls = item.tool_calls as ChatCompletionMessageToolCall[];
value.push({
//@ts-ignore
type: ChatItemValueTypeEnum.tool,
tools: toolCalls.map((tool) => {
let toolResponse =
messages.find(
(msg) =>
msg.role === ChatCompletionRequestMessageRoleEnum.Tool &&
msg.tool_call_id === tool.id
)?.content || '';
toolResponse =
typeof toolResponse === 'string' ? toolResponse : JSON.stringify(toolResponse);
return {
id: tool.id,
toolName: tool.toolName || '',
toolAvatar: tool.toolAvatar || '',
functionName: tool.function.name,
params: tool.function.arguments,
response: toolResponse as string
};
})
});
} else if (item.function_call && reserveTool) {
const functionCall = item.function_call as ChatCompletionMessageFunctionCall;
const functionResponse = messages.find(
(msg) =>
msg.role === ChatCompletionRequestMessageRoleEnum.Function &&
msg.name === item.function_call?.name
) as ChatCompletionFunctionMessageParam;
if (functionResponse) {
value.push({
//@ts-ignore
type: ChatItemValueTypeEnum.tool,
tools: [
{
id: functionCall.id || '',
toolName: functionCall.toolName || '',
toolAvatar: functionCall.toolAvatar || '',
functionName: functionCall.name,
params: functionCall.arguments,
response: functionResponse.content || ''
}
]
});
}
}
}
return {
dataId: item.dataId,
obj,
value
} as ChatItemType;
})
.filter((item) => item.value.length > 0);
};
export const chatValue2RuntimePrompt = (value: ChatItemValueItemType[]): RuntimeUserPromptType => {
const prompt: RuntimeUserPromptType = {
files: [],
text: ''
};
value.forEach((item) => {
if (item.type === 'file' && item.file) {
prompt.files?.push(item.file);
} else if (item.text) {
prompt.text += item.text.content;
}
});
return prompt;
};
export const runtimePrompt2ChatsValue = (
prompt: RuntimeUserPromptType
): UserChatItemType['value'] => {
const value: UserChatItemType['value'] = [];
if (prompt.files) {
prompt.files.forEach((file) => {
value.push({
type: ChatItemValueTypeEnum.file,
file
});
});
}
if (prompt.text) {
value.push({
type: ChatItemValueTypeEnum.text,
text: {
content: prompt.text
}
});
}
return value;
};
export const getSystemPrompt = (prompt?: string): ChatItemType[] => {
if (!prompt) return [];
return [
{
obj: ChatRoleEnum.System,
value: [{ type: ChatItemValueTypeEnum.text, text: { content: prompt } }]
}
];
};

View File

@@ -1,33 +1,36 @@
export enum ChatRoleEnum {
System = 'System',
Human = 'Human',
AI = 'AI',
Function = 'Function',
Tool = 'Tool'
AI = 'AI'
}
export const ChatRoleMap = {
[ChatRoleEnum.System]: {
name: '系统提示词'
name: '系统'
},
[ChatRoleEnum.Human]: {
name: '用户'
},
[ChatRoleEnum.AI]: {
name: 'AI'
},
[ChatRoleEnum.Function]: {
name: 'Function'
},
[ChatRoleEnum.Tool]: {
name: 'Tool'
}
};
export enum ChatFileTypeEnum {
image = 'image',
file = 'file'
}
export enum ChatItemValueTypeEnum {
text = 'text',
file = 'file',
tool = 'tool'
}
export enum ChatSourceEnum {
test = 'test',
online = 'online',
share = 'share',
api = 'api'
api = 'api',
team = 'team'
}
export const ChatSourceMap = {
[ChatSourceEnum.test]: {
@@ -41,6 +44,9 @@ export const ChatSourceMap = {
},
[ChatSourceEnum.api]: {
name: 'core.chat.logs.api'
},
[ChatSourceEnum.team]: {
name: 'core.chat.logs.team'
}
};

View File

@@ -1,10 +1,20 @@
import { ClassifyQuestionAgentItemType } from '../module/type';
import { SearchDataResponseItemType } from '../dataset/type';
import { ChatRoleEnum, ChatSourceEnum, ChatStatusEnum } from './constants';
import {
ChatFileTypeEnum,
ChatItemValueTypeEnum,
ChatRoleEnum,
ChatSourceEnum,
ChatStatusEnum
} from './constants';
import { FlowNodeTypeEnum } from '../module/node/constant';
import { ModuleOutputKeyEnum } from '../module/constants';
import { DispatchNodeResponseKeyEnum } from '../module/runtime/constants';
import { AppSchema } 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 '../module/runtime/type.d';
export type ChatSchema = {
_id: string;
@@ -29,7 +39,53 @@ export type ChatWithAppSchema = Omit<ChatSchema, 'appId'> & {
appId: AppSchema;
};
export type ChatItemSchema = {
export type UserChatItemValueItemType = {
type: ChatItemValueTypeEnum.text | ChatItemValueTypeEnum.file;
text?: {
content: string;
};
file?: {
type: `${ChatFileTypeEnum}`;
name?: string;
url: string;
};
};
export type UserChatItemType = {
obj: ChatRoleEnum.Human;
value: UserChatItemValueItemType[];
};
export type SystemChatItemValueItemType = {
type: ChatItemValueTypeEnum.text;
text?: {
content: string;
};
};
export type SystemChatItemType = {
obj: ChatRoleEnum.System;
value: SystemChatItemValueItemType[];
};
export type AIChatItemValueItemType = {
type: ChatItemValueTypeEnum.text | ChatItemValueTypeEnum.tool;
text?: {
content: string;
};
tools?: ToolModuleResponseItemType[];
};
export type AIChatItemType = {
obj: ChatRoleEnum.AI;
value: AIChatItemValueItemType[];
userGoodFeedback?: string;
userBadFeedback?: string;
customFeedbacks?: string[];
adminFeedback?: AdminFbkType;
[DispatchNodeResponseKeyEnum.nodeResponse]?: ChatHistoryItemResType[];
};
export type ChatItemValueItemType =
| UserChatItemValueItemType
| SystemChatItemValueItemType
| AIChatItemValueItemType;
export type ChatItemSchema = (UserChatItemType | SystemChatItemType | AIChatItemType) & {
dataId: string;
chatId: string;
userId: string;
@@ -37,13 +93,6 @@ export type ChatItemSchema = {
tmbId: string;
appId: string;
time: Date;
obj: `${ChatRoleEnum}`;
value: string;
userGoodFeedback?: string;
userBadFeedback?: string;
customFeedbacks?: string[];
adminFeedback?: AdminFbkType;
[ModuleOutputKeyEnum.responseData]?: ChatHistoryItemResType[];
};
export type AdminFbkType = {
@@ -55,21 +104,22 @@ export type AdminFbkType = {
};
/* --------- chat item ---------- */
export type ChatItemType = {
export type ChatItemType = (UserChatItemType | SystemChatItemType | AIChatItemType) & {
dataId?: string;
obj: ChatItemSchema['obj'];
value: any;
userGoodFeedback?: string;
userBadFeedback?: string;
customFeedbacks?: ChatItemSchema['customFeedbacks'];
adminFeedback?: ChatItemSchema['feedback'];
[ModuleOutputKeyEnum.responseData]?: ChatHistoryItemResType[];
};
export type ChatSiteItemType = ChatItemType & {
export type ChatSiteItemType = (UserChatItemType | SystemChatItemType | AIChatItemType) & {
dataId?: string;
status: `${ChatStatusEnum}`;
moduleName?: string;
ttsBuffer?: Uint8Array;
} & ChatBoxInputType;
/* --------- team chat --------- */
export type ChatAppListSchema = {
apps: AppType[];
teamInfo: teamInfoSchema;
uid?: string;
};
/* ---------- history ------------- */
@@ -85,59 +135,25 @@ export type ChatHistoryItemType = HistoryItemType & {
};
/* ------- response data ------------ */
export type moduleDispatchResType = {
// common
moduleLogo?: string;
price?: number;
runningTime?: number;
inputTokens?: number;
outputTokens?: number;
charsLength?: number;
model?: string;
query?: string;
contextTotalLen?: number;
textOutput?: string;
// chat
temperature?: number;
maxToken?: number;
quoteList?: SearchDataResponseItemType[];
historyPreview?: ChatItemType[]; // completion context array. history will slice
// dataset search
similarity?: number;
limit?: number;
searchMode?: `${DatasetSearchModeEnum}`;
searchUsingReRank?: boolean;
extensionModel?: string;
extensionResult?: string;
// cq
cqList?: ClassifyQuestionAgentItemType[];
cqResult?: string;
// content extract
extractDescription?: string;
extractResult?: Record<string, any>;
// http
params?: Record<string, any>;
body?: Record<string, any>;
headers?: Record<string, any>;
httpResult?: Record<string, any>;
// plugin output
pluginOutput?: Record<string, any>;
pluginDetail?: ChatHistoryItemResType[];
// tf switch
tfSwitchResult?: boolean;
// abandon
tokens?: number;
};
export type ChatHistoryItemResType = moduleDispatchResType & {
export type ChatHistoryItemResType = DispatchNodeResponseType & {
moduleType: `${FlowNodeTypeEnum}`;
moduleName: string;
};
/* One tool run response */
export type ToolRunResponseItemType = Record<string, any> | Array;
/* tool module response */
export type ToolModuleResponseItemType = {
id: string;
toolName: string; // tool name
toolAvatar: string;
params: string; // tool params
response: string;
functionName: string;
};
/* dispatch run time */
export type RuntimeUserPromptType = {
files?: UserChatItemValueItemType['file'][];
text: string;
};

View File

@@ -1,6 +1,79 @@
import { IMG_BLOCK_KEY, FILE_BLOCK_KEY } from './constants';
import { DispatchNodeResponseType } from '../module/runtime/type';
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '../module/node/constant';
import { ChatItemValueTypeEnum, ChatRoleEnum } from './constants';
import { ChatHistoryItemResType, ChatItemType } from './type.d';
export function chatContentReplaceBlock(content: string = '') {
const regex = new RegExp(`\`\`\`(${IMG_BLOCK_KEY})\\n([\\s\\S]*?)\`\`\``, 'g');
return content.replace(regex, '').trim();
}
export const getChatTitleFromChatMessage = (message?: ChatItemType, defaultValue = '新对话') => {
// @ts-ignore
const textMsg = message?.value.find((item) => item.type === ChatItemValueTypeEnum.text);
if (textMsg?.text?.content) {
return textMsg.text.content.slice(0, 20);
}
return defaultValue;
};
export const getHistoryPreview = (
completeMessages: ChatItemType[]
): {
obj: `${ChatRoleEnum}`;
value: string;
}[] => {
return completeMessages.map((item, i) => {
if (item.obj === ChatRoleEnum.System || i >= completeMessages.length - 2) {
return {
obj: item.obj,
value: item.value?.[0]?.text?.content || ''
};
}
const content = item.value
.map((item) => {
if (item.text?.content) {
const content =
item.text.content.length > 20
? `${item.text.content.slice(0, 20)}...`
: item.text.content;
return content;
}
return '';
})
.filter(Boolean)
.join('\n');
return {
obj: item.obj,
value: content
};
});
};
export const filterPublicNodeResponseData = ({
flowResponses = []
}: {
flowResponses?: ChatHistoryItemResType[];
}) => {
const filedList = ['quoteList', 'moduleType'];
const filterModuleTypeList: any[] = [
FlowNodeTypeEnum.pluginModule,
FlowNodeTypeEnum.datasetSearchNode,
FlowNodeTypeEnum.tools
];
return flowResponses
.filter((item) => filterModuleTypeList.includes(item.moduleType))
.map((item) => {
const obj: DispatchNodeResponseType = {};
for (let key in item) {
if (key === 'toolDetail' || key === 'pluginDetail') {
// @ts-ignore
obj[key] = filterPublicNodeResponseData({ flowResponses: item[key] });
} else if (filedList.includes(key)) {
// @ts-ignore
obj[key] = item[key];
}
}
return obj as ChatHistoryItemResType;
});
};

View File

@@ -71,45 +71,29 @@ export const DatasetCollectionSyncResultMap = {
};
/* ------------ data -------------- */
export enum DatasetDataIndexTypeEnum {
chunk = 'chunk',
qa = 'qa',
summary = 'summary',
hypothetical = 'hypothetical',
custom = 'custom'
}
export const DatasetDataIndexTypeMap = {
[DatasetDataIndexTypeEnum.chunk]: {
name: 'dataset.data.indexes.chunk'
},
[DatasetDataIndexTypeEnum.summary]: {
name: 'dataset.data.indexes.summary'
},
[DatasetDataIndexTypeEnum.hypothetical]: {
name: 'dataset.data.indexes.hypothetical'
},
[DatasetDataIndexTypeEnum.qa]: {
name: 'dataset.data.indexes.qa'
},
[DatasetDataIndexTypeEnum.custom]: {
name: 'dataset.data.indexes.custom'
}
};
/* ------------ training -------------- */
export enum TrainingModeEnum {
chunk = 'chunk',
auto = 'auto',
qa = 'qa'
}
export const TrainingTypeMap = {
[TrainingModeEnum.chunk]: {
label: 'core.dataset.training.Chunk mode',
tooltip: 'core.dataset.import.Chunk Split Tip'
tooltip: 'core.dataset.import.Chunk Split Tip',
openSource: true
},
[TrainingModeEnum.auto]: {
label: 'core.dataset.training.Auto mode',
tooltip: 'core.dataset.training.Auto mode Tip',
openSource: false
},
[TrainingModeEnum.qa]: {
label: 'core.dataset.training.QA mode',
tooltip: 'core.dataset.import.QA Import Tip'
tooltip: 'core.dataset.import.QA Import Tip',
openSource: true
}
};

View File

@@ -3,7 +3,6 @@ import { PermissionTypeEnum } from '../../support/permission/constant';
import { PushDatasetDataChunkProps } from './api';
import {
DatasetCollectionTypeEnum,
DatasetDataIndexTypeEnum,
DatasetStatusEnum,
DatasetTypeEnum,
SearchScoreTypeEnum,
@@ -64,7 +63,6 @@ export type DatasetCollectionSchemaType = {
export type DatasetDataIndexItemType = {
defaultIndex: boolean;
dataId: string; // pg data id
type: `${DatasetDataIndexTypeEnum}`;
text: string;
};
export type DatasetDataSchemaType = {
@@ -142,6 +140,7 @@ export type DatasetCollectionItemType = CollectionWithDatasetType & {
/* ================= data ===================== */
export type DatasetDataItemType = {
id: string;
teamId: string;
datasetId: string;
collectionId: string;
sourceName: string;
@@ -173,7 +172,7 @@ export type DatasetFileSchema = {
/* ============= search =============== */
export type SearchDataResponseItemType = Omit<
DatasetDataItemType,
'indexes' | 'isOwner' | 'canWrite'
'teamId' | 'indexes' | 'isOwner' | 'canWrite'
> & {
score: { type: `${SearchScoreTypeEnum}`; value: number; index: number }[];
// score: number;

View File

@@ -1,4 +1,4 @@
import { TrainingModeEnum, DatasetCollectionTypeEnum, DatasetDataIndexTypeEnum } from './constants';
import { TrainingModeEnum, DatasetCollectionTypeEnum } from './constants';
import { getFileIcon } from '../../common/file/icon';
import { strIsLink } from '../../common/string/tools';
@@ -41,7 +41,6 @@ export function getDefaultIndex(props?: { q?: string; a?: string; dataId?: strin
const qaStr = `${q}\n${a}`.trim();
return {
defaultIndex: true,
type: a ? DatasetDataIndexTypeEnum.qa : DatasetDataIndexTypeEnum.chunk,
text: a ? qaStr : q,
dataId
};
@@ -49,5 +48,6 @@ export function getDefaultIndex(props?: { q?: string; a?: string; dataId?: strin
export const predictDataLimitLength = (mode: `${TrainingModeEnum}`, data: any[]) => {
if (mode === TrainingModeEnum.qa) return data.length * 20;
if (mode === TrainingModeEnum.auto) return data.length * 5;
return data.length;
};

View File

@@ -21,7 +21,10 @@ export enum ModuleIOValueTypeEnum {
// plugin special type
selectApp = 'selectApp',
selectDataset = 'selectDataset'
selectDataset = 'selectDataset',
// tool
tools = 'tools'
}
/* reg: modulename key */
@@ -91,9 +94,8 @@ export enum ModuleOutputKeyEnum {
// common
userChatInput = 'userChatInput',
finish = 'finish',
responseData = 'responseData',
history = 'history',
answerText = 'answerText', // answer module text key
answerText = 'answerText', // module answer. the value will be show and save to history
success = 'success',
failed = 'failed',
text = 'system_text',
@@ -109,23 +111,41 @@ export enum ModuleOutputKeyEnum {
// tf switch
resultTrue = 'system_resultTrue',
resultFalse = 'system_resultFalse'
resultFalse = 'system_resultFalse',
// tools
selectedTools = 'selectedTools',
// http
httpRawResponse = 'httpRawResponse'
}
export enum VariableInputEnum {
input = 'input',
textarea = 'textarea',
select = 'select'
select = 'select',
external = 'external'
}
export const variableMap = {
[VariableInputEnum.input]: {
icon: 'core/app/variable/input'
icon: 'core/app/variable/input',
title: 'core.module.variable.input type',
desc: ''
},
[VariableInputEnum.textarea]: {
icon: 'core/app/variable/textarea'
icon: 'core/app/variable/textarea',
title: 'core.module.variable.textarea type',
desc: '允许用户最多输入4000字的对话框。'
},
[VariableInputEnum.select]: {
icon: 'core/app/variable/select'
icon: 'core/app/variable/select',
title: 'core.module.variable.select type',
desc: ''
},
[VariableInputEnum.external]: {
icon: 'core/app/variable/external',
title: 'core.module.variable.External type',
desc: '可以通过API接口或分享链接的Query传递变量。增加该类型变量的主要目的是用于变量提示。使用例子: 你可以通过分享链接Query中拼接Token来实现内部系统身份鉴权。'
}
};

View File

@@ -20,9 +20,7 @@ export enum FlowNodeInputTypeEnum {
aiSettings = 'aiSettings',
// ai model select
selectChatModel = 'selectChatModel',
selectCQModel = 'selectCQModel',
selectExtractModel = 'selectExtractModel',
selectLLMModel = 'selectLLMModel',
// dataset special input
selectDataset = 'selectDataset',
@@ -58,7 +56,8 @@ export enum FlowNodeTypeEnum {
pluginModule = 'pluginModule',
pluginInput = 'pluginInput',
pluginOutput = 'pluginOutput',
cfr = 'cfr'
queryExtension = 'cfr',
tools = 'tools'
// abandon
}

View File

@@ -2,6 +2,7 @@ import { FlowNodeInputTypeEnum, FlowNodeOutputTypeEnum, FlowNodeTypeEnum } from
import { ModuleIOValueTypeEnum, ModuleInputKeyEnum, ModuleOutputKeyEnum } from '../constants';
import { SelectedDatasetType } from '../api';
import { EditInputFieldMap, EditOutputFieldMap } from './type';
import { LLMModelTypeEnum } from '../../ai/constants';
export type FlowNodeChangeProps = {
moduleId: string;
@@ -28,6 +29,7 @@ export type FlowNodeInputItemType = {
label: string;
description?: string;
required?: boolean;
toolDescription?: string; // If this field is not empty, it is entered as a tool
edit?: boolean; // Whether to allow editing
editField?: EditInputFieldMap;
@@ -49,6 +51,8 @@ export type FlowNodeInputItemType = {
step?: number; // slider
max?: number; // slider, number input
min?: number; // slider, number input
llmModelType?: `${LLMModelTypeEnum}`;
};
export type FlowNodeOutputTargetItemType = {
@@ -62,6 +66,8 @@ export type FlowNodeOutputItemType = {
label?: string;
description?: string;
required?: boolean;
defaultValue?: any;
edit?: boolean;
editField?: EditOutputFieldMap;
@@ -74,12 +80,14 @@ export type FlowNodeOutputItemType = {
export type EditInputFieldMap = EditOutputFieldMap & {
inputType?: boolean;
required?: boolean;
isToolInput?: boolean;
};
export type EditOutputFieldMap = {
name?: boolean;
key?: boolean;
description?: boolean;
dataType?: boolean;
defaultValue?: boolean;
};
export type EditNodeFieldType = {
inputType?: `${FlowNodeInputTypeEnum}`; // input type
@@ -89,6 +97,8 @@ export type EditNodeFieldType = {
label?: string;
description?: string;
valueType?: `${ModuleIOValueTypeEnum}`;
isToolInput?: boolean;
defaultValue?: string;
};
/* ------------- item type --------------- */

View File

@@ -0,0 +1,19 @@
export enum SseResponseEventEnum {
error = 'error',
answer = 'answer', // animation stream
fastAnswer = 'fastAnswer', // direct answer text, not animation
flowNodeStatus = 'flowNodeStatus', // update node status
toolCall = 'toolCall', // tool start
toolParams = 'toolParams', // tool params return
toolResponse = 'toolResponse', // tool response return
flowResponses = 'flowResponses' // sse response request
}
export enum DispatchNodeResponseKeyEnum {
nodeResponse = 'responseData', // run node response
nodeDispatchUsages = 'nodeDispatchUsages', // the node bill.
childrenResponses = 'childrenResponses', // Some nodes make recursive calls that need to be returned
toolResponses = 'toolResponses', // The result is passed back to the tool node for use
assistantResponses = 'assistantResponses' // assistant response
}

View File

@@ -0,0 +1,101 @@
import { ChatNodeUsageType } from '../../../support/wallet/bill/type';
import { ChatItemValueItemType, ToolRunResponseItemType } from '../../chat/type';
import { FlowNodeInputItemType, FlowNodeOutputItemType } from '../node/type';
import { ModuleItemType } from '../type';
import { DispatchNodeResponseKeyEnum } from './constants';
export type RunningModuleItemType = {
name: ModuleItemType['name'];
avatar: ModuleItemType['avatar'];
intro?: ModuleItemType['intro'];
moduleId: ModuleItemType['moduleId'];
flowType: ModuleItemType['flowType'];
showStatus?: ModuleItemType['showStatus'];
isEntry?: ModuleItemType['isEntry'];
inputs: {
key: string;
value?: any;
valueType?: FlowNodeInputItemType['valueType'];
required?: boolean;
toolDescription?: string;
}[];
outputs: {
key: string;
required?: boolean;
defaultValue?: any;
answer?: boolean;
response?: boolean;
value?: any;
valueType?: FlowNodeOutputItemType['valueType'];
targets: {
moduleId: string;
key: string;
}[];
}[];
};
export type DispatchNodeResponseType = {
// common
moduleLogo?: string;
runningTime?: number;
query?: string;
textOutput?: string;
// bill
tokens?: number;
model?: string;
contextTotalLen?: number;
totalPoints?: number;
// chat
temperature?: number;
maxToken?: number;
quoteList?: SearchDataResponseItemType[];
historyPreview?: {
obj: `${ChatRoleEnum}`;
value: string;
}[]; // completion context array. history will slice
// dataset search
similarity?: number;
limit?: number;
searchMode?: `${DatasetSearchModeEnum}`;
searchUsingReRank?: boolean;
extensionModel?: string;
extensionResult?: string;
extensionTokens?: number;
// cq
cqList?: ClassifyQuestionAgentItemType[];
cqResult?: string;
// content extract
extractDescription?: string;
extractResult?: Record<string, any>;
// http
params?: Record<string, any>;
body?: Record<string, any>;
headers?: Record<string, any>;
httpResult?: Record<string, any>;
// plugin output
pluginOutput?: Record<string, any>;
pluginDetail?: ChatHistoryItemResType[];
// tf switch
tfSwitchResult?: boolean;
// tool
toolCallTokens?: number;
toolDetail?: ChatHistoryItemResType[];
};
export type DispatchNodeResultType<T> = {
[DispatchNodeResponseKeyEnum.nodeResponse]?: DispatchNodeResponseType; // The node response detail
[DispatchNodeResponseKeyEnum.nodeDispatchUsages]?: ChatNodeUsageType[]; //
[DispatchNodeResponseKeyEnum.childrenResponses]?: DispatchNodeResultType[];
[DispatchNodeResponseKeyEnum.toolResponses]?: ToolRunResponseItemType;
[DispatchNodeResponseKeyEnum.assistantResponses]?: ChatItemValueItemType[];
} & T;

View File

@@ -0,0 +1,31 @@
import { ChatCompletionRequestMessageRoleEnum } from '../../ai/constants';
export const textAdaptGptResponse = ({
text,
model = '',
finish_reason = null,
extraData = {}
}: {
model?: string;
text: string | null;
finish_reason?: null | 'stop';
extraData?: Object;
}) => {
return JSON.stringify({
...extraData,
id: '',
object: '',
created: 0,
model,
choices: [
{
delta:
text === null
? {}
: { role: ChatCompletionRequestMessageRoleEnum.Assistant, content: text },
index: 0,
finish_reason
}
]
});
};

View File

@@ -1,26 +1,25 @@
import { UserGuideModule } from '@fastgpt/global/core/module/template/system/userGuide';
import { UserInputModule } from '@fastgpt/global/core/module/template/system/userInput';
import { AiChatModule } from '@fastgpt/global/core/module/template/system/aiChat';
import { DatasetSearchModule } from '@fastgpt/global/core/module/template/system/datasetSearch';
import { DatasetConcatModule } from '@fastgpt/global/core/module/template/system/datasetConcat';
import { AssignedAnswerModule } from '@fastgpt/global/core/module/template/system/assignedAnswer';
import { ClassifyQuestionModule } from '@fastgpt/global/core/module/template/system/classifyQuestion';
import { ContextExtractModule } from '@fastgpt/global/core/module/template/system/contextExtract';
import { HttpModule468 } from '@fastgpt/global/core/module/template/system/http468';
import { HttpModule } from '@fastgpt/global/core/module/template/system/abandon/http';
import { UserGuideModule } from './system/userGuide';
import { UserInputModule } from './system/userInput';
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 { HttpModule } from './system/abandon/http';
import { ToolModule } from './system/tools';
import { RunAppModule } from '@fastgpt/global/core/module/template/system/runApp';
import { PluginInputModule } from '@fastgpt/global/core/module/template/system/pluginInput';
import { PluginOutputModule } from '@fastgpt/global/core/module/template/system/pluginOutput';
import { RunPluginModule } from '@fastgpt/global/core/module/template/system/runPlugin';
import { AiCFR } from '@fastgpt/global/core/module/template/system/coreferenceResolution';
import { RunAppModule } from './system/runApp';
import { PluginInputModule } from './system/pluginInput';
import { PluginOutputModule } from './system/pluginOutput';
import { RunPluginModule } from './system/runPlugin';
import { AiQueryExtension } from './system/queryExtension';
import type {
FlowModuleTemplateType,
moduleTemplateListType
} from '@fastgpt/global/core/module/type.d';
import { ModuleTemplateTypeEnum } from '@fastgpt/global/core/module/constants';
import type { FlowModuleTemplateType, moduleTemplateListType } from '../../module/type.d';
import { ModuleTemplateTypeEnum } from '../../module/constants';
/* app flow module templates */
export const appSystemModuleTemplates: FlowModuleTemplateType[] = [
UserGuideModule,
UserInputModule,
@@ -29,10 +28,13 @@ export const appSystemModuleTemplates: FlowModuleTemplateType[] = [
DatasetSearchModule,
DatasetConcatModule,
RunAppModule,
ToolModule,
ClassifyQuestionModule,
ContextExtractModule,
HttpModule468
HttpModule468,
AiQueryExtension
];
/* plugin flow module templates */
export const pluginSystemModuleTemplates: FlowModuleTemplateType[] = [
PluginInputModule,
PluginOutputModule,
@@ -41,11 +43,14 @@ export const pluginSystemModuleTemplates: FlowModuleTemplateType[] = [
DatasetSearchModule,
DatasetConcatModule,
RunAppModule,
ToolModule,
ClassifyQuestionModule,
ContextExtractModule,
HttpModule468
HttpModule468,
AiQueryExtension
];
/* all module */
export const moduleTemplatesFlat: FlowModuleTemplateType[] = [
UserGuideModule,
UserInputModule,
@@ -57,11 +62,13 @@ export const moduleTemplatesFlat: FlowModuleTemplateType[] = [
ContextExtractModule,
HttpModule468,
HttpModule,
ToolModule,
AiChatModule,
RunAppModule,
PluginInputModule,
PluginOutputModule,
RunPluginModule,
AiCFR
AiQueryExtension
];
export const moduleTemplatesList: moduleTemplateListType = [

View File

@@ -2,6 +2,7 @@ import type { FlowNodeInputItemType } from '../node/type.d';
import { DYNAMIC_INPUT_KEY, ModuleInputKeyEnum } from '../constants';
import { FlowNodeInputTypeEnum } from '../node/constant';
import { ModuleIOValueTypeEnum } from '../constants';
import { chatNodeSystemPromptTip } from './tip';
export const Input_Template_Switch: FlowNodeInputItemType = {
key: ModuleInputKeyEnum.switch,
@@ -58,6 +59,28 @@ export const Input_Template_DynamicInput: FlowNodeInputItemType = {
hideInApp: true
};
export const Input_Template_AiModel: FlowNodeInputItemType = {
key: ModuleInputKeyEnum.aiModel,
type: FlowNodeInputTypeEnum.selectLLMModel,
label: 'core.module.input.label.aiModel',
required: true,
valueType: ModuleIOValueTypeEnum.string,
showTargetInApp: false,
showTargetInPlugin: false
};
export const Input_Template_System_Prompt: FlowNodeInputItemType = {
key: ModuleInputKeyEnum.aiSystemPrompt,
type: FlowNodeInputTypeEnum.textarea,
max: 3000,
valueType: ModuleIOValueTypeEnum.string,
label: 'core.ai.Prompt',
description: chatNodeSystemPromptTip,
placeholder: chatNodeSystemPromptTip,
showTargetInApp: true,
showTargetInPlugin: true
};
export const Input_Template_Dataset_Quote: FlowNodeInputItemType = {
key: ModuleInputKeyEnum.aiChatDatasetQuote,
type: FlowNodeInputTypeEnum.target,

View File

@@ -11,9 +11,11 @@ import {
ModuleTemplateTypeEnum
} from '../../constants';
import {
Input_Template_AiModel,
Input_Template_Dataset_Quote,
Input_Template_History,
Input_Template_Switch,
Input_Template_System_Prompt,
Input_Template_UserChatInput
} from '../input';
import { chatNodeSystemPromptTip } from '../tip';
@@ -24,20 +26,13 @@ export const AiChatModule: FlowModuleTemplateType = {
templateType: ModuleTemplateTypeEnum.textAnswer,
flowType: FlowNodeTypeEnum.chatNode,
avatar: '/imgs/module/AI.png',
name: 'core.module.template.Ai chat',
intro: 'core.module.template.Ai chat intro',
name: 'AI 对话',
intro: 'AI 大模型对话',
showStatus: true,
// isTool: true,
inputs: [
Input_Template_Switch,
{
key: ModuleInputKeyEnum.aiModel,
type: FlowNodeInputTypeEnum.selectChatModel,
label: 'core.module.input.label.aiModel',
required: true,
valueType: ModuleIOValueTypeEnum.string,
showTargetInApp: false,
showTargetInPlugin: false
},
Input_Template_AiModel,
// --- settings modal
{
key: ModuleInputKeyEnum.aiChatTemperature,
@@ -98,18 +93,13 @@ export const AiChatModule: FlowModuleTemplateType = {
},
// settings modal ---
{
key: ModuleInputKeyEnum.aiSystemPrompt,
type: FlowNodeInputTypeEnum.textarea,
...Input_Template_System_Prompt,
label: 'core.ai.Prompt',
max: 300,
valueType: ModuleIOValueTypeEnum.string,
description: chatNodeSystemPromptTip,
placeholder: chatNodeSystemPromptTip,
showTargetInApp: true,
showTargetInPlugin: true
placeholder: chatNodeSystemPromptTip
},
Input_Template_History,
Input_Template_UserChatInput,
{ ...Input_Template_UserChatInput, toolDescription: '用户问题' },
Input_Template_Dataset_Quote
],
outputs: [

View File

@@ -9,8 +9,9 @@ export const AssignedAnswerModule: FlowModuleTemplateType = {
templateType: ModuleTemplateTypeEnum.textAnswer,
flowType: FlowNodeTypeEnum.answerNode,
avatar: '/imgs/module/reply.png',
name: 'core.module.template.Assigned reply',
intro: 'core.module.template.Assigned reply intro',
name: '指定回复',
intro:
'该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。',
inputs: [
Input_Template_Switch,
{

View File

@@ -6,40 +6,34 @@ import {
import { FlowModuleTemplateType } from '../../type.d';
import { ModuleIOValueTypeEnum, ModuleInputKeyEnum, ModuleTemplateTypeEnum } from '../../constants';
import {
Input_Template_AiModel,
Input_Template_History,
Input_Template_Switch,
Input_Template_UserChatInput
} from '../input';
import { Output_Template_UserChatInput } from '../output';
import { Input_Template_System_Prompt } from '../input';
import { LLMModelTypeEnum } from '../../../ai/constants';
export const ClassifyQuestionModule: FlowModuleTemplateType = {
id: FlowNodeTypeEnum.classifyQuestion,
templateType: ModuleTemplateTypeEnum.functionCall,
flowType: FlowNodeTypeEnum.classifyQuestion,
avatar: '/imgs/module/cq.png',
name: 'core.module.template.Classify question',
intro: `core.module.template.Classify question intro`,
name: '问题分类',
intro: `根据用户的历史记录和当前问题判断该次提问的类型。可以添加多组问题类型,下面是一个模板例子:\n类型1: 打招呼\n类型2: 关于商品“使用”问题\n类型3: 关于商品“购买”问题\n类型4: 其他问题`,
showStatus: true,
inputs: [
Input_Template_Switch,
{
key: ModuleInputKeyEnum.aiModel,
type: FlowNodeInputTypeEnum.selectCQModel,
valueType: ModuleIOValueTypeEnum.string,
label: 'core.module.input.label.Classify model',
required: true,
showTargetInApp: false,
showTargetInPlugin: false
...Input_Template_AiModel,
llmModelType: LLMModelTypeEnum.classify
},
{
key: ModuleInputKeyEnum.aiSystemPrompt,
type: FlowNodeInputTypeEnum.textarea,
valueType: ModuleIOValueTypeEnum.string,
...Input_Template_System_Prompt,
label: 'core.module.input.label.Background',
description: 'core.module.input.description.Background',
placeholder: 'core.module.input.placeholder.Classify background',
showTargetInApp: true,
showTargetInPlugin: true
placeholder: 'core.module.input.placeholder.Classify background'
},
Input_Template_History,
Input_Template_UserChatInput,

View File

@@ -10,26 +10,23 @@ import {
ModuleOutputKeyEnum,
ModuleTemplateTypeEnum
} from '../../constants';
import { Input_Template_History, Input_Template_Switch } from '../input';
import { Input_Template_AiModel, Input_Template_History, Input_Template_Switch } from '../input';
import { LLMModelTypeEnum } from '../../../ai/constants';
export const ContextExtractModule: FlowModuleTemplateType = {
id: FlowNodeTypeEnum.contentExtract,
templateType: ModuleTemplateTypeEnum.functionCall,
flowType: FlowNodeTypeEnum.contentExtract,
avatar: '/imgs/module/extract.png',
name: 'core.module.template.Extract field',
intro: 'core.module.template.Extract field intro',
name: '文本内容提取',
intro: '可从文本中提取指定的数据例如sql语句、搜索关键词、代码等',
showStatus: true,
isTool: true,
inputs: [
Input_Template_Switch,
{
key: ModuleInputKeyEnum.aiModel,
type: FlowNodeInputTypeEnum.selectExtractModel,
valueType: ModuleIOValueTypeEnum.string,
label: 'core.module.input.label.LLM',
required: true,
showTargetInApp: false,
showTargetInPlugin: false
...Input_Template_AiModel,
llmModelType: LLMModelTypeEnum.extractFields
},
{
key: ModuleInputKeyEnum.description,
@@ -52,12 +49,13 @@ export const ContextExtractModule: FlowModuleTemplateType = {
required: true,
valueType: ModuleIOValueTypeEnum.string,
showTargetInApp: true,
showTargetInPlugin: true
showTargetInPlugin: true,
toolDescription: '需要检索的内容'
},
{
key: ModuleInputKeyEnum.extractKeys,
type: FlowNodeInputTypeEnum.custom,
label: '目标字段',
label: '',
valueType: ModuleIOValueTypeEnum.any,
description: "由 '描述' 和 'key' 组成一个目标字段,可提取多个目标字段",
value: [], // {desc: string; key: string; required: boolean; enum: string[]}[]
@@ -76,6 +74,7 @@ export const ContextExtractModule: FlowModuleTemplateType = {
{
key: ModuleOutputKeyEnum.failed,
label: '提取字段缺失',
description: '存在一个或多个字段未提取成功。尽管使用了默认值也算缺失。',
valueType: ModuleIOValueTypeEnum.boolean,
type: FlowNodeOutputTypeEnum.source,
targets: []

View File

@@ -26,7 +26,7 @@ export const DatasetConcatModule: FlowModuleTemplateType = {
templateType: ModuleTemplateTypeEnum.tools,
avatar: '/imgs/module/concat.svg',
name: '知识库搜索引用合并',
intro: 'core.module.template.Dataset search result concat intro',
intro: '可以将多个知识库搜索结果进行合并输出。使用 RRF 的合并方式进行最终排序输出。',
showStatus: false,
inputs: [
Input_Template_Switch,

View File

@@ -19,9 +19,10 @@ export const DatasetSearchModule: FlowModuleTemplateType = {
templateType: ModuleTemplateTypeEnum.functionCall,
flowType: FlowNodeTypeEnum.datasetSearchNode,
avatar: '/imgs/module/db.png',
name: 'core.module.template.Dataset search',
intro: 'core.module.template.Dataset search intro',
name: '知识库搜索',
intro: '调用知识库搜索能力,查找“有可能”与问题相关的内容',
showStatus: true,
isTool: true,
inputs: [
Input_Template_Switch,
{
@@ -97,7 +98,10 @@ export const DatasetSearchModule: FlowModuleTemplateType = {
showTargetInPlugin: false,
value: ''
},
Input_Template_UserChatInput
{
...Input_Template_UserChatInput,
toolDescription: '需要检索的内容'
}
],
outputs: [
Output_Template_UserChatInput,

View File

@@ -5,9 +5,9 @@ import {
} from '../../node/constant';
import { FlowModuleTemplateType } from '../../type';
import {
DYNAMIC_INPUT_KEY,
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
ModuleOutputKeyEnum,
ModuleTemplateTypeEnum
} from '../../constants';
import {
@@ -22,9 +22,10 @@ export const HttpModule468: FlowModuleTemplateType = {
templateType: ModuleTemplateTypeEnum.externalCall,
flowType: FlowNodeTypeEnum.httpRequest468,
avatar: '/imgs/module/http.png',
name: 'core.module.template.Http request',
intro: 'core.module.template.Http request intro',
name: 'HTTP 请求',
intro: '可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)',
showStatus: true,
isTool: true,
inputs: [
Input_Template_Switch,
{
@@ -85,9 +86,7 @@ export const HttpModule468: FlowModuleTemplateType = {
...Input_Template_AddInputParam,
editField: {
key: true,
name: true,
description: true,
required: true,
dataType: true
},
defaultEditField: {
@@ -95,20 +94,27 @@ export const HttpModule468: FlowModuleTemplateType = {
key: '',
description: '',
inputType: FlowNodeInputTypeEnum.target,
valueType: ModuleIOValueTypeEnum.string,
required: true
valueType: ModuleIOValueTypeEnum.string
}
}
],
outputs: [
Output_Template_Finish,
{
key: ModuleOutputKeyEnum.httpRawResponse,
label: '原始响应',
description: 'HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。',
valueType: ModuleIOValueTypeEnum.any,
type: FlowNodeOutputTypeEnum.source,
targets: []
},
{
...Output_Template_AddOutput,
editField: {
key: true,
name: true,
description: true,
dataType: true
dataType: true,
defaultValue: true
},
defaultEditField: {
label: '',

View File

@@ -3,7 +3,7 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '../../node/constant';
import { FlowModuleTemplateType } from '../../type.d';
import { FlowModuleTemplateType } from '../../type';
import {
ModuleIOValueTypeEnum,
ModuleInputKeyEnum,
@@ -13,33 +13,31 @@ import {
import {
Input_Template_History,
Input_Template_Switch,
Input_Template_UserChatInput
Input_Template_UserChatInput,
Input_Template_AiModel
} from '../input';
import { Output_Template_UserChatInput } from '../output';
import { LLMModelTypeEnum } from '../../../ai/constants';
export const AiCFR: FlowModuleTemplateType = {
export const AiQueryExtension: FlowModuleTemplateType = {
id: FlowNodeTypeEnum.chatNode,
templateType: ModuleTemplateTypeEnum.other,
flowType: FlowNodeTypeEnum.cfr,
flowType: FlowNodeTypeEnum.queryExtension,
avatar: '/imgs/module/cfr.svg',
name: 'core.module.template.Query extension',
intro: '该模块已合并到知识库搜索参数中无需单独使用。模块将于2024/3/31弃用请尽快修改。',
name: '问题优化',
intro:
'使用问题优化功能,可以提高知识库连续对话时搜索的精度。使用该功能后,会先利用 AI 根据上下文构建一个或多个新的检索词,这些检索词更利于进行知识库搜索。该模块已内置在知识库搜索模块中,如果您仅进行一次知识库搜索,可直接使用知识库内置的补全功能。',
showStatus: true,
inputs: [
Input_Template_Switch,
{
key: ModuleInputKeyEnum.aiModel,
type: FlowNodeInputTypeEnum.selectExtractModel,
label: 'core.module.input.label.aiModel',
required: true,
valueType: ModuleIOValueTypeEnum.string,
showTargetInApp: false,
showTargetInPlugin: false
...Input_Template_AiModel,
llmModelType: LLMModelTypeEnum.queryExtension
},
{
key: ModuleInputKeyEnum.aiSystemPrompt,
type: FlowNodeInputTypeEnum.textarea,
label: 'core.module.input.label.Background',
label: 'core.app.edit.Query extension background prompt',
max: 300,
valueType: ModuleIOValueTypeEnum.string,
description: 'core.app.edit.Query extension background tip',
@@ -54,7 +52,8 @@ export const AiCFR: FlowModuleTemplateType = {
Output_Template_UserChatInput,
{
key: ModuleOutputKeyEnum.text,
label: 'core.module.output.label.cfr result',
label: 'core.module.output.label.query extension result',
description: 'core.module.output.description.query extension result',
valueType: ModuleIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.source,
targets: []

View File

@@ -22,8 +22,8 @@ export const RunAppModule: FlowModuleTemplateType = {
templateType: ModuleTemplateTypeEnum.externalCall,
flowType: FlowNodeTypeEnum.runApp,
avatar: '/imgs/module/app.png',
name: 'core.module.template.Running app',
intro: 'core.module.template.Running app intro',
name: '应用调用',
intro: '可以选择一个其他应用进行调用',
showStatus: true,
inputs: [
Input_Template_Switch,
@@ -52,7 +52,7 @@ export const RunAppModule: FlowModuleTemplateType = {
},
{
key: ModuleOutputKeyEnum.answerText,
label: 'AI回复',
label: '回复的文本',
description: '将在应用完全结束后触发',
valueType: ModuleIOValueTypeEnum.string,
type: FlowNodeOutputTypeEnum.source,

View File

@@ -9,6 +9,7 @@ export const RunPluginModule: FlowModuleTemplateType = {
intro: '',
name: '',
showStatus: false,
isTool: true,
inputs: [], // [{key:'pluginId'},...]
outputs: []
};

View File

@@ -0,0 +1,52 @@
import { FlowNodeOutputTypeEnum, FlowNodeTypeEnum } from '../../node/constant';
import { FlowModuleTemplateType } from '../../type.d';
import {
ModuleIOValueTypeEnum,
ModuleOutputKeyEnum,
ModuleTemplateTypeEnum
} from '../../constants';
import {
Input_Template_AiModel,
Input_Template_History,
Input_Template_Switch,
Input_Template_System_Prompt,
Input_Template_UserChatInput
} from '../input';
import { chatNodeSystemPromptTip } from '../tip';
import { Output_Template_Finish, Output_Template_UserChatInput } from '../output';
import { LLMModelTypeEnum } from '../../../ai/constants';
export const ToolModule: FlowModuleTemplateType = {
id: FlowNodeTypeEnum.tools,
flowType: FlowNodeTypeEnum.tools,
templateType: ModuleTemplateTypeEnum.functionCall,
avatar: '/imgs/module/tool.svg',
name: '工具调用(实验)',
intro: '通过AI模型自动选择一个或多个工具进行调用。工具可以是其他功能块或插件。',
showStatus: true,
inputs: [
Input_Template_Switch,
{
...Input_Template_AiModel,
llmModelType: LLMModelTypeEnum.toolCall
},
{
...Input_Template_System_Prompt,
label: 'core.ai.Prompt',
description: chatNodeSystemPromptTip,
placeholder: chatNodeSystemPromptTip
},
Input_Template_History,
Input_Template_UserChatInput
],
outputs: [
Output_Template_UserChatInput,
{
key: ModuleOutputKeyEnum.selectedTools,
valueType: ModuleIOValueTypeEnum.tools,
type: FlowNodeOutputTypeEnum.hidden,
targets: []
},
Output_Template_Finish
]
};

View File

@@ -8,7 +8,7 @@ export const UserGuideModule: FlowModuleTemplateType = {
templateType: ModuleTemplateTypeEnum.userGuide,
flowType: FlowNodeTypeEnum.userGuide,
avatar: '/imgs/module/userGuide.png',
name: 'core.module.template.User guide',
name: '全局配置',
intro: userGuideTip,
inputs: [
{

View File

@@ -16,8 +16,8 @@ export const UserInputModule: FlowModuleTemplateType = {
templateType: ModuleTemplateTypeEnum.systemInput,
flowType: FlowNodeTypeEnum.questionInput,
avatar: '/imgs/module/userChatInput.svg',
name: 'core.module.template.Chat entrance',
intro: 'core.module.template.Chat entrance intro',
name: '对话入口',
intro: '当用户发送一个内容后,流程将会从这个模块开始执行。',
inputs: [
{
key: ModuleInputKeyEnum.userChatInput,

View File

@@ -1,6 +1,20 @@
import { FlowNodeTypeEnum } from './node/constant';
import { ModuleIOValueTypeEnum, ModuleTemplateTypeEnum, VariableInputEnum } from './constants';
import {
ModuleIOValueTypeEnum,
ModuleOutputKeyEnum,
ModuleTemplateTypeEnum,
VariableInputEnum
} from './constants';
import { DispatchNodeResponseKeyEnum } from './runtime/constants';
import { FlowNodeInputItemType, FlowNodeOutputItemType } from './node/type';
import { UserModelSchema } from 'support/user/type';
import {
ChatItemValueItemType,
ToolRunResponseItemType,
UserChatItemValueItemType
} from '../chat/type';
import { ChatNodeUsageType } from '../../support/wallet/bill/type';
import { RunningModuleItemType } from './runtime/type';
export type FlowModuleTemplateType = {
id: string; // module id, unique
@@ -9,6 +23,7 @@ export type FlowModuleTemplateType = {
avatar?: string;
name: string;
intro: string; // template list intro
isTool?: boolean; // can be connected by tool
showStatus?: boolean; // chatting response step status
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
@@ -36,6 +51,9 @@ export type ModuleItemType = {
showStatus?: boolean;
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
// runTime field
isEntry?: boolean;
};
/* --------------- function type -------------------- */
@@ -72,51 +90,29 @@ export type ContextExtractAgentItemType = {
desc: string;
key: string;
required: boolean;
defaultValue?: string;
enum?: string;
};
/* -------------- running module -------------- */
export type RunningModuleItemType = {
name: ModuleItemType['name'];
moduleId: ModuleItemType['moduleId'];
flowType: ModuleItemType['flowType'];
showStatus?: ModuleItemType['showStatus'];
} & {
inputs: {
key: string;
value?: any;
valueType?: `${ModuleIOValueTypeEnum}`;
}[];
outputs: {
key: string;
answer?: boolean;
response?: boolean;
value?: any;
valueType?: `${ModuleIOValueTypeEnum}`;
targets: {
moduleId: string;
key: string;
}[];
}[];
};
export type ChatDispatchProps = {
res: NextApiResponse;
mode: 'test' | 'chat';
teamId: string;
tmbId: string;
user: UserType;
user: UserModelSchema;
appId: string;
chatId?: string;
responseChatItemId?: string;
histories: ChatItemType[];
variables: Record<string, any>;
inputFiles?: UserChatItemValueItemType['file'][];
stream: boolean;
detail: boolean; // response detail
};
export type ModuleDispatchProps<T> = ChatDispatchProps & {
outputs: RunningModuleItemType['outputs'];
inputs: RunningModuleItemType['inputs'];
module: RunningModuleItemType;
runtimeModules: RunningModuleItemType[];
params: T;
};

View File

@@ -10,6 +10,7 @@ import { AppTTSConfigType, ModuleItemType, VariableItemType } from './type';
import { Input_Template_Switch } from './template/input';
import { EditorVariablePickerType } from '../../../web/components/common/Textarea/PromptEditor/type';
/* module */
export const getGuideModule = (modules: ModuleItemType[]) =>
modules.find((item) => item.flowType === FlowNodeTypeEnum.userGuide);
@@ -57,13 +58,13 @@ export const getModuleInputUiField = (input: FlowNodeInputItemType) => {
return {};
};
export function plugin2ModuleIO(
export const plugin2ModuleIO = (
pluginId: string,
modules: ModuleItemType[]
): {
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
} {
} => {
const pluginInput = modules.find((module) => module.flowType === FlowNodeTypeEnum.pluginInput);
const pluginOutput = modules.find((module) => module.flowType === FlowNodeTypeEnum.pluginOutput);
@@ -99,7 +100,7 @@ export function plugin2ModuleIO(
}))
: []
};
}
};
export const formatEditorVariablePickerIcon = (
variables: { key: string; label: string; type?: `${VariableInputEnum}` }[]

View File

@@ -6,7 +6,7 @@
"dayjs": "^1.11.7",
"encoding": "^0.1.13",
"js-tiktoken": "^1.0.7",
"openai": "4.23.0",
"openai": "4.28.0",
"nanoid": "^4.0.1",
"timezones-list": "^3.0.2"
},

View File

@@ -1,6 +1,5 @@
export type OpenApiSchema = {
_id: string;
userId: string;
teamId: string;
tmbId: string;
createTime: Date;
@@ -8,9 +7,9 @@ export type OpenApiSchema = {
apiKey: string;
appId?: string;
name: string;
usage: number;
usagePoints: number;
limit?: {
expiredTime?: Date;
credit?: number;
maxUsagePoints: number;
};
};

View File

@@ -1,5 +1,5 @@
import type { HistoryItemType, ChatSiteItemType } from '../../core/chat/type.d';
import { OutLinkSchema } from '@fastgpt/global/support/outLink/type';
import type { HistoryItemType } from '../../core/chat/type.d';
import { OutLinkSchema } from './type.d';
export type AuthOutLinkInitProps = {
outLinkUid: string;

View File

@@ -1,3 +1,4 @@
import { AppSchema } from 'core/app/type';
import { OutLinkTypeEnum } from './constant';
export type OutLinkSchema = {
@@ -7,17 +8,20 @@ export type OutLinkSchema = {
tmbId: string;
appId: string;
name: string;
total: number;
usagePoints: number;
lastTime: Date;
type: `${OutLinkTypeEnum}`;
responseDetail: boolean;
limit?: {
expiredTime?: Date;
QPM: number;
credit: number;
maxUsagePoints: number;
hookUrl?: string;
};
};
export type OutLinkWithAppType = Omit<OutLinkSchema, 'appId'> & {
appId: AppSchema;
};
export type OutLinkEditType = {
_id?: string;

View File

@@ -0,0 +1,9 @@
type ShareChatAuthProps = {
shareId?: string;
outLinkUid?: string;
};
type TeamChatAuthProps = {
teamId?: string;
teamToken?: string;
};
export type OutLinkChatAuthProps = ShareChatAuthProps & TeamChatAuthProps;

View File

@@ -2,7 +2,8 @@ export enum AuthUserTypeEnum {
token = 'token',
root = 'root',
apikey = 'apikey',
outLink = 'outLink'
outLink = 'outLink',
teamDomain = 'teamDomain'
}
export enum PermissionTypeEnum {

View File

@@ -1,7 +1,6 @@
import { AuthUserTypeEnum } from './constant';
export type AuthResponseType = {
userId: string;
teamId: string;
tmbId: string;
isOwner: boolean;

View File

@@ -10,7 +10,11 @@ export type OauthLoginProps = {
code: string;
callbackUrl: string;
inviterId?: string;
tmbId?: string;
};
export type WxLoginProps = {
inviterId?: string;
code: string;
};
export type FastLoginProps = {

View File

@@ -0,0 +1,11 @@
export enum UserAuthTypeEnum {
register = 'register',
findPassword = 'findPassword',
wxLogin = 'wxLogin'
}
export const userAuthTypeMap = {
[UserAuthTypeEnum.register]: 'register',
[UserAuthTypeEnum.findPassword]: 'findPassword',
[UserAuthTypeEnum.wxLogin]: 'wxLogin'
};

View File

@@ -13,10 +13,6 @@ export const userStatusMap = {
export enum OAuthEnum {
github = 'github',
google = 'google'
}
export enum UserAuthTypeEnum {
register = 'register',
findPassword = 'findPassword'
google = 'google',
wechat = 'wechat'
}

View File

@@ -0,0 +1,4 @@
export type GetWXLoginQRResponse = {
code: string;
codeUrl: string;
};

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