Compare commits
53 Commits
v4.8.11-al
...
v4.8.12-al
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b0706ed92 | ||
|
|
718108a552 | ||
|
|
025facbc2d | ||
|
|
87b4061302 | ||
|
|
618729a254 | ||
|
|
3f34c33d4c | ||
|
|
779ff29ed5 | ||
|
|
445a38924f | ||
|
|
7ec2253f0a | ||
|
|
6522cc7dfa | ||
|
|
40f527a021 | ||
|
|
4aaf9bfeb0 | ||
|
|
5efa70f3a1 | ||
|
|
d45d18cc3b | ||
|
|
8bdb35ff51 | ||
|
|
e56965a8ed | ||
|
|
d4e0a43771 | ||
|
|
00638d6ee7 | ||
|
|
da281ea9ec | ||
|
|
4f1ce640a7 | ||
|
|
2a2b919daf | ||
|
|
3f01cc9c63 | ||
|
|
bc70428d89 | ||
|
|
d55ccc9f64 | ||
|
|
27ef4dc8ea | ||
|
|
daa5b552b1 | ||
|
|
fe6c8897ce | ||
|
|
0dcda9822e | ||
|
|
06e1c5d68d | ||
|
|
d52da7d4e0 | ||
|
|
a42707064a | ||
|
|
02bcab8802 | ||
|
|
27291faa66 | ||
|
|
3878a50d0f | ||
|
|
15b8353c7d | ||
|
|
b950146031 | ||
|
|
887e1d53d6 | ||
|
|
1dcd39bfbe | ||
|
|
01dad96618 | ||
|
|
13401294ad | ||
|
|
8273c96bbc | ||
|
|
61c6b1e471 | ||
|
|
f06aca9874 | ||
|
|
3a4b4a866b | ||
|
|
7afa8f00b8 | ||
|
|
f6c5695df4 | ||
|
|
dd3a1b910b | ||
|
|
a66d9d2e98 | ||
|
|
fc6f28f26e | ||
|
|
d4b99ddcab | ||
|
|
df328b2a73 | ||
|
|
fadb389294 | ||
|
|
7c38d1da9a |
2
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -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
|
After Width: | Height: | Size: 21 KiB |
2
.github/workflows/docs-deploy-kubeconfig.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Deploy image by kubeconfig
|
||||
name: Deploy doc image by kubeconfig
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
|
||||
2
.github/workflows/docs-deploy-vercel.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Deploy image to vercel
|
||||
name: Deploy doc image to vercel
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
7
.vscode/settings.json
vendored
@@ -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}`;"
|
||||
}
|
||||
@@ -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
|
||||
|
||||
扫码加入飞书话题群 (新开,逐渐弃用微信群):
|
||||
|
||||

|
||||

|
||||
|
||||
<a href="#readme">
|
||||
<img src="https://img.shields.io/badge/-返回顶部-7d09f1.svg" alt="#" align="right">
|
||||
|
||||
205
README_en.md
@@ -4,6 +4,8 @@
|
||||
|
||||
# FastGPT
|
||||
|
||||

|
||||
|
||||
<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.
|
||||
|
||||
</div>
|
||||
[](https://github.com/labring/FastGPT/stargazers)
|
||||
[](https://github.com/labring/FastGPT/pulls)
|
||||
[](https://github.com/labring/FastGPT/pulls)
|
||||
[](https://github.com/labring/FastGPT/blob/main/LICENSE)
|
||||
[](https://doc.tryfastgpt.ai/docs/intro)
|
||||
[](https://doc.tryfastgpt.ai/docs/intro)
|
||||
[](https://tryfastgpt.ai/)
|
||||
|
||||
<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">
|
||||
|
||||
[](https://discord.gg/mp68xkZn2Q)
|
||||
[](https://discord.gg/mp68xkZn2Q)
|
||||
[](https://oss.laf.run/otnvvf-imgs/feishu3.png)
|
||||
|
||||
</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 |
|
||||
|  |  |
|
||||
| Knowledge Base Setup | Integration Process |
|
||||
|  |  |
|
||||
|
||||
<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://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>
|
||||
5
docSite/assets/images/social/lark.svg
Normal 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 |
BIN
docSite/assets/imgs/image-1.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
docSite/assets/imgs/image-2.png
Normal file
|
After Width: | Height: | Size: 116 KiB |
BIN
docSite/assets/imgs/image-3.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
docSite/assets/imgs/image-4.png
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
docSite/assets/imgs/image.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
@@ -1,7 +1,7 @@
|
||||
---
|
||||
weight: 1100
|
||||
title: '商业版介绍'
|
||||
description: 'FastGPT 商业版介绍'
|
||||
title: '收费说明'
|
||||
description: 'FastGPT 收费说明'
|
||||
icon: 'shopping_cart'
|
||||
draft: false
|
||||
images: []
|
||||
|
||||
@@ -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
|
||||
---
|
||||
@@ -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)。
|
||||
@@ -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 = 上一步获取到的密钥
|
||||
```
|
||||
|
||||
|
||||
@@ -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/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"
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ weight: 707
|
||||
|
||||
### Milvus版本
|
||||
|
||||
暂不推荐,部分系统存在精度丢失,等待修复。
|
||||
|
||||
对于千万级以上向量性能更优秀。
|
||||
|
||||
[点击查看 Milvus 官方推荐配置](https://milvus.io/docs/prerequisite-docker.md)
|
||||
@@ -49,6 +51,8 @@ weight: 707
|
||||
|
||||
### zilliz cloud版本
|
||||
|
||||
暂不推荐,部分系统存在精度丢失,等待修复。
|
||||
|
||||
亿级以上向量首选。
|
||||
|
||||
由于向量库使用了 Cloud,无需占用本地资源,无需太关注。
|
||||
|
||||
@@ -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" />
|
||||
|
||||
## 代码结构说明
|
||||
|
||||
|
||||
@@ -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 '{
|
||||
|
||||
@@ -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": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "导演是谁",
|
||||
"role": "user"
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
{{< /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,728 @@ 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
|
||||
}'
|
||||
```
|
||||
|
||||
{{< /markdownify >}}
|
||||
{{< /tab >}}
|
||||
|
||||
{{< tab tabName="参数说明" >}}
|
||||
{{< markdownify >}}
|
||||
|
||||
{{% alert icon=" " context="success" %}}
|
||||
- appId - 应用 Id
|
||||
- offset - 偏移量,即从第几条数据开始取
|
||||
- pageSize - 记录数量
|
||||
{{% /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 >}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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 '{
|
||||
|
||||
@@ -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}} 替换成自己域名
|
||||
|
||||
@@ -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. 执行初始化
|
||||
|
||||
@@ -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,34 +80,70 @@ weight: 813
|
||||
|
||||
### 3. 修改镜像 tag 并重启
|
||||
|
||||
- 更新 FastGPT 镜像 tag: v4.8.11-alpha
|
||||
- 更新 FastGPT 商业版镜像 tag: v4.8.11-alpha
|
||||
- 更新 FastGPT Sandbox 镜像 tag: v4.8.11-alpha
|
||||
- 更新 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. 新增 - 子应用嵌套调用时,版本锁定。主应用未主动更新版本时,不会取最新版进行执行,保证主应用服务稳定。
|
||||
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. 优化 - 工作流嵌套层级限制 20 层,避免因编排不合理导致的无限死循环。
|
||||
16. 优化 - 工作流 handler 性能优化。
|
||||
17. 优化 - 工作流快捷键,避免调试测试时也会触发复制和回退。
|
||||
18. 修复 - 工作流工具调用中修改全局变量后,无法传递到后续流程。
|
||||
19. 优化 - 流输出,切换浏览器 Tab 后仍可以继续输出。
|
||||
20. 优化 - 完善外部文件知识库相关 API
|
||||
21. 修复 - 知识库选择权限问题。
|
||||
22. 修复 - 空 chatId 发起对话,首轮携带用户选择时会异常。
|
||||
23. 修复 - createDataset 接口,intro 为赋值。
|
||||
24. 修复 - 对话框渲染性能问题。
|
||||
25. 修复 - 工具调用历史记录存储不正确。
|
||||
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. 修复 - 全局变量在工具调用中未持久传递。
|
||||
|
||||
29
docSite/content/zh-cn/docs/development/upgrading/4812.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
title: 'V4.8.12(进行中)'
|
||||
description: 'FastGPT V4.8.12 更新说明'
|
||||
icon: 'upgrade'
|
||||
draft: false
|
||||
toc: true
|
||||
weight: 812
|
||||
---
|
||||
|
||||
## 更新指南
|
||||
|
||||
|
||||
## 更新说明
|
||||
|
||||
1. 新增 - 全局变量支持数字类型,支持配置默认值和部分输入框参数。
|
||||
2. 新增 - 插件自定义输入,文本输入框、数字输入框、选择框、开关,默认都支持作为变量引用。
|
||||
3. 新增 - FE_DOMAIN 环境变量,配置该环境变量后,上传文件/图片会补全后缀后得到完整地址。(可解决 docx 文件图片链接,有时模型会伪造图片域名)
|
||||
4. 新增 - 工具调用支持使用交互节点
|
||||
5. 新增 - Debug 模式支持输入全局变量
|
||||
6. 新增 - chat OpenAPI 文档
|
||||
7. 新增 - wiki 搜索插件
|
||||
8. 新增 - Google 搜索插件
|
||||
9. 新增 - 数据库连接和操作插件
|
||||
10. 新增 - Cookie 隐私协议提示
|
||||
11. 新增 - HTTP 节点支持 JSONPath 表达式
|
||||
12. 修复 - 文件后缀判断,去除 query 影响。
|
||||
13. 修复 - AI 响应为空时,会造成 LLM 历史记录合并。
|
||||
14. 修复 - 用户交互节点未阻塞流程。
|
||||
15. 修复 - 新建 APP,有时候会导致空指针报错。
|
||||
11
docSite/content/zh-cn/docs/faq/_index.md
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: 'FAQ'
|
||||
description: '常见问题的解答'
|
||||
icon: 'quiz'
|
||||
draft: false
|
||||
toc: true
|
||||
weight: 900
|
||||
---
|
||||
<!-- 9800 ~ 1000 -->
|
||||
|
||||
FastGPT 是一个由用户和贡献者参与推动的开源项目,如果您对产品使用存在疑问和建议,可尝试[加入社区](community)寻求支持。我们的团队与社区会竭尽所能为您提供帮助。
|
||||
16
docSite/content/zh-cn/docs/faq/app.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
title: '应用使用问题'
|
||||
description: 'FastGPT 常见应用使用问题,包括简易应用、工作流和插件'
|
||||
icon: 'quiz'
|
||||
draft: false
|
||||
toc: true
|
||||
weight: 903
|
||||
---
|
||||
|
||||
## 工作流中多轮对话场景中如何使连续问题被问题分类节点正确的归类
|
||||
|
||||
问题分类节点具有获取上下文信息的能力,当处理两个关联性较大的问题时,模型的判断准确性往往依赖于这两个问题之间的联系和模型的能力。例如,当用户先问“我该如何使用这个功能?”接着又询问“这个功能有什么限制?”时,模型借助上下文信息,就能够更精准地理解并响应。
|
||||
|
||||
但是,当连续问题之间的关联性较小,模型判断的准确度可能会受到限制。在这种情况下,我们可以引入全局变量的概念来记录分类结果。在后续的问题分类阶段,首先检查全局变量是否存有分类结果。如果有,那么直接沿用该结果;若没有,则让模型自行判断。
|
||||
|
||||
建议:构建批量运行脚本进行测试,评估问题分类的准确性。
|
||||
18
docSite/content/zh-cn/docs/faq/chat.md
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
title: '聊天框问题'
|
||||
description: 'FastGPT 常见聊天框问题'
|
||||
icon: 'quiz'
|
||||
draft: false
|
||||
toc: true
|
||||
weight: 905
|
||||
---
|
||||
|
||||
## 我修改了工作台的应用,为什么在“聊天”时没有更新配置?
|
||||
|
||||
应用需要点击发布后,聊天才会更新应用。
|
||||
|
||||
## 浏览器不支持语音输入
|
||||
|
||||
1. 首先需要确保浏览器、电脑本身麦克风权限的开启。
|
||||
2. 确认浏览器允许该站点使用麦克风,并且选择正确的麦克风来源。
|
||||
3. 需有 SSL 证书的站点才可以使用麦克风。
|
||||
17
docSite/content/zh-cn/docs/faq/dataset.md
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
title: '知识库使用问题'
|
||||
description: '常见知识库使用问题'
|
||||
icon: 'quiz'
|
||||
draft: false
|
||||
toc: true
|
||||
weight: 904
|
||||
---
|
||||
|
||||
## 上传的文件内容出现中文乱码
|
||||
|
||||
将文件另存为 UTF-8 编码格式。
|
||||
|
||||
## 知识库配置里的文件处理模型是什么?与索引模型有什么区别?
|
||||
|
||||
* **文件处理模型**:用于数据处理的【增强处理】和【问答拆分】。在【增强处理】中,生成相关问题和摘要,在【问答拆分】中执行问答对生成。
|
||||
* **索引模型**:用于向量化,即通过对文本数据进行处理和组织,构建出一个能够快速查询的数据结构。
|
||||
10
docSite/content/zh-cn/docs/faq/docker.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: 'Docker 部署问题'
|
||||
description: 'FastGPT Docker 部署问题'
|
||||
icon: ''
|
||||
draft: false
|
||||
toc: true
|
||||
weight: 901
|
||||
type: redirect
|
||||
target: /docs/development/docker/#faq
|
||||
---
|
||||
7
docSite/content/zh-cn/docs/faq/error.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: '常见错误'
|
||||
icon: 'quiz'
|
||||
draft: false
|
||||
toc: true
|
||||
weight: 920
|
||||
---
|
||||
11
docSite/content/zh-cn/docs/faq/other.md
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: '其他问题'
|
||||
icon: 'quiz'
|
||||
draft: false
|
||||
toc: true
|
||||
weight: 925
|
||||
---
|
||||
|
||||
## oneapi 官网是哪个
|
||||
|
||||
只有开源的 README,没官网,GitHub: https://github.com/songquanpeng/one-api
|
||||
10
docSite/content/zh-cn/docs/faq/privateDeploy.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
title: "私有部署常见问题"
|
||||
description: "FastGPT 私有部署常见问题"
|
||||
icon: upgrade
|
||||
draft: false
|
||||
images: []
|
||||
weight: 902
|
||||
type: redirect
|
||||
target: /docs/development/faq/
|
||||
---
|
||||
@@ -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: ''
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
87
docSite/content/zh-cn/docs/workflow/modules/sandbox.md
Normal file
@@ -0,0 +1,87 @@
|
||||
---
|
||||
title: "代码运行"
|
||||
description: "FastGPT 代码运行节点介绍"
|
||||
icon: "input"
|
||||
draft: false
|
||||
toc: true
|
||||
weight: 364
|
||||
---
|
||||
|
||||

|
||||
|
||||
## 功能
|
||||
|
||||
可用于执行一段简单的 js 代码,用于进行一些复杂的数据处理。代码运行在沙盒中,无法进行网络请求、dom和异步操作。如需复杂操作,需外挂 HTTP 实现。
|
||||
|
||||
**注意事项**
|
||||
|
||||
- 私有化用户需要部署`fastgpt-sandbox` 镜像,并配置`SANDBOX_URL`环境变量。
|
||||
- 沙盒最大运行 10s, 32M 内存限制。
|
||||
|
||||
|
||||
## 变量输入
|
||||
|
||||
可在自定义输入中添加代码运行需要的变量,在代码的 main 函数中,可解构出相同名字的变量。
|
||||
|
||||
如上图,自定义输入中有 data1 和 data2 两个变量,main 函数中可以解构出相同名字的变量。
|
||||
|
||||
## 结果输出
|
||||
|
||||
务必返回一个 object 对象
|
||||
|
||||
自定义输出中,可以添加变量名来获取 object 对应 key 下的值。例如上图中,返回了一个对象:
|
||||
|
||||
```json
|
||||
{
|
||||
result: data1,
|
||||
data2
|
||||
}
|
||||
```
|
||||
|
||||
他有 2 个 key:result和 data2(js 缩写,key=data2,value=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)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
|
||||
### 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,')
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
@@ -35,8 +35,6 @@ weight: 356
|
||||
1. 无必须的参数:尽管上下文中,没有适合的参数,也可以调用该工具。但有时候,LLM会自己伪造一个参数。
|
||||
2. 有必须的参数:如果没有适合的参数,LLM可能不会调用该工具。可以通过提示词,引导用户提供参数。
|
||||
|
||||
### 工具调用逻辑
|
||||
|
||||
在支持`函数调用`的模型中,可以一次性调用多个工具,调用逻辑如下:
|
||||
|
||||

|
||||
@@ -49,10 +47,24 @@ weight: 356
|
||||
|
||||
高级编排中,托动工具调用的连接点,可用的工具头部会出现一个菱形,可以将它与工具调用模块底部的菱形相连接。
|
||||
|
||||
被连接的工具,会自动分离工具输入与普通的输入,并且可以编辑`介绍`,可以通过调整介绍,使得该工具调用时机更加精确。
|
||||
被连接的工具,会自动分离工具输入与普通的输入,并且可以编辑`描述`,可以通过调整介绍,使得该工具调用时机更加精确。对于一些内置的节点,务必修改`描述`才能让模型正常调用。
|
||||
|
||||
关于工具调用,如何调试仍然是一个玄学,所以建议,不要一次性增加太多工具,选择少量工具调优后再进一步尝试。
|
||||
|
||||
## 组合节点
|
||||
|
||||
### 工具调用终止
|
||||
|
||||
工具调用默认会把子流程运行的结果作为`工具结果`,返回给模型进行回答。有时候,你可能不希望模型做回答,你可以给对应子流程的末尾增加上一个`工具调用终止`节点,这样,子流程的结果就不会被返回给模型。
|
||||
|
||||

|
||||
|
||||
### 自定义工具变量
|
||||
|
||||
工具调用的子流程运行,有时候会依赖`AI`生成的一些变量,为了简化交互流程,我们给系统内置的节点都指定了`工具变量`。然而,有些时候,你需要的变量不仅是目标流程的`首个节点`的变量,而是需要更复杂的变量,此时你可以使用`自定义工具变量`。它允许你完全自定义该`工具流程`的变量。
|
||||
|
||||

|
||||
|
||||
## 相关示例
|
||||
|
||||
- [谷歌搜索](/docs/workflow/examples/google_search/)
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
{{ $.Scratch.Set "pathName" (printf "%s" (.Site.Params.docs.pathName | default "docs")) }}
|
||||
<!-- 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 .) }}
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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) {
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -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`;
|
||||
|
||||
34
packages/global/core/ai/type.d.ts
vendored
@@ -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 & {
|
||||
export type ChatCompletionMessageFunctionCall =
|
||||
SdkChatCompletionAssistantMessageParam.FunctionCall & {
|
||||
id?: string;
|
||||
toolName?: string;
|
||||
toolAvatar?: string;
|
||||
};
|
||||
};
|
||||
|
||||
// Stream response
|
||||
export type StreamChatType = Stream<ChatCompletionChunk>;
|
||||
|
||||
17
packages/global/core/app/type.d.ts
vendored
@@ -13,6 +13,7 @@ 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;
|
||||
@@ -114,11 +115,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 = {
|
||||
|
||||
@@ -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
|
||||
})
|
||||
.concat(toolResponse);
|
||||
} else if (value.text?.content) {
|
||||
results.push({
|
||||
});
|
||||
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,
|
||||
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
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
packages/global/core/chat/api.d.ts
vendored
@@ -1,7 +1,7 @@
|
||||
export type UpdateChatFeedbackProps = {
|
||||
appId: string;
|
||||
chatId: string;
|
||||
chatItemId: string;
|
||||
dataId: string;
|
||||
shareId?: string;
|
||||
teamId?: string;
|
||||
teamToken?: string;
|
||||
|
||||
6
packages/global/core/chat/type.d.ts
vendored
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}, []);
|
||||
};
|
||||
|
||||
@@ -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
|
||||
@@ -213,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')
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ export type RuntimeNodeItemType = {
|
||||
intro?: StoreNodeItemType['intro'];
|
||||
flowNodeType: StoreNodeItemType['flowNodeType'];
|
||||
showStatus?: StoreNodeItemType['showStatus'];
|
||||
isEntry?: StoreNodeItemType['isEntry'];
|
||||
isEntry?: boolean;
|
||||
|
||||
inputs: FlowNodeInputItemType[];
|
||||
outputs: FlowNodeOutputItemType[];
|
||||
@@ -108,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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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: [
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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: [
|
||||
{
|
||||
|
||||
@@ -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: [
|
||||
{
|
||||
|
||||
@@ -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: [
|
||||
{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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: [
|
||||
{
|
||||
|
||||
@@ -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: [
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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: [
|
||||
{
|
||||
|
||||
@@ -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: [
|
||||
{
|
||||
|
||||
@@ -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: [
|
||||
{
|
||||
|
||||
@@ -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: [
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ export const ToolParamsNode: FlowNodeTemplateType = {
|
||||
sourceHandle: getHandleConfig(true, true, true, true),
|
||||
targetHandle: getHandleConfig(true, true, true, true),
|
||||
avatar: 'core/workflow/template/toolParams',
|
||||
name: i18nT('workflow:tool_params_config'),
|
||||
name: i18nT('workflow:tool_custom_field'),
|
||||
intro: i18nT('workflow:intro_tool_params_config'),
|
||||
version: '4811',
|
||||
isTool: true,
|
||||
|
||||
@@ -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: [
|
||||
{
|
||||
|
||||
@@ -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: [
|
||||
|
||||
@@ -35,7 +35,7 @@ export type WorkflowTemplateType = {
|
||||
avatar: string;
|
||||
intro?: string;
|
||||
author?: string;
|
||||
inputExplanationUrl?: string;
|
||||
courseUrl?: string;
|
||||
version: string;
|
||||
|
||||
showStatus?: boolean;
|
||||
|
||||
3
packages/global/core/workflow/type/node.d.ts
vendored
@@ -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 = {
|
||||
|
||||
@@ -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
|
||||
}))
|
||||
@@ -298,7 +299,8 @@ export const formatEditorVariablePickerIcon = (
|
||||
};
|
||||
|
||||
export const isReferenceValue = (value: any, nodeIds: string[]): boolean => {
|
||||
return Array.isArray(value) && value.length === 2 && nodeIds.includes(value[0]);
|
||||
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 || '';
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { RequireAtLeastOne, RequireOnlyOne } from '../../common/type/utils';
|
||||
import { Permission } from './controller';
|
||||
import { PermissionValueType } from './type';
|
||||
|
||||
@@ -10,6 +11,19 @@ export type CollaboratorItemType = {
|
||||
};
|
||||
|
||||
export type UpdateClbPermissionProps = {
|
||||
tmbIds: string[];
|
||||
members?: string[];
|
||||
groups?: string[];
|
||||
permission: PermissionValueType;
|
||||
};
|
||||
|
||||
export type DeleteClbPermissionProps = RequireOnlyOne<{
|
||||
tmbId: string;
|
||||
groupId: string;
|
||||
}>;
|
||||
|
||||
export type UpdatePermissionBody = {
|
||||
permission: PermissionValueType;
|
||||
} & RequireOnlyOne<{
|
||||
memberId: string;
|
||||
groupId: string;
|
||||
}>;
|
||||
|
||||
@@ -61,7 +61,7 @@ export const PermissionList: PermissionListType = {
|
||||
[PermissionKeyEnum.write]: {
|
||||
name: i18nT('common:permission.write'),
|
||||
description: '',
|
||||
value: 0b110, // 如果某个资源有特殊要求,再重写这个值
|
||||
value: 0b110,
|
||||
checkBoxType: 'single'
|
||||
},
|
||||
[PermissionKeyEnum.manage]: {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { PermissionValueType } from './type';
|
||||
import { PermissionListType, PermissionValueType } from './type';
|
||||
import { PermissionList, NullPermission, OwnerPermissionVal } from './constant';
|
||||
|
||||
export type PerConstructPros = {
|
||||
per?: PermissionValueType;
|
||||
isOwner?: boolean;
|
||||
permissionList?: PermissionListType;
|
||||
};
|
||||
|
||||
// the Permission helper class
|
||||
@@ -13,9 +14,10 @@ export class Permission {
|
||||
hasManagePer: boolean;
|
||||
hasWritePer: boolean;
|
||||
hasReadPer: boolean;
|
||||
_permissionList: PermissionListType;
|
||||
|
||||
constructor(props?: PerConstructPros) {
|
||||
const { per = NullPermission, isOwner = false } = props || {};
|
||||
const { per = NullPermission, isOwner = false, permissionList = PermissionList } = props || {};
|
||||
if (isOwner) {
|
||||
this.value = OwnerPermissionVal;
|
||||
} else {
|
||||
@@ -23,9 +25,10 @@ export class Permission {
|
||||
}
|
||||
|
||||
this.isOwner = isOwner;
|
||||
this.hasManagePer = this.checkPer(PermissionList['manage'].value);
|
||||
this.hasWritePer = this.checkPer(PermissionList['write'].value);
|
||||
this.hasReadPer = this.checkPer(PermissionList['read'].value);
|
||||
this._permissionList = permissionList;
|
||||
this.hasManagePer = this.checkPer(this._permissionList['manage'].value);
|
||||
this.hasWritePer = this.checkPer(this._permissionList['write'].value);
|
||||
this.hasReadPer = this.checkPer(this._permissionList['read'].value);
|
||||
}
|
||||
|
||||
// add permission(s)
|
||||
@@ -36,36 +39,39 @@ export class Permission {
|
||||
// perm.add(PermissionList['read'], PermissionList['write'])
|
||||
// perm.add(PermissionList['read']).add(PermissionList['write'])
|
||||
addPer(...perList: PermissionValueType[]) {
|
||||
for (let oer of perList) {
|
||||
this.value = this.value | oer;
|
||||
if (this.isOwner) {
|
||||
return this;
|
||||
}
|
||||
for (const per of perList) {
|
||||
this.value = this.value | per;
|
||||
}
|
||||
this.updatePermissions();
|
||||
return this.value;
|
||||
return this;
|
||||
}
|
||||
|
||||
removePer(...perList: PermissionValueType[]) {
|
||||
for (let per of perList) {
|
||||
if (this.isOwner) {
|
||||
return this.value;
|
||||
}
|
||||
for (const per of perList) {
|
||||
this.value = this.value & ~per;
|
||||
}
|
||||
this.updatePermissions();
|
||||
return this.value;
|
||||
return this;
|
||||
}
|
||||
|
||||
checkPer(perm: PermissionValueType): boolean {
|
||||
// if the permission is owner permission, only owner has this permission.
|
||||
if (perm === OwnerPermissionVal) {
|
||||
return this.value === OwnerPermissionVal;
|
||||
} else if (this.hasManagePer) {
|
||||
// The manager has all permissions except the owner permission
|
||||
return true;
|
||||
}
|
||||
return (this.value & perm) === perm;
|
||||
}
|
||||
|
||||
private updatePermissions() {
|
||||
this.isOwner = this.value === OwnerPermissionVal;
|
||||
this.hasManagePer = this.checkPer(PermissionList['manage'].value);
|
||||
this.hasWritePer = this.checkPer(PermissionList['write'].value);
|
||||
this.hasReadPer = this.checkPer(PermissionList['read'].value);
|
||||
this.hasManagePer = this.checkPer(this._permissionList['manage'].value);
|
||||
this.hasWritePer = this.checkPer(this._permissionList['write'].value);
|
||||
this.hasReadPer = this.checkPer(this._permissionList['read'].value);
|
||||
}
|
||||
}
|
||||
|
||||
23
packages/global/support/permission/memberGroup/constant.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { PermissionKeyEnum, PermissionList } from '../constant';
|
||||
import { PermissionListType } from '../type';
|
||||
|
||||
export enum GroupMemberRole {
|
||||
owner = 'owner',
|
||||
admin = 'admin',
|
||||
member = 'member'
|
||||
}
|
||||
|
||||
export const memberGroupPermissionList: PermissionListType = {
|
||||
[PermissionKeyEnum.read]: {
|
||||
...PermissionList[PermissionKeyEnum.read],
|
||||
value: 0b100
|
||||
},
|
||||
[PermissionKeyEnum.write]: {
|
||||
...PermissionList[PermissionKeyEnum.write],
|
||||
value: 0b010
|
||||
},
|
||||
[PermissionKeyEnum.manage]: {
|
||||
...PermissionList[PermissionKeyEnum.manage],
|
||||
value: 0b001
|
||||
}
|
||||
};
|
||||
27
packages/global/support/permission/memberGroup/type.d.ts
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { TeamMemberItemType } from 'support/user/team/type';
|
||||
import { TeamPermission } from '../user/controller';
|
||||
import { GroupMemberRole } from './constant';
|
||||
|
||||
type MemberGroupSchemaType = {
|
||||
_id: string;
|
||||
teamId: string;
|
||||
name: string;
|
||||
avatar: string;
|
||||
updateTime: Date;
|
||||
};
|
||||
|
||||
type GroupMemberSchemaType = {
|
||||
groupId: string;
|
||||
tmbId: string;
|
||||
role: `${GroupMemberRole}`;
|
||||
};
|
||||
|
||||
type MemberGroupType = MemberGroupSchemaType & {
|
||||
members: {
|
||||
tmbId: string;
|
||||
role: `${GroupMemberRole}`;
|
||||
}[]; // we can get tmb's info from other api. there is no need but only need to get tmb's id
|
||||
permission: TeamPermission;
|
||||
};
|
||||
|
||||
type MemberGroupListType = MemberGroupType[];
|
||||
7
packages/global/support/permission/type.d.ts
vendored
@@ -1,3 +1,4 @@
|
||||
import { RequireOnlyOne } from '../../common/type/utils';
|
||||
import { TeamMemberWithUserSchema } from '../user/team/type';
|
||||
import { AuthUserTypeEnum, PermissionKeyEnum, PerResourceTypeEnum } from './constant';
|
||||
|
||||
@@ -20,11 +21,13 @@ export type PermissionListType<T = {}> = Record<
|
||||
|
||||
export type ResourcePermissionType = {
|
||||
teamId: string;
|
||||
tmbId: string;
|
||||
resourceType: ResourceType;
|
||||
permission: PermissionValueType;
|
||||
resourceId: string;
|
||||
};
|
||||
} & RequireOnlyOne<{
|
||||
tmbId: string;
|
||||
groupId: string;
|
||||
}>;
|
||||
|
||||
export type ResourcePerWithTmbWithUser = Omit<ResourcePermissionType, 'tmbId'> & {
|
||||
tmbId: TeamMemberWithUserSchema;
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
import { PermissionKeyEnum, PermissionList, ReadPermissionVal } from '../constant';
|
||||
import { PermissionKeyEnum } from '../constant';
|
||||
import { PermissionListType } from '../type';
|
||||
import { i18nT } from '../../../../web/i18n/utils';
|
||||
import { PermissionList } from '../constant';
|
||||
export const TeamPermissionList: PermissionListType = {
|
||||
[PermissionKeyEnum.read]: {
|
||||
...PermissionList[PermissionKeyEnum.read],
|
||||
description: i18nT('user:permission_des.read')
|
||||
value: 0b100
|
||||
},
|
||||
[PermissionKeyEnum.write]: {
|
||||
...PermissionList[PermissionKeyEnum.write],
|
||||
description: i18nT('user:permission_des.write')
|
||||
value: 0b010
|
||||
},
|
||||
[PermissionKeyEnum.manage]: {
|
||||
...PermissionList[PermissionKeyEnum.manage],
|
||||
description: i18nT('user:permission_des.manage')
|
||||
value: 0b001
|
||||
}
|
||||
};
|
||||
|
||||
export const TeamDefaultPermissionVal = ReadPermissionVal;
|
||||
export const TeamReadPermissionVal = TeamPermissionList['read'].value;
|
||||
export const TeamWritePermissionVal = TeamPermissionList['write'].value;
|
||||
export const TeamManagePermissionVal = TeamPermissionList['manage'].value;
|
||||
export const TeamDefaultPermissionVal = TeamReadPermissionVal;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { PerConstructPros, Permission } from '../controller';
|
||||
import { TeamDefaultPermissionVal } from './constant';
|
||||
import { TeamDefaultPermissionVal, TeamPermissionList } from './constant';
|
||||
|
||||
export class TeamPermission extends Permission {
|
||||
constructor(props?: PerConstructPros) {
|
||||
@@ -10,6 +10,7 @@ export class TeamPermission extends Permission {
|
||||
} else if (!props?.per) {
|
||||
props.per = TeamDefaultPermissionVal;
|
||||
}
|
||||
props.permissionList = TeamPermissionList;
|
||||
super(props);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ export type UpdateTeamMemberProps = {
|
||||
export type InviteMemberProps = {
|
||||
teamId: string;
|
||||
usernames: string[];
|
||||
permission: PermissionValueType;
|
||||
};
|
||||
export type UpdateInviteProps = {
|
||||
tmbId: string;
|
||||
|
||||
17
packages/global/support/user/team/group/api.d.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import { GroupMemberRole } from '../../../../support/permission/memberGroup/constant';
|
||||
|
||||
export type postCreateGroupData = {
|
||||
name: string;
|
||||
avatar?: string;
|
||||
memberIdList?: string[];
|
||||
};
|
||||
|
||||
export type putUpdateGroupData = {
|
||||
groupId: string;
|
||||
name?: string;
|
||||
avatar?: string;
|
||||
memberList?: {
|
||||
tmbId: string;
|
||||
role: `${GroupMemberRole}`;
|
||||
}[];
|
||||
};
|
||||
1
packages/global/support/user/team/group/constant.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const DefaultGroupName = 'DEFAULT_GROUP';
|
||||
4
packages/global/support/user/team/type.d.ts
vendored
@@ -17,7 +17,6 @@ export type TeamSchema = {
|
||||
lastWebsiteSyncTime: Date;
|
||||
};
|
||||
lafAccount: LafAccountType;
|
||||
defaultPermission: PermissionValueType;
|
||||
notificationAccount?: string;
|
||||
};
|
||||
|
||||
@@ -25,6 +24,7 @@ export type tagsType = {
|
||||
label: string;
|
||||
key: string;
|
||||
};
|
||||
|
||||
export type TeamTagSchema = TeamTagItemType & {
|
||||
_id: string;
|
||||
teamId: string;
|
||||
@@ -45,9 +45,11 @@ export type TeamMemberSchema = {
|
||||
export type TeamMemberWithUserSchema = Omit<TeamMemberSchema, 'userId'> & {
|
||||
userId: UserModelSchema;
|
||||
};
|
||||
|
||||
export type TeamMemberWithTeamSchema = Omit<TeamMemberSchema, 'teamId'> & {
|
||||
teamId: TeamSchema;
|
||||
};
|
||||
|
||||
export type TeamMemberWithTeamAndUserSchema = Omit<TeamMemberWithTeamSchema, 'userId'> & {
|
||||
userId: UserModelSchema;
|
||||
};
|
||||
|
||||
@@ -3,11 +3,16 @@
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"duck-duck-scrape": "^2.2.5",
|
||||
"lodash": "^4.17.21",
|
||||
"@types/pg": "^8.6.6",
|
||||
"axios": "^1.5.1",
|
||||
"duck-duck-scrape": "^2.2.5",
|
||||
"echarts": "5.4.1",
|
||||
"expr-eval": "^2.0.2",
|
||||
"echarts": "5.4.1"
|
||||
"lodash": "^4.17.21",
|
||||
"mysql2": "^3.11.3",
|
||||
"json5": "^2.2.3",
|
||||
"pg": "^8.10.0",
|
||||
"wikijs": "^6.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fastgpt/global": "workspace:*",
|
||||
|
||||
@@ -13,7 +13,8 @@ const staticPluginList = [
|
||||
'Doc2X/URLImg2text',
|
||||
`Doc2X/FilePDF2text`,
|
||||
`Doc2X/FileImg2text`,
|
||||
'feishu'
|
||||
'feishu',
|
||||
'google'
|
||||
];
|
||||
// Run in worker thread (Have npm packages)
|
||||
const packagePluginList = [
|
||||
@@ -24,7 +25,9 @@ const packagePluginList = [
|
||||
'duckduckgo/searchNews',
|
||||
'duckduckgo/searchVideo',
|
||||
'drawing',
|
||||
'drawing/baseChart'
|
||||
'drawing/baseChart',
|
||||
'wiki',
|
||||
'databaseConnection'
|
||||
];
|
||||
|
||||
export const list = [...staticPluginList, ...packagePluginList];
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"name": "Doc2X 图像(文件)识别",
|
||||
"avatar": "plugins/doc2x",
|
||||
"intro": "将上传的图片文件发送至Doc2X进行解析,返回带LaTeX公式的markdown格式的文本",
|
||||
"inputExplanationUrl": "https://fael3z0zfze.feishu.cn/wiki/Rkc5witXWiJoi5kORd2cofh6nDg?fromScene=spaceOverview",
|
||||
"courseUrl": "https://fael3z0zfze.feishu.cn/wiki/Rkc5witXWiJoi5kORd2cofh6nDg?fromScene=spaceOverview",
|
||||
"showStatus": true,
|
||||
"weight": 10,
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"name": "Doc2X PDF文件(文件)识别",
|
||||
"avatar": "plugins/doc2x",
|
||||
"intro": "将上传的PDF文件发送至Doc2X进行解析,返回带LaTeX公式的markdown格式的文本",
|
||||
"inputExplanationUrl": "https://fael3z0zfze.feishu.cn/wiki/Rkc5witXWiJoi5kORd2cofh6nDg?fromScene=spaceOverview",
|
||||
"courseUrl": "https://fael3z0zfze.feishu.cn/wiki/Rkc5witXWiJoi5kORd2cofh6nDg?fromScene=spaceOverview",
|
||||
"showStatus": true,
|
||||
"weight": 10,
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"name": "Doc2X 图像(URL)识别",
|
||||
"avatar": "plugins/doc2x",
|
||||
"intro": "从URL下载图片并发送至Doc2X进行解析,返回带LaTeX公式的markdown格式的文本",
|
||||
"inputExplanationUrl": "https://fael3z0zfze.feishu.cn/wiki/Rkc5witXWiJoi5kORd2cofh6nDg?fromScene=spaceOverview",
|
||||
"courseUrl": "https://fael3z0zfze.feishu.cn/wiki/Rkc5witXWiJoi5kORd2cofh6nDg?fromScene=spaceOverview",
|
||||
"showStatus": true,
|
||||
"weight": 10,
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"name": "Doc2X PDF文件(URL)识别",
|
||||
"avatar": "plugins/doc2x",
|
||||
"intro": "从URL下载PDF文件,并发送至Doc2X进行解析,返回带LaTeX公式的markdown格式的文本",
|
||||
"inputExplanationUrl": "https://fael3z0zfze.feishu.cn/wiki/Rkc5witXWiJoi5kORd2cofh6nDg?fromScene=spaceOverview",
|
||||
"courseUrl": "https://fael3z0zfze.feishu.cn/wiki/Rkc5witXWiJoi5kORd2cofh6nDg?fromScene=spaceOverview",
|
||||
"showStatus": true,
|
||||
"weight": 10,
|
||||
|
||||
|
||||