Compare commits

..

97 Commits

Author SHA1 Message Date
Archer
4061b11922 fix: dataset select check (#3048) 2024-10-31 17:25:02 +08:00
Finley Ge
bc171db945 fix: alldataset get dataset without folders. omit the permission check (#3047) 2024-10-31 17:06:56 +08:00
Jiangween
eb365fef44 Update i18n files and Upload component (#3040)
* Update i18n files and Upload component

* 完善 i18n 和优化 Upload.tsx 文件

* 修改Upload.tsx 文件的问题...
2024-10-31 15:25:00 +08:00
Archer
2e7047cb3b Update 4812.md (#3036) 2024-10-31 00:48:36 +08:00
Archer
89a817d1c9 fix: dataset select cannot refresh (#3032)
* fix: dataset select cannot refresh

* update cors
2024-10-30 19:30:31 +08:00
Finley Ge
e788bcaabe fix: only owner or team owner can change app's owner (#3033) 2024-10-30 19:11:54 +08:00
heheer
9219903341 add goole tag manager (#3028) 2024-10-30 19:04:26 +08:00
Finley Ge
6939899baa fix: allDataset (#3031) 2024-10-30 19:02:08 +08:00
papapatrick
732b6d7780 add more market template (#3030)
* add more market template

* delete long translate avatar
2024-10-30 18:42:46 +08:00
heheer
e361279208 feat: add baidu conversion tracking (#3016)
* feat: add baidu conversion tracking

* chore
2024-10-30 14:40:49 +08:00
Archer
946fda0843 4.8.12 test (#3026)
* perf: app list permission

* perf: create dataset tip

* fix: create dataset
2024-10-30 14:23:37 +08:00
Archer
97216eec59 perf: app list permission (#3023)
* perf: app list permission

* perf: create dataset tip
2024-10-30 12:38:16 +08:00
Finley Ge
9f4aa3160e fix: app/dataset auth (#3021) 2024-10-30 11:50:25 +08:00
Archer
8e4084f7ee update text splitter (#3020) 2024-10-30 01:10:35 +08:00
Archer
ee718750e2 perf: dataset data auth (#3015) 2024-10-29 15:44:46 +08:00
Archer
1e02544c3a feat: reset milvus (#3013) 2024-10-29 14:55:27 +08:00
heheer
98771284e4 app list open-api & completion with appid & get history source (#3011)
* app list open-api & completion with appid & get history source

* change default value position
2024-10-29 14:27:29 +08:00
Finley Ge
efc4e860b7 fix/group (#3012)
* fix: app/dataset list private resource bug

* fix: auth owner
2024-10-29 11:22:21 +08:00
Archer
e06d72e86e 4.8.12 test (#3006)
* perf: oneapi error tip

* fix: qps limit condition error

* perf: Plan tip

* fix: permission modal ui

* perf: dataset slider ui

* perf: api key auth tmbId problem

* perf: dataset upload i18n

* fix: http json path check
2024-10-28 22:47:45 +08:00
Finley Ge
b712a821f8 fix: upload file (#2992)
* fix: upload file

* chore: remove wasm, support html image parse

* chore: adjust

* chore: move base64match function into htmlstr2md
2024-10-28 21:44:50 +08:00
Finley Ge
4e3d817b63 fix: milvus (#3004) 2024-10-28 16:06:08 +08:00
heheer
78a85bf847 fix: optimize tool node check in workflow (#3002)
* fix: optimize tool node check in workflow

* comment
2024-10-28 15:37:00 +08:00
ainuoyan
a5b913f1b1 Update chat.md (#2996) 2024-10-27 18:44:52 +08:00
Jiangween
7ee1a340e6 Re-add RAG documentation and images (#2995) 2024-10-27 09:15:44 +08:00
Archer
c722ced68d 4.8.12 test (#2994)
* perf: run loop code

* doc

* fix: mulity loop node will error; loop node variables cannot inherit

* back save tip position

* fix: child workflow runtime

* stream connection
2024-10-25 23:13:53 +08:00
Archer
f89452acdd Group role (#2993)
* feat: app/dataset support group (#2898)

* pref: member-group (#2862)

* feat: group list ordered by updateTime

* fix: transfer ownership of group when deleting member

* fix: i18n fix

* feat: can not set member as admin/owner when user is not active

* fix: GroupInfoModal hover input do not change color

* fix(fe): searchinput do not scroll

* feat: app collaborator with group, remove default permission

* feat: dataset collaborator with group, remove default permission

* chore(test): pref mock

* chore: remove useless code

* chore: adjust

* fix: add self as collaborator when creating folder

* fix(fe): folder manage menu do not show when user has write permission
only

* fix: dataset folder create

* feat: Add code comment

* Pref: app move (#2952)

* perf: app schema

* doc

---------

Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com>
2024-10-25 19:39:11 +08:00
Archer
74d58d562b 4.8.12 test fix (#2988)
* perf: qps limit

* perf: http response data

* perf: json path check

* fix: ts

* loop support reference parent variable
2024-10-25 16:34:26 +08:00
heheer
165fe077bc fix: http raw response undefined (#2981) 2024-10-25 11:53:32 +08:00
Finley Ge
75494f8d01 feat: QPS Limit middleware (#2956)
* feat: QPS Limit middleware

* chore: use request-ip to get client ip

* feat: frequencyLimit schema
2024-10-25 10:08:59 +08:00
papapatrick
bb727b0710 add bing search plugins (#2970) 2024-10-23 22:45:06 +08:00
Archer
9b0706ed92 HTTP support jsonPath; System plugin support save file. (#2969)
* perf: system plugin auto save file

* feat: http support jsonPath

* fix: assistant response

* reset milvus version

* fix: textarea register

* fix: global variable

* delete tip

* doc
2024-10-23 00:40:54 +08:00
Finley Ge
718108a552 fix: milvus (#2968) 2024-10-22 21:53:48 +08:00
heheer
025facbc2d perf:textarea auto height (#2967)
* perf:textarea auto height

* optimize editor height & fix variable label split
2024-10-22 18:33:02 +08:00
Archer
87b4061302 System plugin adapt reference type in plugin input (#2965)
* perf: plugin input support reference

* perf: system plugin adapt plugin input reference
2024-10-22 14:51:15 +08:00
Archer
618729a254 Concat textinput to input type (#2963)
* perf: toast position

* concat textinput to input
2024-10-22 12:04:16 +08:00
heheer
3f34c33d4c perf: all plugin variables type support referense & replace input and textarea with prompt editor (#2950)
* support reference as plugin variables

* replace input and textarea with prompt editor

* adjust height & optimize textarea and input

* input select
2024-10-22 11:21:28 +08:00
zhengkai
779ff29ed5 typofix:laf函数调用时,弹出文字错误 (#2951)
* typofix:laf函数调用时,弹出文字错误

laf函数调用,新增/编辑输出时,显示错误,目前显示为新增/编辑输入

* fix typo ui
2024-10-22 08:50:03 +08:00
papapatrick
445a38924f add google search plugin (#2947) 2024-10-22 08:49:05 +08:00
silencezhang
7ec2253f0a 新增数据源配置:可以直接执行sql,支持MySQL,PG数据库 (#2958) 2024-10-21 14:26:33 +08:00
heheer
6522cc7dfa chore: adjust toast top distance (#2953)
* adjust toast top distance

* save button top
2024-10-18 17:20:57 +08:00
Archer
40f527a021 4.8.12 test (#2936)
* system config tip

* perf: prompt editor code

* perf: cookie tip
2024-10-18 16:49:35 +08:00
Zhenyi-Wang
4aaf9bfeb0 在“发布成功”通知中,显示关闭按钮 (#2948)
* feat: remove style tag when fetching url

* 在“发布成功”通知中,显示关闭按钮

---------

Co-authored-by: zhenyiwang <zhenyiwang@intl.zju.edu.cn>
2024-10-17 18:12:40 +08:00
papapatrick
5efa70f3a1 feat: add cookies tip drawer (#2935) 2024-10-16 15:18:55 +08:00
heheer
d45d18cc3b fix: variable label i18n & create question guide language (#2933) 2024-10-16 14:21:53 +08:00
heheer
8bdb35ff51 fix: quote settings default value & zindex & i18n (#2931) 2024-10-16 13:26:51 +08:00
居里栈栈
e56965a8ed feat: add AI Icon Svg Logo (#2930)
Co-authored-by: 勤劳上班的卑微小张 <jiazhan.zhang@ggimage.com>
2024-10-16 12:19:53 +08:00
Archer
d4e0a43771 4.8.12 dev (#2928)
* perf: optimize global variables (#2863)

* feat: add global variable types

* add global variables to debug

* fix select dnd

* unify InputTypeConfig params

* feat: http node url support variables (#2891)

* feat: http node url support variables

* change to prompt editor

* fix: global variables (#2892)

* fix global variables

* fix type

* perf: global variables

* perf: workflow delete node error (#2905)

* update lock

* update 4812 doc

* feat: add node course url config (#2897)

* feat: add node course url config

* change plugin course url

* change default doc url

* change url store

* delete unused code

* fix: global variable (#2915)

* fix: global variable

* add comment

* fix: interactive check

* locj

* perf: debug switch to global tab when click run & global var default reset (#2925)

* fix: tool course url

* fix: global var default value & wrap variable form (#2926)

* fix: add dataset tags not update render (#2927)

* feat: tool will save histories

* perf: global variables code

* perf: FE_DOMAIN config

---------

Co-authored-by: heheer <heheer@sealos.io>
2024-10-15 20:23:18 +08:00
heheer
00638d6ee7 fix: add dataset tags not update render (#2927) 2024-10-15 17:44:50 +08:00
Archer
da281ea9ec perf: variable replace rang (#2923) 2024-10-15 16:42:42 +08:00
Archer
4f1ce640a7 Tool call support interactive node (#2903)
* feat: tool call support interactive node

* feat: interactive node tool response

* fix: tool call concat

* fix: llm history concat
2024-10-14 21:55:18 +08:00
Zhenyi-Wang
2a2b919daf feat: remove style tag when fetching url (#2913)
Co-authored-by: zhenyiwang <zhenyiwang@intl.zju.edu.cn>
2024-10-14 14:37:29 +08:00
Archer
3f01cc9c63 Doc (#2916)
* perf: community code

* update doc
2024-10-14 14:36:28 +08:00
Archer
bc70428d89 update feishu-img (#2914) 2024-10-14 12:31:07 +08:00
Archer
d55ccc9f64 Doc (#2910)
* feat: add app chat openapi (#2908)

* add chat openapi

* create question guide openapi

* change auth method

* add chat openapi doc

* delete unused code

* feat: chat openapi doc

* rerank doc

* add chat detail openapi & doc

* update chat openapi doc

---------

Co-authored-by: heheer <heheer@sealos.io>
Co-authored-by: heheer <1239331448@qq.com>
2024-10-14 10:26:57 +08:00
Nathanael
27ef4dc8ea Updated readme english (#2907) 2024-10-13 15:48:27 +08:00
papapatrick
daa5b552b1 plugins: add wiki search (#2886)
* plugins: add wiki search

* 扁平化代码

* fix: url error
2024-10-12 15:02:00 +08:00
Finley Ge
fe6c8897ce fix: resource permission indexes (#2890) 2024-10-12 09:59:59 +08:00
heheer
0dcda9822e change app template default author (#2893) 2024-10-12 09:59:16 +08:00
heheer
06e1c5d68d fix: not delete edges when deleting non-deletable nodes (#2887) 2024-10-11 12:09:33 +08:00
methol
d52da7d4e0 fix:fastgpt-sandbox image version (#2882) 2024-10-10 22:20:24 +08:00
Archer
a42707064a Update 469.md (#2880) 2024-10-10 19:51:23 +08:00
Archer
02bcab8802 fix: workflow delete error (#2879)
* fix: workflow delete key error

* fix: chat auth error
2024-10-10 19:31:51 +08:00
Archer
27291faa66 fix: dataset data list api adapt (#2878)
* fix: dataset data list api adapt

* update doc version

* perf: fedomain env

* add fedomain env
2024-10-10 18:10:19 +08:00
Archer
3878a50d0f fix: file extension check (#2876) 2024-10-10 17:35:56 +08:00
Archer
15b8353c7d Update README.md (#2875)
* Update README.md

* Update README.md
2024-10-10 16:56:59 +08:00
Archer
b950146031 update o1 config (#2874)
* update o1 config

* update yml
2024-10-10 16:52:32 +08:00
Archer
887e1d53d6 fix: o1 model cannot run in simpleApp (#2873) 2024-10-10 16:46:32 +08:00
Archer
1dcd39bfbe action (#2872) 2024-10-10 15:46:15 +08:00
Archer
01dad96618 4.8.11 test (#2871)
* fix: variables check

* remove log

* update version doc
2024-10-10 14:54:09 +08:00
Archer
13401294ad IOS safari whisper support (#2870)
* fix: variables check

* remove log

* perf: safari whisper

* feat: comment

* perf: connetion check

* doc
2024-10-10 12:24:07 +08:00
heheer
8273c96bbc fix: form-data not display in http node log (#2868)
* fix: fix form-data not display in http node log

* fix
2024-10-10 11:47:45 +08:00
Archer
61c6b1e471 Perf: delete app tip; fix: can't stop debug. (#2865)
* fix: variables check

* remove log

* perf: delete app tip

* perf: remove node code

* fix: can not stop debug

* update version

* update version intro

* fix: per error

* perf: apikey manager

* Add permission check

* update README
2024-10-10 11:30:36 +08:00
heheer
f06aca9874 fix: customize flow remove change (#2858)
* fix: customize flow remove change

* fix when mouse not in canvas
2024-10-09 22:02:17 +08:00
Archer
3a4b4a866b Team group (#2864)
* feat(member-group): Team (#2616)

* feat: member-group schema define

* feat(fe): create group

* feat: add group edit modal

* feat(fe): add avatar group component

* feat: edit group
fix: permission select menu style

* feat: bio-mode support for select-member component

* fix: avatar group key unique

* feat: group manage

* feat: divide member into group and clbs

* feat: finish team permission

* chore: adjust

* fix: get clbs

* perf: groups code

* pref: member group for team (#2706)

* chore: fe adjust
fix: remove the member from groups when removing from team
feat: change the groups avatar when updating the team's avatar

* chore: DefaultGroupName as a constant string ''

* fix: create default group when create team for root

* feat: comment

* feat: 4811 init

* pref: member group for team (#2732)

* chore: default group name

* feat: get default group when get by tmbid

* feat(fe): adjust

* member ui

* fix: delete group (#2736)

* perf: init4811

* pref: member group (#2818)

* fix: update clb per then refetch clb list

* fix: calculate group permission

* feat(fe): group tag

* refactor(fe): team and group manage

* feat: manage group member

* feat: add group transfer owner modal

* feat: group manage member

* chore: adjust the file structure

* pref: member group

* chore: adjust fe style

* fix: ts error

* chore: fe adjust

* chore: fe adjust

* chore: adjust

* chore: adjust the code

* perf: i18n and schema name

* pref: member-group (#2862)

* feat: group list ordered by updateTime

* fix: transfer ownership of group when deleting member

* fix: i18n fix

* feat: can not set member as admin/owner when user is not active

* fix: GroupInfoModal hover input do not change color

* fix(fe): searchinput do not scroll

* perf: team group ui

* doc

* remove enum

---------

Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com>
2024-10-09 18:32:10 +08:00
Finley Ge
7afa8f00b8 pref: trim the input of outlink (#2860) 2024-10-09 14:05:23 +08:00
Archer
f6c5695df4 Optimize base64 storage in files to support concurrent storage (#2856)
* fix: variables check

* remove log

* perf: file img saved

* update doc
2024-10-08 12:58:33 +08:00
papapatrick
dd3a1b910b docs: add FAQ (#2833) 2024-10-08 12:36:23 +08:00
Archer
a66d9d2e98 4.8.11 test (#2850)
* fix: variables check

* remove log

* fix: variables refresh

* perf: team select button

* perf: remove change fn
2024-10-04 10:25:20 +08:00
Archer
fc6f28f26e fix: variables check (#2849)
* fix: variables check

* remove log
2024-10-01 11:11:19 +08:00
Archer
d4b99ddcab fix: login ip check (#2848) 2024-09-30 18:24:03 +08:00
Archer
df328b2a73 fix: comment node cannot save (#2847) 2024-09-30 18:16:20 +08:00
Archer
fadb389294 fix: loop node cannot save parentId (#2845) 2024-09-30 17:58:17 +08:00
Archer
7c38d1da9a 4.8.11 test (#2843)
* feat: app version test

* update doc

* fix: paging num error

* fix: doc api domain

* rename variable

* perf: memment node min size
2024-09-30 17:28:03 +08:00
heheer
7c829febec feat: add context menu & comment node (#2834)
* feat: add comment node

* useMemo
2024-09-29 10:08:19 +08:00
heheer
7bdff9ce9c perf: change tool params type label & enum input conditional rendering (#2835) 2024-09-28 18:00:22 +08:00
heheer
1599d144ce feat: add tool params node & tool params add array type (#2824)
* add tool params node

* add tool params enum

* node response

* tool add array type params

* fix tool params

* fix

* fix

* fix
2024-09-28 15:58:55 +08:00
Archer
f2749cbb00 4.8.11 perf (#2832)
* save toast

* perf: surya ocr

* perf: remove same model name

* fix: indexes

* perf: ip check

* feat: Fixed the version number of the subapplication

* feat: simple app get latest child version

* perf: update child dispatch variables

* feat: variables update doc
2024-09-28 15:31:25 +08:00
heheer
f7a8203454 fix:variable not update in nested workflow runs (#2830) 2024-09-28 13:59:35 +08:00
Archer
d95f71e9e3 Update dataset_engine.md (#2829) 2024-09-28 10:08:54 +08:00
Deepturn
a43d845298 Update configuration.md (#2828)
修改 claude
2024-09-28 09:57:16 +08:00
papapatrick
3e64f46d92 fix: change ip detect url (#2827) 2024-09-27 22:19:48 +08:00
yiming-alicloud
0335f16742 submit ocr module (#2815) 2024-09-27 16:07:28 +08:00
Archer
98dbec2cf7 4.8.11 fix (#2822)
* fix: tool choice hostiry error

* fix: chat page auth error redirect

* perf: ip redirect tip

* feat: fedomain env

* fix: tool desc empty

* feat: 4811 doc
2024-09-27 15:52:33 +08:00
silencezhang7
d259eda6b4 新增BI圖標功能-柱狀圖 (#2779)
* 新增BI圖標功能-柱狀圖

* 新增BI图表功能-柱狀圖,优化代码,删除无用代码

* 优化生成逻辑,支持插件手动选择图表类型:目前支持柱状图,折线图,饼图

* 修改包名称,完成基础图表
2024-09-27 13:50:42 +08:00
heheer
7c8f2ab6f5 perf: support prompt editor dynamic height increase & modify aichat placeholder (#2817) 2024-09-27 13:45:44 +08:00
papapatrick
691476c821 feat: add login page ip detect (#2819)
* feat: add login page ip detect

* code perf
2024-09-27 13:39:10 +08:00
Archer
efcb53cd6d Rename node(#2814) 2024-09-26 18:25:42 +08:00
470 changed files with 19964 additions and 5089 deletions

View File

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

BIN
.github/imgs/image.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -1,4 +1,4 @@
name: Deploy image by kubeconfig
name: Deploy doc image by kubeconfig
on:
workflow_dispatch:
push:

View File

@@ -1,4 +1,4 @@
name: Deploy image to vercel
name: Deploy doc image to vercel
on:
workflow_dispatch:

View File

@@ -24,5 +24,10 @@
"i18n-ally.translate.engines": ["google"],
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
},
"markdown.copyFiles.destination": {
"/docSite/content/**/*": "${documentWorkspaceFolder}/docSite/assets/imgs/"
},
"markdown.copyFiles.overwriteBehavior": "nameIncrementally",
"markdown.copyFiles.transformPath": "const filename = uri.path.split('/').pop(); return `/imgs/${filename}`;"
}

View File

@@ -55,7 +55,7 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
- [x] Code sandbox
- [x] 循环调用
- [x] 用户选择
- [ ] 表单输入
- [x] 表单输入
`2` 知识库能力
- [x] 多库复用,混用
@@ -77,7 +77,7 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
`4` OpenAPI 接口
- [x] completions 接口 (chat 模式对齐 GPT 接口)
- [x] 知识库 CRUD
- [ ] 对话 CRUD
- [x] 对话 CRUD
`5` 运营能力
- [x] 免登录分享窗口
@@ -96,7 +96,7 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
## 👨‍💻 开发
项目技术栈NextJs + TS + ChakraUI + Mongo + Postgres (Vector 插件)
项目技术栈NextJs + TS + ChakraUI + MongoDB + PostgreSQL (PG Vector 插件)/Milvus
- **⚡ 快速部署**
@@ -120,7 +120,7 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
扫码加入飞书话题群 (新开,逐渐弃用微信群)
![](https://oss.laf.run/otnvvf-imgs/feishu3.png)
![](https://oss.laf.run/otnvvf-imgs/fastgpt-feishu1.png)
<a href="#readme">
<img src="https://img.shields.io/badge/-返回顶部-7d09f1.svg" alt="#" align="right">

View File

@@ -4,6 +4,8 @@
# FastGPT
![Qoute](./.github/imgs/image.png)
<p align="center">
<a href="./README_en.md">English</a> |
<a href="./README.md">简体中文</a> |
@@ -12,106 +14,67 @@
FastGPT is a knowledge-based platform built on the LLMs, offers a comprehensive suite of out-of-the-box capabilities such as data processing, RAG retrieval, and visual AI workflow orchestration, letting you easily develop and deploy complex question-answering systems without the need for extensive setup or configuration.
[![GitHub Repo stars](https://img.shields.io/github/stars/labring/FastGPT?style=flat-square&labelColor=d4eaf7&color=7d09f1)](https://github.com/labring/FastGPT/stargazers)
[![GitHub pull request](https://img.shields.io/badge/PRs-welcome-fffff?style=flat-square&labelColor=d4eaf7&color=7d09f1)](https://github.com/labring/FastGPT/pulls)
[![GitHub last commit](https://img.shields.io/github/last-commit/labring/FastGPT?style=flat-square&labelColor=d4eaf7&color=7d09f1)](https://github.com/labring/FastGPT/pulls)
[![License](https://img.shields.io/badge/License-Apache--2.0-ffffff?style=flat-square&labelColor=d4eaf7&color=7d09f1)](https://github.com/labring/FastGPT/blob/main/LICENSE)
[![Documentation](https://img.shields.io/badge/Documentation-7d09f1?style=flat-square)](https://doc.tryfastgpt.ai/docs/intro)
[![Local Development](https://img.shields.io/badge/Local_Development-%23d4eaf7?style=flat-square&logo=xcode&logoColor=7d09f1)](https://doc.tryfastgpt.ai/docs/intro)
[![Explore our platform](https://img.shields.io/badge/Explore_our_platform-d4eaf7?style=flat-square&logo=spoj&logoColor=7d09f1)](https://tryfastgpt.ai/)
[![discord](https://theme.zdassets.com/theme_assets/678183/cc59daa07820943e943c2fc283b9079d7003ff76.svg)](https://discord.gg/mp68xkZn2Q)&nbsp;&nbsp;&nbsp;&nbsp;
[![Wechat](https://upload.wikimedia.org/wikipedia/en/thumb/a/af/WeChat_logo.svg/100px-WeChat_logo.svg.png?20231125073656)](https://oss.laf.run/otnvvf-imgs/feishu3.png)
</div>
<p align="center">
<a href="https://tryfastgpt.ai/">
<img height="21" src="https://img.shields.io/badge/Try it Online-d4eaf7?style=flat-square&logo=spoj&logoColor=7d09f1" alt="cloud">
</a>
<a href="https://doc.tryfastgpt.ai/docs/intro">
<img height="21" src="https://img.shields.io/badge/Documents-7d09f1?style=flat-square" alt="document">
</a>
<a href="https://doc.tryfastgpt.ai/docs/development">
<img height="21" src="https://img.shields.io/badge/Local Development-%23d4eaf7?style=flat-square&logo=xcode&logoColor=7d09f1" alt="development">
</a>
<a href="https://github.com/labring/FastGPT/blob/main/LICENSE">
<img height="21" src="https://img.shields.io/badge/License-Apache--2.0-ffffff?style=flat-square&labelColor=d4eaf7&color=7d09f1" alt="license">
</a>
</p>
<div align="center">
[![discord](https://theme.zdassets.com/theme_assets/678183/cc59daa07820943e943c2fc283b9079d7003ff76.svg)](https://discord.gg/mp68xkZn2Q)
</div>
## 🎥 Comprehensive Feature Demonstration
https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409bd33f6d4
## 🛸 Use Cloud Services
## 🛸 Online Use
Cloud: [tryfastgpt.ai](https://tryfastgpt.ai/)
Website: [tryfastgpt.ai](https://tryfastgpt.ai/)
| | |
| ---------------------------------- | ---------------------------------- |
| Conversational AI Setup | Workflow Automation |
| ![Demo](./.github/imgs/intro1.png) | ![Demo](./.github/imgs/intro2.png) |
| Knowledge Base Setup | Integration Process |
| ![Demo](./.github/imgs/intro3.png) | ![Demo](./.github/imgs/intro4.png) |
<a href="#readme">
<a href="#FastGPT">
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
</a>
## 💡 Features
`1` Application Orchestration Features
- [x] Offers a straightforward mode, eliminating the need for complex orchestration
- [x] Provides clear next-step instructions in dialogues
- [x] Facilitates workflow orchestration
- [x] Tracks references in source files
- [x] Encapsulates modules for enhanced reuse at multiple levels
- [x] Combines search and reordering functions
- [ ] Includes a tool module
- [ ] Integrates [Laf](https://github.com/labring/laf) for online HTTP module creation
- [ ] Plugin encapsulation capabilities
`2` Knowledge Base Features
- [x] Allows for the mixed use of multiple databases
- [x] Keeps track of modifications and deletions in data chunks
- [x] Enables specific vector models for each knowledge base
- [x] Stores original source files
- [x] Supports direct input and segment-based QA import
- [x] Compatible with a variety of file formats: pdf, docx, txt, html, md, csv
- [x] Facilitates URL reading and bulk CSV importing
- [ ] Supports PPT and Excel file import
- [ ] Features a file reader
- [ ] Offers diverse data preprocessing options
`3` Application Debugging Features
- [x] Enables targeted search testing within the knowledge base
- [x] Allows feedback, editing, and deletion during conversations
- [x] Presents the full context of interactions
- [x] Displays all intermediate values within modules
- [ ] Advanced DeBug mode for orchestration
`4` OpenAPI Interface
- [x] The completions interface (aligned with GPT's chat mode interface)
- [x] CRUD operations for the knowledge base
- [ ] CRUD operations for conversations
`5` Operational Features
- [x] Share without requiring login
- [x] Easy embedding with Iframe
- [x] Customizable chat window embedding with features like default open, drag-and-drop
- [x] Centralizes conversation records for review and annotation
| **Features** | **Details** |
|--------------------------------------------|---------------------------------------------------|
| **Application Orchestration Features** | ✅ Offers a straightforward mode, eliminating the need for complex orchestration <br> ✅ Provides clear next-step instructions in dialogues <br> ✅ Facilitates workflow orchestration <br> ✅ Tracks references in source files <br> ✅ Encapsulates modules for enhanced reuse at multiple levels <br> ✅ Combines search and reordering functions <br> 🔜 Includes a tool module <br> 🔜 Integrates [Laf](https://github.com/labring/laf) for online HTTP module creation <br> 🔜 Plugin encapsulation capabilities |
| **Knowledge Base Features** | ✅ Allows for the mixed use of multiple databases <br> ✅ Keeps track of modifications and deletions in data chunks <br> ✅ Enables specific vector models for each knowledge base <br> ✅ Stores original source files <br> ✅ Supports direct input and segment-based QA import <br> ✅ Compatible with a variety of file formats: pdf, docx, txt, html, md, csv <br> ✅ Facilitates URL reading and bulk CSV importing <br> 🔜 Supports PPT and Excel file import <br> 🔜 Features a file reader <br> 🔜 Offers diverse data preprocessing options |
| **Application Debugging Features** | ✅ Enables targeted search testing within the knowledge base <br> ✅ Allows feedback, editing, and deletion during conversations <br> ✅ Presents the full context of interactions <br> ✅ Displays all intermediate values within modules <br> 🔜 Advanced Debug mode for orchestration |
| **OpenAPI Interface** | ✅ The completions interface (aligned with GPT's chat mode interface) <br> ✅ CRUD operations for the knowledge base <br> 🔜 CRUD operations for conversation |
| **Operational Features** | ✅ Share without requiring login <br> ✅ Easy embedding with Iframe <br> ✅ Customizable chat window embedding with features like default open, drag-and-drop <br> ✅ Centralizes conversation records for review and annotation |
<a href="#readme">
<a href="#FastGPT">
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
</a>
## 👨‍💻 Development
Project tech stack: NextJs + TS + ChakraUI + Mongo + Postgres (Vector plugin)
Project tech stack: NextJs + TS + ChakraUI + MongoDB + PostgreSQL (PG Vector plug-in)/Milvus
- **⚡ Deployment**
- **⚡ Fast Deployment**
> When using [Sealos](https://sealos.io) services, there is no need to purchase servers or domain names. It supports high concurrency and dynamic scaling, and the database application uses the kubeblocks database, which far exceeds the simple Docker container deployment in terms of IO performance.
<div align="center">
[![](https://cdn.jsdelivr.net/gh/labring-actions/templates@main/Deploy-on-Sealos.svg)](https://cloud.sealos.io/?openapp=system-fastdeploy%3FtemplateName%3Dfastgpt)
</div>
Give it a 2-4 minute wait after deployment as it sets up the database. Initially, it might be a tad slow since we're using the basic settings.
Give it a 2-4 minute wait after deployment as it sets up the database. Initially, it might be a too slow since we're using the basic settings.
[sealos one click deployment tutorial](https://doc.tryfastgpt.ai/docs/development/sealos/)
- [Getting Started with Local Development](https://doc.tryfastgpt.ai/docs/development)
- [Deploying FastGPT](https://doc.tryfastgpt.ai/docs/installation)
@@ -119,25 +82,7 @@ Project tech stack: NextJs + TS + ChakraUI + Mongo + Postgres (Vector plugin)
- [Configuring Multiple Models](https://doc.tryfastgpt.ai/docs/installation/reference/models)
- [Version Updates & Upgrades](https://doc.tryfastgpt.ai/docs/installation/upgrading)
## 🏘️ Community & support
+ 🌐 Visit the [FastGPT website](https://tryfastgpt.ai/) for full documentation and useful links.
+ 💬 Join our [Discord server](https://discord.gg/mp68xkZn2Q) is to chat with FastGPT developers and other FastGPT users. This is a good place to learn about FastGPT, ask questions, and share your experiences.
+ 🐞 Create [GitHub Issues](https://github.com/labring/FastGPT/issues/new/choose) for bug reports and feature requests.
<a href="#readme">
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
</a>
## 👀 Others
- [FastGPT FAQ](https://kjqvjse66l.feishu.cn/docx/HtrgdT0pkonP4kxGx8qcu6XDnGh)
- [Docker Deployment Tutorial Video](https://www.bilibili.com/video/BV1jo4y147fT/)
- [Official Account Integration Video Tutorial](https://www.bilibili.com/video/BV1xh4y1t7fy/)
- [FastGPT Knowledge Base Demo](https://www.bilibili.com/video/BV1Wo4y1p7i1/)
<a href="#readme">
<a href="#FastGPT">
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
</a>
@@ -148,7 +93,7 @@ Project tech stack: NextJs + TS + ChakraUI + Mongo + Postgres (Vector plugin)
- [One API: Multi-model management, supports Azure, Wenxin Yiyuan, etc.](https://github.com/songquanpeng/one-api)
- [TuShan: Build a backend management system in 5 minutes](https://github.com/msgbyte/tushan)
<a href="#readme">
<a href="#FastGPT">
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
</a>
@@ -156,10 +101,69 @@ Project tech stack: NextJs + TS + ChakraUI + Mongo + Postgres (Vector plugin)
- [luolinAI: Enterprise WeChat bot, ready to use](https://github.com/luolin-ai/FastGPT-Enterprise-WeChatbot)
<a href="#readme">
<a href="#FastGPT">
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
</a>
## 🏘️ Community & Support
+ 🌐 Visit the [FastGPT website](https://tryfastgpt.ai/) for full documentation and useful links.
+ 💬 Join our [Discord server](https://discord.gg/mp68xkZn2Q) is to chat with FastGPT developers and other FastGPT users. This is a good place to learn about FastGPT, ask questions, and share your experiences.
+ 🐞 Create [GitHub Issues](https://github.com/labring/FastGPT/issues/new/choose) for bug reports and feature requests.
<a href="#FastGPT">
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
</a>
## 👀 Others
- [FastGPT FAQ](https://kjqvjse66l.feishu.cn/docx/HtrgdT0pkonP4kxGx8qcu6XDnGh)
- [Docker Deployment Tutorial Video](https://www.bilibili.com/video/BV1jo4y147fT/)
- [Official Account Integration Video Tutorial](https://www.bilibili.com/video/BV1xh4y1t7fy/)
- [FastGPT Knowledge Base Demo](https://www.bilibili.com/video/BV1Wo4y1p7i1/)
<a href="#FastGPT">
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
</a>
## 🌱 Contributors
We welcome all forms of contributions. If you are interested in contributing code, you can check out our GitHub [Issues](https://github.com/labring/FastGPT/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) to show us your ideas.
<a href="https://github.com/labring/FastGPT/graphs/contributors" target="_blank">
<table>
<tr>
<th colspan="2">
<br><img src="https://contrib.rocks/image?repo=labring/FastGPT"><br><br>
</th>
</tr>
<tr>
<td>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=active&period=past_28_days&owner_id=102226726&repo_ids=605673387&image_size=2x3&color_scheme=dark">
<img alt="Active participants of labring - past 28 days" src="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=active&period=past_28_days&owner_id=102226726&repo_ids=605673387&image_size=2x3&color_scheme=light">
</picture>
</td>
<td rowspan="2">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-participants-growth/thumbnail.png?activity=new&period=past_28_days&owner_id=102226726&repo_ids=605673387&image_size=4x7&color_scheme=dark">
<img alt="New trends of labring" src="https://next.ossinsight.io/widgets/official/compose-org-participants-growth/thumbnail.png?activity=new&period=past_28_days&owner_id=102226726&repo_ids=605673387&image_size=4x7&color_scheme=light">
</picture>
</td>
</tr>
<tr>
<td>
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=new&period=past_28_days&owner_id=102226726&repo_ids=605673387&image_size=2x3&color_scheme=dark">
<img alt="New participants of labring - past 28 days" src="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=new&period=past_28_days&owner_id=102226726&repo_ids=605673387&image_size=2x3&color_scheme=light">
</picture>
</td>
</tr>
</table>
</a>
## 🌟 Star History
<a href="https://github.com/labring/FastGPT/stargazers" target="_blank" style="display: block" align="center">
@@ -169,3 +173,20 @@ Project tech stack: NextJs + TS + ChakraUI + Mongo + Postgres (Vector plugin)
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=labring/FastGPT&type=Date" />
</picture>
</a>
<a href="#FastGPT">
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
</a>
## 📄 Usage Agreement
This repository complies with the [FastGPT Open Source License](./LICENSE) open source agreement.
1. Direct commercial use as a backend service is allowed, but provision of SaaS services is not allowed.
2. Without commercial authorization, any form of commercial service must retain relevant copyright information.
3. For full details, please see [FastGPT Open Source License](./LICENSE)
4. Contact: Dennis@sealos.io , [click to view commercial version pricing strategy](https://doc.tryfastgpt.ai/docs/commercial)
<a href="#FastGPT">
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
</a>

View File

@@ -0,0 +1,5 @@
<svg t="1728884315234" class="icon" viewBox="0 0 1224 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4847" width="28" height="28" fill="currentColor">
<path d="M1224.146926 401.768509a50.444385 50.444385 0 0 0-23.813954-38.631991c-6.095363-3.741292-61.752335-36.782364-141.475481-43.949671a317.253146 317.253146 0 0 0-135.884563 16.982943L746.964061 25.579507A50.444385 50.444385 0 0 0 703.077446 0h-418.268027A50.444385 50.444385 0 0 0 248.027055 84.97777c3.236848 3.447033 296.360763 315.739814 426.969683 459.653442-59.734559 55.762064-103.558119 83.800735-127.666331 96.832201l-200.894764-140.823909a50.045034 50.045034 0 0 0-6.97814-4.098606L79.416697 314.205464A50.444385 50.444385 0 0 0 0.744475 364.124387c0.210185 1.177036 20.619142 118.607361 42.036988 237.635091C86.815207 847.297523 91.775572 859.656397 95.054457 867.874628c5.065457 12.611096 14.334613 24.549601 44.895503 44.538188a595.916337 595.916337 0 0 0 69.361029 38.337733c49.519571 23.603769 128.212812 54.437899 221.59798 67.25918a623.009175 623.009175 0 0 0 85.061845 5.948234c131.491697 0 290.055215-44.138837 418.373119-211.404011 73.564728-96.054517 118.250046-163.944252 154.086578-218.592335 44.033745-67.070014 70.622139-107.551633 118.838564-150.177139a50.444385 50.444385 0 0 0 16.877851-42.015969zM673.693591 100.88877L834.443032 384.638437a413.097477 413.097477 0 0 0-63.055481 59.356226c-8.743693 10.04684-17.256183 19.568218-25.579507 28.711263C656.248242 373.961042 497.033151 203.332909 401.188819 100.88877zM305.491617 882.125167c-59.86067-22.594881-102.065806-47.85911-118.523287-59.692523-10.299062-45.610132-39.935138-209.638457-65.829922-355.780044l391.238243 274.270325a48.132351 48.132351 0 0 0 6.725918 3.951477l189.166445 132.689752a398.300458 398.300458 0 0 1-155.410744 44.138837c-97.336645 7.713787-188.262649-17.277202-247.366653-39.577824z m698.654734-343.442189c-34.932737 53.197808-78.398982 119.385045-149.819824 212.496972a503.371908 503.371908 0 0 1-58.641598 64.33761l-158.185184-110.830518c35.31107-23.813953 81.152405-60.070855 135.905581-114.803013a48.342536 48.342536 0 0 0 14.944149-15.154334c18.790533-19.379051 38.568936-40.859952 59.272153-64.694924 57.086229-65.745849 124.009113-96.243683 198.540692-90.673782a247.639894 247.639894 0 0 1 38.589955 6.011289c-28.290893 33.62959-51.936698 69.63427-80.605924 113.3107z" p-id="4848"></path>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -1,7 +1,7 @@
---
weight: 1100
title: '商业版介绍'
description: 'FastGPT 商业版介绍'
title: '收费说明'
description: 'FastGPT 收费说明'
icon: 'shopping_cart'
draft: false
images: []

View File

@@ -4,7 +4,7 @@ description: 'FastGPT 线上版定价'
icon: 'currency_yen'
draft: false
toc: true
weight: 1200
weight: 1002
type: redirect
target: https://cloud.tryfastgpt.ai/price
---

View File

@@ -11,6 +11,6 @@ FastGPT 是一个由用户和贡献者参与推动的开源项目,如果您对
+ 📱 扫码加入社区微信交流群👇
<img width="400px" src="https://oss.laf.run/htr4n1-images/fastgpt-qr-code.jpg" class="medium-zoom-image" />
<img width="400px" src="https://oss.laf.run/otnvvf-imgs/fastgpt-feishu1.png" class="medium-zoom-image" />
+ 🐞 请将任何 FastGPT 的 Bug、问题和需求提交到 [GitHub Issue](https://github.com/labring/fastgpt/issues/new/choose)。

View File

@@ -0,0 +1,331 @@
---
title: '知识库基础原理介绍'
description: '本节详细介绍RAG模型的核心机制、应用场景及其在生成任务中的优势与局限性。'
icon: 'language'
draft: false
toc: true
weight: 106
---
[RAG文档](https://huggingface.co/docs/transformers/model_doc/rag)
# 1. 引言
随着自然语言处理NLP技术的迅猛发展生成式语言模型如GPT、BART等在多种文本生成任务中表现卓越尤其在语言生成和上下文理解方面。然而纯生成模型在处理事实类任务时存在一些固有的局限性。例如由于这些模型依赖于固定的预训练数据它们在回答需要最新或实时信息的问题时可能会出现“编造”信息的现象导致生成结果不准确或缺乏事实依据。此外生成模型在面对长尾问题和复杂推理任务时常因缺乏特定领域的外部知识支持而表现不佳难以提供足够的深度和准确性。
与此同时检索模型Retriever能够通过在海量文档中快速找到相关信息解决事实查询的问题。然而传统检索模型如BM25在面对模糊查询或跨域问题时往往只能返回孤立的结果无法生成连贯的自然语言回答。由于缺乏上下文推理能力检索模型生成的答案通常不够连贯和完整。
为了解决这两类模型的不足检索增强生成模型Retrieval-Augmented GenerationRAG应运而生。RAG通过结合生成模型和检索模型的优势实时从外部知识库中获取相关信息并将其融入生成任务中确保生成的文本既具备上下文连贯性又包含准确的知识。这种混合架构在智能问答、信息检索与推理、以及领域特定的内容生成等场景中表现尤为出色。
## 1.1 RAG的定义
RAG是一种将信息检索与生成模型相结合的混合架构。首先检索器从外部知识库或文档集中获取与用户查询相关的内容片段然后生成器基于这些检索到的内容生成自然语言输出确保生成的内容既信息丰富又具备高度的相关性和准确性。
# 2. RAG模型的核心机制
RAG 模型由两个主要模块构成检索器Retriever与生成器Generator。这两个模块相互配合确保生成的文本既包含外部的相关知识又具备自然流畅的语言表达。
## 2.1 检索器Retriever
检索器的主要任务是从一个外部知识库或文档集中获取与输入查询最相关的内容。在RAG中常用的技术包括
- 向量检索如BERT向量等它通过将文档和查询转化为向量空间中的表示并使用相似度计算来进行匹配。向量检索的优势在于能够更好地捕捉语义相似性而不仅仅是依赖于词汇匹配。
- 传统检索算法如BM25主要基于词频和逆文档频率TF-IDF的加权搜索模型来对文档进行排序和检索。BM25适用于处理较为简单的匹配任务尤其是当查询和文档中的关键词有直接匹配时。
RAG中检索器的作用是为生成器提供一个上下文背景使生成器能够基于这些检索到的文档片段生成更为相关的答案。
## 2.2 生成器Generator
生成器负责生成最终的自然语言输出。在RAG系统中常用的生成器包括
- BARTBART是一种序列到序列的生成模型专注于文本生成任务可以通过不同层次的噪声处理来提升生成的质量 。
- GPT系列GPT是一个典型的预训练语言模型擅长生成流畅自然的文本。它通过大规模数据训练能够生成相对准确的回答尤其在任务-生成任务中表现尤为突出 。
生成器在接收来自检索器的文档片段后,会利用这些片段作为上下文,并结合输入的查询,生成相关且自然的文本回答。这确保了模型的生成结果不仅仅基于已有的知识,还能够结合外部最新的信息。
## 2.3 RAG的工作流程
RAG模型的工作流程可以总结为以下几个步骤
1. 输入查询:用户输入问题,系统将其转化为向量表示。
2. 文档检索检索器从知识库中提取与查询最相关的文档片段通常使用向量检索技术或BM25等传统技术进行。
3. 生成答案:生成器接收检索器提供的片段,并基于这些片段生成自然语言答案。生成器不仅基于原始的用户查询,还会利用检索到的片段提供更加丰富、上下文相关的答案。
4. 输出结果:生成的答案反馈给用户,这个过程确保了用户能够获得基于最新和相关信息的准确回答。
# 3. RAG模型的工作原理
## 3.1 检索阶段
在RAG模型中用户的查询首先被转化为向量表示然后在知识库中执行向量检索。通常检索器采用诸如BERT等预训练模型生成查询和文档片段的向量表示并通过相似度计算如余弦相似度匹配最相关的文档片段。RAG的检索器不仅仅依赖简单的关键词匹配而是采用语义级别的向量表示从而在面对复杂问题或模糊查询时能够更加准确地找到相关知识。这一步骤对于最终生成的回答至关重要因为检索的效率和质量直接决定了生成器可利用的上下文信息 。
## 3.2 生成阶段
生成阶段是RAG模型的核心部分生成器负责基于检索到的内容生成连贯且自然的文本回答。RAG中的生成器如BART或GPT等模型结合用户输入的查询和检索到的文档片段生成更加精准且丰富的答案。与传统生成模型相比RAG的生成器不仅能够生成语言流畅的回答还可以根据外部知识库中的实际信息提供更具事实依据的内容从而提高了生成的准确性 。
## 3.3 多轮交互与反馈机制
RAG模型在对话系统中能够有效支持多轮交互。每一轮的查询和生成结果会作为下一轮的输入系统通过分析和学习用户的反馈逐步优化后续查询的上下文。通过这种循环反馈机制RAG能够更好地调整其检索和生成策略使得在多轮对话中生成的答案越来越符合用户的期望。此外多轮交互还增强了RAG在复杂对话场景中的适应性使其能够处理跨多轮的知识整合和复杂推理 。
# 4. RAG的优势与局限
## 4.1 优势
- 信息完整性RAG 模型结合了检索与生成技术使得生成的文本不仅语言自然流畅还能够准确利用外部知识库提供的实时信息。这种方法能够显著提升生成任务的准确性特别是在知识密集型场景下如医疗问答或法律意见生成。通过从知识库中检索相关文档RAG 模型避免了生成模型“编造”信息的风险,确保输出更具真实性 。
- 知识推理能力RAG 能够利用大规模的外部知识库进行高效检索并结合这些真实数据进行推理生成基于事实的答案。相比传统生成模型RAG 能处理更为复杂的任务特别是涉及跨领域或跨文档的推理任务。例如法律领域的复杂判例推理或金融领域的分析报告生成都可以通过RAG的推理能力得到优化 。
- 领域适应性强RAG 具有良好的跨领域适应性能够根据不同领域的知识库进行特定领域内的高效检索和生成。例如在医疗、法律、金融等需要实时更新和高度准确性的领域RAG 模型的表现优于仅依赖预训练的生成模型 。
## 4.2 局限
RAG检索增强生成模型通过结合检索器和生成器实现了在多种任务中知识密集型内容生成的突破性进展。然而尽管其具有较强的应用潜力和跨领域适应能力但在实际应用中仍然面临着一些关键局限限制了其在大规模系统中的部署和优化。以下是RAG模型的几个主要局限性
#### 4.2.1 检索器的依赖性与质量问题
RAG模型的性能很大程度上取决于检索器返回的文档质量。由于生成器主要依赖检索器提供的上下文信息如果检索到的文档片段不相关、不准确生成的文本可能出现偏差甚至产生误导性的结果。尤其在多模糊查询或跨领域检索的情况下检索器可能无法找到合适的片段这将直接影响生成内容的连贯性和准确性。
- 挑战当知识库庞大且内容多样时如何提高检索器在复杂问题下的精确度是一大挑战。当前的方法如BM25等在特定任务上有局限尤其是在面对语义模糊的查询时传统的关键词匹配方式可能无法提供语义上相关的内容。
- 解决途径引入混合检索技术如结合稀疏检索BM25与密集检索如向量检索。例如[Faiss](https://fael3z0zfze.feishu.cn/wiki/LULawsUufitGvWkDjx3cKJqHnle?from=from_copylink)的底层实现允许通过BERT等模型生成密集向量表示显著提升语义级别的匹配效果。通过这种方式检索器可以捕捉深层次的语义相似性减少无关文档对生成器的负面影响。
#### 4.2.2 生成器的计算复杂度与性能瓶颈
RAG模型将检索和生成模块结合尽管生成结果更加准确但也大大增加了模型的计算复杂度。尤其在处理大规模数据集或长文本时生成器需要处理来自多个文档片段的信息导致生成时间明显增加推理速度下降。对于实时问答系统或其他需要快速响应的应用场景这种高计算复杂度是一个主要瓶颈。
- 挑战当知识库规模扩大时检索过程中的计算开销以及生成器在多片段上的整合能力都会显著影响系统的效率。同时生成器也面临着资源消耗的问题尤其是在多轮对话或复杂生成任务中GPU和内存的消耗会成倍增加。
- 解决途径:使用模型压缩技术和知识蒸馏来减少生成器的复杂度和推理时间。此外,分布式计算与模型并行化技术的引入,如[DeepSpeed](https://www.deepspeed.ai/)和模型压缩工具,可以有效应对生成任务的高计算复杂度,提升大规模应用场景中的推理效率。
#### 4.2.3 知识库的更新与维护
RAG模型通常依赖于一个预先建立的外部知识库该知识库可能包含文档、论文、法律条款等各类信息。然而知识库内容的时效性和准确性直接影响到RAG生成结果的可信度。随着时间推移知识库中的内容可能过时导致生成的回答不能反映最新的信息。这对于需要实时信息的场景如医疗、金融尤其明显。
- 挑战:知识库需要频繁更新,但手动更新知识库既耗时又容易出错。如何在不影响系统性能的情况下实现知识库的持续自动更新是当前的一大挑战。
- 解决途径利用自动化爬虫和信息提取系统可以实现对知识库的自动化更新例如Scrapy等爬虫框架可以自动抓取网页数据并更新知识库。结合[动态索引技术](https://arxiv.org/pdf/2102.03315),可以帮助检索器实时更新索引,确保知识库反映最新信息。同时,结合增量学习技术,生成器可以逐步吸收新增的信息,避免生成过时答案。此外,动态索引技术也可以帮助检索器实时更新索引,确保知识库检索到的文档反映最新的内容。
#### 4.2.4 生成内容的可控性与透明度
RAG模型结合了检索与生成模块在生成内容的可控性和透明度上存在一定问题。特别是在复杂任务或多义性较强的用户输入情况下生成器可能会基于不准确的文档片段生成错误的推理导致生成的答案偏离实际问题。此外由于RAG模型的“黑箱”特性用户难以理解生成器如何利用检索到的文档信息这在高敏感领域如法律或医疗中尤为突出可能导致用户对生成内容产生不信任感。
- 挑战:模型透明度不足使得用户难以验证生成答案的来源和可信度。对于需要高可解释性的任务(如医疗问诊、法律咨询等),无法追溯生成答案的知识来源会导致用户不信任模型的决策。
- 解决途径为提高透明度可以引入可解释性AIXAI技术如LIME或SHAP[链接](https://github.com/marcotcr/lime)),为每个生成答案提供详细的溯源信息,展示所引用的知识片段。这种方法能够帮助用户理解模型的推理过程,从而增强对模型输出的信任。此外,针对生成内容的控制,可以通过加入规则约束或用户反馈机制,逐步优化生成器的输出,确保生成内容更加可信。
# 5. RAG整体改进方向
RAG模型的整体性能依赖于知识库的准确性和检索的效率因此在数据采集、内容分块、精准检索和回答生成等环节进行优化是提升模型效果的关键。通过加强数据来源、改进内容管理、优化检索策略及提升回答生成的准确性RAG模型能够更加适应复杂且动态的实际应用需求。
## 5.1 数据采集与知识库构建
RAG模型的核心依赖在于知识库的数据质量和广度知识库在某种程度上充当着“外部记忆”的角色。因此高质量的知识库不仅应包含广泛领域的内容更要确保数据来源的权威性、可靠性以及时效性。知识库的数据源应涵盖多种可信的渠道例如科学文献数据库如PubMed、IEEE Xplore、权威新闻媒体、行业标准和报告等这样才能提供足够的背景信息支持RAG在不同任务中的应用。此外为了确保RAG模型能够提供最新的回答知识库需要具备自动化更新的能力以避免数据内容老旧导致回答失准或缺乏现实参考。
- 挑战:
- 尽管数据采集是构建知识库的基础,但在实际操作中仍存在以下几方面的不足:
- 数据采集来源单一或覆盖不全
1. RAG模型依赖多领域数据的支持然而某些知识库过度依赖单一或有限的数据源通常集中在某些领域导致在多任务需求下覆盖不足。例如依赖医学领域数据而缺乏法律和金融数据会使RAG模型在跨领域问答中表现不佳。这种局限性削弱了RAG模型在处理不同主题或多样化查询时的准确性使得系统在应对复杂或跨领域任务时能力欠缺。
- 数据质量参差不齐
1. 数据源的质量差异直接影响知识库的可靠性。一些数据可能来源于非权威或低质量渠道存在偏见、片面或不准确的内容。这些数据若未经筛选录入知识库会导致RAG模型生成偏差或不准确的回答。例如在医学领域中如果引入未经验证的健康信息可能导致模型给出误导性回答产生负面影响。数据质量不一致的知识库会大大降低模型输出的可信度和适用性。
- 缺乏定期更新机制
1. 许多知识库缺乏自动化和频繁的更新机制特别是在信息变动频繁的领域如法律、金融和科技。若知识库长期未更新则RAG模型无法提供最新信息生成的回答可能过时或不具备实时参考价值。对于用户而言特别是在需要实时信息的场景下滞后的知识库会显著影响RAG模型的可信度和用户体验。
- 数据处理耗时且易出错
1. 数据的采集、清洗、分类和结构化处理是一项繁琐而复杂的任务尤其是当数据量巨大且涉及多种格式时。通常大量数据需要人工参与清洗和结构化而自动化处理流程也存在缺陷可能会产生错误或遗漏关键信息。低效和易出错的数据处理流程会导致知识库内容不准确、不完整进而影响RAG模型生成的答案的准确性和连贯性。
- 数据敏感性和隐私问题
1. 一些特定领域的数据(如医疗、法律、金融)包含敏感信息,未经适当的隐私保护直接引入知识库可能带来隐私泄露的风险。此外,某些敏感数据需要严格的授权和安全存储,以确保在知识库使用中避免违规或隐私泄漏。若未能妥善处理数据隐私问题,不仅会影响系统的合规性,还可能对用户造成严重后果。
- 改进:
- 针对以上不足,可以从以下几个方面进行改进,以提高数据采集和知识库构建的有效性:
- 扩大数据源覆盖范围,增加数据的多样性
1. 具体实施将知识库的数据源扩展至多个重要领域确保包含医疗、法律、金融等关键领域的专业数据库如PubMed、LexisNexis和金融数据库。使用具有开放许可的开源数据库和经过认证的数据确保来源多样化且权威性强。
2. 目的与效果通过跨领域数据覆盖知识库的广度和深度得以增强确保RAG模型能够在多任务场景下提供可靠回答。借助多领域合作机构的数据支持在应对多样化需求时将更具优势。
- 构建数据质量审查与过滤机制
1. 具体实施:采用自动化数据质量检测算法,如文本相似度检查、情感偏差检测等工具,结合人工审查过滤不符合标准的数据。为数据打分并构建“数据可信度评分”,基于来源可信度、内容完整性等指标筛选数据。
2. 目的与效果减少低质量、偏见数据的干扰确保知识库内容的可靠性。此方法保障了RAG模型输出的权威性特别在回答复杂或专业问题时用户能够获得更加精准且中立的答案。
- 实现知识库的自动化更新
1. 具体实施:引入自动化数据更新系统,如网络爬虫,定期爬取可信站点、行业数据库的最新数据,并利用变化检测算法筛选出与已有知识库重复或已失效的数据。更新机制可以结合智能筛选算法,仅采纳与用户查询高相关性或时效性强的数据。
2. 目的与效果:知识库保持及时更新,确保模型在快速变化的领域(如金融、政策、科技)中提供最新信息。用户体验将因此大幅提升,特别是在需要动态或最新信息的领域,输出的内容将更具时效性。
- 采用高效的数据清洗与分类流程
1. 具体实施使用自然语言处理技术如BERT等模型进行数据分类、实体识别和文本去噪结合去重算法清理重复内容。采用自动化的数据标注和分类算法将不同数据类型分领域存储。
2. 目的与效果数据清洗和分领域管理可以大幅提高数据处理的准确性减少低质量数据的干扰。此改进确保RAG模型的回答生成更流畅、上下文更连贯提升用户对生成内容的理解和信赖。
- 强化数据安全与隐私保护措施
1. 具体实施:针对医疗、法律等敏感数据,采用去标识化处理技术(如数据脱敏、匿名化等),并结合差分隐私保护。建立数据权限管理和加密存储机制,对敏感信息进行严格管控。
2. 目的与效果:在保护用户隐私的前提下,确保使用的数据合规、安全,适用于涉及个人或敏感数据的应用场景。此措施进一步保证了系统的法律合规性,并有效防止隐私泄露风险。
- 优化数据格式与结构的标准化
1. 具体实施建立统一的数据格式与标准编码格式例如使用JSON、XML或知识图谱形式组织结构化数据以便于检索系统在查询时高效利用。同时使用知识图谱等结构化工具将复杂数据间的关系进行系统化存储。
2. 目的与效果提高数据检索效率确保模型在生成回答时能够高效使用数据的关键信息。标准化的数据结构支持高效的跨领域检索并提高了RAG模型的内容准确性和知识关系的透明度。
- 用户反馈机制
1. 具体实施:通过用户反馈系统,记录用户对回答的满意度、反馈意见及改进建议。使用机器学习算法从反馈中识别知识库中的盲区与信息误差,反馈至数据管理流程中进行更新和优化。
2. 目的与效果利用用户反馈作为数据质量的调整依据帮助知识库持续优化内容。此方法不仅提升了RAG模型的实际效用还使知识库更贴合用户需求确保输出内容始终符合用户期望。
## 5.2 数据分块与内容管理
RAG模型的数据分块与内容管理是优化检索与生成流程的关键。合理的分块策略能够帮助模型高效定位目标信息并在回答生成时提供清晰的上下文支持。通常情况下将数据按段落、章节或主题进行分块不仅有助于检索效率的提升还能避免冗余数据对生成内容造成干扰。尤其在复杂、长文本中适当的分块策略可保证模型生成的答案具备连贯性、精确性避免出现内容跳跃或上下文断裂的问题。
- 挑战:
- 在实际操作中,数据分块与内容管理环节存在以下问题:
- 分块不合理导致的信息断裂
1. 部分文本过度切割或分块策略不合理,可能导致信息链条被打断,使得模型在回答生成时缺乏必要的上下文支持。这会使生成内容显得零散,不具备连贯性,影响用户对答案的理解。例如,将法律文本或技术文档随意切割成小段落会导致重要的上下文关系丢失,降低模型的回答质量。
- 冗余数据导致生成内容重复或信息过载
1. 数据集中往往包含重复信息,若不去重或优化整合,冗余数据可能导致生成内容的重复或信息过载。这不仅影响用户体验,还会浪费计算资源。例如,在新闻数据或社交媒体内容中,热点事件的描述可能重复出现,模型在生成回答时可能反复引用相同信息。
- 分块粒度选择不当影响检索精度
1. 如果分块粒度过细,模型可能因缺乏足够的上下文而生成不准确的回答;若分块过大,检索时将难以定位具体信息,导致回答内容冗长且含有无关信息。选择适当的分块粒度对生成答案的准确性和相关性至关重要,特别是在问答任务中需要精确定位答案的情况下,粗放的分块策略会明显影响用户的阅读体验和回答的可读性。
- 难以实现基于主题或内容逻辑的分块
1. 某些复杂文本难以直接按主题或逻辑结构进行分块,尤其是内容密集或领域专业性较强的数据。基于关键字或简单的规则切割往往难以识别不同主题和信息层次,导致模型在回答生成时信息杂乱。对内容逻辑或主题的错误判断,尤其是在医学、金融等场景下,会大大影响生成答案的准确度和专业性。
- 改进:
- 为提高数据分块和内容管理的有效性,可以从以下几方面进行优化:
- 引入NLP技术进行自动化分块和上下文分析
1. 具体实施借助自然语言处理NLP技术通过句法分析、语义分割等方式对文本进行逻辑切割以确保分块的合理性。可以基于BERT等预训练模型实现主题识别和上下文分析确保每个片段均具备完整的信息链避免信息断裂。
2. 目的与效果:确保文本切割基于逻辑或语义关系,避免信息链条被打断,生成答案时能够更具连贯性,尤其适用于长文本和复杂结构的内容,使模型在回答时上下文更加完整、连贯。
- 去重与信息整合,优化内容简洁性
1. 具体实施利用相似度算法如TF-IDF、余弦相似度识别冗余内容并结合聚类算法自动合并重复信息。针对内容频繁重复的情况可设置内容标记或索引避免生成时多次引用相同片段。
2. 目的与效果:通过去重和信息整合,使数据更具简洁性,避免生成答案中出现重复信息。减少冗余信息的干扰,使用户获得简明扼要的回答,增强阅读体验,同时提升生成过程的计算效率。
- 根据任务需求动态调整分块粒度
1. 具体实施:根据模型任务的不同,设置动态分块策略。例如,在问答任务中对关键信息较短的内容可采用小粒度分块,而在长文本或背景性内容中采用较大粒度。分块策略可基于查询需求或内容复杂度自动调整。
2. 目的与效果:分块粒度的动态调整确保模型在检索和生成时既能准确定位关键内容,又能为回答提供足够的上下文支持,提升生成内容的精准性和相关性,确保用户获取的信息既准确又不冗长。
- 引入基于主题的分块方法以提升上下文完整性
1. 具体实施使用主题模型如LDA或嵌入式文本聚类技术对文本内容按主题进行自动分类与分块。基于相同主题内容的聚合分块有助于模型识别不同内容层次尤其适用于复杂的学术文章或多章节的长篇报告。
2. 目的与效果:基于主题的分块确保同一主题的内容保持在一个片段内,提升模型在回答生成时的上下文连贯性。适用于主题复杂、层次清晰的内容场景,提高回答的专业性和条理性,使用户更容易理解生成内容的逻辑关系。
- 实时评估分块策略与内容呈现效果的反馈机制
1. 具体实施:通过用户反馈机制和生成质量评估系统实时监测生成内容的连贯性和准确性。对用户反馈中涉及分块效果差的部分进行重新分块,通过用户使用数据优化分块策略。
2. 目的与效果:用户反馈帮助识别不合理的分块和内容呈现问题,实现分块策略的动态优化,持续提升生成内容的质量和用户满意度。
## 5.3 检索优化
在RAG模型中检索模块决定了生成答案的相关性和准确性。有效的检索策略可确保模型获取到最适合的上下文片段使生成的回答更加精准且贴合查询需求。常用的混合检索策略如BM25和DPR结合能够在关键词匹配和语义检索方面实现优势互补BM25适合高效地处理关键字匹配任务而DPR在理解深层语义上表现更为优异。因此合理选用检索策略有助于在不同任务场景下达到计算资源和检索精度的平衡以高效提供相关上下文供生成器使用。
- 挑战:
- 检索优化过程中,仍面临以下不足之处:
- 检索策略单一导致的回答偏差
1. 当仅依赖BM25或DPR等单一技术时模型可能难以平衡关键词匹配与语义理解。BM25在处理具象关键字时表现良好但在面对复杂、含义丰富的语义查询时效果欠佳相反DPR虽然具备深度语义匹配能力但对高频关键词匹配的敏感度较弱。检索策略单一将导致模型难以适应复杂的用户查询回答中出现片面性或不够精准的情况。
- 检索效率与资源消耗的矛盾
1. 检索模块需要在短时间内处理大量查询而语义检索如DPR需要进行大量的计算和存储操作计算资源消耗高影响系统响应速度。特别是对于需要实时响应的应用场景DPR的计算复杂度往往难以满足实际需求因此在实时性和资源利用率上亟需优化。
- 检索结果的冗余性导致内容重复
1. 当检索策略未对结果进行去重或排序优化时RAG模型可能从知识库中检索出相似度高但内容冗余的文档片段。这会导致生成的回答中包含重复信息影响阅读体验同时增加无效信息的比例使用户难以迅速获取核心答案。
- 不同任务需求下检索策略的适配性差
1. RAG模型应用场景丰富但不同任务对检索精度、速度和上下文长度的需求不尽相同。固定检索策略难以灵活应对多样化的任务需求导致在应对不同任务时模型检索效果受限。例如面向精确性较高的医疗问答场景时检索策略应偏向语义准确性而在热点新闻场景中则应偏重检索速度。
- 改进:
- 针对上述不足,可以从以下几个方面优化检索模块:
- 结合BM25与DPR的混合检索策略
1. 具体实施采用BM25进行关键词初筛快速排除无关信息然后使用DPR进行深度语义匹配筛选。这样可以有效提升检索精度平衡关键词匹配和语义理解。
2. 目的与效果:通过多层筛选过程,确保检索结果在语义理解和关键词匹配方面互补,提升生成内容的准确性,特别适用于多意图查询或复杂的长文本检索。
- 优化检索效率,控制计算资源消耗
1. 具体实施利用缓存机制存储近期高频查询结果避免对相似查询的重复计算。同时可基于分布式计算结构将DPR的语义计算任务分散至多节点并行处理。
2. 目的与效果:缓存与分布式计算结合可显著减少检索计算压力,使系统能够在有限资源下提高响应速度,适用于高并发、实时性要求高的应用场景。
- 引入去重和排序优化算法
1. 具体实施:在检索结果中应用余弦相似度去重算法,筛除冗余内容,并基于用户偏好或时间戳对检索结果排序,以确保输出内容的丰富性和新鲜度。
2. 目的与效果:通过去重和优化排序,确保生成内容更加简洁、直接,减少重复信息的干扰,提高用户获取信息的效率和体验。
- 动态调整检索策略适应多任务需求
1. 具体实施:设置不同检索策略模板,根据任务类型自动调整检索权重、片段长度和策略组合。例如在医疗场景中偏向语义检索,而在金融新闻场景中更重视快速关键词匹配。
2. 目的与效果动态调整检索策略使RAG模型更加灵活能够适应不同任务需求确保检索的精准性和生成答案的上下文适配性显著提升多场景下的用户体验。
- 借助Haystack等检索优化框架
1. 具体实施在RAG模型中集成Haystack框架以实现更高效的检索效果并利用框架中的插件生态系统来增强检索模块的可扩展性和可调节性。
2. 目的与效果Haystack提供了检索和生成的整合接口有助于快速优化检索模块并适应复杂多样的用户需求在多任务环境中提供更稳定的性能表现。
## 5.4 回答生成与优化
在RAG模型中生成器负责基于检索模块提供的上下文为用户查询生成自然语言答案。生成内容的准确性和逻辑性直接决定了用户的体验因此优化生成器的表现至关重要。通过引入知识图谱等结构化信息生成器能够更准确地理解和关联上下文从而生成逻辑连贯、准确的回答。此外生成器的生成逻辑可结合用户反馈持续优化使回答风格和内容更加符合用户需求。
- 挑战:
- 在回答生成过程中RAG模型仍面临以下不足
- 上下文不充分导致的逻辑不连贯
1. 当生成器在上下文缺失或信息不完整的情况下生成回答时,生成内容往往不够连贯,特别是在处理复杂、跨领域任务时。这种缺乏上下文支持的问题,容易导致生成器误解或忽略关键信息,最终生成内容的逻辑性和完整性欠佳。如在医学场景中,若生成器缺少对病例或症状的全面理解,可能导致回答不准确或不符合逻辑,影响专业性和用户信任度。
- 专业领域回答的准确性欠佳
1. 在医学、法律等高专业领域中,生成器的回答需要高度的准确性。然而,生成器可能因缺乏特定知识而生成不符合领域要求的回答,出现内容偏差或理解错误,尤其在涉及专业术语和复杂概念时更为明显。如在法律咨询中,生成器可能未能正确引用相关法条或判例,导致生成的答案不够精确,甚至可能产生误导。
- 难以有效整合多轮用户反馈
1. 生成器缺乏有效机制来利用多轮用户反馈进行自我优化。用户反馈可能涉及回答内容的准确性、逻辑性以及风格适配等方面,但生成器在连续对话中缺乏充分的调节机制,难以持续调整生成策略和回答风格。如在客服场景中,生成器可能连续生成不符合用户需求的回答,降低了用户满意度。
- 生成内容的可控性和一致性不足
1. 在特定领域回答生成中,生成器的输出往往不具备足够的可控性和一致性。由于缺乏领域特定的生成规则和约束,生成内容的专业性和风格一致性欠佳,难以满足高要求的应用场景。如在金融报告生成中,生成内容需要确保一致的风格和术语使用,否则会影响输出的专业性和可信度。
- 改进:
- 针对以上不足,可以从以下方面优化回答生成模块:
- 引入知识图谱与结构化数据,增强上下文理解
1. 具体实施:结合知识图谱或知识库,将医学、法律等专业领域的信息整合到生成过程中。生成器在生成回答时,可以从知识图谱中提取关键信息和关联知识点,确保回答具备连贯的逻辑链条。
2. 目的与效果:知识图谱的引入提升了生成内容的连贯性和准确性,尤其在高专业性领域中,通过丰富的上下文理解,使生成器能够产生符合逻辑的回答。
- 设计专业领域特定的生成规则和约束
1. 具体实施:在生成模型中加入领域特定的生成规则和用语约束,特别针对医学、法律等领域的常见问答场景,设定回答模板、术语库等,以提高生成内容的准确性和一致性。
2. 目的与效果:生成内容更具领域特征,输出风格和内容的专业性增强,有效降低了生成器在专业领域中的回答偏差,满足用户对专业性和可信度的要求。
- 优化用户反馈机制,实现动态生成逻辑调整
1. 具体实施:利用机器学习算法对用户反馈进行分析,从反馈中提取生成错误或用户需求的调整信息,动态调节生成器的生成逻辑和策略。同时,在多轮对话中逐步适应用户的需求和风格偏好。
2. 目的与效果:用户反馈的高效利用能够帮助生成器优化生成内容,提高连续对话中的响应质量,提升用户体验,并使回答更贴合用户需求。
- 引入生成器与检索器的协同优化机制
1. 具体实施:通过协同优化机制,在生成器生成答案之前,允许生成器请求检索器补充缺失的上下文信息。生成器可基于回答需求自动向检索器发起上下文补充请求,从而获取完整的上下文。
2. 目的与效果:协同优化机制保障了生成器在回答时拥有足够的上下文支持,避免信息断层或缺失,提升回答的完整性和准确性。
- 实施生成内容的一致性检测和语义校正
1. 具体实施:通过一致性检测算法对生成内容进行术语、风格的统一管理,并结合语义校正模型检测生成内容是否符合用户需求的逻辑结构。在复杂回答生成中,使用语义校正对不符合逻辑的生成内容进行自动优化。
2. 目的与效果:生成内容具备高度一致性和逻辑性,特别是在多轮对话和专业领域生成中,保障了内容的稳定性和专业水准,提高了生成答案的可信度和用户满意度。
## 5.5 RAG流程
![](/imgs/RAG1.png)
1. 数据加载与查询输入:
1. 用户通过界面或API提交自然语言查询系统接收查询作为输入。
2. 输入被传递至向量化器利用向量化技术如BERT或Sentence Transformer将自然语言查询转换为向量表示。
2. 文档检索:
1. 向量化后的查询会传递给检索器,检索器通过在知识库中查找最相关的文档片段。
2. 检索可以基于稀疏检索技术如BM25或密集检索技术如DPR来提高匹配效率和精度。
3. 生成器处理与自然语言生成:
1. 检索到的文档片段作为生成器的输入生成器如GPT、BART或T5基于查询和文档内容生成自然语言回答。
2. 生成器结合了外部检索结果和预训练模型的语言知识,使回答更加精准、自然。
4. 结果输出:
1. 系统生成的答案通过API或界面返回给用户确保答案连贯且知识准确。
5. 反馈与优化:
1. 用户可以对生成的答案进行反馈,系统根据反馈优化检索与生成过程。
2. 通过微调模型参数或调整检索权重,系统逐步改进其性能,确保未来查询时更高的准确性与效率。
# 6. RAG相关案例整合
[各种分类领域下的RAG](https://github.com/hymie122/RAG-Survey)
# 7. RAG模型的应用
RAG模型已在多个领域得到广泛应用主要包括
## 7.1 智能问答系统中的应用
- RAG通过实时检索外部知识库生成包含准确且详细的答案避免传统生成模型可能产生的错误信息。例如在医疗问答系统中RAG能够结合最新的医学文献生成包含最新治疗方案的准确答案避免生成模型提供过时或错误的建议。这种方法帮助医疗专家快速获得最新的研究成果和诊疗建议提升医疗决策的质量。
- [医疗问答系统案例](https://www.apexon.com/blog/empowering-discovery-the-role-of-rag-architecture-generative-ai-in-healthcare-life-sciences/)
- ![](/imgs/RAG2.png)
- 用户通过Web应用程序发起查询
1. 用户在一个Web应用上输入查询请求这个请求进入后端系统启动了整个数据处理流程。
- 使用Azure AD进行身份验证
1. 系统通过Azure Active Directory (Azure AD) 对用户进行身份验证,确保只有经过授权的用户才能访问系统和数据。
- 用户权限检查:
1. 系统根据用户的组权限由Azure AD管理过滤用户能够访问的内容。这个步骤保证了用户只能看到他们有权限查看的信息。
- Azure AI搜索服务
1. 过滤后的用户查询被传递给Azure AI搜索服务该服务会在已索引的数据库或文档中查找与查询相关的内容。这个搜索引擎通过语义搜索技术检索最相关的信息。
- 文档智能处理:
1. 系统使用OCR光学字符识别和文档提取等技术处理输入的文档将非结构化数据转换为结构化、可搜索的数据便于Azure AI进行检索。
- 文档来源:
1. 这些文档来自预先存储的输入文档集合,这些文档在被用户查询之前已经通过文档智能处理进行了准备和索引。
- Azure Open AI生成响应
1. 在检索到相关信息后数据会被传递到Azure Open AI该模块利用自然语言生成NLG技术根据用户的查询和检索结果生成连贯的回答。
- 响应返回用户:
1. 最终生成的回答通过Web应用程序返回给用户完成整个查询到响应的流程。
- 整个流程展示了Azure AI技术的集成通过文档检索、智能处理以及自然语言生成来处理复杂的查询并确保了数据的安全和合规性。
## 7.2 信息检索与文本生成
- 文本生成RAG不仅可以检索相关文档还能根据这些文档生成总结、报告或文档摘要从而增强生成内容的连贯性和准确性。例如法律领域中RAG可以整合相关法条和判例生成详细的法律意见书确保内容的全面性和严谨性。这在法律咨询和文件生成过程中尤为重要可以帮助律师和法律从业者提高工作效率。
- [法律领域检索增强生成案例](https://www.apexon.com/blog/empowering-discovery-the-role-of-rag-architecture-generative-ai-in-healthcare-life-sciences/)
- 内容总结:
- 背景: 传统的大语言模型 (LLMs) 在生成任务中表现优异但在处理法律领域中的复杂任务时存在局限。法律文档具有独特的结构和术语标准的检索评估基准往往无法充分捕捉这些领域特有的复杂性。为了弥补这一不足LegalBench-RAG 旨在提供一个评估法律文档检索效果的专用基准。
- LegalBench-RAG 的结构:
1. ![](/imgs/RAG3.png)
2. 工作流程:
3. 用户输入问题Q: ?A: ?):用户通过界面输入查询问题,提出需要答案的具体问题。
4. 嵌入与检索模块Embed + Retrieve该模块接收到用户的查询后会对问题进行嵌入将其转化为向量并在外部知识库或文档中执行相似度检索。通过检索算法系统找到与查询相关的文档片段或信息。
5. 生成答案A基于检索到的最相关信息生成模型如GPT或类似的语言模型根据检索的结果生成连贯的自然语言答案。
6. 对比和返回结果:生成的答案会与之前的相关问题答案进行对比,并最终将生成的答案返回给用户。
7. 该基准基于 LegalBench 的数据集,构建了 6858 个查询-答案对,并追溯到其原始法律文档的确切位置。
8. LegalBench-RAG 侧重于精确地检索法律文本中的小段落,而非宽泛的、上下文不相关的片段。
9. 数据集涵盖了合同、隐私政策等不同类型的法律文档,确保涵盖多个法律应用场景。
- 意义: LegalBench-RAG 是第一个专门针对法律检索系统的公开可用的基准。它为研究人员和公司提供了一个标准化的框架,用于比较不同的检索算法的效果,特别是在需要高精度的法律任务中,例如判决引用、条款解释等。
- 关键挑战:
1. RAG 系统的生成部分依赖检索到的信息,错误的检索结果可能导致错误的生成输出。
2. 法律文档的长度和术语复杂性增加了模型检索和生成的难度。
- 质量控制: 数据集的构建过程确保了高质量的人工注释和文本精确性特别是在映射注释类别和文档ID到具体文本片段时进行了多次人工校验。
## 7.3 其它应用场景
RAG还可以应用于多模态生成场景如图像、音频和3D内容生成。例如跨模态应用如ReMoDiffuse和Make-An-Audio利用RAG技术实现不同数据形式的生成。此外在企业决策支持中RAG能够快速检索外部资源如行业报告、市场数据生成高质量的前瞻性报告从而提升企业战略决策的能力。
## 8 总结
本文档系统阐述了检索增强生成RAG模型的核心机制、优势与应用场景。通过结合生成模型与检索模型RAG解决了传统生成模型在面对事实性任务时的“编造”问题和检索模型难以生成连贯自然语言输出的不足。RAG模型能够实时从外部知识库获取信息使生成内容既包含准确的知识又具备流畅的语言表达适用于医疗、法律、智能问答系统等多个知识密集型领域。
在应用实践中RAG模型虽然有着信息完整性、推理能力和跨领域适应性等显著优势但也面临着数据质量、计算资源消耗和知识库更新等挑战。为进一步提升RAG的性能提出了针对数据采集、内容分块、检索策略优化以及回答生成的全面改进措施如引入知识图谱、优化用户反馈机制、实施高效去重算法等以增强模型的适用性和效率。
RAG在智能问答、信息检索与文本生成等领域展现了出色的应用潜力并在不断发展的技术支持下进一步拓展至多模态生成和企业决策支持等场景。通过引入混合检索技术、知识图谱以及动态反馈机制RAG能够更加灵活地应对复杂的用户需求生成具有事实支撑和逻辑连贯性的回答。未来RAG将通过增强模型透明性与可控性进一步提升在专业领域中的可信度和实用性为智能信息检索与内容生成提供更广泛的应用空间。

View File

@@ -42,7 +42,7 @@ FastGPT 采用了 RAG 中的 Embedding 方案构建知识库,要使用好 Fast
FastGPT 采用了`PostgresSQL``PG Vector`插件作为向量检索器,索引为`HNSW`。且`PostgresSQL`仅用于向量检索(该引擎可以替换成其它数据库),`MongoDB`用于其他数据的存取。
`MongoDB``dataset.datas`表中,会存储向量原数据的信息,同时有一个`indexes`字段会记录其对应的向量ID这是一个数组也就是说一组向量可以对应多组数据
`MongoDB``dataset.datas`表中,会存储向量原数据的信息,同时有一个`indexes`字段会记录其对应的向量ID这是一个数组也就是说一组数据可以对应多个向量
`PostgresSQL`的表中,设置一个`vector`字段用于存储向量。在检索时会先召回向量再根据向量的ID`MongoDB`中寻找原数据内容,如果对应了同一组原数据,则进行合并,向量得分取最高得分。

View File

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

View File

@@ -188,19 +188,22 @@ weight: 708
## 关于模型 logo
统一放置在项目的`public/imgs/model/xxx`目录中目前内置了以下几种如果有需要可以PR增加。默认头像为 Hugging face 的 logo~
统一放置在项目的`public/imgs/model/xxx`目录中目前内置了以下几种如果有需要可以PR增加。默认logo为 Hugging face 的 logo~
- /imgs/model/baichuan.svg - 百川
- /imgs/model/chatglm.svg - 智谱
- /imgs/model/calude.svg - calude
- /imgs/model/baichuan.svg - 百川智能
- /imgs/model/chatglm.svg - 智谱清言
- /imgs/model/claude.svg - claude
- /imgs/model/deepseek.svg - deepseek
- /imgs/model/doubao.svg - 火山豆包
- /imgs/model/ernie.svg - 文心一言
- /imgs/model/gemini.svg - gemini
- /imgs/model/huggingface.svg - Hugging face【默认logo】
- /imgs/model/minimax.svg - minimax
- /imgs/model/moonshot.svg - 月之暗面
- /imgs/model/openai.svg - OpenAI GPT
- /imgs/model/qwen.svg - 通义千问
- /imgs/model/sparkDesk.svg - 讯飞星火
- /imgs/model/yi.svg - 零一万物
- /imgs/model/gemini.svg - gemini
- /imgs/model/deepseek.svg - deepseek
- /imgs/model/minimax.svg - minimax
-
## 特殊模型
@@ -227,6 +230,27 @@ weight: 708
}
```
### ReRank 接入(硅基流动)
有免费的 `bge-reranker-v2-m3` 模型可以使用。
1. 注册硅基流动账号: https://siliconflow.cn/
2. 进入控制台,获取 API key: https://cloud.siliconflow.cn/account/ak
3. 修改 FastGPT 配置文件
```json
{
"reRankModels": [
{
"model": "BAAI/bge-reranker-v2-m3", // 这里的model需要对应 siliconflow 的模型名
"name": "BAAI/bge-reranker-v2-m3",
"requestUrl": "https://api.siliconflow.cn/v1/rerank",
"requestAuth": "siliconflow 上申请的 key"
}
]
}
```
### ReRank 接入Cohere
这个重排模型对中文不是很好,不如 bge 的好用。
@@ -239,7 +263,7 @@ weight: 708
"reRankModels": [
{
"model": "rerank-multilingual-v2.0", // 这里的model需要对应 cohere 的模型名
"name": "检索重排", // 随意
"name": "rerank-multilingual-v2.0",
"requestUrl": "https://api.cohere.ai/v1/rerank",
"requestAuth": "Coherer上申请的key"
}

View File

@@ -35,6 +35,8 @@ weight: 707
### Milvus版本
暂不推荐,部分系统存在精度丢失,等待修复。
对于千万级以上向量性能更优秀。
[点击查看 Milvus 官方推荐配置](https://milvus.io/docs/prerequisite-docker.md)
@@ -49,6 +51,8 @@ weight: 707
### zilliz cloud版本
暂不推荐,部分系统存在精度丢失,等待修复。
亿级以上向量首选。
由于向量库使用了 Cloud无需占用本地资源无需太关注。

View File

@@ -150,7 +150,7 @@ FastGPT 在`pnpm i`后会执行`postinstall`脚本,用于自动生成`ChakraUI
遇到困难了吗?有任何问题吗? 加入微信群与开发者和用户保持沟通。
<img width="400px" src="https://oss.laf.run/htr4n1-images/fastgpt-qr-code.jpg" class="medium-zoom-image" />
<img width="400px" src="https://oss.laf.run/otnvvf-imgs/fastgpt-feishu1.png" class="medium-zoom-image" />
## 代码结构说明

View File

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

View File

@@ -7,13 +7,15 @@ toc: true
weight: 852
---
# 发起对话
{{% alert icon="🤖 " context="success" %}}
* 该接口的 API Key 需使用`应用特定的 key`,否则会报错。
* 有些包调用时,`BaseUrl`需要添加`v1`路径有些不需要如果出现404情况可补充`v1`重试。
{{% /alert %}}
## 发起对话(简易应用和工作流)
## 请求简易应用和工作流
对话接口兼容`GPT`的接口!如果你的项目使用的是标准的`GPT`官方接口,可以直接通过修改`BaseUrl``Authorization`来访问 FastGpt 应用,不过需要注意下面几个规则:
@@ -24,12 +26,12 @@ weight: 852
### 请求
{{< tabs tabTotal="2" >}}
{{< tab tabName="请求示例" >}}
{{< tabs tabTotal="3" >}}
{{< tab tabName="基础请求示例" >}}
{{< markdownify >}}
```bash
curl --location --request POST 'https://api.tryfastgpt.ai/api/v1/chat/completions' \
curl --location --request POST 'http://localhost:3000/api/v1/chat/completions' \
--header 'Authorization: Bearer fastgpt-xxxxxx' \
--header 'Content-Type: application/json' \
--data-raw '{
@@ -42,8 +44,49 @@ curl --location --request POST 'https://api.tryfastgpt.ai/api/v1/chat/completion
},
"messages": [
{
"content": "导演是谁",
"role": "user"
"role": "user",
"content": "导演是谁"
}
]
}'
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="图片/文件请求示例" >}}
{{< markdownify >}}
*`messages`有部分区别,其他参数一致。
* 目前不支持上次文件,需上传到自己的对象存储中,获取对应的文件链接。
```bash
curl --location --request POST 'http://localhost:3000/api/v1/chat/completions' \
--header 'Authorization: Bearer fastgpt-xxxxxx' \
--header 'Content-Type: application/json' \
--data-raw '{
"chatId": "abcd",
"stream": false,
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "导演是谁"
},
{
"type": "image_url",
"image_url": {
"url": "图片链接"
}
},
{
"type": "file_url",
"name": "文件名",
"url": "文档链接,支持 txt md html word pdf ppt csv excel"
}
]
}
]
}'
@@ -269,7 +312,6 @@ event取值
{{< /tabs >}}
## 请求插件
插件的接口与对话接口一致,仅请求参数略有区别,有以下规定:
@@ -455,8 +497,730 @@ event取值
{{< /tab >}}
{{< /tabs >}}
## 使用案例
- [接入 NextWeb/ChatGPT web 等应用](/docs/course/openapi)
- [接入 onwechat](/docs/use-cases/onwechat)
- [接入 飞书](/docs/course/feishu)
# 对话 CRUD
{{% alert icon="🤖 " context="success" %}}
* 以下接口可使用任意`API Key`调用。
* 4.8.12 以上版本才能使用
{{% /alert %}}
**重要字段**
* chatId - 指一个应用下,某一个对话窗口的 ID
* dataId - 指一个对话窗口下,某一个对话记录的 ID
## 历史记录
### 获取某个应用历史记录
{{< tabs tabTotal="3" >}}
{{< tab tabName="请求示例" >}}
{{< markdownify >}}
```bash
curl --location --request POST 'http://localhost:3000/api/core/chat/getHistories' \
--header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"appId": "appId",
"offset": 0,
"pageSize": 20,
"source: "api"
}'
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="参数说明" >}}
{{< markdownify >}}
{{% alert icon=" " context="success" %}}
- appId - 应用 Id
- offset - 偏移量,即从第几条数据开始取
- pageSize - 记录数量
- source - 对话源
{{% /alert %}}
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="响应示例" >}}
{{< markdownify >}}
```json
{
"code": 200,
"statusText": "",
"message": "",
"data": {
"list": [
{
"chatId": "usdAP1GbzSGu",
"updateTime": "2024-10-13T03:29:05.779Z",
"appId": "66e29b870b24ce35330c0f08",
"customTitle": "",
"title": "你好",
"top": false
},
{
"chatId": "lC0uTAsyNBlZ",
"updateTime": "2024-10-13T03:22:19.950Z",
"appId": "66e29b870b24ce35330c0f08",
"customTitle": "",
"title": "测试",
"top": false
}
],
"total": 2
}
}
```
{{< /markdownify >}}
{{< /tab >}}
{{< /tabs >}}
### 修改某个对话的标题
{{< tabs tabTotal="3" >}}
{{< tab tabName="请求示例" >}}
{{< markdownify >}}
```bash
curl --location --request POST 'http://localhost:3000/api/core/chat/updateHistory' \
--header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"appId": "appId",
"chatId": "chatId",
"customTitle": "自定义标题"
}'
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="参数说明" >}}
{{< markdownify >}}
{{% alert icon=" " context="success" %}}
- appId - 应用 Id
- chatId - 历史记录 Id
- customTitle - 自定义对话名
{{% /alert %}}
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="响应示例" >}}
{{< markdownify >}}
```json
{
"code": 200,
"statusText": "",
"message": "",
"data": null
}
```
{{< /markdownify >}}
{{< /tab >}}
{{< /tabs >}}
### 置顶 / 取消置顶
{{< tabs tabTotal="3" >}}
{{< tab tabName="请求示例" >}}
{{< markdownify >}}
```bash
curl --location --request POST 'http://localhost:3000/api/core/chat/updateHistory' \
--header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"appId": "appId",
"chatId": "chatId",
"top": true
}'
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="参数说明" >}}
{{< markdownify >}}
{{% alert icon=" " context="success" %}}
- appId - 应用Id
- chatId - 历史记录 Id
- top - 是否置顶ture 置顶false 取消置顶
{{% /alert %}}
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="响应示例" >}}
{{< markdownify >}}
```json
{
"code": 200,
"statusText": "",
"message": "",
"data": null
}
```
{{< /markdownify >}}
{{< /tab >}}
{{< /tabs >}}
### 删除某个历史记录
{{< tabs tabTotal="3" >}}
{{< tab tabName="请求示例" >}}
{{< markdownify >}}
```bash
curl --location --request DELETE 'http://localhost:3000/api/core/chat/delHistory?chatId={{chatId}}&appId={{appId}}' \
--header 'Authorization: Bearer {{apikey}}'
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="参数说明" >}}
{{< markdownify >}}
{{% alert icon=" " context="success" %}}
- appId - 应用 Id
- chatId - 历史记录 Id
{{% /alert %}}
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="响应示例" >}}
{{< markdownify >}}
```json
{
"code": 200,
"statusText": "",
"message": "",
"data": null
}
```
{{< /markdownify >}}
{{< /tab >}}
{{< /tabs >}}
### 清空所有历史记录
{{< tabs tabTotal="3" >}}
{{< tab tabName="请求示例" >}}
{{< markdownify >}}
```bash
curl --location --request DELETE 'http://localhost:3000/api/core/chat/clearHistories?appId={{appId}}' \
--header 'Authorization: Bearer {{apikey}}'
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="参数说明" >}}
{{< markdownify >}}
{{% alert icon=" " context="success" %}}
- appId - 应用 Id
{{% /alert %}}
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="响应示例" >}}
{{< markdownify >}}
```json
{
"code": 200,
"statusText": "",
"message": "",
"data": null
}
```
{{< /markdownify >}}
{{< /tab >}}
{{< /tabs >}}
## 对话记录
指的是某个 chatId 下的对话记录操作。
### 获取单个对话初始化信息
{{< tabs tabTotal="3" >}}
{{< tab tabName="请求示例" >}}
{{< markdownify >}}
```bash
curl --location --request GET 'http://localhost:3000/api/core/chat/init?appId={{appId}}&chatId={{chatId}}' \
--header 'Authorization: Bearer {{apikey}}'
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="参数说明" >}}
{{< markdownify >}}
{{% alert icon=" " context="success" %}}
- appId - 应用 Id
- chatId - 历史记录 Id
{{% /alert %}}
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="响应示例" >}}
{{< markdownify >}}
```json
{
"code": 200,
"statusText": "",
"message": "",
"data": {
"chatId": "sPVOuEohjo3w",
"appId": "66e29b870b24ce35330c0f08",
"variables": {
},
"app": {
"chatConfig": {
"questionGuide": true,
"ttsConfig": {
"type": "web"
},
"whisperConfig": {
"open": false,
"autoSend": false,
"autoTTSResponse": false
},
"chatInputGuide": {
"open": false,
"textList": [
],
"customUrl": ""
},
"instruction": "",
"variables": [
],
"fileSelectConfig": {
"canSelectFile": true,
"canSelectImg": true,
"maxFiles": 10
},
"_id": "66f1139aaab9ddaf1b5c596d",
"welcomeText": ""
},
"chatModels": [
"GPT-4o-mini"
],
"name": "测试",
"avatar": "/imgs/app/avatar/workflow.svg",
"intro": "",
"type": "advanced",
"pluginInputs": [
]
}
}
}
```
{{< /markdownify >}}
{{< /tab >}}
{{< /tabs >}}
### 获取对话记录列表
{{< tabs tabTotal="3" >}}
{{< tab tabName="请求示例" >}}
{{< markdownify >}}
```bash
curl --location --request POST 'http://localhost:3000/api/core/chat/getPaginationRecords' \
--header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"appId": "appId",
"chatId": "chatId",
"offset": 0,
"pageSize": 10,
"loadCustomFeedbacks": true
}'
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="参数说明" >}}
{{< markdownify >}}
{{% alert icon=" " context="success" %}}
- appId - 应用 Id
- chatId - 历史记录 Id
- offset - 偏移量
- pageSize - 记录数量
- loadCustomFeedbacks - 是否读取自定义反馈(可选)
{{% /alert %}}
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="响应示例" >}}
{{< markdownify >}}
```json
{
"code": 200,
"statusText": "",
"message": "",
"data": {
"list": [
{
"_id": "670b84e6796057dda04b0fd2",
"dataId": "jzqdV4Ap1u004rhd2WW8yGLn",
"obj": "Human",
"value": [
{
"type": "text",
"text": {
"content": "你好"
}
}
],
"customFeedbacks": [
]
},
{
"_id": "670b84e6796057dda04b0fd3",
"dataId": "x9KQWcK9MApGdDQH7z7bocw1",
"obj": "AI",
"value": [
{
"type": "text",
"text": {
"content": "你好!有什么我可以帮助你的吗?"
}
}
],
"customFeedbacks": [
],
"llmModuleAccount": 1,
"totalQuoteList": [
],
"totalRunningTime": 2.42,
"historyPreviewLength": 2
}
],
"total": 2
}
}
```
{{< /markdownify >}}
{{< /tab >}}
{{< /tabs >}}
### 获取单个对话记录运行详情
{{< tabs tabTotal="3" >}}
{{< tab tabName="请求示例" >}}
{{< markdownify >}}
```bash
curl --location --request GET 'http://localhost:3000/api/core/chat/getResData?appId={{appId}}&chatId={{chatId}}&dataId={{dataId}}' \
--header 'Authorization: Bearer {{apikey}}'
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="参数说明" >}}
{{< markdownify >}}
{{% alert icon=" " context="success" %}}
- appId - 应用 Id
- chatId - 对话 Id
- dataId - 对话记录 Id
{{% /alert %}}
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="响应示例" >}}
{{< markdownify >}}
```json
{
"code": 200,
"statusText": "",
"message": "",
"data": [
{
"id": "mVlxkz8NfyfU",
"nodeId": "448745",
"moduleName": "common:core.module.template.work_start",
"moduleType": "workflowStart",
"runningTime": 0
},
{
"id": "b3FndAdHSobY",
"nodeId": "z04w8JXSYjl3",
"moduleName": "AI 对话",
"moduleType": "chatNode",
"runningTime": 1.22,
"totalPoints": 0.02475,
"model": "GPT-4o-mini",
"tokens": 75,
"query": "测试",
"maxToken": 2000,
"historyPreview": [
{
"obj": "Human",
"value": "你好"
},
{
"obj": "AI",
"value": "你好!有什么我可以帮助你的吗?"
},
{
"obj": "Human",
"value": "测试"
},
{
"obj": "AI",
"value": "测试成功!请问你有什么具体的问题或者需要讨论的话题吗?"
}
],
"contextTotalLen": 4
}
]
}
```
{{< /markdownify >}}
{{< /tab >}}
{{< /tabs >}}
### 删除对话记录
{{< tabs tabTotal="3" >}}
{{< tab tabName="请求示例" >}}
{{< markdownify >}}
```bash
curl --location --request DELETE 'http://localhost:3000/api/core/chat/item/delete?contentId={{contentId}}&chatId={{chatId}}&appId={{appId}}' \
--header 'Authorization: Bearer {{apikey}}'
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="参数说明" >}}
{{< markdownify >}}
{{% alert icon=" " context="success" %}}
- appId - 应用 Id
- chatId - 历史记录 Id
- contentId - 对话记录 Id
{{% /alert %}}
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="响应示例" >}}
{{< markdownify >}}
```json
{
"code": 200,
"statusText": "",
"message": "",
"data": null
}
```
{{< /markdownify >}}
{{< /tab >}}
{{< /tabs >}}
### 点赞 / 取消点赞
{{< tabs tabTotal="3" >}}
{{< tab tabName="请求示例" >}}
{{< markdownify >}}
```bash
curl --location --request POST 'http://localhost:3000/api/core/chat/feedback/updateUserFeedback' \
--header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"appId": "appId",
"chatId": "chatId",
"dataId": "dataId",
"userGoodFeedback": "yes"
}'
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="参数说明" >}}
{{< markdownify >}}
{{% alert icon=" " context="success" %}}
- appId - 应用 Id
- chatId - 历史记录 Id
- dataId - 对话记录 Id
- userGoodFeedback - 用户点赞时的信息(可选),取消点赞时不填此参数即可
{{% /alert %}}
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="响应示例" >}}
{{< markdownify >}}
```json
{
"code": 200,
"statusText": "",
"message": "",
"data": null
}
```
{{< /markdownify >}}
{{< /tab >}}
{{< /tabs >}}
### 点踩 / 取消点踩
{{< tabs tabTotal="3" >}}
{{< tab tabName="请求示例" >}}
{{< markdownify >}}
```bash
curl --location --request POST 'http://localhost:3000/api/core/chat/feedback/updateUserFeedback' \
--header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"appId": "appId",
"chatId": "chatId",
"dataId": "dataId",
"userBadFeedback": "yes"
}'
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="参数说明" >}}
{{< markdownify >}}
{{% alert icon=" " context="success" %}}
- appId - 应用 Id
- chatId - 历史记录 Id
- dataId - 对话记录 Id
- userBadFeedback - 用户点踩时的信息(可选),取消点踩时不填此参数即可
{{% /alert %}}
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="响应示例" >}}
{{< markdownify >}}
```json
{
"code": 200,
"statusText": "",
"message": "",
"data": null
}
```
{{< /markdownify >}}
{{< /tab >}}
{{< /tabs >}}
## 猜你想问
{{< tabs tabTotal="3" >}}
{{< tab tabName="请求示例" >}}
{{< markdownify >}}
```bash
curl --location --request POST 'http://localhost:3000/api/core/ai/agent/createQuestionGuide' \
--header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"messages":[
{
"role": "user",
"content": "你好"
},
{
"role": "assistant",
"content": "你好!有什么我可以帮助你的吗?"
}
]
}'
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="参数说明" >}}
{{< markdownify >}}
{{% alert icon=" " context="success" %}}
- messages - 对话消息,提供给 AI 的消息记录
{{% /alert %}}
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="响应示例" >}}
{{< markdownify >}}
```json
{
"code": 200,
"statusText": "",
"message": "",
"data": [
"你对AI有什么看法",
"想了解AI的应用吗",
"你希望AI能做什么"
]
}
```
{{< /markdownify >}}
{{< /tab >}}
{{< /tabs >}}

View File

@@ -22,7 +22,7 @@ weight: 853
**新例子**
```bash
curl --location --request POST 'https://api.tryfastgpt.ai/api/support/wallet/usage/createTrainingUsage' \
curl --location --request POST 'http://localhost:3000/api/support/wallet/usage/createTrainingUsage' \
--header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \
--data-raw '{
@@ -34,7 +34,7 @@ curl --location --request POST 'https://api.tryfastgpt.ai/api/support/wallet/usa
**x例子**
```bash
curl --location --request POST 'https://api.tryfastgpt.ai/api/support/wallet/bill/createTrainingBill' \
curl --location --request POST 'http://localhost:3000/api/support/wallet/bill/createTrainingBill' \
--header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \
--data-raw '{
@@ -991,7 +991,7 @@ curl --location --request DELETE 'http://localhost:3000/api/core/dataset/collect
{{< markdownify >}}
```bash
curl --location --request POST 'https://api.tryfastgpt.ai/api/core/dataset/data/pushData' \
curl --location --request POST 'https://api.fastgpt.in/api/core/dataset/data/pushData' \
--header 'Authorization: Bearer apikey' \
--header 'Content-Type: application/json' \
--data-raw '{
@@ -1093,6 +1093,22 @@ A2:
{{< tab tabName="请求示例" >}}
{{< markdownify >}}
**4.8.11+**
```bash
curl --location --request POST 'http://localhost:3000/api/core/dataset/data/v2/list' \
--header 'Authorization: Bearer {{authorization}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"offset": 0,
"pageSize": 10,
"collectionId":"65abd4ac9d1448617cba6171",
"searchText":""
}'
```
**4.6.7+**
```bash
curl --location --request POST 'http://localhost:3000/api/core/dataset/data/list' \
--header 'Authorization: Bearer {{authorization}}' \
@@ -1112,10 +1128,13 @@ curl --location --request POST 'http://localhost:3000/api/core/dataset/data/list
{{< markdownify >}}
{{% alert icon=" " context="success" %}}
- pageNum: 偏移量(选填)
- pageNum: 页码(选填)
- pageSize: 每页数量最大30选填
- collectionId: 集合的ID必填
- searchText: 模糊搜索词(选填)
{{% /alert %}}
{{< /markdownify >}}
@@ -1328,7 +1347,7 @@ curl --location --request DELETE 'http://localhost:3000/api/core/dataset/data/de
{{< markdownify >}}
```bash
curl --location --request POST 'https://api.tryfastgpt.ai/api/core/dataset/searchTest' \
curl --location --request POST 'https://api.fastgpt.in/api/core/dataset/searchTest' \
--header 'Authorization: Bearer fastgpt-xxxxx' \
--header 'Content-Type: application/json' \
--data-raw '{

View File

@@ -7,6 +7,15 @@ toc: true
weight: 827
---
## 修改商业版环境变量
增加 oneapi 地址和令牌。
```
OPENAI_BASE_URL=http://oneapi:3000/v1
CHAT_API_KEY=sk-fastgpt
```
## 初始化脚本
从任意终端,发起 1 个 HTTP 请求。其中 {{rootkey}} 替换成环境变量里的 `rootkey`{{host}} 替换成自己域名

View File

@@ -24,8 +24,8 @@ STORE_LOG_LEVEL=warn
### 3. 修改镜像tag
- 更新 FastGPT 镜像 tag: v4.8.10-fix2
- 更新 FastGPT 商业版镜像 tag: v4.8.10-fix
- 更新 FastGPT 镜像 tag: v4.8.10
- 更新 FastGPT 商业版镜像 tag: v4.8.10
- Sandbox 镜像,可以不更新
## 4. 执行初始化

View File

@@ -1,5 +1,5 @@
---
title: 'V4.8.11进行中'
title: 'V4.8.11商业版初始化'
description: 'FastGPT V4.8.11 更新说明'
icon: 'upgrade'
draft: false
@@ -21,7 +21,7 @@ weight: 813
"name": "o1-mini",
"avatar": "/imgs/model/openai.svg",
"maxContext": 125000,
"maxResponse": 4000,
"maxResponse": 65000,
"quoteMaxToken": 120000,
"maxTemperature": 1.2,
"charsPointsPrice": 0,
@@ -50,7 +50,7 @@ weight: 813
"name": "o1-preview",
"avatar": "/imgs/model/openai.svg",
"maxContext": 125000,
"maxResponse": 4000,
"maxResponse": 32000,
"quoteMaxToken": 120000,
"maxTemperature": 1.2,
"charsPointsPrice": 0,
@@ -80,29 +80,70 @@ weight: 813
### 3. 修改镜像 tag 并重启
- 更新 FastGPT 镜像 tag: v4.8.11-fix
- 更新 FastGPT 商业版镜像 tag: v4.8.11
- 更新 FastGPT Sandbox 镜像 tag: v4.8.11
### 4. 商业版初始化
从任意终端,发起 1 个 HTTP 请求。其中 {{rootkey}} 替换成环境变量里的 `rootkey`{{host}} 替换成**FastGPT 商业版域名**。
```bash
curl --location --request POST 'https://{{host}}/api/admin/init/4811' \
--header 'rootkey: {{rootkey}}' \
--header 'Content-Type: application/json'
```
会初始化团队成员组。
## V4.8.11 更新说明
1. 新增 - 表单输入节点,允许用户在工作流中让用户输入一些信息。
2. 新增 - 循环运行节点,可传入数组进行批量调用,目前最多支持 50 长度的数组串行执行。
3. 新增 - 节点支持折叠。
4. 新增 - 聊天记录滚动加载,不再只加载 30 条
5. 新增 - 工作流增加触摸板优先模式,可以通过工作流右下角按键进行切换
6. 新增 - 沙盒增加字符串转 base64 全局方法(全局变量 strToBase64)
7. 新增 - 支持 Openai o1 模型,需增加模型的 `defaultConfig` 配置,覆盖 `temperature``max_tokens``stream`配置o1 不支持 stream 模式, 详细可重新拉取 `config.json` 配置文件查看
8. 新增 - AI 对话节点知识库引用,支持配置 role=system 和 role=user已配置的过自定义提示词的节点将会保持 user 模式,其余用户将转成 system 模式。
9. 新增 - 插件支持上传系统文件
10. 新增 - 插件输出,支持指定字段作为工具响应
11. 新增 - 支持工作流嵌套子应用时,可以设置`非流模式`,同时简易模式也可以选择工作流作为插件了,简易模式调用子应用时,都将强制使用非流模式
12. 新增 - 调试模式下,子应用调用,支持返回详细运行数据
13. 新增 - 保留所有模式下子应用嵌套调用的日志
14. 优化 - 工作流嵌套层级限制 20 层,避免因编排不合理导致的无限死循环
15. 优化 - 工作流 handler 性能优化
16. 优化 - 工作流快捷键,避免调试测试时也会触发复制和回退
17. 优化 - 流输出,切换浏览器 Tab 后仍可以继续输出
18. 优化 - 完善外部文件知识库相关 API
19. 修复 - 知识库选择权限问题
20. 修复 - 空 chatId 发起对话,首轮携带用户选择时会异常
21. 修复 - createDataset 接口intro 为赋值
22. 修复 - 对话框渲染性能问题。
4. 新增 - 简易模式支持新的历史记录模式,可记录本地变更记录
5. 新增 - 聊天记录滚动加载,不再只加载 30 条
6. 新增 - 工作流增加触摸板优先模式,可以通过工作流右下角按键进行切换
7. 新增 - 沙盒增加字符串转 base64 全局方法(全局变量 strToBase64)
8. 新增 - 支持 Openai o1 模型,需增加模型的 `defaultConfig` 配置,覆盖 `temperature``max_tokens``stream`配置o1 不支持 stream 模式。
9. 新增 - AI 对话节点知识库引用,支持配置 role=system 和 role=user已配置的过自定义提示词的节点将会保持 user 模式,其余用户将转成 system 模式
10. 新增 - 插件支持上传系统文件
11. 新增 - 插件输出,支持指定字段作为工具响应
12. 新增 - 支持工作流嵌套子应用时,可以设置`非流模式`,同时简易模式也可以选择工作流作为插件了,简易模式调用子应用时,都将强制使用非流模式
13. 新增 - 调试模式下子应用调用,支持返回详细运行数据
14. 新增 - 保留所有模式下子应用嵌套调用的日志
15. 新增 - 对话日志显示成员
16. 新增 - 商业版支持后台配置 AI 生成文案提示
17. 新增 - Jest 单测框架
18. 新增 - 工具调用参数节点,可以配合工具调用完全自由声明参数。
19. 新增 - BI 图表插件
20. 新增 - Surya OCR 识别模块示例
21. 新增 - 工作流右键新增注释
22. 商业版新增 - 团队成员组。
23. 优化 - 工作流嵌套层级限制 20 层,避免因编排不合理导致的无限死循环。
24. 优化 - 工作流 handler 性能优化。
25. 优化 - 工作流快捷键,避免调试测试时也会触发复制和回退。
26. 优化 - 工作流复制时,名字去掉多余“#”。
27. 优化 - 流输出,切换浏览器 Tab 后仍可以继续输出。
28. 优化 - 完善外部文件知识库相关 API 。
29. 优化 - 修改 config.json 的地址。
30. 优化 - 正确处理//开头的超链接。
31. 优化 - 工作流 Textarea 滚轮可以正常滚动而不是缩放。
32. 优化 - 去除部分输入框前后空格。
33. 优化 - 工作流返回时,跳转到上一次记忆的 Tab 。
34. 优化 - 工作流画布禁止触摸板缩放浏览器。
35. 优化 - 工作流部分节点会自动选择用户问题作为初始值。
36. 优化 - Prompt Editor 支持动态增高。
37. 优化 - 自动补全工具描述。
38. 优化 - 文档说明 configuration.md 。
39. 优化 - IOS safari 浏览器语音输入不准确。
40. 修复 - 知识库选择权限问题。
41. 修复 - 空 chatId 发起对话,首轮携带用户选择时会异常。
42. 修复 - createDataset 接口intro 未赋值。
43. 修复 - 对话框渲染性能问题。
44. 修复 - Rerank 文档地址。
45. 修复 - Stream 模式下使用 toolChoice,toolCall 的function 和type 可能为 null 。
46. 修复 - 站点同步自定义分割符未同步。
47. 修复 - 工具调用历史记录存储问题。
48. 修复 - 对话页面可能无限重定向。
49. 修复 - 全局变量在工具调用中未持久传递。

View File

@@ -0,0 +1,68 @@
---
title: 'V4.8.12(需要初始化)'
description: 'FastGPT V4.8.12 更新说明'
icon: 'upgrade'
draft: false
toc: true
weight: 812
---
## 更新指南
### 1. 做好数据备份
### 2. 修改镜像
- 更新 FastGPT 镜像 tag: v4.8.12
- 更新 FastGPT 管理端镜像 tag: v4.8.12 fastgpt-pro镜像
- Sandbox 镜像,可以不更新
### 3. 商业版执行初始化
从任意终端,发起 1 个 HTTP 请求。其中 {{rootkey}} 替换成环境变量里的 `rootkey`{{host}} 替换成**FastGPT 管理端域名**。
```bash
curl --location --request POST 'https://{{host}}/api/admin/init/4812' \
--header 'rootkey: {{rootkey}}' \
--header 'Content-Type: application/json'
```
会初始化应用和知识库的成员组数据。
### 4. 重构 Milvus 数据
由于 js int64 精度丢失问题,之前私有化使用 milvus 或者 zilliz 的用户,如果存在数据精度丢失的问题,需要重构 Milvus 数据。(可以查看 dataset_datas 表中indexes 中的 dataId 是否末尾精度丢失)。使用 PG 的用户不需要操作。
从任意终端,发起 1 个 HTTP 请求。其中 {{rootkey}} 替换成环境变量里的 `rootkey`{{host}} 替换成**FastGPT 主域名**。
```bash
curl --location --request POST 'https://{{host}}/api/admin/resetMilvus' \
--header 'rootkey: {{rootkey}}' \
--header 'Content-Type: application/json'
```
## 更新说明
1. 新增 - 全局变量支持数字类型,支持配置默认值和部分输入框参数。
2. 新增 - 插件自定义输入,文本输入框、数字输入框、选择框、开关,默认都支持作为变量引用。
3. 新增 - FE_DOMAIN 环境变量,配置该环境变量后,上传文件/图片会补全后缀后得到完整地址。(可解决 docx 文件图片链接,有时模型会伪造图片域名)
4. 新增 - 工具调用支持使用交互节点
5. 新增 - Debug 模式支持输入全局变量
6. 新增 - chat OpenAPI 文档
7. 新增 - wiki 搜索插件
8. 新增 - Google 搜索插件
9. 新增 - 数据库连接和操作插件
10. 新增 - Cookie 隐私协议提示
11. 新增 - HTTP 节点支持 JSONPath 表达式
12. 新增 - 应用和知识库支持成员组配置权限
13. 优化 - 循环节点支持选择外部节点的变量
14. 优化 - Docx 文件读取中, HTML to Markdown 优化,提高速度和大幅度降低内存消耗。
15. 修复 - 文件后缀判断,去除 query 影响。
16. 修复 - AI 响应为空时,会造成 LLM 历史记录合并。
17. 修复 - 用户交互节点未阻塞流程。
18. 修复 - 新建 APP有时候会导致空指针报错。
19. 修复 - 拥有多个循环节点时,错误运行。
20. 修复 - 循环节点中修改变量,无法传递。
21. 修复 - 非 stream 模式,嵌套子应用/插件执行时无法获取子应用响应。
22. 修复 - 数据分块策略,同时将每个 Markdown 独立分块。

View File

@@ -0,0 +1,11 @@
---
title: 'FAQ'
description: '常见问题的解答'
icon: 'quiz'
draft: false
toc: true
weight: 900
---
<!-- 9800 ~ 1000 -->
FastGPT 是一个由用户和贡献者参与推动的开源项目,如果您对产品使用存在疑问和建议,可尝试[加入社区](community)寻求支持。我们的团队与社区会竭尽所能为您提供帮助。

View File

@@ -0,0 +1,16 @@
---
title: '应用使用问题'
description: 'FastGPT 常见应用使用问题,包括简易应用、工作流和插件'
icon: 'quiz'
draft: false
toc: true
weight: 903
---
## 工作流中多轮对话场景中如何使连续问题被问题分类节点正确的归类
问题分类节点具有获取上下文信息的能力,当处理两个关联性较大的问题时,模型的判断准确性往往依赖于这两个问题之间的联系和模型的能力。例如,当用户先问“我该如何使用这个功能?”接着又询问“这个功能有什么限制?”时,模型借助上下文信息,就能够更精准地理解并响应。
但是,当连续问题之间的关联性较小,模型判断的准确度可能会受到限制。在这种情况下,我们可以引入全局变量的概念来记录分类结果。在后续的问题分类阶段,首先检查全局变量是否存有分类结果。如果有,那么直接沿用该结果;若没有,则让模型自行判断。
建议:构建批量运行脚本进行测试,评估问题分类的准确性。

View File

@@ -0,0 +1,18 @@
---
title: '聊天框问题'
description: 'FastGPT 常见聊天框问题'
icon: 'quiz'
draft: false
toc: true
weight: 905
---
## 我修改了工作台的应用,为什么在“聊天”时没有更新配置?
应用需要点击发布后,聊天才会更新应用。
## 浏览器不支持语音输入
1. 首先需要确保浏览器、电脑本身麦克风权限的开启。
2. 确认浏览器允许该站点使用麦克风,并且选择正确的麦克风来源。
3. 需有 SSL 证书的站点才可以使用麦克风。

View File

@@ -0,0 +1,17 @@
---
title: '知识库使用问题'
description: '常见知识库使用问题'
icon: 'quiz'
draft: false
toc: true
weight: 904
---
## 上传的文件内容出现中文乱码
将文件另存为 UTF-8 编码格式。
## 知识库配置里的文件处理模型是什么?与索引模型有什么区别?
* **文件处理模型**:用于数据处理的【增强处理】和【问答拆分】。在【增强处理】中,生成相关问题和摘要,在【问答拆分】中执行问答对生成。
* **索引模型**:用于向量化,即通过对文本数据进行处理和组织,构建出一个能够快速查询的数据结构。

View File

@@ -0,0 +1,10 @@
---
title: 'Docker 部署问题'
description: 'FastGPT Docker 部署问题'
icon: ''
draft: false
toc: true
weight: 901
type: redirect
target: /docs/development/docker/#faq
---

View File

@@ -0,0 +1,7 @@
---
title: '常见错误'
icon: 'quiz'
draft: false
toc: true
weight: 920
---

View File

@@ -0,0 +1,11 @@
---
title: '其他问题'
icon: 'quiz'
draft: false
toc: true
weight: 925
---
## oneapi 官网是哪个
只有开源的 README没官网GitHub: https://github.com/songquanpeng/one-api

View File

@@ -0,0 +1,10 @@
---
title: "私有部署常见问题"
description: "FastGPT 私有部署常见问题"
icon: upgrade
draft: false
images: []
weight: 902
type: redirect
target: /docs/development/faq/
---

View File

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

View File

@@ -120,10 +120,12 @@ HTTP 模块会向对应的地址发送一个 `HTTP` 请求,实际操作与 Pos
### 如何获取返回值
从图中可以看出FastGPT可以添加多个返回值这个返回值并不代表接口的返回值而是代表`如何解析接口返回值`,可以通过 key `提取`接口响应的值。例如:
从图中可以看出FastGPT可以添加多个返回值这个返回值并不代表接口的返回值而是代表`如何解析接口返回值`,可以通过 `JSON path` 的语法,`提取`接口响应的值。
语法可以参考: https://github.com/JSONPath-Plus/JSONPath?tab=readme-ov-file
{{< tabs tabTotal="2" >}}
{{< tab tabName="接口响应格式" >}}
{{< tab tabName="接口响应示例" >}}
{{< markdownify >}}
```json
@@ -148,23 +150,23 @@ HTTP 模块会向对应的地址发送一个 `HTTP` 请求,实际操作与 Pos
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="FastGPT 转化后的格式" >}}
{{< tab tabName="提取示例" >}}
{{< markdownify >}}
```json
{
"message": "测试",
"data.user": { "name": "xxx", "age": 12 },
"data.user.name": "xxx",
"data.user.age": 12,
"data.list": [ { "name": "xxx", "age": 50 }, [{ "test": 22 }] ],
"data.list[0]": { "name": "xxx", "age": 50 },
"data.list[0].name": "xxx",
"data.list[0].age": 50,
"data.list[1]": [ { "test": 22 } ],
"data.list[1][0]": { "test": 22 },
"data.list[1][0].test": 22,
"data.psw": "xxx"
"$.message": "测试",
"$.data.user": { "name": "xxx", "age": 12 },
"$.data.user.name": "xxx",
"$.data.user.age": 12,
"$.data.list": [ { "name": "xxx", "age": 50 }, [{ "test": 22 }] ],
"$.data.list[0]": { "name": "xxx", "age": 50 },
"$.data.list[0].name": "xxx",
"$.data.list[0].age": 50,
"$.data.list[1]": [ { "test": 22 } ],
"$.data.list[1][0]": { "test": 22 },
"$.data.list[1][0].test": 22,
"$.data.psw": "xxx"
}
```
@@ -250,4 +252,4 @@ export default async function (ctx: FunctionContext) {
- [谷歌搜索](/docs/workflow/examples/google_search/)
- [发送飞书webhook](/docs/workflow/examples/feishu_webhook/)
- [实验室预约(操作数据库)](/docs/workflow/examples/lab_appointment/)
- [实验室预约(操作数据库)](/docs/workflow/examples/lab_appointment/)

View File

@@ -0,0 +1,87 @@
---
title: "代码运行"
description: "FastGPT 代码运行节点介绍"
icon: "input"
draft: false
toc: true
weight: 364
---
![alt text](/imgs/image.png)
## 功能
可用于执行一段简单的 js 代码用于进行一些复杂的数据处理。代码运行在沙盒中无法进行网络请求、dom和异步操作。如需复杂操作需外挂 HTTP 实现。
**注意事项**
- 私有化用户需要部署`fastgpt-sandbox` 镜像,并配置`SANDBOX_URL`环境变量。
- 沙盒最大运行 10s 32M 内存限制。
## 变量输入
可在自定义输入中添加代码运行需要的变量,在代码的 main 函数中,可解构出相同名字的变量。
如上图,自定义输入中有 data1 和 data2 两个变量main 函数中可以解构出相同名字的变量。
## 结果输出
务必返回一个 object 对象
自定义输出中,可以添加变量名来获取 object 对应 key 下的值。例如上图中,返回了一个对象:
```json
{
result: data1,
data2
}
```
他有 2 个 keyresult和 data2(js 缩写key=data2value=data2)。这时候自定义输出中就可以添加 2 个变量来获取对应 key 下的 value。
## 内置 JS 全局变量
### delay 延迟
延迟 1 秒后返回
```js
async function main({data1, data2}){
await delay(1000)
return {
result: "111"
}
}
```
### countToken 统计 token
```js
function main({input}){
return {
result: countToken(input)
}
}
```
![alt text](/imgs/image-1.png)
### strToBase64 字符串转 base64(4.8.11 版本新增)
可用于将 SVG 图片转换为 base64 格式展示。
```js
function main({input}){
return {
/*
param1: input 需要转换的字符串
param2: base64 prefix 前缀
*/
result: strToBase64(input,'data:image/svg+xml;base64,')
}
}
```
![alt text](/imgs/image-2.png)

View File

@@ -35,8 +35,6 @@ weight: 356
1. 无必须的参数尽管上下文中没有适合的参数也可以调用该工具。但有时候LLM会自己伪造一个参数。
2. 有必须的参数如果没有适合的参数LLM可能不会调用该工具。可以通过提示词引导用户提供参数。
### 工具调用逻辑
在支持`函数调用`的模型中,可以一次性调用多个工具,调用逻辑如下:
![](/imgs/flow-tool2.png)
@@ -49,10 +47,24 @@ weight: 356
高级编排中,托动工具调用的连接点,可用的工具头部会出现一个菱形,可以将它与工具调用模块底部的菱形相连接。
被连接的工具,会自动分离工具输入与普通的输入,并且可以编辑`介绍`,可以通过调整介绍,使得该工具调用时机更加精确。
被连接的工具,会自动分离工具输入与普通的输入,并且可以编辑`描述`,可以通过调整介绍,使得该工具调用时机更加精确。对于一些内置的节点,务必修改`描述`才能让模型正常调用。
关于工具调用,如何调试仍然是一个玄学,所以建议,不要一次性增加太多工具,选择少量工具调优后再进一步尝试。
## 组合节点
### 工具调用终止
工具调用默认会把子流程运行的结果作为`工具结果`,返回给模型进行回答。有时候,你可能不希望模型做回答,你可以给对应子流程的末尾增加上一个`工具调用终止`节点,这样,子流程的结果就不会被返回给模型。
![alt text](/imgs/image-3.png)
### 自定义工具变量
工具调用的子流程运行,有时候会依赖`AI`生成的一些变量,为了简化交互流程,我们给系统内置的节点都指定了`工具变量`。然而,有些时候,你需要的变量不仅是目标流程的`首个节点`的变量,而是需要更复杂的变量,此时你可以使用`自定义工具变量`。它允许你完全自定义该`工具流程`的变量。
![alt text](/imgs/image-4.png)
## 相关示例
- [谷歌搜索](/docs/workflow/examples/google_search/)

View File

@@ -69,6 +69,7 @@ defaultContentLanguageInSubdir = false
# twitter = "" # YOUR_TWITTER_ID
# instagram = "colinwilson" # YOUR_INSTAGRAM_ID
# rss = true # show rss icon with link
lark = "https://oss.laf.run/otnvvf-imgs/fastgpt-feishu1.png"
wechat = "https://oss.laf.run/htr4n1-images/fastgpt-qr-code.jpg"
[params.docs] # Parameters for the /docs 'template'

View File

@@ -1,9 +1,16 @@
<!DOCTYPE html>
{{ $.Scratch.Delete "social_list" }}
{{ $.Scratch.Set "pathName" (printf "%s" (.Site.Params.docs.pathName | default "docs")) }}
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-W9HPZZ22');</script>
<!-- End Google Tag Manager -->
<!-- social_list -->
<!-- change -->
{{ $social_params := slice "github" "twitter" "instagram" "rss" "wechat" }}
{{ $social_params := slice "github" "twitter" "instagram" "rss" "wechat" "lark" }}
{{ range $social_params }}
{{ if isset site.Params.social . }}
{{ $.Scratch.Add "social_list" (slice .) }}
@@ -12,6 +19,10 @@
<html lang="{{ site.LanguageCode }}">
{{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "head.html") . -}}
<body>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-W9HPZZ22"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
<div class="content">
<div class="page-wrapper toggled">
{{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "sidebar.html") . -}}

View File

@@ -52,7 +52,12 @@
{{ $path := printf "images/social/%s.%s" . "svg" }}
<li class="list-inline-item mb-0">
<!-- change -->
<a href="{{ if eq . `rss` }} {{ `index.xml` | absURL }} {{ else if eq . `wechat` }} {{ index site.Params.social . | absURL }} {{ else }} https://{{ . }}.com/{{ index site.Params.social . }} {{ end }}" alt="{{ . }}" rel="noopener noreferrer" target="_blank">
<a href="{{ if eq . `rss` }} {{ `index.xml` | absURL }}
{{ else if eq . `wechat` }} {{ index site.Params.social . | absURL }}
{{ else if eq . `lark` }} {{ index site.Params.social . | absURL }}
{{ else }} https://{{ . }}.com/{{ index site.Params.social . }}
{{ end }}"
alt="{{ . }}" rel="noopener noreferrer" target="_blank">
<div class="btn btn-icon btn-default border-0">
{{ with resources.Get $path }}
{{ .Content | safeHTML }}

View File

@@ -114,15 +114,15 @@ services:
# fastgpt
sandbox:
container_name: sandbox
image: ghcr.io/labring/fastgpt-sandbox:latest # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:latest # 阿里云
image: ghcr.io/labring/fastgpt-sandbox:v4.8.11 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.11 # 阿里云
networks:
- fastgpt
restart: always
fastgpt:
container_name: fastgpt
image: ghcr.io/labring/fastgpt:v4.8.9 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.9 # 阿里云
image: ghcr.io/labring/fastgpt:v4.8.11 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.11 # 阿里云
ports:
- 3000:3000
networks:
@@ -154,6 +154,8 @@ services:
- MILVUS_TOKEN=none
# sandbox 地址
- SANDBOX_URL=http://sandbox:3000
# 前端地址: http://localhost:3000
- FE_DOMAIN=
# 日志等级: debug, info, warn, error
- LOG_LEVEL=info
- STORE_LOG_LEVEL=warn

View File

@@ -72,15 +72,15 @@ services:
# fastgpt
sandbox:
container_name: sandbox
image: ghcr.io/labring/fastgpt-sandbox:latest # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:latest # 阿里云
image: ghcr.io/labring/fastgpt-sandbox:v4.8.11 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.11 # 阿里云
networks:
- fastgpt
restart: always
fastgpt:
container_name: fastgpt
image: ghcr.io/labring/fastgpt:v4.8.9 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.9 # 阿里云
image: ghcr.io/labring/fastgpt:v4.8.11 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.11 # 阿里云
ports:
- 3000:3000
networks:
@@ -111,6 +111,8 @@ services:
- PG_URL=postgresql://username:password@pg:5432/postgres
# sandbox 地址
- SANDBOX_URL=http://sandbox:3000
# 前端地址: http://localhost:3000
- FE_DOMAIN=
# 日志等级: debug, info, warn, error
- LOG_LEVEL=info
- STORE_LOG_LEVEL=warn

View File

@@ -53,15 +53,15 @@ services:
wait $$!
sandbox:
container_name: sandbox
image: ghcr.io/labring/fastgpt-sandbox:latest # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:latest # 阿里云
image: ghcr.io/labring/fastgpt-sandbox:v4.8.11 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.8.11 # 阿里云
networks:
- fastgpt
restart: always
fastgpt:
container_name: fastgpt
image: ghcr.io/labring/fastgpt:v4.8.9 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.9 # 阿里云
image: ghcr.io/labring/fastgpt:v4.8.11 # git
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.11 # 阿里云
ports:
- 3000:3000
networks:
@@ -92,6 +92,8 @@ services:
- MILVUS_TOKEN=zilliz_cloud_token
# sandbox 地址
- SANDBOX_URL=http://sandbox:3000
# 前端地址: http://localhost:3000
- FE_DOMAIN=
# 日志等级: debug, info, warn, error
- LOG_LEVEL=info
- STORE_LOG_LEVEL=warn

View File

@@ -10,7 +10,12 @@ export enum TeamErrEnum {
appAmountNotEnough = 'appAmountNotEnough',
pluginAmountNotEnough = 'pluginAmountNotEnough',
websiteSyncNotEnough = 'websiteSyncNotEnough',
reRankNotEnough = 'reRankNotEnough'
reRankNotEnough = 'reRankNotEnough',
groupNameEmpty = 'groupNameEmpty',
groupNameDuplicate = 'groupNameDuplicate',
groupNotExist = 'groupNotExist',
cannotDeleteDefaultGroup = 'cannotDeleteDefaultGroup',
userNotActive = 'userNotActive'
}
const teamErr = [
@@ -46,6 +51,26 @@ const teamErr = [
{
statusText: TeamErrEnum.reRankNotEnough,
message: i18nT('common:code_error.team_error.re_rank_not_enough')
},
{
statusText: TeamErrEnum.groupNameEmpty,
message: i18nT('common:code_error.team_error.group_name_empty')
},
{
statusText: TeamErrEnum.groupNotExist,
message: i18nT('common:code_error.team_error.group_not_exist')
},
{
statusText: TeamErrEnum.cannotDeleteDefaultGroup,
message: i18nT('common:code_error.team_error.cannot_delete_default_group')
},
{
statusText: TeamErrEnum.groupNameDuplicate,
message: i18nT('common:code_error.team_error.group_name_duplicate')
},
{
statusText: TeamErrEnum.userNotActive,
message: i18nT('common:code_error.team_error.user_not_active')
}
];

View File

@@ -19,6 +19,7 @@ export const ERROR_CODE: { [key: number]: string } = {
406: i18nT('common:code_error.error_code.406'),
410: i18nT('common:code_error.error_code.410'),
422: i18nT('common:code_error.error_code.422'),
429: i18nT('common:code_error.error_code.429'),
500: i18nT('common:code_error.error_code.500'),
502: i18nT('common:code_error.error_code.502'),
503: i18nT('common:code_error.error_code.503'),
@@ -39,7 +40,8 @@ export enum ERROR_ENUM {
insufficientQuota = 'insufficientQuota',
unAuthModel = 'unAuthModel',
unAuthApiKey = 'unAuthApiKey',
unAuthFile = 'unAuthFile'
unAuthFile = 'unAuthFile',
tooManyRequest = 'tooManyRequest'
}
export type ErrType<T> = Record<
@@ -67,6 +69,12 @@ export const ERROR_RESPONSE: Record<
message: i18nT('common:code_error.error_message.403'),
data: null
},
[ERROR_ENUM.tooManyRequest]: {
code: 429,
statusText: ERROR_ENUM.tooManyRequest,
message: 'Too many request',
data: null
},
[ERROR_ENUM.insufficientQuota]: {
code: 510,
statusText: ERROR_ENUM.insufficientQuota,

View File

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

View File

@@ -7,6 +7,7 @@ export enum MongoImageTypeEnum {
datasetAvatar = 'datasetAvatar',
userAvatar = 'userAvatar',
teamAvatar = 'teamAvatar',
groupAvatar = 'groupAvatar',
chatImage = 'chatImage',
collectionImage = 'collectionImage'
@@ -36,6 +37,10 @@ export const mongoImageTypeMap = {
label: 'teamAvatar',
unique: true
},
[MongoImageTypeEnum.groupAvatar]: {
label: 'groupAvatar',
unique: true
},
[MongoImageTypeEnum.chatImage]: {
label: 'chatImage',

View File

@@ -8,3 +8,24 @@ export const retryRun = <T>(fn: () => T, retry = 2): T => {
throw error;
}
};
export const batchRun = async <T>(arr: T[], fn: (arr: T) => any, batchSize = 10) => {
const batchArr = new Array(batchSize).fill(null);
const result: any[] = [];
const batchFn = async () => {
const data = arr.shift();
if (data) {
result.push(await fn(data));
return batchFn();
}
};
await Promise.all(
batchArr.map(async () => {
await batchFn();
})
);
return result;
};

View File

@@ -1,3 +1,4 @@
import { batchRun } from '../fn/utils';
import { simpleText } from './tools';
/* Delete redundant text in markdown */
@@ -53,23 +54,26 @@ export const uploadMarkdownBase64 = async ({
const base64Arr = rawText.match(base64Regex) || [];
// upload base64 and replace it
for await (const base64Img of base64Arr) {
try {
const str = await uploadImgController(base64Img);
rawText = rawText.replace(base64Img, str);
} catch (error) {
rawText = rawText.replace(base64Img, '');
rawText = rawText.replace(/!\[.*\]\(\)/g, '');
}
}
await batchRun(
base64Arr,
async (base64Img) => {
try {
const str = await uploadImgController(base64Img);
rawText = rawText.replace(base64Img, str);
} catch (error) {
rawText = rawText.replace(base64Img, '');
rawText = rawText.replace(/!\[.*\]\(\)/g, '');
}
},
20
);
}
// Remove white space on both sides of the picture
const trimReg = /(!\[.*\]\(.*\))\s*/g;
if (trimReg.test(rawText)) {
rawText = rawText.replace(trimReg, '$1');
}
// const trimReg = /(!\[.*\]\(.*\))\s*/g;
// if (trimReg.test(rawText)) {
// rawText = rawText.replace(trimReg, '$1');
// }
return rawText;
};

View File

@@ -92,9 +92,9 @@ ${mdSplitString}
};
/*
1. 自定义分隔符:不需要重叠
2. Markdown 标题:不需要重叠;标题嵌套共享
3. 特殊 markdown 语法:不需要重叠
1. 自定义分隔符:不需要重叠,不需要小块合并
2. Markdown 标题:不需要重叠;标题嵌套共享,不需要小块合并
3. 特殊 markdown 语法:不需要重叠,需要小块合并
4. 段落:尽可能保证它是一个完整的段落。
5. 标点分割:重叠
*/
@@ -118,10 +118,10 @@ const commonSplit = (props: SplitProps): SplitResponse => {
reg: new RegExp(`(${replaceRegChars(text)})`, 'g'),
maxLen: chunkLen * 1.4
})),
{ reg: /^(#\s[^\n]+)\n/gm, maxLen: chunkLen * 1.2 },
{ reg: /^(##\s[^\n]+)\n/gm, maxLen: chunkLen * 1.2 },
{ reg: /^(###\s[^\n]+)\n/gm, maxLen: chunkLen * 1.2 },
{ reg: /^(####\s[^\n]+)\n/gm, maxLen: chunkLen * 1.2 },
{ reg: /^(#\s[^\n]+\n)/gm, maxLen: chunkLen * 1.2 },
{ reg: /^(##\s[^\n]+\n)/gm, maxLen: chunkLen * 1.4 },
{ reg: /^(###\s[^\n]+\n)/gm, maxLen: chunkLen * 1.6 },
{ reg: /^(####\s[^\n]+\n)/gm, maxLen: chunkLen * 1.8 },
{ reg: /([\n]([`~]))/g, maxLen: chunkLen * 4 }, // code block
{ reg: /([\n](?!\s*[\*\-|>0-9]))/g, maxLen: chunkLen * 2 }, // 增大块,尽可能保证它是一个完整的段落。 (?![\*\-|>`0-9]): markdown special char
@@ -137,7 +137,6 @@ const commonSplit = (props: SplitProps): SplitResponse => {
const customRegLen = customReg.length;
const checkIsCustomStep = (step: number) => step < customRegLen;
const checkIsMarkdownSplit = (step: number) => step >= customRegLen && step <= 3 + customRegLen;
const checkIndependentChunk = (step: number) => step >= customRegLen && step <= 4 + customRegLen;
const checkForbidOverlap = (step: number) => step <= 6 + customRegLen;
// if use markdown title split, Separate record title
@@ -153,7 +152,6 @@ const commonSplit = (props: SplitProps): SplitResponse => {
const isCustomStep = checkIsCustomStep(step);
const isMarkdownSplit = checkIsMarkdownSplit(step);
const independentChunk = checkIndependentChunk(step);
const { reg } = stepReges[step];
@@ -162,7 +160,7 @@ const commonSplit = (props: SplitProps): SplitResponse => {
reg,
(() => {
if (isCustomStep) return splitMarker;
if (independentChunk) return `${splitMarker}$1`;
if (isMarkdownSplit) return `${splitMarker}$1`;
return `$1${splitMarker}`;
})()
)
@@ -178,7 +176,7 @@ const commonSplit = (props: SplitProps): SplitResponse => {
title: matchTitle
};
})
.filter((item) => item.text.trim());
.filter((item) => item.text?.trim());
};
/* Gets the overlap at the end of a text as the beginning of the next block */
@@ -214,15 +212,16 @@ const commonSplit = (props: SplitProps): SplitResponse => {
text = '',
step,
lastText,
mdTitle = ''
parentTitle = ''
}: {
text: string;
step: number;
lastText: string;
mdTitle: string;
lastText: string; // 上一个分块末尾数据会通过这个参数传入。
parentTitle: string;
}): string[] => {
const independentChunk = checkIndependentChunk(step);
const isMarkdownStep = checkIsMarkdownSplit(step);
const isCustomStep = checkIsCustomStep(step);
const forbidConcat = isMarkdownStep || isCustomStep; // forbid=true时候lastText肯定为空
// oversize
if (step >= stepReges.length) {
@@ -232,7 +231,7 @@ const commonSplit = (props: SplitProps): SplitResponse => {
// use slice-chunkLen to split text
const chunks: string[] = [];
for (let i = 0; i < text.length; i += chunkLen - overlapLen) {
chunks.push(`${mdTitle}${text.slice(i, i + chunkLen)}`);
chunks.push(`${parentTitle}${text.slice(i, i + chunkLen)}`);
}
return chunks;
}
@@ -242,67 +241,78 @@ const commonSplit = (props: SplitProps): SplitResponse => {
const maxLen = splitTexts.length > 1 ? stepReges[step].maxLen : chunkLen;
const minChunkLen = chunkLen * 0.7;
const miniChunkLen = 30;
// console.log(splitTexts, stepReges[step].reg);
const chunks: string[] = [];
for (let i = 0; i < splitTexts.length; i++) {
const item = splitTexts[i];
const currentTitle = `${mdTitle}${item.title}`;
const lastTextLen = lastText.length;
const currentText = item.text;
const currentTextLen = currentText.length;
const lastTextLen = lastText.length;
const newText = lastText + currentText;
const newTextLen = lastTextLen + currentTextLen;
// newText is too large(now, The lastText must be smaller than chunkLen)
if (newTextLen > maxLen) {
if (newTextLen > maxLen || isMarkdownStep) {
// lastText greater minChunkLen, direct push it to chunks, not add to next chunk. (large lastText)
if (lastTextLen > minChunkLen) {
chunks.push(`${currentTitle}${lastText}`);
lastText = getOneTextOverlapText({ text: lastText, step }); // next chunk will start with overlayText
i--;
chunks.push(lastText);
lastText = getOneTextOverlapText({ text: lastText, step }); // next chunk will start with overlayText
i--;
continue;
}
// 说明是新的文本块比较大,需要进一步拆分
// split new Text, split chunks must will greater 1 (small lastText)
const innerChunks = splitTextRecursively({
text: newText,
step: step + 1,
lastText: '',
mdTitle: currentTitle
parentTitle: parentTitle + item.title
});
const lastChunk = innerChunks[innerChunks.length - 1];
if (!lastChunk) continue;
if (forbidConcat) {
chunks.push(
...innerChunks.map(
(chunk) => (step === 3 + customRegLen ? `${parentTitle}${chunk}` : chunk) // 合并进 Markdown 分块时,需要补标题
)
);
continue;
}
// last chunk is too small, concat it to lastText(next chunk start)
if (!independentChunk && lastChunk.length < minChunkLen) {
if (lastChunk.length < minChunkLen) {
chunks.push(...innerChunks.slice(0, -1));
lastText = lastChunk;
} else {
chunks.push(...innerChunks);
// compute new overlapText
lastText = getOneTextOverlapText({
text: lastChunk,
step
});
continue;
}
// Last chunk is large enough
chunks.push(...innerChunks);
// compute new overlapText
lastText = getOneTextOverlapText({
text: lastChunk,
step
});
continue;
}
// size less than chunkLen, push text to last chunk. now, text definitely less than maxLen
lastText = newText;
// new text is small
// markdown paragraph block: Direct addition; If the chunk size reaches, add a chunk
if (
isCustomStep ||
(independentChunk && newTextLen > miniChunkLen) ||
newTextLen >= chunkLen
) {
chunks.push(`${currentTitle}${lastText}`);
lastText = getOneTextOverlapText({ text: lastText, step });
// Not overlap
if (forbidConcat) {
chunks.push(`${parentTitle}${item.title}${item.text}`);
continue;
}
lastText += item.text;
}
/* If the last chunk is independent, it needs to be push chunks. */
@@ -310,9 +320,10 @@ const commonSplit = (props: SplitProps): SplitResponse => {
if (lastText.length < chunkLen * 0.4) {
chunks[chunks.length - 1] = chunks[chunks.length - 1] + lastText;
} else {
chunks.push(`${mdTitle}${lastText}`);
chunks.push(lastText);
}
} else if (lastText && chunks.length === 0) {
// 只分出一个很小的块,则直接追加到末尾(如果大于 1 个块,说明这个小块内容已经被上一个块拿到了)
chunks.push(lastText);
}
@@ -324,8 +335,8 @@ const commonSplit = (props: SplitProps): SplitResponse => {
text,
step: 0,
lastText: '',
mdTitle: ''
}).map((chunk) => chunk?.replaceAll(codeBlockMarker, '\n') || ''); // restore code block
parentTitle: ''
}).map((chunk) => chunk?.replaceAll(codeBlockMarker, '\n')?.trim() || ''); // restore code block
const chars = chunks.reduce((sum, chunk) => sum + chunk.length, 0);

View File

@@ -33,9 +33,9 @@ export function replaceVariable(text: any, obj: Record<string, string | number>)
for (const key in obj) {
const val = obj[key];
if (!['string', 'number'].includes(typeof val)) continue;
const formatVal = typeof val === 'object' ? JSON.stringify(val) : String(val);
text = text.replace(new RegExp(`{{(${key})}}`, 'g'), String(val));
text = text.replace(new RegExp(`{{(${key})}}`, 'g'), formatVal);
}
return text || '';
}
@@ -63,6 +63,7 @@ export const getNanoid = (size = 12) => {
return `${firstChar}${randomsStr}`;
};
export const customNanoid = (str: string, size: number) => customAlphabet(str, size)();
/* Custom text to reg, need to replace special chats */
export const replaceRegChars = (text: string) => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
@@ -102,3 +103,21 @@ export const sliceStrStartEnd = (str: string, start: number, end: number) => {
return `${startContent}${overSize ? `\n\n...[hide ${str.length - start - end} chars]...\n\n` : ''}${endContent}`;
};
/*
Parse file extension from url
Test
1. https://xxx.com/file.pdf?token=123
=> pdf
2. https://xxx.com/file.pdf
=> pdf
*/
export const parseFileExtensionFromUrl = (url = '') => {
// Remove query params
const urlWithoutQuery = url.split('?')[0];
// Get file name
const fileName = urlWithoutQuery.split('/').pop() || '';
// Get file extension
const extension = fileName.split('.').pop();
return (extension || '').toLowerCase();
};

View File

@@ -1,3 +1,4 @@
export const HUMAN_ICON = `/icon/human.svg`;
export const LOGO_ICON = `/icon/logo.svg`;
export const HUGGING_FACE_ICON = `/imgs/model/huggingface.svg`;
export const DEFAULT_TEAM_AVATAR = `/imgs/avatar/defaultTeamAvatar.svg`;

View File

@@ -4,12 +4,14 @@ import type {
ChatCompletionChunk,
ChatCompletionMessageParam as SdkChatCompletionMessageParam,
ChatCompletionToolMessageParam,
ChatCompletionAssistantMessageParam,
ChatCompletionContentPart as SdkChatCompletionContentPart,
ChatCompletionUserMessageParam as SdkChatCompletionUserMessageParam
ChatCompletionUserMessageParam as SdkChatCompletionUserMessageParam,
ChatCompletionToolMessageParam as SdkChatCompletionToolMessageParam,
ChatCompletionAssistantMessageParam as SdkChatCompletionAssistantMessageParam,
ChatCompletionContentPartText
} from 'openai/resources';
import { ChatMessageTypeEnum } from './constants';
import { InteractiveNodeResponseItemType } from '../workflow/template/system/interactive/type';
import { WorkflowInteractiveResponseType } from '../workflow/template/system/interactive/type';
export * from 'openai/resources';
// Extension of ChatCompletionMessageParam, Add file url type
@@ -22,18 +24,31 @@ export type ChatCompletionContentPartFile = {
export type ChatCompletionContentPart =
| SdkChatCompletionContentPart
| ChatCompletionContentPartFile;
type CustomChatCompletionUserMessageParam = {
content: string | Array<ChatCompletionContentPart>;
type CustomChatCompletionUserMessageParam = Omit<ChatCompletionUserMessageParam, 'content'> & {
role: 'user';
content: string | Array<ChatCompletionContentPart>;
};
type CustomChatCompletionToolMessageParam = SdkChatCompletionToolMessageParam & {
role: 'tool';
name?: string;
};
type CustomChatCompletionAssistantMessageParam = SdkChatCompletionAssistantMessageParam & {
role: 'assistant';
interactive?: WorkflowInteractiveResponseType;
};
export type ChatCompletionMessageParam = (
| Exclude<SdkChatCompletionMessageParam, SdkChatCompletionUserMessageParam>
| Exclude<
SdkChatCompletionMessageParam,
| SdkChatCompletionUserMessageParam
| SdkChatCompletionToolMessageParam
| SdkChatCompletionAssistantMessageParam
>
| CustomChatCompletionUserMessageParam
| CustomChatCompletionToolMessageParam
| CustomChatCompletionAssistantMessageParam
) & {
dataId?: string;
interactive?: InteractiveNodeResponseItemType;
};
export type SdkChatCompletionMessageParam = SdkChatCompletionMessageParam;
@@ -47,11 +62,12 @@ export type ChatCompletionMessageToolCall = ChatCompletionMessageToolCall & {
toolName?: string;
toolAvatar?: string;
};
export type ChatCompletionMessageFunctionCall = ChatCompletionAssistantMessageParam.FunctionCall & {
id?: string;
toolName?: string;
toolAvatar?: string;
};
export type ChatCompletionMessageFunctionCall =
SdkChatCompletionAssistantMessageParam.FunctionCall & {
id?: string;
toolName?: string;
toolAvatar?: string;
};
// Stream response
export type StreamChatType = Stream<ChatCompletionChunk>;

View File

@@ -1,4 +1,8 @@
import { UpdateClbPermissionProps } from '../../support/permission/collaborator';
import { RequireOnlyOne } from '../../common/type/utils';
import {
UpdateClbPermissionProps,
UpdatePermissionBody
} from '../../support/permission/collaborator';
import { PermissionValueType } from '../../support/permission/type';
export type UpdateAppCollaboratorBody = UpdateClbPermissionProps & {
@@ -7,5 +11,7 @@ export type UpdateAppCollaboratorBody = UpdateClbPermissionProps & {
export type AppCollaboratorDeleteParams = {
appId: string;
} & RequireOnlyOne<{
tmbId: string;
};
groupId: string;
}>;

View File

@@ -10,9 +10,9 @@ import { SelectedDatasetType } from '../workflow/api';
import { DatasetSearchModeEnum } from '../dataset/constants';
import { TeamTagSchema as TeamTagsSchemaType } from '@fastgpt/global/support/user/team/type.d';
import { StoreEdgeItemType } from '../workflow/type/edge';
import { PermissionSchemaType, PermissionValueType } from '../../support/permission/type';
import { AppPermission } from '../../support/permission/app/controller';
import { ParentIdType } from '../../common/parentFolder/type';
import { FlowNodeInputTypeEnum } from 'core/workflow/node/constant';
export type AppSchema = {
_id: string;
@@ -44,7 +44,11 @@ export type AppSchema = {
inited?: boolean;
teamTags: string[];
} & PermissionSchemaType;
inheritPermission?: boolean;
// abandon
defaultPermission?: number;
};
export type AppListItemType = {
_id: string;
@@ -56,7 +60,9 @@ export type AppListItemType = {
updateTime: Date;
pluginData?: AppSchema['pluginData'];
permission: AppPermission;
} & PermissionSchemaType;
inheritPermission?: boolean;
private?: boolean;
};
export type AppDetailType = AppSchema & {
permission: AppPermission;
@@ -114,11 +120,19 @@ export type VariableItemType = {
id: string;
key: string;
label: string;
type: `${VariableInputEnum}`;
type: VariableInputEnum;
required: boolean;
maxLen: number;
enums: { value: string }[];
valueType: WorkflowIOValueTypeEnum;
description: string;
valueType?: WorkflowIOValueTypeEnum;
defaultValue?: any;
// input
maxLength?: number;
// numberInput
max?: number;
min?: number;
// select
enums?: { value: string; label: string }[];
};
// tts
export type AppTTSConfigType = {

View File

@@ -90,8 +90,9 @@ export const chats2GPTMessages = ({
});
}
} else {
const aiResults: ChatCompletionMessageParam[] = [];
//AI
item.value.forEach((value) => {
item.value.forEach((value, i) => {
if (value.type === ChatItemValueTypeEnum.tool && value.tools && reserveTool) {
const tool_calls: ChatCompletionMessageToolCall[] = [];
const toolResponse: ChatCompletionToolMessageParam[] = [];
@@ -111,28 +112,56 @@ export const chats2GPTMessages = ({
content: tool.response
});
});
results = results
.concat({
aiResults.push({
dataId,
role: ChatCompletionRequestMessageRoleEnum.Assistant,
tool_calls
});
aiResults.push(...toolResponse);
} else if (
value.type === ChatItemValueTypeEnum.text &&
typeof value.text?.content === 'string'
) {
if (!value.text.content && item.value.length > 1) {
return;
}
// Concat text
const lastValue = item.value[i - 1];
const lastResult = aiResults[aiResults.length - 1];
if (
lastValue &&
lastValue.type === ChatItemValueTypeEnum.text &&
typeof lastResult.content === 'string'
) {
lastResult.content += value.text.content;
} else {
aiResults.push({
dataId,
role: ChatCompletionRequestMessageRoleEnum.Assistant,
tool_calls
})
.concat(toolResponse);
} else if (value.text?.content) {
results.push({
dataId,
role: ChatCompletionRequestMessageRoleEnum.Assistant,
content: value.text.content
});
content: value.text.content
});
}
} else if (value.type === ChatItemValueTypeEnum.interactive) {
results = results.concat({
aiResults.push({
dataId,
role: ChatCompletionRequestMessageRoleEnum.Assistant,
interactive: value.interactive,
content: ''
interactive: value.interactive
});
}
});
// Auto add empty assistant message
results = results.concat(
aiResults.length > 0
? aiResults
: [
{
dataId,
role: ChatCompletionRequestMessageRoleEnum.Assistant,
content: ''
}
]
);
}
});
@@ -215,14 +244,7 @@ export const GPTMessages2Chats = (
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) {
if (item.tool_calls && reserveTool) {
// save tool calls
const toolCalls = item.tool_calls as ChatCompletionMessageToolCall[];
value.push({
@@ -278,6 +300,18 @@ export const GPTMessages2Chats = (
type: ChatItemValueTypeEnum.interactive,
interactive: item.interactive
});
} else if (typeof item.content === 'string') {
const lastValue = value[value.length - 1];
if (lastValue && lastValue.type === ChatItemValueTypeEnum.text && lastValue.text) {
lastValue.text.content += item.content;
} else {
value.push({
type: ChatItemValueTypeEnum.text,
text: {
content: item.content
}
});
}
}
}
@@ -289,7 +323,7 @@ export const GPTMessages2Chats = (
})
.filter((item) => item.value.length > 0);
// Merge data with the same dataId
// Merge data with the same dataIdSequential obj merging
const result = chatMessages.reduce((result: ChatItemType[], currentItem) => {
const lastItem = result[result.length - 1];

View File

@@ -1,7 +1,7 @@
export type UpdateChatFeedbackProps = {
appId: string;
chatId: string;
chatItemId: string;
dataId: string;
shareId?: string;
teamId?: string;
teamToken?: string;

View File

@@ -15,7 +15,7 @@ import type { AppSchema as AppType } from '@fastgpt/global/core/app/type.d';
import { DatasetSearchModeEnum } from '../dataset/constants';
import { DispatchNodeResponseType } from '../workflow/runtime/type.d';
import { ChatBoxInputType } from '../../../../projects/app/src/components/core/chat/ChatContainer/ChatBox/type';
import { InteractiveNodeResponseItemType } from '../workflow/template/system/interactive/type';
import { WorkflowInteractiveResponseType } from '../workflow/template/system/interactive/type';
export type ChatSchema = {
_id: string;
@@ -73,7 +73,7 @@ export type AIChatItemValueItemType = {
content: string;
};
tools?: ToolModuleResponseItemType[];
interactive?: InteractiveNodeResponseItemType;
interactive?: WorkflowInteractiveResponseType;
};
export type AIChatItemType = {
obj: ChatRoleEnum.AI;
@@ -100,7 +100,7 @@ export type ChatItemSchema = (UserChatItemType | SystemChatItemType | AIChatItem
};
export type AdminFbkType = {
dataId: string;
feedbackDataId: string;
datasetId: string;
collectionId: string;
q: string;

View File

@@ -143,3 +143,29 @@ export const getChatSourceByPublishChannel = (publishChannel: PublishChannelEnum
return ChatSourceEnum.online;
}
};
/*
Merge chat responseData
1. Same tool mergeSignId (Interactive tool node)
*/
export const mergeChatResponseData = (responseDataList: ChatHistoryItemResType[]) => {
let lastResponse: ChatHistoryItemResType | undefined = undefined;
return responseDataList.reduce<ChatHistoryItemResType[]>((acc, curr) => {
if (lastResponse && lastResponse.mergeSignId && curr.mergeSignId === lastResponse.mergeSignId) {
// 替换 lastResponse
const concatResponse: ChatHistoryItemResType = {
...curr,
runningTime: +((lastResponse.runningTime || 0) + (curr.runningTime || 0)).toFixed(2),
totalPoints: (lastResponse.totalPoints || 0) + (curr.totalPoints || 0),
childTotalPoints: (lastResponse.childTotalPoints || 0) + (curr.childTotalPoints || 0),
toolCallTokens: (lastResponse.toolCallTokens || 0) + (curr.toolCallTokens || 0),
toolDetail: [...(lastResponse.toolDetail || []), ...(curr.toolDetail || [])]
};
return [...acc.slice(0, -1), concatResponse];
} else {
lastResponse = curr;
return [...acc, curr];
}
}, []);
};

View File

@@ -1,5 +1,6 @@
import { UpdateClbPermissionProps } from '../../support/permission/collaborator';
import { PermissionValueType } from '../../support/permission/type';
import { RequireOnlyOne } from '../../common/type/utils';
export type UpdateDatasetCollaboratorBody = UpdateClbPermissionProps & {
datasetId: string;
@@ -7,5 +8,7 @@ export type UpdateDatasetCollaboratorBody = UpdateClbPermissionProps & {
export type DatasetCollaboratorDeleteParams = {
datasetId: string;
} & RequireOnlyOne<{
tmbId: string;
};
groupId: string;
}>;

View File

@@ -1,4 +1,3 @@
import { PermissionSchemaType } from '../../support/permission/type';
import type { LLMModelItemType, VectorModelItemType } from '../../core/ai/model.d';
import { PermissionTypeEnum } from '../../support/permission/constant';
import { PushDatasetDataChunkProps } from './api';
@@ -32,8 +31,11 @@ export type DatasetSchemaType = {
selector: string;
};
externalReadUrl?: string;
} & PermissionSchemaType;
// } & PermissionSchemaType;
inheritPermission: boolean;
// abandon
defaultPermission?: number;
};
export type DatasetCollectionSchemaType = {
_id: string;
@@ -146,7 +148,9 @@ export type DatasetListItemType = {
type: `${DatasetTypeEnum}`;
permission: DatasetPermission;
vectorModel: VectorModelItemType;
} & PermissionSchemaType;
inheritPermission: boolean;
private?: boolean;
};
export type DatasetItemType = Omit<DatasetSchemaType, 'vectorModel' | 'agentModel'> & {
vectorModel: VectorModelItemType;
@@ -187,7 +191,7 @@ export type DatasetDataItemType = {
chunkIndex: number;
indexes: DatasetDataIndexItemType[];
isOwner: boolean;
canWrite: boolean;
// permission: DatasetPermission;
};
/* --------------- file ---------------------- */
@@ -208,7 +212,7 @@ export type DatasetFileSchema = {
/* ============= search =============== */
export type SearchDataResponseItemType = Omit<
DatasetDataItemType,
'teamId' | 'indexes' | 'isOwner' | 'canWrite'
'teamId' | 'indexes' | 'isOwner'
> & {
score: { type: `${SearchScoreTypeEnum}`; value: number; index: number }[];
// score: number;

View File

@@ -37,6 +37,60 @@ export enum WorkflowIOValueTypeEnum {
selectDataset = 'selectDataset'
}
export const toolValueTypeList = [
{
label: WorkflowIOValueTypeEnum.string,
value: WorkflowIOValueTypeEnum.string,
jsonSchema: {
type: 'string'
}
},
{
label: WorkflowIOValueTypeEnum.number,
value: WorkflowIOValueTypeEnum.number,
jsonSchema: {
type: 'number'
}
},
{
label: WorkflowIOValueTypeEnum.boolean,
value: WorkflowIOValueTypeEnum.boolean,
jsonSchema: {
type: 'boolean'
}
},
{
label: 'array<string>',
value: WorkflowIOValueTypeEnum.arrayString,
jsonSchema: {
type: 'array',
items: {
type: 'string'
}
}
},
{
label: 'array<number>',
value: WorkflowIOValueTypeEnum.arrayNumber,
jsonSchema: {
type: 'array',
items: {
type: 'number'
}
}
},
{
label: 'array<boolean>',
value: WorkflowIOValueTypeEnum.arrayBoolean,
jsonSchema: {
type: 'array',
items: {
type: 'boolean'
}
}
}
];
/* reg: modulename key */
export enum NodeInputKeyEnum {
// old
@@ -151,7 +205,11 @@ export enum NodeInputKeyEnum {
loopEndInput = 'loopEndInput',
// form input
userInputForms = 'userInputForms'
userInputForms = 'userInputForms',
// comment
commentText = 'commentText',
commentSize = 'commentSize'
}
export enum NodeOutputKeyEnum {
@@ -209,29 +267,51 @@ export enum NodeOutputKeyEnum {
export enum VariableInputEnum {
input = 'input',
textarea = 'textarea',
numberInput = 'numberInput',
select = 'select',
custom = 'custom'
}
export const variableMap = {
export const variableMap: Record<
VariableInputEnum,
{
icon: string;
label: string;
value: VariableInputEnum;
defaultValueType: WorkflowIOValueTypeEnum;
description?: string;
}
> = {
[VariableInputEnum.input]: {
icon: 'core/app/variable/input',
title: i18nT('common:core.module.variable.input type'),
desc: ''
icon: 'core/workflow/inputType/input',
label: i18nT('common:core.workflow.inputType.textInput'),
value: VariableInputEnum.input,
defaultValueType: WorkflowIOValueTypeEnum.string
},
[VariableInputEnum.textarea]: {
icon: 'core/app/variable/textarea',
title: i18nT('common:core.module.variable.textarea type'),
desc: i18nT('app:variable.textarea_type_desc')
icon: 'core/workflow/inputType/textarea',
label: i18nT('common:core.workflow.inputType.textarea'),
value: VariableInputEnum.textarea,
defaultValueType: WorkflowIOValueTypeEnum.string,
description: i18nT('app:variable.textarea_type_desc')
},
[VariableInputEnum.numberInput]: {
icon: 'core/workflow/inputType/numberInput',
label: i18nT('common:core.workflow.inputType.number input'),
value: VariableInputEnum.numberInput,
defaultValueType: WorkflowIOValueTypeEnum.number
},
[VariableInputEnum.select]: {
icon: 'core/app/variable/select',
title: i18nT('common:core.module.variable.select type'),
desc: ''
icon: 'core/workflow/inputType/option',
label: i18nT('common:core.workflow.inputType.select'),
value: VariableInputEnum.select,
defaultValueType: WorkflowIOValueTypeEnum.string
},
[VariableInputEnum.custom]: {
icon: 'core/app/variable/external',
title: i18nT('common:core.module.variable.Custom type'),
desc: i18nT('app:variable.select type_desc')
icon: 'core/workflow/inputType/customVariable',
label: i18nT('common:core.workflow.inputType.custom'),
value: VariableInputEnum.custom,
defaultValueType: WorkflowIOValueTypeEnum.string,
description: i18nT('app:variable.select type_desc')
}
};

View File

@@ -3,12 +3,12 @@ import { i18nT } from '../../../../web/i18n/utils';
export enum FlowNodeInputTypeEnum { // render ui
reference = 'reference', // reference to other node output
input = 'input', // one line input
textarea = 'textarea',
numberInput = 'numberInput',
switch = 'switch', // true/false
select = 'select',
// editor
textarea = 'textarea',
JSONEditor = 'JSONEditor',
addInputParam = 'addInputParam', // params input
@@ -38,9 +38,6 @@ export const FlowNodeInputMap: Record<
[FlowNodeInputTypeEnum.reference]: {
icon: 'core/workflow/inputType/reference'
},
[FlowNodeInputTypeEnum.input]: {
icon: 'core/workflow/inputType/input'
},
[FlowNodeInputTypeEnum.numberInput]: {
icon: 'core/workflow/inputType/numberInput'
},
@@ -50,9 +47,6 @@ export const FlowNodeInputMap: Record<
[FlowNodeInputTypeEnum.switch]: {
icon: 'core/workflow/inputType/switch'
},
[FlowNodeInputTypeEnum.textarea]: {
icon: 'core/workflow/inputType/textarea'
},
[FlowNodeInputTypeEnum.JSONEditor]: {
icon: 'core/workflow/inputType/jsonEditor'
},
@@ -85,6 +79,12 @@ export const FlowNodeInputMap: Record<
},
[FlowNodeInputTypeEnum.custom]: {
icon: 'core/workflow/inputType/custom'
},
[FlowNodeInputTypeEnum.input]: {
icon: 'core/workflow/inputType/input'
},
[FlowNodeInputTypeEnum.textarea]: {
icon: 'core/workflow/inputType/textarea'
}
};
@@ -118,6 +118,7 @@ export enum FlowNodeTypeEnum {
queryExtension = 'cfr',
tools = 'tools',
stopTool = 'stopTool',
toolParams = 'toolParams',
lafModule = 'lafModule',
ifElseNode = 'ifElseNode',
variableUpdate = 'variableUpdate',
@@ -129,7 +130,8 @@ export enum FlowNodeTypeEnum {
loop = 'loop',
loopStart = 'loopStart',
loopEnd = 'loopEnd',
formInput = 'formInput'
formInput = 'formInput',
comment = 'comment'
}
// node IO value type

View File

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

View File

@@ -73,12 +73,13 @@ export type RuntimeNodeItemType = {
intro?: StoreNodeItemType['intro'];
flowNodeType: StoreNodeItemType['flowNodeType'];
showStatus?: StoreNodeItemType['showStatus'];
isEntry?: StoreNodeItemType['isEntry'];
isEntry?: boolean;
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
pluginId?: string; // workflow id / plugin id
version: string;
};
export type PluginRuntimeType = {
@@ -107,12 +108,14 @@ export type DispatchNodeResponseType = {
customOutputs?: Record<string, any>;
nodeInputs?: Record<string, any>;
nodeOutputs?: Record<string, any>;
mergeSignId?: string;
// bill
tokens?: number;
model?: string;
contextTotalLen?: number;
totalPoints?: number;
childTotalPoints?: number;
// chat
temperature?: number;
@@ -185,6 +188,9 @@ export type DispatchNodeResponseType = {
// form input
formInputResult?: string;
// tool params
toolParamsResult?: Record<string, any>;
};
export type DispatchNodeResultType<T = {}> = {
@@ -196,6 +202,7 @@ export type DispatchNodeResultType<T = {}> = {
[DispatchNodeResponseKeyEnum.assistantResponses]?: AIChatItemValueItemType[]; // Assistant response(Store to db)
[DispatchNodeResponseKeyEnum.rewriteHistories]?: ChatItemType[];
[DispatchNodeResponseKeyEnum.runTimes]?: number;
[DispatchNodeResponseKeyEnum.newVariables]?: Record<string, any>;
} & T;
/* Single node props */

View File

@@ -69,7 +69,7 @@ export const initWorkflowEdgeStatus = (
histories?: ChatItemType[]
): RuntimeEdgeItemType[] => {
// If there is a history, use the last interactive value
if (!!histories) {
if (histories && histories.length > 0) {
const memoryEdges = getLastInteractiveValue(histories)?.memoryEdges;
if (memoryEdges && memoryEdges.length > 0) {
@@ -90,7 +90,7 @@ export const getWorkflowEntryNodeIds = (
histories?: ChatItemType[]
) => {
// If there is a history, use the last interactive entry node
if (!!histories) {
if (histories && histories.length > 0) {
const entryNodeIds = getLastInteractiveValue(histories)?.entryNodeIds;
if (Array.isArray(entryNodeIds) && entryNodeIds.length > 0) {
@@ -124,7 +124,8 @@ export const storeNodes2RuntimeNodes = (
isEntry: entryNodeIds.includes(node.nodeId),
inputs: node.inputs,
outputs: node.outputs,
pluginId: node.pluginId
pluginId: node.pluginId,
version: node.version
};
}) || []
);
@@ -233,7 +234,8 @@ export const getReferenceVariableValue = ({
nodes: RuntimeNodeItemType[];
variables: Record<string, any>;
}) => {
if (!isReferenceValue(value)) {
const nodeIds = nodes.map((node) => node.nodeId);
if (!isReferenceValue(value, nodeIds)) {
return value;
}
const sourceNodeId = value[0];

View File

@@ -33,17 +33,19 @@ import { LoopNode } from './system/loop/loop';
import { LoopStartNode } from './system/loop/loopStart';
import { LoopEndNode } from './system/loop/loopEnd';
import { FormInputNode } from './system/interactive/formInput';
import { ToolParamsNode } from './system/toolParams';
const systemNodes: FlowNodeTemplateType[] = [
AiChatModule,
TextEditorNode,
AssignedAnswerModule,
DatasetSearchModule,
DatasetConcatModule,
ToolModule,
StopToolNode,
ClassifyQuestionModule,
ContextExtractModule,
DatasetConcatModule,
ToolModule,
ToolParamsNode,
StopToolNode,
ReadFilesNode,
HttpNode468,
AiQueryExtension,

View File

@@ -1,7 +1,7 @@
import { NodeInputKeyEnum } from '../constants';
import { FlowNodeInputTypeEnum } from '../node/constant';
import { WorkflowIOValueTypeEnum } from '../constants';
import { chatNodeSystemPromptTip } from './tip';
import { chatNodeSystemPromptTip, systemPromptTip } from './tip';
import { FlowNodeInputItemType } from '../type/io';
import { i18nT } from '../../../../web/i18n/utils';
@@ -55,7 +55,7 @@ export const Input_Template_System_Prompt: FlowNodeInputItemType = {
max: 3000,
valueType: WorkflowIOValueTypeEnum.string,
label: i18nT('common:core.ai.Prompt'),
description: chatNodeSystemPromptTip,
description: systemPromptTip,
placeholder: chatNodeSystemPromptTip
};

View File

@@ -19,7 +19,7 @@ import {
Input_Template_UserChatInput,
Input_Template_Text_Quote
} from '../../input';
import { chatNodeSystemPromptTip } from '../../tip';
import { chatNodeSystemPromptTip, systemPromptTip } from '../../tip';
import { getHandleConfig } from '../../utils';
import { i18nT } from '../../../../../../web/i18n/utils';
@@ -54,6 +54,7 @@ export const AiChatModule: FlowNodeTemplateType = {
intro: i18nT('workflow:template.ai_chat_intro'),
showStatus: true,
isTool: true,
courseUrl: '/docs/workflow/modules/ai_chat/',
version: '481',
inputs: [
Input_Template_SettingAiModel,
@@ -94,7 +95,7 @@ export const AiChatModule: FlowNodeTemplateType = {
{
...Input_Template_System_Prompt,
label: i18nT('common:core.ai.Prompt'),
description: chatNodeSystemPromptTip,
description: systemPromptTip,
placeholder: chatNodeSystemPromptTip
},
Input_Template_History,

View File

@@ -17,7 +17,7 @@ export const AssignedAnswerModule: FlowNodeTemplateType = {
avatar: 'core/workflow/template/reply',
name: i18nT('workflow:assigned_reply'),
intro: i18nT('workflow:intro_assigned_reply'),
courseUrl: '/docs/workflow/modules/reply/',
version: '481',
isTool: true,
inputs: [

View File

@@ -31,6 +31,7 @@ export const ClassifyQuestionModule: FlowNodeTemplateType = {
intro: i18nT('workflow:intro_question_classification'),
showStatus: true,
version: '481',
courseUrl: '/docs/workflow/modules/question_classify/',
inputs: [
{
...Input_Template_SelectAIModel,

View File

@@ -0,0 +1,40 @@
import { FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/node.d';
import {
FlowNodeTemplateTypeEnum,
NodeInputKeyEnum,
WorkflowIOValueTypeEnum
} from '../../constants';
import { getHandleConfig } from '../utils';
export const CommentNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.comment,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowNodeType: FlowNodeTypeEnum.comment,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(false, false, false, false),
avatar: '',
name: '',
intro: '',
version: '4811',
inputs: [
{
key: NodeInputKeyEnum.commentText,
renderTypeList: [],
valueType: WorkflowIOValueTypeEnum.string,
label: '',
value: ''
},
{
key: NodeInputKeyEnum.commentSize,
renderTypeList: [],
valueType: WorkflowIOValueTypeEnum.object,
label: '',
value: {
width: 240,
height: 140
}
}
],
outputs: []
};

View File

@@ -26,6 +26,7 @@ export const ContextExtractModule: FlowNodeTemplateType = {
intro: i18nT('workflow:intro_text_content_extraction'),
showStatus: true,
isTool: true,
courseUrl: '/docs/workflow/modules/content_extract/',
version: '481',
inputs: [
{

View File

@@ -17,6 +17,7 @@ export const CustomFeedbackNode: FlowNodeTemplateType = {
avatar: 'core/workflow/template/customFeedback',
name: i18nT('workflow:custom_feedback'),
intro: i18nT('workflow:intro_custom_feedback'),
courseUrl: '/docs/workflow/modules/custom_feedback/',
version: '486',
inputs: [
{

View File

@@ -29,6 +29,7 @@ export const DatasetSearchModule: FlowNodeTemplateType = {
intro: Dataset_SEARCH_DESC,
showStatus: true,
isTool: true,
courseUrl: '/docs/workflow/modules/dataset_search/',
version: '481',
inputs: [
{

View File

@@ -27,6 +27,7 @@ export const HttpNode468: FlowNodeTemplateType = {
intro: i18nT('workflow:intro_http_request'),
showStatus: true,
isTool: true,
courseUrl: '/docs/workflow/modules/http/',
version: '481',
inputs: [
{
@@ -113,7 +114,9 @@ export const HttpNode468: FlowNodeTemplateType = {
],
outputs: [
{
...Output_Template_AddOutput
...Output_Template_AddOutput,
label: i18nT('workflow:http_extract_output'),
description: i18nT('workflow:http_extract_output_description')
},
{
id: NodeOutputKeyEnum.error,

View File

@@ -23,6 +23,7 @@ export const IfElseNode: FlowNodeTemplateType = {
name: i18nT('workflow:condition_checker'),
intro: i18nT('workflow:execute_different_branches_based_on_conditions'),
showStatus: true,
courseUrl: '/docs/workflow/modules/tfswitch/',
version: '481',
inputs: [
{

View File

@@ -22,7 +22,7 @@ export const FormInputNode: FlowNodeTemplateType = {
avatar: 'core/workflow/template/formInput',
name: i18nT('app:workflow.form_input'),
intro: i18nT(`app:workflow.form_input_tip`),
showStatus: true,
isTool: true,
version: '4811',
inputs: [
{

View File

@@ -1,8 +1,9 @@
import { NodeOutputItemType } from '../../../../chat/type';
import { FlowNodeOutputItemType } from '../../../type/io';
import { RuntimeEdgeItemType } from '../../../runtime/type';
import type { NodeOutputItemType } from '../../../../chat/type';
import type { FlowNodeOutputItemType } from '../../../type/io';
import type { RuntimeEdgeItemType } from '../../../runtime/type';
import { FlowNodeInputTypeEnum } from 'core/workflow/node/constant';
import { WorkflowIOValueTypeEnum } from 'core/workflow/constants';
import type { ChatCompletionMessageParam } from '../../../../ai/type';
export type UserSelectOptionItemType = {
key: string;
@@ -32,6 +33,12 @@ type InteractiveBasicType = {
entryNodeIds: string[];
memoryEdges: RuntimeEdgeItemType[];
nodeOutputs: NodeOutputItemType[];
toolParams?: {
entryNodeIds: string[]; // 记录工具中,交互节点的 Id而不是起始工作流的入口
memoryMessages: ChatCompletionMessageParam[]; // 这轮工具中,产生的新的 messages
toolCallId: string; // 记录对应 tool 的id用于后续交互节点可以替换掉 tool 的 response
};
};
type UserSelectInteractive = {
@@ -52,5 +59,5 @@ type UserInputInteractive = {
};
};
export type InteractiveNodeResponseItemType = InteractiveBasicType &
(UserSelectInteractive | UserInputInteractive);
export type InteractiveNodeResponseType = UserSelectInteractive | UserInputInteractive;
export type WorkflowInteractiveResponseType = InteractiveBasicType & InteractiveNodeResponseType;

View File

@@ -23,7 +23,7 @@ export const UserSelectNode: FlowNodeTemplateType = {
diagram: '/imgs/app/userSelect.svg',
name: i18nT('app:workflow.user_select'),
intro: i18nT(`app:workflow.user_select_tip`),
showStatus: true,
isTool: true,
version: '489',
inputs: [
{

View File

@@ -32,6 +32,7 @@ export const LafModule: FlowNodeTemplateType = {
intro: i18nT('workflow:intro_laf_function_call'),
showStatus: true,
isTool: true,
courseUrl: '/docs/workflow/modules/laf/',
version: '481',
inputs: [
{

View File

@@ -26,6 +26,7 @@ export const CodeNode: FlowNodeTemplateType = {
name: i18nT('workflow:code_execution'),
intro: i18nT('workflow:execute_a_simple_script_code_usually_for_complex_data_processing'),
showStatus: true,
courseUrl: '/docs/workflow/modules/sandbox/',
version: '482',
inputs: [
{

View File

@@ -23,6 +23,7 @@ export const TextEditorNode: FlowNodeTemplateType = {
avatar: 'core/workflow/template/textConcat',
name: i18nT('workflow:text_concatenation'),
intro: i18nT('workflow:intro_text_concatenation'),
courseUrl: '/docs/workflow/modules/text_editor/',
version: '486',
inputs: [
{

View File

@@ -0,0 +1,20 @@
import { FlowNodeTypeEnum } from '../../node/constant';
import { FlowNodeTemplateType } from '../../type/node';
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { getHandleConfig } from '../utils';
import { i18nT } from '../../../../../web/i18n/utils';
export const ToolParamsNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.toolParams,
templateType: FlowNodeTemplateTypeEnum.ai,
flowNodeType: FlowNodeTypeEnum.toolParams,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
avatar: 'core/workflow/template/toolParams',
name: i18nT('workflow:tool_custom_field'),
intro: i18nT('workflow:intro_tool_params_config'),
version: '4811',
isTool: true,
inputs: [],
outputs: []
};

View File

@@ -16,7 +16,7 @@ import {
Input_Template_System_Prompt,
Input_Template_UserChatInput
} from '../input';
import { chatNodeSystemPromptTip } from '../tip';
import { chatNodeSystemPromptTip, systemPromptTip } from '../tip';
import { LLMModelTypeEnum } from '../../../ai/constants';
import { getHandleConfig } from '../utils';
import { i18nT } from '../../../../../web/i18n/utils';
@@ -31,6 +31,7 @@ export const ToolModule: FlowNodeTemplateType = {
name: i18nT('workflow:template.tool_call'),
intro: i18nT('workflow:template.tool_call_intro'),
showStatus: true,
courseUrl: '/docs/workflow/modules/tool/',
version: '481',
inputs: [
{
@@ -62,7 +63,7 @@ export const ToolModule: FlowNodeTemplateType = {
{
...Input_Template_System_Prompt,
label: i18nT('common:core.ai.Prompt'),
description: chatNodeSystemPromptTip,
description: systemPromptTip,
placeholder: chatNodeSystemPromptTip
},
Input_Template_History,

View File

@@ -18,7 +18,7 @@ export const VariableUpdateNode: FlowNodeTemplateType = {
name: i18nT('workflow:variable_update'),
intro: i18nT('workflow:update_specified_node_output_or_global_variable'),
showStatus: false,
isTool: false,
isTool: true,
version: '481',
inputs: [
{

View File

@@ -30,6 +30,7 @@ export const WorkflowStart: FlowNodeTemplateType = {
intro: '',
forbidDelete: true,
unique: true,
courseUrl: '/docs/workflow/modules/input/',
version: '481',
inputs: [{ ...Input_Template_UserChatInput, toolDescription: i18nT('workflow:user_question') }],
outputs: [

View File

@@ -1 +1,2 @@
export const chatNodeSystemPromptTip = 'core.app.tip.chatNodeSystemPromptTip';
export const systemPromptTip = 'core.app.tip.systemPromptTip';

View File

@@ -35,7 +35,7 @@ export type WorkflowTemplateType = {
avatar: string;
intro?: string;
author?: string;
inputExplanationUrl?: string;
courseUrl?: string;
version: string;
showStatus?: boolean;

View File

@@ -50,6 +50,7 @@ export type FlowNodeInputItemType = InputComponentPropsType & {
description?: string; // field desc
required?: boolean;
toolDescription?: string; // If this field is not empty, it is entered as a tool
enum?: string;
// render components params
canEdit?: boolean; // dynamic inputs

View File

@@ -25,13 +25,13 @@ import { ParentIdType } from 'common/parentFolder/type';
import { AppTypeEnum } from 'core/app/constants';
export type FlowNodeCommonType = {
parentNodeId?: string;
flowNodeType: FlowNodeTypeEnum; // render node card
abandon?: boolean; // abandon node
avatar?: string;
name: string;
intro?: string; // template list intro
inputExplanationUrl?: string;
showStatus?: boolean; // chatting response step status
version: string;
@@ -68,6 +68,7 @@ export type FlowNodeTemplateType = FlowNodeCommonType & {
unique?: boolean;
diagram?: string; // diagram url
courseUrl?: string; // course url
};
export type NodeTemplateListItemType = {

View File

@@ -230,6 +230,7 @@ export const appData2FlowNodeIO = ({
FlowNodeInputTypeEnum.textarea,
FlowNodeInputTypeEnum.reference
],
[VariableInputEnum.numberInput]: [FlowNodeInputTypeEnum.numberInput],
[VariableInputEnum.select]: [FlowNodeInputTypeEnum.select],
[VariableInputEnum.custom]: [
FlowNodeInputTypeEnum.input,
@@ -246,7 +247,7 @@ export const appData2FlowNodeIO = ({
description: '',
valueType: WorkflowIOValueTypeEnum.any,
required: item.required,
list: item.enums.map((enumItem) => ({
list: item.enums?.map((enumItem) => ({
label: enumItem.value,
value: enumItem.value
}))
@@ -297,8 +298,9 @@ export const formatEditorVariablePickerIcon = (
}));
};
export const isReferenceValue = (value: any): boolean => {
return Array.isArray(value) && value.length === 2 && typeof value[0] === 'string';
export const isReferenceValue = (value: any, nodeIds: string[]): boolean => {
const validIdList = [VARIABLE_NODE_ID, ...nodeIds];
return Array.isArray(value) && value.length === 2 && validIdList.includes(value[0]);
};
export const getElseIFLabel = (i: number) => {
@@ -390,22 +392,25 @@ export function replaceEditorVariable({
}
];
}
return [];
return [
{
id: item.key,
value: item.value,
nodeId: runningNode.nodeId
}
];
});
const allVariables = [...globalVariables, ...nodeVariables, ...customInputs];
// Replace {{$xxx.xxx$}} to value
for (const key in allVariables) {
const val = allVariables[key];
const regex = new RegExp(`\\{\\{\\$(${val.nodeId}\\.${val.id})\\$\\}\\}`, 'g');
if (['string', 'number'].includes(typeof val.value)) {
text = text.replace(regex, String(val.value));
} else if (['object'].includes(typeof val.value)) {
text = text.replace(regex, JSON.stringify(val.value));
} else {
continue;
}
const variable = allVariables[key];
const val = variable.value;
const formatVal = typeof val === 'object' ? JSON.stringify(val) : String(val);
const regex = new RegExp(`\\{\\{\\$(${variable.nodeId}\\.${variable.id})\\$\\}\\}`, 'g');
text = text.replace(regex, formatVal);
}
return text || '';
}

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