Commit c20fba11 by Carson Yang Committed by GitHub

docs: update the framework of doc site (#207)

Signed-off-by: Carson Yang <yangchuansheng33@gmail.com>
parent c7d0975f
...@@ -29,4 +29,8 @@ next-env.d.ts ...@@ -29,4 +29,8 @@ next-env.d.ts
platform.json platform.json
testApi/ testApi/
local/ local/
dist/ dist/
\ No newline at end of file
# hugo
**/.hugo_build.lock
docSite/public/
\ No newline at end of file
# Dependencies
/node_modules
# Production
/build
# Generated files
.docusaurus
.cache-loader
# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Website
This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
### Installation
```
$ yarn
```
### Local Development
```
$ yarn start
```
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
### Build
```
$ yarn build
```
This command generates static content into the `build` directory and can be served using any static contents hosting service.
### Deployment
Using SSH:
```
$ USE_SSH=true yarn deploy
```
Not using SSH:
```
$ GIT_USER=<Your GitHub username> yarn deploy
```
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
---
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 28 28" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<title>微信群</title>
<path d="M21.6696 15.9962C21.9464 15.9925 22.2107 15.881 22.4064 15.6853C22.6021 15.4896 22.7137 15.2252 22.7173 14.9485C22.7173 14.3675 22.2518 13.9008 21.6696 13.9008C21.0875 13.9008 20.622 14.3675 20.622 14.9485C20.622 15.5318 21.0886 15.9962 21.6696 15.9962ZM16.5071 15.9962C16.7839 15.9925 17.0482 15.881 17.2439 15.6853C17.4396 15.4896 17.5512 15.2252 17.5548 14.9485C17.5548 14.3675 17.0881 13.9008 16.5071 13.9008C15.9238 13.9008 15.4595 14.3675 15.4595 14.9485C15.4595 15.5318 15.925 15.9962 16.5071 15.9962ZM24.1686 21.8762C24.0939 21.9177 24.0342 21.9818 23.9981 22.0594C23.9621 22.1369 23.9515 22.2239 23.968 22.3078C23.968 22.3638 23.968 22.421 23.9971 22.4793C24.1115 22.9658 24.3401 23.7405 24.3401 23.7697C24.3401 23.8548 24.3693 23.912 24.3693 23.9703C24.3693 24.0041 24.3626 24.0376 24.3496 24.0688C24.3367 24.1 24.3177 24.1284 24.2937 24.1522C24.2697 24.1761 24.2413 24.195 24.21 24.2078C24.1788 24.2206 24.1453 24.2272 24.1115 24.227C24.0531 24.227 24.0251 24.199 23.968 24.171L22.2775 23.1957C22.154 23.1277 22.0168 23.0886 21.8761 23.0813C21.791 23.0813 21.7046 23.0813 21.6475 23.1093C20.8448 23.3392 20.0141 23.4535 19.1263 23.4535C14.8563 23.4535 11.4181 20.587 11.4181 17.031C11.4181 13.4762 14.8563 10.6085 19.1263 10.6085C23.3951 10.6085 26.8333 13.4762 26.8333 17.031C26.8333 18.9525 25.802 20.7013 24.1686 21.8773V21.8762ZM19.4518 9.44883C19.3429 9.44521 19.234 9.44327 19.1251 9.443C14.2555 9.443 10.2515 12.7797 10.2515 17.0322C10.2515 17.6785 10.3448 18.3038 10.5175 18.8988H10.4136C9.39426 18.8885 8.38067 18.7442 7.39896 18.4695C7.31263 18.4403 7.22629 18.4403 7.13996 18.4403C6.96754 18.444 6.79921 18.4935 6.65229 18.5838L4.61296 19.7563C4.55463 19.7855 4.49746 19.8147 4.44029 19.8147C4.35703 19.8138 4.27744 19.7803 4.21856 19.7214C4.15968 19.6625 4.1262 19.5829 4.12529 19.4997C4.12529 19.4133 4.15329 19.3562 4.18246 19.2698C4.21046 19.2418 4.46946 18.2968 4.61296 17.7252C4.61296 17.6668 4.64096 17.5817 4.64096 17.5245C4.64065 17.4245 4.61721 17.3259 4.57248 17.2364C4.52775 17.147 4.46295 17.0691 4.38313 17.0088C2.40096 15.6053 1.16663 13.517 1.16663 11.1977C1.16663 6.93583 5.33163 3.5 10.4416 3.5C14.8341 3.5 18.5266 6.0305 19.4518 9.44767V9.44883ZM13.4388 9.9365C14.1073 9.9365 14.6358 9.38 14.6358 8.7395C14.6358 8.071 14.1073 7.5425 13.4388 7.5425C12.7703 7.5425 12.2418 8.071 12.2418 8.7395C12.2418 9.408 12.7703 9.9365 13.4388 9.9365ZM7.30213 9.9365C7.97063 9.9365 8.50029 9.38 8.50029 8.7395C8.50029 8.071 7.97063 7.5425 7.30213 7.5425C6.63479 7.5425 6.10513 8.071 6.10513 8.7395C6.10513 9.408 6.63479 9.9365 7.30213 9.9365Z"/>
</svg>
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_280_54)">
<path d="M21.6696 15.9962C21.9464 15.9925 22.2107 15.881 22.4064 15.6853C22.6021 15.4896 22.7137 15.2252 22.7173 14.9485C22.7173 14.3675 22.2518 13.9008 21.6696 13.9008C21.0875 13.9008 20.622 14.3675 20.622 14.9485C20.622 15.5318 21.0886 15.9962 21.6696 15.9962ZM16.5071 15.9962C16.7839 15.9925 17.0482 15.881 17.2439 15.6853C17.4396 15.4896 17.5512 15.2252 17.5548 14.9485C17.5548 14.3675 17.0881 13.9008 16.5071 13.9008C15.9238 13.9008 15.4595 14.3675 15.4595 14.9485C15.4595 15.5318 15.925 15.9962 16.5071 15.9962ZM24.1686 21.8762C24.0939 21.9177 24.0342 21.9818 23.9981 22.0594C23.9621 22.1369 23.9515 22.2239 23.968 22.3078C23.968 22.3638 23.968 22.421 23.9971 22.4793C24.1115 22.9658 24.3401 23.7405 24.3401 23.7697C24.3401 23.8548 24.3693 23.912 24.3693 23.9703C24.3693 24.0041 24.3626 24.0376 24.3496 24.0688C24.3367 24.1 24.3177 24.1284 24.2937 24.1522C24.2697 24.1761 24.2413 24.195 24.21 24.2078C24.1788 24.2206 24.1453 24.2272 24.1115 24.227C24.0531 24.227 24.0251 24.199 23.968 24.171L22.2775 23.1957C22.154 23.1277 22.0168 23.0886 21.8761 23.0813C21.791 23.0813 21.7046 23.0813 21.6475 23.1093C20.8448 23.3392 20.0141 23.4535 19.1263 23.4535C14.8563 23.4535 11.4181 20.587 11.4181 17.031C11.4181 13.4762 14.8563 10.6085 19.1263 10.6085C23.3951 10.6085 26.8333 13.4762 26.8333 17.031C26.8333 18.9525 25.802 20.7013 24.1686 21.8773V21.8762ZM19.4518 9.44883C19.3429 9.44521 19.234 9.44327 19.1251 9.443C14.2555 9.443 10.2515 12.7797 10.2515 17.0322C10.2515 17.6785 10.3448 18.3038 10.5175 18.8988H10.4136C9.39426 18.8885 8.38067 18.7442 7.39896 18.4695C7.31263 18.4403 7.22629 18.4403 7.13996 18.4403C6.96754 18.444 6.79921 18.4935 6.65229 18.5838L4.61296 19.7563C4.55463 19.7855 4.49746 19.8147 4.44029 19.8147C4.35703 19.8138 4.27744 19.7803 4.21856 19.7214C4.15968 19.6625 4.1262 19.5829 4.12529 19.4997C4.12529 19.4133 4.15329 19.3562 4.18246 19.2698C4.21046 19.2418 4.46946 18.2968 4.61296 17.7252C4.61296 17.6668 4.64096 17.5817 4.64096 17.5245C4.64065 17.4245 4.61721 17.3259 4.57248 17.2364C4.52775 17.147 4.46295 17.0691 4.38313 17.0088C2.40096 15.6053 1.16663 13.517 1.16663 11.1977C1.16663 6.93583 5.33163 3.5 10.4416 3.5C14.8341 3.5 18.5266 6.0305 19.4518 9.44767V9.44883ZM13.4388 9.9365C14.1073 9.9365 14.6358 9.38 14.6358 8.7395C14.6358 8.071 14.1073 7.5425 13.4388 7.5425C12.7703 7.5425 12.2418 8.071 12.2418 8.7395C12.2418 9.408 12.7703 9.9365 13.4388 9.9365ZM7.30213 9.9365C7.97063 9.9365 8.50029 9.38 8.50029 8.7395C8.50029 8.071 7.97063 7.5425 7.30213 7.5425C6.63479 7.5425 6.10513 8.071 6.10513 8.7395C6.10513 9.408 6.63479 9.9365 7.30213 9.9365Z" fill="#2CE25E"/>
</g>
<defs>
<clipPath id="clip0_280_54">
<rect width="28" height="28" fill="white"/>
</clipPath>
</defs>
</svg>
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"*": [
"../../../../../Library/Caches/hugo_cache/modules/filecache/modules/pkg/mod/github.com/gohugoio/hugo-mod-jslibs-dist/popperjs/v2@v2.21100.20000/package/dist/cjs/popper.js/*",
"../../../../../Library/Caches/hugo_cache/modules/filecache/modules/pkg/mod/github.com/twbs/bootstrap@v5.3.0+incompatible/js/*"
]
}
}
}
\ No newline at end of file
module.exports = {
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
};
---
weight: 10
title: "文档"
description: "FastGPT 官方文档"
icon: menu_book
lead: ""
draft: false
images: []
---
\ No newline at end of file
---
weight: 500
title: "开发指南"
description: "对 FastGPT 进行开发调试"
icon: "developer_guide"
draft: false
images: []
---
本文档介绍了如何设置开发环境以构建和测试 [FastGPT](https://fastgpt.run)。
### 安装依赖项
您需要在计算机上安装和配置以下依赖项才能构建 [FastGPT](https://fastgpt.run):
- [Git](http://git-scm.com/)
- [Docker](https://www.docker.com/)
- [Docker Compose](https://docs.docker.com/compose/install/)
- [Node.js v18.x (LTS)](http://nodejs.org)
- [npm](https://www.npmjs.com/) 版本 8.x.x 或 [Yarn](https://yarnpkg.com/)
## 本地开发
要设置一个可工作的开发环境,只需 Fork 项目的 Git 存储库,并部署一个数据库,然后开始进行开发测试。
### Fork存储库
您需要 Fork [存储库](https://github.com/labring/FastGPT)。
### 克隆存储库
克隆您在 GitHub 上 Fork 的存储库:
```
git clone git@github.com:<github_username>/FastGPT.git
```
client 目录下为 FastGPT 核心代码。NextJS 框架前后端放在一起,API 服务位于 `src/pages/api` 目录内。
### 安装数据库
第一次开发,需要先部署数据库,建议本地开发可以随便找一台 2C2G 的轻量小数据库实践。数据库部署教程:[Docker 快速部署](/docs/installation/docker/)
### 初始配置
**1. 环境变量**
复制.env.template 文件,生成一个.env.local 环境变量文件夹,修改.env.local 里内容才是有效的变量。变量说明见 .env.template
**2. config 配置文件**
复制 data/config.json 文件,生成一个 data/config.local.json 配置文件。
这个文件大部分时候不需要修改。只需要关注 SystemParams 里的参数:
+ `vectorMaxProcess`: 向量生成最大进程,根据数据库和 key 的并发数来决定,通常单个 120 号,2c4g 服务器设置10~15。
+ `qaMaxProcess`: QA 生成最大进程
+ `pgIvfflatProbe`: PostgreSQL vector 搜索探针,没有添加 vector 索引时可忽略。
### 运行
```bash
cd client
pnpm i
pnpm dev
```
### 镜像打包
```bash
docker build -t dockername/fastgpt .
```
## 创建拉取请求
在进行更改后,打开一个拉取请求(PR)。提交拉取请求后,FastGPT 团队/社区的其他人将与您一起审查它。
如果遇到问题,比如合并冲突或不知道如何打开拉取请求,请查看 GitHub 的[拉取请求教程](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests),了解如何解决合并冲突和其他问题。一旦您的 PR 被合并,您将自豪地被列为[贡献者表](https://github.com/labring/FastGPT/graphs/contributors)中的一员。
## 加入社区
遇到困难了吗?有任何问题吗? 加入微信群与开发者和用户保持沟通。
<center><image width="400px" src="/wechat-fastgpt.webp" /></center>
\ No newline at end of file
---
weight: 700
title: "私有化部署"
description: "FastGPT 私有化部署文档"
icon: menu_book
draft: false
images: []
---
\ No newline at end of file
# docker-compose 快速部署 ---
title: "Docker Compose 快速部署"
description: "使用 Docker Compose 快速部署 FastGPT"
icon: ""
draft: false
toc: true
weight: 720
---
## 一、预先准备 ## 准备条件
### 1. 准备好代理环境(国外服务器可忽略) ### 1. 准备好代理环境(国外服务器可忽略)
确保可访问到 OpenAI,方案可参考:[sealos nginx 中转](../proxy/sealos) 确保可以访问 OpenAI,具体方案可以参考:[Nginx 中转](/docs/installation/proxy/nginx/)
### 2. OneAPI (可选,需要多模型和 key 轮询时使用) ### 2. 多模型支持
推荐使用 [one-api](https://github.com/songquanpeng/one-api) 项目来管理 key 池,兼容 openai 、微软和国内主流模型等。 推荐使用 one-api 项目来管理模型池,兼容 OpenAI 、Azure 和国内主流模型等。
部署可以看该项目的 [README.md](https://github.com/songquanpeng/one-api),也可以看 [在 Sealos 1 分钟部署 one-api](../oneapi) 具体部署方法可参考该项目的 [README](https://github.com/songquanpeng/one-api),也可以直接通过以下按钮一键部署:
## 二、安装 docker 和 docker-compose [![](https://cdn.jsdelivr.us/gh/labring-actions/templates@main/Deploy-on-Sealos.svg)](https://cloud.sealos.io/?openapp=system-fastdeploy%3FtemplateName%3Done-api)
这个不同系统略有区别,百度安装下。验证安装成功后进行下一步。下面给出 centos 一个例子: ## 安装 Docker 和 docker-compose
{{< tabs tabTotal="3" >}}
{{< tab tabName="Linux" >}}
{{< markdownify >}}
```bash ```bash
# 安装docker # 安装 Docker
curl -L https://get.daocloud.io/docker | sh curl -sSL https://get.daocloud.io/docker | sh
sudo systemctl start docker systemctl enable --now docker
# 安装 docker-compose # 安装 docker-compose
curl -L https://github.com/docker/compose/releases/download/1.23.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose curl -L https://github.com/docker/compose/releases/download/2.20.3/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose
# 验证安装 # 验证安装
docker -v docker -v
docker-compose -v docker-compose -v
``` ```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="MacOS" >}}
{{< markdownify >}}
推荐直接使用 [Orbstack](https://orbstack.dev/)。可直接通过 Homebrew 来安装:
## 三、创建 docker-compose.yml 文件 ```bash
brew install orbstack
```
或者直接[下载安装包](https://orbstack.dev/download)进行安装。
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="Windows" >}}
{{< markdownify >}}
我们建议将源代码和其他数据绑定到 Linux 容器中时,将其存储在 Linux 文件系统中,而不是 Windows 文件系统中。
可以选择直接[使用 WSL 2 后端在 Windows 中安装 Docker Desktop](https://docs.docker.com/desktop/wsl/)。
也可以直接[在 WSL 2 中安装命令行版本的 Docker](https://nickjanetakis.com/blog/install-docker-in-wsl-2-without-docker-desktop)。
{{< /markdownify >}}
{{< /tab >}}
{{< /tabs >}}
## 创建 docker-compose.yml 文件
先创建一个目录(例如 fastgpt)并进入该目录:
随便找一个目录,创建一个 `docker-compose.yml` 文件,粘贴下面的内容。只需要改 fastgpt 容器的 3 个参数即可启动。 ```bash
mkdir fastgpt
cd fastgpt
```
```yml 创建一个 docker-compose.yml 文件,粘贴下面的内容:
```yaml
# 非 host 版本, 不使用本机代理 # 非 host 版本, 不使用本机代理
version: '3.3' version: '3.3'
services: services:
pg: pg:
image: ankane/pgvector:v0.4.2 # git image: ankane/pgvector:v0.4.2
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/pgvector:v0.4.2 # 阿里云 # image: registry.cn-hangzhou.aliyuncs.com/fastgpt/pgvector:v0.4.2 # 阿里云
container_name: pg container_name: pg
restart: always restart: always
...@@ -88,87 +128,43 @@ services: ...@@ -88,87 +128,43 @@ services:
- DB_MAX_LINK=5 # database max link - DB_MAX_LINK=5 # database max link
- TOKEN_KEY=any - TOKEN_KEY=any
- ROOT_KEY=root_key - ROOT_KEY=root_key
# mongo 配置,不需要改. 如果连不上,可能需要去掉 ?authSource=admin # mongo 配置,不需要改
- MONGODB_URI=mongodb://username:password@mongo:27017/fastgpt?authSource=admin - MONGODB_URI=mongodb://username:password@mongo:27017/?authSource=admin
# pg配置. 不需要改 - MONGODB_NAME=fastgpt
- PG_URL=postgresql://username:password@pg:5432/postgres # pg配置
- PG_HOST=pg
- PG_PORT=5432
- PG_USER=username
- PG_PASSWORD=password
- PG_DB_NAME=postgres
networks: networks:
fastgpt: fastgpt:
``` ```
```yml > 只需要改 fastgpt 容器的 3 个参数即可启动。
# host 版本, 不推荐。
version: '3.3'
services:
pg:
image: ankane/pgvector:v0.4.2 # dockerhub
container_name: pg
restart: always
ports: # 生产环境建议不要暴露
- 5432:5432
environment:
# 这里的配置只有首次运行生效。修改后,重启镜像是不会生效的。需要把持久化数据删除再重启,才有效果
- POSTGRES_USER=username
- POSTGRES_PASSWORD=password
- POSTGRES_DB=postgres
volumes:
- ./pg/data:/var/lib/postgresql/data
mongo:
image: mongo:5.0.18
container_name: mongo
restart: always
ports: # 生产环境建议不要暴露
- 27017:27017
environment:
# 这里的配置只有首次运行生效。修改后,重启镜像是不会生效的。需要把持久化数据删除再重启,才有效果
- MONGO_INITDB_ROOT_USERNAME=username
- MONGO_INITDB_ROOT_PASSWORD=password
volumes:
- ./mongo/data:/data/db
- ./mongo/logs:/var/log/mongodb
fastgpt:
image: ghcr.io/labring/fastgpt:latest # github
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:latest # 阿里云
network_mode: host
restart: always
container_name: fastgpt
environment:
# root 密码,用户名为: root
- DEFAULT_ROOT_PSW=1234
# 中转地址,如果是用官方号,不需要管
- OPENAI_BASE_URL=https://api.openai.com/v1
- CHAT_API_KEY=sk-xxxx
- DB_MAX_LINK=5 # database max link
# token加密凭证(随便填,作为登录凭证)
- TOKEN_KEY=any
# root key, 最高权限,可以内部接口互相调用
- ROOT_KEY=root_key
# mongo 配置,不需要改. 如果连不上,可能需要去掉 ?authSource=admin
- MONGODB_URI=mongodb://username:password@0.0.0.0:27017/fastgpt?authSource=admin
# pg配置. 不需要改
- PG_URL=postgresql://username:password@0.0.0.0:5432/postgres
```
## 四、运行 docker-compose ## 启动容器
```bash ```bash
# 在 docker-compose.yml 同级目录下执行 # 在 docker-compose.yml 同级目录下执行
docker-compose up -d docker-compose up -d
``` ```
## 五、访问 ## 访问 FastGPT
目前可以通过 `ip:3000`` 直接访问(注意防火墙)。登录用户名为 `root`,密码为刚刚环境变量里设置的 `DEFAULT_ROOT_PSW`。
如果需要域名访问,自行安装 Nginx。目前可以通过: `ip:3000` 直接访问(注意防火墙)。登录用户名为 root,密码为刚刚环境变量里设置的 `DEFAULT_ROOT_PSW` 如果需要域名访问,请自行安装并配置 Nginx。
## 一些问题 ## QA
### 1. 如何更新? ### 如何更新?
执行 `docker-compose up -d` 会自动拉取最新镜像,一般情况下不需要执行额外操作。 执行 `docker-compose up -d` 会自动拉取最新镜像,一般情况下不需要执行额外操作。
### 2. 挂载配置文件 ### 如何自定义配置文件?
在和 `docker-compose.yml` 同级目录,创建一个 `config.json` 文件,内容如下: 需要在 `docker-compose.yml` 同级目录创建一个 `config.json` 文件,内容如下:
```json ```json
{ {
...@@ -237,12 +233,13 @@ docker-compose up -d ...@@ -237,12 +233,13 @@ docker-compose up -d
} }
``` ```
修改 docker-compose.yml 中 fastgpt 容器内容,增加挂载。具体配置可参考 [config 配置说明](/docs/category/data-config) 然后修改 `docker-compose.yml` 中的 `fastgpt` 容器内容,增加挂载选项即可:
```yml ```yaml
fastgpt: fastgpt:
container_name: fastgpt container_name: fastgpt
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:latest # 阿里云 image: ghcr.io/labring/fastgpt:latest # github
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:latest # 阿里云
ports: ports:
- 3000:3000 - 3000:3000
networks: networks:
...@@ -252,10 +249,10 @@ fastgpt: ...@@ -252,10 +249,10 @@ fastgpt:
- pg - pg
restart: always restart: always
environment: environment:
......
# root 密码,用户名为: root # root 密码,用户名为: root
- DEFAULT_ROOT_PSW=1234 - DEFAULT_ROOT_PSW=1234
......
volumes: volumes:
- ./config.json:/app/data/config.json - ./config.json:/app/data/config.json
``` ```
> 参考[配置详解](/docs/installation/reference/configuration/)
\ No newline at end of file
---
title: "部署 one-api,实现多模型支持"
description: "通过接入 one-api 来实现对各种大模型的支持"
icon: "Api"
draft: false
toc: true
weight: 730
---
[one-api](https://github.com/songquanpeng/one-api) 是一个 OpenAI 接口管理 & 分发系统,可以通过标准的 OpenAI API 格式访问所有的大模型,开箱即用。
FastGPT 可以通过接入 one-api 来实现对各种大模型的支持。部署方法也很简单,直接点击以下按钮即可一键部署 👇
[![](https://cdn.jsdelivr.us/gh/labring-actions/templates@main/Deploy-on-Sealos.svg)](https://cloud.sealos.io/?openapp=system-fastdeploy%3FtemplateName%3Done-api)
部署完后会跳转「应用管理」,数据库在另一个应用「数据库」中。需要等待 1~3 分钟数据库运行后才能访问成功。
配置好 one-api 的模型后,可以直接修改 FastGPT 的环境变量:
```bash
# 下面的地址是 Sealos 提供的,务必写上 v1
OPENAI_BASE_URL=https://xxxx.cloud.sealos.io/v1
# 下面的 key 由 one-api 提供
CHAT_API_KEY=sk-xxxxxx
```
\ No newline at end of file
---
weight: 740
title: "代理方案"
description: "使用代理访问 OpenAI"
icon: public
draft: false
images: []
---
\ No newline at end of file
# cloudflare 代理配置 ---
title: "Cloudflare Worker 中转"
description: "使用 Cloudflare Worker 实现中转"
icon: "foggy"
draft: false
toc: true
weight: 742
---
[来自 "不做了睡觉" 教程](https://gravel-twister-d32.notion.site/FastGPT-API-ba7bb261d5fd4fd9bbb2f0607dacdc9e) [参考 "不做了睡觉" 的教程](https://gravel-twister-d32.notion.site/FastGPT-API-ba7bb261d5fd4fd9bbb2f0607dacdc9e)
**workers 配置文件** **workers 配置文件**
...@@ -37,10 +44,11 @@ async function handleRequest(request) { ...@@ -37,10 +44,11 @@ async function handleRequest(request) {
} }
``` ```
**对应的环境变量** **修改 FastGPT 的环境变量**
务必别忘了填 v1
``` > 务必别忘了填 v1!
```bash
OPENAI_BASE_URL=https://xxxxxx/v1 OPENAI_BASE_URL=https://xxxxxx/v1
OPENAI_BASE_URL_AUTH=auth_code OPENAI_BASE_URL_AUTH=auth_code
``` ```
\ No newline at end of file
---
title: "HTTP 代理中转"
description: "使用 HTTP 代理实现中转"
icon: "http"
draft: false
toc: true
weight: 743
---
如果你有代理工具(例如 [Clash](https://github.com/Dreamacro/clash) 或者 [sing-box](https://github.com/SagerNet/sing-box)),也可以使用 HTTP 代理来访问 OpenAI。只需要添加以下两个环境变量即可:
```bash
AXIOS_PROXY_HOST=
AXIOS_PROXY_PORT=
```
以 Clash 为例,建议指定 `api.openai.com` 走代理,其他请求都直连。示例配置如下:
```yaml
mixed-port: 7890
allow-lan: false
bind-address: '*'
mode: rule
log-level: warning
dns:
enable: true
ipv6: false
nameserver:
- 8.8.8.8
- 8.8.4.4
cache-size: 400
proxies:
-
proxy-groups:
- { name: '♻️ 自动选择', type: url-test, proxies: [香港V01×1.5], url: 'https://api.openai.com', interval: 3600}
rules:
- 'DOMAIN-SUFFIX,api.openai.com,♻️ 自动选择'
- 'MATCH,DIRECT'
```
然后给 FastGPT 添加两个环境变量:
```bash
AXIOS_PROXY_HOST=127.0.0.1
AXIOS_PROXY_PORT=7890
```
--- ---
sidebar_position: 1 title: "Nginx 中转"
description: "使用 Sealos 部署 Nginx 实现中转"
icon: "cloud_sync"
draft: false
toc: true
weight: 741
--- ---
# sealos 部署 nginx 实现中转 ## 登录 Sealos
## 登录 sealos cloud [Sealos](https://cloud.sealos.io/)
[sealos cloud](https://cloud.sealos.io/) ## 创建应用
## 一、点击创建应用 打开 「应用管理」,点击「新建应用」:
打开 App Launchpad -> 新建应用 ![](/imgs/sealos3.png)
![](/imgs/sealos4.png)
![step1](./imgs//sealos1.png) ### 填写基本配置
![step2](./imgs//sealos2.png)
### 二、填写基本配置 务必开启外网访问,复制外网访问提供的地址。
务必开启外网访问,复制下外网访问提供的地址。 ![](/imgs/sealos5.png)
![step3](./imgs//sealos3.png) ### 添加配置文件
### 三、添加 configmap 文件
1. 复制下面这段配置文件,注意 `server_name` 后面的内容替换成第二步的外网访问地址。 1. 复制下面这段配置文件,注意 `server_name` 后面的内容替换成第二步的外网访问地址。
``` ```nginx
user nginx; user nginx;
worker_processes auto; worker_processes auto;
worker_rlimit_nofile 51200; worker_rlimit_nofile 51200;
events { events {
worker_connections 1024; worker_connections 1024;
} }
http { http {
resolver 8.8.8.8; resolver 8.8.8.8;
proxy_ssl_server_name on; proxy_ssl_server_name on;
access_log off; access_log off;
server_names_hash_bucket_size 512; server_names_hash_bucket_size 512;
client_header_buffer_size 64k; client_header_buffer_size 64k;
large_client_header_buffers 4 64k; large_client_header_buffers 4 64k;
client_max_body_size 50M; client_max_body_size 50M;
proxy_connect_timeout 240s; proxy_connect_timeout 240s;
proxy_read_timeout 240s; proxy_read_timeout 240s;
proxy_buffer_size 128k; proxy_buffer_size 128k;
proxy_buffers 4 256k; proxy_buffers 4 256k;
server { server {
listen 80; listen 80;
server_name tgohwtdlrmer.cloud.sealos.io; # 这个地方替换成 sealos 提供的内容 server_name tgohwtdlrmer.cloud.sealos.io; # 这个地方替换成 Sealos 提供的外网地址
location ~ /openai/(.*) { location ~ /openai/(.*) {
proxy_pass https://api.openai.com/$1$is_args$args; proxy_pass https://api.openai.com/$1$is_args$args;
proxy_set_header Host api.openai.com; proxy_set_header Host api.openai.com;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 如果响应是流式的 # 如果响应是流式的
proxy_set_header Connection ''; proxy_set_header Connection '';
proxy_http_version 1.1; proxy_http_version 1.1;
chunked_transfer_encoding off; chunked_transfer_encoding off;
proxy_buffering off; proxy_buffering off;
proxy_cache off; proxy_cache off;
# 如果响应是一般的 # 如果响应是一般的
proxy_buffer_size 128k; proxy_buffer_size 128k;
proxy_buffers 4 256k; proxy_buffers 4 256k;
proxy_busy_buffers_size 256k; proxy_busy_buffers_size 256k;
} }
} }
} }
``` ```
2. 点开高级配置 2. 点开高级配置。
3. 点击新增 configmap 3. 点击「新增配置文件」。
4. 文件名写: `/etc/nginx/nginx.conf` 4. 文件名写: `/etc/nginx/nginx.conf`。
5. 文件值为刚刚复制的那段代码 5. 文件值为刚刚复制的那段代码。
6. 点击确认 6. 点击确认。
![step4](./imgs//sealos4.png) ![](/imgs/sealos6.png)
### 四、部署应用 ### 部署应用
填写完毕后,点击右上角的 `部署应用`,即可完成。 填写完毕后,点击右上角的「部署」,即可完成部署。
## 五、修改 FastGpt 环境变量 ## 修改 FastGPT 环境变量
1. 进入刚刚部署应用的详情,复制外网地址 1. 进入刚刚部署应用的详情,复制外网地址
注意:这是个 API 地址,点击打开是无效的。如需验证,可以访问: 【\*\*\*.close.sealos.io/openai/api】,如果提示 "Invalid URL (GET /api)" 则代表成功。 > 注意:这是个 API 地址,点击打开是无效的。如需验证,可以访问: `*.cloud.sealos.io/openai/api`,如果提示 `Invalid URL (GET /api)` 则代表成功。
![step5](./imgs//sealos5.png) ![](/imgs/sealos7.png)
2. 修改环境变量(是 FastGpt 的环境变量,不是 sealos 的):
``` 2. 修改环境变量(是 FastGPT 的环境变量,不是 Sealos 的):
OPENAI_BASE_URL=https://tgohwtdlrmer.cloud.sealos.io/openai/v1
```
**Done!** ```bash
OPENAI_BASE_URL=https://tgohwtdlrmer.cloud.sealos.io/openai/v1
```
**Done!**
\ No newline at end of file
---
weight: 750
title: "配置说明"
description: "FastGPT 配置指南"
icon: quick_reference_all
draft: false
images: []
---
\ No newline at end of file
---
title: "接入 ChatGLM2-6B"
description: " 将 FastGPT 接入私有化模型 ChatGLM2-6B"
icon: "model_training"
draft: false
toc: true
weight: 753
---
## 前言
FastGPT 允许你使用自己的 OpenAI API KEY 来快速调用 OpenAI 接口,目前集成了 GPT-3.5, GPT-4 和 embedding,可构建自己的知识库。但考虑到数据安全的问题,我们并不能将所有的数据都交付给云端大模型。
那么如何在 FastGPT 上接入私有化模型呢?本文就以清华的 ChatGLM2 为例,为各位讲解如何在 FastGPT 中接入私有化模型。
## ChatGLM2-6B 简介
ChatGLM2-6B 是开源中英双语对话模型 ChatGLM-6B 的第二代版本,具体介绍可参阅 [ChatGLM2-6B 项目主页](https://github.com/THUDM/ChatGLM2-6B)。
{{% alert context="warning" %}}
注意,ChatGLM2-6B 权重对学术研究完全开放,在获得官方的书面许可后,亦允许商业使用。本教程只是介绍了一种用法,无权给予任何授权!
{{% /alert %}}
## 推荐配置
依据官方数据,同样是生成 8192 长度,量化等级为 FP16 要占用 12.8GB 显存、int8 为 8.1GB 显存、int4 为 5.1GB 显存,量化后会稍微影响性能,但不多。
因此推荐配置如下:
{{< table "table-hover table-striped" >}}
| 类型 | 内存 | 显存 | 硬盘空间 | 启动命令 |
|------|---------|---------|----------|--------------------------|
| fp16 | >=16GB | >=16GB | >=25GB | python openai_api.py 16 |
| int8 | >=16GB | >=9GB | >=25GB | python openai_api.py 8 |
| int4 | >=16GB | >=6GB | >=25GB | python openai_api.py 4 |
{{< /table >}}
## 环境配置
+ Python 3.8.10
+ CUDA 11.8
+ 科学上网环境
## 部署步骤
1. 根据上面的环境配置配置好环境,具体教程自行 GPT;
2. 在命令行输入命令 `pip install -r requirments.txt`;
3. 打开你需要启动的 py 文件,在代码的第 76 行配置 token,这里的 token 只是加一层验证,防止接口被人盗用;
4. 执行命令 `python openai_api.py 16`。这里的数字根据上面的配置进行选择。
然后等待模型下载,直到模型加载完毕为止。如果出现报错先问 GPT。
启动成功后应该会显示如下地址:
![](/imgs/chatglm2.png)
> 这里的 `http://0.0.0.0:6006` 就是连接地址。
然后现在回到 .env.local 文件,依照以下方式配置地址:
```bash
OPENAI_BASE_URL=http://127.0.0.1:6006/v1
OPENAIKEY=sk-aaabbbcccdddeeefffggghhhiiijjjkkk # 这里是你在代码中配置的 token,这里的 OPENAIKEY 可以任意填写
```
这样就成功接入 ChatGLM2-6B 了。
--- ---
sidebar_position: 1 title: "配置详解"
description: "FastGPT 配置参数介绍"
icon: "settings"
draft: false
toc: true
weight: 751
--- ---
# Default Config.json 由于环境变量不利于配置复杂的内容,新版 FastGPT 采用了 ConfigMap 的形式挂载配置文件,你可以在 `client/data/config.json` 看到默认的配置文件。可以参考 [docker-compose 快速部署](/docs/installation/docker/) 来挂载配置文件。
开发环境下,你需要将示例配置文件 `config.json` 复制成 `config.local.json` 文件才会生效。
注意: 为了方便介绍,文档介绍里会把注释写到 json 文件,实际运行时候 json 文件不能包含注释。
这个配置文件中包含了前端页面定制、系统级参数、AI 对话的模型等……
{{% alert context="warning" %}}
注意:下面的配置介绍仅是局部介绍,你需要完整挂载整个 `config.json`,不能仅挂载一部分。你可以直接在默认的 config.json 基础上根据下面的介绍进行修改。
{{% /alert %}}
## 基础字段粗略说明
这里介绍一些基础的配置字段:
```json
// 这个配置会控制前端的一些样式
"FeConfig": {
"show_emptyChat": true, // 对话页面,空内容时,是否展示介绍页
"show_register": false, // 是否展示注册按键(包括忘记密码,注册账号和三方登录)
"show_appStore": false, // 是否展示应用市场(不过目前权限还没做好,放开也没用)
"show_userDetail": false, // 是否展示用户详情(账号余额、OpenAI 绑定)
"show_git": true, // 是否展示 Git
"systemTitle": "FastGPT", // 系统的 title
"authorText": "Made by FastGPT Team.", // 签名
"gitLoginKey": "" // Git 登录凭证
},
...
...
// 这个配置文件是系统级参数
"SystemParams": {
"gitLoginSecret": "", // Git 登录凭证
"vectorMaxProcess": 15, // 向量生成最大进程,结合数据库性能和 key 来设置
"qaMaxProcess": 15, // QA 生成最大进程,结合数据库性能和 key 来设置
"pgIvfflatProbe": 20 // pg vector 搜索探针。没有设置索引前可忽略,通常 50w 组以上才需要设置。
},
...
```
## 完整配置参数
```json ```json
{ {
...@@ -69,4 +114,4 @@ sidebar_position: 1 ...@@ -69,4 +114,4 @@ sidebar_position: 1
} }
] ]
} }
``` ```
\ No newline at end of file
# 配置其他对话模型 ---
title: "多模型支持"
description: "如何接入除了 GPT 以外的其他大模型"
icon: "model_training"
draft: false
toc: true
weight: 752
---
默认情况下,FastGPT 只配置了 GPT 的 3 个模型,如果你需要接入其他模型,需要进行一些额外配置。 默认情况下,FastGPT 只配置了 GPT 的 3 个模型,如果你需要接入其他模型,需要进行一些额外配置。
## 一、安装 OneAPI ## 部署 one-api
首先你需要部署一个 [OneAPI](/docs/develop/oneapi),并添加对应的【渠道】 首先你需要部署一个 [one-api](/docs/installation/one-api/),并添加对应的【渠道】
![](./imgs/chatmodels1.png) ![](/imgs/chatmodels1.png)
## 二、添加 FastGPT 配置 ## 添加 FastGPT 配置
可以在 /client/src/data/config.json 里找到配置文件(本地开发需要复制成 config.local.json),配置文件中有一项是对话模型配置: 可以在 `/client/src/data/config.json` 里找到配置文件(本地开发需要复制成 config.local.json),配置文件中有一项是对话模型配置:
```json ```json
"ChatModels": [ "ChatModels": [
...@@ -64,4 +71,4 @@ ...@@ -64,4 +71,4 @@
] ]
``` ```
添加完后,重启应用即可在选择文心一言模型进行对话。 添加完后,重启应用即可在选择文心一言模型进行对话。
\ No newline at end of file
---
title: "Sealos 一键部署"
description: "使用 Sealos 一键部署 FastGPT"
icon: "cloud"
draft: false
toc: true
weight: 710
---
Sealos 的服务器在国外,不需要额外处理网络问题,无需服务器、无需魔法、无需域名,支持高并发 & 动态伸缩。点击以下按钮即可一键部署 👇
[![](https://cdn.jsdelivr.us/gh/labring-actions/templates@main/Deploy-on-Sealos.svg)](https://cloud.sealos.io/?openapp=system-fastdeploy%3FtemplateName%3Dfastgpt)
由于需要部署数据库,部署完后需要等待 2~4 分钟才能正常访问。默认用了最低配置,首次访问时会有些慢。
![](/imgs/sealos1.png)
点击 Sealos 提供的外网地址即可打开 FastGPT 的可视化界面。
![](/imgs/sealos2.png)
> 用户名:`root`
>
> 密码就是刚刚一键部署时设置的环境变量
\ No newline at end of file
# V4.0 版本初始化 ---
title: "升级到 V4.0"
description: "FastGPT 从旧版本升级到 V4.0 操作指南"
icon: "upgrade"
draft: false
toc: true
weight: 761
---
新版 mongo 表进行了不少的变更,需要执行一些初始化脚本。 如果您是**从旧版本升级到 V4**,由于新版 MongoDB 表变更比较大,需要按照本文档的说明执行一些初始化脚本。
## 重命名表名 ## 重命名表名
需要连接上 mongo 数据库,执行两条命令: 需要连接上 MongoDB 数据库,执行两条命令:
`db.models.renameCollection("apps")` ```mongodb
db.models.renameCollection("apps")
`db.sharechats.renameCollection("outlinks")` db.sharechats.renameCollection("outlinks")
```
如果你已经更新部署了,mongo 会自动创建空表,需要手动删除这两个空表。 {{% alert context="warning" %}}
注意:从旧版更新到 V4, MongoDB 会自动创建空表,你需要先手动删除这两个空表,再执行上面的操作。
{{% /alert %}}
## 初始化几个表中的字段 ## 初始化几个表中的字段
依次执行下面 3 条命令,时间比较长,不成功可以重复执行(会跳过已经初始化的数据),直到所有数据更新完成。 依次执行下面 3 条命令,时间比较长,不成功可以重复执行(会跳过已经初始化的数据),直到所有数据更新完成。
```mongo ```mongodb
db.chats.find({appId: {$exists: false}}).forEach(function(item){ db.chats.find({appId: {$exists: false}}).forEach(function(item){
db.chats.updateOne( db.chats.updateOne(
{ {
...@@ -45,12 +55,12 @@ db.outlinks.find({shareId: {$exists: false}}).forEach(function(item){ ...@@ -45,12 +55,12 @@ db.outlinks.find({shareId: {$exists: false}}).forEach(function(item){
}) })
``` ```
## 执行初始化 API ## 初始化 API
部署新版项目,并发起 3 个 HTTP 请求(记得携带 headers.rootkey,这个值是环境变量里的) 部署新版项目,并发起 3 个 HTTP 请求(记得携带 `headers.rootkey`,这个值是环境变量里的)
1. https://xxxxx/api/admin/initv4 1. https://xxxxx/api/admin/initv4
2. https://xxxxx/api/admin/initChat 2. https://xxxxx/api/admin/initChat
3. https://xxxxx/api/admin/initOutlink 3. https://xxxxx/api/admin/initOutlink
1 和 2,有可能会因为内存不足挂掉,可以重复执行。 1 和 2 有可能会因为内存不足挂掉,可以重复执行。
\ No newline at end of file
---
title: "升级到 V4.1"
description: "FastGPT 从旧版本升级到 V4.1 操作指南"
icon: "upgrade"
draft: false
toc: true
weight: 762
---
如果您是**从旧版本升级到 V4.1**,由于新版重新设置了对话存储结构,需要初始化原来的存储内容。
## 更新环境变量
V4.1 优化了 PostgreSQL 和 MongoDB 的连接变量,只需要填 1 个 URL 即可:
```bash
# mongo 配置,不需要改. 如果连不上,可能需要去掉 ?authSource=admin
- MONGODB_URI=mongodb://username:password@mongo:27017/fastgpt?authSource=admin
# pg配置. 不需要改
- PG_URL=postgresql://username:password@pg:5432/postgres
```
## 初始化 API
部署新版项目,并发起 1 个 HTTP 请求(记得携带 `headers.rootkey`,这个值是环境变量里的)
+ https://xxxxx/api/admin/initChatItem
\ No newline at end of file
---
weight: 760
title: "版本升级"
description: "FastGPT 升级指南"
icon: upgrade
draft: false
images: []
---
\ No newline at end of file
---
title: "快速了解 FastGPT"
description: "FastGPT 的能力与优势"
icon: "rocket_launch"
draft: false
toc: true
weight: -100
---
FastGPT 是一个基于 LLM 大语言模型的知识库问答系统,提供开箱即用的数据处理、模型调用等能力。同时可以通过 Flow 可视化进行工作流编排,从而实现复杂的问答场景!
{{% alert icon="🤖 " context="success" %}}
FastGPT 在线体验:[https://fastgpt.run](https://fastgpt.run)
{{% /alert %}}
| | |
| -------------------------- | -------------------------- |
| ![](/imgs/intro1.png) | ![](/imgs/intro2.png) |
| ![](/imgs/intro3.png) | ![](/imgs/intro4.png) |
## FastGPT 能力
### 1. 专属 AI 客服
通过导入文档或已有问答对进行训练,让 AI 模型能根据你的文档以交互式对话方式回答问题。
![](/imgs/ability1.png)
### 2. 简单易用的可视化界面
FastGPT 采用直观的可视化界面设计,为各种应用场景提供了丰富实用的功能。通过简洁易懂的操作步骤,可以轻松完成 AI 客服的创建和训练流程。
![](/imgs/ability5.png)
### 3. 自动数据预处理
提供手动输入、直接分段、LLM 自动处理和 CSV 等多种数据导入途径,其中“直接分段”支持通过 PDF、WORD、Markdown 和 CSV 文档内容作为上下文。FastGPT 会自动对文本数据进行预处理、向量化和 QA 分割,节省手动训练时间,提升效能。
![](/imgs/ability2.png)
### 4. 工作流编排
基于 Flow 模块的工作流编排,可以帮助你设计更加复杂的问答流程。例如查询数据库、查询库存、预约实验室等。
![](/imgs/ability3.png)
### 5. 强大的 API 集成
FastGPT 对外的 API 接口对齐了 OpenAI 官方接口,可以直接接入现有的 GPT 应用,也可以轻松集成到企业微信、公众号、飞书等平台。
![](/imgs/ability4.png)
## FastGPT 特点
1. **项目完全开源**
FastGPT 遵循 Apache License 2.0 开源协议,你可以 [Fork](https://github.com/labring/FastGPT/fork) 之后进行二次开发和发布。FastGPT 社区版将保留核心功能,商业版仅在社区版基础上使用 API 的形式进行扩展,不影响学习使用。
2. **独特的 QA 结构**
针对客服问答场景设计的 QA 结构,提高在大量数据场景中的问答准确性。
3. **可视化工作流**
通过 Flow 模块展示了从问题输入到模型输出的完整流程,便于调试和设计复杂流程。
4. **无限扩展**
基于 API 进行扩展,无需修改 FastGPT 源码,也可快速接入现有的程序中。
5. **便于调试**
提供搜索测试、引用修改、完整对话预览等多种调试途径。
6. **支持多种模型**
支持 GPT、Claude、文心一言等多种 LLM 模型,未来也将支持自定义的向量模型。
## 知识库核心流程图
![](/imgs/KBProcess.jpg)
\ No newline at end of file
---
weight: 600
title: "使用案例"
description: "有关 FastGPT 其他实践案例的更多信息"
icon: "cases"
draft: false
images: []
---
\ No newline at end of file
# 利用 FastGpt 打造高质量 AI 知识库 ---
title: " 打造高质量 AI 知识库"
description: " 利用 FastGPT 打造高质量 AI 知识库"
icon: "school"
draft: false
toc: true
weight: 640
---
## 前言 ## 前言
自从去年 12 月 chatgpt 发布后,带动了新的一轮应用交互革命。尤其是 gpt35 接口全面放开后,LLM 应用雨后春笋般快速涌现,但因为 gpt 的可控性、随机性和合规性等问题,很多应用场景都没法落地。 自从去年 12 月 ChatGPT 发布后,带动了新的一轮应用交互革命。尤其是 GPT-3.5 接口全面放开后,LLM 应用雨后春笋般快速涌现,但因为 GPT 的可控性、随机性和合规性等问题,很多应用场景都没法落地。
3 月时候,在 twitter 上刷到一个老哥使用 gpt 训练自己的博客记录,并且成本非常低(比起 FT)。他给出了一个完整的流程图:
![向量搜索 GPT 流程图](imgs/1.png) 3 月时候,在 Twitter 上刷到一个老哥使用 GPT 训练自己的博客记录,并且成本非常低(比起 FT)。他给出了一个完整的流程图:
看到这个推文后,我灵机一动,应用场景就十分清晰了。直接上手开干,在经过不到 1 个月时间,FastGpt 在原来多助手管理基础上,加入了向量搜索。于是便有了最早的一期视频:https://www.bilibili.com/video/BV1Wo4y1p7i1/?vd_source=92041a1a395f852f9d89158eaa3f61b4 ![向量搜索 GPT 流程图](/imgs/1.png)
3 个月过去了,FastGpt 延续着早期的思路去完善和扩展,目前在向量搜索 + LLM 线性问答方面的功能基本上完成了。不过我们始终没有出一期关于如何构建知识库的教程,趁着 V4 在开发中,我们计划介绍一期《如何在 FastGpt 上构建高质量知识库》,以便大家更好的使用。 看到这个推文后,我灵机一动,应用场景就十分清晰了。直接上手开干,在经过不到 1 个月时间,FastGPT 在原来多助手管理基础上,加入了向量搜索。于是便有了最早的一期视频:
## FastGpt 知识库完整逻辑 {{< bilibili BV1Wo4y1p7i1 >}}
在正式构建知识库前,我们先来了解下 FastGpt 是如何进行知识库检索的。首先了解几个基本概念: 3 个月过去了,FastGPT 延续着早期的思路去完善和扩展,目前在向量搜索 + LLM 线性问答方面的功能基本上完成了。不过我们始终没有出一期关于如何构建知识库的教程,趁着 V4 在开发中,我们计划介绍一期《如何在 FastGPT 上构建高质量知识库》,以便大家更好的使用。
## FastGPT 知识库完整逻辑
在正式构建知识库前,我们先来了解下 FastGPT 是如何进行知识库检索的。首先了解几个基本概念:
1. 向量:将人类直观的语言(文字、图片、视频等)转成计算机可识别的语言(数组)。 1. 向量:将人类直观的语言(文字、图片、视频等)转成计算机可识别的语言(数组)。
2. 向量相似度:两个向量之间可以进行计算,得到一个相似度,即代表:两个语言相似的程度。 2. 向量相似度:两个向量之间可以进行计算,得到一个相似度,即代表:两个语言相似的程度。
3. 语言大模型的一些特点:上下文理解、总结和推理。 3. 语言大模型的一些特点:上下文理解、总结和推理。
结合上述 3 个概念,便有了 “向量搜索 + 大模型 = 知识库问答” 的公式。下图是 FastGpt V3 中知识库问答功能的完整逻辑: 结合上述 3 个概念,便有了 “向量搜索 + 大模型 = 知识库问答” 的公式。下图是 FastGPT V3 中知识库问答功能的完整逻辑:
![向量搜索 GPT 流程图](imgs/2.png) ![向量搜索 GPT 流程图](/imgs/2.png)
与大部分其他知识库问答产品不一样的是, FastGpt 采用了 QA 问答对进行存储,而不是仅进行 chunk(文本分块)处理。目的是为了减少向量化内容的长度,让向量能更好的表达文本的含义,从而提高搜索精准度。 与大部分其他知识库问答产品不一样的是, FastGPT 采用了 QA 问答对进行存储,而不是仅进行 chunk(文本分块)处理。目的是为了减少向量化内容的长度,让向量能更好的表达文本的含义,从而提高搜索精准度。
此外 FastGpt 还提供了搜索测试和对话测试两种途径对数据进行调整,从而方便用户调整自己的数据。根据上述流程和方式,我们以构建一个 FastGpt 常见问题机器人为例,展示如何构建一个高质量的 AI 知识库。 此外 FastGPT 还提供了搜索测试和对话测试两种途径对数据进行调整,从而方便用户调整自己的数据。根据上述流程和方式,我们以构建一个 FastGPT 常见问题机器人为例,展示如何构建一个高质量的 AI 知识库。
## 构建知识库应用 ## 构建知识库应用
首先,先创建一个 FastGpt 常见问题知识库 首先,先创建一个 FastGPT 常见问题知识库
![创建知识库应用](imgs/3.png) ![创建知识库应用](/imgs/3.png)
### 通过 QA 拆分,获取基础知识 ### 通过 QA 拆分,获取基础知识
我们先直接把 FastGpt Git 上一些已有文档,进行 QA 拆分,从而获取一些 FastGpt 基础的知识。下面是 README 例子。 我们先直接把 FastGPT Git 上一些已有文档,进行 QA 拆分,从而获取一些 FastGPT 基础的知识。下面是 README 例子。
![QA 拆分示意图](imgs/4.png) ![QA 拆分示意图](/imgs/4.png)
![](imgs/5.png) ![](/imgs/5.png)
### 修正 QA ### 修正 QA
通过 README 我们一共得到了 11 组数据,整体的质量还是不错的,图片和链接都提取出来了。不过最后一个知识点出现了一些截断,我们需要手动的修正一下。 通过 README 我们一共得到了 11 组数据,整体的质量还是不错的,图片和链接都提取出来了。不过最后一个知识点出现了一些截断,我们需要手动的修正一下。
此外,我们观察到第一列第三个知识点。这个知识点是介绍了 FastGpt 一些资源链接,但是 QA 拆分将答案放置在了 A 中,但通常来说用户的提问并不会直接问“有哪些链接”,通常会问:“部署教程”,“问题文档”之类的。因此,我们需要将这个知识点进行简单的一个处理,如下图: 此外,我们观察到第一列第三个知识点。这个知识点是介绍了 FastGPT 一些资源链接,但是 QA 拆分将答案放置在了 A 中,但通常来说用户的提问并不会直接问“有哪些链接”,通常会问:“部署教程”,“问题文档”之类的。因此,我们需要将这个知识点进行简单的一个处理,如下图:
![手动修改知识库数据](imgs/6.png) ![手动修改知识库数据](/imgs/6.png)
我们先来创建一个应用,看看效果如何。 首先需要去创建一个应用,并且在知识库中关联相关的知识库。另外还需要在配置页的提示词中,告诉 GPT:“知识库的范围”。 我们先来创建一个应用,看看效果如何。 首先需要去创建一个应用,并且在知识库中关联相关的知识库。另外还需要在配置页的提示词中,告诉 GPT:“知识库的范围”。
![](imgs/7.png) ![](/imgs/7.png)
![README QA 拆分后效果](imgs/8.png) ![README QA 拆分后效果](/imgs/8.png)
整体的效果还是不错的,链接和对应的图片都可以顺利的展示。 整体的效果还是不错的,链接和对应的图片都可以顺利的展示。
...@@ -60,24 +70,24 @@ ...@@ -60,24 +70,24 @@
接着,我们再把 FastGPT 常见问题的文档导入,由于平时整理不当,我们只能手动的录入对应的问答。 接着,我们再把 FastGPT 常见问题的文档导入,由于平时整理不当,我们只能手动的录入对应的问答。
![手动录入知识库结果](imgs/9.png) ![手动录入知识库结果](/imgs/9.png)
导入结果如上图。可以看到,我们均采用的是问答对的格式,而不是粗略的直接导入。目的就是为了模拟用户问题,进一步的提高向量搜索的匹配效果。可以为同一个问题设置多种问法,效果更佳。 导入结果如上图。可以看到,我们均采用的是问答对的格式,而不是粗略的直接导入。目的就是为了模拟用户问题,进一步的提高向量搜索的匹配效果。可以为同一个问题设置多种问法,效果更佳。
FastGpt 还提供了 openapi 功能,你可以在本地对特殊格式的文件进行处理后,再上传到 FastGpt,具体可以参考:[FastGpt Api Docs](https://kjqvjse66l.feishu.cn/docx/DmLedTWtUoNGX8xui9ocdUEjnNh) FastGPT 还提供了 openapi 功能,你可以在本地对特殊格式的文件进行处理后,再上传到 FastGPT,具体可以参考:[FastGPT Api Docs](https://kjqvjse66l.feishu.cn/docx/DmLedTWtUoNGX8xui9ocdUEjnNh)
## 知识库微调和参数调整 ## 知识库微调和参数调整
FastGpt 提供了搜索测试和对话测试两种途径对知识库进行微调,我们先来使用搜索测试对知识库进行调整。我们建议你提前收集一些用户问题进行测试,根据预期效果进行跳转。可以先进行搜索测试调整,判断知识点是否合理。 FastGPT 提供了搜索测试和对话测试两种途径对知识库进行微调,我们先来使用搜索测试对知识库进行调整。我们建议你提前收集一些用户问题进行测试,根据预期效果进行跳转。可以先进行搜索测试调整,判断知识点是否合理。
### 搜索测试 ### 搜索测试
![搜索测试作用](imgs/10.png) ![搜索测试作用](/imgs/10.png)
你可能会遇到下面这种情况,由于“知识库”这个关键词导致一些无关内容的相似度也被搜索进去,此时就需要给第四条记录也增加一个“知识库”关键词,从而去提高它的相似度。 你可能会遇到下面这种情况,由于“知识库”这个关键词导致一些无关内容的相似度也被搜索进去,此时就需要给第四条记录也增加一个“知识库”关键词,从而去提高它的相似度。
![搜索测试结果](imgs/11.png) ![搜索测试结果](/imgs/11.png)
![优化后的搜索测试结果](imgs/12.png) ![优化后的搜索测试结果](/imgs/12.png)
### 提示词设置 ### 提示词设置
...@@ -86,24 +96,24 @@ FastGpt 提供了搜索测试和对话测试两种途径对知识库进行微调 ...@@ -86,24 +96,24 @@ FastGpt 提供了搜索测试和对话测试两种途径对知识库进行微调
1. 告诉 Gpt 回答什么方面内容。 1. 告诉 Gpt 回答什么方面内容。
2. 给知识库一个基本描述,从而让 Gpt 更好的判断用户的问题是否属于知识库范围。 2. 给知识库一个基本描述,从而让 Gpt 更好的判断用户的问题是否属于知识库范围。
![提示词设置](imgs/13.png) ![提示词设置](/imgs/13.png)
### 更好的限定模型聊天范围 ### 更好的限定模型聊天范围
首先,你可以通过调整知识库搜索时的相似度和最大搜索数量,实现从知识库层面限制聊天范围。通常我们可以设置相似度为 0.82,并设置空搜索回复内容。这意味着,如果用户的问题无法在知识库中匹配时,会直接回复预设的内容。 首先,你可以通过调整知识库搜索时的相似度和最大搜索数量,实现从知识库层面限制聊天范围。通常我们可以设置相似度为 0.82,并设置空搜索回复内容。这意味着,如果用户的问题无法在知识库中匹配时,会直接回复预设的内容。
![搜索参数设置](imgs/14.png) ![搜索参数设置](/imgs/14.png)
![空搜索控制效果](imgs/15.png) ![空搜索控制效果](/imgs/15.png)
由于 openai 向量模型并不是针对中文,所以当问题中有一些知识库内容的关键词时,相似度 由于 openai 向量模型并不是针对中文,所以当问题中有一些知识库内容的关键词时,相似度
会较高,此时无法从知识库层面进行限定。需要通过限定词进行调整,例如: 会较高,此时无法从知识库层面进行限定。需要通过限定词进行调整,例如:
> 我的问题如果不是关于 FastGpt 的,请直接回复:“我不确定”。你仅需要回答知识库中的内容,不在其中的内容,不需要回答。 > 我的问题如果不是关于 FastGPT 的,请直接回复:“我不确定”。你仅需要回答知识库中的内容,不在其中的内容,不需要回答。
效果如下: 效果如下:
![限定词效果](imgs/16.png) ![限定词效果](/imgs/16.png)
当然,gpt35 在一定情况下依然是不可控的。 当然,gpt35 在一定情况下依然是不可控的。
...@@ -111,7 +121,7 @@ FastGpt 提供了搜索测试和对话测试两种途径对知识库进行微调 ...@@ -111,7 +121,7 @@ FastGpt 提供了搜索测试和对话测试两种途径对知识库进行微调
与搜索测试类似,你可以直接在对话页里,点击“引用”,来随时修改知识库内容。 与搜索测试类似,你可以直接在对话页里,点击“引用”,来随时修改知识库内容。
![查看答案引用](imgs/17.png) ![查看答案引用](/imgs/17.png)
## 总结 ## 总结
...@@ -120,4 +130,4 @@ FastGpt 提供了搜索测试和对话测试两种途径对知识库进行微调 ...@@ -120,4 +130,4 @@ FastGpt 提供了搜索测试和对话测试两种途径对知识库进行微调
3. 最有效的知识库构建方式是 QA 和手动构建。 3. 最有效的知识库构建方式是 QA 和手动构建。
4. Q 的长度不宜过长。 4. Q 的长度不宜过长。
5. 需要调整提示词,来引导模型回答知识库内容。 5. 需要调整提示词,来引导模型回答知识库内容。
6. 可以通过调整搜索相似度、最大搜索数量和限定词来控制模型回复的范围。 6. 可以通过调整搜索相似度、最大搜索数量和限定词来控制模型回复的范围。
\ No newline at end of file
---
title: "对接第三方 GPT 应用"
description: "通过与 OpenAI 兼容的 API 对接第三方应用"
icon: "model_training"
draft: false
toc: true
weight: 620
---
## 获取 API 秘钥
依次选择应用 -> 「API访问」,然后点击「API 密钥」来创建密钥。
{{% alert context="warning" %}}
密钥需要自己保管好,一旦关闭就无法再复制密钥,只能创建新密钥再复制。
{{% /alert %}}
![](/imgs/fastgpt-api.png)
## 组合秘钥
利用刚复制的 API 秘钥加上 AppId 组合成一个新的秘钥,格式为:`API 秘钥-AppId`,例如:`fastgpt-z51pkjqm9nrk03a1rx2funoy-642adec15f04d67d4613efdb`。
## 替换三方应用的变量
```bash
OPENAI_API_BASE_URL: https://fastgpt.run/api/openapi (改成自己部署的域名)
OPENAI_API_KEY = 组合秘钥
```
**[ChatGPT Next Web](https://github.com/Yidadaa/ChatGPT-Next-Web) 示例:**
![](/imgs/chatgptnext.png)
**[ChatGPT Web](https://github.com/Chanzhaoyu/chatgpt-web) 示例:**
![](/imgs/chatgptweb.png)
\ No newline at end of file
# 提示词示例 ---
title: "提示词示例"
description: "FastGPT 更多提示词示例"
icon: "sign_language"
draft: false
toc: true
weight: 610
---
## 客服 ## 客服
...@@ -80,7 +87,7 @@ ...@@ -80,7 +87,7 @@
客户:谢谢。 客户:谢谢。
样本示例5: 样本示例5:
户:87322.5。 客户:87322.5。
客服:好的,您是要扁圆头半空心铆钉吗?您需要具体什么材质的呢? 客服:好的,您是要扁圆头半空心铆钉吗?您需要具体什么材质的呢?
客户:材质无所谓。您们的最低起订量是多少? 客户:材质无所谓。您们的最低起订量是多少?
客服:起订量这边需要帮您查询一下系统。您是只要规格,材质无所谓吗? 客服:起订量这边需要帮您查询一下系统。您是只要规格,材质无所谓吗?
...@@ -103,4 +110,4 @@ ...@@ -103,4 +110,4 @@
客户:全牙201不锈钢 M825 客户:全牙201不锈钢 M825
客服说:好的,您总共有几种产品需要报价? 客服说:好的,您总共有几种产品需要报价?
客户:十几种 客户:十几种
``` ```
\ No newline at end of file
---
weight: 400
title: "高级编排"
description: "FastGPT 高级编排文档"
icon: "family_history"
draft: false
images: []
---
\ No newline at end of file
---
weight: 440
title: "编排示例"
description: "介绍 FastGPT 的高级编排实践案例"
icon: "list"
draft: false
images: []
---
\ No newline at end of file
# 谷歌搜索 ---
title: "联网 GPT"
description: "将 FastGPT 外接搜索引擎"
icon: "search"
draft: false
toc: true
weight: 441
---
![](./imgs/google_search_1.png) ![](/imgs/google_search_1.png)
![](./imgs/google_search_2.png) ![](/imgs/google_search_2.png)
如上图,利用 HTTP 模块,你可以轻松的外接一个搜索引擎。这里以调用 google search api 为例。 如上图,利用 HTTP 模块,你可以轻松的外接一个搜索引擎。这里以调用 Google Search API 为例。
## 注册 google search api ## 注册 Google Search API
[参考这篇文章,注册 google search api](https://zhuanlan.zhihu.com/p/174666017) [参考这篇文章](https://zhuanlan.zhihu.com/p/174666017)
## 写一个 google search 接口 ## 写一个 Google Search 接口
[这里用 laf 快速实现一个接口,即写即发布,无需部署。点击打开 laf cloud](https://laf.dev/),务必打开 POST 请求方式。 这里用 [Laf](https://laf.dev/) 快速实现一个接口,即写即发布,无需部署。务必打开 POST 请求方式。
```ts ```ts
import cloud from '@lafjs/cloud'; import cloud from '@lafjs/cloud';
...@@ -55,7 +62,7 @@ export default async function (ctx: FunctionContext) { ...@@ -55,7 +62,7 @@ export default async function (ctx: FunctionContext) {
## 模块编排 ## 模块编排
复制下面配置,点击高级编排右上角的导入按键,导入该配置,导入后将接口地址复制到 【HTTP 模块】。 复制下面配置,点击「高级编排」右上角的导入按键,导入该配置,导入后将接口地址复制到「HTTP 模块」。
```json ```json
[ [
...@@ -443,7 +450,7 @@ export default async function (ctx: FunctionContext) { ...@@ -443,7 +450,7 @@ export default async function (ctx: FunctionContext) {
## 流程说明 ## 流程说明
1. 提取模块将用户的问题提取成搜索关键词 1. 提取模块将用户的问题提取成搜索关键词。
2. 将搜索关键词传入 HTTP 模块 2. 将搜索关键词传入 HTTP 模块。
3. HTTP 模块调用谷歌搜索接口,返回搜索内容 3. HTTP 模块调用谷歌搜索接口,返回搜索内容。
4. 将搜索内容传入【AI 对话】的提示词,引导模型进行回答。 4. 将搜索内容传入【AI 对话】的提示词,引导模型进行回答。
\ No newline at end of file
--- ---
sidebar_position: 1 title: "高级编排介绍"
description: "快速了解 FastGPT 高级编排"
icon: "circle"
draft: false
toc: true
weight: 410
--- ---
# 快速了解 FastGPT 从 V4 版本开始采用新的交互方式来构建 AI 应用。使用了 Flow 节点编排的方式来实现复杂工作流,提高可玩性和扩展性。但同时也提高了上手的门槛,有一定开发背景的用户使用起来会比较容易。
FastGpt V4 后将采用新的交互方式来构建 AI 应用。使用了 Flow 节点编排的方式来实现复杂工作流,提高可玩性和扩展性。但同时也提高了上手的门槛,有一定开发背景的用户使用起来会比较容易。 ![](/imgs/flow-intro1.png)
这篇文章就来简单介绍一下模块编排基本内容。每个模块的详解会单独分出一章。
![](./imgs/intro1.png)
## 什么是模块? ## 什么是模块?
在程序中,模块可以理解为一个个 function 或者接口。可以理解为它就是一个**步骤**。将多个模块一个个拼接起来,即可一步步的去实现最终的 AI 输出。 在程序中,模块可以理解为一个个 Function 或者接口。可以理解为它就是一个**步骤**。将多个模块一个个拼接起来,即可一步步的去实现最终的 AI 输出。
如下图,是一个最简单的 AI 对话。它由用户输入的问题、聊天记录以及 AI 对话模块组成。 如下图,这是一个最简单的 AI 对话。它由用户输入的问题、聊天记录以及 AI 对话模块组成。
![](./imgs/intro2.png) ![](/imgs/flow-intro2.png)
运行的流程如下: 执行流程如下:
1. 用户输入问题后,会向服务器发送一个请求,并携带问题。从而得到【用户问题】模块的一个输出。 1. 用户输入问题后,会向服务器发送一个请求,并携带问题。从而得到【用户问题】模块的输出。
2. 根据设置的【最长记录数】来进行获取数据库中的记录数,从而得到【聊天记录】模块的输出。 2. 根据设置的【最长记录数】来获取数据库中的记录数,从而得到【聊天记录】模块的输出。
经过上面两个流程,就得到了左侧两个蓝色点的结果。结果会被注入到右侧的【AI】对话模块。 经过上面两个流程,就得到了左侧两个蓝色点的结果。结果会被注入到右侧的【AI】对话模块。
3. AI 对话模块根据传入的聊天记录和用户问题,调用对话接口,从而实现回答。(这里的对话结果输出隐藏了起来,默认只要触发了对话模块,就会往客户端输出内容) 3. 【AI 对话】模块根据传入的聊天记录和用户问题,调用对话接口,从而实现回答。(这里的对话结果输出隐藏了起来,默认只要触发了对话模块,就会往客户端输出内容)
### 模块分类 ### 模块分类
从功能上,可以分为 3 类: 从功能上,模块可以分为 3 类:
1. 仅读模块:全局变量、用户引导 1. **只读模块**:全局变量、用户引导。
2. 系统模块:聊天记录(无输入,直接从数据库取)、用户问题(流程入口) 2. **系统模块**:聊天记录(无输入,直接从数据库取)、用户问题(流程入口)。
3. 功能模块:知识库搜索、AI 对话等剩余模块。(这些模块都有输入和输出,可以自由组合) 3. **功能模块**:知识库搜索、AI 对话等剩余模块。(这些模块都有输入和输出,可以自由组合)。
### 模块的组成 ### 模块的组成
每个模块会包含 3 个核心部分:固定参数、外部输入(左边有个圆圈)和输出(右边有个圆圈)。 每个模块会包含 3 个核心部分:固定参数、外部输入(左边有个圆圈)和输出(右边有个圆圈)。
对于仅读模块,只需要根据提示填写即可,不参与流程运行。 + 对于只读模块,只需要根据提示填写即可,不参与流程运行。
+ 对于系统模块,通常只有固定参数和输出,主要需要关注输出到哪个位置。
对于系统模块,通常只有固定参数和输出,主要需要关注输出到哪个位置。 + 对于功能模块,通常这 3 部分都是重要的,以下图的 AI 对话为例:
对于功能模块,通常这 3 部分都是重要的,以下图的 AI 对话为例
![](./imgs/intro3.png)
- 对话模型、温度、回复上限、系统提示词和限定词为固定参数,同时系统提示词和限定词也可以作为外部输入,意味着如果你有输入流向了系统提示词,那么原本填写的内容就会被**覆盖**。
- 触发器、引用内容、聊天记录和用户问题则为外部输入,需要从其他模块的输出流入。
- 回复结束则为该模块的输出。 ![](/imgs/flow-intro3.png)
- 对话模型、温度、回复上限、系统提示词和限定词为固定参数,同时系统提示词和限定词也可以作为外部输入,意味着如果你有输入流向了系统提示词,那么原本填写的内容就会被**覆盖**。
- 触发器、引用内容、聊天记录和用户问题则为外部输入,需要从其他模块的输出流入。
- 回复结束则为该模块的输出。
### 模块什么时候执行? ### 模块什么时候被执行?
记住原则: 模块执行的原则:
1. 仅关心**已连接的**外部输入,即左边的圆圈被连接了。 1. 仅关心**已连接的**外部输入,即左边的圆圈被连接了。
2. 当连接内容都有值时触发。 2. 当连接内容都有值时触发。
#### 例子 1: #### 示例 1:
聊天记录模块会自动执行,因此聊天记录输入会自动赋值。当用户发送问题时,【用户问题】模块会输出值,此时【AI 对话】模块的用户问题输入也会被赋值。两个连接的输入都被赋值后,会执行 【AI 对话】模块。 聊天记录模块会自动执行,因此聊天记录输入会自动赋值。当用户发送问题时,【用户问题】模块会输出值,此时【AI 对话】模块的用户问题输入也会被赋值。两个连接的输入都被赋值后,会执行 【AI 对话】模块。
![](./imgs/intro1.png) ![](/imgs/flow-intro1.png)
#### 例子 2: #### 例子 2:
下图是一个知识库搜索例子。 下图是一个知识库搜索例子。
1. 历史记录会流入【AI】对话模块。 1. 历史记录会流入【AI 对话】模块。
2. 用户的问题会流入【知识库搜索】和【AI 对话】模块,由于【AI 对话】模块的触发器和引用内容还是空,此时不会执行。 2. 用户的问题会流入【知识库搜索】和【AI 对话】模块,由于【AI 对话】模块的触发器和引用内容还是空,此时不会执行。
3. 【知识库搜索】模块仅一个外部输入,并且被赋值,开始执行。 3. 【知识库搜索】模块仅一个外部输入,并且被赋值,开始执行。
4. 【知识库搜索】结果为空时,“搜索结果不为空”的值为空,不会输出,因此【AI 对话】模块会因为触发器没有赋值而无法执行。而“搜索结果为空”会有输出,流向指定回复的触发器,因此【指定回复】模块进行输出。 4. 【知识库搜索】结果为空时,“搜索结果不为空”的值为空,不会输出,因此【AI 对话】模块会因为触发器没有赋值而无法执行。而“搜索结果为空”会有输出,流向指定回复的触发器,因此【指定回复】模块进行输出。
5. 【知识库搜索】结果不为空时,“搜索结果不为空”和“引用内容”都有输出,会流向【AI 对话】,此时【AI 对话】的 4 个外部输入都被赋值,开始执行。 5. 【知识库搜索】结果不为空时,“搜索结果不为空”和“引用内容”都有输出,会流向【AI 对话】,此时【AI 对话】的 4 个外部输入都被赋值,开始执行。
![](./imgs/intro4.png) ![](/imgs/flow-intro4.png)
## 如何连接模块 ## 如何连接模块
1. 为了方便识别不同输入输出的类型,FastGPT 给每个模块的输入输出连接点不同的颜色,你可以把相同颜色的连接点连接起来。其中,灰色代表任意类型,可以随意连接。 1. 为了方便识别不同输入输出的类型,FastGPT 给每个模块的输入输出连接点赋予不同的颜色,你可以把相同颜色的连接点连接起来。其中,灰色代表任意类型,可以随意连接。
2. 位于左侧的连接点为输入,右侧的为输出,连接只能将一个输入和输出连接起来,不能输入和输入/输出和输出项链。 2. 位于左侧的连接点为输入,右侧的为输出,连接只能将一个输入和输出连接起来,不能连接“输入和输入”或者“输出和输出”。
3. 可以点击连接线中间的 x 来删除连接线。 3. 可以点击连接线中间的 x 来删除连接线。
4. 可以左键点击选中连接线 4. 可以左键点击选中连接线
...@@ -87,4 +84,4 @@ FastGpt V4 后将采用新的交互方式来构建 AI 应用。使用了 Flow ...@@ -87,4 +84,4 @@ FastGpt V4 后将采用新的交互方式来构建 AI 应用。使用了 Flow
1. 建议从左往右阅读。 1. 建议从左往右阅读。
2. 从 **用户问题** 模块开始。用户问题模块,代表的是用户发送了一段文本,触发任务开始。 2. 从 **用户问题** 模块开始。用户问题模块,代表的是用户发送了一段文本,触发任务开始。
3. 关注 AI 对话和指定回复模块,这两个模块是输出答案的地方。 3. 关注【AI 对话】和【指定回复】模块,这两个模块是输出答案的地方。
\ No newline at end of file
---
weight: 420
title: "模块介绍"
description: "介绍 FastGPT 的常用模块"
icon: "apps"
draft: false
images: []
---
\ No newline at end of file
# AI 对话 ---
title: "AI 对话"
- 可重复添加(复杂编排时候防止线太乱,可以更美观) description: "FastGPT AI 对话模块介绍"
icon: "chat"
draft: false
toc: true
weight: 423
---
## 特点
- 可重复添加(复杂编排时防止线太乱,可以更美观)
- 有外部输入 - 有外部输入
- 有静态配置 - 有静态配置
- 触发执行 - 触发执行
- 核心模块 - 核心模块
![](./imgs/aichat.png) ![](/imgs/aichat.png)
## 参数说明 ## 参数说明
### 对话模型 ### 对话模型
可以通过 [data/config.json](/docs/develop/data_config/chat_models) 配置可选的对话模型,通过 [OneAPI](http://localhost:3000/docs/develop/oneapi) 来实现多模型接入。 可以通过 [config.json](/docs/installation/reference/models/) 配置可选的对话模型,通过 [one-api](/docs/installation/one-api/) 来实现多模型接入。
### 温度 & 回复上限 ### 温度 & 回复上限
温度:越低回答越严谨,少废话(实测下来,感觉差别不大) + **温度**:越低回答越严谨,少废话(实测下来,感觉差别不大)
+ **回复上限**:最大回复 token 数量(只有 OpenAI 模型有效)。注意,是回复!不是总 tokens。
回复上限:最大回复 token 数量(只有 OpenAI 模型有效)。注意,是回复!不是总 tokens。
### 系统提示词(可被外部输入覆盖) ### 系统提示词(可被外部输入覆盖)
...@@ -30,7 +38,7 @@ ...@@ -30,7 +38,7 @@
### 引用内容 ### 引用内容
接收一个外部输入的数组,主要是由【知识库搜索】模块生成,也可以由 Http 模块从外部引入。数据结构例子如下: 接收一个外部输入的数组,主要是由【知识库搜索】模块生成,也可以由 HTTP 模块从外部引入。数据结构示例如下:
```ts ```ts
type DataType = { type DataType = {
...@@ -52,7 +60,7 @@ const quoteList: DataType[] = [ ...@@ -52,7 +60,7 @@ const quoteList: DataType[] = [
最终发送给 LLM 大模型的数据是一个数组,内容和顺序如下: 最终发送给 LLM 大模型的数据是一个数组,内容和顺序如下:
``` ```bash
[ [
系统提示词 系统提示词
引用内容 引用内容
...@@ -60,5 +68,4 @@ const quoteList: DataType[] = [ ...@@ -60,5 +68,4 @@ const quoteList: DataType[] = [
限定词 限定词
问题 问题
] ]
```
``` \ No newline at end of file
---
title: "内容提取"
description: "FastGPT 内容提取模块介绍"
icon: "content_paste_go"
draft: false
toc: true
weight: 424
---
## 特点
- 可重复添加
- 有外部输入
- 需要手动配置
- 触发执行
- function_call 模块
- 核心模块
![](/imgs/extract1.png)
## 功能
从文本中提取结构化数据,通常是配合 HTTP 模块实现扩展。也可以做一些直接提取操作,例如:翻译。
## 参数说明
### 提取要求描述
顾名思义,给模型设置一个目标,需要提取哪些内容。
**示例 1**
> 你是实验室预约助手,从对话中提取出姓名,预约时间,实验室号。当前时间 {{cTime}}
**示例 2**
> 你是谷歌搜索助手,从对话中提取出搜索关键词
**示例 3**
> 将我的问题直接翻译成英文,不要回答问题
### 历史记录
通常需要一些历史记录,才能更完整的提取用户问题。例如上图中需要提供姓名、时间和实验室名,用户可能一开始只给了时间和实验室名,没有提供自己的姓名。再经过一轮缺失提示后,用户输入了姓名,此时需要结合上一次的记录才能完整的提取出 3 个内容。
### 目标字段
目标字段与提取的结果相对应,从上图可以看到,每增加一个字段,输出会增加一个对应的出口。
+ **key**: 字段的唯一标识,不可重复!
+ **字段描述**:描述该字段是关于什么的,例如:姓名、时间、搜索词等等。
+ **必须**:是否强制模型提取该字段,可能提取出来是空字符串。
## 输出介绍
- **字段完全提取**:说明用户的问题中包含需要提取的所有内容。
- **提取字段缺失**:与 “字段完全提取” 对立,有缺失提取的字段时触发。
- **完整提取结果**: 一个 JSON 字符串,包含所有字段的提取结果。
- **目标字段提取结果**:类型均为字符串。
\ No newline at end of file
---
title: "用户引导"
description: "FastGPT 用户引导模块介绍"
icon: "psychology"
draft: false
toc: true
weight: 426
---
## 特点
- 仅可添加 1 个
- 无外部输入
- 不参与实际调度
如图,可以在用户提问前给予一定引导。并可以设置引导问题。
![](/imgs/guide.png)
---
title: "历史记录"
description: "FastGPT 历史记录模块介绍"
icon: "history"
draft: false
toc: true
weight: 427
---
# 特点
- 可重复添加(防止复杂编排时线太乱,重复添加可以更美观)
- 无外部输入
- 流程入口
- 自动执行
每次对话时,会从数据库取最多 n 条聊天记录作为上下文。注意,不是指本轮对话最多 n 条上下文,本轮对话还包括:提示词、限定词、引用内容和问题。
![](/imgs/history.png)
\ No newline at end of file
# HTTP 模块 ---
title: "HTTP 模块"
description: "FastGPT HTTP 模块介绍"
icon: "http"
draft: false
toc: true
weight: 428
---
## 特点
- 可重复添加 - 可重复添加
- 有外部输入 - 有外部输入
...@@ -6,15 +15,15 @@ ...@@ -6,15 +15,15 @@
- 触发执行 - 触发执行
- 核中核模块 - 核中核模块
![](./imgs/http1.png) ![](/imgs/http1.png)
## 介绍 ## 介绍
HTTP 模块会向对应的地址发送一个 POST 请求,Body 中携带 json 类型的参数,具体的参数可自定义。并接收一个 json 响应值,字段也是自定义。如上图中,我们定义了一个入参:提取的字段(定义的 key 为 appointment,类型为 string),和一个出参:提取结果(定义的 key 为 response,类型为 string)。 HTTP 模块会向对应的地址发送一个 POST 请求(Body 中携带 JSON 类型的参数,具体的参数可自定义),并接收一个 JSON 响应值,字段也是自定义。如上图中,我们定义了一个入参:「提取的字段」(定义的 key 为 appointment,类型为 string)和一个出参:「提取结果」(定义的 key 为 response,类型为 string)。
那么,这个请求的 curl 为: 那么,这个请求的命令为:
```curl ```bash
curl --location --request POST 'https://xxxx.laf.dev/appointment-lab' \ curl --location --request POST 'https://xxxx.laf.dev/appointment-lab' \
--header 'Content-Type: application/json' \ --header 'Content-Type: application/json' \
--data-raw '{ --data-raw '{
...@@ -30,11 +39,11 @@ curl --location --request POST 'https://xxxx.laf.dev/appointment-lab' \ ...@@ -30,11 +39,11 @@ curl --location --request POST 'https://xxxx.laf.dev/appointment-lab' \
} }
``` ```
**如果你不想额外的部署服务,可以使用 laf 快速的搭建接口,即写即发,无需部署** {{% alert context="warning" %}}
如果你不想额外部署服务,可以使用 [Laf](https://laf.dev/) 来快速开发上线接口,即写即发,无需部署。
[laf 在线地址](https://laf.dev/)
下面是一个请求例子: 下面是在 Laf 上编写的一个请求示例:
{{% /alert %}}
```ts ```ts
import cloud from '@lafjs/cloud'; import cloud from '@lafjs/cloud';
...@@ -92,4 +101,4 @@ export default async function (ctx: FunctionContext) { ...@@ -92,4 +101,4 @@ export default async function (ctx: FunctionContext) {
## 作用 ## 作用
基于 HTTP 模块,你可以做无限的扩展,可以操作数据库、执行联网搜索、发送邮箱等等。如果你有有趣的案例,欢迎 PR 到 [编排案例](/docs/category/examples) 基于 HTTP 模块可以无限扩展,比如操作数据库、执行联网搜索、发送邮箱等等。如果你有有趣的案例,欢迎提交 PR 到 [编排案例](/docs/category/examples)
\ No newline at end of file
---
title: "用户问题"
description: "FastGPT 用户问题模块介绍"
icon: "input"
draft: false
toc: true
weight: 430
---
## 特点
- 可重复添加(防止复杂编排时线太乱,重复添加可以更美观)
- 无外部输入
- 流程入口
- 自动执行
![](/imgs/chatinput.png)
\ No newline at end of file
# 问题分类 ---
title: "问题分类"
description: "FastGPT 问题分类模块介绍"
icon: "quiz"
draft: false
toc: true
weight: 425
---
## 特点
- 可重复添加 - 可重复添加
- 有外部输入 - 有外部输入
- 手动配置 - 需要手动配置
- 触发执行 - 触发执行
- function_call 模块 - function_call 模块
![](./imgs/cq1.png) ![](/imgs/cq1.png)
## 功能 ## 功能
...@@ -19,17 +28,17 @@ ...@@ -19,17 +28,17 @@
被放置在对话最前面,可用于补充说明分类内容的定义。例如问题会被分为: 被放置在对话最前面,可用于补充说明分类内容的定义。例如问题会被分为:
1. 打招呼 1. 打招呼
2. laf 常见问题 2. Laf 常见问题
3. 其他问题 3. 其他问题
由于 laf 不是一个明确的东西,需要给它一个定义,此时提示词里可以填入 laf 的定义: 由于 Laf 不是一个明确的东西,需要给它一个定义,此时提示词里可以填入 Laf 的定义:
``` ```
laf 是云开发平台,可以快速的开发应用 Laf 是云开发平台,可以快速的开发应用
laf 是一个开源的 BaaS 开发平台(Backend as a Service) Laf 是一个开源的 BaaS 开发平台(Backend as a Service)
laf 是一个开箱即用的 serverless 开发平台 Laf 是一个开箱即用的 serverless 开发平台
laf 是一个集「函数计算」、「数据库」、「对象存储」等于一身的一站式开发平台 Laf 是一个集「函数计算」、「数据库」、「对象存储」等于一身的一站式开发平台
laf 可以是开源版的腾讯云开发、开源版的 Google Firebase、开源版的 UniCloud Laf 可以是开源版的腾讯云开发、开源版的 Google Firebase、开源版的 UniCloud
``` ```
### 聊天记录 ### 聊天记录
...@@ -38,14 +47,14 @@ laf 可以是开源版的腾讯云开发、开源版的 Google Firebase、开源 ...@@ -38,14 +47,14 @@ laf 可以是开源版的腾讯云开发、开源版的 Google Firebase、开源
### 用户问题 ### 用户问题
输入的内容。 用户输入的内容。
### 分类内容 ### 分类内容
依然以这 3 个分类为例,可以看到最终组成的 function。其中返回值由系统随机生成,不需要关心。 依然以这 3 个分类为例,可以看到最终组成的 Function。其中返回值由系统随机生成,不需要关心。
1. 打招呼 1. 打招呼
2. laf 常见问题 2. Laf 常见问题
3. 其他问题 3. 其他问题
```js ```js
...@@ -57,7 +66,7 @@ const agentFunction = { ...@@ -57,7 +66,7 @@ const agentFunction = {
properties: { properties: {
type: { type: {
type: 'string', type: 'string',
description: `打招呼,返回: abc;laf 常见问题,返回:vvv;其他问题,返回:aaa` description: `打招呼,返回: abc;Laf 常见问题,返回:vvv;其他问题,返回:aaa`
enum: ["abc","vvv","aaa"] enum: ["abc","vvv","aaa"]
} }
}, },
...@@ -66,4 +75,4 @@ const agentFunction = { ...@@ -66,4 +75,4 @@ const agentFunction = {
}; };
``` ```
上面的 function 必然会返回 type = abc,vvv,aaa 其中一个值,从而实现分类判断。 上面的 Function 必然会返回 `type = abc,vvv,aaa` 其中一个值,从而实现分类判断。
\ No newline at end of file
---
title: "指定回复"
description: "FastGPT 指定回复模块介绍"
icon: "reply"
draft: false
toc: true
weight: 429
---
## 特点
- 可重复添加(防止复杂编排时线太乱,重复添加可以更美观)
- 可手动输入
- 可外部输入
- 会输出结果给客户端
制定回复模块通常用户特殊状态回复,当然你也可以像图 2 一样,实现一些比较骚的操作~ 触发逻辑非常简单:
1. 一种是写好回复内容,通过触发器触发。
2. 一种是不写回复内容,直接由外部输入触发,并回复输入的内容。
{{< figure
src="/imgs/specialreply.png"
alt=""
caption="图 1"
>}}
{{< figure
src="/imgs/specialreply2.png"
alt=""
caption="图 2"
>}}
\ No newline at end of file
--- ---
sidebar_position: 1 title: "触发器"
description: "FastGPT 触发器模块介绍"
icon: "work_history"
draft: false
toc: true
weight: 421
--- ---
# 触发器介绍
细心的同学可以发现,在每个功能模块里都会有一个叫【触发器】的外部输入,并且是 any 类型。 细心的同学可以发现,在每个功能模块里都会有一个叫【触发器】的外部输入,并且是 any 类型。
它的**核心作用**就是控制模块的执行时机,以下图 2 个知识库搜索中的【AI 对话】模块为例子: 它的**核心作用**就是控制模块的执行时机,以下图两个知识库搜索中的【AI 对话】模块为例子:
| 图 1 | 图 2 | | 图 1 | 图 2 |
| ---------------------------- | ---------------------------- | | ---------------------------- | ---------------------------- |
| ![Demo](./imgs/trigger1.png) | ![Demo](./imgs/trigger2.png) | | ![](/imgs/trigger1.png) | ![](/imgs/trigger2.png) |
【知识库搜索】模块中,由于**引用内容**始终会有输出,会导致【AI 对话】模块的**引用内容**输入无论有没有搜到内容都会被赋值。如果此时不连接触发器(图 2),在搜索结束后必定会执行【AI 对话】模块。 【知识库搜索】模块中,由于**引用内容**始终会有输出,会导致【AI 对话】模块的**引用内容**输入无论有没有搜到内容都会被赋值。如果此时不连接触发器(图 2),在搜索结束后必定会执行【AI 对话】模块。
...@@ -18,6 +21,4 @@ sidebar_position: 1 ...@@ -18,6 +21,4 @@ sidebar_position: 1
当搜索结果为空时,【知识库搜索】模块不会输出 **搜索结果不为空** 的结果,因此 【AI 对话】 模块的触发器始终为空,便不会执行。 当搜索结果为空时,【知识库搜索】模块不会输出 **搜索结果不为空** 的结果,因此 【AI 对话】 模块的触发器始终为空,便不会执行。
总之,记住模块执行的逻辑就可以灵活的使用触发器: 总之,记住模块执行的逻辑就可以灵活的使用触发器:**外部输入字段(有连接的才有效)全部被赋值时才会被执行**。
**外部输入字段(有连接的才有效)全部被赋值时候执行**
--- ---
sidebar_position: 2 title: "全局变量"
description: "FastGPT 全局变量模块介绍"
icon: "variables"
draft: false
toc: true
weight: 422
--- ---
# 全局变量
## 特点 ## 特点
- 仅可添加 1 个 - 仅可添加 1 个
- 手动配置 - 需要手动配置
- 对其他模块有影响 - 对其他模块有影响
- 可作为用户引导 - 可作为用户引导
...@@ -17,16 +20,16 @@ sidebar_position: 2 ...@@ -17,16 +20,16 @@ sidebar_position: 2
如下图,定义了两个变量:目标语言和下拉框测试(忽略) 如下图,定义了两个变量:目标语言和下拉框测试(忽略)
用户在对话前会被要求先填写目标语言,配合用户引导,我们就构建了一个简单的翻译机器人。**目标语言**的 key:language 被写入到【AI 对话】模块的限定词里。 用户在对话前会被要求先填写目标语言,配合用户引导,我们就构建了一个简单的翻译机器人。**目标语言**的 `key:language` 被写入到【AI 对话】模块的限定词里。
![](./imgs/variable.png) ![](/imgs/variable.png)
通过完整对话记录我们可以看到,实际的限定词从:“将我的问题直接翻译成{{language}}” 变成了 “将我的问题直接翻译成英语”,因为 {{language}} 被变量替换了。 通过完整对话记录我们可以看到,实际的限定词从:“将我的问题直接翻译成{{language}}” 变成了 “将我的问题直接翻译成英语”,因为 {{language}} 被变量替换了。
![](./imgs/variable2.png) ![](/imgs/variable2.png)
## 系统级变量 ## 系统级变量
除了用户自定义设置的变量外,还会有一些系统变量: 除了用户自定义设置的变量外,还会有一些系统变量:
cTime: 当前时间,例如:2023/3/3 20:22 + **cTime**: 当前时间。例如:2023/3/3 20:22
\ No newline at end of file
# Config Chat Model
By default, FastGPT is only configured with 3 models of GPT. If you need to integrate other models, you need to do some additional configuration.
## 1. Install OneAPI
First, you need to deploy a [OneAPI](/docs/develop/oneapi) and add the corresponding "channel".
![](./imgs/chatmodels1.png)
## 2. Add FastGPT Configuration
You can find the configuration file in /client/src/data/config.json (for local development, you need to copy it as config.local.json). In the configuration file, there is a section for chat model configuration:
```json
"ChatModels": [
{
"model": "gpt-3.5-turbo", // The model here needs to correspond to the model in OneAPI
"name": "FastAI-4k", // The name displayed externally
"contextMaxToken": 4000, // Maximum context token, calculated according to GPT35 regardless of the model. Models other than GPT need to roughly calculate this value themselves. You can call the official API to compare the token ratio and then roughly calculate it here.
// For example: the ratio of Chinese and English tokens in Wenxin Yiyuan is basically 1:1, while the ratio of Chinese tokens in GPT is 2:1. If the maximum token of Wenxin Yiyuan is 4000, then you can fill in 8000 here, or fill in 7000 for safety.
"quoteMaxToken": 2000, // Maximum token for quoting knowledge base
"maxTemperature": 1.2, // Maximum temperature
"price": 1.5, // Price per token => 1.5 / 100000 * 1000 = 0.015 yuan/1k token
"defaultSystem": "" // Default system prompt
},
{
"model": "gpt-3.5-turbo-16k",
"name": "FastAI-16k",
"contextMaxToken": 16000,
"quoteMaxToken": 8000,
"maxTemperature": 1.2,
"price": 3,
"defaultSystem": ""
},
{
"model": "gpt-4",
"name": "FastAI-Plus",
"contextMaxToken": 8000,
"quoteMaxToken": 4000,
"maxTemperature": 1.2,
"price": 45,
"defaultSystem": ""
}
],
```
### Add a New Model
Taking Wenxin Yiyuan as an example:
```json
"ChatModels": [
...
{
"model": "ERNIE-Bot",
"name": "Wenxin Yiyuan",
"contextMaxToken": 4000,
"quoteMaxToken": 2000,
"maxTemperature": 1,
"price": 1.2
}
...
]
```
After adding it, restart the application and you can choose the Wenxin Yiyuan model for conversation.
---
sidebar_position: 1
---
# Quick Introduction
Due to the limitations of environment variables in configuring complex content, the new version of FastGPT uses ConfigMap to mount the configuration file. You can see the default configuration file in `client/data/config.json`. You can refer to [docker-compose deployment](/docs/develop/deploy/docker) to mount the configuration file.
In the development environment, you need to make a copy of `config.json` as `config.local.json` for it to take effect.
This configuration file contains customization of the frontend page, system-level parameters, and AI dialogue models, etc.
**Note: The configuration instructions below are only a partial introduction. You need to mount the entire config.json file and not just a part of it. You can directly modify the provided config.json file based on the instructions below.**
## Brief Explanation of Basic Fields
Here are some basic configuration fields.
```json
// This configuration controls some styles of the frontend
"FeConfig": {
"show_emptyChat": true, // Whether to display the introduction page when the conversation page is empty
"show_register": false, // Whether to display the registration button (including forget password, register account, and third-party login)
"show_appStore": false, // Whether to display the app store (currently the permission is not properly set, so it is useless to open it)
"show_userDetail": false, // Whether to display user details (account balance, OpenAI binding)
"show_git": true, // Whether to display Git
"systemTitle": "FastGPT", // The title of the system
"authorText": "Made by FastGPT Team.", // Signature
"gitLoginKey": "" // Git login credentials
}
```
```json
// This configuration file contains system-level parameters
"SystemParams": {
"gitLoginSecret": "", // Git login credentials
"vectorMaxProcess": 15, // Maximum number of processes for vector generation, set in combination with database performance and key
"qaMaxProcess": 15, // Maximum number of processes for QA generation, set in combination with database performance and key
"pgIvfflatProbe": 20 // pg vector search probe. Can be ignored before setting the index, usually only needed for more than 500,000 groups.
},
```
# Mac 上部署可能遇到的问题(旧版)
### 前置条件
1、可以 curl api.openai.com
2、有 openai key
3、有邮箱 MAILE_CODE
4、有 docker
```
docker -v
```
5、有 pnpm ,可以使用`brew install pnpm`安装
6、需要创建一个放置 pg 和 mongo 数据的文件夹,这里创建在`~/fastgpt`目录中,里面有`pg` 和`mongo `两个文件夹
```
➜ fastgpt pwd
/Users/jie/fastgpt
➜ fastgpt ls
mongo pg
```
### docker 部署方式
这种方式主要是为了方便调试,可以使用`pnpm dev ` 运行 fastgpt 项目
**1、.env.local 文件**
```
# proxy
AXIOS_PROXY_HOST=127.0.0.1
AXIOS_PROXY_PORT_FAST=7890
AXIOS_PROXY_PORT_NORMAL=7890
# email
MY_MAIL= {Your Mail}
MAILE_CODE={Yoir Mail code}
# ali ems
aliAccessKeyId=xxx
aliAccessKeySecret=xxx
aliSignName=xxx
aliTemplateCode=SMS_xxx
# token
TOKEN_KEY=sswada
# 使用 oneapi
ONEAPI_URL=[https://api.xyz.com/v1](https://xxxxx.cloud.sealos.io/v1)
ONEAPI_KEY=sk-xxxxxx
# openai
OPENAIKEY=sk-xxx # 对话用的key
OPENAI_TRAINING_KEY=sk-xxx # 训练用的key
# db
MONGODB_URI=mongodb://username:password@0.0.0.0:27017/test?authSource=admin
PG_HOST=0.0.0.0
PG_PORT=8100
PG_USER=xxx
PG_PASSWORD=xxx
PG_DB_NAME=fastgpt
```
**2、部署 mongo**
```
docker run --name mongo -p 27017:27017 -e MONGO_INITDB_ROOT_USERNAME=username -e MONGO_INITDB_ROOT_PASSWORD=password -v ~/fastgpt/mongo/data:/data/db -d mongo:4.0.1
```
**3、部署 pgsql**
```
docker run -it --name pg -e "POSTGRES_DB=fastgpt" -e "POSTGRES_PASSWORD=xxx" -e POSTGRES_USER=xxx -p 8100:5432 -v ~/fastgpt/pg/data:/var/lib/postgresql/data -d octoberlan/pgvector:v0.4.1
```
进 pgsql 容器运行
```
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
CREATE EXTENSION IF NOT EXISTS vector;
-- init table
CREATE TABLE IF NOT EXISTS modeldata (
id BIGSERIAL PRIMARY KEY,
vector VECTOR(1536) NOT NULL,
user_id VARCHAR(50) NOT NULL,
kb_id VARCHAR(50) NOT NULL,
source VARCHAR(100),
q TEXT NOT NULL,
a TEXT NOT NULL
);
-- 索引设置,按需取
-- CREATE INDEX IF NOT EXISTS modeldata_userId_index ON modeldata USING HASH (user_id);
-- CREATE INDEX IF NOT EXISTS modeldata_kbId_index ON modeldata USING HASH (kb_id);
-- CREATE INDEX IF NOT EXISTS idx_model_data_md5_q_a_user_id_kb_id ON modeldata (md5(q), md5(a), user_id, kb_id);
-- CREATE INDEX modeldata_id_desc_idx ON modeldata (id DESC);
-- vector 索引,可以参考 [pg vector](https://github.com/pgvector/pgvector) 去配置,根据数据量去配置
EOSQL
```
4、**最后在 FASTGPT 项目里面运行 pnpm dev 运行项目,然后进入 localhost:3000 看项目是否跑起来了**
---
sidebar_position: 1
---
# Sealos 一键部署
无需服务器、无需魔法、无需域名,点击即可部署 👇
[![](https://raw.githubusercontent.com/labring-actions/templates/main/Deploy-on-Sealos.svg)](https://cloud.sealos.io/?openapp=system-fastdeploy%3FtemplateName%3Dfastgpt)
由于需要部署数据库,部署完后需要等待 2~4 分钟才能正常访问。默认用了最低配置,首次访问时会有些慢。
![](./imgs/sealos1.png)
## 运行
点击 sealos 提供的【外网地址】即可使用。登录用户名为: root,密码是刚设置的环境变量,上图中设置了: 1234
![](./imgs/sealos3.png)
# 本地开发
第一次开发,需要先部署数据库,建议本地开发可以随便找一台 2c2g 的轻量小数据库实践。数据库部署教程:[Docker 快速部署](/docs/develop/deploy/docker)
client 目录下为 FastGPT 核心代码。NextJS 框架前后端在一起的,api 服务位于 src/pages/api 内。
## 初始配置
**1. 环境变量**
复制.env.template 文件,生成一个.env.local 环境变量文件夹,修改.env.local 里内容才是有效的变量。变量说明见 .env.template
**2. config 配置文件**
复制 data/config.json 文件,生成一个 data/config.local.json 配置文件。
这个文件大部分时候不需要修改。只需要关注 SystemParams 里的参数:
```
"vectorMaxProcess": 向量生成最大进程,根据数据库和 key 的并发数来决定,通常单个 120 号,2c4g 服务器设置10~15。
"qaMaxProcess": QA 生成最大进程
"pgIvfflatProbe": PG vector 搜索探针,没有添加 vector 索引时可忽略。
```
## 运行
```
cd client
pnpm i
pnpm dev
```
## 镜像打包
```bash
docker build -t dockername/fastgpt .
```
# Sealos 快速部署 OneAPI
无需魔法,部署即可使用
## SqlLite 版本
sqllite 版本适合个人,少并发
## 一、[点击打开 Sealos 公有云](https://cloud.sealos.io/)
## 二、打开 AppLaunchpad(应用管理) 工具
![step1](./imgs/step1.png)
## 三、点击创建新应用
## 四、填写对应参数
镜像:ghcr.io/songquanpeng/one-api:latest
![step2](./imgs/step2.png)
打开外网访问开关后,Sealos 会自动分配一个可访问的地址,不需要自己配置。
![step3](./imgs/step3.png)
填写完参数后,点击右上角部署即可。
## 5. 访问
点击 Sealos 提供的外网访问地址,即可访问 OneAPI 项目。
![step3](./imgs/step4.png)
![step3](./imgs/step5.png)
## 6. 替换 FastGpt 的环境变量
```
# 下面的地址是 Sealos 提供的,务必写上 v1
OPENAI_BASE_URL=https://xxxx.cloud.sealos.io/v1
# 下面的 key 由 one-api 提供
CHAT_API_KEY=sk-xxxxxx
```
## MySQL 版本
高流量推荐使用 MySQL 版本,支持多实例扩展。
点击下方按键一键部署 👇
[![](https://raw.githubusercontent.com/labring-actions/templates/main/Deploy-on-Sealos.svg)](https://cloud.sealos.io/?openapp=system-fastdeploy%3FtemplateName%3Done-api)
部署完后会跳转【应用管理】,数据库在另一个应用里。需要等待 1~3 分钟数据库运行后才能访问成功。
# 安装 clash
clash 会在本机启动代理。对应的,你需要配置项目的两个环境变量:
```
AXIOS_PROXY_HOST=127.0.0.1
AXIOS_PROXY_PORT=7890
```
需要注的是,在你的 config.yaml 文件中,最好仅指定 api.openai.com 走代理,其他请求都直连。
**安装clash**
```bash
# 下载包
curl https://glados.rocks/tools/clash-linux.zip -o clash.zip
# 解压
unzip clash.zip
# 下载终端配置⽂件(改成自己配置文件路径)
curl https://update.glados-config.com/clash/98980/8f30944/70870/glados-terminal.yaml > config.yaml
# 赋予运行权限
chmod +x ./clash-linux-amd64-v1.10.0
```
**runClash.sh**
```sh
# 记得配置端口变量:
export ALL_PROXY=socks5://127.0.0.1:7891
export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890
export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890
# 运行脚本: 删除clash - 到 clash 目录 - 删除缓存 - 执行运行. 会生成一个 nohup.out 文件,可以看到 clash 的 logs
OLD_PROCESS=$(pgrep clash)
if [ ! -z "$OLD_PROCESS" ]; then
echo "Killing old process: $OLD_PROCESS"
kill $OLD_PROCESS
fi
sleep 2
cd **/clash
rm -f ./nohup.out || true
rm -f ./cache.db || true
nohup ./clash-linux-amd64-v1.10.0 -d ./ &
echo "Restart clash"
```
**config.yaml配置例子**
```yaml
mixed-port: 7890
allow-lan: false
bind-address: '*'
mode: rule
log-level: warning
dns:
enable: true
ipv6: false
nameserver:
- 8.8.8.8
- 8.8.4.4
cache-size: 400
proxies:
-
proxy-groups:
- { name: '♻️ 自动选择', type: url-test, proxies: [香港V01×1.5], url: 'https://api.openai.com', interval: 3600}
rules:
- 'DOMAIN-SUFFIX,api.openai.com,♻️ 自动选择'
- 'MATCH,DIRECT'
```
\ No newline at end of file
# nginx 反向代理 openai 接口
如果你有国外的服务器,可以通过配置 nginx 反向代理,转发 openai 相关的请求,从而让国内的服务器可以通过访问该 nginx 去访问 openai 接口。
```conf
user nginx;
worker_processes auto;
worker_rlimit_nofile 51200;
events {
worker_connections 1024;
}
http {
resolver 8.8.8.8;
proxy_ssl_server_name on;
access_log off;
server_names_hash_bucket_size 512;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
client_max_body_size 50M;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 8k;
gzip_http_version 1.1;
gzip_comp_level 6;
gzip_vary on;
gzip_types text/plain application/x-javascript text/css application/javascript application/json application/xml;
gzip_disable "MSIE [1-6]\.";
open_file_cache max=1000 inactive=1d;
open_file_cache_valid 30s;
open_file_cache_min_uses 8;
open_file_cache_errors off;
server {
listen 3999;
server_name 你的 ip 地址;
location ~ /openai/(.*) {
proxy_pass https://api.openai.com/$1$is_args$args;
proxy_set_header Host api.openai.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 流式响应
proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;
proxy_buffering off;
proxy_cache off;
# 一般响应
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}
}
}
```
# V4.1 版本初始化
新版重新设置了对话存储结构,需要初始化原来的存储内容
## 更新环境变量
优化了 PG 和 Mongo 的连接变量,只需要 1 个 url 即可。
```
# mongo 配置,不需要改. 如果连不上,可能需要去掉 ?authSource=admin
- MONGODB_URI=mongodb://username:password@mongo:27017/fastgpt?authSource=admin
# pg配置. 不需要改
- PG_URL=postgresql://username:password@pg:5432/postgres
```
## 执行初始化 API
部署新版项目,并发起 1 个 HTTP 请求(记得携带 headers.rootkey,这个值是环境变量里的)
https://xxxxx/api/admin/initChatItem
# Google Search
![](./imgs/google_search_1.png)
![](./imgs/google_search_2.png)
As shown in the above images, with the help of the HTTP module, you can easily integrate a search engine. Here, we take calling the Google Search API as an example.
## Register Google Search API
[Refer to this article to register the Google Search API](https://zhuanlan.zhihu.com/p/174666017)
## Create a Google Search interface
[Here, we use laf to quickly implement an interface, which can be written and published without deployment. Click to open laf cloud](https://laf.dev/), make sure to open the POST request method.
```ts
import cloud from '@lafjs/cloud';
const googleSearchKey = '';
const googleCxId = '';
const baseurl = 'https://www.googleapis.com/customsearch/v1';
export default async function (ctx: FunctionContext) {
const { searchKey } = ctx.body;
if (!searchKey) {
return {
prompt: ''
};
}
try {
const { data } = await cloud.fetch.get(baseurl, {
params: {
q: searchKey,
cx: googleCxId,
key: googleSearchKey,
c2coff: 1,
start: 1,
end: 5,
dateRestrict: 'm[1]'
}
});
const result = data.items.map((item) => item.snippet).join('\n');
return { prompt: `搜索词: ${searchKey};google 搜索结果: ${result}` };
} catch (err) {
console.log(err);
return {
prompt: ''
};
}
}
```
## Workflow
Copy the following configuration, click the Import button in the upper right corner of Advanced orchestration, import the configuration, and copy the interface address to [HTTP module] after import.
```json
[
{
"moduleId": "userChatInput",
"name": "用户问题(对话入口)",
"flowType": "questionInput",
"position": {
"x": 464.32198615344566,
"y": 1602.2698463081606
},
"inputs": [
{
"key": "userChatInput",
"type": "systemInput",
"label": "用户问题",
"connected": true
}
],
"outputs": [
{
"key": "userChatInput",
"label": "用户问题",
"type": "source",
"valueType": "string",
"targets": [
{
"moduleId": "6g2075",
"key": "content"
},
{
"moduleId": "aijmbb",
"key": "userChatInput"
}
]
}
]
},
{
"moduleId": "history",
"name": "聊天记录",
"flowType": "historyNode",
"position": {
"x": 452.5466249541586,
"y": 1276.3930310334215
},
"inputs": [
{
"key": "maxContext",
"type": "numberInput",
"label": "最长记录数",
"value": 6,
"min": 0,
"max": 50,
"connected": true
},
{
"key": "history",
"type": "hidden",
"label": "聊天记录",
"connected": true
}
],
"outputs": [
{
"key": "history",
"label": "聊天记录",
"valueType": "chat_history",
"type": "source",
"targets": [
{
"moduleId": "6g2075",
"key": "history"
},
{
"moduleId": "aijmbb",
"key": "history"
}
]
}
]
},
{
"moduleId": "6g2075",
"name": "文本内容提取",
"flowType": "contentExtract",
"showStatus": true,
"position": {
"x": 971.5119545668634,
"y": 1118.186021718385
},
"inputs": [
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": false
},
{
"key": "description",
"type": "textarea",
"valueType": "string",
"label": "提取要求描述",
"description": "写一段提取要求,告诉 AI 需要提取哪些内容",
"required": true,
"placeholder": "例如: \n1. 你是一个实验室预约助手。根据用户问题,提取出姓名、实验室号和预约时间",
"value": "你是谷歌搜索机器人,可以生成搜索词。你需要自行判断是否需要生成搜索词,如果不需要则返回空字符串。",
"connected": true
},
{
"key": "history",
"type": "target",
"label": "聊天记录",
"valueType": "chat_history",
"connected": true
},
{
"key": "content",
"type": "target",
"label": "需要提取的文本",
"required": true,
"valueType": "string",
"connected": true
},
{
"key": "extractKeys",
"type": "custom",
"label": "目标字段",
"description": "由 '描述' 和 'key' 组成一个目标字段,可提取多个目标字段",
"value": [
{
"desc": "搜索词",
"key": "searchKey",
"required": false
}
],
"connected": true
}
],
"outputs": [
{
"key": "success",
"label": "字段完全提取",
"valueType": "boolean",
"type": "source",
"targets": []
},
{
"key": "failed",
"label": "提取字段缺失",
"valueType": "boolean",
"type": "source",
"targets": [
{
"moduleId": "aijmbb",
"key": "switch"
}
]
},
{
"key": "fields",
"label": "完整提取结果",
"description": "一个 JSON 字符串,例如:{\"name:\":\"YY\",\"Time\":\"2023/7/2 18:00\"}",
"valueType": "string",
"type": "source",
"targets": []
},
{
"key": "searchKey",
"label": "提取结果-搜索词",
"description": "无法提取时不会返回",
"valueType": "string",
"type": "source",
"targets": [
{
"moduleId": "5fk9ru",
"key": "searchKey"
}
]
}
]
},
{
"moduleId": "5fk9ru",
"name": "HTTP模块",
"flowType": "httpRequest",
"showStatus": true,
"position": {
"x": 1481.5339897373183,
"y": 1290.2958964143072
},
"inputs": [
{
"key": "url",
"value": "https://d8dns0.laf.dev/google_web_search",
"type": "input",
"label": "请求地址",
"description": "请求目标地址",
"placeholder": "https://api.fastgpt.run/getInventory",
"required": true,
"connected": true
},
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": false
},
{
"valueType": "string",
"type": "target",
"label": "搜索词",
"edit": true,
"key": "searchKey",
"required": true,
"connected": true
}
],
"outputs": [
{
"label": "搜索词",
"valueType": "string",
"type": "source",
"edit": true,
"targets": [],
"key": "searchKey"
},
{
"label": "搜索结果",
"valueType": "string",
"type": "source",
"edit": true,
"targets": [
{
"moduleId": "aijmbb",
"key": "systemPrompt"
}
],
"key": "prompt"
},
{
"key": "finish",
"label": "请求结束",
"valueType": "boolean",
"type": "source",
"targets": [
{
"moduleId": "aijmbb",
"key": "switch"
}
]
}
]
},
{
"moduleId": "aijmbb",
"name": "AI 对话",
"flowType": "chatNode",
"showStatus": true,
"position": {
"x": 2086.6387991825745,
"y": 1090.812798225035
},
"inputs": [
{
"key": "model",
"type": "custom",
"label": "对话模型",
"value": "gpt-3.5-turbo-16k",
"list": [],
"connected": true
},
{
"key": "temperature",
"type": "slider",
"label": "温度",
"value": 0,
"min": 0,
"max": 10,
"step": 1,
"markList": [
{
"label": "严谨",
"value": 0
},
{
"label": "发散",
"value": 10
}
],
"connected": true
},
{
"key": "maxToken",
"type": "custom",
"label": "回复上限",
"value": 8000,
"min": 100,
"max": 4000,
"step": 50,
"markList": [
{
"label": "100",
"value": 100
},
{
"label": "4000",
"value": 4000
}
],
"connected": true
},
{
"key": "systemPrompt",
"type": "textarea",
"label": "系统提示词",
"valueType": "string",
"description": "模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}",
"placeholder": "模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}",
"value": "",
"connected": true
},
{
"key": "limitPrompt",
"type": "textarea",
"valueType": "string",
"label": "限定词",
"description": "限定模型对话范围,会被放置在本次提问前,拥有强引导和限定性。可使用变量,例如 {{language}}。引导例子:\n1. 知识库是关于 Laf 的介绍,参考知识库回答问题,与 \"Laf\" 无关内容,直接回复: \"我不知道\"。\n2. 你仅回答关于 \"xxx\" 的问题,其他问题回复: \"xxxx\"",
"placeholder": "限定模型对话范围,会被放置在本次提问前,拥有强引导和限定性。可使用变量,例如 {{language}}。引导例子:\n1. 知识库是关于 Laf 的介绍,参考知识库回答问题,与 \"Laf\" 无关内容,直接回复: \"我不知道\"。\n2. 你仅回答关于 \"xxx\" 的问题,其他问题回复: \"xxxx\"",
"value": "上文是谷歌搜索的结果,你可以提供实时信息,根据搜索结果回答问题。当前时间是{{cTime}}。",
"connected": true
},
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": true
},
{
"key": "quoteQA",
"type": "target",
"label": "引用内容",
"valueType": "kb_quote",
"connected": false
},
{
"key": "history",
"type": "target",
"label": "聊天记录",
"valueType": "chat_history",
"connected": true
},
{
"key": "userChatInput",
"type": "target",
"label": "用户问题",
"required": true,
"valueType": "string",
"connected": true
}
],
"outputs": [
{
"key": "answerText",
"label": "模型回复",
"description": "直接响应,无需配置",
"type": "hidden",
"targets": []
},
{
"key": "finish",
"label": "回复结束",
"description": "AI 回复完成后触发",
"valueType": "boolean",
"type": "source",
"targets": []
}
]
}
]
```
## Process Description
1. The extraction module extracts the user's question into search keywords.
2. The search keywords are passed to the HTTP module.
3. The HTTP module calls the Google search API and returns the search results.
4. The search results are passed to the prompt of the "AI Dialogue" to guide the model in generating an answer.
---
sidebar_position: 1
---
# Quick Start
Starting from FastGpt V4, a new interactive way is introduced to build AI applications. It uses Flow node orchestration to implement complex workflows, improving playability and scalability. However, this also increases the learning curve, and users with some development background may find it easier to use.
This article provides a brief introduction to the basics of module orchestration. Each module will be explained in detail in separate chapters.
![](./imgs/intro1.png)
## What is a Module?
In programming, a module can be understood as a function or interface. It can be seen as a **step**. By connecting multiple modules together, you can gradually achieve the final AI output.
In the following diagram, we have a simple AI conversation. It consists of a user input question, chat records, and an AI conversation module.
![](./imgs/intro2.png)
The workflow is as follows:
1. After the user inputs a question, a request is sent to the server with the question, resulting in an output from the "User Question" module.
2. The "Chat Records" module retrieves the number of records from the database based on the set "Max Record Count", resulting in an output.
After the above two steps, we obtain the results of the two blue dots on the left. The results are injected into the "AI" conversation module on the right.
3. The AI conversation module uses the chat records and user question as inputs to call the conversation API and generate a response. (The conversation result output is hidden by default and will be sent to the client whenever the conversation module is triggered)
### Module Categories
In terms of functionality, modules can be divided into 3 categories:
1. Read-only modules: global variables, user prompts
2. System modules: chat records (no input, directly retrieved from the database), user question (workflow entry)
3. Function modules: knowledge base search, AI conversation, and other remaining modules (these modules have both input and output and can be freely combined)
### Module Components
Each module consists of 3 core parts: fixed parameters, external inputs (represented by a circle on the left), and outputs (represented by a circle on the right).
For read-only modules, you only need to fill in the prompts and they do not participate in the workflow execution.
For system modules, usually only fixed parameters and outputs are present, and the focus is on where the output is directed.
For function modules, all 3 parts are important. Taking the AI conversation module in the following diagram as an example:
![](./imgs/intro3.png)
The dialogue model, temperature, reply limit, system prompts, and restricted words are fixed parameters. The system prompts and restricted words can also be used as external inputs, which means that if you have an input flow to the system prompts, the originally filled content will be **overwritten**.
The triggers, referenced content, chat records, and user question are external inputs that need to flow in from the outputs of other modules.
The reply end is the output of this module.
### When are Modules Executed?
Remember the principles:
1. Only **connected** external inputs matter, i.e., the circles on the left are connected.
2. Execution is triggered when all connected inputs have values.
#### Example 1:
The chat records module is automatically executed, so the input for chat records is automatically assigned a value. When the user sends a question, the "User Question" module outputs a value, and at this point, the user question input of the "AI Conversation" module is also assigned a value. After both connected inputs have values, the "AI Conversation" module is executed.
![](./imgs/intro1.png)
#### Example 2:
The following diagram shows an example of a knowledge base search.
1. The chat history flows into the "AI" conversation module.
2. The user's question flows into both the "Knowledge Base Search" and "AI Conversation" modules. Since the triggers and referenced content of the "AI Conversation" module are still empty, it will not be executed at this point.
3. The "Knowledge Base Search" module has only one external input, and it is assigned a value, so it starts executing.
4. When the "Knowledge Base Search" result is empty, the value of "Search Result Not Empty" is empty and will not be output. Therefore, the "AI Conversation" module cannot be executed due to the triggers not being assigned a value. However, "Search Result Empty" has an output and flows to the triggers of the specified reply module, so the "Specified Reply" module outputs a response.
5. When the "Knowledge Base Search" result is not empty, both "Search Result Not Empty" and "Referenced Content" have outputs, which flow into the "AI Conversation" module. At this point, all 4 external inputs of the "AI Conversation" module are assigned values, and it starts executing.
![](./imgs/intro4.png)
## How to Read?
1. It is recommended to read from left to right.
2. Start with the "User Question" module. The user question module represents a user sending a piece of text, triggering the task.
3. Pay attention to the "AI Conversation" and "Specified Reply" modules, as these are the places where the answers are output.
# AI Chat
- Repeatable addition (to prevent messy lines in complex arrangements and make it more visually appealing)
- External input available
- Static configuration available
- Trigger execution
- Core module
![](./imgs/aichat.png)
## Parameter Description
### Chat Model
You can configure the optional chat models through [data/config.json](/docs/develop/data_config/chat_models) and implement multi-model access through [OneAPI](http://localhost:3000/docs/develop/oneapi).
### Temperature & Reply Limit
Temperature: The lower the temperature, the more precise the answer and the less unnecessary words (tested, but the difference doesn't seem significant).
Reply Limit: Maximum number of reply tokens (only applicable to OpenAI models). Note that this is the reply, not the total tokens.
### System Prompt (can be overridden by external input)
Placed at the beginning of the context array with the role as system, used to guide the model. Refer to the tutorials of various search engines for specific usage~
### Constraint Words (can be overridden by external input)
Similar to system prompts, the role is also system type, but the position is placed before the question, with a stronger guiding effect.
### Quoted Content
Receives an array of external input, mainly generated by the "Knowledge Base Search" module, and can also be imported from external sources through the Http module. The data structure example is as follows:
```ts
type DataType = {
kb_id?: string;
id?: string;
q: string;
a: string;
source?: string;
};
// If it is externally imported content, try not to carry kb_id and id
const quoteList: DataType[] = [
{ kb_id: '11', id: '222', q: '你还', a: '哈哈', source: '' },
{ kb_id: '11', id: '333', q: '你还', a: '哈哈', source: '' },
{ kb_id: '11', id: '444', q: '你还', a: '哈哈', source: '' }
];
```
## Complete Context Composition
The data sent to the LLM model in the end is an array, with the content and order as follows:
```
[
System Prompt
Quoted Content
Chat History
Constraint Words
Question
]
```
# Content Extraction
- Repeatable addition
- External input
- Manual configuration
- Trigger execution
- function_call module
- Core module
![](./imgs/extract1.png)
## Functionality
Extract structured data from text, usually in conjunction with the HTTP module for extension. It can also perform direct extraction operations, such as translation.
## Parameter Description
### Extraction Requirement Description
As the name suggests, give the model a target and specify which content needs to be extracted.
**Example 1**
> You are a lab reservation assistant, extract the name, appointment time, and lab number from the conversation. Current time is {{cTime}}.
**Example 2**
> You are a Google search assistant, extract the search keywords from the conversation.
**Example 3**
> Translate my question directly into English, do not answer the question.
### History Records
Usually, some history records are needed to extract user questions more completely. For example, in the figure above, the name, time, and lab name need to be provided in advance. The user may only provide the time and lab name at the beginning, without giving their own name. After a round of missing prompts, the user enters their name. At this time, it is necessary to combine the previous record to extract all 3 contents completely.
### Target Fields
The target fields correspond to the extracted results. From the figure above, it can be seen that for each additional field, there will be a corresponding output.
key: The unique identifier of the field, cannot be repeated!
Field Description: Describes what the field is about, such as name, time, search term, etc.
Required: Whether to force the model to extract the field, it may be extracted as an empty string.
## Output Introduction
- Field fully extracted: Indicates that the user's question contains all the content that needs to be extracted.
- Missing extracted fields: The opposite of "Field fully extracted", triggered when there are missing extracted fields.
- Complete extraction result: A JSON string containing the extraction results of all fields.
- Extraction results of target fields: All types are strings.
# Problem Classification
- Can be added repeatedly
- Has external input
- Manual configuration
- Trigger execution
- function_call module
![](./imgs/cq1.png)
## Functionality
It can classify user questions and perform different operations based on the classification. In some ambiguous scenarios, the classification effect may not be very obvious.
## Parameter Description
### System Prompt Words
Placed at the beginning of the conversation, it can be used to supplement the definition of the classification content. For example, questions will be classified into:
1. Greetings
2. Common questions about laf
3. Other questions
Because laf is not a clear concept and needs to be defined, the prompt words can be filled with the definition of laf:
```
laf is a cloud development platform that allows for rapid application development.
laf is an open-source BaaS (Backend as a Service) development platform.
laf is a ready-to-use serverless development platform.
laf is an all-in-one development platform that combines "function computing," "database," "object storage," and more.
laf can be an open-source version of Tencent Cloud Development, Google Firebase, or UniCloud.
```
### Chat Records
Adding some chat records can help with context-based classification.
### User Question
The input content from the user.
### Classification Content
Using the example of these 3 classifications, you can see the final function composition. The return value is randomly generated by the system and does not need to be concerned about.
1. Greetings
2. Common questions about laf
3. Other questions
```js
const agentFunction = {
name: agentFunName,
description: 'Determines the type of user question and returns the corresponding enumeration field',
parameters: {
type: 'object',
properties: {
type: {
type: 'string',
description: `Greetings, return: abc; Common questions about laf, return: vvv; Other questions, return: aaa`
enum: ["abc","vvv","aaa"]
}
},
required: ['type']
}
};
```
The above function will definitely return one of the values: abc, vvv, or aaa, thereby achieving classification determination.
# User Guide
- Only one can be added
- No external input
- Not involved in actual scheduling
As shown in the image, you can provide some guidance to the user before asking questions. You can also set a guiding question.
![](./imgs/guide.png)
# History
- Can be repeated (to prevent messy lines when complex arrangements are made, for a more aesthetic appearance)
- No external input
- Entry point of the process
- Automatic execution
During each conversation, up to n chat records will be retrieved from the database as context. Note that this does not refer to a maximum of n context records for the current round of conversation, as the current round of conversation also includes: prompts, qualifiers, referenced content, and questions.
![](./imgs/history.png)
# HTTP Module
- Can be added repeatedly
- Has external input
- Manual configuration
- Trigger execution
- Core module
![](./imgs/http1.png)
## Introduction
The HTTP module sends a POST request to the corresponding address, with json parameters in the body. The specific parameters can be customized. It also receives a json response value, with customizable fields. In the above figure, we define an input parameter: extracted field (key is appointment, type is string), and an output parameter: extraction result (key is response, type is string).
So, the curl command for this request is:
```curl
curl --location --request POST 'https://xxxx.laf.dev/appointment-lab' \
--header 'Content-Type: application/json' \
--data-raw '{
"appointment":"{\"name\":\"小明\",\"time\":\"2023/08/16 15:00\",\"labname\":\"子良A323\"}"
}'
```
The response is:
```json
{
"response": "您已经有一个预约记录了,每人仅能同时预约一个实验室:\n 姓名:小明\n 时间: 2023/08/15 15:00\n 实验室: 子良A323\n "
}
```
**If you don't want to deploy additional services, you can use laf to quickly build interfaces, write and send them without deployment**
[laf online address](https://laf.dev/)
Here is a request example:
```ts
import cloud from '@lafjs/cloud';
const db = cloud.database();
export default async function (ctx: FunctionContext) {
const { appointment } = ctx.body;
const { name, time, labname } = JSON.parse(appointment);
const missData = [];
if (!name) missData.push('你的姓名');
if (!time) missData.push('需要预约的时间');
if (!labname) missData.push('实验室名称');
if (missData.length > 0) {
return {
response: `请提供: ${missData.join('、')}`
};
}
const { data: record } = await db
.collection('LabAppointment')
.where({
name,
status: 'unStart'
})
.getOne();
if (record) {
return {
response: `您已经有一个预约记录了,每人仅能同时预约一个实验室:
姓名:${record.name}
时间: ${record.time}
实验室: ${record.labname}
`
};
}
await db.collection('LabAppointment').add({
name,
time,
labname,
status: 'unStart'
});
return {
response: `预约成功。
姓名:${name}
时间: ${time}
实验室: ${labname}
`
};
}
```
## Purpose
With the HTTP module, you can do unlimited extensions, such as manipulating databases, performing internet searches, sending emails, and so on. If you have interesting use cases, feel free to submit a PR to [Examples](/docs/category/examples)
# Special Reply
- Can be added repeatedly (to prevent messy lines in complex arrangements and make it more visually appealing)
- Can be manually inputted
- Can be externally inputted
- Will output results to the client
The special reply module is usually used for replying to specific states. Of course, you can also implement some fancy operations like in Figure 2. The triggering logic is very simple. One way is to write the reply content and trigger it through a trigger. Another way is to not write the reply content and directly trigger it through external input, and reply with the inputted content.
![Figure 1](./imgs/specialreply.png)
![Figure 2](./imgs/specialreply2.png)
---
sidebar_position: 1
---
# Introduction to Triggers
Observant students may notice that there is an external input called "Trigger" in each functional module, and it is of type "any".
Its **core function** is to control the timing of module execution. Let's take the "AI Dialogue" module in the two knowledge base search examples below as an example:
| Figure 1 | Figure 2 |
| ---------------------------- | ---------------------------- |
| ![Demo](./imgs/trigger1.png) | ![Demo](./imgs/trigger2.png) |
In the "Knowledge Base Search" module, since the referenced content always has an output, the "Referenced Content" input of the "AI Dialogue" module will always be assigned a value, regardless of whether the content is found or not. If the trigger is not connected (Figure 2), the "AI Dialogue" module will always be executed after the search is completed.
Sometimes, you may want to perform additional processing when there is an empty search, such as replying with fixed content, calling another GPT with different prompts, or sending an HTTP request... In this case, you need to use a trigger and connect the **search result is not empty** with the **trigger**.
When the search result is empty, the "Knowledge Base Search" module will not output the result of **search result is not empty**, so the trigger of the "AI Dialogue" module will always be empty and it will not be executed.
In summary, by understanding the logic of module execution, you can use triggers flexibly:
**Execute when all external input fields (those with connections) are assigned values**.
# User Questions
- Repeated Addition (to prevent messy lines and improve visual aesthetics in complex workflows)
- No external input
- Flow entry point
- Automatic execution
![](./imgs/chatinput.png)
---
sidebar_position: 2
---
# Global Variables
- Only one can be added
- Manually configured
- Affects other modules
- Can be used for user guidance
You can set some questions before the conversation starts, allowing users to input or select their answers, and inject the results into other modules. Currently, it can only be injected into string type data (represented by a blue circle).
In the example below, two variables are defined: "Target Language" and "Dropdown Test (Ignore)". Users will be asked to fill in the target language before the conversation starts. With user guidance, we can build a simple translation bot. The key of "Target Language" (language) is written into the qualifiers of the "AI Dialogue" module.
![](./imgs/variable.png)
By examining the complete conversation log, we can see that the actual qualifier changes from "Translate my question directly into {{language}}" to "Translate my question directly into English" because {{language}} is replaced by the variable.
![](./imgs/variable2.png)
---
sidebar_position: 1
---
# Introduction to FastGpt
FastGPT is a knowledge-based question-answering system built on top of the LLM language model. It provides out-of-the-box capabilities for data processing, model invocation, and more. Additionally, it offers a visual workflow editor called Flow to enable complex question-answering scenarios!
| | |
| -------------------------- | -------------------------- |
| ![Demo](./imgs/intro1.png) | ![Demo](./imgs/intro2.png) |
| ![Demo](./imgs/intro3.png) | ![Demo](./imgs/intro4.png) |
## FastGPT Capabilities
### 1. AI Customer Service
Train the AI model by importing documents or existing question-answer pairs, allowing it to answer questions based on your documents.
![Ability1](./imgs/ability1.png)
### 2. Automated Data Preprocessing
Provides multiple ways to import data, including manual input, direct segmentation, LLM automatic processing, and CSV, to accommodate precise and fast training scenarios.
![Ability1](./imgs/ability2.png)
### 3. Workflow Orchestration
Design more complex question-answering workflows using the Flow module. For example, querying databases, checking inventory, scheduling laboratory appointments, etc.
![Ability1](./imgs/ability3.png)
### 4. Seamless Integration with OpenAPI
FastGPT's API interface aligns with the official GPT API, allowing you to integrate FastGPT into existing GPT applications by simply modifying the BaseURL and Authorization.
![Ability1](./imgs/ability4.png)
## FastGPT Features
1. Open-source project. FastGPT follows the Apache License 2.0 open-source agreement. You can clone FastGPT from GitHub for further development and distribution. The community edition of FastGPT will retain core functionality, while the commercial edition extends it through APIs without affecting learning usage.
2. Unique QA structure. Designed specifically for customer service question-answering scenarios, the QA structure improves accuracy in large-scale data scenarios.
3. Visual workflow. The Flow module displays the complete process from question input to model output, facilitating debugging and designing complex workflows.
4. Infinite scalability. Extensible via HTTP without modifying FastGPT source code, allowing for quick integration into existing programs.
5. Convenient debugging. Provides various debugging methods, such as search testing, reference modification, and complete conversation preview.
6. Support for multiple models: Supports various LLM models such as GPT, Claude, and Wenxin Yiyuan, and will also support custom vector models in the future.
## Core Knowledge Base Process Diagram
![KBProcess](./imgs/KBProcess.jpg?raw=true 'KBProcess')
# 3分钟在Fastgpt上用上GLM
## 前言
Fast GPT 允许你使用自己的 openai API KEY 来快速的调用 openai 接口,目前集成了 Gpt35, Gpt4 和 embedding. 可构建自己的知识库。但考虑到数据安全的问题,我们并不能将所有的数据都交付给云端大模型。那如何在fastgpt上接入私有化模型呢,本文就以清华的ChatGLM2为例,为各位讲解如何在fastgpt中接入私有化模型。
## ChatGLM2简介
ChatGLM2-6B 是开源中英双语对话模型 ChatGLM-6B 的第二代版本,具体介绍请看项目:https://github.com/THUDM/ChatGLM2-6B
注意,ChatGLM2-6B 权重对学术研究完全开放,在获得官方的书面许可后,亦允许商业使用。本教程只是介绍了一种用法,并不会给予任何授权。
## 推荐配置
依据官方数据,同样是生成 8192 长度,量化等级为FP16要占用12.8GB 显存、INT8为8.1GB显存、INT4为5.1GB显存,量化后会稍微影响性能,但不多。
因此推荐配置如下:
fp16:内存>=16GB,显存>=16GB,硬盘空间>=25GB,启动时使用命令python openai_api.py 16
int8:内存>=16GB,显存>=9GB,硬盘空间>=25GB,启动时选择python openai_api.py 8
int4:内存>=16GB,显存>=6GB,硬盘空间>=25GB,启动时选择python openai_api.py 4
## 环境配置
Python 3.8.10
CUDA 11.8
科学上网环境
## 简单的步骤
1. 根据上面的环境配置配置好环境,具体教程自行GPT;
1. 在命令行输入pip install -r requirments.txt
2. 打开你需要启动的py文件,在代码的第76行配置token,这里的token只是加一层验证,防止接口被人盗用
2. python openai_api.py 16//这里的数字根据上面的配置进行选择
然后等待模型下载,直到模型加载完毕,出现报错先问GPT
上面两个文件在本文档的同目录
启动成功后应该会显示如下地址:
![Alt text](image.png)
这里的http://0.0.0.0:6006就是连接地址
然后现在回到.env.local文件,依照以下方式配置地址:
OPENAI_BASE_URL=http://127.0.0.1:6006/v1
OPENAIKEY=sk-aaabbbcccdddeeefffggghhhiiijjjkkk //这里是你在代码中配置的token
这里的OPENAIKEY可以任意填写
这样就成功接入ChatGLM2了
# 通过 OpenAPI 接入第三方应用
## 1. 获取 API 秘钥
注意复制,关掉了需要新建~
![imgs](./img1.png)
## 2. 组合秘钥
利用刚复制的 API 秘钥加上 AppId 组合成一个新的秘钥,格式为: API 秘钥-AppId,例如:`fastgpt-z51pkjqm9nrk03a1rx2funoy-642adec15f04d67d4613efdb`
## 3. 替换三方应用的变量
OPENAI_API_BASE_URL: https://fastgpt.run/api/openapi (改成自己部署的域名)
OPENAI_API_KEY = 组合秘钥
**[chatgpt next](https://github.com/Yidadaa/ChatGPT-Next-Web) 示例**
![imgs](./chatgptnext.png)
**[chatgpt web](https://github.com/Chanzhaoyu/chatgpt-web) 示例**
![imgs](./chatgptweb.png)
// @ts-check
// Note: type annotations allow type checking and IDEs autocompletion
const lightCodeTheme = require('prism-react-renderer/themes/github');
const darkCodeTheme = require('prism-react-renderer/themes/dracula');
/** @type {import('@docusaurus/types').Config} */
const config = {
title: 'FastGpt',
tagline: 'FastGpt',
favicon: 'img/favicon.ico',
url: 'https://fastgpt.run',
baseUrl: '/',
organizationName: 'labring',
projectName: 'FastGpt',
onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn',
i18n: {
defaultLocale: 'zh-Hans',
locales: ['en', 'zh-Hans']
},
presets: [
[
'classic',
/** @type {import('@docusaurus/preset-classic').Options} */
({
docs: {
sidebarPath: require.resolve('./sidebars.js'),
editUrl: 'https://github.com/labring/FastGPT/blob/main/docSite/'
},
theme: {
customCss: require.resolve('./src/css/custom.css')
}
})
]
],
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
image: 'img/docusaurus-social-card.jpg',
navbar: {
title: 'FastGpt',
logo: {
alt: 'My Logo',
src: 'img/logo.svg'
},
items: [
{
type: 'doc',
docId: 'intro',
position: 'left',
label: 'Docs',
to: '/docs/Intro'
},
{ to: 'https://fastgpt.run', label: 'Start Now', position: 'left' },
{
href: 'https://github.com/labring/FastGPT',
label: 'GitHub',
position: 'right'
},
{
type: 'localeDropdown',
position: 'right'
}
]
},
prism: {
theme: lightCodeTheme,
darkTheme: darkCodeTheme
}
})
};
module.exports = config;
module fastgpt-docs
go 1.21.0
require (
github.com/colinwilson/lotusdocs v0.0.0-20230821033552-c5bcbdd9df80 // indirect
github.com/gohugoio/hugo-mod-bootstrap-scss/v5 v5.20300.20003 // indirect
)
github.com/colinwilson/lotusdocs v0.0.0-20230818024855-49afc59b7165 h1:mAdPDYE2n2gSX8TpXgIZCns5HYz8G3DfXqaY/4hAmfY=
github.com/colinwilson/lotusdocs v0.0.0-20230818024855-49afc59b7165/go.mod h1:9zu2REJDi+zdPRcR5/bRYSUR7gkNF4NQLvV38SEoCP8=
github.com/colinwilson/lotusdocs v0.0.0-20230820063310-51255ddcf986 h1:IZb47oZD5rU3QCqaVfZi4xoMhiVk5JECFOethhMPzEo=
github.com/colinwilson/lotusdocs v0.0.0-20230820063310-51255ddcf986/go.mod h1:9zu2REJDi+zdPRcR5/bRYSUR7gkNF4NQLvV38SEoCP8=
github.com/colinwilson/lotusdocs v0.0.0-20230821033552-c5bcbdd9df80 h1:jKZF8sqr/q34TF0batU4q/qs1VSj22AvVjJlO1y+BSk=
github.com/colinwilson/lotusdocs v0.0.0-20230821033552-c5bcbdd9df80/go.mod h1:9zu2REJDi+zdPRcR5/bRYSUR7gkNF4NQLvV38SEoCP8=
github.com/gohugoio/hugo-mod-bootstrap-scss/v5 v5.20300.20003 h1:pt/JGVD5YYRsVVijOHPZI6YKTUvbR4e0hgV9B0S6rbI=
github.com/gohugoio/hugo-mod-bootstrap-scss/v5 v5.20300.20003/go.mod h1:mvM05r93HiefwoaxQTaYiJxtJAhTebwQtU1Xh/J+Okk=
github.com/gohugoio/hugo-mod-jslibs-dist/popperjs/v2 v2.21100.20000/go.mod h1:mFberT6ZtcchrsDtfvJM7aAH2bDKLdOnruUHl0hlapI=
github.com/twbs/bootstrap v5.3.0+incompatible/go.mod h1:fZTSrkpSf0/HkL0IIJzvVspTt1r9zuf7XlZau8kpcY0=
baseURL = "/"
languageCode = "en-GB"
contentDir = "content"
enableEmoji = true
enableGitInfo = false # N.B. .GitInfo does not currently function with git submodule content directories
defaultContentLanguage = 'zh-cn'
[languages]
[languages.zh-cn]
title = "FastGPT"
languageName = "简体中文"
#contentDir = "content/zh-cn"
weight = 10
[languages.en]
title = "FastGPT Docs"
languageName = "English"
contentDir = "content/en"
weight = 10
disabled = true
[module]
[module.hugoVersion]
extended = true
min = "0.100.0"
[[module.imports]]
path = "github.com/colinwilson/lotusdocs"
disable = false
[[module.imports]]
path = "github.com/gohugoio/hugo-mod-bootstrap-scss/v5"
disable = false
[markup]
defaultMarkdownHandler = "goldmark"
[markup.tableOfContents]
endLevel = 3
startLevel = 1
[markup.goldmark]
[markup.goldmark.renderer]
unsafe = true # https://jdhao.github.io/2019/12/29/hugo_html_not_shown/
# [markup.highlight]
# codeFences = false # disables Hugo's default syntax highlighting
# [markup.goldmark.parser]
# [markup.goldmark.parser.attribute]
# block = true
# title = true
[params]
google_fonts = [
["Inter", "300, 400, 600, 700"],
["Fira Code", "500, 700"]
]
sans_serif_font = "Inter" # Default is System font
secondary_font = "Inter" # Default is System font
mono_font = "Fira Code" # Default is System font
[params.footer]
copyright = "© :YEAR: the FastGPT Authors."
version = false # includes git commit info
[params.social]
github = "labring/FastGPT" # YOUR_GITHUB_ID or YOUR_GITHUB_URL
# twitter = "" # YOUR_TWITTER_ID
# instagram = "colinwilson" # YOUR_INSTAGRAM_ID
# rss = true # show rss icon with link
wechat = "/wechat-fastgpt.webp"
[params.docs] # Parameters for the /docs 'template'
title = "" # default html title for documentation pages/sections
# pathName = "docs" # path name for documentation site | default "docs"
# themeColor = "cyan" # (optional) - Set theme accent colour. Options include: blue (default), green, red, yellow, emerald, cardinal, magenta, cyan
darkMode = true # enable dark mode option? default false
prism = true # enable syntax highlighting via Prism
# gitinfo
ghrepo = "https://github.com/labring/FastGPT" # Git repository URL for your site
editPage = true # enable 'Edit this page' feature - default false
lastMod = false # enable 'Last modified' date on pages - default false
lastModRelative = true # format 'Last modified' time as relative - default true
sidebarIcons = true # enable sidebar icons? default false
breadcrumbs = true # default is true
backToTop = true # enable back-to-top button? default true
# ToC
toc = true # enable table of contents? default is true
tocMobile = true # enable table of contents in mobile view? default is true
scrollSpy = true # enable scrollspy on ToC? default is true
# front matter
descriptions = true # enable front matter descriptions under content title?
titleIcon = true # enable front matter icon title prefix? default is false
# content navigation
navDesc = true # include front matter descriptions in Prev/Next navigation cards
navDescTrunc = 30 # Number of characters by which to truncate the Prev/Next descriptions
listDescTrunc = 100 # Number of characters by which to truncate the list card description
[params.flexsearch] # Parameters for FlexSearch
enabled = true
tokenize = "full"
# optimize = true
# cache = 100
# minQueryChar = 3 # default is 0 (disabled)
# maxResult = 5 # default is 5
# searchSectionsIndex = []
[params.docsearch] # Parameters for DocSearch
# appID = "O2QIOCBDAK" # Algolia Application ID
# apiKey = "fdc60eee76a72a35d739b54521498b77" # Algolia Search-Only API (Public) Key
# indexName = "prod_lotusdocs.dev" # Index Name to perform search on (or set env variable HUGO_PARAM_DOCSEARCH_indexName)
[params.analytics] # Parameters for Analytics (Google, Plausible)
# plausibleURL = "/docs/s" # (or set via env variable HUGO_PARAM_ANALYTICS_plausibleURL)
# plausibleAPI = "/docs/s" # optional - (or set via env variable HUGO_PARAM_ANALYTICS_plausibleAPI)
# plausibleDomain = "lotusdocs.dev" # (or set via env variable HUGO_PARAM_ANALYTICS_plausibleDomain)
[params.feedback]
# enabled = true
# analytics = "plausible"
# positiveEventName = "Positive Feedback"
# negativeEventName = "Negative Feedback"
# positiveFormTitle = "What did you like?"
# negativeFormTitle = "What went wrong?"
# successMsg = "Thank you for helping to improve Lotus Docs' documentation!"
# errorMsg = "Sorry! There was an error while attempting to submit your feedback!"
# positiveForm = [
# ["Accurate", "Accurately describes the feature or option."],
# ["Solved my problem", "Helped me resolve an issue."],
# ["Easy to understand", "Easy to follow and comprehend."],
# ["Something else"]
# ]
# negativeForm = [
# ["Inaccurate", "Doesn't accurately describe the feature or option."],
# ["Couldn't find what I was looking for", "Missing important information."],
# ["Hard to understand", "Too complicated or unclear."],
# ["Code sample errors", "One or more code samples are incorrect."],
# ["Something else"]
# ]
[menu]
[[menu.primary]]
name = "Docs"
url = "docs/"
identifier = "docs"
weight = 10
# [[menu.primary]]
# name = "Showcase"
# url = "/showcase"
# identifier = "showcase"
# weight = 20
# [[menu.primary]]
# name = "Community"
# url = "https://github.com/colinwilson/lotusdocs/discussions"
# identifier = "community"
# weight = 30
{
"theme.ErrorPageContent.title": {
"message": "页面已崩溃。",
"description": "The title of the fallback page when the page crashed"
},
"theme.ErrorPageContent.tryAgain": {
"message": "重试",
"description": "The label of the button to try again rendering when the React error boundary captures an error"
},
"theme.NotFound.title": {
"message": "找不到页面",
"description": "The title of the 404 page"
},
"theme.NotFound.p1": {
"message": "我们找不到您要找的页面。",
"description": "The first paragraph of the 404 page"
},
"theme.NotFound.p2": {
"message": "请联系原始链接来源网站的所有者,并告知他们链接已损坏。",
"description": "The 2nd paragraph of the 404 page"
},
"theme.AnnouncementBar.closeButtonAriaLabel": {
"message": "关闭",
"description": "The ARIA label for close button of announcement bar"
},
"theme.BackToTopButton.buttonAriaLabel": {
"message": "回到顶部",
"description": "The ARIA label for the back to top button"
},
"theme.blog.paginator.navAriaLabel": {
"message": "博文列表分页导航",
"description": "The ARIA label for the blog pagination"
},
"theme.blog.paginator.newerEntries": {
"message": "较新的博文",
"description": "The label used to navigate to the newer blog posts page (previous page)"
},
"theme.blog.paginator.olderEntries": {
"message": "较旧的博文",
"description": "The label used to navigate to the older blog posts page (next page)"
},
"theme.blog.archive.title": {
"message": "历史博文",
"description": "The page & hero title of the blog archive page"
},
"theme.blog.archive.description": {
"message": "历史博文",
"description": "The page & hero description of the blog archive page"
},
"theme.blog.post.readingTime.plurals": {
"message": "{readingTime} 分钟阅读",
"description": "Pluralized label for \"{readingTime} min read\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.blog.post.readMoreLabel": {
"message": "阅读 {title} 的全文",
"description": "The ARIA label for the link to full blog posts from excerpts"
},
"theme.blog.post.readMore": {
"message": "阅读更多",
"description": "The label used in blog post item excerpts to link to full blog posts"
},
"theme.blog.post.paginator.navAriaLabel": {
"message": "博文分页导航",
"description": "The ARIA label for the blog posts pagination"
},
"theme.blog.post.paginator.newerPost": {
"message": "较新一篇",
"description": "The blog post button label to navigate to the newer/previous post"
},
"theme.blog.post.paginator.olderPost": {
"message": "较旧一篇",
"description": "The blog post button label to navigate to the older/next post"
},
"theme.blog.post.plurals": {
"message": "{count} 篇博文",
"description": "Pluralized label for \"{count} posts\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.blog.tagTitle": {
"message": "{nPosts} 含有标签「{tagName}」",
"description": "The title of the page for a blog tag"
},
"theme.tags.tagsPageLink": {
"message": "查看所有标签",
"description": "The label of the link targeting the tag list page"
},
"theme.colorToggle.ariaLabel": {
"message": "切换浅色/暗黑模式(当前为{mode})",
"description": "The ARIA label for the navbar color mode toggle"
},
"theme.colorToggle.ariaLabel.mode.dark": {
"message": "暗黑模式",
"description": "The name for the dark color mode"
},
"theme.colorToggle.ariaLabel.mode.light": {
"message": "浅色模式",
"description": "The name for the light color mode"
},
"theme.docs.breadcrumbs.home": {
"message": "主页面",
"description": "The ARIA label for the home page in the breadcrumbs"
},
"theme.docs.breadcrumbs.navAriaLabel": {
"message": "页面路径",
"description": "The ARIA label for the breadcrumbs"
},
"theme.docs.DocCard.categoryDescription": {
"message": "{count} 个项目",
"description": "The default description for a category card in the generated index about how many items this category includes"
},
"theme.docs.paginator.navAriaLabel": {
"message": "文档分页导航",
"description": "The ARIA label for the docs pagination"
},
"theme.docs.paginator.previous": {
"message": "上一页",
"description": "The label used to navigate to the previous doc"
},
"theme.docs.paginator.next": {
"message": "下一页",
"description": "The label used to navigate to the next doc"
},
"theme.docs.tagDocListPageTitle.nDocsTagged": {
"message": "{count} 篇文档带有标签",
"description": "Pluralized label for \"{count} docs tagged\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.docs.tagDocListPageTitle": {
"message": "{nDocsTagged}「{tagName}」",
"description": "The title of the page for a docs tag"
},
"theme.docs.versionBadge.label": {
"message": "版本:{versionLabel}"
},
"theme.docs.versions.unreleasedVersionLabel": {
"message": "此为 {siteTitle} {versionLabel} 版尚未发行的文档。",
"description": "The label used to tell the user that he's browsing an unreleased doc version"
},
"theme.docs.versions.unmaintainedVersionLabel": {
"message": "此为 {siteTitle} {versionLabel} 版的文档,现已不再积极维护。",
"description": "The label used to tell the user that he's browsing an unmaintained doc version"
},
"theme.docs.versions.latestVersionSuggestionLabel": {
"message": "最新的文档请参阅 {latestVersionLink} ({versionLabel})。",
"description": "The label used to tell the user to check the latest version"
},
"theme.docs.versions.latestVersionLinkLabel": {
"message": "最新版本",
"description": "The label used for the latest version suggestion link label"
},
"theme.common.editThisPage": {
"message": "编辑此页",
"description": "The link label to edit the current page"
},
"theme.common.headingLinkTitle": {
"message": "标题的直接链接",
"description": "Title for link to heading"
},
"theme.lastUpdated.atDate": {
"message": "于 {date} ",
"description": "The words used to describe on which date a page has been last updated"
},
"theme.lastUpdated.byUser": {
"message": "由 {user} ",
"description": "The words used to describe by who the page has been last updated"
},
"theme.lastUpdated.lastUpdatedAtBy": {
"message": "最后{byUser}{atDate}更新",
"description": "The sentence used to display when a page has been last updated, and by who"
},
"theme.navbar.mobileVersionsDropdown.label": {
"message": "选择版本",
"description": "The label for the navbar versions dropdown on mobile view"
},
"theme.common.skipToMainContent": {
"message": "跳到主要内容",
"description": "The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation"
},
"theme.tags.tagsListLabel": {
"message": "标签:",
"description": "The label alongside a tag list"
},
"theme.blog.sidebar.navAriaLabel": {
"message": "最近博文导航",
"description": "The ARIA label for recent posts in the blog sidebar"
},
"theme.CodeBlock.copied": {
"message": "复制成功",
"description": "The copied button label on code blocks"
},
"theme.CodeBlock.copyButtonAriaLabel": {
"message": "复制代码到剪贴板",
"description": "The ARIA label for copy code blocks button"
},
"theme.CodeBlock.copy": {
"message": "复制",
"description": "The copy button label on code blocks"
},
"theme.CodeBlock.wordWrapToggle": {
"message": "切换自动换行",
"description": "The title attribute for toggle word wrapping button of code block lines"
},
"theme.DocSidebarItem.toggleCollapsedCategoryAriaLabel": {
"message": "打开/收起侧边栏菜单「{label}」",
"description": "The ARIA label to toggle the collapsible sidebar category"
},
"theme.navbar.mobileLanguageDropdown.label": {
"message": "选择语言",
"description": "The label for the mobile language switcher dropdown"
},
"theme.TOCCollapsible.toggleButtonLabel": {
"message": "本页总览",
"description": "The label used by the button on the collapsible TOC component"
},
"theme.docs.sidebar.collapseButtonTitle": {
"message": "收起侧边栏",
"description": "The title attribute for collapse button of doc sidebar"
},
"theme.docs.sidebar.collapseButtonAriaLabel": {
"message": "收起侧边栏",
"description": "The title attribute for collapse button of doc sidebar"
},
"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel": {
"message": "← 回到主菜单",
"description": "The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)"
},
"theme.docs.sidebar.expandButtonTitle": {
"message": "展开侧边栏",
"description": "The ARIA label and title attribute for expand button of doc sidebar"
},
"theme.docs.sidebar.expandButtonAriaLabel": {
"message": "展开侧边栏",
"description": "The ARIA label and title attribute for expand button of doc sidebar"
},
"Powerful": {
"message": "强大",
"description": "homepage powerful"
},
"The cloud services can be easily found and acquired in the application marketplace, offering simplicity and power.": {
"message": "通过应用商店来灵活满足各类用户的需求,形成强大的应用生态",
"description": "homepage flexible intro"
},
"Kernel Arch": {
"message": "以 kubernetes 为云内核架构"
},
"Cloud Driver": {
"message": "云驱动"
},
"Cloud Kernel": {
"message": "云内核"
},
"Distributed Applications": {
"message": "分布式应用程序"
},
"Used By": {
"message": "客户列表"
},
"theme.SearchBar.seeAll": {
"message": "查看全部 {count} 个结果"
},
"theme.SearchBar.label": {
"message": "搜索",
"description": "The ARIA label and placeholder for search button"
},
"theme.SearchPage.documentsFound.plurals": {
"message": "找到 {count} 份文件",
"description": "Pluralized label for \"{count} documents found\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
},
"theme.SearchPage.existingResultsTitle": {
"message": "「{query}」的搜索结果",
"description": "The search page title for non-empty query"
},
"theme.SearchPage.emptyResultsTitle": {
"message": "在文档中搜索",
"description": "The search page title for empty query"
},
"theme.SearchPage.inputPlaceholder": {
"message": "在此输入搜索字词",
"description": "The placeholder for search page input"
},
"theme.SearchPage.inputLabel": {
"message": "搜索",
"description": "The ARIA label for search page input"
},
"theme.SearchPage.algoliaLabel": {
"message": "通过 Algolia 搜索",
"description": "The ARIA label for Algolia mention"
},
"theme.SearchPage.noResultsText": {
"message": "未找到任何结果",
"description": "The paragraph for empty search result"
},
"theme.SearchPage.fetchingNewResults": {
"message": "正在获取新的搜索结果...",
"description": "The paragraph for fetching new search results"
},
"Docs": {
"message": "Doc"
},
"Contact": {
"message": "联系我们"
},
"theme.admonition.note": {
"message": "备注",
"description": "The default label used for the Note admonition (:::note)"
},
"theme.admonition.tip": {
"message": "提示",
"description": "The default label used for the Tip admonition (:::tip)"
},
"theme.admonition.danger": {
"message": "危险",
"description": "The default label used for the Danger admonition (:::danger)"
},
"theme.admonition.info": {
"message": "信息",
"description": "The default label used for the Info admonition (:::info)"
},
"theme.admonition.caution": {
"message": "警告",
"description": "The default label used for the Caution admonition (:::caution)"
},
"theme.docs.sidebar.closeSidebarButtonAriaLabel": {
"message": "Close navigation bar",
"description": "The ARIA label for close button of mobile sidebar"
},
"theme.docs.sidebar.toggleSidebarButtonAriaLabel": {
"message": "Toggle navigation bar",
"description": "The ARIA label for hamburger menu button of mobile navigation"
},
"theme.SearchModal.searchBox.resetButtonTitle": {
"message": "清除查询",
"description": "The label and ARIA label for search box reset button"
},
"theme.SearchModal.searchBox.cancelButtonText": {
"message": "取消",
"description": "The label and ARIA label for search box cancel button"
},
"theme.SearchModal.startScreen.recentSearchesTitle": {
"message": "最近搜索",
"description": "The title for recent searches"
},
"theme.SearchModal.startScreen.noRecentSearchesText": {
"message": "没有最近搜索",
"description": "The text when no recent searches"
},
"theme.SearchModal.startScreen.saveRecentSearchButtonTitle": {
"message": "保存这个搜索",
"description": "The label for save recent search button"
},
"theme.SearchModal.startScreen.removeRecentSearchButtonTitle": {
"message": "从历史记录中删除这个搜索",
"description": "The label for remove recent search button"
},
"theme.SearchModal.startScreen.favoriteSearchesTitle": {
"message": "收藏",
"description": "The title for favorite searches"
},
"theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": {
"message": "从收藏列表中删除这个搜索",
"description": "The label for remove favorite search button"
},
"theme.SearchModal.errorScreen.titleText": {
"message": "无法获取结果",
"description": "The title for error screen of search modal"
},
"theme.SearchModal.errorScreen.helpText": {
"message": "你可能需要检查网络连接。",
"description": "The help text for error screen of search modal"
},
"theme.SearchModal.footer.selectText": {
"message": "选中",
"description": "The explanatory text of the action for the enter key"
},
"theme.SearchModal.footer.selectKeyAriaLabel": {
"message": "Enter 键",
"description": "The ARIA label for the Enter key button that makes the selection"
},
"theme.SearchModal.footer.navigateText": {
"message": "导航",
"description": "The explanatory text of the action for the Arrow up and Arrow down key"
},
"theme.SearchModal.footer.navigateUpKeyAriaLabel": {
"message": "向上键",
"description": "The ARIA label for the Arrow up key button that makes the navigation"
},
"theme.SearchModal.footer.navigateDownKeyAriaLabel": {
"message": "向下键",
"description": "The ARIA label for the Arrow down key button that makes the navigation"
},
"theme.SearchModal.footer.closeText": {
"message": "关闭",
"description": "The explanatory text of the action for Escape key"
},
"theme.SearchModal.footer.closeKeyAriaLabel": {
"message": "Esc 键",
"description": "The ARIA label for the Escape key button that close the modal"
},
"theme.SearchModal.footer.searchByText": {
"message": "搜索提供",
"description": "The text explain that the search is making by Algolia"
},
"theme.SearchModal.noResultsScreen.noResultsText": {
"message": "没有结果:",
"description": "The text explains that there are no results for the following search"
},
"theme.SearchModal.noResultsScreen.suggestedQueryText": {
"message": "试试搜索",
"description": "The text for the suggested query when no results are found for the following search"
},
"theme.SearchModal.noResultsScreen.reportMissingResultsText": {
"message": "认为这个查询应该有结果?",
"description": "The text for the question where the user thinks there are missing results"
},
"theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": {
"message": "请告知我们。",
"description": "The text for the link to report missing results"
},
"theme.SearchModal.placeholder": {
"message": "搜索文档",
"description": "The placeholder of the input of the DocSearch pop-up modal"
},
"theme.tags.tagsPageTitle": {
"message": "标签",
"description": "The title of the tag list page"
},
"Features": {
"message": "特性"
},
"Copy": {
"message": "复制"
},
"START NOW": {
"message": "在线使用"
},
"CONTACT US NOW": {
"message": "联系我们"
}
}
{
"sidebar.docSidebar.intro": {
"message": "介绍"
},
"sidebar.docSidebar.category.Develop": {
"message": "开发"
},
"sidebar.docSidebar.category.Proxy": {
"message": "Proxy 方案"
},
"sidebar.docSidebar.category.Data Config": {
"message": "Config 配置"
},
"sidebar.docSidebar.category.Deploy": {
"message": "部署"
},
"sidebar.docSidebar.category.Version Updating": {
"message": "版本更新"
},
"sidebar.docSidebar.category.Datasets": {
"message": "知识库实践"
},
"sidebar.docSidebar.category.Flow Modules": {
"message": "高级编排"
},
"sidebar.docSidebar.category.Modules Intro": {
"message": "模块介绍"
},
"sidebar.docSidebar.category.Examples": {
"message": "例子"
},
"sidebar.docSidebar.category.Other": {
"message": "其他"
}
}
# 利用 FastGpt 打造高质量 AI 知识库
## 前言
自从去年 12 月 chatgpt 发布后,带动了新的一轮应用交互革命。尤其是 gpt35 接口全面放开后,LLM 应用雨后春笋般快速涌现,但因为 gpt 的可控性、随机性和合规性等问题,很多应用场景都没法落地。
3 月时候,在 twitter 上刷到一个老哥使用 gpt 训练自己的博客记录,并且成本非常低(比起 FT)。他给出了一个完整的流程图:
![向量搜索 GPT 流程图](imgs/1.png)
看到这个推文后,我灵机一动,应用场景就十分清晰了。直接上手开干,在经过不到 1 个月时间,FastGpt 在原来多助手管理基础上,加入了向量搜索。于是便有了最早的一期视频:https://www.bilibili.com/video/BV1Wo4y1p7i1/?vd_source=92041a1a395f852f9d89158eaa3f61b4
3 个月过去了,FastGpt 延续着早期的思路去完善和扩展,目前在向量搜索 + LLM 线性问答方面的功能基本上完成了。不过我们始终没有出一期关于如何构建知识库的教程,趁着 V4 在开发中,我们计划介绍一期《如何在 FastGpt 上构建高质量知识库》,以便大家更好的使用。
## FastGpt 知识库完整逻辑
在正式构建知识库前,我们先来了解下 FastGpt 是如何进行知识库检索的。首先了解几个基本概念:
1. 向量:将人类直观的语言(文字、图片、视频等)转成计算机可识别的语言(数组)。
2. 向量相似度:两个向量之间可以进行计算,得到一个相似度,即代表:两个语言相似的程度。
3. 语言大模型的一些特点:上下文理解、总结和推理。
结合上述 3 个概念,便有了 “向量搜索 + 大模型 = 知识库问答” 的公式。下图是 FastGpt V3 中知识库问答功能的完整逻辑:
![向量搜索 GPT 流程图](imgs/2.png)
与大部分其他知识库问答产品不一样的是, FastGpt 采用了 QA 问答对进行存储,而不是仅进行 chunk(文本分块)处理。目的是为了减少向量化内容的长度,让向量能更好的表达文本的含义,从而提高搜索精准度。
此外 FastGpt 还提供了搜索测试和对话测试两种途径对数据进行调整,从而方便用户调整自己的数据。根据上述流程和方式,我们以构建一个 FastGpt 常见问题机器人为例,展示如何构建一个高质量的 AI 知识库。
## 构建知识库应用
首先,先创建一个 FastGpt 常见问题知识库
![创建知识库应用](imgs/3.png)
### 通过 QA 拆分,获取基础知识
我们先直接把 FastGpt Git 上一些已有文档,进行 QA 拆分,从而获取一些 FastGpt 基础的知识。下面是 README 例子。
![QA 拆分示意图](imgs/4.png)
![](imgs/5.png)
### 修正 QA
通过 README 我们一共得到了 11 组数据,整体的质量还是不错的,图片和链接都提取出来了。不过最后一个知识点出现了一些截断,我们需要手动的修正一下。
此外,我们观察到第一列第三个知识点。这个知识点是介绍了 FastGpt 一些资源链接,但是 QA 拆分将答案放置在了 A 中,但通常来说用户的提问并不会直接问“有哪些链接”,通常会问:“部署教程”,“问题文档”之类的。因此,我们需要将这个知识点进行简单的一个处理,如下图:
![手动修改知识库数据](imgs/6.png)
我们先来创建一个应用,看看效果如何。 首先需要去创建一个应用,并且在知识库中关联相关的知识库。另外还需要在配置页的提示词中,告诉 GPT:“知识库的范围”。
![](imgs/7.png)
![README QA 拆分后效果](imgs/8.png)
整体的效果还是不错的,链接和对应的图片都可以顺利的展示。
### 录入社区常见问题
接着,我们再把 FastGPT 常见问题的文档导入,由于平时整理不当,我们只能手动的录入对应的问答。
![手动录入知识库结果](imgs/9.png)
导入结果如上图。可以看到,我们均采用的是问答对的格式,而不是粗略的直接导入。目的就是为了模拟用户问题,进一步的提高向量搜索的匹配效果。可以为同一个问题设置多种问法,效果更佳。
FastGpt 还提供了 openapi 功能,你可以在本地对特殊格式的文件进行处理后,再上传到 FastGpt,具体可以参考:[FastGpt Api Docs](https://kjqvjse66l.feishu.cn/docx/DmLedTWtUoNGX8xui9ocdUEjnNh)
## 知识库微调和参数调整
FastGpt 提供了搜索测试和对话测试两种途径对知识库进行微调,我们先来使用搜索测试对知识库进行调整。我们建议你提前收集一些用户问题进行测试,根据预期效果进行跳转。可以先进行搜索测试调整,判断知识点是否合理。
### 搜索测试
![搜索测试作用](imgs/10.png)
你可能会遇到下面这种情况,由于“知识库”这个关键词导致一些无关内容的相似度也被搜索进去,此时就需要给第四条记录也增加一个“知识库”关键词,从而去提高它的相似度。
![搜索测试结果](imgs/11.png)
![优化后的搜索测试结果](imgs/12.png)
### 提示词设置
提示词的作用是引导模型对话的方向。在设置提示词时,遵守 2 个原则:
1. 告诉 Gpt 回答什么方面内容。
2. 给知识库一个基本描述,从而让 Gpt 更好的判断用户的问题是否属于知识库范围。
![提示词设置](imgs/13.png)
### 更好的限定模型聊天范围
首先,你可以通过调整知识库搜索时的相似度和最大搜索数量,实现从知识库层面限制聊天范围。通常我们可以设置相似度为 0.82,并设置空搜索回复内容。这意味着,如果用户的问题无法在知识库中匹配时,会直接回复预设的内容。
![搜索参数设置](imgs/14.png)
![空搜索控制效果](imgs/15.png)
由于 openai 向量模型并不是针对中文,所以当问题中有一些知识库内容的关键词时,相似度
会较高,此时无法从知识库层面进行限定。需要通过限定词进行调整,例如:
> 我的问题如果不是关于 FastGpt 的,请直接回复:“我不确定”。你仅需要回答知识库中的内容,不在其中的内容,不需要回答。
效果如下:
![限定词效果](imgs/16.png)
当然,gpt35 在一定情况下依然是不可控的。
### 通过对话调整知识库
与搜索测试类似,你可以直接在对话页里,点击“引用”,来随时修改知识库内容。
![查看答案引用](imgs/17.png)
## 总结
1. 向量搜索是一种可以比较文本相似度的技术。
2. 大模型具有总结和推理能力,可以从给定的文本中回答问题。
3. 最有效的知识库构建方式是 QA 和手动构建。
4. Q 的长度不宜过长。
5. 需要调整提示词,来引导模型回答知识库内容。
6. 可以通过调整搜索相似度、最大搜索数量和限定词来控制模型回复的范围。
---
sidebar_position: 1
---
# 默认配置文件
```json
{
"FeConfig": {
"show_emptyChat": true,
"show_register": false,
"show_appStore": false,
"show_userDetail": false,
"show_git": true,
"systemTitle": "FastGPT",
"authorText": "Made by FastGPT Team.",
"gitLoginKey": "",
"scripts": []
},
"SystemParams": {
"gitLoginSecret": "",
"vectorMaxProcess": 15,
"qaMaxProcess": 15,
"pgIvfflatProbe": 20
},
"plugins": {},
"ChatModels": [
{
"model": "gpt-3.5-turbo",
"name": "GPT35-4k",
"contextMaxToken": 4000,
"quoteMaxToken": 2000,
"maxTemperature": 1.2,
"price": 0,
"defaultSystem": ""
},
{
"model": "gpt-3.5-turbo-16k",
"name": "GPT35-16k",
"contextMaxToken": 16000,
"quoteMaxToken": 8000,
"maxTemperature": 1.2,
"price": 0,
"defaultSystem": ""
},
{
"model": "gpt-4",
"name": "GPT4-8k",
"contextMaxToken": 8000,
"quoteMaxToken": 4000,
"maxTemperature": 1.2,
"price": 0,
"defaultSystem": ""
}
],
"QAModels": [
{
"model": "gpt-3.5-turbo-16k",
"name": "GPT35-16k",
"maxToken": 16000,
"price": 0
}
],
"VectorModels": [
{
"model": "text-embedding-ada-002",
"name": "Embedding-2",
"price": 0
}
]
}
```
---
sidebar_position: 2
---
# 快速介绍
由于环境变量不利于配置复杂的内容,新版 FastGPT 采用了 ConfigMap 的形式挂载配置文件,你可以在 client/data/config.json 看到默认的配置文件。可以参考 [docker-compose 部署](/docs/develop/deploy/docker) 来挂载配置文件。
开发环境下,你需要复制一份 config.json 成 config.local.json 文件才会生效。
这个配置文件中包含了前端页面定制、系统级参数、AI 对话的模型等……
**注意:下面的配置介绍仅是局部介绍,你需要完整挂载整个 config.jso ,不能仅挂载一部分。你可以直接在给的 config.json 基础上根据下面的介绍进行修改。**
## 基础字段粗略说明
这里会介绍一些基础的配置字段。
```json
// 这个配置会控制前端的一些样式
"FeConfig": {
"show_emptyChat": true, // 对话页面,空内容时,是否展示介绍页
"show_register": false, // 是否展示注册按键(包括忘记密码,注册账号和三方登录)
"show_appStore": false, // 是否展示应用市场(不过目前权限还没做好,放开也没用)
"show_userDetail": false, // 是否展示用户详情(账号余额、OpenAI 绑定)
"show_git": true, // 是否展示 Git
"systemTitle": "FastGPT", // 系统的 title
"authorText": "Made by FastGPT Team.", // 签名
"gitLoginKey": "" // Git 登录凭证
}
```
```json
// 这个配置文件是系统级参数
"SystemParams": {
"gitLoginSecret": "", // Git 登录凭证
"vectorMaxProcess": 15, // 向量生成最大进程,结合数据库性能和 key 来设置
"qaMaxProcess": 15, // QA 生成最大进程,结合数据库性能和 key 来设置
"pgIvfflatProbe": 20 // pg vector 搜索探针。没有设置索引前可忽略,通常 50w 组以上才需要设置。
},
```
# docker-compose 快速部署
## 一、预先准备
### 1. 准备好代理环境(国外服务器可忽略)
确保可访问到 OpenAI,方案可参考:[sealos nginx 中转](../proxy/sealos)
### 2. OneAPI (可选,需要多模型和 key 轮询时使用)
推荐使用 [one-api](https://github.com/songquanpeng/one-api) 项目来管理 key 池,兼容 openai 、微软和国内主流模型等。
部署可以看该项目的 [README.md](https://github.com/songquanpeng/one-api),也可以看 [在 Sealos 1 分钟部署 one-api](../oneapi)
## 二、安装 docker 和 docker-compose
这个不同系统略有区别,百度安装下。验证安装成功后进行下一步。下面给出 centos 一个例子:
```bash
# 安装docker
curl -L https://get.daocloud.io/docker | sh
sudo systemctl start docker
# 安装 docker-compose
curl -L https://github.com/docker/compose/releases/download/1.23.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# 验证安装
docker -v
docker-compose -v
```
## 三、创建 docker-compose.yml 文件
随便找一个目录,创建一个 `docker-compose.yml` 文件,粘贴下面的内容。只需要改 fastgpt 容器的 3 个参数即可启动。
```yml
# 非 host 版本, 不使用本机代理
version: '3.3'
services:
pg:
image: ankane/pgvector:v0.4.2 # docker
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/pgvector:v0.4.2 # 阿里云
container_name: pg
restart: always
ports: # 生产环境建议不要暴露
- 5432:5432
networks:
- fastgpt
environment:
# 这里的配置只有首次运行生效。修改后,重启镜像是不会生效的。需要把持久化数据删除再重启,才有效果
- POSTGRES_USER=username
- POSTGRES_PASSWORD=password
- POSTGRES_DB=postgres
volumes:
- ./pg/data:/var/lib/postgresql/data
mongo:
image: mongo:5.0.18
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/mongo:5.0.18 # 阿里云
container_name: mongo
restart: always
ports: # 生产环境建议不要暴露
- 27017:27017
networks:
- fastgpt
environment:
# 这里的配置只有首次运行生效。修改后,重启镜像是不会生效的。需要把持久化数据删除再重启,才有效果
- MONGO_INITDB_ROOT_USERNAME=username
- MONGO_INITDB_ROOT_PASSWORD=password
volumes:
- ./mongo/data:/data/db
fastgpt:
container_name: fastgpt
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:latest # 阿里云
image: ghcr.io/labring/fastgpt:latest # github
ports:
- 3000:3000
networks:
- fastgpt
depends_on:
- mongo
- pg
restart: always
environment:
# root 密码,用户名为: root
- DEFAULT_ROOT_PSW=1234
# 中转地址,如果是用官方号,不需要管
- OPENAI_BASE_URL=https://api.openai.com/v1
- CHAT_API_KEY=sk-xxxx
- DB_MAX_LINK=5 # database max link
- TOKEN_KEY=any
- ROOT_KEY=root_key
# mongo 配置,不需要改. 如果连不上,可能需要去掉 ?authSource=admin
- MONGODB_URI=mongodb://username:password@mongo:27017/fastgpt?authSource=admin
# pg配置. 不需要改
- PG_URL=postgresql://username:password@pg:5432/postgres
networks:
fastgpt:
```
```yml
# host 版本, 不推荐。
version: '3.3'
services:
pg:
image: ankane/pgvector:v0.4.2 # dockerhub
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/pgvector:v0.4.2 # 阿里云
container_name: pg
restart: always
ports: # 生产环境建议不要暴露
- 5432:5432
environment:
# 这里的配置只有首次运行生效。修改后,重启镜像是不会生效的。需要把持久化数据删除再重启,才有效果
- POSTGRES_USER=username
- POSTGRES_PASSWORD=password
- POSTGRES_DB=postgres
volumes:
- ./pg/data:/var/lib/postgresql/data
mongo:
image: mongo:5.0.18
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/mongo:5.0.18 # 阿里云
container_name: mongo
restart: always
ports: # 生产环境建议不要暴露
- 27017:27017
environment:
# 这里的配置只有首次运行生效。修改后,重启镜像是不会生效的。需要把持久化数据删除再重启,才有效果
- MONGO_INITDB_ROOT_USERNAME=username
- MONGO_INITDB_ROOT_PASSWORD=password
volumes:
- ./mongo/data:/data/db
- ./mongo/logs:/var/log/mongodb
fastgpt:
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:latest # 阿里云
image: ghcr.io/labring/fastgpt:latest # git
network_mode: host
restart: always
container_name: fastgpt
environment:
# root 密码,用户名为: root
- DEFAULT_ROOT_PSW=1234
# 中转地址,如果是用官方号,不需要管
- OPENAI_BASE_URL=https://api.openai.com/v1
- CHAT_API_KEY=sk-xxxx
- DB_MAX_LINK=5 # database max link
# token加密凭证(随便填,作为登录凭证)
- TOKEN_KEY=any
# root key, 最高权限,可以内部接口互相调用
- ROOT_KEY=root_key
# mongo 配置,不需要改. 如果连不上,可能需要去掉 ?authSource=admin
- MONGODB_URI=mongodb://username:password@0.0.0.0:27017/fastgpt?authSource=admin
# pg配置. 不需要改
- PG_URL=postgresql://username:password@0.0.0.0:5432/postgres
```
## 四、运行 docker-compose
```bash
# 在 docker-compose.yml 同级目录下执行
docker-compose up -d
```
## 五、访问
如果需要域名访问,自行安装 Nginx。目前可以通过: `ip:3000` 直接访问(注意防火墙)。登录用户名为 root,密码为刚刚环境变量里设置的 `DEFAULT_ROOT_PSW`
## 一些问题
### 1. 如何更新?
执行 `docker-compose up -d` 会自动拉取最新镜像,一般情况下不需要执行额外操作。
### 2. 挂载配置文件
在和 `docker-compose.yml` 同级目录,创建一个 `config.json` 文件,内容如下:
```json
{
"FeConfig": {
"show_emptyChat": true,
"show_register": false,
"show_appStore": false,
"show_userDetail": false,
"show_git": true,
"systemTitle": "FastGPT",
"authorText": "Made by FastGPT Team.",
"gitLoginKey": "",
"scripts": []
},
"SystemParams": {
"gitLoginSecret": "",
"vectorMaxProcess": 15,
"qaMaxProcess": 15,
"pgIvfflatProbe": 20
},
"plugins": {},
"ChatModels": [
{
"model": "gpt-3.5-turbo",
"name": "GPT35-4k",
"contextMaxToken": 4000,
"quoteMaxToken": 2000,
"maxTemperature": 1.2,
"price": 0,
"defaultSystem": ""
},
{
"model": "gpt-3.5-turbo-16k",
"name": "GPT35-16k",
"contextMaxToken": 16000,
"quoteMaxToken": 8000,
"maxTemperature": 1.2,
"price": 0,
"defaultSystem": ""
},
{
"model": "gpt-4",
"name": "GPT4-8k",
"contextMaxToken": 8000,
"quoteMaxToken": 4000,
"maxTemperature": 1.2,
"price": 0,
"defaultSystem": ""
}
],
"QAModels": [
{
"model": "gpt-3.5-turbo-16k",
"name": "GPT35-16k",
"maxToken": 16000,
"price": 0
}
],
"VectorModels": [
{
"model": "text-embedding-ada-002",
"name": "Embedding-2",
"price": 0
}
]
}
```
修改 docker-compose.yml 中 fastgpt 容器内容,增加挂载。具体配置可参考 [config 配置说明](/docs/category/data-config)
```yml
fastgpt:
container_name: fastgpt
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:latest # 阿里云
ports:
- 3000:3000
networks:
- fastgpt
depends_on:
- mongo
- pg
restart: always
environment:
......
# root 密码,用户名为: root
- DEFAULT_ROOT_PSW=1234
......
volumes:
- ./config.json:/app/data/config.json
```
# Mac 上部署可能遇到的问题(旧版)
### 前置条件
1、可以 curl api.openai.com
2、有 openai key
3、有邮箱 MAILE_CODE
4、有 docker
```
docker -v
```
5、有 pnpm ,可以使用`brew install pnpm`安装
6、需要创建一个放置 pg 和 mongo 数据的文件夹,这里创建在`~/fastgpt`目录中,里面有`pg` 和`mongo `两个文件夹
```
➜ fastgpt pwd
/Users/jie/fastgpt
➜ fastgpt ls
mongo pg
```
### docker 部署方式
这种方式主要是为了方便调试,可以使用`pnpm dev ` 运行 fastgpt 项目
**1、.env.local 文件**
```
# proxy
AXIOS_PROXY_HOST=127.0.0.1
AXIOS_PROXY_PORT_FAST=7890
AXIOS_PROXY_PORT_NORMAL=7890
# email
MY_MAIL= {Your Mail}
MAILE_CODE={Yoir Mail code}
# ali ems
aliAccessKeyId=xxx
aliAccessKeySecret=xxx
aliSignName=xxx
aliTemplateCode=SMS_xxx
# token
TOKEN_KEY=sswada
# 使用 oneapi
ONEAPI_URL=[https://api.xyz.com/v1](https://xxxxx.cloud.sealos.io/v1)
ONEAPI_KEY=sk-xxxxxx
# openai
OPENAIKEY=sk-xxx # 对话用的key
OPENAI_TRAINING_KEY=sk-xxx # 训练用的key
# db
MONGODB_URI=mongodb://username:password@0.0.0.0:27017/test?authSource=admin
PG_HOST=0.0.0.0
PG_PORT=8100
PG_USER=xxx
PG_PASSWORD=xxx
PG_DB_NAME=fastgpt
```
**2、部署 mongo**
```
docker run --name mongo -p 27017:27017 -e MONGO_INITDB_ROOT_USERNAME=username -e MONGO_INITDB_ROOT_PASSWORD=password -v ~/fastgpt/mongo/data:/data/db -d mongo:4.0.1
```
**3、部署 pgsql**
```
docker run -it --name pg -e "POSTGRES_DB=fastgpt" -e "POSTGRES_PASSWORD=xxx" -e POSTGRES_USER=xxx -p 8100:5432 -v ~/fastgpt/pg/data:/var/lib/postgresql/data -d octoberlan/pgvector:v0.4.1
```
进 pgsql 容器运行
```
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
CREATE EXTENSION IF NOT EXISTS vector;
-- init table
CREATE TABLE IF NOT EXISTS modeldata (
id BIGSERIAL PRIMARY KEY,
vector VECTOR(1536) NOT NULL,
user_id VARCHAR(50) NOT NULL,
kb_id VARCHAR(50) NOT NULL,
source VARCHAR(100),
q TEXT NOT NULL,
a TEXT NOT NULL
);
-- 索引设置,按需取
-- CREATE INDEX IF NOT EXISTS modeldata_userId_index ON modeldata USING HASH (user_id);
-- CREATE INDEX IF NOT EXISTS modeldata_kbId_index ON modeldata USING HASH (kb_id);
-- CREATE INDEX IF NOT EXISTS idx_model_data_md5_q_a_user_id_kb_id ON modeldata (md5(q), md5(a), user_id, kb_id);
-- CREATE INDEX modeldata_id_desc_idx ON modeldata (id DESC);
-- vector 索引,可以参考 [pg vector](https://github.com/pgvector/pgvector) 去配置,根据数据量去配置
EOSQL
```
4、**最后在 FASTGPT 项目里面运行 pnpm dev 运行项目,然后进入 localhost:3000 看项目是否跑起来了**
---
sidebar_position: 1
---
# Sealos 一键部署
无需服务器、无需魔法、无需域名,点击即可部署 👇
[![](https://raw.githubusercontent.com/labring-actions/templates/main/Deploy-on-Sealos.svg)](https://cloud.sealos.io/?openapp=system-fastdeploy%3FtemplateName%3Dfastgpt)
由于需要部署数据库,部署完后需要等待 2~4 分钟才能正常访问。默认用了最低配置,首次访问时会有些慢。
![](./imgs/sealos1.png)
## 运行
点击 sealos 提供的【外网地址】即可使用。登录用户名为: root,密码是刚设置的环境变量,上图中设置了: 1234
![](./imgs/sealos3.png)
# 本地开发
第一次开发,需要先部署数据库,建议本地开发可以随便找一台 2c2g 的轻量小数据库实践。数据库部署教程:[Docker 快速部署](/docs/develop/deploy/docker)
client 目录下为 FastGPT 核心代码。NextJS 框架前后端在一起的,api 服务位于 src/pages/api 内。
## 初始配置
**1. 环境变量**
复制.env.template 文件,生成一个.env.local 环境变量文件夹,修改.env.local 里内容才是有效的变量。变量说明见 .env.template
**2. config 配置文件**
复制 data/config.json 文件,生成一个 data/config.local.json 配置文件。
这个文件大部分时候不需要修改。只需要关注 SystemParams 里的参数:
```
"vectorMaxProcess": 向量生成最大进程,根据数据库和 key 的并发数来决定,通常单个 120 号,2c4g 服务器设置10~15。
"qaMaxProcess": QA 生成最大进程
"pgIvfflatProbe": PG vector 搜索探针,没有添加 vector 索引时可忽略。
```
## 运行
```
cd client
pnpm i
pnpm dev
```
## 镜像打包
```bash
docker build -t dockername/fastgpt .
```
# 部署 OneAPI,实现多模型
无需魔法,部署即可使用
## SqlLite 版本
sqllite 版本适合个人,少并发
## 一、[点击打开 Sealos 公有云](https://cloud.sealos.io/)
## 二、打开 AppLaunchpad(应用管理) 工具
![step1](./imgs/step1.png)
## 三、点击创建新应用
## 四、填写对应参数
镜像:ghcr.io/songquanpeng/one-api:latest
![step2](./imgs/step2.png)
打开外网访问开关后,Sealos 会自动分配一个可访问的地址,不需要自己配置。
![step3](./imgs/step3.png)
填写完参数后,点击右上角部署即可。
## 5. 访问
点击 Sealos 提供的外网访问地址,即可访问 OneAPI 项目。
![step3](./imgs/step4.png)
![step3](./imgs/step5.png)
## 6. 替换 FastGpt 的环境变量
```
# 下面的地址是 Sealos 提供的,务必写上 v1
OPENAI_BASE_URL=https://xxxx.cloud.sealos.io/v1
# 下面的 key 由 one-api 提供
CHAT_API_KEY=sk-xxxxxx
```
## MySQL 版本
高流量推荐使用 MySQL 版本,支持多实例扩展。
点击下方按键一键部署 👇
[![](https://raw.githubusercontent.com/labring-actions/templates/main/Deploy-on-Sealos.svg)](https://cloud.sealos.io/?openapp=system-fastdeploy%3FtemplateName%3Done-api)
部署完后会跳转【应用管理】,数据库在另一个应用里。需要等待 1~3 分钟数据库运行后才能访问成功。
# 安装 clash
clash 会在本机启动代理。对应的,你需要配置项目的两个环境变量:
```
AXIOS_PROXY_HOST=127.0.0.1
AXIOS_PROXY_PORT=7890
```
需要注的是,在你的 config.yaml 文件中,最好仅指定 api.openai.com 走代理,其他请求都直连。
**安装clash**
```bash
# 下载包
curl https://glados.rocks/tools/clash-linux.zip -o clash.zip
# 解压
unzip clash.zip
# 下载终端配置⽂件(改成自己配置文件路径)
curl https://update.glados-config.com/clash/98980/8f30944/70870/glados-terminal.yaml > config.yaml
# 赋予运行权限
chmod +x ./clash-linux-amd64-v1.10.0
```
**runClash.sh**
```sh
# 记得配置端口变量:
export ALL_PROXY=socks5://127.0.0.1:7891
export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890
export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890
# 运行脚本: 删除clash - 到 clash 目录 - 删除缓存 - 执行运行. 会生成一个 nohup.out 文件,可以看到 clash 的 logs
OLD_PROCESS=$(pgrep clash)
if [ ! -z "$OLD_PROCESS" ]; then
echo "Killing old process: $OLD_PROCESS"
kill $OLD_PROCESS
fi
sleep 2
cd **/clash
rm -f ./nohup.out || true
rm -f ./cache.db || true
nohup ./clash-linux-amd64-v1.10.0 -d ./ &
echo "Restart clash"
```
**config.yaml配置例子**
```yaml
mixed-port: 7890
allow-lan: false
bind-address: '*'
mode: rule
log-level: warning
dns:
enable: true
ipv6: false
nameserver:
- 8.8.8.8
- 8.8.4.4
cache-size: 400
proxies:
-
proxy-groups:
- { name: '♻️ 自动选择', type: url-test, proxies: [香港V01×1.5], url: 'https://api.openai.com', interval: 3600}
rules:
- 'DOMAIN-SUFFIX,api.openai.com,♻️ 自动选择'
- 'MATCH,DIRECT'
```
\ No newline at end of file
# cloudflare 代理配置
[来自 "不做了睡觉" 教程](https://gravel-twister-d32.notion.site/FastGPT-API-ba7bb261d5fd4fd9bbb2f0607dacdc9e)
**workers 配置文件**
```js
const TELEGRAPH_URL = 'https://api.openai.com';
addEventListener('fetch', (event) => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
// 安全校验
if (request.headers.get('auth') !== 'auth_code') {
return new Response('UnAuthorization', { status: 403 });
}
const url = new URL(request.url);
url.host = TELEGRAPH_URL.replace(/^https?:\/\//, '');
const modifiedRequest = new Request(url.toString(), {
headers: request.headers,
method: request.method,
body: request.body,
redirect: 'follow'
});
const response = await fetch(modifiedRequest);
const modifiedResponse = new Response(response.body, response);
// 添加允许跨域访问的响应头
modifiedResponse.headers.set('Access-Control-Allow-Origin', '*');
return modifiedResponse;
}
```
**对应的环境变量**
务必别忘了填 v1
```
OPENAI_BASE_URL=https://xxxxxx/v1
OPENAI_BASE_URL_AUTH=auth_code
```
# nginx 反向代理 openai 接口
如果你有国外的服务器,可以通过配置 nginx 反向代理,转发 openai 相关的请求,从而让国内的服务器可以通过访问该 nginx 去访问 openai 接口。
```conf
user nginx;
worker_processes auto;
worker_rlimit_nofile 51200;
events {
worker_connections 1024;
}
http {
resolver 8.8.8.8;
proxy_ssl_server_name on;
access_log off;
server_names_hash_bucket_size 512;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
client_max_body_size 50M;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 8k;
gzip_http_version 1.1;
gzip_comp_level 6;
gzip_vary on;
gzip_types text/plain application/x-javascript text/css application/javascript application/json application/xml;
gzip_disable "MSIE [1-6]\.";
open_file_cache max=1000 inactive=1d;
open_file_cache_valid 30s;
open_file_cache_min_uses 8;
open_file_cache_errors off;
server {
listen 3999;
server_name 你的 ip 地址;
location ~ /openai/(.*) {
proxy_pass https://api.openai.com/$1$is_args$args;
proxy_set_header Host api.openai.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 流式响应
proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;
proxy_buffering off;
proxy_cache off;
# 一般响应
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}
}
}
```
---
sidebar_position: 1
---
# sealos 部署 nginx 实现中转
## 登录 sealos cloud
[sealos cloud](https://cloud.sealos.io/)
## 一、点击创建应用
打开 App Launchpad -> 新建应用
![step1](./imgs//sealos1.png)
![step2](./imgs//sealos2.png)
### 二、填写基本配置
务必开启外网访问,复制下外网访问提供的地址。
![step3](./imgs//sealos3.png)
### 三、添加 configmap 文件
1. 复制下面这段配置文件,注意 `server_name` 后面的内容替换成第二步的外网访问地址。
```
user nginx;
worker_processes auto;
worker_rlimit_nofile 51200;
events {
worker_connections 1024;
}
http {
resolver 8.8.8.8;
proxy_ssl_server_name on;
access_log off;
server_names_hash_bucket_size 512;
client_header_buffer_size 64k;
large_client_header_buffers 4 64k;
client_max_body_size 50M;
proxy_connect_timeout 240s;
proxy_read_timeout 240s;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
server {
listen 80;
server_name tgohwtdlrmer.cloud.sealos.io; # 这个地方替换成 sealos 提供的内容
location ~ /openai/(.*) {
proxy_pass https://api.openai.com/$1$is_args$args;
proxy_set_header Host api.openai.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 如果响应是流式的
proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;
proxy_buffering off;
proxy_cache off;
# 如果响应是一般的
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}
}
}
```
2. 点开高级配置
3. 点击新增 configmap
4. 文件名写: `/etc/nginx/nginx.conf`
5. 文件值为刚刚复制的那段代码
6. 点击确认
![step4](./imgs//sealos4.png)
### 四、部署应用
填写完毕后,点击右上角的 `部署应用`,即可完成。
## 五、修改 FastGpt 环境变量
1. 进入刚刚部署应用的详情,复制外网地址
注意:这是个 API 地址,点击打开是无效的。如需验证,可以访问: 【\*\*\*.close.sealos.io/openai/api】,如果提示 "Invalid URL (GET /api)" 则代表成功。
![step5](./imgs//sealos5.png)
2. 修改环境变量(是 FastGpt 的环境变量,不是 sealos 的):
```
OPENAI_BASE_URL=https://tgohwtdlrmer.cloud.sealos.io/openai/v1
```
**Done!**
# V4.0 版本初始化
新版 mongo 表进行了不少的变更,需要执行一些初始化脚本。
## 重命名表名
需要连接上 mongo 数据库,执行两条命令:
`db.models.renameCollection("apps")`
`db.sharechats.renameCollection("outlinks")`
如果你已经更新部署了,mongo 会自动创建空表,需要手动删除这两个空表。
## 初始化几个表中的字段
依次执行下面 3 条命令,时间比较长,不成功可以重复执行(会跳过已经初始化的数据),直到所有数据更新完成。
```mongo
db.chats.find({appId: {$exists: false}}).forEach(function(item){
db.chats.updateOne(
{
_id: item._id,
},
{ "$set": {"appId":item.modelId}}
)
})
db.collections.find({appId: {$exists: false}}).forEach(function(item){
db.collections.updateOne(
{
_id: item._id,
},
{ "$set": {"appId":item.modelId}}
)
})
db.outlinks.find({shareId: {$exists: false}}).forEach(function(item){
db.outlinks.updateOne(
{
_id: item._id,
},
{ "$set": {"shareId":item._id.toString(),"appId":item.modelId}}
)
})
```
## 执行初始化 API
部署新版项目,并发起 3 个 HTTP 请求(记得携带 headers.rootkey,这个值是环境变量里的)
1. https://xxxxx/api/admin/initv4
2. https://xxxxx/api/admin/initChat
3. https://xxxxx/api/admin/initOutlink
1 和 2,有可能会因为内存不足挂掉,可以重复执行。
# V4.1 版本初始化
新版重新设置了对话存储结构,需要初始化原来的存储内容
## 更新环境变量
优化了 PG 和 Mongo 的连接变量,只需要 1 个 url 即可。
```
# mongo 配置,不需要改. 如果连不上,可能需要去掉 ?authSource=admin
- MONGODB_URI=mongodb://username:password@mongo:27017/fastgpt?authSource=admin
# pg配置. 不需要改
- PG_URL=postgresql://username:password@pg:5432/postgres
```
## 执行初始化 API
部署新版项目,并发起 1 个 HTTP 请求(记得携带 headers.rootkey,这个值是环境变量里的)
https://xxxxx/api/admin/initChatItem
# 内容提取
- 可重复添加
- 有外部输入
- 手动配置
- 触发执行
- function_call 模块
- 核心模块
![](./imgs/extract1.png)
## 功能
从文本中提取结构化数据,通常是配合 HTTP 模块实现扩展。也可以做一些直接提取操作,例如:翻译。
## 参数说明
### 提取要求描述
顾名思义,给模型一个要目标,需要提取哪些内容。
**例子 1**
> 你是实验室预约助手,从对话中提取出姓名,预约时间,实验室号。当前时间 {{cTime}}
**例子 2**
> 你是谷歌搜索助手,从对话中提取出搜索关键词
**例子 3**
> 将我的问题直接翻译成英文,不要回答问题
### 历史记录
通常需要一些历史记录,才能更完整的提取用户问题。例如上图中需要提前名字、时间和实验室名,用户可能一开始只给了时间和实验室名,没有给自己的名字。再经过一轮缺失提示后,用户输入了姓名,此时需要结合上一次的记录才能完整的提取出 3 个内容。
### 目标字段
目标字段与提取的结果相对应,从上图可以看到,每增加一个字段,输出会增加一个对应的出口。
key: 字段的唯一标识,不可重复!
字段描述:描述该字段是关于什么的,例如:姓名、时间、搜索词等等。
必须:是否强制模型提取该字段,可能提取出来是空字符串。
## 输出介绍
- 字段完全提取:说明用户的问题中包含需要提取的所有内容。
- 提取字段缺失:与 “字段完全提取” 对立,有缺失提取的字段时触发。
- 完整提取结果: 一个 json 字符串,包含所有字段的提取结果。
- 目标字段提取结果:类型均为字符串。
# 用户引导
- 仅可添加 1 个
- 无外部输入
- 不参与实际调度
如图,可以在用户提问前给予一定引导。并可以设置引导问题。
![](./imgs/guide.png)
# 历史记录
- 可重复添加(复杂编排时候防止线太乱,可以更美观)
- 无外部输入
- 流程入口
- 自动执行
每次对话时,会从数据库取最多 n 条聊天记录作为上下文。注意,不是指本轮对话最多 n 条上下文,本轮对话还包括:提示词、限定词、引用内容和问题。
![](./imgs/history.png)
# 指定回复
- 可重复添加(复杂编排时候防止线太乱,可以更美观)
- 可手动输入
- 可外部输入
- 会输出结果给客户端
制定回复模块通常用户特殊状态回复,当然你也可以像图 2 一样,实现一些比较骚的操作~ 触发逻辑非常简单,一种是写好回复内容,通过触发器触发;一种是不写回复内容,直接由外部输入触发,并回复输入的内容。
![](./imgs/specialreply.png)
图 1
![](./imgs/specialreply2.png)
图 2
# 用户问题
- 可重复添加(复杂编排时候防止线太乱,可以更美观)
- 无外部输入
- 流程入口
- 自动执行
![](./imgs/chatinput.png)
---
sidebar_position: 1
---
# 快速了解 FastGpt
FastGPT 是一个基于 LLM 大语言模型的知识库问答系统,提供开箱即用的数据处理、模型调用等能力。同时可以通过 Flow 可视化进行工作流编排,从而实现复杂的问答场景!
| | |
| -------------------------- | -------------------------- |
| ![Demo](./imgs/intro1.png) | ![Demo](./imgs/intro2.png) |
| ![Demo](./imgs/intro3.png) | ![Demo](./imgs/intro4.png) |
## FastGPT 能力
### 1. AI 客服
通过导入文档或已有问答对进行训练,让 AI 模型能根据你的文档进行回答问题。
![Ability1](./imgs/ability1.png)
### 2. 自动数据预处理
提供手动输入、直接分段、LLM 自动处理和 CSV 等多种数据导入途径,兼顾精确和快速训练场景。
![Ability1](./imgs/ability2.png)
### 3. 工作流编排
基于 Flow 模块的工作流编排,可以帮助你设计更加复杂的问答流程。例如查询数据库、查询库存、预约实验室等。
![Ability1](./imgs/ability3.png)
### 4. 无缝衔接的 OpenAPI
FastGPT 对外 API 接口对齐 GPT 官方接口,你可以直接在现有的 GPT 应用中通过修改 BaseURL 和 Authorization 即可接入 FastGPT。
![Ability1](./imgs/ability4.png)
## FastGPT 特点
1. 项目开源。FastGPT 遵循 Apache License 2.0 开源协议,你可以在 GitHub Clone FastGPT 进行二次开发和发布。FastGPT 社区版将保留核心的功能,商业版仅在社区版基础上使用 API 的形式进行扩展,不影响学习使用。
2. 独特的 QA 结构。针对客服问答场景设计的 QA 结构,提高在大量数据场景中的准确性。
3. 可视化工作流。通过 Flow 模块展示了从问题输入到模型输出的完整流程,便于调试和设计复杂流程。
4. 无限扩展。基于 HTTP 进行扩展,无需修改 FastGPT 源码,也可快速接入现有的程序中。
5. 便捷调试。提供搜索测试、引用修改、完整对话预览等多种调试途径。
6. 支持多种模型:支持 GPT、Claude、文心一言等多类 LLM 模型,未来也将支持自定义的向量模型。
## 知识库核心流程图
![KBProcess](./imgs/KBProcess.jpg?raw=true 'KBProcess')
# 3分钟在Fastgpt上用上GLM
## 前言
Fast GPT 允许你使用自己的 openai API KEY 来快速的调用 openai 接口,目前集成了 Gpt35, Gpt4 和 embedding. 可构建自己的知识库。但考虑到数据安全的问题,我们并不能将所有的数据都交付给云端大模型。那如何在fastgpt上接入私有化模型呢,本文就以清华的ChatGLM2为例,为各位讲解如何在fastgpt中接入私有化模型。
## ChatGLM2简介
ChatGLM2-6B 是开源中英双语对话模型 ChatGLM-6B 的第二代版本,具体介绍请看项目:https://github.com/THUDM/ChatGLM2-6B
注意,ChatGLM2-6B 权重对学术研究完全开放,在获得官方的书面许可后,亦允许商业使用。本教程只是介绍了一种用法,并不会给予任何授权。
## 推荐配置
依据官方数据,同样是生成 8192 长度,量化等级为FP16要占用12.8GB 显存、INT8为8.1GB显存、INT4为5.1GB显存,量化后会稍微影响性能,但不多。
因此推荐配置如下:
fp16:内存>=16GB,显存>=16GB,硬盘空间>=25GB,启动时使用命令python openai_api.py 16
int8:内存>=16GB,显存>=9GB,硬盘空间>=25GB,启动时选择python openai_api.py 8
int4:内存>=16GB,显存>=6GB,硬盘空间>=25GB,启动时选择python openai_api.py 4
## 环境配置
Python 3.8.10
CUDA 11.8
科学上网环境
## 简单的步骤
1. 根据上面的环境配置配置好环境,具体教程自行GPT;
1. 在命令行输入pip install -r requirments.txt
2. 打开你需要启动的py文件,在代码的第76行配置token,这里的token只是加一层验证,防止接口被人盗用
2. python openai_api.py 16//这里的数字根据上面的配置进行选择
然后等待模型下载,直到模型加载完毕,出现报错先问GPT
上面两个文件在本文档的同目录
启动成功后应该会显示如下地址:
![Alt text](image.png)
这里的http://0.0.0.0:6006就是连接地址
然后现在回到.env.local文件,依照以下方式配置地址:
OPENAI_BASE_URL=http://127.0.0.1:6006/v1
OPENAIKEY=sk-aaabbbcccdddeeefffggghhhiiijjjkkk //这里是你在代码中配置的token
这里的OPENAIKEY可以任意填写
这样就成功接入ChatGLM2了
# 通过 OpenAPI 接入第三方应用
## 1. 获取 API 秘钥
注意复制,关掉了需要新建~
![imgs](./img1.png)
## 2. 组合秘钥
利用刚复制的 API 秘钥加上 AppId 组合成一个新的秘钥,格式为: API 秘钥-AppId,例如:`fastgpt-z51pkjqm9nrk03a1rx2funoy-642adec15f04d67d4613efdb`
## 3. 替换三方应用的变量
OPENAI_API_BASE_URL: https://fastgpt.run/api/openapi (改成自己部署的域名)
OPENAI_API_KEY = 组合秘钥
**[chatgpt next](https://github.com/Yidadaa/ChatGPT-Next-Web) 示例**
![imgs](./chatgptnext.png)
**[chatgpt web](https://github.com/Chanzhaoyu/chatgpt-web) 示例**
![imgs](./chatgptweb.png)
{
"item.label.Docs": {
"message": "文档"
},
"item.label.Start Now": {
"message": "在线使用"
}
}
[lang_select_title]
other = "语言切换"
[search_title]
other = "搜索"
[search_navigate]
other = "导航"
[search_select]
other = "选中"
[search_close]
other = "关闭"
[search_cancel]
other = "取消"
[search_no_results]
other = "没有结果:"
[feedback_yes]
other = "Yes"
[feedback_no]
other = "No"
[feedback_helpful]
other = "Was this page helpful?"
[feedback_submit]
other = "提交"
\ No newline at end of file
<!DOCTYPE html>
{{ $.Scratch.Delete "social_list" }}
<!-- social_list -->
<!-- change -->
{{ $social_params := slice "github" "twitter" "instagram" "rss" "wechat" }}
{{ range $social_params }}
{{ if isset site.Params.social . }}
{{ $.Scratch.Add "social_list" (slice .) }}
{{ end }}
{{ end }}
<html lang="{{ site.LanguageCode }}">
{{- partial (printf "%s/%s" (.Site.Params.docs.pathName | default "docs") "head.html") . -}}
<body>
<div class="content">
<div class="page-wrapper toggled">
{{- partial (printf "%s/%s" (.Site.Params.docs.pathName | default "docs") "sidebar.html") . -}}
<!-- Start Page Content -->
<main class="page-content bg-transparent">
{{- partialCached (printf "%s/%s" (.Site.Params.docs.pathName | default "docs") "top-header.html") . -}}
<div class="container-fluid">
<div class="layout-spacing">
{{ $currentPage := . -}}
{{ if site.Params.docs.breadcrumbs | default true }}
<div class="d-md-flex justify-content-between align-items-center">
{{- partial (printf "%s/%s" (.Site.Params.docs.pathName | default "docs") "breadcrumbs.html") . -}}
</div>
{{ end }}
<div class="row flex-xl-nowrap">
{{ if site.Params.docs.toc | default true }}
<div class="docs-toc col-xl-3 {{ if .IsNode }}visually-hidden{{ else }}{{end}} {{ if and (ne .Params.toc false) (ne .TableOfContents "<nav id=\"TableOfContents\"></nav>") }}{{ else }}visually-hidden{{ end }} {{ if site.Params.docs.toc | default true }}{{ else }}visually-hidden{{ end }} d-xl-block">
{{- partial (printf "%s/%s" (.Site.Params.docs.pathName | default "docs") "toc.html") . -}}
</div>
{{ end }}
{{ if site.Params.docs.tocMobile | default true }}
<div class="docs-toc-mobile {{ if .IsNode }}visually-hidden{{ else }}{{end}} {{ if and (ne .Params.toc false) (ne .TableOfContents "<nav id=\"TableOfContents\"></nav>") }}{{ else }}visually-hidden{{ end }} {{ if site.Params.docs.tocMobile | default true }}{{ else }}visually-hidden{{ end }} d-print-none d-xl-none">
<button id="toc-dropdown-btn" class="btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" data-bs-offset="0,0" aria-expanded="false">
Contents
</button>
{{- partial (printf "%s/%s" (.Site.Params.docs.pathName | default "docs") "toc-mobile.html") . -}}
</div>
{{ end -}}
<div class="docs-content col-12 {{ if .IsNode }}{{ else }}{{ if site.Params.docs.toc | default true }}{{ if and (ne .Params.toc false) }}col-xl-9{{else}}{{end}}{{ else }}{{ end }}{{ end }} mt-0">
<div class="mb-3">
<h1 class="content-title mb-0">
{{ if site.Params.docs.titleIcon | default false }}
<i class="material-icons me-0">{{- .Params.icon | default "article" }}</i>
{{ end }}
<span class="title-text">
{{ $currentPage.Title }}
</span>
{{ if .Draft }}
<span class="badge bg-default fs-6 mb-1 align-middle">DRAFT</span>
{{ end }}
</h1>
{{ if site.Params.docs.descriptions | default false }}
<p class="lead mb-0">{{ $currentPage.Description | markdownify }}</p>
{{ end }}
</div>
<div id="content" class="main-content" {{ if eq .Site.Params.docs.toc true -}}data-bs-spy="scroll" data-bs-root-margin="0px 0px -65%" data-bs-target="#toc-mobile"{{ end }}>
{{ block "main" . }}{{ end }}
</div>
<div>
{{- partial (printf "%s/%s" (.Site.Params.docs.pathName | default "docs") "doc-nav.html") . -}}
</div>
</div>
</div>
</div>
</div>
{{- partialCached (printf "%s/%s" (.Site.Params.docs.pathName | default "docs") "footer.html") . -}}
</main>
</div>
</div>
{{ if site.Params.docs.backToTop | default true }}
<!-- Back to top -->
<button onclick="topFunction()" id="back-to-top" class="back-to-top fs-5"><svg width="24" height="24"><path d="M12,10.224l-6.3,6.3L4.32,15.152,12,7.472l7.68,7.68L18.3,16.528Z" style="fill:#fff"/></svg></button>
<!-- Back to top -->
{{ end }}
<!-- Dark Mode Switch JS -->
{{ if eq .Site.Params.docs.darkMode true -}}
{{ $darkModeSwitch := resources.Get (printf "/%s/%s" (.Site.Params.docs.pathName | default "docs") "js/darkmode-switch.js") | js.Build | minify }}
<script>{{ $darkModeSwitch.Content | safeJS }}</script>
{{ end -}}
{{- partialCached (printf "%s/%s" (.Site.Params.docs.pathName | default "docs") "footer/footer-scripts.html") . -}}
<!-- DocSearch Config -->
{{ if and (.Site.Params.docsearch.appID) (.Site.Params.docsearch.apiKey) -}}
{{- partialCached (printf "%s/%s" (.Site.Params.docs.pathName | default "docs") "footer/docsearch.html") . -}}
{{ end }}
<!-- FlexSearch Config -->
{{ if or (not (isset .Site.Params.flexsearch "enabled")) (eq .Site.Params.flexsearch.enabled true) -}}
{{ if and (.Site.Params.docsearch.appID) (.Site.Params.docsearch.apiKey) -}}
{{ else }}
{{- partialCached (printf "%s/%s" (.Site.Params.docs.pathName | default "docs") "footer/flexsearch.html") . -}}
{{ end }}
{{ end }}
</body>
{{- partial (printf "%s/%s" (.Site.Params.docs.pathName | default "docs") "modals.html") . -}}
</html>
\ No newline at end of file
<style>
.medium-zoom-overlay,
.medium-zoom-image--opened {
z-index: 1999;
}
</style>
{{ $dayjs := resources.Get (printf "/%s/%s" (.Site.Params.docs.pathName | default "docs") "js/dayjs.min.js") }}
{{ $relativeTime := resources.Get (printf "/%s/%s" (.Site.Params.docs.pathName | default "docs") "js/relativeTime.min.js") }}
{{ $app := resources.Get (printf "/%s/%s" (.Site.Params.docs.pathName | default "docs") "js/app.js") -}}
{{ $slice := slice $dayjs $relativeTime $app -}}
{{ if and (.Site.Params.docsearch.appID) (.Site.Params.docsearch.apiKey) -}}
{{ $docsearch := resources.Get (printf "/%s/%s" (.Site.Params.docs.pathName | default "docs") "js/docsearch.min.js") }}
{{ $slice = $slice | append $docsearch -}}
{{ end }}
{{ if site.Params.docs.toc | default true }}
{{ if eq .Site.Params.docs.scrollSpy true -}}
{{ $simplescrollspy := resources.Get (printf "/%s/%s" (.Site.Params.docs.pathName | default "docs") "js/simple-scrollspy.min.js") }}
{{ $slice = $slice | append $simplescrollspy -}}
{{ end -}}
{{ if eq .Site.Params.docs.scrollSpy true -}}
{{ $scrollspyScript := resources.Get (printf "/%s/%s" (.Site.Params.docs.pathName | default "docs") "js/scrollspy-script.js") }}
{{ $scrollspyScript := $scrollspyScript | js.Build -}}
{{ $slice = $slice | append $scrollspyScript -}}
{{ end -}}
{{ end -}}
{{ if site.Params.docs.tocMobile | default true }}
{{ $tocmobilescrollspy := resources.Get (printf "/%s/%s" (.Site.Params.docs.pathName | default "docs") "js/toc-mobile-scrollspy.js") }}
{{ $slice = $slice | append $tocmobilescrollspy -}}
{{ end -}}
{{ if eq .Site.Params.docs.prism true -}}
{{ $prism := resources.Get (printf "/%s/%s" (.Site.Params.docs.pathName | default "docs") "js/prism.js") }}
{{ $prism := $prism | js.Build -}}
{{ $slice = $slice | append $prism -}}
{{ end -}}
<!-- Bootstrap JS -->
{{ $js := resources.Get (printf "/%s/%s" (.Site.Params.docs.pathName | default "docs") "js/bootstrap.js") }}
{{ $params := dict }}
{{ $sourceMap := cond hugo.IsProduction "" "inline" }}
{{ $opts := dict "sourceMap" $sourceMap "minify" hugo.IsProduction "target" "es2018" "params" $params }}
{{ $js = $js | js.Build $opts }}
{{ if hugo.IsProduction }}
{{ $js = $js | fingerprint "sha384" }}
{{ end }}
<script src="{{ $js.RelPermalink }}" {{ if hugo.IsProduction }}integrity="{{ $js.Data.Integrity }}"{{ end -}} defer></script>
{{ $js := $slice | resources.Concat (printf "/%s/%s" (.Site.Params.docs.pathName | default "docs") "js/bundle.js") -}}
{{- if not .Site.IsServer }}
{{- $js := $js | minify | fingerprint "sha384" }}
<script type="text/javascript" src="{{ $js.Permalink }}" integrity="{{ $js.Data.Integrity }}" crossorigin="anonymous" defer></script>
{{- else }}
<script type="text/javascript" src="{{ $js.Permalink }}" defer></script>
{{- end }}
<script
src="https://cdn.jsdelivr.us/npm/medium-zoom/dist/medium-zoom.min.js"
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
<script>
const images = Array.from(document.querySelectorAll(".main-content img"));
images.forEach((img) => {
mediumZoom(img, {
margin: 0 /* The space outside the zoomed image */,
scrollOffset: 40 /* The number of pixels to scroll to close the zoom */,
container: null /* The viewport to render the zoom in */,
template: null /* The template element to display on zoom */,
background: "rgba(0, 0, 0, 0.8)"
});
});
</script>
\ No newline at end of file
<head>
<meta charset="utf-8" />
<title>
{{- $url := replace .Permalink ( printf "%s" .Site.BaseURL) "" }}
{{- if eq $url "/" }}
{{- .Site.Title }}
{{- else }}
{{- if .Params.heading }}
{{ .Params.heading }}
{{ else }}
{{- if eq .Title .Site.Title }}
{{- .Title }}
{{- else }}
{{ .Site.Params.docs.Title | default (.Site.Title) }} | {{ .Title }}
{{- end }}
{{- end }}
{{- end -}}
</title>
{{- if not hugo.IsProduction }}
<meta name="robots" content="noindex">
{{- end }}
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="A Modern Documentation Theme for Hugo" />
<meta name="keywords" content="Documentation, Hugo, Hugo Theme, Bootstrap" />
<meta name="author" content="Colin Wilson - Lotus Labs" />
<meta name="email" content="support@aigis.uk" />
<meta name="website" content="https://lotusdocs.dev" />
<meta name="Version" content="v0.1.0" />
<!-- favicon -->
{{ block "favicon" . }}{{ partialCached (printf "%s/%s" (.Site.Params.docs.pathName | default "docs") "head/favicon.html") . }}{{ end }}
<!-- Dark Mode -->
{{ if eq .Site.Params.docs.darkMode true -}}
{{ $darkModeInit := resources.Get (printf "/%s/%s" (.Site.Params.docs.pathName | default "docs") "js/darkmode-init.js") | js.Build | minify -}}
<script>{{ $darkModeInit.Content | safeJS }}</script>
{{ end -}}
<!-- FlexSearch -->
{{ if or (not (isset .Site.Params.flexsearch "enabled")) (eq .Site.Params.flexsearch.enabled true) -}}
{{ if and (.Site.Params.docsearch.appID) (.Site.Params.docsearch.apiKey) -}}
{{ else }}
{{ $flexSearch := resources.Get (printf "/%s/%s" (.Site.Params.docs.pathName | default "docs") "js/flexsearch.bundle.js") }}
{{- if not .Site.IsServer }}
{{ $flexSearch := $flexSearch | minify | fingerprint "sha384" }}
<script type="text/javascript" src="{{ $flexSearch.Permalink }}" integrity="{{ $flexSearch.Data.Integrity }}" crossorigin="anonymous"></script>
{{ else }}
<script type="text/javascript" src="{{ $flexSearch.Permalink }}"></script>
{{ end }}
{{ end }}
{{ end }}
<!-- Google Fonts -->
{{- partialCached "google-fonts" . }}
<!-- Custom CSS -->
{{- $options := dict "enableSourceMap" true }}
{{- if hugo.IsProduction}}
{{- $options := dict "enableSourceMap" false "outputStyle" "compressed" }}
{{- end }}
{{- $style := resources.Get (printf "/%s/%s" (.Site.Params.docs.pathName | default "docs") "scss/style.scss") }}
{{- $style = $style | resources.ExecuteAsTemplate (printf "/%s/%s" (.Site.Params.docs.pathName | default "docs") "scss/style.scss") . | resources.ToCSS $options }}
{{- if hugo.IsProduction }}
{{- $style = $style | minify | fingerprint "sha384" }}
{{- end -}}
<link rel="stylesheet" href="{{ $style.RelPermalink }}" {{ if hugo.IsProduction }}integrity="{{ $style.Data.Integrity }}"{{ end -}} crossorigin="anonymous">
<!-- Plausible Analytics Config -->
{{- if not .Site.IsServer }}
{{ if and (.Site.Params.plausible.scriptURL | default "https://plausible.io") (.Site.Params.plausible.dataDomain) -}}
{{- partialCached (printf "%s/%s" (.Site.Params.docs.pathName | default "docs") "head/plausible") . }}
{{- end -}}
{{- end -}}
<!-- Google Analytics v4 Config -->
{{- if not .Site.IsServer }}
{{- if .Site.GoogleAnalytics }}
{{- template "_internal/google_analytics.html" . -}}
{{- end -}}
{{- end -}}
</head>
\ No newline at end of file
<toc>
<div class="fw-bold text-uppercase mb-2">{{ .Title }}</div>
{{ if eq .Site.Params.docs.scrollSpy true -}}
{{ .TableOfContents | replaceRE "<nav id=\"TableOfContents\">" "<nav id=\"toc\">" | safeHTML }}
{{ else -}}
{{ .TableOfContents }}
{{ end -}}
</toc>
\ No newline at end of file
<!-- Top Header -->
<div id="top-header" class="top-header d-print-none">
<div class="header-bar d-flex justify-content-between">
<div class="d-flex align-items-center">
<a href='{{ relLangURL "" }}' class="logo-icon me-3" aria-label="HomePage" alt="HomePage">
<div class="small">
{{ with resources.Get "images/logos/mark.svg" }}
{{ .Content | safeHTML }}
{{ end }}
</div>
<div class="big">
{{ with resources.Get "images/logos/logo.svg" }}
{{ .Content | safeHTML }}
{{ end }}
</div>
</a>
<button id="close-sidebar" class="btn btn-icon btn-soft">
<span class="material-icons size-20 menu-icon align-middle">menu</span>
</button>
{{ if and (.Site.Params.docsearch.appID) (.Site.Params.docsearch.apiKey) -}}
<span><div id="docsearch"></div></span>
{{ end }}
{{ if or (not (isset .Site.Params.flexsearch "enabled")) (eq .Site.Params.flexsearch.enabled true) -}}
{{ if and (.Site.Params.docsearch.appID) (.Site.Params.docsearch.apiKey) -}}
{{ else }}
<!-- <form class="flexsearch position-relative flex-grow-1 ms-2 me-lg-2 d-none">
<input id="flexsearch" class="form-control is-search" type="search" placeholder="{{ i18n "search_title" }}" aria-label="{{ i18n "search_title" }}" autocomplete="off">
<div id="suggestions" class="shadow bg-white rounded d-none"></div>
</form> -->
<button id="flexsearch-button" class="ms-3 btn btn-soft" data-bs-toggle="collapse" data-bs-target="#FlexSearchCollapse" aria-expanded="false" aria-controls="FlexSearchCollapse">
<span class="material-icons size-20 menu-icon align-middle">search</span>
<span class="flexsearch-button-placeholder ms-1 me-2 d-none d-sm-block">{{ i18n "search_title" }}</span>
<div class="d-none d-sm-block">
<span class="flexsearch-button-keys">
<kbd class="flexsearch-button-cmd-key">
<svg width="44" height="15"><path d="M2.118,11.5A1.519,1.519,0,0,1,1,11.042,1.583,1.583,0,0,1,1,8.815a1.519,1.519,0,0,1,1.113-.458h.715V6.643H2.118A1.519,1.519,0,0,1,1,6.185,1.519,1.519,0,0,1,.547,5.071,1.519,1.519,0,0,1,1,3.958,1.519,1.519,0,0,1,2.118,3.5a1.519,1.519,0,0,1,1.114.458A1.519,1.519,0,0,1,3.69,5.071v.715H5.4V5.071A1.564,1.564,0,0,1,6.976,3.5,1.564,1.564,0,0,1,8.547,5.071,1.564,1.564,0,0,1,6.976,6.643H6.261V8.357h.715a1.575,1.575,0,0,1,1.113,2.685,1.583,1.583,0,0,1-2.227,0A1.519,1.519,0,0,1,5.4,9.929V9.214H3.69v.715a1.519,1.519,0,0,1-.458,1.113A1.519,1.519,0,0,1,2.118,11.5Zm0-.857a.714.714,0,0,0,.715-.714V9.214H2.118a.715.715,0,1,0,0,1.429Zm4.858,0a.715.715,0,1,0,0-1.429H6.261v.715a.714.714,0,0,0,.715.714ZM3.69,8.357H5.4V6.643H3.69ZM2.118,5.786h.715V5.071a.714.714,0,0,0-.715-.714.715.715,0,0,0-.5,1.22A.686.686,0,0,0,2.118,5.786Zm4.143,0h.715a.715.715,0,0,0,.5-1.22.715.715,0,0,0-1.22.5Z" fill="currentColor"></path><path d="M12.4,11.475H11.344l3.879-7.95h1.056Z" fill="currentColor"></path><path d="M25.073,5.384l-.864.576a2.121,2.121,0,0,0-1.786-.923,2.207,2.207,0,0,0-2.266,2.326,2.206,2.206,0,0,0,2.266,2.325,2.1,2.1,0,0,0,1.782-.918l.84.617a3.108,3.108,0,0,1-2.622,1.293,3.217,3.217,0,0,1-3.349-3.317,3.217,3.217,0,0,1,3.349-3.317A3.046,3.046,0,0,1,25.073,5.384Z" fill="currentColor"></path><path d="M30.993,5.142h-2.07v5.419H27.891V5.142h-2.07V4.164h5.172Z" fill="currentColor"></path><path d="M34.67,4.164c1.471,0,2.266.658,2.266,1.851,0,1.087-.832,1.809-2.134,1.855l2.107,2.691h-1.28L33.591,7.87H33.07v2.691H32.038v-6.4Zm-1.6.969v1.8h1.572c.832,0,1.22-.3,1.22-.918s-.411-.882-1.22-.882Z" fill="currentColor"></path><path d="M42.883,10.561H38.31v-6.4h1.033V9.583h3.54Z" fill="currentColor"></path></svg>
</kbd>
<kbd class="flexsearch-button-key">
<svg width="15" height="15"><path d="M5.926,12.279H4.41L9.073,2.721H10.59Z" fill="currentColor"/></svg>
</kbd>
</span>
</div>
</button>
{{ end }}
{{ end -}}
</div>
<div class="d-flex align-items-center">
<ul class="list-unstyled mb-0">
{{ with $.Scratch.Get "social_list" }}
{{ range . }}
{{ $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">
<div class="btn btn-icon btn-default border-0">
{{ with resources.Get $path }}
{{ .Content | safeHTML }}
{{ end }}
</div>
</a>
</li>
{{ end }}
{{ end }}
</ul>
{{ if eq .Site.Params.docs.darkMode true -}}
<button id="mode" class="btn btn-icon btn-default ms-2" type="button" aria-label="Toggle user interface mode">
<span class="toggle-dark">
<svg xmlns="http://www.w3.org/2000/svg" height="30" width="30" viewBox="0 0 48 48" fill="currentColor"><path d="M24 42q-7.5 0-12.75-5.25T6 24q0-7.5 5.25-12.75T24 6q.4 0 .85.025.45.025 1.15.075-1.8 1.6-2.8 3.95-1 2.35-1 4.95 0 4.5 3.15 7.65Q28.5 25.8 33 25.8q2.6 0 4.95-.925T41.9 22.3q.05.6.075.975Q42 23.65 42 24q0 7.5-5.25 12.75T24 42Zm0-3q5.45 0 9.5-3.375t5.05-7.925q-1.25.55-2.675.825Q34.45 28.8 33 28.8q-5.75 0-9.775-4.025T19.2 15q0-1.2.25-2.575.25-1.375.9-3.125-4.9 1.35-8.125 5.475Q9 18.9 9 24q0 6.25 4.375 10.625T24 39Zm-.2-14.85Z"/></svg>
</span>
<span class="toggle-light">
<svg xmlns="http://www.w3.org/2000/svg" height="30" width="30" viewBox="0 0 48 48" fill="currentColor"><path d="M24 31q2.9 0 4.95-2.05Q31 26.9 31 24q0-2.9-2.05-4.95Q26.9 17 24 17q-2.9 0-4.95 2.05Q17 21.1 17 24q0 2.9 2.05 4.95Q21.1 31 24 31Zm0 3q-4.15 0-7.075-2.925T14 24q0-4.15 2.925-7.075T24 14q4.15 0 7.075 2.925T34 24q0 4.15-2.925 7.075T24 34ZM3.5 25.5q-.65 0-1.075-.425Q2 24.65 2 24q0-.65.425-1.075Q2.85 22.5 3.5 22.5h5q.65 0 1.075.425Q10 23.35 10 24q0 .65-.425 1.075-.425.425-1.075.425Zm36 0q-.65 0-1.075-.425Q38 24.65 38 24q0-.65.425-1.075.425-.425 1.075-.425h5q.65 0 1.075.425Q46 23.35 46 24q0 .65-.425 1.075-.425.425-1.075.425ZM24 10q-.65 0-1.075-.425Q22.5 9.15 22.5 8.5v-5q0-.65.425-1.075Q23.35 2 24 2q.65 0 1.075.425.425.425.425 1.075v5q0 .65-.425 1.075Q24.65 10 24 10Zm0 36q-.65 0-1.075-.425-.425-.425-.425-1.075v-5q0-.65.425-1.075Q23.35 38 24 38q.65 0 1.075.425.425.425.425 1.075v5q0 .65-.425 1.075Q24.65 46 24 46ZM12 14.1l-2.85-2.8q-.45-.45-.425-1.075.025-.625.425-1.075.45-.45 1.075-.45t1.075.45L14.1 12q.4.45.4 1.05 0 .6-.4 1-.4.45-1.025.45-.625 0-1.075-.4Zm24.7 24.75L33.9 36q-.4-.45-.4-1.075t.45-1.025q.4-.45 1-.45t1.05.45l2.85 2.8q.45.45.425 1.075-.025.625-.425 1.075-.45.45-1.075.45t-1.075-.45ZM33.9 14.1q-.45-.45-.45-1.05 0-.6.45-1.05l2.8-2.85q.45-.45 1.075-.425.625.025 1.075.425.45.45.45 1.075t-.45 1.075L36 14.1q-.4.4-1.025.4-.625 0-1.075-.4ZM9.15 38.85q-.45-.45-.45-1.075t.45-1.075L12 33.9q.45-.45 1.05-.45.6 0 1.05.45.45.45.45 1.05 0 .6-.45 1.05l-2.8 2.85q-.45.45-1.075.425-.625-.025-1.075-.425ZM24 24Z"/></svg>
</span>
</button>
{{ end -}}
{{ if .Site.IsMultiLingual }}
<button type="button" class="ps-2 btn btn-link btn-default" data-bs-toggle="modal" data-bs-target="#lang-selector-popup">
{{ site.Language.Lang | upper }}
</button>
{{ end }}
</div>
</div>
<!-- FlexSearch Input Start -->
{{ if or (not (isset .Site.Params.flexsearch "enabled")) (eq .Site.Params.flexsearch.enabled true) -}}
{{ if and (.Site.Params.docsearch.appID) (.Site.Params.docsearch.apiKey) -}}
{{ else }}
<div class="collapse" id="FlexSearchCollapse">
<div class="flexsearch-container">
<div class="flexsearch-keymap">
<li>
<kbd class="flexsearch-button-cmd-key"><svg width="15" height="15" aria-label="Arrow down" role="img"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.2"><path d="M7.5 3.5v8M10.5 8.5l-3 3-3-3"></path></g></svg></kbd>
<kbd class="flexsearch-button-cmd-key"><svg width="15" height="15" aria-label="Arrow up" role="img"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.2"><path d="M7.5 11.5v-8M10.5 6.5l-3-3-3 3"></path></g></svg></kbd>
<span class="flexsearch-key-label">{{ i18n "search_navigate" | default "to navigate" }}</span>
</li>
<li>
<kbd class="flexsearch-button-cmd-key"><svg width="15" height="15" aria-label="Enter key" role="img"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.2"><path d="M12 3.53088v3c0 1-1 2-2 2H4M7 11.53088l-3-3 3-3"></path></g></svg></kbd>
<span class="flexsearch-key-label">{{ i18n "search_select" | default "to select" }}</span>
</li>
<li>
<kbd class="flexsearch-button-cmd-key"><svg width="15" height="15" aria-label="Escape key" role="img"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.2"><path d="M13.6167 8.936c-.1065.3583-.6883.962-1.4875.962-.7993 0-1.653-.9165-1.653-2.1258v-.5678c0-1.2548.7896-2.1016 1.653-2.1016.8634 0 1.3601.4778 1.4875 1.0724M9 6c-.1352-.4735-.7506-.9219-1.46-.8972-.7092.0246-1.344.57-1.344 1.2166s.4198.8812 1.3445.9805C8.465 7.3992 8.968 7.9337 9 8.5c.032.5663-.454 1.398-1.4595 1.398C6.6593 9.898 6 9 5.963 8.4851m-1.4748.5368c-.2635.5941-.8099.876-1.5443.876s-1.7073-.6248-1.7073-2.204v-.4603c0-1.0416.721-2.131 1.7073-2.131.9864 0 1.6425 1.031 1.5443 2.2492h-2.956"></path></g></svg></kbd>
<span class="flexsearch-key-label">{{ i18n "search_close" | default "to close" }}</span>
</li>
</div>
<form class="flexsearch position-relative flex-grow-1 ms-2 me-2">
<div class="d-flex flex-row">
<input id="flexsearch" class="form-control" type="search" placeholder="{{ i18n "search_title" }}" aria-label="{{ i18n "search_title" }}" autocomplete="off">
<button id="hideFlexsearch" type="button" class="ms-2 btn btn-soft">
{{ i18n "search_cancel" | default "cancel" }}
</button>
</div>
<div id="suggestions" class="shadow rounded-1 d-none"></div>
</form>
</div>
</div>
{{ end }}
{{ end }}
<!-- FlexSearch Input End -->
</div>
<!-- Top Header -->
\ No newline at end of file
<!DOCTYPE HTML>
<html>
<head>
<!-- style 样式 是为了让网页上的视频框按比例显示而非固定的大小 -->
<style type="text/css">
.aspect-ratio {
position: relative;
width: 100%;
height: 0;
padding-bottom: 75%;
margin-bottom: 1rem;
}
.aspect-ratio iframe {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
}
</style>
</head>
<body>
<div class="aspect-ratio">
<iframe
src="https://player.bilibili.com/player.html?bvid={{.Get 0 }}&page={{ if .Get 1 }}{{.Get 1}}{{ else }}1&high_quality=1&danmaku=0{{end}}"
scrolling="no"
border="0"
frameborder="no"
framespacing="0"
allowfullscreen="true"
>
</iframe>
<!-- src 中的 &high_quality=1&danmaku=0 设定了高清程度并默认屏蔽弹幕 -->
</div>
</body>
</html>
\ No newline at end of file
{{ if .Get "default" }}
{{ template "_internal/shortcodes/figure.html" . }}
{{ else }}
{{ $url := urls.Parse (.Get "src") }}
{{ $altText := .Get "alt" }}
{{ $caption := .Get "caption" }}
{{ $href := .Get "href" }}
{{ $class := .Get "class" }}
<figure{{ with $class }} class="{{ . }}"{{ end }}>
{{ with $href }}<a href="{{ . }}">{{ end }}
<img
class="mx-auto my-0 rounded-md"
alt="{{ $altText }}"
{{ if .Site.Params.enableImageLazyLoading | default true }}
loading="lazy"
{{ end }}
{{ if findRE "^https?" $url.Scheme }}
src="{{ $url.String }}"
{{ else }}
{{ $resource := "" }}
{{ if $.Page.Resources.GetMatch ($url.String) }}
{{ $resource = $.Page.Resources.GetMatch ($url.String) }}
{{ else if resources.GetMatch ($url.String) }}
{{ $resource = resources.Get ($url.String) }}
{{ end }}
{{ with $resource }}
{{ if eq .MediaType.SubType "svg" }}
src="{{ .RelPermalink }}"
{{ else }}
src="{{ .RelPermalink }}"
{{ end }}
{{ else }}
src="{{ $url.String }}"
{{ end }}
{{ end }}
/>
{{ with $href }}</a>{{ end }}
{{ with $caption }}<figcaption style="text-align: center; margin-top: .8571429em; font-size: .875em">{{ . | markdownify }}</figcaption>{{ end }}
</figure>
{{ end }}
\ No newline at end of file
{
"name": "fastgpt-doc-site",
"version": "0.0.0",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
"start": "docusaurus start",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"typecheck": "tsc"
},
"dependencies": {
"@docusaurus/core": "2.4.1",
"@docusaurus/preset-classic": "2.4.1",
"@mdx-js/react": "^1.6.22",
"clsx": "^1.2.1",
"prism-react-renderer": "^1.3.5",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "2.4.1",
"@tsconfig/docusaurus": "^1.0.5",
"typescript": "^4.7.4"
},
"browserslist": {
"production": [
">0.5%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"engines": {
"node": ">=16.14"
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
{"Target":"docs/scss/style.min.42fafeafea4b9a26eac18c5664437b88442be7755acffbad0d38d25197ed8edc50a753a2e4d31e985effeb9bbcd8d24c.css","MediaType":"text/css","Data":{"Integrity":"sha384-Qvr+r+pLmibqwYxWZEN7iEQr53Vaz/utDTjSUZftjtxQp1Oi5NMemF7/65u82NJM"}}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
{"Target":"docs/scss/style.css","MediaType":"text/css","Data":{}}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
{"Target":"scss/style.min.ec1b3216a7a530dcec8d1bfbaa75dbaea1cfb55e6f93457f68ecae35089def4fdad51a1aa8c8c4a915aeeb420f5f95a3.css","MediaType":"text/css","Data":{"Integrity":"sha384-7BsyFqelMNzsjRv7qnXbrqHPtV5vk0V/aOyuNQid70/a1RoaqMjEqRWu60IPX5Wj"}}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
{"Target":"scss/style.css","MediaType":"text/css","Data":{}}
\ No newline at end of file
// @ts-check
/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
const sidebars = {
docSidebar: [
'intro',
{
type: 'category',
label: 'Develop',
link: {
type: 'generated-index'
},
collapsed: true,
items: [
{
type: 'category',
label: 'Proxy',
link: {
type: 'generated-index'
},
items: [
{
type: 'autogenerated',
dirName: 'develop/proxy'
}
]
},
'develop/dev',
{
type: 'category',
label: 'Data Config',
link: {
type: 'generated-index'
},
collapsed: false,
items: [
{
type: 'autogenerated',
dirName: 'develop/data_config'
}
]
},
{
type: 'category',
label: 'Deploy',
link: {
type: 'generated-index'
},
items: [
{
type: 'autogenerated',
dirName: 'develop/deploy'
}
]
},
'develop/oneapi',
{
type: 'category',
label: 'Version Updating',
link: {
type: 'generated-index'
},
items: [
{
type: 'autogenerated',
dirName: 'develop/update'
}
]
}
]
},
{
type: 'category',
label: 'Datasets',
link: {
type: 'generated-index'
},
collapsed: false,
items: [{ type: 'autogenerated', dirName: 'datasets' }]
},
{
type: 'category',
label: 'Flow Modules',
link: {
type: 'generated-index'
},
collapsed: false,
items: [
'flow-modules/intro',
{
type: 'category',
label: 'Modules Intro',
link: {
type: 'generated-index'
},
items: [
{
type: 'autogenerated',
dirName: 'flow-modules/modules'
}
]
},
{
type: 'category',
label: 'Examples',
link: {
type: 'generated-index'
},
items: [
{
type: 'autogenerated',
dirName: 'flow-modules/examples'
}
]
}
]
},
{
type: 'category',
label: 'Other',
link: {
type: 'generated-index'
},
items: [{ type: 'autogenerated', dirName: 'other' }]
}
]
};
module.exports = sidebars;
import React from 'react';
import clsx from 'clsx';
import styles from './styles.module.css';
type FeatureItem = {
title: string;
Svg: React.ComponentType<React.ComponentProps<'svg'>>;
description: JSX.Element;
};
const FeatureList: FeatureItem[] = [
{
title: 'Easy to Use',
Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default,
description: (
<>
Docusaurus was designed from the ground up to be easily installed and used to get your
website up and running quickly.
</>
)
},
{
title: 'Focus on What Matters',
Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default,
description: (
<>
Docusaurus lets you focus on your docs, and we&apos;ll do the chores. Go ahead and move your
docs into the <code>docs</code> directory.
</>
)
},
{
title: 'Powered by React',
Svg: require('@site/static/img/undraw_docusaurus_react.svg').default,
description: (
<>
Extend or customize your website layout by reusing React. Docusaurus can be extended while
reusing the same header and footer.
</>
)
}
];
function Feature({ title, Svg, description }: FeatureItem) {
return (
<div className={clsx('col col--4')}>
<div className="text--center">
<Svg className={styles.featureSvg} role="img" />
</div>
<div className="text--center padding-horiz--md">
<h3>{title}</h3>
<p>{description}</p>
</div>
</div>
);
}
export default function HomepageFeatures(): JSX.Element {
return (
<section className={styles.features}>
<div className="container">
<div className="row">
{FeatureList.map((props, idx) => (
<Feature key={idx} {...props} />
))}
</div>
</div>
</section>
);
}
.features {
display: flex;
align-items: center;
padding: 2rem 0;
width: 100%;
}
.featureSvg {
height: 200px;
width: 200px;
}
/**
* Any CSS included here will be global. The classic template
* bundles Infima by default. Infima is a CSS framework designed to
* work well for content-centric websites.
*/
/* You can override the default Infima variables here. */
:root {
--ifm-color-primary: #2e8555;
--ifm-color-primary-dark: #29784c;
--ifm-color-primary-darker: #277148;
--ifm-color-primary-darkest: #205d3b;
--ifm-color-primary-light: #33925d;
--ifm-color-primary-lighter: #359962;
--ifm-color-primary-lightest: #3cad6e;
--ifm-code-font-size: 95%;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
}
/* For readability concerns, you should choose a lighter palette in dark mode. */
[data-theme='dark'] {
--ifm-color-primary: #25c2a0;
--ifm-color-primary-dark: #21af90;
--ifm-color-primary-darker: #1fa588;
--ifm-color-primary-darkest: #1a8870;
--ifm-color-primary-light: #29d5b0;
--ifm-color-primary-lighter: #32d8b4;
--ifm-color-primary-lightest: #4fddbf;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
}
/**
* CSS files with the .module.css suffix will be treated as CSS modules
* and scoped locally.
*/
.heroBanner {
padding: 4rem 0;
text-align: center;
position: relative;
overflow: hidden;
}
@media screen and (max-width: 996px) {
.heroBanner {
padding: 2rem;
}
}
.buttons {
display: flex;
align-items: center;
justify-content: center;
}
import React, { useEffect } from 'react';
export default function Home(): JSX.Element {
useEffect(() => {
location.replace('https://fastgpt.run');
}, []);
return <></>;
}
---
title: Markdown page example
---
# Markdown page example
You don't need React to write simple standalone pages.
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" width="256px" height="256px"><svg version="1.1" id="SvgjsSvg1001" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="256px" height="256px" viewBox="0 0 256 256" enable-background="new 0 0 256 256" xml:space="preserve"> <image id="SvgjsImage1000" width="256" height="256" x="0" y="0" href="data:image/png;base64,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
MDqUEekAAAAASUVORK5CYII="></image>
</svg><style>@media (prefers-color-scheme: light) { :root { filter: none; } }
</style></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="256.000000pt" height="256.000000pt" viewBox="0 0 256.000000 256.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,256.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M1125 2443 c-85 -12 -198 -40 -255 -61 -14 -5 -28 -10 -33 -11 -10
-1 -153 -78 -198 -107 -80 -50 -177 -137 -268 -239 -62 -69 -164 -249 -194
-340 -9 -27 -17 -52 -16 -55 0 -3 -4 -18 -10 -33 -6 -15 -13 -40 -16 -55 -2
-15 -9 -49 -14 -76 -5 -27 -10 -108 -10 -180 -1 -116 4 -165 33 -301 8 -39 44
-141 67 -190 22 -49 107 -195 118 -205 3 -3 24 -27 46 -55 95 -119 233 -229
372 -299 62 -31 117 -56 133 -61 3 0 32 -9 65 -19 143 -43 327 -58 485 -41 64
7 212 46 286 74 127 49 280 149 385 253 68 68 179 208 179 227 0 5 4 11 8 13
13 5 88 168 108 234 33 110 42 150 50 214 12 87 5 298 -11 365 -19 84 -28 115
-40 153 -49 143 -125 281 -205 369 -11 12 -20 25 -20 29 0 8 -152 154 -161
154 -3 0 -18 11 -33 24 -40 34 -176 113 -208 121 -16 4 -28 10 -28 14 0 4 -6
8 -12 9 -7 0 -33 8 -58 17 -25 9 -53 19 -62 21 -10 2 -26 6 -35 8 -10 2 -30 9
-44 14 -15 6 -29 9 -32 6 -2 -2 -27 0 -55 6 -74 16 -214 17 -317 3z"/>
</g>
</svg>
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-256x256.png",
"sizes": "256x256",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" width="256px" height="256px"><svg version="1.1" id="SvgjsSvg1001" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="256px" height="256px" viewBox="0 0 256 256" enable-background="new 0 0 256 256" xml:space="preserve"> <image id="SvgjsImage1000" width="256" height="256" x="0" y="0" href="data:image/png;base64,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
MDqUEekAAAAASUVORK5CYII="></image>
</svg><style>@media (prefers-color-scheme: light) { :root { filter: none; } }
</style></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="1088" height="687.962" viewBox="0 0 1088 687.962">
<title>Easy to Use</title>
<g id="Group_12" data-name="Group 12" transform="translate(-57 -56)">
<g id="Group_11" data-name="Group 11" transform="translate(57 56)">
<path id="Path_83" data-name="Path 83" d="M1017.81,560.461c-5.27,45.15-16.22,81.4-31.25,110.31-20,38.52-54.21,54.04-84.77,70.28a193.275,193.275,0,0,1-27.46,11.94c-55.61,19.3-117.85,14.18-166.74,3.99a657.282,657.282,0,0,0-104.09-13.16q-14.97-.675-29.97-.67c-15.42.02-293.07,5.29-360.67-131.57-16.69-33.76-28.13-75-32.24-125.27-11.63-142.12,52.29-235.46,134.74-296.47,155.97-115.41,369.76-110.57,523.43,7.88C941.15,276.621,1036.99,396.031,1017.81,560.461Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
<path id="Path_84" data-name="Path 84" d="M986.56,670.771c-20,38.52-47.21,64.04-77.77,80.28a193.272,193.272,0,0,1-27.46,11.94c-55.61,19.3-117.85,14.18-166.74,3.99a657.3,657.3,0,0,0-104.09-13.16q-14.97-.675-29.97-.67-23.13.03-46.25,1.72c-100.17,7.36-253.82-6.43-321.42-143.29L382,283.981,444.95,445.6l20.09,51.59,55.37-75.98L549,381.981l130.2,149.27,36.8-81.27L970.78,657.9l14.21,11.59Z" transform="translate(-56 -106.019)" fill="#f2f2f2"/>
<path id="Path_85" data-name="Path 85" d="M302,282.962l26-57,36,83-31-60Z" opacity="0.1"/>
<path id="Path_86" data-name="Path 86" d="M610.5,753.821q-14.97-.675-29.97-.67L465.04,497.191Z" transform="translate(-56 -106.019)" opacity="0.1"/>
<path id="Path_87" data-name="Path 87" d="M464.411,315.191,493,292.962l130,150-132-128Z" opacity="0.1"/>
<path id="Path_88" data-name="Path 88" d="M908.79,751.051a193.265,193.265,0,0,1-27.46,11.94L679.2,531.251Z" transform="translate(-56 -106.019)" opacity="0.1"/>
<circle id="Ellipse_11" data-name="Ellipse 11" cx="3" cy="3" r="3" transform="translate(479 98.962)" fill="#f2f2f2"/>
<circle id="Ellipse_12" data-name="Ellipse 12" cx="3" cy="3" r="3" transform="translate(396 201.962)" fill="#f2f2f2"/>
<circle id="Ellipse_13" data-name="Ellipse 13" cx="2" cy="2" r="2" transform="translate(600 220.962)" fill="#f2f2f2"/>
<circle id="Ellipse_14" data-name="Ellipse 14" cx="2" cy="2" r="2" transform="translate(180 265.962)" fill="#f2f2f2"/>
<circle id="Ellipse_15" data-name="Ellipse 15" cx="2" cy="2" r="2" transform="translate(612 96.962)" fill="#f2f2f2"/>
<circle id="Ellipse_16" data-name="Ellipse 16" cx="2" cy="2" r="2" transform="translate(736 192.962)" fill="#f2f2f2"/>
<circle id="Ellipse_17" data-name="Ellipse 17" cx="2" cy="2" r="2" transform="translate(858 344.962)" fill="#f2f2f2"/>
<path id="Path_89" data-name="Path 89" d="M306,121.222h-2.76v-2.76h-1.48v2.76H299V122.7h2.76v2.759h1.48V122.7H306Z" fill="#f2f2f2"/>
<path id="Path_90" data-name="Path 90" d="M848,424.222h-2.76v-2.76h-1.48v2.76H841V425.7h2.76v2.759h1.48V425.7H848Z" fill="#f2f2f2"/>
<path id="Path_91" data-name="Path 91" d="M1144,719.981c0,16.569-243.557,74-544,74s-544-57.431-544-74,243.557,14,544,14S1144,703.413,1144,719.981Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
<path id="Path_92" data-name="Path 92" d="M1144,719.981c0,16.569-243.557,74-544,74s-544-57.431-544-74,243.557,14,544,14S1144,703.413,1144,719.981Z" transform="translate(-56 -106.019)" opacity="0.1"/>
<ellipse id="Ellipse_18" data-name="Ellipse 18" cx="544" cy="30" rx="544" ry="30" transform="translate(0 583.962)" fill="#3f3d56"/>
<path id="Path_93" data-name="Path 93" d="M624,677.981c0,33.137-14.775,24-33,24s-33,9.137-33-24,33-96,33-96S624,644.844,624,677.981Z" transform="translate(-56 -106.019)" fill="#ff6584"/>
<path id="Path_94" data-name="Path 94" d="M606,690.66c0,15.062-6.716,10.909-15,10.909s-15,4.153-15-10.909,15-43.636,15-43.636S606,675.6,606,690.66Z" transform="translate(-56 -106.019)" opacity="0.1"/>
<rect id="Rectangle_97" data-name="Rectangle 97" width="92" height="18" rx="9" transform="translate(489 604.962)" fill="#2f2e41"/>
<rect id="Rectangle_98" data-name="Rectangle 98" width="92" height="18" rx="9" transform="translate(489 586.962)" fill="#2f2e41"/>
<path id="Path_95" data-name="Path 95" d="M193,596.547c0,55.343,34.719,100.126,77.626,100.126" transform="translate(-56 -106.019)" fill="#3f3d56"/>
<path id="Path_96" data-name="Path 96" d="M270.626,696.673c0-55.965,38.745-101.251,86.626-101.251" transform="translate(-56 -106.019)" fill="#6c63ff"/>
<path id="Path_97" data-name="Path 97" d="M221.125,601.564c0,52.57,22.14,95.109,49.5,95.109" transform="translate(-56 -106.019)" fill="#6c63ff"/>
<path id="Path_98" data-name="Path 98" d="M270.626,696.673c0-71.511,44.783-129.377,100.126-129.377" transform="translate(-56 -106.019)" fill="#3f3d56"/>
<path id="Path_99" data-name="Path 99" d="M254.3,697.379s11.009-.339,14.326-2.7,16.934-5.183,17.757-1.395,16.544,18.844,4.115,18.945-28.879-1.936-32.19-3.953S254.3,697.379,254.3,697.379Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
<path id="Path_100" data-name="Path 100" d="M290.716,710.909c-12.429.1-28.879-1.936-32.19-3.953-2.522-1.536-3.527-7.048-3.863-9.591l-.368.014s.7,8.879,4.009,10.9,19.761,4.053,32.19,3.953c3.588-.029,4.827-1.305,4.759-3.2C294.755,710.174,293.386,710.887,290.716,710.909Z" transform="translate(-56 -106.019)" opacity="0.2"/>
<path id="Path_101" data-name="Path 101" d="M777.429,633.081c0,38.029,23.857,68.8,53.341,68.8" transform="translate(-56 -106.019)" fill="#3f3d56"/>
<path id="Path_102" data-name="Path 102" d="M830.769,701.882c0-38.456,26.623-69.575,59.525-69.575" transform="translate(-56 -106.019)" fill="#6c63ff"/>
<path id="Path_103" data-name="Path 103" d="M796.755,636.528c0,36.124,15.213,65.354,34.014,65.354" transform="translate(-56 -106.019)" fill="#6c63ff"/>
<path id="Path_104" data-name="Path 104" d="M830.769,701.882c0-49.139,30.773-88.9,68.8-88.9" transform="translate(-56 -106.019)" fill="#3f3d56"/>
<path id="Path_105" data-name="Path 105" d="M819.548,702.367s7.565-.233,9.844-1.856,11.636-3.562,12.2-.958,11.368,12.949,2.828,13.018-19.844-1.33-22.119-2.716S819.548,702.367,819.548,702.367Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
<path id="Path_106" data-name="Path 106" d="M844.574,711.664c-8.54.069-19.844-1.33-22.119-2.716-1.733-1.056-2.423-4.843-2.654-6.59l-.253.01s.479,6.1,2.755,7.487,13.579,2.785,22.119,2.716c2.465-.02,3.317-.9,3.27-2.2C847.349,711.159,846.409,711.649,844.574,711.664Z" transform="translate(-56 -106.019)" opacity="0.2"/>
<path id="Path_107" data-name="Path 107" d="M949.813,724.718s11.36-1.729,14.5-4.591,16.89-7.488,18.217-3.667,19.494,17.447,6.633,19.107-30.153,1.609-33.835-.065S949.813,724.718,949.813,724.718Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
<path id="Path_108" data-name="Path 108" d="M989.228,734.173c-12.86,1.659-30.153,1.609-33.835-.065-2.8-1.275-4.535-6.858-5.2-9.45l-.379.061s1.833,9.109,5.516,10.783,20.975,1.725,33.835.065c3.712-.479,4.836-1.956,4.529-3.906C993.319,732.907,991.991,733.817,989.228,734.173Z" transform="translate(-56 -106.019)" opacity="0.2"/>
<path id="Path_109" data-name="Path 109" d="M670.26,723.9s9.587-1.459,12.237-3.875,14.255-6.32,15.374-3.095,16.452,14.725,5.6,16.125-25.448,1.358-28.555-.055S670.26,723.9,670.26,723.9Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
<path id="Path_110" data-name="Path 110" d="M703.524,731.875c-10.853,1.4-25.448,1.358-28.555-.055-2.367-1.076-3.827-5.788-4.39-7.976l-.32.051s1.547,7.687,4.655,9.1,17.7,1.456,28.555.055c3.133-.4,4.081-1.651,3.822-3.3C706.977,730.807,705.856,731.575,703.524,731.875Z" transform="translate(-56 -106.019)" opacity="0.2"/>
<path id="Path_111" data-name="Path 111" d="M178.389,719.109s7.463-1.136,9.527-3.016,11.1-4.92,11.969-2.409,12.808,11.463,4.358,12.553-19.811,1.057-22.23-.043S178.389,719.109,178.389,719.109Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
<path id="Path_112" data-name="Path 112" d="M204.285,725.321c-8.449,1.09-19.811,1.057-22.23-.043-1.842-.838-2.979-4.506-3.417-6.209l-.249.04s1.2,5.984,3.624,7.085,13.781,1.133,22.23.043c2.439-.315,3.177-1.285,2.976-2.566C206.973,724.489,206.1,725.087,204.285,725.321Z" transform="translate(-56 -106.019)" opacity="0.2"/>
<path id="Path_113" data-name="Path 113" d="M439.7,707.337c0,30.22-42.124,20.873-93.7,20.873s-93.074,9.347-93.074-20.873,42.118-36.793,93.694-36.793S439.7,677.117,439.7,707.337Z" transform="translate(-56 -106.019)" opacity="0.1"/>
<path id="Path_114" data-name="Path 114" d="M439.7,699.9c0,30.22-42.124,20.873-93.7,20.873s-93.074,9.347-93.074-20.873S295.04,663.1,346.616,663.1,439.7,669.676,439.7,699.9Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
</g>
<g id="docusaurus_keytar" transform="translate(312.271 493.733)">
<path id="Path_40" data-name="Path 40" d="M99,52h91.791V89.153H99Z" transform="translate(5.904 -14.001)" fill="#fff" fill-rule="evenodd"/>
<path id="Path_41" data-name="Path 41" d="M24.855,163.927A21.828,21.828,0,0,1,5.947,153a21.829,21.829,0,0,0,18.908,32.782H46.71V163.927Z" transform="translate(-3 -4.634)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_42" data-name="Path 42" d="M121.861,61.1l76.514-4.782V45.39A21.854,21.854,0,0,0,176.52,23.535H78.173L75.441,18.8a3.154,3.154,0,0,0-5.464,0l-2.732,4.732L64.513,18.8a3.154,3.154,0,0,0-5.464,0l-2.732,4.732L53.586,18.8a3.154,3.154,0,0,0-5.464,0L45.39,23.535c-.024,0-.046,0-.071,0l-4.526-4.525a3.153,3.153,0,0,0-5.276,1.414l-1.5,5.577-5.674-1.521a3.154,3.154,0,0,0-3.863,3.864L26,34.023l-5.575,1.494a3.155,3.155,0,0,0-1.416,5.278l4.526,4.526c0,.023,0,.046,0,.07L18.8,48.122a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,59.05a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,69.977a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,80.9a3.154,3.154,0,0,0,0,5.464L23.535,89.1,18.8,91.832a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,102.76a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,113.687a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,124.615a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,135.542a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,146.469a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,157.4a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,168.324a3.154,3.154,0,0,0,0,5.464l4.732,2.732A21.854,21.854,0,0,0,45.39,198.375H176.52a21.854,21.854,0,0,0,21.855-21.855V89.1l-76.514-4.782a11.632,11.632,0,0,1,0-23.219" transform="translate(-1.681 -17.226)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_43" data-name="Path 43" d="M143,186.71h32.782V143H143Z" transform="translate(9.984 -5.561)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_44" data-name="Path 44" d="M196.71,159.855a5.438,5.438,0,0,0-.7.07c-.042-.164-.081-.329-.127-.493a5.457,5.457,0,1,0-5.4-9.372q-.181-.185-.366-.367a5.454,5.454,0,1,0-9.384-5.4c-.162-.046-.325-.084-.486-.126a5.467,5.467,0,1,0-10.788,0c-.162.042-.325.08-.486.126a5.457,5.457,0,1,0-9.384,5.4,21.843,21.843,0,1,0,36.421,21.02,5.452,5.452,0,1,0,.7-10.858" transform="translate(10.912 -6.025)" fill="#44d860" fill-rule="evenodd"/>
<path id="Path_45" data-name="Path 45" d="M153,124.855h32.782V103H153Z" transform="translate(10.912 -9.271)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_46" data-name="Path 46" d="M194.855,116.765a2.732,2.732,0,1,0,0-5.464,2.811,2.811,0,0,0-.349.035c-.022-.082-.04-.164-.063-.246a2.733,2.733,0,0,0-1.052-5.253,2.7,2.7,0,0,0-1.648.566q-.09-.093-.184-.184a2.7,2.7,0,0,0,.553-1.633,2.732,2.732,0,0,0-5.245-1.07,10.928,10.928,0,1,0,0,21.031,2.732,2.732,0,0,0,5.245-1.07,2.7,2.7,0,0,0-.553-1.633q.093-.09.184-.184a2.7,2.7,0,0,0,1.648.566,2.732,2.732,0,0,0,1.052-5.253c.023-.081.042-.164.063-.246a2.814,2.814,0,0,0,.349.035" transform="translate(12.767 -9.377)" fill="#44d860" fill-rule="evenodd"/>
<path id="Path_47" data-name="Path 47" d="M65.087,56.891a2.732,2.732,0,0,1-2.732-2.732,8.2,8.2,0,0,0-16.391,0,2.732,2.732,0,0,1-5.464,0,13.659,13.659,0,0,1,27.319,0,2.732,2.732,0,0,1-2.732,2.732" transform="translate(0.478 -15.068)" fill-rule="evenodd"/>
<path id="Path_48" data-name="Path 48" d="M103,191.347h65.565a21.854,21.854,0,0,0,21.855-21.855V93H124.855A21.854,21.854,0,0,0,103,114.855Z" transform="translate(6.275 -10.199)" fill="#ffff50" fill-rule="evenodd"/>
<path id="Path_49" data-name="Path 49" d="M173.216,129.787H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0,21.855H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186m0,21.855H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0-54.434H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0,21.652H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186m0,21.855H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186M189.585,61.611c-.013,0-.024-.007-.037-.005-3.377.115-4.974,3.492-6.384,6.472-1.471,3.114-2.608,5.139-4.473,5.078-2.064-.074-3.244-2.406-4.494-4.874-1.436-2.835-3.075-6.049-6.516-5.929-3.329.114-4.932,3.053-6.346,5.646-1.5,2.762-2.529,4.442-4.5,4.364-2.106-.076-3.225-1.972-4.52-4.167-1.444-2.443-3.112-5.191-6.487-5.1-3.272.113-4.879,2.606-6.3,4.808-1.5,2.328-2.552,3.746-4.551,3.662-2.156-.076-3.27-1.65-4.558-3.472-1.447-2.047-3.077-4.363-6.442-4.251-3.2.109-4.807,2.153-6.224,3.954-1.346,1.709-2.4,3.062-4.621,2.977a1.093,1.093,0,0,0-.079,2.186c3.3.11,4.967-1.967,6.417-3.81,1.286-1.635,2.4-3.045,4.582-3.12,2.1-.09,3.091,1.218,4.584,3.327,1.417,2,3.026,4.277,6.263,4.394,3.391.114,5.022-2.42,6.467-4.663,1.292-2,2.406-3.734,4.535-3.807,1.959-.073,3.026,1.475,4.529,4.022,1.417,2.4,3.023,5.121,6.324,5.241,3.415.118,5.064-2.863,6.5-5.5,1.245-2.282,2.419-4.437,4.5-4.509,1.959-.046,2.981,1.743,4.492,4.732,1.412,2.79,3.013,5.95,6.365,6.071l.185,0c3.348,0,4.937-3.36,6.343-6.331,1.245-2.634,2.423-5.114,4.444-5.216Z" transform="translate(7.109 -13.11)" fill-rule="evenodd"/>
<path id="Path_50" data-name="Path 50" d="M83,186.71h43.71V143H83Z" transform="translate(4.42 -5.561)" fill="#3ecc5f" fill-rule="evenodd"/>
<g id="Group_8" data-name="Group 8" transform="matrix(0.966, -0.259, 0.259, 0.966, 109.327, 91.085)">
<rect id="Rectangle_3" data-name="Rectangle 3" width="92.361" height="36.462" rx="2" transform="translate(0 0)" fill="#d8d8d8"/>
<g id="Group_2" data-name="Group 2" transform="translate(1.531 23.03)">
<rect id="Rectangle_4" data-name="Rectangle 4" width="5.336" height="5.336" rx="1" transform="translate(16.797 0)" fill="#4a4a4a"/>
<rect id="Rectangle_5" data-name="Rectangle 5" width="5.336" height="5.336" rx="1" transform="translate(23.12 0)" fill="#4a4a4a"/>
<rect id="Rectangle_6" data-name="Rectangle 6" width="5.336" height="5.336" rx="1" transform="translate(29.444 0)" fill="#4a4a4a"/>
<rect id="Rectangle_7" data-name="Rectangle 7" width="5.336" height="5.336" rx="1" transform="translate(35.768 0)" fill="#4a4a4a"/>
<rect id="Rectangle_8" data-name="Rectangle 8" width="5.336" height="5.336" rx="1" transform="translate(42.091 0)" fill="#4a4a4a"/>
<rect id="Rectangle_9" data-name="Rectangle 9" width="5.336" height="5.336" rx="1" transform="translate(48.415 0)" fill="#4a4a4a"/>
<rect id="Rectangle_10" data-name="Rectangle 10" width="5.336" height="5.336" rx="1" transform="translate(54.739 0)" fill="#4a4a4a"/>
<rect id="Rectangle_11" data-name="Rectangle 11" width="5.336" height="5.336" rx="1" transform="translate(61.063 0)" fill="#4a4a4a"/>
<rect id="Rectangle_12" data-name="Rectangle 12" width="5.336" height="5.336" rx="1" transform="translate(67.386 0)" fill="#4a4a4a"/>
<path id="Path_51" data-name="Path 51" d="M1.093,0H14.518a1.093,1.093,0,0,1,1.093,1.093V4.243a1.093,1.093,0,0,1-1.093,1.093H1.093A1.093,1.093,0,0,1,0,4.243V1.093A1.093,1.093,0,0,1,1.093,0ZM75,0H88.426a1.093,1.093,0,0,1,1.093,1.093V4.243a1.093,1.093,0,0,1-1.093,1.093H75a1.093,1.093,0,0,1-1.093-1.093V1.093A1.093,1.093,0,0,1,75,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
</g>
<g id="Group_3" data-name="Group 3" transform="translate(1.531 10.261)">
<path id="Path_52" data-name="Path 52" d="M1.093,0H6.218A1.093,1.093,0,0,1,7.31,1.093V4.242A1.093,1.093,0,0,1,6.218,5.335H1.093A1.093,1.093,0,0,1,0,4.242V1.093A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
<rect id="Rectangle_13" data-name="Rectangle 13" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
<rect id="Rectangle_14" data-name="Rectangle 14" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
<rect id="Rectangle_15" data-name="Rectangle 15" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
<rect id="Rectangle_16" data-name="Rectangle 16" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
<rect id="Rectangle_17" data-name="Rectangle 17" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
<rect id="Rectangle_18" data-name="Rectangle 18" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
<rect id="Rectangle_19" data-name="Rectangle 19" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
<rect id="Rectangle_20" data-name="Rectangle 20" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
<rect id="Rectangle_21" data-name="Rectangle 21" width="5.336" height="5.336" rx="1" transform="translate(58.888 0)" fill="#4a4a4a"/>
<rect id="Rectangle_22" data-name="Rectangle 22" width="5.336" height="5.336" rx="1" transform="translate(65.212 0)" fill="#4a4a4a"/>
<rect id="Rectangle_23" data-name="Rectangle 23" width="5.336" height="5.336" rx="1" transform="translate(71.536 0)" fill="#4a4a4a"/>
<rect id="Rectangle_24" data-name="Rectangle 24" width="5.336" height="5.336" rx="1" transform="translate(77.859 0)" fill="#4a4a4a"/>
<rect id="Rectangle_25" data-name="Rectangle 25" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
</g>
<g id="Group_4" data-name="Group 4" transform="translate(91.05 9.546) rotate(180)">
<path id="Path_53" data-name="Path 53" d="M1.093,0H6.219A1.093,1.093,0,0,1,7.312,1.093v3.15A1.093,1.093,0,0,1,6.219,5.336H1.093A1.093,1.093,0,0,1,0,4.243V1.093A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
<rect id="Rectangle_26" data-name="Rectangle 26" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
<rect id="Rectangle_27" data-name="Rectangle 27" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
<rect id="Rectangle_28" data-name="Rectangle 28" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
<rect id="Rectangle_29" data-name="Rectangle 29" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
<rect id="Rectangle_30" data-name="Rectangle 30" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
<rect id="Rectangle_31" data-name="Rectangle 31" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
<rect id="Rectangle_32" data-name="Rectangle 32" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
<rect id="Rectangle_33" data-name="Rectangle 33" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
<rect id="Rectangle_34" data-name="Rectangle 34" width="5.336" height="5.336" rx="1" transform="translate(58.889 0)" fill="#4a4a4a"/>
<rect id="Rectangle_35" data-name="Rectangle 35" width="5.336" height="5.336" rx="1" transform="translate(65.213 0)" fill="#4a4a4a"/>
<rect id="Rectangle_36" data-name="Rectangle 36" width="5.336" height="5.336" rx="1" transform="translate(71.537 0)" fill="#4a4a4a"/>
<rect id="Rectangle_37" data-name="Rectangle 37" width="5.336" height="5.336" rx="1" transform="translate(77.86 0)" fill="#4a4a4a"/>
<rect id="Rectangle_38" data-name="Rectangle 38" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
<rect id="Rectangle_39" data-name="Rectangle 39" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
<rect id="Rectangle_40" data-name="Rectangle 40" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
<rect id="Rectangle_41" data-name="Rectangle 41" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
<rect id="Rectangle_42" data-name="Rectangle 42" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
<rect id="Rectangle_43" data-name="Rectangle 43" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
<rect id="Rectangle_44" data-name="Rectangle 44" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
<rect id="Rectangle_45" data-name="Rectangle 45" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
<rect id="Rectangle_46" data-name="Rectangle 46" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
<rect id="Rectangle_47" data-name="Rectangle 47" width="5.336" height="5.336" rx="1" transform="translate(58.889 0)" fill="#4a4a4a"/>
<rect id="Rectangle_48" data-name="Rectangle 48" width="5.336" height="5.336" rx="1" transform="translate(65.213 0)" fill="#4a4a4a"/>
<rect id="Rectangle_49" data-name="Rectangle 49" width="5.336" height="5.336" rx="1" transform="translate(71.537 0)" fill="#4a4a4a"/>
<rect id="Rectangle_50" data-name="Rectangle 50" width="5.336" height="5.336" rx="1" transform="translate(77.86 0)" fill="#4a4a4a"/>
<rect id="Rectangle_51" data-name="Rectangle 51" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
</g>
<g id="Group_6" data-name="Group 6" transform="translate(1.531 16.584)">
<path id="Path_54" data-name="Path 54" d="M1.093,0h7.3A1.093,1.093,0,0,1,9.485,1.093v3.15A1.093,1.093,0,0,1,8.392,5.336h-7.3A1.093,1.093,0,0,1,0,4.243V1.094A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
<g id="Group_5" data-name="Group 5" transform="translate(10.671 0)">
<rect id="Rectangle_52" data-name="Rectangle 52" width="5.336" height="5.336" rx="1" fill="#4a4a4a"/>
<rect id="Rectangle_53" data-name="Rectangle 53" width="5.336" height="5.336" rx="1" transform="translate(6.324 0)" fill="#4a4a4a"/>
<rect id="Rectangle_54" data-name="Rectangle 54" width="5.336" height="5.336" rx="1" transform="translate(12.647 0)" fill="#4a4a4a"/>
<rect id="Rectangle_55" data-name="Rectangle 55" width="5.336" height="5.336" rx="1" transform="translate(18.971 0)" fill="#4a4a4a"/>
<rect id="Rectangle_56" data-name="Rectangle 56" width="5.336" height="5.336" rx="1" transform="translate(25.295 0)" fill="#4a4a4a"/>
<rect id="Rectangle_57" data-name="Rectangle 57" width="5.336" height="5.336" rx="1" transform="translate(31.619 0)" fill="#4a4a4a"/>
<rect id="Rectangle_58" data-name="Rectangle 58" width="5.336" height="5.336" rx="1" transform="translate(37.942 0)" fill="#4a4a4a"/>
<rect id="Rectangle_59" data-name="Rectangle 59" width="5.336" height="5.336" rx="1" transform="translate(44.265 0)" fill="#4a4a4a"/>
<rect id="Rectangle_60" data-name="Rectangle 60" width="5.336" height="5.336" rx="1" transform="translate(50.589 0)" fill="#4a4a4a"/>
<rect id="Rectangle_61" data-name="Rectangle 61" width="5.336" height="5.336" rx="1" transform="translate(56.912 0)" fill="#4a4a4a"/>
<rect id="Rectangle_62" data-name="Rectangle 62" width="5.336" height="5.336" rx="1" transform="translate(63.236 0)" fill="#4a4a4a"/>
</g>
<path id="Path_55" data-name="Path 55" d="M1.094,0H8A1.093,1.093,0,0,1,9.091,1.093v3.15A1.093,1.093,0,0,1,8,5.336H1.093A1.093,1.093,0,0,1,0,4.243V1.094A1.093,1.093,0,0,1,1.093,0Z" transform="translate(80.428 0)" fill="#4a4a4a" fill-rule="evenodd"/>
</g>
<g id="Group_7" data-name="Group 7" transform="translate(1.531 29.627)">
<rect id="Rectangle_63" data-name="Rectangle 63" width="5.336" height="5.336" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
<rect id="Rectangle_64" data-name="Rectangle 64" width="5.336" height="5.336" rx="1" transform="translate(6.324 0)" fill="#4a4a4a"/>
<rect id="Rectangle_65" data-name="Rectangle 65" width="5.336" height="5.336" rx="1" transform="translate(12.647 0)" fill="#4a4a4a"/>
<rect id="Rectangle_66" data-name="Rectangle 66" width="5.336" height="5.336" rx="1" transform="translate(18.971 0)" fill="#4a4a4a"/>
<path id="Path_56" data-name="Path 56" d="M1.093,0H31.515a1.093,1.093,0,0,1,1.093,1.093V4.244a1.093,1.093,0,0,1-1.093,1.093H1.093A1.093,1.093,0,0,1,0,4.244V1.093A1.093,1.093,0,0,1,1.093,0ZM34.687,0h3.942a1.093,1.093,0,0,1,1.093,1.093V4.244a1.093,1.093,0,0,1-1.093,1.093H34.687a1.093,1.093,0,0,1-1.093-1.093V1.093A1.093,1.093,0,0,1,34.687,0Z" transform="translate(25.294 0)" fill="#4a4a4a" fill-rule="evenodd"/>
<rect id="Rectangle_67" data-name="Rectangle 67" width="5.336" height="5.336" rx="1" transform="translate(66.003 0)" fill="#4a4a4a"/>
<rect id="Rectangle_68" data-name="Rectangle 68" width="5.336" height="5.336" rx="1" transform="translate(72.327 0)" fill="#4a4a4a"/>
<rect id="Rectangle_69" data-name="Rectangle 69" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
<path id="Path_57" data-name="Path 57" d="M5.336,0V1.18A1.093,1.093,0,0,1,4.243,2.273H1.093A1.093,1.093,0,0,1,0,1.18V0Z" transform="translate(83.59 2.273) rotate(180)" fill="#4a4a4a"/>
<path id="Path_58" data-name="Path 58" d="M5.336,0V1.18A1.093,1.093,0,0,1,4.243,2.273H1.093A1.093,1.093,0,0,1,0,1.18V0Z" transform="translate(78.255 3.063)" fill="#4a4a4a"/>
</g>
<rect id="Rectangle_70" data-name="Rectangle 70" width="88.927" height="2.371" rx="1.085" transform="translate(1.925 1.17)" fill="#4a4a4a"/>
<rect id="Rectangle_71" data-name="Rectangle 71" width="4.986" height="1.581" rx="0.723" transform="translate(4.1 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_72" data-name="Rectangle 72" width="4.986" height="1.581" rx="0.723" transform="translate(10.923 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_73" data-name="Rectangle 73" width="4.986" height="1.581" rx="0.723" transform="translate(16.173 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_74" data-name="Rectangle 74" width="4.986" height="1.581" rx="0.723" transform="translate(21.421 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_75" data-name="Rectangle 75" width="4.986" height="1.581" rx="0.723" transform="translate(26.671 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_76" data-name="Rectangle 76" width="4.986" height="1.581" rx="0.723" transform="translate(33.232 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_77" data-name="Rectangle 77" width="4.986" height="1.581" rx="0.723" transform="translate(38.48 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_78" data-name="Rectangle 78" width="4.986" height="1.581" rx="0.723" transform="translate(43.73 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_79" data-name="Rectangle 79" width="4.986" height="1.581" rx="0.723" transform="translate(48.978 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_80" data-name="Rectangle 80" width="4.986" height="1.581" rx="0.723" transform="translate(55.54 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_81" data-name="Rectangle 81" width="4.986" height="1.581" rx="0.723" transform="translate(60.788 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_82" data-name="Rectangle 82" width="4.986" height="1.581" rx="0.723" transform="translate(66.038 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_83" data-name="Rectangle 83" width="4.986" height="1.581" rx="0.723" transform="translate(72.599 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_84" data-name="Rectangle 84" width="4.986" height="1.581" rx="0.723" transform="translate(77.847 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_85" data-name="Rectangle 85" width="4.986" height="1.581" rx="0.723" transform="translate(83.097 1.566)" fill="#d8d8d8" opacity="0.136"/>
</g>
<path id="Path_59" data-name="Path 59" d="M146.71,159.855a5.439,5.439,0,0,0-.7.07c-.042-.164-.081-.329-.127-.493a5.457,5.457,0,1,0-5.4-9.372q-.181-.185-.366-.367a5.454,5.454,0,1,0-9.384-5.4c-.162-.046-.325-.084-.486-.126a5.467,5.467,0,1,0-10.788,0c-.162.042-.325.08-.486.126a5.457,5.457,0,1,0-9.384,5.4,21.843,21.843,0,1,0,36.421,21.02,5.452,5.452,0,1,0,.7-10.858" transform="translate(6.275 -6.025)" fill="#44d860" fill-rule="evenodd"/>
<path id="Path_60" data-name="Path 60" d="M83,124.855h43.71V103H83Z" transform="translate(4.42 -9.271)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_61" data-name="Path 61" d="M134.855,116.765a2.732,2.732,0,1,0,0-5.464,2.811,2.811,0,0,0-.349.035c-.022-.082-.04-.164-.063-.246a2.733,2.733,0,0,0-1.052-5.253,2.7,2.7,0,0,0-1.648.566q-.09-.093-.184-.184a2.7,2.7,0,0,0,.553-1.633,2.732,2.732,0,0,0-5.245-1.07,10.928,10.928,0,1,0,0,21.031,2.732,2.732,0,0,0,5.245-1.07,2.7,2.7,0,0,0-.553-1.633q.093-.09.184-.184a2.7,2.7,0,0,0,1.648.566,2.732,2.732,0,0,0,1.052-5.253c.023-.081.042-.164.063-.246a2.811,2.811,0,0,0,.349.035" transform="translate(7.202 -9.377)" fill="#44d860" fill-rule="evenodd"/>
<path id="Path_62" data-name="Path 62" d="M143.232,42.33a2.967,2.967,0,0,1-.535-.055,2.754,2.754,0,0,1-.514-.153,2.838,2.838,0,0,1-.471-.251,4.139,4.139,0,0,1-.415-.339,3.2,3.2,0,0,1-.338-.415A2.7,2.7,0,0,1,140.5,39.6a2.968,2.968,0,0,1,.055-.535,3.152,3.152,0,0,1,.152-.514,2.874,2.874,0,0,1,.252-.47,2.633,2.633,0,0,1,.753-.754,2.837,2.837,0,0,1,.471-.251,2.753,2.753,0,0,1,.514-.153,2.527,2.527,0,0,1,1.071,0,2.654,2.654,0,0,1,.983.4,4.139,4.139,0,0,1,.415.339,4.019,4.019,0,0,1,.339.415,2.786,2.786,0,0,1,.251.47,2.864,2.864,0,0,1,.208,1.049,2.77,2.77,0,0,1-.8,1.934,4.139,4.139,0,0,1-.415.339,2.722,2.722,0,0,1-1.519.459m21.855-1.366a2.789,2.789,0,0,1-1.935-.8,4.162,4.162,0,0,1-.338-.415,2.7,2.7,0,0,1-.459-1.519,2.789,2.789,0,0,1,.8-1.934,4.139,4.139,0,0,1,.415-.339,2.838,2.838,0,0,1,.471-.251,2.752,2.752,0,0,1,.514-.153,2.527,2.527,0,0,1,1.071,0,2.654,2.654,0,0,1,.983.4,4.139,4.139,0,0,1,.415.339,2.79,2.79,0,0,1,.8,1.934,3.069,3.069,0,0,1-.055.535,2.779,2.779,0,0,1-.153.514,3.885,3.885,0,0,1-.251.47,4.02,4.02,0,0,1-.339.415,4.138,4.138,0,0,1-.415.339,2.722,2.722,0,0,1-1.519.459" transform="translate(9.753 -15.532)" fill-rule="evenodd"/>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="1041.277" height="554.141" viewBox="0 0 1041.277 554.141">
<title>Powered by React</title>
<g id="Group_24" data-name="Group 24" transform="translate(-440 -263)">
<g id="Group_23" data-name="Group 23" transform="translate(439.989 262.965)">
<path id="Path_299" data-name="Path 299" d="M1040.82,611.12q-1.74,3.75-3.47,7.4-2.7,5.67-5.33,11.12c-.78,1.61-1.56,3.19-2.32,4.77-8.6,17.57-16.63,33.11-23.45,45.89A73.21,73.21,0,0,1,942.44,719l-151.65,1.65h-1.6l-13,.14-11.12.12-34.1.37h-1.38l-17.36.19h-.53l-107,1.16-95.51,1-11.11.12-69,.75H429l-44.75.48h-.48l-141.5,1.53-42.33.46a87.991,87.991,0,0,1-10.79-.54h0c-1.22-.14-2.44-.3-3.65-.49a87.38,87.38,0,0,1-51.29-27.54C116,678.37,102.75,655,93.85,629.64q-1.93-5.49-3.6-11.12C59.44,514.37,97,380,164.6,290.08q4.25-5.64,8.64-11l.07-.08c20.79-25.52,44.1-46.84,68.93-62,44-26.91,92.75-34.49,140.7-11.9,40.57,19.12,78.45,28.11,115.17,30.55,3.71.24,7.42.42,11.11.53,84.23,2.65,163.17-27.7,255.87-47.29,3.69-.78,7.39-1.55,11.12-2.28,66.13-13.16,139.49-20.1,226.73-5.51a189.089,189.089,0,0,1,26.76,6.4q5.77,1.86,11.12,4c41.64,16.94,64.35,48.24,74,87.46q1.37,5.46,2.37,11.11C1134.3,384.41,1084.19,518.23,1040.82,611.12Z" transform="translate(-79.34 -172.91)" fill="#f2f2f2"/>
<path id="Path_300" data-name="Path 300" d="M576.36,618.52a95.21,95.21,0,0,1-1.87,11.12h93.7V618.52Zm-78.25,62.81,11.11-.09V653.77c-3.81-.17-7.52-.34-11.11-.52ZM265.19,618.52v11.12h198.5V618.52ZM1114.87,279h-74V191.51q-5.35-2.17-11.12-4V279H776.21V186.58c-3.73.73-7.43,1.5-11.12,2.28V279H509.22V236.15c-3.69-.11-7.4-.29-11.11-.53V279H242.24V217c-24.83,15.16-48.14,36.48-68.93,62h-.07v.08q-4.4,5.4-8.64,11h8.64V618.52h-83q1.66,5.63,3.6,11.12h79.39v93.62a87,87,0,0,0,12.2,2.79c1.21.19,2.43.35,3.65.49h0a87.991,87.991,0,0,0,10.79.54l42.33-.46v-97H498.11v94.21l11.11-.12V629.64H765.09V721l11.12-.12V629.64H1029.7v4.77c.76-1.58,1.54-3.16,2.32-4.77q2.63-5.45,5.33-11.12,1.73-3.64,3.47-7.4v-321h76.42Q1116.23,284.43,1114.87,279ZM242.24,618.52V290.08H498.11V618.52Zm267,0V290.08H765.09V618.52Zm520.48,0H776.21V290.08H1029.7Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
<path id="Path_301" data-name="Path 301" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l46.65-28,93.6-.78,2-.01.66-.01,2-.03,44.94-.37,2.01-.01.64-.01,2-.01L315,509.3l.38-.01,35.55-.3h.29l277.4-2.34,6.79-.05h.68l5.18-.05,37.65-.31,2-.03,1.85-.02h.96l11.71-.09,2.32-.03,3.11-.02,9.75-.09,15.47-.13,2-.02,3.48-.02h.65l74.71-.64Z" fill="#65617d"/>
<path id="Path_302" data-name="Path 302" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l46.65-28,93.6-.78,2-.01.66-.01,2-.03,44.94-.37,2.01-.01.64-.01,2-.01L315,509.3l.38-.01,35.55-.3h.29l277.4-2.34,6.79-.05h.68l5.18-.05,37.65-.31,2-.03,1.85-.02h.96l11.71-.09,2.32-.03,3.11-.02,9.75-.09,15.47-.13,2-.02,3.48-.02h.65l74.71-.64Z" opacity="0.2"/>
<path id="Path_303" data-name="Path 303" d="M375.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
<path id="Path_304" data-name="Path 304" d="M375.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
<path id="Path_305" data-name="Path 305" d="M377.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
<rect id="Rectangle_137" data-name="Rectangle 137" width="47.17" height="31.5" transform="translate(680.92 483.65)" fill="#3f3d56"/>
<rect id="Rectangle_138" data-name="Rectangle 138" width="47.17" height="31.5" transform="translate(680.92 483.65)" opacity="0.1"/>
<rect id="Rectangle_139" data-name="Rectangle 139" width="47.17" height="31.5" transform="translate(678.92 483.65)" fill="#3f3d56"/>
<path id="Path_306" data-name="Path 306" d="M298.09,483.65v4.97l-47.17,1.26v-6.23Z" opacity="0.1"/>
<path id="Path_307" data-name="Path 307" d="M460.69,485.27v168.2a4,4,0,0,1-3.85,3.95l-191.65,5.1h-.05a4,4,0,0,1-3.95-3.95V485.27a4,4,0,0,1,3.95-3.95h191.6a4,4,0,0,1,3.95,3.95Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
<path id="Path_308" data-name="Path 308" d="M265.19,481.32v181.2h-.05a4,4,0,0,1-3.95-3.95V485.27a4,4,0,0,1,3.95-3.95Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
<path id="Path_309" data-name="Path 309" d="M194.59,319.15h177.5V467.4l-177.5,4Z" fill="#39374d"/>
<path id="Path_310" data-name="Path 310" d="M726.09,483.65v6.41l-47.17-1.26v-5.15Z" opacity="0.1"/>
<path id="Path_311" data-name="Path 311" d="M867.69,485.27v173.3a4,4,0,0,1-4,3.95h0L672,657.42a4,4,0,0,1-3.85-3.95V485.27a4,4,0,0,1,3.95-3.95H863.7a4,4,0,0,1,3.99,3.95Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
<path id="Path_312" data-name="Path 312" d="M867.69,485.27v173.3a4,4,0,0,1-4,3.95h0V481.32h0a4,4,0,0,1,4,3.95Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
<path id="Path_313" data-name="Path 313" d="M775.59,319.15H598.09V467.4l177.5,4Z" fill="#39374d"/>
<path id="Path_314" data-name="Path 314" d="M663.19,485.27v168.2a4,4,0,0,1-3.85,3.95l-191.65,5.1h0a4,4,0,0,1-4-3.95V485.27a4,4,0,0,1,3.95-3.95h191.6A4,4,0,0,1,663.19,485.27Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
<path id="Path_315" data-name="Path 315" d="M397.09,319.15h177.5V467.4l-177.5,4Z" fill="#4267b2"/>
<path id="Path_316" data-name="Path 316" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l202.51-1.33h.48l40.99-.28h.19l283.08-1.87h.29l.17-.01h.47l4.79-.03h1.46l74.49-.5,4.4-.02.98-.01Z" opacity="0.1"/>
<circle id="Ellipse_111" data-name="Ellipse 111" cx="51.33" cy="51.33" r="51.33" transform="translate(435.93 246.82)" fill="#fbbebe"/>
<path id="Path_317" data-name="Path 317" d="M617.94,550.07s-99.5,12-90,0c3.44-4.34,4.39-17.2,4.2-31.85-.06-4.45-.22-9.06-.45-13.65-1.1-22-3.75-43.5-3.75-43.5s87-41,77-8.5c-4,13.13-2.69,31.57.35,48.88.89,5.05,1.92,10,3,14.7a344.66,344.66,0,0,0,9.65,33.92Z" transform="translate(-79.34 -172.91)" fill="#fbbebe"/>
<path id="Path_318" data-name="Path 318" d="M585.47,546c11.51-2.13,23.7-6,34.53-1.54,2.85,1.17,5.47,2.88,8.39,3.86s6.12,1.22,9.16,1.91c10.68,2.42,19.34,10.55,24.9,20s8.44,20.14,11.26,30.72l6.9,25.83c6,22.45,12,45.09,13.39,68.3a2437.506,2437.506,0,0,1-250.84,1.43c5.44-10.34,11-21.31,10.54-33s-7.19-23.22-4.76-34.74c1.55-7.34,6.57-13.39,9.64-20.22,8.75-19.52,1.94-45.79,17.32-60.65,6.92-6.68,17-9.21,26.63-8.89,12.28.41,24.85,4.24,37,6.11C555.09,547.48,569.79,548.88,585.47,546Z" transform="translate(-79.34 -172.91)" fill="#ff6584"/>
<path id="Path_319" data-name="Path 319" d="M716.37,657.17l-.1,1.43v.1l-.17,2.3-1.33,18.51-1.61,22.3-.46,6.28-1,13.44v.17l-107,1-175.59,1.9v.84h-.14v-1.12l.45-14.36.86-28.06.74-23.79.07-2.37a10.53,10.53,0,0,1,11.42-10.17c4.72.4,10.85.89,18.18,1.41l3,.22c42.33,2.94,120.56,6.74,199.5,2,1.66-.09,3.33-.19,5-.31,12.24-.77,24.47-1.76,36.58-3a10.53,10.53,0,0,1,11.6,11.23Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
<path id="Path_320" data-name="Path 320" d="M429.08,725.44v-.84l175.62-1.91,107-1h.3v-.17l1-13.44.43-6,1.64-22.61,1.29-17.9v-.44a10.617,10.617,0,0,0-.11-2.47.3.3,0,0,0,0-.1,10.391,10.391,0,0,0-2-4.64,10.54,10.54,0,0,0-9.42-4c-12.11,1.24-24.34,2.23-36.58,3-1.67.12-3.34.22-5,.31-78.94,4.69-157.17.89-199.5-2l-3-.22c-7.33-.52-13.46-1-18.18-1.41a10.54,10.54,0,0,0-11.24,8.53,11,11,0,0,0-.18,1.64l-.68,22.16L429.54,710l-.44,14.36v1.12Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
<path id="Path_321" data-name="Path 321" d="M716.67,664.18l-1.23,15.33-1.83,22.85-.46,5.72-1,12.81-.06.64v.17h0l-.15,1.48.11-1.48h-.29l-107,1-175.65,1.9v-.28l.49-14.36,1-28.06.64-18.65A6.36,6.36,0,0,1,434.3,658a6.25,6.25,0,0,1,3.78-.9c2.1.17,4.68.37,7.69.59,4.89.36,10.92.78,17.94,1.22,13,.82,29.31,1.7,48,2.42,52,2,122.2,2.67,188.88-3.17,3-.26,6.1-.55,9.13-.84a6.26,6.26,0,0,1,3.48.66,5.159,5.159,0,0,1,.86.54,6.14,6.14,0,0,1,2,2.46,3.564,3.564,0,0,1,.25.61A6.279,6.279,0,0,1,716.67,664.18Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
<path id="Path_322" data-name="Path 322" d="M377.44,677.87v3.19a6.13,6.13,0,0,1-3.5,5.54l-40.1.77a6.12,6.12,0,0,1-3.57-5.57v-3Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
<path id="Path_323" data-name="Path 323" d="M298.59,515.57l-52.25,1V507.9l52.25-1Z" fill="#3f3d56"/>
<path id="Path_324" data-name="Path 324" d="M298.59,515.57l-52.25,1V507.9l52.25-1Z" opacity="0.1"/>
<path id="Path_325" data-name="Path 325" d="M300.59,515.57l-52.25,1V507.9l52.25-1Z" fill="#3f3d56"/>
<path id="Path_326" data-name="Path 326" d="M758.56,679.87v3.19a6.13,6.13,0,0,0,3.5,5.54l40.1.77a6.12,6.12,0,0,0,3.57-5.57v-3Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
<path id="Path_327" data-name="Path 327" d="M678.72,517.57l52.25,1V509.9l-52.25-1Z" opacity="0.1"/>
<path id="Path_328" data-name="Path 328" d="M676.72,517.57l52.25,1V509.9l-52.25-1Z" fill="#3f3d56"/>
<path id="Path_329" data-name="Path 329" d="M534.13,486.79c.08,7-3.16,13.6-5.91,20.07a163.491,163.491,0,0,0-12.66,74.71c.73,11,2.58,22,.73,32.9s-8.43,21.77-19,24.9c17.53,10.45,41.26,9.35,57.76-2.66,8.79-6.4,15.34-15.33,21.75-24.11a97.86,97.86,0,0,1-13.31,44.75A103.43,103.43,0,0,0,637,616.53c4.31-5.81,8.06-12.19,9.72-19.23,3.09-13-1.22-26.51-4.51-39.5a266.055,266.055,0,0,1-6.17-33c-.43-3.56-.78-7.22.1-10.7,1-4.07,3.67-7.51,5.64-11.22,5.6-10.54,5.73-23.3,2.86-34.88s-8.49-22.26-14.06-32.81c-4.46-8.46-9.3-17.31-17.46-22.28-5.1-3.1-11-4.39-16.88-5.64l-25.37-5.43c-5.55-1.19-11.26-2.38-16.87-1.51-9.47,1.48-16.14,8.32-22,15.34-4.59,5.46-15.81,15.71-16.6,22.86-.72,6.59,5.1,17.63,6.09,24.58,1.3,9,2.22,6,7.3,11.52C532,478.05,534.07,482,534.13,486.79Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
</g>
<g id="docusaurus_keytar" transform="translate(670.271 615.768)">
<path id="Path_40" data-name="Path 40" d="M99,52h43.635V69.662H99Z" transform="translate(-49.132 -33.936)" fill="#fff" fill-rule="evenodd"/>
<path id="Path_41" data-name="Path 41" d="M13.389,158.195A10.377,10.377,0,0,1,4.4,153a10.377,10.377,0,0,0,8.988,15.584H23.779V158.195Z" transform="translate(-3 -82.47)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_42" data-name="Path 42" d="M66.967,38.083l36.373-2.273V30.615A10.389,10.389,0,0,0,92.95,20.226H46.2l-1.3-2.249a1.5,1.5,0,0,0-2.6,0L41,20.226l-1.3-2.249a1.5,1.5,0,0,0-2.6,0l-1.3,2.249-1.3-2.249a1.5,1.5,0,0,0-2.6,0l-1.3,2.249-.034,0-2.152-2.151a1.5,1.5,0,0,0-2.508.672L25.21,21.4l-2.7-.723a1.5,1.5,0,0,0-1.836,1.837l.722,2.7-2.65.71a1.5,1.5,0,0,0-.673,2.509l2.152,2.152c0,.011,0,.022,0,.033l-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6L20.226,41l-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3A10.389,10.389,0,0,0,30.615,103.34H92.95A10.389,10.389,0,0,0,103.34,92.95V51.393L66.967,49.12a5.53,5.53,0,0,1,0-11.038" transform="translate(-9.836 -17.226)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_43" data-name="Path 43" d="M143,163.779h15.584V143H143Z" transform="translate(-70.275 -77.665)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_44" data-name="Path 44" d="M173.779,148.389a2.582,2.582,0,0,0-.332.033c-.02-.078-.038-.156-.06-.234a2.594,2.594,0,1,0-2.567-4.455q-.086-.088-.174-.175a2.593,2.593,0,1,0-4.461-2.569c-.077-.022-.154-.04-.231-.06a2.6,2.6,0,1,0-5.128,0c-.077.02-.154.038-.231.06a2.594,2.594,0,1,0-4.461,2.569,10.384,10.384,0,1,0,17.314,9.992,2.592,2.592,0,1,0,.332-5.161" transform="translate(-75.08 -75.262)" fill="#44d860" fill-rule="evenodd"/>
<path id="Path_45" data-name="Path 45" d="M153,113.389h15.584V103H153Z" transform="translate(-75.08 -58.444)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_46" data-name="Path 46" d="M183.389,108.944a1.3,1.3,0,1,0,0-2.6,1.336,1.336,0,0,0-.166.017c-.01-.039-.019-.078-.03-.117a1.3,1.3,0,0,0-.5-2.5,1.285,1.285,0,0,0-.783.269q-.043-.044-.087-.087a1.285,1.285,0,0,0,.263-.776,1.3,1.3,0,0,0-2.493-.509,5.195,5.195,0,1,0,0,10,1.3,1.3,0,0,0,2.493-.509,1.285,1.285,0,0,0-.263-.776q.044-.043.087-.087a1.285,1.285,0,0,0,.783.269,1.3,1.3,0,0,0,.5-2.5c.011-.038.02-.078.03-.117a1.337,1.337,0,0,0,.166.017" transform="translate(-84.691 -57.894)" fill="#44d860" fill-rule="evenodd"/>
<path id="Path_47" data-name="Path 47" d="M52.188,48.292a1.3,1.3,0,0,1-1.3-1.3,3.9,3.9,0,0,0-7.792,0,1.3,1.3,0,1,1-2.6,0,6.493,6.493,0,0,1,12.987,0,1.3,1.3,0,0,1-1.3,1.3" transform="translate(-21.02 -28.41)" fill-rule="evenodd"/>
<path id="Path_48" data-name="Path 48" d="M103,139.752h31.168a10.389,10.389,0,0,0,10.389-10.389V93H113.389A10.389,10.389,0,0,0,103,103.389Z" transform="translate(-51.054 -53.638)" fill="#ffff50" fill-rule="evenodd"/>
<path id="Path_49" data-name="Path 49" d="M141.1,94.017H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0-25.877H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.293H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m7.782-47.993c-.006,0-.011,0-.018,0-1.605.055-2.365,1.66-3.035,3.077-.7,1.48-1.24,2.443-2.126,2.414-.981-.035-1.542-1.144-2.137-2.317-.683-1.347-1.462-2.876-3.1-2.819-1.582.054-2.344,1.451-3.017,2.684-.715,1.313-1.2,2.112-2.141,2.075-1-.036-1.533-.938-2.149-1.981-.686-1.162-1.479-2.467-3.084-2.423-1.555.053-2.319,1.239-2.994,2.286-.713,1.106-1.213,1.781-2.164,1.741-1.025-.036-1.554-.784-2.167-1.65-.688-.973-1.463-2.074-3.062-2.021a3.815,3.815,0,0,0-2.959,1.879c-.64.812-1.14,1.456-2.2,1.415a.52.52,0,0,0-.037,1.039,3.588,3.588,0,0,0,3.05-1.811c.611-.777,1.139-1.448,2.178-1.483,1-.043,1.47.579,2.179,1.582.674.953,1.438,2.033,2.977,2.089,1.612.054,2.387-1.151,3.074-2.217.614-.953,1.144-1.775,2.156-1.81.931-.035,1.438.7,2.153,1.912.674,1.141,1.437,2.434,3.006,2.491,1.623.056,2.407-1.361,3.09-2.616.592-1.085,1.15-2.109,2.14-2.143.931-.022,1.417.829,2.135,2.249.671,1.326,1.432,2.828,3.026,2.886l.088,0c1.592,0,2.347-1.6,3.015-3.01.592-1.252,1.152-2.431,2.113-2.479Z" transform="translate(-55.378 -38.552)" fill-rule="evenodd"/>
<path id="Path_50" data-name="Path 50" d="M83,163.779h20.779V143H83Z" transform="translate(-41.443 -77.665)" fill="#3ecc5f" fill-rule="evenodd"/>
<g id="Group_8" data-name="Group 8" transform="matrix(0.966, -0.259, 0.259, 0.966, 51.971, 43.3)">
<rect id="Rectangle_3" data-name="Rectangle 3" width="43.906" height="17.333" rx="2" transform="translate(0 0)" fill="#d8d8d8"/>
<g id="Group_2" data-name="Group 2" transform="translate(0.728 10.948)">
<rect id="Rectangle_4" data-name="Rectangle 4" width="2.537" height="2.537" rx="1" transform="translate(7.985 0)" fill="#4a4a4a"/>
<rect id="Rectangle_5" data-name="Rectangle 5" width="2.537" height="2.537" rx="1" transform="translate(10.991 0)" fill="#4a4a4a"/>
<rect id="Rectangle_6" data-name="Rectangle 6" width="2.537" height="2.537" rx="1" transform="translate(13.997 0)" fill="#4a4a4a"/>
<rect id="Rectangle_7" data-name="Rectangle 7" width="2.537" height="2.537" rx="1" transform="translate(17.003 0)" fill="#4a4a4a"/>
<rect id="Rectangle_8" data-name="Rectangle 8" width="2.537" height="2.537" rx="1" transform="translate(20.009 0)" fill="#4a4a4a"/>
<rect id="Rectangle_9" data-name="Rectangle 9" width="2.537" height="2.537" rx="1" transform="translate(23.015 0)" fill="#4a4a4a"/>
<rect id="Rectangle_10" data-name="Rectangle 10" width="2.537" height="2.537" rx="1" transform="translate(26.021 0)" fill="#4a4a4a"/>
<rect id="Rectangle_11" data-name="Rectangle 11" width="2.537" height="2.537" rx="1" transform="translate(29.028 0)" fill="#4a4a4a"/>
<rect id="Rectangle_12" data-name="Rectangle 12" width="2.537" height="2.537" rx="1" transform="translate(32.034 0)" fill="#4a4a4a"/>
<path id="Path_51" data-name="Path 51" d="M.519,0H6.9A.519.519,0,0,1,7.421.52v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0ZM35.653,0h6.383a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H35.652a.519.519,0,0,1-.519-.519V.519A.519.519,0,0,1,35.652,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
</g>
<g id="Group_3" data-name="Group 3" transform="translate(0.728 4.878)">
<path id="Path_52" data-name="Path 52" d="M.519,0H2.956a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
<rect id="Rectangle_13" data-name="Rectangle 13" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
<rect id="Rectangle_14" data-name="Rectangle 14" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
<rect id="Rectangle_15" data-name="Rectangle 15" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
<rect id="Rectangle_16" data-name="Rectangle 16" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
<rect id="Rectangle_17" data-name="Rectangle 17" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
<rect id="Rectangle_18" data-name="Rectangle 18" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
<rect id="Rectangle_19" data-name="Rectangle 19" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
<rect id="Rectangle_20" data-name="Rectangle 20" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
<rect id="Rectangle_21" data-name="Rectangle 21" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
<rect id="Rectangle_22" data-name="Rectangle 22" width="2.537" height="2.537" rx="1" transform="translate(31 0)" fill="#4a4a4a"/>
<rect id="Rectangle_23" data-name="Rectangle 23" width="2.537" height="2.537" rx="1" transform="translate(34.006 0)" fill="#4a4a4a"/>
<rect id="Rectangle_24" data-name="Rectangle 24" width="2.537" height="2.537" rx="1" transform="translate(37.012 0)" fill="#4a4a4a"/>
<rect id="Rectangle_25" data-name="Rectangle 25" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
</g>
<g id="Group_4" data-name="Group 4" transform="translate(43.283 4.538) rotate(180)">
<path id="Path_53" data-name="Path 53" d="M.519,0H2.956a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
<rect id="Rectangle_26" data-name="Rectangle 26" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
<rect id="Rectangle_27" data-name="Rectangle 27" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
<rect id="Rectangle_28" data-name="Rectangle 28" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
<rect id="Rectangle_29" data-name="Rectangle 29" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
<rect id="Rectangle_30" data-name="Rectangle 30" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
<rect id="Rectangle_31" data-name="Rectangle 31" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
<rect id="Rectangle_32" data-name="Rectangle 32" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
<rect id="Rectangle_33" data-name="Rectangle 33" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
<rect id="Rectangle_34" data-name="Rectangle 34" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
<rect id="Rectangle_35" data-name="Rectangle 35" width="2.537" height="2.537" rx="1" transform="translate(31.001 0)" fill="#4a4a4a"/>
<rect id="Rectangle_36" data-name="Rectangle 36" width="2.537" height="2.537" rx="1" transform="translate(34.007 0)" fill="#4a4a4a"/>
<rect id="Rectangle_37" data-name="Rectangle 37" width="2.537" height="2.537" rx="1" transform="translate(37.013 0)" fill="#4a4a4a"/>
<rect id="Rectangle_38" data-name="Rectangle 38" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
<rect id="Rectangle_39" data-name="Rectangle 39" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
<rect id="Rectangle_40" data-name="Rectangle 40" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
<rect id="Rectangle_41" data-name="Rectangle 41" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
<rect id="Rectangle_42" data-name="Rectangle 42" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
<rect id="Rectangle_43" data-name="Rectangle 43" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
<rect id="Rectangle_44" data-name="Rectangle 44" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
<rect id="Rectangle_45" data-name="Rectangle 45" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
<rect id="Rectangle_46" data-name="Rectangle 46" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
<rect id="Rectangle_47" data-name="Rectangle 47" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
<rect id="Rectangle_48" data-name="Rectangle 48" width="2.537" height="2.537" rx="1" transform="translate(31.001 0)" fill="#4a4a4a"/>
<rect id="Rectangle_49" data-name="Rectangle 49" width="2.537" height="2.537" rx="1" transform="translate(34.007 0)" fill="#4a4a4a"/>
<rect id="Rectangle_50" data-name="Rectangle 50" width="2.537" height="2.537" rx="1" transform="translate(37.013 0)" fill="#4a4a4a"/>
<rect id="Rectangle_51" data-name="Rectangle 51" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
</g>
<g id="Group_6" data-name="Group 6" transform="translate(0.728 7.883)">
<path id="Path_54" data-name="Path 54" d="M.519,0h3.47a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.52A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
<g id="Group_5" data-name="Group 5" transform="translate(5.073 0)">
<rect id="Rectangle_52" data-name="Rectangle 52" width="2.537" height="2.537" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
<rect id="Rectangle_53" data-name="Rectangle 53" width="2.537" height="2.537" rx="1" transform="translate(3.006 0)" fill="#4a4a4a"/>
<rect id="Rectangle_54" data-name="Rectangle 54" width="2.537" height="2.537" rx="1" transform="translate(6.012 0)" fill="#4a4a4a"/>
<rect id="Rectangle_55" data-name="Rectangle 55" width="2.537" height="2.537" rx="1" transform="translate(9.018 0)" fill="#4a4a4a"/>
<rect id="Rectangle_56" data-name="Rectangle 56" width="2.537" height="2.537" rx="1" transform="translate(12.025 0)" fill="#4a4a4a"/>
<rect id="Rectangle_57" data-name="Rectangle 57" width="2.537" height="2.537" rx="1" transform="translate(15.031 0)" fill="#4a4a4a"/>
<rect id="Rectangle_58" data-name="Rectangle 58" width="2.537" height="2.537" rx="1" transform="translate(18.037 0)" fill="#4a4a4a"/>
<rect id="Rectangle_59" data-name="Rectangle 59" width="2.537" height="2.537" rx="1" transform="translate(21.042 0)" fill="#4a4a4a"/>
<rect id="Rectangle_60" data-name="Rectangle 60" width="2.537" height="2.537" rx="1" transform="translate(24.049 0)" fill="#4a4a4a"/>
<rect id="Rectangle_61" data-name="Rectangle 61" width="2.537" height="2.537" rx="1" transform="translate(27.055 0)" fill="#4a4a4a"/>
<rect id="Rectangle_62" data-name="Rectangle 62" width="2.537" height="2.537" rx="1" transform="translate(30.061 0)" fill="#4a4a4a"/>
</g>
<path id="Path_55" data-name="Path 55" d="M.52,0H3.8a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.52A.519.519,0,0,1,.519,0Z" transform="translate(38.234 0)" fill="#4a4a4a" fill-rule="evenodd"/>
</g>
<g id="Group_7" data-name="Group 7" transform="translate(0.728 14.084)">
<rect id="Rectangle_63" data-name="Rectangle 63" width="2.537" height="2.537" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
<rect id="Rectangle_64" data-name="Rectangle 64" width="2.537" height="2.537" rx="1" transform="translate(3.006 0)" fill="#4a4a4a"/>
<rect id="Rectangle_65" data-name="Rectangle 65" width="2.537" height="2.537" rx="1" transform="translate(6.012 0)" fill="#4a4a4a"/>
<rect id="Rectangle_66" data-name="Rectangle 66" width="2.537" height="2.537" rx="1" transform="translate(9.018 0)" fill="#4a4a4a"/>
<path id="Path_56" data-name="Path 56" d="M.519,0H14.981A.519.519,0,0,1,15.5.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.018V.519A.519.519,0,0,1,.519,0Zm15.97,0h1.874a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H16.489a.519.519,0,0,1-.519-.519V.519A.519.519,0,0,1,16.489,0Z" transform="translate(12.024 0)" fill="#4a4a4a" fill-rule="evenodd"/>
<rect id="Rectangle_67" data-name="Rectangle 67" width="2.537" height="2.537" rx="1" transform="translate(31.376 0)" fill="#4a4a4a"/>
<rect id="Rectangle_68" data-name="Rectangle 68" width="2.537" height="2.537" rx="1" transform="translate(34.382 0)" fill="#4a4a4a"/>
<rect id="Rectangle_69" data-name="Rectangle 69" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
<path id="Path_57" data-name="Path 57" d="M2.537,0V.561a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,.561V0Z" transform="translate(39.736 1.08) rotate(180)" fill="#4a4a4a"/>
<path id="Path_58" data-name="Path 58" d="M2.537,0V.561a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,.561V0Z" transform="translate(37.2 1.456)" fill="#4a4a4a"/>
</g>
<rect id="Rectangle_70" data-name="Rectangle 70" width="42.273" height="1.127" rx="0.564" transform="translate(0.915 0.556)" fill="#4a4a4a"/>
<rect id="Rectangle_71" data-name="Rectangle 71" width="2.37" height="0.752" rx="0.376" transform="translate(1.949 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_72" data-name="Rectangle 72" width="2.37" height="0.752" rx="0.376" transform="translate(5.193 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_73" data-name="Rectangle 73" width="2.37" height="0.752" rx="0.376" transform="translate(7.688 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_74" data-name="Rectangle 74" width="2.37" height="0.752" rx="0.376" transform="translate(10.183 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_75" data-name="Rectangle 75" width="2.37" height="0.752" rx="0.376" transform="translate(12.679 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_76" data-name="Rectangle 76" width="2.37" height="0.752" rx="0.376" transform="translate(15.797 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_77" data-name="Rectangle 77" width="2.37" height="0.752" rx="0.376" transform="translate(18.292 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_78" data-name="Rectangle 78" width="2.37" height="0.752" rx="0.376" transform="translate(20.788 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_79" data-name="Rectangle 79" width="2.37" height="0.752" rx="0.376" transform="translate(23.283 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_80" data-name="Rectangle 80" width="2.37" height="0.752" rx="0.376" transform="translate(26.402 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_81" data-name="Rectangle 81" width="2.37" height="0.752" rx="0.376" transform="translate(28.897 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_82" data-name="Rectangle 82" width="2.37" height="0.752" rx="0.376" transform="translate(31.393 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_83" data-name="Rectangle 83" width="2.37" height="0.752" rx="0.376" transform="translate(34.512 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_84" data-name="Rectangle 84" width="2.37" height="0.752" rx="0.376" transform="translate(37.007 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_85" data-name="Rectangle 85" width="2.37" height="0.752" rx="0.376" transform="translate(39.502 0.744)" fill="#d8d8d8" opacity="0.136"/>
</g>
<path id="Path_59" data-name="Path 59" d="M123.779,148.389a2.583,2.583,0,0,0-.332.033c-.02-.078-.038-.156-.06-.234a2.594,2.594,0,1,0-2.567-4.455q-.086-.088-.174-.175a2.593,2.593,0,1,0-4.461-2.569c-.077-.022-.154-.04-.231-.06a2.6,2.6,0,1,0-5.128,0c-.077.02-.154.038-.231.06a2.594,2.594,0,1,0-4.461,2.569,10.384,10.384,0,1,0,17.314,9.992,2.592,2.592,0,1,0,.332-5.161" transform="translate(-51.054 -75.262)" fill="#44d860" fill-rule="evenodd"/>
<path id="Path_60" data-name="Path 60" d="M83,113.389h20.779V103H83Z" transform="translate(-41.443 -58.444)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_61" data-name="Path 61" d="M123.389,108.944a1.3,1.3,0,1,0,0-2.6,1.338,1.338,0,0,0-.166.017c-.01-.039-.019-.078-.03-.117a1.3,1.3,0,0,0-.5-2.5,1.285,1.285,0,0,0-.783.269q-.043-.044-.087-.087a1.285,1.285,0,0,0,.263-.776,1.3,1.3,0,0,0-2.493-.509,5.195,5.195,0,1,0,0,10,1.3,1.3,0,0,0,2.493-.509,1.285,1.285,0,0,0-.263-.776q.044-.043.087-.087a1.285,1.285,0,0,0,.783.269,1.3,1.3,0,0,0,.5-2.5c.011-.038.02-.078.03-.117a1.335,1.335,0,0,0,.166.017" transform="translate(-55.859 -57.894)" fill="#44d860" fill-rule="evenodd"/>
<path id="Path_62" data-name="Path 62" d="M141.8,38.745a1.41,1.41,0,0,1-.255-.026,1.309,1.309,0,0,1-.244-.073,1.349,1.349,0,0,1-.224-.119,1.967,1.967,0,0,1-.2-.161,1.52,1.52,0,0,1-.161-.2,1.282,1.282,0,0,1-.218-.722,1.41,1.41,0,0,1,.026-.255,1.5,1.5,0,0,1,.072-.244,1.364,1.364,0,0,1,.12-.223,1.252,1.252,0,0,1,.358-.358,1.349,1.349,0,0,1,.224-.119,1.309,1.309,0,0,1,.244-.073,1.2,1.2,0,0,1,.509,0,1.262,1.262,0,0,1,.468.192,1.968,1.968,0,0,1,.2.161,1.908,1.908,0,0,1,.161.2,1.322,1.322,0,0,1,.12.223,1.361,1.361,0,0,1,.1.5,1.317,1.317,0,0,1-.379.919,1.968,1.968,0,0,1-.2.161,1.346,1.346,0,0,1-.223.119,1.332,1.332,0,0,1-.5.1m10.389-.649a1.326,1.326,0,0,1-.92-.379,1.979,1.979,0,0,1-.161-.2,1.282,1.282,0,0,1-.218-.722,1.326,1.326,0,0,1,.379-.919,1.967,1.967,0,0,1,.2-.161,1.351,1.351,0,0,1,.224-.119,1.308,1.308,0,0,1,.244-.073,1.2,1.2,0,0,1,.509,0,1.262,1.262,0,0,1,.468.192,1.967,1.967,0,0,1,.2.161,1.326,1.326,0,0,1,.379.919,1.461,1.461,0,0,1-.026.255,1.323,1.323,0,0,1-.073.244,1.847,1.847,0,0,1-.119.223,1.911,1.911,0,0,1-.161.2,1.967,1.967,0,0,1-.2.161,1.294,1.294,0,0,1-.722.218" transform="translate(-69.074 -26.006)" fill-rule="evenodd"/>
</g>
<g id="React-icon" transform="translate(906.3 541.56)">
<path id="Path_330" data-name="Path 330" d="M263.668,117.179c0-5.827-7.3-11.35-18.487-14.775,2.582-11.4,1.434-20.477-3.622-23.382a7.861,7.861,0,0,0-4.016-1v4a4.152,4.152,0,0,1,2.044.466c2.439,1.4,3.5,6.724,2.672,13.574-.2,1.685-.52,3.461-.914,5.272a86.9,86.9,0,0,0-11.386-1.954,87.469,87.469,0,0,0-7.459-8.965c5.845-5.433,11.332-8.41,15.062-8.41V78h0c-4.931,0-11.386,3.514-17.913,9.611-6.527-6.061-12.982-9.539-17.913-9.539v4c3.712,0,9.216,2.959,15.062,8.356a84.687,84.687,0,0,0-7.405,8.947,83.732,83.732,0,0,0-11.4,1.972c-.412-1.793-.717-3.532-.932-5.2-.843-6.85.2-12.175,2.618-13.592a3.991,3.991,0,0,1,2.062-.466v-4h0a8,8,0,0,0-4.052,1c-5.039,2.9-6.168,11.96-3.568,23.328-11.153,3.443-18.415,8.947-18.415,14.757,0,5.828,7.3,11.35,18.487,14.775-2.582,11.4-1.434,20.477,3.622,23.382a7.882,7.882,0,0,0,4.034,1c4.931,0,11.386-3.514,17.913-9.611,6.527,6.061,12.982,9.539,17.913,9.539a8,8,0,0,0,4.052-1c5.039-2.9,6.168-11.96,3.568-23.328C256.406,128.511,263.668,122.988,263.668,117.179Zm-23.346-11.96c-.663,2.313-1.488,4.7-2.421,7.083-.735-1.434-1.506-2.869-2.349-4.3-.825-1.434-1.7-2.833-2.582-4.2C235.517,104.179,237.974,104.645,240.323,105.219Zm-8.212,19.1c-1.4,2.421-2.833,4.716-4.321,6.85-2.672.233-5.379.359-8.1.359-2.708,0-5.415-.126-8.069-.341q-2.232-3.2-4.339-6.814-2.044-3.523-3.73-7.136c1.112-2.4,2.367-4.805,3.712-7.154,1.4-2.421,2.833-4.716,4.321-6.85,2.672-.233,5.379-.359,8.1-.359,2.708,0,5.415.126,8.069.341q2.232,3.2,4.339,6.814,2.044,3.523,3.73,7.136C234.692,119.564,233.455,121.966,232.11,124.315Zm5.792-2.331c.968,2.4,1.793,4.805,2.474,7.136-2.349.574-4.823,1.058-7.387,1.434.879-1.381,1.757-2.8,2.582-4.25C236.4,124.871,237.167,123.419,237.9,121.984ZM219.72,141.116a73.921,73.921,0,0,1-4.985-5.738c1.614.072,3.263.126,4.931.126,1.685,0,3.353-.036,4.985-.126A69.993,69.993,0,0,1,219.72,141.116ZM206.38,130.555c-2.546-.377-5-.843-7.352-1.417.663-2.313,1.488-4.7,2.421-7.083.735,1.434,1.506,2.869,2.349,4.3S205.5,129.192,206.38,130.555ZM219.63,93.241a73.924,73.924,0,0,1,4.985,5.738c-1.614-.072-3.263-.126-4.931-.126-1.686,0-3.353.036-4.985.126A69.993,69.993,0,0,1,219.63,93.241ZM206.362,103.8c-.879,1.381-1.757,2.8-2.582,4.25-.825,1.434-1.6,2.869-2.331,4.3-.968-2.4-1.793-4.805-2.474-7.136C201.323,104.663,203.8,104.179,206.362,103.8Zm-16.227,22.449c-6.348-2.708-10.454-6.258-10.454-9.073s4.106-6.383,10.454-9.073c1.542-.663,3.228-1.255,4.967-1.811a86.122,86.122,0,0,0,4.034,10.92,84.9,84.9,0,0,0-3.981,10.866C193.38,127.525,191.694,126.915,190.134,126.252Zm9.647,25.623c-2.439-1.4-3.5-6.724-2.672-13.574.2-1.686.52-3.461.914-5.272a86.9,86.9,0,0,0,11.386,1.954,87.465,87.465,0,0,0,7.459,8.965c-5.845,5.433-11.332,8.41-15.062,8.41A4.279,4.279,0,0,1,199.781,151.875Zm42.532-13.663c.843,6.85-.2,12.175-2.618,13.592a3.99,3.99,0,0,1-2.062.466c-3.712,0-9.216-2.959-15.062-8.356a84.689,84.689,0,0,0,7.405-8.947,83.731,83.731,0,0,0,11.4-1.972A50.194,50.194,0,0,1,242.313,138.212Zm6.9-11.96c-1.542.663-3.228,1.255-4.967,1.811a86.12,86.12,0,0,0-4.034-10.92,84.9,84.9,0,0,0,3.981-10.866c1.775.556,3.461,1.165,5.039,1.829,6.348,2.708,10.454,6.258,10.454,9.073C259.67,119.994,255.564,123.562,249.216,126.252Z" fill="#61dafb"/>
<path id="Path_331" data-name="Path 331" d="M320.8,78.4Z" transform="translate(-119.082 -0.328)" fill="#61dafb"/>
<circle id="Ellipse_112" data-name="Ellipse 112" cx="8.194" cy="8.194" r="8.194" transform="translate(211.472 108.984)" fill="#61dafb"/>
<path id="Path_332" data-name="Path 332" d="M520.5,78.1Z" transform="translate(-282.975 -0.082)" fill="#61dafb"/>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="1129" height="663" viewBox="0 0 1129 663">
<title>Focus on What Matters</title>
<circle cx="321" cy="321" r="321" fill="#f2f2f2" />
<ellipse cx="559" cy="635.49998" rx="514" ry="27.50002" fill="#3f3d56" />
<ellipse cx="558" cy="627" rx="460" ry="22" opacity="0.2" />
<rect x="131" y="152.5" width="840" height="50" fill="#3f3d56" />
<path d="M166.5,727.3299A21.67009,21.67009,0,0,0,188.1701,749H984.8299A21.67009,21.67009,0,0,0,1006.5,727.3299V296h-840Z" transform="translate(-35.5 -118.5)" fill="#3f3d56" />
<path d="M984.8299,236H188.1701A21.67009,21.67009,0,0,0,166.5,257.6701V296h840V257.6701A21.67009,21.67009,0,0,0,984.8299,236Z" transform="translate(-35.5 -118.5)" fill="#3f3d56" />
<path d="M984.8299,236H188.1701A21.67009,21.67009,0,0,0,166.5,257.6701V296h840V257.6701A21.67009,21.67009,0,0,0,984.8299,236Z" transform="translate(-35.5 -118.5)" opacity="0.2" />
<circle cx="181" cy="147.5" r="13" fill="#3f3d56" />
<circle cx="217" cy="147.5" r="13" fill="#3f3d56" />
<circle cx="253" cy="147.5" r="13" fill="#3f3d56" />
<rect x="168" y="213.5" width="337" height="386" rx="5.33505" fill="#606060" />
<rect x="603" y="272.5" width="284" height="22" rx="5.47638" fill="#2e8555" />
<rect x="537" y="352.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
<rect x="537" y="396.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
<rect x="537" y="440.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
<rect x="537" y="484.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
<rect x="865" y="552.5" width="88" height="26" rx="7.02756" fill="#3ecc5f" />
<path d="M1088.60287,624.61594a30.11371,30.11371,0,0,0,3.98291-15.266c0-13.79652-8.54358-24.98081-19.08256-24.98081s-19.08256,11.18429-19.08256,24.98081a30.11411,30.11411,0,0,0,3.98291,15.266,31.248,31.248,0,0,0,0,30.53213,31.248,31.248,0,0,0,0,30.53208,31.248,31.248,0,0,0,0,30.53208,30.11408,30.11408,0,0,0-3.98291,15.266c0,13.79652,8.54353,24.98081,19.08256,24.98081s19.08256-11.18429,19.08256-24.98081a30.11368,30.11368,0,0,0-3.98291-15.266,31.248,31.248,0,0,0,0-30.53208,31.248,31.248,0,0,0,0-30.53208,31.248,31.248,0,0,0,0-30.53213Z" transform="translate(-35.5 -118.5)" fill="#3f3d56" />
<ellipse cx="1038.00321" cy="460.31783" rx="19.08256" ry="24.9808" fill="#3f3d56" />
<ellipse cx="1038.00321" cy="429.78574" rx="19.08256" ry="24.9808" fill="#3f3d56" />
<path d="M1144.93871,339.34489a91.61081,91.61081,0,0,0,7.10658-10.46092l-50.141-8.23491,54.22885.4033a91.566,91.566,0,0,0,1.74556-72.42605l-72.75449,37.74139,67.09658-49.32086a91.41255,91.41255,0,1,0-150.971,102.29805,91.45842,91.45842,0,0,0-10.42451,16.66946l65.0866,33.81447-69.40046-23.292a91.46011,91.46011,0,0,0,14.73837,85.83669,91.40575,91.40575,0,1,0,143.68892,0,91.41808,91.41808,0,0,0,0-113.02862Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
<path d="M981.6885,395.8592a91.01343,91.01343,0,0,0,19.56129,56.51431,91.40575,91.40575,0,1,0,143.68892,0C1157.18982,436.82067,981.6885,385.60008,981.6885,395.8592Z" transform="translate(-35.5 -118.5)" opacity="0.1" />
<path d="M365.62,461.43628H477.094v45.12043H365.62Z" transform="translate(-35.5 -118.5)" fill="#fff" fill-rule="evenodd" />
<path d="M264.76252,608.74122a26.50931,26.50931,0,0,1-22.96231-13.27072,26.50976,26.50976,0,0,0,22.96231,39.81215H291.304V608.74122Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
<path d="M384.17242,468.57061l92.92155-5.80726V449.49263a26.54091,26.54091,0,0,0-26.54143-26.54143H331.1161l-3.31768-5.74622a3.83043,3.83043,0,0,0-6.63536,0l-3.31768,5.74622-3.31767-5.74622a3.83043,3.83043,0,0,0-6.63536,0l-3.31768,5.74622L301.257,417.205a3.83043,3.83043,0,0,0-6.63536,0L291.304,422.9512c-.02919,0-.05573.004-.08625.004l-5.49674-5.49541a3.8293,3.8293,0,0,0-6.4071,1.71723l-1.81676,6.77338L270.607,424.1031a3.82993,3.82993,0,0,0-4.6912,4.69253l1.84463,6.89148-6.77072,1.81411a3.8315,3.8315,0,0,0-1.71988,6.40975l5.49673,5.49673c0,.02787-.004.05574-.004.08493l-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74621,3.31768L259.0163,466.081a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31767a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31767a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83042,3.83042,0,0,0,0,6.63535l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768L259.0163,558.976a3.83042,3.83042,0,0,0,0,6.63535l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83042,3.83042,0,0,0,0,6.63535l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768A26.54091,26.54091,0,0,0,291.304,635.28265H450.55254A26.5409,26.5409,0,0,0,477.094,608.74122V502.5755l-92.92155-5.80727a14.12639,14.12639,0,0,1,0-28.19762" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
<path d="M424.01111,635.28265h39.81214V582.19979H424.01111Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
<path d="M490.36468,602.10586a6.60242,6.60242,0,0,0-.848.08493c-.05042-.19906-.09821-.39945-.15393-.59852A6.62668,6.62668,0,1,0,482.80568,590.21q-.2203-.22491-.44457-.44589a6.62391,6.62391,0,1,0-11.39689-6.56369c-.1964-.05575-.39414-.10218-.59056-.15262a6.63957,6.63957,0,1,0-13.10086,0c-.1964.05042-.39414.09687-.59056.15262a6.62767,6.62767,0,1,0-11.39688,6.56369,26.52754,26.52754,0,1,0,44.23127,25.52756,6.6211,6.6211,0,1,0,.848-13.18579" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
<path d="M437.28182,555.65836H477.094V529.11693H437.28182Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
<path d="M490.36468,545.70532a3.31768,3.31768,0,0,0,0-6.63536,3.41133,3.41133,0,0,0-.42333.04247c-.02655-.09953-.04911-.19907-.077-.29859a3.319,3.319,0,0,0-1.278-6.37923,3.28174,3.28174,0,0,0-2.00122.68742q-.10947-.11346-.22294-.22295a3.282,3.282,0,0,0,.67149-1.98265,3.31768,3.31768,0,0,0-6.37-1.2992,13.27078,13.27078,0,1,0,0,25.54082,3.31768,3.31768,0,0,0,6.37-1.2992,3.282,3.282,0,0,0-.67149-1.98265q.11347-.10947.22294-.22294a3.28174,3.28174,0,0,0,2.00122.68742,3.31768,3.31768,0,0,0,1.278-6.37923c.02786-.0982.05042-.19907.077-.29859a3.41325,3.41325,0,0,0,.42333.04246" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
<path d="M317.84538,466.081a3.31768,3.31768,0,0,1-3.31767-3.31768,9.953,9.953,0,1,0-19.90608,0,3.31768,3.31768,0,1,1-6.63535,0,16.58839,16.58839,0,1,1,33.17678,0,3.31768,3.31768,0,0,1-3.31768,3.31768" transform="translate(-35.5 -118.5)" fill-rule="evenodd" />
<path d="M370.92825,635.28265h79.62429A26.5409,26.5409,0,0,0,477.094,608.74122v-92.895H397.46968a26.54091,26.54091,0,0,0-26.54143,26.54143Z" transform="translate(-35.5 -118.5)" fill="#ffff50" fill-rule="evenodd" />
<path d="M457.21444,556.98543H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.54143H390.80778a1.32707,1.32707,0,1,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.54143H390.80778a1.32707,1.32707,0,1,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0-66.10674H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.29459H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.54143H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414M477.094,474.19076c-.01592,0-.0292-.008-.04512-.00663-4.10064.13934-6.04083,4.24132-7.75274,7.86024-1.78623,3.78215-3.16771,6.24122-5.43171,6.16691-2.50685-.09024-3.94007-2.92222-5.45825-5.91874-1.74377-3.44243-3.73438-7.34667-7.91333-7.20069-4.04227.138-5.98907,3.70784-7.70631,6.857-1.82738,3.35484-3.07084,5.39455-5.46887,5.30033-2.55727-.09289-3.91619-2.39536-5.48877-5.06013-1.75306-2.96733-3.77951-6.30359-7.8775-6.18946-3.97326.13669-5.92537,3.16507-7.64791,5.83912-1.82207,2.82666-3.09872,4.5492-5.52725,4.447-2.61832-.09289-3.9706-2.00388-5.53522-4.21611-1.757-2.4856-3.737-5.299-7.82308-5.16231-3.88567.13271-5.83779,2.61434-7.559,4.80135-1.635,2.07555-2.9116,3.71846-5.61218,3.615a1.32793,1.32793,0,1,0-.09555,2.65414c4.00377.134,6.03154-2.38873,7.79257-4.6275,1.562-1.9853,2.91027-3.69855,5.56441-3.78879,2.55594-.10882,3.75429,1.47968,5.56707,4.04093,1.7212,2.43385,3.67465,5.19416,7.60545,5.33616,4.11789.138,6.09921-2.93946,7.8536-5.66261,1.56861-2.43385,2.92221-4.53461,5.50734-4.62352,2.37944-.08892,3.67466,1.79154,5.50072,4.885,1.72121,2.91557,3.67069,6.21865,7.67977,6.36463,4.14709.14332,6.14965-3.47693,7.89475-6.68181,1.51155-2.77092,2.93814-5.38791,5.46621-5.4755,2.37944-.05573,3.62025,2.11668,5.45558,5.74622,1.71459,3.388,3.65875,7.22591,7.73019,7.37321l.22429.004c4.06614,0,5.99571-4.08074,7.70364-7.68905,1.51154-3.19825,2.94211-6.21069,5.3972-6.33411Z" transform="translate(-35.5 -118.5)" fill-rule="evenodd" />
<path d="M344.38682,635.28265h53.08286V582.19979H344.38682Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
<path d="M424.01111,602.10586a6.60242,6.60242,0,0,0-.848.08493c-.05042-.19906-.09821-.39945-.15394-.59852A6.62667,6.62667,0,1,0,416.45211,590.21q-.2203-.22491-.44458-.44589a6.62391,6.62391,0,1,0-11.39689-6.56369c-.1964-.05575-.39413-.10218-.59054-.15262a6.63957,6.63957,0,1,0-13.10084,0c-.19641.05042-.39414.09687-.59055.15262a6.62767,6.62767,0,1,0-11.39689,6.56369,26.52755,26.52755,0,1,0,44.2313,25.52756,6.6211,6.6211,0,1,0,.848-13.18579" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
<path d="M344.38682,555.65836h53.08286V529.11693H344.38682Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
<path d="M410.74039,545.70532a3.31768,3.31768,0,1,0,0-6.63536,3.41133,3.41133,0,0,0-.42333.04247c-.02655-.09953-.04911-.19907-.077-.29859a3.319,3.319,0,0,0-1.278-6.37923,3.28174,3.28174,0,0,0-2.00122.68742q-.10947-.11346-.22294-.22295a3.282,3.282,0,0,0,.67149-1.98265,3.31768,3.31768,0,0,0-6.37-1.2992,13.27078,13.27078,0,1,0,0,25.54082,3.31768,3.31768,0,0,0,6.37-1.2992,3.282,3.282,0,0,0-.67149-1.98265q.11347-.10947.22294-.22294a3.28174,3.28174,0,0,0,2.00122.68742,3.31768,3.31768,0,0,0,1.278-6.37923c.02786-.0982.05042-.19907.077-.29859a3.41325,3.41325,0,0,0,.42333.04246" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
<path d="M424.01111,447.8338a3.60349,3.60349,0,0,1-.65028-.06636,3.34415,3.34415,0,0,1-.62372-.18579,3.44679,3.44679,0,0,1-.572-.30522,5.02708,5.02708,0,0,1-.50429-.4114,3.88726,3.88726,0,0,1-.41007-.50428,3.27532,3.27532,0,0,1-.55737-1.84463,3.60248,3.60248,0,0,1,.06636-.65027,3.82638,3.82638,0,0,1,.18447-.62373,3.48858,3.48858,0,0,1,.30656-.57064,3.197,3.197,0,0,1,.91436-.91568,3.44685,3.44685,0,0,1,.572-.30523,3.344,3.344,0,0,1,.62372-.18578,3.06907,3.06907,0,0,1,1.30053,0,3.22332,3.22332,0,0,1,1.19436.491,5.02835,5.02835,0,0,1,.50429.41139,4.8801,4.8801,0,0,1,.41139.50429,3.38246,3.38246,0,0,1,.30522.57064,3.47806,3.47806,0,0,1,.25215,1.274A3.36394,3.36394,0,0,1,426.36,446.865a5.02708,5.02708,0,0,1-.50429.4114,3.3057,3.3057,0,0,1-1.84463.55737m26.54143-1.65884a3.38754,3.38754,0,0,1-2.35024-.96877,5.04185,5.04185,0,0,1-.41007-.50428,3.27532,3.27532,0,0,1-.55737-1.84463,3.38659,3.38659,0,0,1,.96744-2.34892,5.02559,5.02559,0,0,1,.50429-.41139,3.44685,3.44685,0,0,1,.572-.30523,3.3432,3.3432,0,0,1,.62373-.18579,3.06952,3.06952,0,0,1,1.30052,0,3.22356,3.22356,0,0,1,1.19436.491,5.02559,5.02559,0,0,1,.50429.41139,3.38792,3.38792,0,0,1,.96876,2.34892,3.72635,3.72635,0,0,1-.06636.65026,3.37387,3.37387,0,0,1-.18579.62373,4.71469,4.71469,0,0,1-.30522.57064,4.8801,4.8801,0,0,1-.41139.50429,5.02559,5.02559,0,0,1-.50429.41139,3.30547,3.30547,0,0,1-1.84463.55737" transform="translate(-35.5 -118.5)" fill-rule="evenodd" />
</svg>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="256.000000pt" height="256.000000pt" viewBox="0 0 256.000000 256.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,256.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M1125 2443 c-85 -12 -198 -40 -255 -61 -14 -5 -28 -10 -33 -11 -10
-1 -153 -78 -198 -107 -80 -50 -177 -137 -268 -239 -62 -69 -164 -249 -194
-340 -9 -27 -17 -52 -16 -55 0 -3 -4 -18 -10 -33 -6 -15 -13 -40 -16 -55 -2
-15 -9 -49 -14 -76 -5 -27 -10 -108 -10 -180 -1 -116 4 -165 33 -301 8 -39 44
-141 67 -190 22 -49 107 -195 118 -205 3 -3 24 -27 46 -55 95 -119 233 -229
372 -299 62 -31 117 -56 133 -61 3 0 32 -9 65 -19 143 -43 327 -58 485 -41 64
7 212 46 286 74 127 49 280 149 385 253 68 68 179 208 179 227 0 5 4 11 8 13
13 5 88 168 108 234 33 110 42 150 50 214 12 87 5 298 -11 365 -19 84 -28 115
-40 153 -49 143 -125 281 -205 369 -11 12 -20 25 -20 29 0 8 -152 154 -161
154 -3 0 -18 11 -33 24 -40 34 -176 113 -208 121 -16 4 -28 10 -28 14 0 4 -6
8 -12 9 -7 0 -33 8 -58 17 -25 9 -53 19 -62 21 -10 2 -26 6 -35 8 -10 2 -30 9
-44 14 -15 6 -29 9 -32 6 -2 -2 -27 0 -55 6 -74 16 -214 17 -317 3z"/>
</g>
</svg>
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-256x256.png",
"sizes": "256x256",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}
{
// This file is not used in compilation. It is here just for a nice editor experience.
"extends": "@tsconfig/docusaurus/tsconfig.json",
"compilerOptions": {
"baseUrl": "."
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment