Compare commits

..

21 Commits

Author SHA1 Message Date
Archer
98ce5103a0 v4.4.6 (#377) 2023-10-07 18:02:20 +08:00
Carson Yang
c65a36d3ab Docs: hide button for questionnaire on mobile device (#376)
Signed-off-by: Carson Yang <yangchuansheng33@gmail.com>
2023-10-07 14:57:26 +08:00
Carson Yang
b6e49da288 Docs: update button for questionnaire (#375)
Signed-off-by: Carson Yang <yangchuansheng33@gmail.com>
2023-10-06 23:52:45 +08:00
Archer
45998f9cf5 README (#372) 2023-10-06 21:19:44 +08:00
Carson Yang
4197f63751 Update README (#371)
Signed-off-by: Carson Yang <yangchuansheng33@gmail.com>
2023-10-06 14:07:37 +08:00
Carson Yang
ace8134a16 Docs: add Dockerfile for docs (#369)
Signed-off-by: Carson Yang <yangchuansheng33@gmail.com>
2023-10-06 08:01:16 +08:00
Carson Yang
7f1fecb84e Docs: update theme (#368)
Signed-off-by: Carson Yang <yangchuansheng33@gmail.com>
2023-10-04 22:25:07 +08:00
Archer
bf172fab81 perf: markdown more wrap (#365) 2023-10-02 20:19:09 +08:00
Archer
36f5648cae perf: v4.4.6-1 (#364) 2023-09-28 17:30:05 +08:00
Archer
ab57bfcc4a perf: completions api.fix: new chat question guide (#361) 2023-09-27 12:05:13 +08:00
Archer
11848b8f44 v4.4.5-3 (#357) 2023-09-26 21:17:13 +08:00
epoh
a11e0bd9c3 Update chatglm2.md (#354) 2023-09-26 15:06:38 +08:00
Archer
f6552d0d4f v4.4.5-2 (#355) 2023-09-26 14:31:37 +08:00
epoh
38d4db5d5f Rename requirement.txt to requirements.txt (#352) 2023-09-26 09:38:14 +08:00
Archer
63cd379682 Add share link hook (#351) 2023-09-25 23:12:42 +08:00
Archer
9136c9306a Add OpenAPI docs;Correct the glm document (#346) 2023-09-25 14:28:44 +08:00
Byte Sound
c9db9f33ea Update intro.md (#348)
错别字,市区改为时区
2023-09-25 13:33:30 +08:00
Archer
3d7178d06f monorepo packages (#344) 2023-09-24 18:02:09 +08:00
Archer
a4ff5a3f73 perf: api key (#342) 2023-09-23 20:28:03 +08:00
Archer
814c5b3d3c Add bill of training and rate of file upload (#339) 2023-09-21 21:02:44 +08:00
Chen X
e7e0677291 Docs:add-workflow-case-全能助手 (#334) 2023-09-21 15:57:42 +08:00
634 changed files with 19401 additions and 26605 deletions

15
.github/imgs/logo-left.svg vendored Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

85
.github/workflows/docs-image.yml vendored Normal file
View File

@@ -0,0 +1,85 @@
name: Build FastGPT docs images and copy image to docker hub
on:
workflow_dispatch:
push:
paths:
- 'docSite/**'
branches:
- 'main'
tags:
- 'v*.*.*'
jobs:
build-fastgpt-images:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 1
- name: Set up QEMU (optional)
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
with:
driver-opts: network=host
- name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GH_PAT }}
- name: Set DOCKER_REPO_TAGGED based on branch or tag
run: |
if [[ "${{ github.ref_name }}" == "main" ]]; then
echo "DOCKER_REPO_TAGGED=ghcr.io/${{ github.repository_owner }}/fastgpt-docs:latest" >> $GITHUB_ENV
else
echo "DOCKER_REPO_TAGGED=ghcr.io/${{ github.repository_owner }}/fastgpt-docs:${{ github.ref_name }}" >> $GITHUB_ENV
fi
- name: Build and publish image for main branch or tag push event
env:
DOCKER_REPO_TAGGED: ${{ env.DOCKER_REPO_TAGGED }}
run: |
docker buildx build \
--build-arg name=app \
--platform linux/amd64,linux/arm64 \
--label "org.opencontainers.image.source= https://github.com/ ${{ github.repository_owner }}/FastGPT" \
--label "org.opencontainers.image.description=fastgpt image" \
--label "org.opencontainers.image.licenses=Apache" \
--push \
--cache-from=type=local,src=/tmp/.buildx-cache \
--cache-to=type=local,dest=/tmp/.buildx-cache \
-t ${DOCKER_REPO_TAGGED} \
-f docSite/Dockerfile \
.
push-to-docker-hub:
needs: build-fastgpt-images
runs-on: ubuntu-20.04
if: github.repository == 'labring/FastGPT'
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_HUB_NAME }}
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
- name: Set DOCKER_REPO_TAGGED based on branch or tag
run: |
if [[ "${{ github.ref_name }}" == "main" ]]; then
echo "IMAGE_TAG=latest" >> $GITHUB_ENV
else
echo "IMAGE_TAG=${{ github.ref_name }}" >> $GITHUB_ENV
fi
- name: Pull image from GitHub Container Registry
run: docker pull ghcr.io/${{ github.repository_owner }}/fastgpt-docs:${{env.IMAGE_TAG}}
- name: Tag image with Docker Hub repository name and version tag
run: docker tag ghcr.io/${{ github.repository_owner }}/fastgpt-docs:${{env.IMAGE_TAG}} ${{ secrets.DOCKER_IMAGE_NAME }}:${{env.IMAGE_TAG}}
- name: Push image to Docker Hub
run: docker push ${{ secrets.DOCKER_IMAGE_NAME }}:${{env.IMAGE_TAG}}

View File

@@ -1,9 +1,10 @@
name: Build fastgpt images and copy image to docker hub
name: Build FastGPT images and copy image to docker hub
on:
workflow_dispatch:
push:
paths:
- 'client/**'
- 'projects/app/**'
- 'packages/**'
branches:
- 'main'
tags:
@@ -49,12 +50,12 @@ jobs:
env:
DOCKER_REPO_TAGGED: ${{ env.DOCKER_REPO_TAGGED }}
run: |
cd client && \
docker buildx build \
--build-arg name=app \
--platform linux/amd64,linux/arm64 \
--label "org.opencontainers.image.source= https://github.com/ ${{ github.repository_owner }}/FastGPT" \
--label "org.opencontainers.image.description=fastgpt image" \
--label "org.opencontainers.image.licenses=MIT" \
--label "org.opencontainers.image.licenses=Apache" \
--push \
--cache-from=type=local,src=/tmp/.buildx-cache \
--cache-to=type=local,dest=/tmp/.buildx-cache \
@@ -64,6 +65,7 @@ jobs:
push-to-docker-hub:
needs: build-fastgpt-images
runs-on: ubuntu-20.04
if: github.repository == 'labring/FastGPT'
steps:
- name: Checkout code
uses: actions/checkout@v3
@@ -87,6 +89,7 @@ jobs:
run: docker push ${{ secrets.DOCKER_IMAGE_NAME }}:${{env.IMAGE_TAG}}
push-to-ali-hub:
needs: build-fastgpt-images
if: github.repository == 'labring/FastGPT'
runs-on: ubuntu-20.04
steps:
- name: Checkout code

52
.github/workflows/preview-image.yml vendored Normal file
View File

@@ -0,0 +1,52 @@
name: Preview FastGPT images
on:
pull_request_target:
paths:
- 'projects/app/**'
- 'packages/**'
branches:
- 'main'
workflow_dispatch:
jobs:
build-fastgpt-images:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
with:
driver-opts: network=host
- name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GH_PAT }}
- name: Set DOCKER_REPO_TAGGED based on branch or tag
run: |
echo "DOCKER_REPO_TAGGED=ghcr.io/${{ github.repository_owner }}/fastgpt-pr:${{ github.event.pull_request.number }}" >> $GITHUB_ENV
- name: Build image for PR
env:
DOCKER_REPO_TAGGED: ${{ env.DOCKER_REPO_TAGGED }}
run: |
docker buildx build \
--build-arg name=app \
--label "org.opencontainers.image.source= https://github.com/ ${{ github.repository_owner }}/FastGPT" \
--label "org.opencontainers.image.description=fastgpt-pr image" \
--label "org.opencontainers.image.licenses=Apache" \
--cache-from=type=local,src=/tmp/.buildx-cache \
--cache-to=type=local,dest=/tmp/.buildx-cache \
-t ${DOCKER_REPO_TAGGED} \
-f Dockerfile \
.

4
.gitignore vendored
View File

@@ -33,4 +33,6 @@ dist/
# hugo
**/.hugo_build.lock
docSite/public/
docSite/public/
docSite/resources/_gen/
docSite/.vercel

View File

@@ -1,10 +1,10 @@
{
"editor.formatOnSave": true,
"editor.mouseWheelZoom": true,
"typescript.tsdk": "client/node_modules/typescript/lib",
"prettier.prettierPath": "./node_modules/prettier",
"typescript.tsdk": "node_modules/typescript/lib",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"i18n-ally.localesPaths": [
"client/public/locales"
"projects/app/public/locales"
],
"i18n-ally.enabledParsers": ["json"],
"i18n-ally.keystyle": "nested",

72
Dockerfile Normal file
View File

@@ -0,0 +1,72 @@
# Install dependencies only when needed
FROM node:current-alpine AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat && npm install -g pnpm
WORKDIR /app
ARG name
# copy packages and one project
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY ./packages ./packages
COPY ./projects/$name/package.json ./projects/$name/package.json
COPY ./projects/$name/pnpm-lock.yaml ./projects/$name/pnpm-lock.yaml
RUN \
[ -f pnpm-lock.yaml ] && pnpm install || \
(echo "Lockfile not found." && exit 1)
RUN pnpm prune
# Rebuild the source code only when needed
FROM node:current-alpine AS builder
WORKDIR /app
ARG name
# copy common node_modules and one project node_modules
COPY --from=deps /app/node_modules ./node_modules
COPY --from=deps /app/packages ./packages
COPY ./projects/$name ./projects/$name
COPY --from=deps /app/projects/$name/node_modules ./projects/$name/node_modules
COPY pnpm-lock.yaml pnpm-workspace.yaml ./
COPY ./packages ./packages
# Uncomment the following line in case you want to disable telemetry during the build.
ENV NEXT_TELEMETRY_DISABLED 1
RUN npm install -g pnpm
RUN pnpm --filter=$name run build
FROM node:current-alpine AS runner
WORKDIR /app
ARG name
# create user and use it
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
RUN sed -i 's/https/http/' /etc/apk/repositories
RUN apk add curl \
&& apk add ca-certificates \
&& update-ca-certificates
# copy running files
COPY --from=builder /app/projects/$name/public ./projects/$name/public
COPY --from=builder /app/projects/$name/next.config.js ./projects/$name/next.config.js
COPY --from=builder --chown=nextjs:nodejs /app/projects/$name/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/projects/$name/.next/static ./projects/$name/.next/static
# copy package.json to version file
COPY --from=builder /app/projects/$name/package.json ./package.json
ENV NODE_ENV production
ENV NEXT_TELEMETRY_DISABLED 1
ENV PORT=3000
EXPOSE 3000
USER nextjs
ENV serverPath=./projects/$name/server.js
ENTRYPOINT ["sh","-c","node ${serverPath}"]

View File

@@ -4,23 +4,36 @@
# FastGPT
<p align="center">
<a href="./README_en.md">English</a> |
<a href="./README.md">简体中文</a>
</p>
FastGPT 是一个基于 LLM 大语言模型的知识库问答系统,提供开箱即用的数据处理、模型调用等能力。同时可以通过 Flow 可视化进行工作流编排,从而实现复杂的问答场景!
</div>
<p align="center">
<a href="https://fastgpt.run/">线上体验</a>
·
<a href="https://doc.fastgpt.run/docs/intro">相关文档</a>
·
<a href="https://doc.fastgpt.run/docs/development">本地开发</a>
·
<a href="https://github.com/labring/FastGPT#-%E7%9B%B8%E5%85%B3%E9%A1%B9%E7%9B%AE">相关项目</a>
<a href="https://fastgpt.run/">
<img height="21" src="https://img.shields.io/badge/在线使用-fff?style=flat-square&logo=spoj&logoColor=7d09f1" alt="cloud">
</a>
<a href="https://doc.fastgpt.run/docs/intro">
<img height="21" src="https://img.shields.io/badge/相关文档-7d09f1?style=flat-square" alt="document">
</a>
<a href="https://doc.fastgpt.run/docs/development">
<img height="21" src="https://img.shields.io/badge/本地开发-%23fff?style=flat-square&logo=xcode&logoColor=7d09f1" alt="development">
</a>
<a href="/#-%E7%9B%B8%E5%85%B3%E9%A1%B9%E7%9B%AE">
<img height="21" src="https://img.shields.io/badge/相关项目-7d09f1?style=flat-square" alt="project">
</a>
<a href="https://github.com/labring/FastGPT/blob/main/LICENSE">
<img height="21" src="https://img.shields.io/badge/License-Apache--2.0-ffffff?style=flat-square&labelColor=fff&color=7d09f1" alt="license">
</a>
</p>
https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409bd33f6d4
## 🛸 在线体验
## 🛸 在线使用
[fastgpt.run](https://fastgpt.run/)(服务器在新加坡,部分地区可能无法直连)
@@ -39,7 +52,7 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
- [x] 文本内容提取成结构化数据
- [x] HTTP 扩展
- [ ] 嵌入 Laf实现在线编写 HTTP 模块
- [ ] 连续对话引导
- [x] 对话下一步指引
- [ ] 对话多路线选择
- [x] 源文件引用追踪
- [ ] 自定义文件阅读器
@@ -55,7 +68,7 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
- [x] 知识库单点搜索测试
- [x] 对话时反馈引用并可修改与删除
- [x] 完整上下文呈现
- [ ] 完整模块中间值呈现
- [x] 完整模块中间值呈现
4. OpenAPI
- [x] completions 接口(对齐 GPT 接口)
- [ ] 知识库 CRUD
@@ -80,8 +93,8 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
* [部署 FastGPT](https://doc.fastgpt.run/docs/installation)
* [系统配置文件说明](https://doc.fastgpt.run/docs/development/configuration/)
* [多模型配置](https://doc.fastgpt.run/docs/installation/one-api/)
* [版本升级](https://doc.fastgpt.run/docs/installation/upgrading)
* [API 文档](https://kjqvjse66l.feishu.cn/docx/DmLedTWtUoNGX8xui9ocdUEjnNh?pre_pathname=%2Fdrive%2Fhome%2F)
* [版本更新/升级介绍](https://doc.fastgpt.run/docs/installation/upgrading)
* [API 文档](https://doc.fastgpt.run/docs/development/openapi/)
## 🏘️ 社区交流群
@@ -89,12 +102,6 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
![](https://otnvvf-imgs.oss.laf.run/wx300.jpg)
## 👀 其他
- [FastGPT 常见问题](https://kjqvjse66l.feishu.cn/docx/HtrgdT0pkonP4kxGx8qcu6XDnGh)
- [docker 部署教程视频](https://www.bilibili.com/video/BV1jo4y147fT/)
- [FastGPT 知识库演示](https://www.bilibili.com/video/BV1Wo4y1p7i1/)
## 💪 相关项目
- [Laf: 3 分钟快速接入三方应用](https://github.com/labring/laf)
@@ -102,10 +109,15 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
- [One API: 多模型管理,支持 Azure、文心一言等](https://github.com/songquanpeng/one-api)
- [TuShan: 5 分钟搭建后台管理系统](https://github.com/msgbyte/tushan)
## 👀 其他
- [保姆级 FastGPT 教程](https://www.bilibili.com/video/BV1n34y1A7Bo/?spm_id_from=333.999.0.0)
- [接入飞书](https://www.bilibili.com/video/BV1Su4y1r7R3/?spm_id_from=333.999.0.0)
- [接入企微](https://www.bilibili.com/video/BV1Tp4y1n72T/?spm_id_from=333.999.0.0)
## 🤝 第三方生态
- [OnWeChat 个人微信/企微机器人](https://doc.fastgpt.run/docs/use-cases/onwechat/)
- [luolinAI: 企微机器人,开箱即用](https://github.com/luolin-ai/FastGPT-Enterprise-WeChatbot)
## 🌟 Star History
@@ -115,7 +127,7 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
本仓库遵循 [FastGPT Open Source License](./LICENSE) 开源协议。
1. 允许作为后台服务直接商用,但不允许直接使用 saas 服务商用。
1. 允许作为后台服务直接商用,但不允许直接使用 SaaS 服务商用。
2. 需保留相关版权信息。
3. 完整请查看 [FastGPT Open Source License](./LICENSE)
4. 联系方式yujinlong@sealos.io, [点击查看定价策略](https://fael3z0zfze.feishu.cn/docx/F155dbirfo8vDDx2WgWc6extnwf)
4. 联系方式yujinlong@sealos.io, [点击查看定价策略](https://doc.fastgpt.run/docs/commercial)

View File

@@ -1,25 +1,39 @@
<div align="center">
<a href="https://fastgpt.run/"><img src="/.github/imgs/logo.svg" width="120" height="120" alt="fastgpt logo"></a>
# FastGPT
FastGPT is a knowledge-based question answering system built on the LLM. It offers out-of-the-box data processing and model invocation capabilities. Moreover, it allows for workflow orchestration through Flow visualization, thereby enabling complex question and answer scenarios!
<p align="center">
<a href="./README_en.md">English</a> |
<a href="./README.md">简体中文</a>
</p>
FastGPT is a knowledge-based Q&A system built on the LLM, offers out-of-the-box data processing and model invocation capabilities, allows for workflow orchestration through Flow visualization!
</div>
<p align="center">
<a href="https://fastgpt.run/">Online</a>
·
<a href="https://doc.fastgpt.run/docs/intro">Document</a>
·
<a href="https://doc.fastgpt.run/docs/development">Development</a>
·
<a href="https://doc.fastgpt.run/docs/installation">Deploy</a>
·
<a href="#powered-by">Power By</a>
<a href="https://fastgpt.run/">
<img height="21" src="https://img.shields.io/badge/Website-fff?style=flat-square&logo=spoj&logoColor=7d09f1" alt="cloud">
</a>
<a href="https://doc.fastgpt.run/docs/intro">
<img height="21" src="https://img.shields.io/badge/Docs-7d09f1?style=flat-square" alt="document">
</a>
<a href="https://doc.fastgpt.run/docs/development">
<img height="21" src="https://img.shields.io/badge/Development-%23fff?style=flat-square&logo=xcode&logoColor=7d09f1" alt="development">
</a>
<a href="/#-%E7%9B%B8%E5%85%B3%E9%A1%B9%E7%9B%AE">
<img height="21" src="https://img.shields.io/badge/Related Projects-7d09f1?style=flat-square" alt="project">
</a>
<a href="https://github.com/labring/FastGPT/blob/main/LICENSE">
<img height="21" src="https://img.shields.io/badge/License-Apache--2.0-ffffff?style=flat-square&labelColor=fff&color=7d09f1" alt="license">
</a>
</p>
## 🛸 Online
https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409bd33f6d4
## 🛸 Use Cloud Services
[fastgpt.run](https://fastgpt.run/)
| | |
@@ -29,35 +43,34 @@ FastGPT is a knowledge-based question answering system built on the LLM. It offe
## 💡 Features
1. Powerful visual orchestration for easy AI application building
1. Powerful visual workflows: Effortlessly craft AI applications
- [x] Provides a simple mode without the need for orchestration operations
- [x] Simple mode on deck - no need for manual arrangement
- [x] User dialogue pre-guidance
- [x] Global variables
- [x] Knowledge base search
- [x] Multi-LLM model dialogue
- [x] Extraction of text content into structured data
- [x] HTTP extension
- [ ] Sandbox JS runtime module
- [ ] Continuous dialogue guidance
- [ ] Dialogue multi-path selection
- [ ] Source file reference tracking
- [x] Dialogue via multiple LLM models
- [x] Text magic - convert to structured data
- [x] Extend with HTTP
- [ ] Embed Laf for on-the-fly HTTP module crafting
- [x] Directions for the next dialogue steps
- [ ] Multiple dialogue paths selection
- [x] Tracking source file references
- [ ] Custom file reader
2. Rich knowledge base preprocessing
2. Extensive knowledge base preprocessing
- [x] Multiple library reuse and mixing
- [x] Chunk record modification and deletion
- [x] Supports direct segment import
- [x] Supports QA split import
- [x] Supports manual input content
- [ ] Supports URL import reading
- [x] Supports batch import of Q&A pairs in CSV format
- [ ] Supports separate vector model settings for knowledge bases
- [ ] Source file storage
- [x] Reuse and mix multiple knowledge bases
- [x] Track chunk modifications and deletions
- [x] Supports manual entries, direct segmentation, and QA split imports
- [x] Supports URL fetching and batch CSV imports
- [x] Supports Set unique vector models for knowledge bases
- [x] Store original files
- [ ] File learning Agent
3. Multiple effect testing channels
- [x] Knowledge base single point search testing
- [x] Single-point knowledge base search test
- [x] Feedback references and ability to modify and delete during dialogue
- [x] Complete context presentation
- [ ] Complete module intermediate value presentation
@@ -77,11 +90,17 @@ FastGPT is a knowledge-based question answering system built on the LLM. It offe
Project tech stack: NextJs + TS + ChakraUI + Mongo + Postgres (Vector plugin)
- **⚡ Deployment**
[![](https://cdn.jsdelivr.us/gh/labring-actions/templates@main/Deploy-on-Sealos.svg)](https://cloud.sealos.io/?openapp=system-fastdeploy%3FtemplateName%3Dfastgpt)
Give it a 2-4 minute wait after deployment as it sets up the database. Initially, it might be a tad slow since we're using the basic settings.
- [Getting Started with Local Development](https://doc.fastgpt.run/docs/development)
- [Deploying FastGPT](https://doc.fastgpt.run/docs/installation)
- [System Configuration File Explanation](https://doc.fastgpt.run/docs/installation/reference)
- [Multi-model Configuration](https://doc.fastgpt.run/docs/installation/reference/models)
- [V3 Upgrade V4 Initialization](https://doc.fastgpt.run/docs/installation/upgrading)
- [Guide on System Configs](https://doc.fastgpt.run/docs/installation/reference)
- [Configuring Multiple Models](https://doc.fastgpt.run/docs/installation/reference/models)
- [Version Updates & Upgrades](https://doc.fastgpt.run/docs/installation/upgrading)
<!-- ## :point_right: RoadMap
- [FastGPT RoadMap](https://kjqvjse66l.feishu.cn/docx/RVUxdqE2WolDYyxEKATcM0XXnte) -->

View File

@@ -1,65 +0,0 @@
# Install dependencies only when needed
FROM node:current-alpine AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat && npm install -g pnpm
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json ./
COPY pnpm-lock.yaml* ./
RUN \
[ -f pnpm-lock.yaml ] && pnpm fetch || \
(echo "Lockfile not found." && exit 1)
# Rebuild the source code only when needed
FROM node:current-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY pnpm-lock.yaml* ./
COPY package.json ./
COPY . .
# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
ENV NEXT_TELEMETRY_DISABLED 1
RUN npm install -g pnpm
RUN \
[ -f pnpm-lock.yaml ] && (pnpm --offline install && pnpm run build) || \
(echo "Lockfile not found." && exit 1)
# Production image, copy all the files and run next
FROM node:current-alpine AS runner
WORKDIR /app
ENV NODE_ENV production
# Uncomment the following line in case you want to disable telemetry during runtime.
ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
RUN sed -i 's/https/http/' /etc/apk/repositories
RUN apk add curl \
&& apk add ca-certificates \
&& update-ca-certificates
# You only need to copy next.config.js if you are NOT using the default configuration
# COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
# COPY --from=builder /app/.env* .
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
ENV PORT=3000
EXPOSE 3000
CMD ["node", "server.js"]

View File

@@ -1,5 +0,0 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

View File

@@ -1,9 +0,0 @@
### Fast GPT V4.4.4
1. 去除 - 限定词。目前旧应用仍生效9/25 后全面去除,请及时替换。
2. 新增 - 引用模板/引用提示词设置,可以 DIY 引用内容的格式,从而更好的适配场景。
3. 优化 - 更好的兼容无 system role 的模型。
4. 优化 - icon 和 JS 加载逻辑。
5. [使用文档](https://doc.fastgpt.run/docs/intro/)
6. [点击查看高级编排介绍文档](https://doc.fastgpt.run/docs/workflow)
7. [点击查看商业版](https://doc.fastgpt.run/docs/commercial/)

View File

@@ -1,16 +0,0 @@
import { GET, POST, DELETE } from './request';
import { UserOpenApiKey } from '@/types/openapi';
/**
* crete a api key
*/
export const createAOpenApiKey = () => POST<string>('/openapi/postKey');
/**
* get api keys
*/
export const getOpenApiKeys = () => GET<UserOpenApiKey[]>('/openapi/getKeys');
/**
* delete api by id
*/
export const delOpenApiById = (id: string) => DELETE(`/openapi/delKey?id=${id}`);

View File

@@ -1,144 +0,0 @@
import React, { useState } from 'react';
import {
Box,
Button,
Flex,
ModalFooter,
ModalBody,
Table,
Thead,
Tbody,
Tr,
Th,
Td,
TableContainer,
IconButton
} from '@chakra-ui/react';
import { getOpenApiKeys, createAOpenApiKey, delOpenApiById } from '@/api/openapi';
import { useQuery, useMutation } from '@tanstack/react-query';
import { useLoading } from '@/hooks/useLoading';
import dayjs from 'dayjs';
import { AddIcon, DeleteIcon } from '@chakra-ui/icons';
import { getErrText } from '@/utils/tools';
import { useCopyData } from '@/hooks/useCopyData';
import { useToast } from '@/hooks/useToast';
import MyIcon from '../Icon';
import MyModal from '../MyModal';
const APIKeyModal = ({ onClose }: { onClose: () => void }) => {
const { Loading } = useLoading();
const { toast } = useToast();
const {
data: apiKeys = [],
isLoading: isGetting,
refetch
} = useQuery(['getOpenApiKeys'], getOpenApiKeys);
const [apiKey, setApiKey] = useState('');
const { copyData } = useCopyData();
const { mutate: onclickCreateApiKey, isLoading: isCreating } = useMutation({
mutationFn: () => createAOpenApiKey(),
onSuccess(res) {
setApiKey(res);
refetch();
},
onError(err) {
toast({
status: 'warning',
title: getErrText(err)
});
}
});
const { mutate: onclickRemove, isLoading: isDeleting } = useMutation({
mutationFn: async (id: string) => delOpenApiById(id),
onSuccess() {
refetch();
}
});
return (
<MyModal isOpen onClose={onClose} w={'600px'}>
<Box py={3} px={5}>
<Box fontWeight={'bold'} fontSize={'2xl'}>
API
</Box>
<Box fontSize={'sm'} color={'myGray.600'}>
API 使~
</Box>
</Box>
<ModalBody minH={'300px'} maxH={['70vh', '500px']} overflow={'overlay'}>
<TableContainer mt={2} position={'relative'}>
<Table>
<Thead>
<Tr>
<Th>Api Key</Th>
<Th></Th>
<Th>使</Th>
<Th />
</Tr>
</Thead>
<Tbody fontSize={'sm'}>
{apiKeys.map(({ id, apiKey, createTime, lastUsedTime }) => (
<Tr key={id}>
<Td>{apiKey}</Td>
<Td>{dayjs(createTime).format('YYYY/MM/DD HH:mm:ss')}</Td>
<Td>
{lastUsedTime
? dayjs(lastUsedTime).format('YYYY/MM/DD HH:mm:ss')
: '没有使用过'}
</Td>
<Td>
<IconButton
icon={<DeleteIcon />}
size={'xs'}
aria-label={'delete'}
variant={'base'}
colorScheme={'gray'}
onClick={() => onclickRemove(id)}
/>
</Td>
</Tr>
))}
</Tbody>
</Table>
</TableContainer>
</ModalBody>
<ModalFooter>
<Button
variant="base"
leftIcon={<AddIcon color={'myGray.600'} fontSize={'sm'} />}
onClick={() => onclickCreateApiKey()}
>
</Button>
</ModalFooter>
<Loading loading={isGetting || isCreating || isDeleting} fixed={false} />
<MyModal isOpen={!!apiKey} w={'400px'} onClose={() => setApiKey('')}>
<Box py={3} px={5}>
<Box fontWeight={'bold'} fontSize={'2xl'}>
API
</Box>
<Box fontSize={'sm'} color={'myGray.600'}>
~
</Box>
</Box>
<ModalBody>
<Flex bg={'myGray.100'} px={3} py={2} cursor={'pointer'} onClick={() => copyData(apiKey)}>
<Box flex={1}>{apiKey}</Box>
<MyIcon name={'copy'} w={'16px'}></MyIcon>
</Flex>
</ModalBody>
<ModalFooter>
<Button variant="base" onClick={() => setApiKey('')}>
</Button>
</ModalFooter>
</MyModal>
</MyModal>
);
};
export default APIKeyModal;

View File

@@ -1,58 +0,0 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { authUser } from '@/service/utils/auth';
import { connectToDatabase, Chat } from '@/service/mongo';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await authUser({ req, authRoot: true });
await connectToDatabase();
const { limit = 1000 } = req.body as { limit: number };
let skip = 0;
const total = await Chat.countDocuments({
chatId: { $exists: false }
});
let promise = Promise.resolve();
console.log(total);
for (let i = 0; i < total; i += limit) {
const skipVal = skip;
skip += limit;
promise = promise
.then(() => init(limit, skipVal))
.then(() => {
console.log(skipVal);
});
}
await promise;
jsonRes(res, {});
} catch (error) {
jsonRes(res, {
code: 500,
error
});
}
}
async function init(limit: number, skip: number) {
// 遍历 app
const chats = await Chat.find(
{
chatId: { $exists: false }
},
'_id'
).limit(limit);
await Promise.all(
chats.map((chat) =>
Chat.findByIdAndUpdate(chat._id, {
chatId: String(chat._id),
source: 'online'
})
)
);
}

View File

@@ -1,98 +0,0 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { authUser } from '@/service/utils/auth';
import { connectToDatabase, Chat, ChatItem } from '@/service/mongo';
import { customAlphabet } from 'nanoid';
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 24);
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await authUser({ req, authRoot: true });
await connectToDatabase();
const { limit = 100 } = req.body as { limit: number };
let skip = 0;
const total = await Chat.countDocuments({
content: { $exists: true, $not: { $size: 0 } },
isInit: { $ne: true }
});
const totalChat = await Chat.aggregate([
{
$project: {
contentLength: { $size: '$content' }
}
},
{
$group: {
_id: null,
totalLength: { $sum: '$contentLength' }
}
}
]);
console.log('chatLen:', total, totalChat);
let promise = Promise.resolve();
for (let i = 0; i < total; i += limit) {
const skipVal = skip;
skip += limit;
promise = promise
.then(() => init(limit))
.then(() => {
console.log(skipVal);
});
}
await promise;
jsonRes(res, {});
} catch (error) {
jsonRes(res, {
code: 500,
error
});
}
}
async function init(limit: number) {
// 遍历 app
const chats = await Chat.find(
{
content: { $exists: true, $not: { $size: 0 } },
isInit: { $ne: true }
},
'_id userId appId chatId content'
)
.sort({ updateTime: -1 })
.limit(limit);
await Promise.all(
chats.map(async (chat) => {
const inserts = chat.content
.map((item) => ({
dataId: nanoid(),
chatId: chat.chatId,
userId: chat.userId,
appId: chat.appId,
obj: item.obj,
value: item.value,
responseData: item.responseData
}))
.filter((item) => item.chatId && item.userId && item.appId && item.obj && item.value);
try {
await Promise.all(inserts.map((item) => ChatItem.create(item)));
await Chat.findByIdAndUpdate(chat._id, {
isInit: true
});
} catch (error) {
console.log(error);
await ChatItem.deleteMany({ chatId: chat.chatId });
}
})
);
}

View File

@@ -1,27 +0,0 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { authUser } from '@/service/utils/auth';
import { connectToDatabase, OutLink } from '@/service/mongo';
import { OutLinkTypeEnum } from '@/constants/chat';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await authUser({ req, authRoot: true });
await connectToDatabase();
await OutLink.updateMany(
{},
{
$set: { type: OutLinkTypeEnum.share }
}
);
jsonRes(res, {});
} catch (error) {
jsonRes(res, {
code: 500,
error
});
}
}

View File

@@ -1,86 +0,0 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase } from '@/service/mongo';
import { authKb, authUser } from '@/service/utils/auth';
import { withNextCors } from '@/service/utils/tools';
import { PgDatasetTableName } from '@/constants/plugin';
import { insertData2Dataset, PgClient } from '@/service/pg';
import { getVectorModel } from '@/service/utils/data';
import { getVector } from '@/pages/api/openapi/plugin/vector';
import { DatasetDataItemType } from '@/types/core/dataset/data';
import { countPromptTokens } from '@/utils/common/tiktoken';
export type Props = {
kbId: string;
data: DatasetDataItemType;
};
export default withNextCors(async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
await connectToDatabase();
const { kbId, data = { q: '', a: '' } } = req.body as Props;
if (!kbId || !data?.q) {
throw new Error('缺少参数');
}
// 凭证校验
const { userId } = await authUser({ req });
// auth kb
const kb = await authKb({ kbId, userId });
const q = data?.q?.replace(/\\n/g, '\n').trim().replace(/'/g, '"');
const a = data?.a?.replace(/\\n/g, '\n').trim().replace(/'/g, '"');
// token check
const token = countPromptTokens(q, 'system');
if (token > getVectorModel(kb.vectorModel).maxToken) {
throw new Error('Over Tokens');
}
const { rows: existsRows } = await PgClient.query(`
SELECT COUNT(*) > 0 AS exists
FROM ${PgDatasetTableName}
WHERE md5(q)=md5('${q}') AND md5(a)=md5('${a}') AND user_id='${userId}' AND kb_id='${kbId}'
`);
const exists = existsRows[0]?.exists || false;
if (exists) {
throw new Error('已经存在完全一致的数据');
}
const { vectors } = await getVector({
model: kb.vectorModel,
input: [q],
userId
});
const response = await insertData2Dataset({
userId,
kbId,
data: [
{
q,
a,
source: data.source,
vector: vectors[0]
}
]
});
// @ts-ignore
const id = response?.rows?.[0]?.id || '';
jsonRes(res, {
data: id
});
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
});

View File

@@ -1,37 +0,0 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase, OpenApi } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import { UserOpenApiKey } from '@/types/openapi';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const { userId } = await authUser({ req, authToken: true });
await connectToDatabase();
const findResponse = await OpenApi.find({ userId }).sort({ _id: -1 });
// jus save four data
const apiKeys = findResponse.map<UserOpenApiKey>(
({ _id, apiKey, createTime, lastUsedTime }) => {
return {
id: _id,
apiKey: `******${apiKey.substring(apiKey.length - 4)}`,
createTime,
lastUsedTime
};
}
);
jsonRes(res, {
data: apiKeys
});
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
}

View File

@@ -1,96 +0,0 @@
import React, { useEffect, useState } from 'react';
import { Box, Divider, Flex, useTheme, Button, Skeleton, useDisclosure } from '@chakra-ui/react';
import { useCopyData } from '@/hooks/useCopyData';
import dynamic from 'next/dynamic';
import MyIcon from '@/components/Icon';
import { useGlobalStore } from '@/store/global';
import { feConfigs } from '@/store/static';
const APIKeyModal = dynamic(() => import('@/components/APIKeyModal'), {
ssr: false
});
const API = ({ appId }: { appId: string }) => {
const theme = useTheme();
const { copyData } = useCopyData();
const [baseUrl, setBaseUrl] = useState('https://fastgpt.run/api/openapi');
const {
isOpen: isOpenAPIModal,
onOpen: onOpenAPIModal,
onClose: onCloseAPIModal
} = useDisclosure();
const [isLoaded, setIsLoaded] = useState(false);
const { isPc } = useGlobalStore();
useEffect(() => {
setBaseUrl(`${location.origin}/api/openapi`);
}, []);
return (
<Flex flexDirection={'column'} pt={[0, 5]} h={'100%'}>
<Flex px={5} alignItems={'center'}>
<Box flex={1}>
AppId:
<Box
as={'span'}
ml={2}
fontWeight={'bold'}
cursor={'pointer'}
onClick={() => copyData(appId, '已复制 AppId')}
>
{appId}
</Box>
</Box>
{isPc && (
<>
<Flex
bg={'myWhite.600'}
py={2}
px={4}
borderRadius={'md'}
cursor={'pointer'}
onClick={() => copyData(baseUrl, '已复制 API 地址')}
>
<Box border={theme.borders.md} px={2} borderRadius={'md'} fontSize={'sm'}>
API服务器
</Box>
<Box ml={2} color={'myGray.900'} fontSize={['sm', 'md']}>
{baseUrl}
</Box>
</Flex>
<Button
ml={3}
leftIcon={<MyIcon name={'apikey'} w={'16px'} color={''} />}
variant={'base'}
onClick={onOpenAPIModal}
>
API
</Button>
</>
)}
</Flex>
<Divider mt={3} />
<Box flex={'1 0 0'} h={0}>
<Skeleton h="100%" isLoaded={isLoaded} fadeDuration={2}>
<iframe
style={{
width: '100%',
height: '100%'
}}
src={
feConfigs?.openAPIUrl ||
'https://kjqvjse66l.feishu.cn/docx/DmLedTWtUoNGX8xui9ocdUEjnNh'
}
frameBorder="0"
onLoad={() => setIsLoaded(true)}
onError={() => setIsLoaded(true)}
/>
</Skeleton>
</Box>
{isOpenAPIModal && <APIKeyModal onClose={onCloseAPIModal} />}
</Flex>
);
};
export default API;

View File

@@ -1,59 +0,0 @@
import React, { useMemo } from 'react';
import { NodeProps } from 'reactflow';
import { Box, Flex, Textarea } from '@chakra-ui/react';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import NodeCard from '../modules/NodeCard';
import { FlowModuleItemType } from '@/types/flow';
import Container from '../modules/Container';
import { SystemInputEnum } from '@/constants/app';
import MyIcon from '@/components/Icon';
import MyTooltip from '@/components/MyTooltip';
import { welcomeTextTip } from '@/constants/flow/ModuleTemplate';
const NodeUserGuide = ({ data }: NodeProps<FlowModuleItemType>) => {
const { inputs, moduleId, onChangeNode } = data;
const welcomeText = useMemo(
() => inputs.find((item) => item.key === SystemInputEnum.welcomeText),
[inputs]
);
return (
<>
<NodeCard minW={'300px'} {...data}>
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'}>
<>
<Flex mb={1} alignItems={'center'}>
<MyIcon name={'welcomeText'} mr={2} w={'16px'} color={'#E74694'} />
<Box></Box>
<MyTooltip label={welcomeTextTip} forceShow>
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
</MyTooltip>
</Flex>
{welcomeText && (
<Textarea
className="nodrag"
rows={6}
resize={'both'}
defaultValue={welcomeText.value}
bg={'myWhite.500'}
placeholder={welcomeTextTip}
onChange={(e) => {
onChangeNode({
moduleId,
key: SystemInputEnum.welcomeText,
type: 'inputs',
value: {
...welcomeText,
value: e.target.value
}
});
}}
/>
)}
</>
</Container>
</NodeCard>
</>
);
};
export default React.memo(NodeUserGuide);

View File

@@ -1,179 +0,0 @@
import { connectToDatabase, Bill, User, OutLink } from '../mongo';
import { BillSourceEnum } from '@/constants/user';
import { getModel } from '../utils/data';
import { ChatHistoryItemResType } from '@/types/chat';
import { formatPrice } from '@/utils/user';
import { addLog } from '../utils/tools';
export const pushTaskBill = async ({
appName,
appId,
userId,
source,
shareId,
response
}: {
appName: string;
appId: string;
userId: string;
source: `${BillSourceEnum}`;
shareId?: string;
response: ChatHistoryItemResType[];
}) => {
try {
const total = response.reduce((sum, item) => sum + item.price, 0);
await Promise.allSettled([
Bill.create({
userId,
appName,
appId,
total,
source,
list: response.map((item) => ({
moduleName: item.moduleName,
amount: item.price || 0,
model: item.model,
tokenLen: item.tokens
}))
}),
User.findByIdAndUpdate(userId, {
$inc: { balance: -total }
}),
...(shareId
? [
updateShareChatBill({
shareId,
total
})
]
: [])
]);
addLog.info(`finish completions`, {
source,
userId,
price: formatPrice(total)
});
} catch (error) {
addLog.error(`pushTaskBill error`, error);
}
};
export const updateShareChatBill = async ({
shareId,
total
}: {
shareId: string;
total: number;
}) => {
try {
await OutLink.findOneAndUpdate(
{ shareId },
{
$inc: { total },
lastTime: new Date()
}
);
} catch (err) {
addLog.error('update shareChat error', err);
}
};
export const pushQABill = async ({
userId,
totalTokens,
appName
}: {
userId: string;
totalTokens: number;
appName: string;
}) => {
addLog.info('splitData generate success', { totalTokens });
let billId;
try {
await connectToDatabase();
// 获取模型单价格, 都是用 gpt35 拆分
const unitPrice = global.qaModel.price || 3;
// 计算价格
const total = unitPrice * totalTokens;
// 插入 Bill 记录
const res = await Bill.create({
userId,
appName,
tokenLen: totalTokens,
total
});
billId = res._id;
// 账号扣费
await User.findByIdAndUpdate(userId, {
$inc: { balance: -total }
});
} catch (err) {
addLog.error('Create completions bill error', err);
billId && Bill.findByIdAndDelete(billId);
}
};
export const pushGenerateVectorBill = async ({
userId,
tokenLen,
model
}: {
userId: string;
tokenLen: number;
model: string;
}) => {
let billId;
try {
await connectToDatabase();
try {
// 计算价格. 至少为1
const vectorModel =
global.vectorModels.find((item) => item.model === model) || global.vectorModels[0];
const unitPrice = vectorModel.price || 0.2;
let total = unitPrice * tokenLen;
total = total > 1 ? total : 1;
// 插入 Bill 记录
const res = await Bill.create({
userId,
model: vectorModel.model,
appName: '索引生成',
total,
list: [
{
moduleName: '索引生成',
amount: total,
model: vectorModel.model,
tokenLen
}
]
});
billId = res._id;
// 账号扣费
await User.findByIdAndUpdate(userId, {
$inc: { balance: -total }
});
} catch (err) {
addLog.error('Create generateVector bill error', err);
billId && Bill.findByIdAndDelete(billId);
}
} catch (error) {
console.log(error);
}
};
export const countModelPrice = ({ model, tokens }: { model: string; tokens: number }) => {
const modelData = getModel(model);
if (!modelData) return 0;
return modelData.price * tokens;
};

View File

@@ -1,23 +0,0 @@
import { Schema, model, models, Model } from 'mongoose';
import { OpenApiSchema } from '@/types/mongoSchema';
const OpenApiSchema = new Schema({
userId: {
type: Schema.Types.ObjectId,
ref: 'user',
required: true
},
apiKey: {
type: String,
required: true
},
createTime: {
type: Date,
default: () => new Date()
},
lastUsedTime: {
type: Date
}
});
export const OpenApi: Model<OpenApiSchema> = models['openapi'] || model('openapi', OpenApiSchema);

View File

@@ -1,79 +0,0 @@
import { PRICE_SCALE } from '@/constants/common';
import { IpLimit } from '@/service/common/ipLimit/schema';
import { authBalanceByUid, AuthUserTypeEnum } from '@/service/utils/auth';
import { OutLinkSchema } from '@/types/support/outLink';
import { OutLink } from './schema';
export async function authOutLinkChat({ shareId, ip }: { shareId: string; ip?: string | null }) {
// get outLink
const outLink = await OutLink.findOne({
shareId
});
if (!outLink) {
return Promise.reject('分享链接无效');
}
const uid = String(outLink.userId);
// authBalance
const user = await authBalanceByUid(uid);
// limit auth
await authOutLinkLimit({ outLink, ip });
return {
user,
userId: String(outLink.userId),
appId: String(outLink.appId),
authType: AuthUserTypeEnum.token,
responseDetail: outLink.responseDetail
};
}
export async function authOutLinkLimit({
outLink,
ip
}: {
outLink: OutLinkSchema;
ip?: string | null;
}) {
if (!ip || !outLink.limit) {
return;
}
if (outLink.limit.expiredTime && outLink.limit.expiredTime.getTime() < Date.now()) {
return Promise.reject('分享链接已过期');
}
if (outLink.limit.credit > -1 && outLink.total > outLink.limit.credit * PRICE_SCALE) {
return Promise.reject('链接超出使用限制');
}
const ipLimit = await IpLimit.findOne({ ip, eventId: outLink._id });
try {
if (!ipLimit) {
await IpLimit.create({
eventId: outLink._id,
ip,
account: outLink.limit.QPM - 1
});
return;
}
// over one minute
const diffTime = Date.now() - ipLimit.lastMinute.getTime();
if (diffTime >= 60 * 1000) {
ipLimit.account = outLink.limit.QPM - 1;
ipLimit.lastMinute = new Date();
return await ipLimit.save();
}
if (ipLimit.account <= 0) {
return Promise.reject(
`每分钟仅能请求 ${outLink.limit.QPM} 次, ${60 - Math.round(diffTime / 1000)}s 后重试~`
);
}
ipLimit.account = ipLimit.account - 1;
await ipLimit.save();
} catch (error) {}
}

View File

@@ -1,6 +0,0 @@
export interface UserOpenApiKey {
id: string;
apiKey: string;
createTime: Date;
lastUsedTime?: Date;
}

View File

@@ -1,28 +0,0 @@
export const hasVoiceApi = typeof window !== 'undefined' && 'speechSynthesis' in window;
/**
* voice broadcast
*/
export const voiceBroadcast = ({ text }: { text: string }) => {
window.speechSynthesis?.cancel();
const msg = new SpeechSynthesisUtterance(text);
const voices = window.speechSynthesis?.getVoices?.(); // 获取语言包
const voice = voices.find((item) => {
return item.name === 'Microsoft Yaoyao - Chinese (Simplified, PRC)';
});
if (voice) {
msg.voice = voice;
}
window.speechSynthesis?.speak(msg);
msg.onerror = (e) => {
console.log(e);
};
return {
cancel: () => window.speechSynthesis?.cancel()
};
};
export const cancelBroadcast = () => {
window.speechSynthesis?.cancel();
};

12
docSite/Dockerfile Normal file
View File

@@ -0,0 +1,12 @@
FROM hugomods/hugo:0.117.0 AS builder
WORKDIR /app
ADD ./docSite hugo
RUN cd /app/hugo && hugo mod get -u github.com/colinwilson/lotusdocs && hugo -v --minify
FROM fholzer/nginx-brotli:latest
LABEL org.opencontainers.image.source https://github.com/labring/FastGPT
COPY --from=builder /app/hugo/public /usr/share/nginx/html

View File

@@ -96,4 +96,50 @@ footer a:hover {
}
.github-badge .bg-lightgrey, .github-badge .bg-lightgray {
background-color: #9f9f9f !important;
}
#fixed-box {
position: fixed;
z-index: 9999;
}
@media (max-width: 600px) {
#fixed-box {
display: none
}
}
.feedback-btn-wrapper {
position: fixed;
z-index: 1000;
bottom: 0;
left: 0;
margin: 2rem;
}
#feedback-btn {
height: 30px;
display: flex;
align-items: center;
padding: 1.2rem 0.7rem;
border-radius: 0.4rem;
cursor: pointer;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1),
0 4px 6px -2px rgba(0, 0, 0, 0.05);
user-select: none;
border: 0;
outline: 0;
color: #fff;
background-color: #4d698e;
transition: filter 0.4s ease;
}
#feedback-btn svg {
width: 1.25rem;
height: 1.25rem;
}
#feedback-btn span {
font-weight: 700;
font-size: 1rem;
margin-left: 0.5rem;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 196 KiB

After

Width:  |  Height:  |  Size: 436 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -1,11 +0,0 @@
{
"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/*"
]
}
}
}

View File

@@ -20,20 +20,24 @@ weight: 20
1. 自定义 title 和 logo
2. 用户注册,支付 (已有微信扫码支付,后续会补充支付方式)
3. 团队空间 (下期开发)
4. 完善的 OpenAPI
5. 高级编排额外插件
6. 后台管理系统 (已有,持续更新
3. API 访问限制,可配置:额度、过期时间
4. 团队空间 (计划)
5. 完善的 OpenAPI计划
6. 高级编排额外插件(计划
7. 后台管理系统
a. 查询:用户、支付、应用、知识库
b. 变更:用户
c. 新增:用户
{{% /alert %}}
### 商业版定价
#### 交付费用
+ 使用 [Sealos 公有云](https://sealos.io)交付1w/年/套 (直接在 Sealos 公有云充值,便可**免费获取 FastGPT 商业版 License**,同时您充值的金额可用于部署其他云资源,相当于白嫖了一个 FastGPT 商业版)。
+ 渠道商使用 Sealos 交付:返现 20% 成交额。
+ 私有服务器交付2w/年/套(如需部署支持,按技术服务费计算)
+ 渠道商私有服务器交付1.3w/年/套(渠道商合同单独约谈,累计 5 套以上可签)
+ 使用 [Sealos 公有云](https://sealos.io)部署1万元/年/套 (无部署费用。赠送 8000 sealos 公有云额度,可用于 FastGPT 或其他云资源)。
+ 渠道商使用 Sealos 部署:返现 20% 成交额。
+ 私有服务器部署2万元/年/套(如需部署支持,按技术服务费计算)
+ 渠道商私有服务器部署1.3万元/年/套(渠道商合同单独约谈,累计 5 套以上可签)
#### 用户注册数量费用(按注册量算,不计量分享和 API
@@ -49,7 +53,7 @@ weight: 20
#### 总费用
总费用 = 商业版功能费用 + 用户数量费用
总费用 = 商业版交付费用 + 用户数量费用
## 技术支持
@@ -69,7 +73,7 @@ weight: 20
## 联系方式
通过邮箱联系 yujinlong@sealos.io
请填写[咨询问卷](https://fael3z0zfze.feishu.cn/share/base/form/shrcnRxj3utrzjywsom96Px4sud),我们会尽快与您联系。
## QA
@@ -77,7 +81,7 @@ weight: 20
完整版应用 = 开源版镜像 + 商业版镜像
我们会提供一个商业版镜像给你使用,还会提供一个简单的后台管理系统(目前只设置了简单的查询功能)
我们会提供一个商业版镜像给你使用,该镜像需要一个 license 启动license 有效期为 1 年。此外,还会提供一个简单的后台管理系统(目前只设置了简单的查询功能)
2. 二次开发如何操作?

View File

@@ -62,19 +62,18 @@ Authorization 为 sk-aaabbbcccdddeeefffggghhhiiijjjkkk。model 为刚刚在 One
修改 config.json 配置文件,在 VectorModels 中加入 chatglm2 和 M3E 模型:
```json
"ChatModels": [
//已有模型
{
"model": "chatglm2",
"name": "chatglm2",
"contextMaxToken": 8000,
"quoteMaxToken": 4000,
"maxTemperature": 1.2,
"price": 0,
"defaultSystem": ""
}
],
"ChatModels": [
//已有模型
{
"model": "chatglm2",
"name": "chatglm2",
"contextMaxToken": 8000,
"quoteMaxToken": 4000,
"maxTemperature": 1.2,
"price": 0,
"defaultSystem": ""
}
],
"VectorModels": [
{
"model": "text-embedding-ada-002",

View File

@@ -48,8 +48,8 @@ ChatGLM2-6B 是开源中英双语对话模型 ChatGLM-6B 的第二代版本,
1. 根据上面的环境配置配置好环境,具体教程自行 GPT
2. 下载 [python 文件](https://github.com/labring/FastGPT/blob/main/files/models/ChatGLM2/openai_api.py)
3. 在命令行输入命令 `pip install -r requirments.txt`
4. 打开你需要启动的 py 文件,在代码的第 76 行配置 token这里的 token 只是加一层验证,防止接口被人盗用;
5. 执行命令 `python openai_api.py 16`。这里的数字根据上面的配置进行选择。
4. 打开你需要启动的 py 文件,在代码的 `verify_token` 方法中配置 token这里的 token 只是加一层验证,防止接口被人盗用;
5. 执行命令 `python openai_api.py --model_name 16`。这里的数字根据上面的配置进行选择。
然后等待模型下载,直到模型加载完毕为止。如果出现报错先问 GPT。
@@ -99,21 +99,21 @@ Authorization 为 sk-aaabbbcccdddeeefffggghhhiiijjjkkk。model 为刚刚在 One
## 接入 FastGPT
修改 config.json 配置文件,在 VectorModels 中加入 chatglm2 和 M3E 模型:
修改 config.json 配置文件,在 VectorModels 中加入 chatglm2 模型:
```json
"ChatModels": [
//已有模型
{
"model": "chatglm2",
"name": "chatglm2",
"contextMaxToken": 8000,
"quoteMaxToken": 4000,
"maxTemperature": 1.2,
"price": 0,
"defaultSystem": ""
}
],
"ChatModels": [
//已有模型
{
"model": "chatglm2",
"name": "chatglm2",
"contextMaxToken": 8000,
"quoteMaxToken": 4000,
"maxTemperature": 1.2,
"price": 0,
"defaultSystem": ""
}
]
```
## 测试使用

View File

@@ -66,7 +66,7 @@ Authorization 为 sk-key。model 为刚刚在 One API 填写的自定义模型
"defaultToken": 500,
"maxToken": 1800
}
],
]
```
## 测试使用

View File

@@ -7,62 +7,24 @@ toc: true
weight: 520
---
由于环境变量不利于配置复杂的内容,新版 FastGPT 采用了 ConfigMap 的形式挂载配置文件,你可以在 `client/data/config.json` 看到默认的配置文件。可以参考 [docker-compose 快速部署](/docs/installation/docker/) 来挂载配置文件。
由于环境变量不利于配置复杂的内容,新版 FastGPT 采用了 ConfigMap 的形式挂载配置文件,你可以在 `projects/app/data/config.json` 看到默认的配置文件。可以参考 [docker-compose 快速部署](/docs/installation/docker/) 来挂载配置文件。
**开发环境下**,你需要将示例配置文件 `config.json` 复制成 `config.local.json` 文件才会生效。
这个配置文件中包含了前端页面定制、系统级参数、AI 对话的模型等……
这个配置文件中包含了系统级参数、AI 对话的模型、function 模型等……
{{% 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.", // 签名
},
...
...
// 这个配置文件是系统级参数
"SystemParams": {
"vectorMaxProcess": 15, // 向量生成最大进程,结合数据库性能和 key 来设置
"qaMaxProcess": 15, // QA 生成最大进程,结合数据库性能和 key 来设置
"pgIvfflatProbe": 20 // pg vector 搜索探针。没有设置索引前可忽略,通常 50w 组以上才需要设置。
},
...
```
## 完整配置参数
**使用时,请务必去除注释!**
```json
{
"FeConfig": {
"show_emptyChat": true,
"show_register": false,
"show_appStore": false,
"show_userDetail": false,
"show_git": true,
"systemTitle": "FastGPT",
"authorText": "Made by FastGPT Team.",
"scripts": []
},
"SystemParams": {
"vectorMaxProcess": 15,
"qaMaxProcess": 15,
"pgIvfflatProbe": 20
"vectorMaxProcess": 15, // 向量生成最大进程,结合数据库性能和 key 来设置
"qaMaxProcess": 15, // QA 生成最大进程,结合数据库性能和 key 来设置
"pgIvfflatProbe": 20 // pg vector 搜索探针。没有设置索引前可忽略,通常 50w 组以上才需要设置。
},
"plugins": {},
"ChatModels": [
{
"model": "gpt-3.5-turbo",
@@ -92,12 +54,6 @@ weight: 520
"defaultSystem": ""
}
],
"QAModel": {
"model": "gpt-3.5-turbo-16k",
"name": "GPT35-16k",
"maxToken": 16000,
"price": 0
},
"VectorModels": [
{
"model": "text-embedding-ada-002",
@@ -106,6 +62,28 @@ weight: 520
"defaultToken": 500,
"maxToken": 3000
}
]
],
"QAModel": { // QA 拆分模型
"model": "gpt-3.5-turbo-16k",
"name": "GPT35-16k",
"maxToken": 16000,
"price": 0
},
"ExtractModel": { // 内容提取模型
"model": "gpt-3.5-turbo-16k",
"functionCall": true, // 是否使用 functionCall
"name": "GPT35-16k",
"maxToken": 16000,
"price": 0,
"prompt": ""
},
"CQModel": { // 问题分类模型
"model": "gpt-3.5-turbo-16k",
"functionCall": true,
"name": "GPT35-16k",
"maxToken": 16000,
"price": 0,
"prompt": ""
}
}
```

View File

@@ -10,30 +10,27 @@ weight: 510
本文档介绍了如何设置开发环境以构建和测试 [FastGPT](https://fastgpt.run)。
## Tips
1. 用户默认的市区为 `Asia/Shanghai`,非 linux 环境时候,获取系统时间会异常,本地开发时候,可以将用户的时区调整成 UTC+0
## 前置依赖项
您需要在计算机上安装和配置以下依赖项才能构建 [FastGPT](https://fastgpt.run)
- [Git](http://git-scm.com/)
- [Docker](https://www.docker.com/)
- [Docker Compose](https://docs.docker.com/compose/install/)
- [Docker](https://www.docker.com/)(构建镜像)
- [Node.js v18.x (LTS)](http://nodejs.org)
- [npm](https://www.npmjs.com/) 版本 8.x.x 或 [Yarn](https://yarnpkg.com/)
- [pnpm](https://pnpm.io/) 版本 8.x.x
## 本地开发
## 开始本地开发
要设置一个可工作的开发环境,只需 Fork 项目的 Git 存储库,并部署一个数据库,然后开始进行开发测试。
**Tips**
### Fork 存储库
1. 用户默认的时区为 `Asia/Shanghai`,非 linux 环境时候,获取系统时间会异常,本地开发时候,可以将用户的时区调整成 UTC+0
2. 建议先服务器装好数据库在进行本地开发。
### 1. Fork 存储库
您需要 Fork [存储库](https://github.com/labring/FastGPT)。
### 克隆存储库
### 2. 克隆存储库
克隆您在 GitHub 上 Fork 的存储库:
@@ -41,21 +38,27 @@ weight: 510
git clone git@github.com:<github_username>/FastGPT.git
```
client 目录下为 FastGPT 核心代码。NextJS 框架前后端放在一起API 服务位于 `src/pages/api` 目录内。
**目录简要说明**
### 安装数据库
1. `projects` 目录下为 FastGPT 应用代码。其中 `app` 为 FastGPT 核心应用。(后续可能会引入其他应用)
2. NextJS 框架前后端放在一起API 服务位于 `src/pages/api` 目录内。
3. `packages` 目录为共用代码,通过 workspace 被注入到 `projects` 中,已配置 monorepo 自动注入,无需额外打包。
第一次开发,需要先部署数据库,建议本地开发可以随便找一台 2C2G 的轻量小数据库实践。数据库部署教程:[Docker 快速部署](/docs/installation/docker/)
### 3. 安装数据库
### 初始配置
第一次开发,需要先部署数据库,建议本地开发可以随便找一台 2C2G 的轻量小数据库实践。数据库部署教程:[Docker 快速部署](/docs/installation/docker/)。部署完了,可以本地访问其数据库。
**1. 环境变量**
### 4. 初始配置
以下文件均在 `projects/app` 路径下。
**环境变量**
复制.env.template 文件,生成一个.env.local 环境变量文件夹,修改.env.local 里内容才是有效的变量。变量说明见 .env.template
**2. config 配置文件**
**config 配置文件**
复制 data/config.json 文件,生成一个 data/config.local.json 配置文件具体参数说明,可参考 [config 配置说](/docs/development/configuration)
复制 data/config.json 文件,生成一个 data/config.local.json 配置文件具体配置参数说明,可参考 [config 配置说](/docs/development/configuration)
**注意json 配置文件不能包含注释,介绍中为了方便看才加入的注释**
@@ -65,23 +68,29 @@ client 目录下为 FastGPT 核心代码。NextJS 框架前后端放在一起,
- `qaMaxProcess`: QA 生成最大进程
- `pgIvfflatProbe`: PostgreSQL vector 搜索探针,没有添加 vector 索引时可忽略。
### 运行
### 5. 运行
```bash
cd client
# 代码根目录下执行,会安装根 package、projects 和 packages 内所有依赖
pnpm i
# 切换到应用目录
cd projects/app
# 开发模式运行
pnpm dev
```
### 镜像打包
### 6. 发布 - 镜像打包
```bash
docker build -t dockername/fastgpt .
# 根目录下执行
docker build -t dockername/fastgpt --build-arg name=app .
```
## 创建拉取请求
## 提交代码至开源仓库
在进行更改后打开一个拉取请求PR。提交拉取请求后FastGPT 团队/社区的其他人将与您一起审查它。
1. 确保你的代码是 Fork [FastGPT](https://github.com/labring/FastGPT) 仓库
2. 尽可能少量的提交代码,每次提交仅解决一个问题。
3. 向 FastGPT 的 main 分支提交一个 PR提交请求后FastGPT 团队/社区的其他人将与您一起审查它。
如果遇到问题,比如合并冲突或不知道如何打开拉取请求,请查看 GitHub 的[拉取请求教程](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests),了解如何解决合并冲突和其他问题。一旦您的 PR 被合并,您将自豪地被列为[贡献者表](https://github.com/labring/FastGPT/graphs/contributors)中的一员。

View File

@@ -0,0 +1,533 @@
---
title: 'OpenAPI 使用API Key 使用)'
description: 'FastGPT OpenAPI 文档'
icon: 'api'
draft: false
toc: true
weight: 512
---
# 基本配置
```
baseUrl: "https://fastgpt.run/api"
headers: {
Authorization: "Bearer apikey"
}
```
# 如何获取 API Key
FastGPT 的 API Key 有 2 类,一类是全局通用的 key一类是携带了 AppId 也就是有应用标记的 key。
| 通用key | 应用特定 key |
| --------------------- | --------------------- |
| ![](/imgs/fastgpt-api2.png) | ![](/imgs/fastgpt-api.png) |
# 接口
## 发起对话
{{% alert icon="🤖 " context="success" %}}
该接口 API Key 需使用应用特定的 key否则会报错。
有些包的 BaseUrl 需要添加 `v1` 路径,有些不需要,建议都试一下。
{{% /alert %}}
对话接口兼容`GPT`的接口!如果你的项目使用的是标准的`GPT`官方接口,可以直接通过修改 `BaseUrl``Authorization` 来访问 FastGpt 应用。
请求参数说明
- headers.Authorization: Bearer apikey
- chatId: string | undefined 。
- 为 undefined 时(不传入),不使用 FastGpt 提供的上下文功能,完全通过传入的 messages 构建上下文。 不会将你的记录存储到数据库中,你也无法在记录汇总中查阅到。
- 为非空字符串时,意味着使用 chatId 进行对话,自动从 FastGpt 数据库取历史记录,并使用 messages 数组最后一个内容作为用户问题。(请自行确保 chatId 唯一,长度不限制)
- messages: 结构与 [GPT接口](https://platform.openai.com/docs/api-reference/chat/object) 完全一致。
- detail: 是否返回详细值(模块状态,响应的完整结果),`stream模式`下会通过event进行区分`非stream模式`结果保存在responseData中。
- variables: 变量内容,一个对象,会替换`{{key}}`变量。在`HTTP`模块中会发给接口,可作为身份凭证等标识。
**请求示例:**
```bash
curl --location --request POST 'https://fastgpt.run/api/v1/chat/completions' \
--header 'Authorization: Bearer apikey' \
--header 'Content-Type: application/json' \
--data-raw '{
"chatId":"111",
"stream":false,
"detail": false,
"variables": {
"cTime": "2022/2/2 22:22"
},
"messages": [
{
"content": "导演是谁",
"role": "user"
}
]
}'
```
{{< tabs tabTotal="3" >}}
{{< tab tabName="detail=false 响应" >}}
{{< markdownify >}}
```bash
data: {"id":"","object":"","created":0,"choices":[{"delta":{"content":""},"index":0,"finish_reason":null}]}
data: {"id":"","object":"","created":0,"choices":[{"delta":{"content":"电"},"index":0,"finish_reason":null}]}
data: {"id":"","object":"","created":0,"choices":[{"delta":{"content":"影"},"index":0,"finish_reason":null}]}
data: {"id":"","object":"","created":0,"choices":[{"delta":{"content":"《"},"index":0,"finish_reason":null}]}
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="detail=true 响应" >}}
{{< markdownify >}}
```bash
event: answer
data: {"id":"","object":"","created":0,"choices":[{"delta":{"content":""},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"choices":[{"delta":{"content":"电"},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"choices":[{"delta":{"content":"影"},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"choices":[{"delta":{"content":"《"},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"choices":[{"delta":{"content":"铃"},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"choices":[{"delta":{"content":"芽"},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"choices":[{"delta":{"content":"。"},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"choices":[{"delta":{"content":""},"index":0,"finish_reason":null}]}
event: answer
data: {"id":"","object":"","created":0,"choices":[{"delta":{},"index":0,"finish_reason":"stop"}]}
event: answer
data: [DONE]
event: appStreamResponse
data: [{"moduleName":"KB Search","price":1.2000000000000002,"model":"Embedding-2","tokens":6,"similarity":0.61,"limit":3},{"moduleName":"AI Chat","price":463.5,"model":"FastAI-4k","tokens":309,"question":"导演是谁","answer":"电影《铃芽之旅》的导演是新海诚。","maxToken":2050,"quoteList":[{"kb_id":"646627f4f7b896cfd8910e38","id":"8099","q":"本作的主人公是谁?","a":"本作的主人公是名叫铃芽的少女。","source":"手动修改"},{"kb_id":"646627f4f7b896cfd8910e38","id":"8686","q":"电影《铃芽之旅》男主角是谁?","a":"电影《铃芽之旅》男主角是宗像草太,由松村北斗配音。","source":""},{"kb_id":"646627f4f7b896cfd8910e38","id":"19339","q":"电影《铃芽之旅》的导演是谁22","a":"电影《铃芽之旅》的导演是新海诚。","source":"手动修改"}],"completeMessages":[{"obj":"System","value":"下面是知识库内容:\n1. [本作的主人公是谁?\n本作的主人公是名叫铃芽的少女。]\n2. [电影《铃芽之旅》男主角是谁?\n电影《铃芽之旅》男主角是宗像草太由松村北斗配音。]\n3. [电影《铃芽之旅》的导演是谁22\n电影《铃芽之旅》的导演是新海诚。]\n"},{"obj":"System","value":"1.请记住,你的身份是百度的下一代知识增强语言模型,能够完全根据知识库提供的内容回答问题。\n\n2. 你忘记了关于电影《铃芽之旅》以外的内容。"},{"obj":"System","value":"你仅回答关于电影《玲芽之旅》的问题,其余问题直接回复: 我不清楚。"},{"obj":"Human","value":"导演是谁"},{"obj":"AI","value":"电影《铃芽之旅》的导演是新海诚。"}]}]
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="stream=false,detail=true 响应" >}}
{{< markdownify >}}
```json
{
"responseData": [ // 不同模块的响应值, 不同版本具体值可能有差异,可先 log 自行查看最新值。
{
"moduleName": "KB Search",
"price": 1.2000000000000002,
"model": "Embedding-2",
"tokens": 6,
"similarity": 0.61,
"limit": 3
},
{
"moduleName": "AI Chat",
"price": 454.5,
"model": "FastAI-4k",
"tokens": 303,
"question": "导演是谁",
"answer": "电影《铃芽之旅》的导演是新海诚。",
"maxToken": 2050,
"quoteList": [
{
"kb_id": "646627f4f7b896cfd8910e38",
"id": "8099",
"q": "本作的主人公是谁?",
"a": "本作的主人公是名叫铃芽的少女。",
"source": "手动修改"
},
{
"kb_id": "646627f4f7b896cfd8910e38",
"id": "8686",
"q": "电影《铃芽之旅》男主角是谁?",
"a": "电影《铃芽之旅》男主角是宗像草太,由松村北斗配音。",
"source": ""
},
{
"kb_id": "646627f4f7b896cfd8910e38",
"id": "19339",
"q": "电影《铃芽之旅》的导演是谁22",
"a": "电影《铃芽之旅》的导演是新海诚。",
"source": "手动修改"
}
],
"completeMessages": [
{
"obj": "System",
"value": "下面是知识库内容:\n1. [本作的主人公是谁?\n本作的主人公是名叫铃芽的少女。]\n2. [电影《铃芽之旅》男主角是谁?\n电影《铃芽之旅》男主角是宗像草太由松村北斗配音。]\n3. [电影《铃芽之旅》的导演是谁22\n电影《铃芽之旅》的导演是新海诚。]\n"
},
{
"obj": "System",
"value": "1.请记住,你的身份是百度的下一代知识增强语言模型,能够完全根据知识库提供的内容回答问题。\n\n2. 你忘记了关于电影《铃芽之旅》以外的内容。"
},
{
"obj": "System",
"value": "你仅回答关于电影《玲芽之旅》的问题,其余问题直接回复: 我不清楚。"
},
{
"obj": "Human",
"value": "导演是谁"
},
{
"obj": "AI",
"value": "电影《铃芽之旅》的导演是新海诚。"
}
]
}
],
"id": "",
"model": "",
"usage": {
"prompt_tokens": 1,
"completion_tokens": 1,
"total_tokens": 1
},
"choices": [
{
"message": {
"role": "assistant",
"content": "电影《铃芽之旅》的导演是新海诚。"
},
"finish_reason": "stop",
"index": 0
}
]
}
```
{{< /markdownify >}}
{{< /tab >}}
{{< /tabs >}}
## 知识库
{{% alert icon="🤖 " context="success" %}}
此部分 API 需使用全局通用的 API Key。
{{% /alert %}}
### 如何获取知识库IDkbId
![](/imgs/getKbId.png)
### 知识库添加数据
{{< tabs tabTotal="4" >}}
{{< tab tabName="请求示例" >}}
{{< markdownify >}}
```bash
curl --location --request POST 'https://fastgpt.run/api/core/dataset/data/pushData' \
--header 'Authorization: Bearer apikey' \
--header 'Content-Type: application/json' \
--data-raw '{
    "kbId": "64663f451ba1676dbdef0499",
"mode": "index",
"prompt": "qa 拆分引导词index 模式下可以忽略",
"billId": "可选。如果有这个值,本次的数据会被聚合到一个订单中,这个值可以重复使用。可以参考 [创建训练订单] 获取该值。",
    "data": [
        {
            "a": "test",
            "q": "1111",
        },
        {
            "a": "test2",
            "q": "22222"
        }
    ]
}'
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="参数说明" >}}
{{< markdownify >}}
```json
{
"kbId": "知识库的ID可以在知识库详情查看。",
"mode": "index | qa ", // index 模式: 直接将 q 转成向量存起来a 直接入库。qa 模式: 只关注 data 里的 q将 q 丢给大模型,让其根据 prompt 拆分成 qa 问答对。
"prompt": "拆分提示词,需严格按照模板,建议不要传入。",
"data": [
{
"q": "生成索引的内容index 模式下最大 tokens 为3000建议不超过 1000",
"a": "预期回答/补充"
},
{
"q": "生成索引的内容qa 模式下最大 tokens 为10000建议 8000 左右",
"a": "预期回答/补充"
}
]
}
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="响应例子" >}}
{{< markdownify >}}
```json
{
"code": 200,
"statusText": "",
"data": {
"insertLen": 1 // 最终插入成功的数量,可能因为超出 tokens 或者插入异常index 可以重复插入,会自动去重
}
}
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="QA Prompt 模板" >}}
{{< markdownify >}}
{{theme}} 里的内容可以换成数据的主题。默认为:它们可能包含多个主题内容
```
我会给你一段文本,{{theme}},学习它们,并整理学习成果,要求为:
1. 提出最多 25 个问题。
2. 给出每个问题的答案。
3. 答案要详细完整,答案可以包含普通文字、链接、代码、表格、公示、媒体链接等 markdown 元素。
4. 按格式返回多个问题和答案:
Q1: 问题。
A1: 答案。
Q2:
A2:
……
我的文本:"""{{text}}"""
```
{{< /markdownify >}}
{{< /tab >}}
{{< /tabs >}}
### 搜索测试
{{< tabs tabTotal="2" >}}
{{< tab tabName="请求示例" >}}
{{< markdownify >}}
```bash
curl --location --request POST 'https://fastgpt.run/api/core/dataset/searchTest' \
--header 'Authorization: Bearer apiKey' \
--header 'Content-Type: application/json' \
--data-raw '{
"kbId": "xxxxx",
"text": "导演是谁"
}'
```
{{< /markdownify >}}
{{< /tab >}}
{{< tab tabName="响应示例" >}}
{{< markdownify >}}
返回 top12 结果
```bash
{
"code": 200,
"statusText": "",
"data": [
{
"id": "5613327",
"q": "该人有获奖情况吗?",
"a": "该人获得过2020/07全国大学生服务外包大赛国家一等奖和2021/05国家创新创业计划立项的获奖情况。",
"source": "余金隆简历.pdf",
"score": 0.41556452839298963
},
......
]
}
```
{{< /markdownify >}}
{{< /tab >}}
{{< /tabs >}}
## 订单
### 创建训练订单
**请求示例**
```bash
curl --location --request POST 'https://fastgpt.run/api/common/bill/createTrainingBill' \
--header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \
--data-raw ''
```
**响应结果**
data 为 billId可用于 api 添加数据时进行账单聚合。
```json
{
"code": 200,
"statusText": "",
"message": "",
"data": "65112ab717c32018f4156361"
}
```
## 免登录分享链接校验(内测中)
免登录链接配置中,增加了`凭证校验服务器`后,使用分享链接时会向服务器发起请求,校验链接是否可用,并在每次对话结束后,向服务器发送对话结果。下面以`host`来表示`凭证校验服务器`。服务器接口仅需返回是否校验成功即可,不需要返回其他数据,格式如下:
```json
{
"success": true,
"message": "错误提示"
}
```
![](/imgs/sharelinkProcess.png)
### 分享链接中增加额外 query
增加一个 query: authToken。例如
原始的链接https://fastgpt.run/chat/share?shareId=648aaf5ae121349a16d62192
完整链接: https://fastgpt.run/chat/share?shareId=648aaf5ae121349a16d62192&authToken=userid12345
发出校验请求时候,会在`body`中携带 token={{authToken}} 的参数。
### 初始化校验
**FastGPT 发出的请求**
```bash
curl --location --request POST '{{host}}/shareAuth/init' \
--header 'Content-Type: application/json' \
--data-raw '{
"token": "sintdolore"
}'
```
### 对话前校验
**FastGPT 发出的请求**
```bash
curl --location --request POST '{{host}}/shareAuth/start' \
--header 'Content-Type: application/json' \
--data-raw '{
"token": "sintdolore",
"question": "用户问题",
}'
```
### 对话结果上报
**FastGPT 发出的请求**
```bash
curl --location --request POST '{{host}}/shareAuth/finish' \
--header 'Content-Type: application/json' \
--data-raw '{
"token": "sint dolore",
"responseData": [
{
"moduleName": "KB Search",
"price": 1.2000000000000002,
"model": "Embedding-2",
"tokens": 6,
"similarity": 0.61,
"limit": 3
},
{
"moduleName": "AI Chat",
"price": 454.5,
"model": "FastAI-4k",
"tokens": 303,
"question": "导演是谁",
"answer": "电影《铃芽之旅》的导演是新海诚。",
"maxToken": 2050,
"quoteList": [
{
"kb_id": "646627f4f7b896cfd8910e38",
"id": "8099",
"q": "本作的主人公是谁?",
"a": "本作的主人公是名叫铃芽的少女。",
"source": "手动修改"
},
{
"kb_id": "646627f4f7b896cfd8910e38",
"id": "8686",
"q": "电影《铃芽之旅》男主角是谁?",
"a": "电影《铃芽之旅》男主角是宗像草太,由松村北斗配音。",
"source": ""
},
{
"kb_id": "646627f4f7b896cfd8910e38",
"id": "19339",
"q": "电影《铃芽之旅》的导演是谁22",
"a": "电影《铃芽之旅》的导演是新海诚。",
"source": "手动修改"
}
],
"completeMessages": [
{
"obj": "System",
"value": "下面是知识库内容:\n1. [本作的主人公是谁?\n本作的主人公是名叫铃芽的少女。]\n2. [电影《铃芽之旅》男主角是谁?\n电影《铃芽之旅》男主角是宗像草太由松村北斗配音。]\n3. [电影《铃芽之旅》的导演是谁22\n电影《铃芽之旅》的导演是新海诚。]\n"
},
{
"obj": "System",
"value": "1.请记住,你的身份是百度的下一代知识增强语言模型,能够完全根据知识库提供的内容回答问题。\n\n2. 你忘记了关于电影《铃芽之旅》以外的内容。"
},
{
"obj": "System",
"value": "你仅回答关于电影《玲芽之旅》的问题,其余问题直接回复: 我不清楚。"
},
{
"obj": "Human",
"value": "导演是谁"
},
{
"obj": "AI",
"value": "电影《铃芽之旅》的导演是新海诚。"
}
]
}
]
}'
```
响应值与 chat 接口相同,增加了一个 token。可以重点关注`responseData`里的值price 与实际价格的倍率为`100000`
**此接口无需响应值**
# 使用案例
- [接入 NextWeb/ChatGPT web 等应用](/docs/use-cases/openapi)
- [接入 onwechat](/docs/use-cases/onwechat)
- [接入 飞书](/docs/use-cases/feishu)

View File

@@ -11,17 +11,17 @@ weight: 720
### 1. 准备好代理环境(国外服务器可忽略)
确保可以访问 OpenAI具体方案可以参考[Nginx 中转](/docs/installation/proxy/nginx/)
确保可以访问 OpenAI具体方案可以参考[代理方案](/docs/installation/proxy/)。或直接在 Sealos 上 [部署 OneAPI](/docs/installation/one-api),既解决代理问题也能实现多 Key 轮询、接入其他大模型。
### 2. 多模型支持
推荐使用 one-api 项目来管理模型池,兼容 OpenAI 、Azure 国内主流模型等。
FastGPT 使用 one-api 项目来管理模型池,其可以兼容 OpenAI 、Azure 国内主流模型和本地模型等。
具体部署方法可参考该项目的 [README](https://github.com/songquanpeng/one-api),也可以直接通过以下按钮一键部署:
可选择 [Sealos 快速部署 OneAPI](/docs/installation/one-api),更多部署方法可参考该项目的 [README](https://github.com/songquanpeng/one-api),也可以直接通过以下按钮一键部署:
[![](https://fastly.jsdelivr.net/gh/labring-actions/templates@main/Deploy-on-Sealos.svg)](https://cloud.sealos.io/?openapp=system-fastdeploy%3FtemplateName%3Done-api)
## 安装 Docker 和 docker-compose
## 一、安装 Docker 和 docker-compose
{{< tabs tabTotal="3" >}}
{{< tab tabName="Linux" >}}
@@ -29,7 +29,7 @@ weight: 720
```bash
# 安装 Docker
curl -sSL https://get.daocloud.io/docker | sh
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
systemctl enable --now docker
# 安装 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
@@ -37,6 +37,7 @@ chmod +x /usr/local/bin/docker-compose
# 验证安装
docker -v
docker-compose -v
# 如失效,自行百度~
```
{{< /markdownify >}}
@@ -65,93 +66,35 @@ brew install orbstack
{{< /tab >}}
{{< /tabs >}}
## 创建 docker-compose.yml 文件
## 二、创建目录并下载 docker-compose.yml
先创建一个目录(例如 fastgpt并进入该目录创建一个 docker-compose.yml 文件
依次执行下面命令,创建 FastGPT 文件并拉取`docker-compose.yml``config.json`,执行完后目录下会有 2 个文件
非 Linux 环境可手动创建目录并下载这2个文件。
**注意: 配置文件中 Mongo 为 5.x部分服务器不支持需手动更改其镜像版本为 4.4.24**
```bash
mkdir fastgpt
cd fastgpt
touch docker-compose.yml
curl -O https://raw.githubusercontent.com/labring/FastGPT/main/files/deploy/fastgpt/docker-compose.yml
curl -O https://raw.githubusercontent.com/labring/FastGPT/main/projects/app/data/config.json
```
粘贴下面的内容,仅需把 `CHAT_API_KEY` 修改成 openai key 即可。如果需要使用中转或 oneapi 还需要修改 `OPENAI_BASE_URL`:
```yaml
# 非 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
- FILE_TOKEN_KEY=filetoken
# mongo 配置,不需要改. 如果连不上,可能需要去掉 ?authSource=admin
- MONGODB_URI=mongodb://username:password@mongo:27017/fastgpt?authSource=admin
# pg配置. 不需要改
- PG_URL=postgresql://username:password@pg:5432/postgres
networks:
fastgpt:
```
## 三、启动容器
## 启动容器
修改`docker-compose.yml`中的`OPENAI_BASE_URL``CHAT_API_KEY`即可,对应为 API 的地址和 key。
```bash
# 在 docker-compose.yml 同级目录下执行
docker-compose pull
docker-compose up -d
```
## 访问 FastGPT
## 四、访问 FastGPT
目前可以通过 `ip:3000` 直接访问(注意防火墙)。登录用户名为 `root`,密码为刚刚环境变量里设置的 `DEFAULT_ROOT_PSW`
目前可以通过 `ip:3000` 直接访问(注意防火墙)。登录用户名为 `root`,密码为`docker-compose.yml`环境变量里设置的 `DEFAULT_ROOT_PSW`
如果需要域名访问,请自行安装并配置 Nginx。
@@ -168,28 +111,30 @@ docker-compose up -d
### 如何自定义配置文件?
需要在 `docker-compose.yml` 同级目录创建一个 `config.json` 文件,内容参考: [配置详解](/docs/development/configuration)
修改`config.json`文件,并执行`docker-compose up -d`重起容器。具体配置,参考[配置详解](/docs/development/configuration)
然后修改 `docker-compose.yml` 中的 `fastgpt` 容器内容,增加挂载选项即可:
### 如何检查自定义配置文件是否挂载
```yaml
fastgpt:
container_name: fastgpt
image: ghcr.io/labring/fastgpt:latest # github
ports:
- 3000:3000
networks:
- fastgpt
depends_on:
- mongo
- pg
restart: always
environment:
...
- DEFAULT_ROOT_PSW=1234
...
volumes:
- ./config.json:/app/data/config.json
```
1. `docker logs fastgpt` 可以查看日志,在启动容器后,第一次请求网页,会进行配置文件读取,可以看看有没有读取成功以及有无错误日志。
2. `docker exec -it fastgpt sh` 进入 FastGPT 容器,可以通过`ls data`查看目录下是否成功挂载`config.json`文件。可通过`cat data/config.json`查看配置文件。
> 参考[配置详解](/docs/development/configuration)
### 为什么无法连接 oneapi 和 本地模型镜像。
`docker-compose.yml`中使用了桥接的模式建立了`fastgpt`网络如想通过0.0.0.0或镜像名访问其它镜像,需将其它镜像也加入到网络中。
### 端口冲突怎么解决?
docker-compose 端口定义为:`映射端口:运行端口`
桥接模式下,容器运行端口不会有冲突,但是会有映射端口冲突,只需将映射端口修改成不同端口即可。
如果`容器1`需要连接`容器2`,使用`容器2:运行端口`来进行连接即可。
(自行补习 docker 基本知识)
### 错误排查方式
遇到问题先按下面方式排查。
1. `docker ps -a` 查看所有容器运行状态,检查是否全部 running如有异常尝试`docker logs 容器名`查看对应日志。
2. 不懂 docker 不要瞎改端口,只需要改`OPENAI_BASE_URL``CHAT_API_KEY`即可。

View File

@@ -1,5 +1,5 @@
---
title: '部署 One API实现多模型支持'
title: '接入微软、ChatGLM、本地模型等'
description: '通过接入 One API 来实现对各种大模型的支持'
icon: 'Api'
draft: false
@@ -7,9 +7,8 @@ toc: true
weight: 730
---
默认情况下FastGPT 只配置了 GPT 的 3 个模型,如果你需要接入其他模型,需要进行一些额外配置。
[One API](https://github.com/songquanpeng/one-api) 是一个 OpenAI 接口管理 & 分发系统,可以通过标准的 OpenAI API 格式访问所有的大模型,开箱即用。
* 默认情况下FastGPT 只配置了 GPT 的 3 个模型,如果你需要接入其他模型,需要进行一些额外配置。
* [One API](https://github.com/songquanpeng/one-api) 是一个 OpenAI 接口管理 & 分发系统,可以通过标准的 OpenAI API 格式访问所有的大模型,开箱即用。
FastGPT 可以通过接入 One API 来实现对各种大模型的支持。部署方法也很简单。
@@ -92,7 +91,7 @@ CHAT_API_KEY=sk-xxxxxx
### 2. 修改 FastGPT 配置文件
可以在 `/client/src/data/config.json` 里找到配置文件(本地开发需要复制成 config.local.json配置文件中有一项是对话模型配置
可以在 `/projects/app/src/data/config.json` 里找到配置文件(本地开发需要复制成 config.local.json配置文件中有一项是对话模型配置
```json
"ChatModels": [

View File

@@ -23,6 +23,22 @@ Sealos 的服务器在国外,不需要额外处理网络问题,无需服务
>
> 密码就是刚刚一键部署时设置的环境变量
## 修改配置文件和环境变量
在 Sealos 中,你可以打开`应用管理`App Launchpad看到部署的 FastGPT可以打开`数据库`Database看到对应的数据库。
`应用管理`中,选中 FastGPT点击变更可以看到对应的环境变量和配置文件。
![](/imgs/fastgptonsealos1.png)
{{% alert icon="🤖 " context="success" %}}
在 Sealos 上FastGPT 一共运行了 1 个服务和 2 个数据库,如暂停和删除请注意数据库一同操作。(你可以白天启动,晚上暂停它们,省钱大法)
{{% /alert %}}
## 更新
点击重启会自动拉取最新镜像更新,请确保镜像`tag`正确。
## 部署架构图
![](/imgs/sealos-fastgpt.webp)

View File

@@ -4,7 +4,7 @@ description: 'FastGPT 从旧版本升级到 V4.0 操作指南'
icon: 'upgrade'
draft: false
toc: true
weight: 1000
weight: 850
---
如果您是**从旧版本升级到 V4**,由于新版 MongoDB 表变更比较大,需要按照本文档的说明执行一些初始化脚本。

View File

@@ -4,7 +4,7 @@ description: 'FastGPT 从旧版本升级到 V4.1 操作指南'
icon: 'upgrade'
draft: false
toc: true
weight: 999
weight: 849
---
如果您是**从旧版本升级到 V4.1**,由于新版重新设置了对话存储结构,需要初始化原来的存储内容。

View File

@@ -4,7 +4,7 @@ description: 'FastGPT 从旧版本升级到 V4.2 操作指南'
icon: 'upgrade'
draft: false
toc: true
weight: 998
weight: 848
---
99.9%用户不影响,升级 4.2 主要是修改了配置文件中 QAModel 的格式。从原先的数组改成对象:

View File

@@ -4,7 +4,7 @@ description: 'FastGPT 从旧版本升级到 V4.2.1 操作指南'
icon: 'upgrade'
draft: false
toc: true
weight: 997
weight: 847
---
私有部署,如果添加了配置文件,需要在配置文件中修改 `VectorModels` 字段。增加 defaultToken 和 maxToken分别对应直接分段时的默认 token 数量和该模型支持的 token 上限(通常不建议超过 3000

View File

@@ -4,7 +4,7 @@ description: 'FastGPT 从旧版本升级到 V4.3 操作指南'
icon: 'upgrade'
draft: false
toc: true
weight: 996
weight: 846
---
## 执行初始化 API

View File

@@ -4,7 +4,7 @@ description: 'FastGPT 从旧版本升级到 V4.4 操作指南'
icon: 'upgrade'
draft: false
toc: true
weight: 995
weight: 845
---
## 执行初始化 API

View File

@@ -4,7 +4,7 @@ description: 'FastGPT 从旧版本升级到 V4.4.1 操作指南'
icon: 'upgrade'
draft: false
toc: true
weight: 994
weight: 844
---
## 执行初始化 API

View File

@@ -4,7 +4,7 @@ description: 'FastGPT 从旧版本升级到 V4.4.2 操作指南'
icon: 'upgrade'
draft: false
toc: true
weight: 993
weight: 843
---
## 执行初始化 API

View File

@@ -0,0 +1,31 @@
---
title: 'V4.4.5'
description: 'FastGPT V4.4.5 更新(需执行升级脚本)'
icon: 'upgrade'
draft: false
toc: true
weight: 842
---
## 执行初始化 API
发起 1 个 HTTP 请求(记得携带 `headers.rootkey`,这个值是环境变量里的)
1. https://xxxxx/api/admin/initv445
```bash
curl --location --request POST 'https://{{host}}/api/admin/initv445' \
--header 'rootkey: {{rootkey}}' \
--header 'Content-Type: application/json'
```
初始化了 variable 模块,将其合并到用户引导模块中。
## 功能介绍
### Fast GPT V4.4.5
1. 新增 - 下一步指引选项,可以通过模型生成 3 个预测问题。
2. 商业版新增 - 分享链接限制及 hook 身份校验(可对接已有的用户系统)。
3. 商业版新增 - Api Key 使用。增加别名、额度限制和过期时间。自带 appId无需额外连接。
4. 优化 - 全局变量与开场白合并成同一模块。

View File

@@ -0,0 +1,14 @@
---
title: 'V4.4.6'
description: 'FastGPT V4.4.6 更新'
icon: 'upgrade'
draft: false
toc: true
weight: 841
---
## 功能介绍
1. 高级编排新增模块 - 应用调用,可调用其他应用。
2. 新增 - 必要连接校验
3. 修复 - 下一步指引在免登录中身份问题。

View File

@@ -1,7 +1,7 @@
---
weight: 760
title: "版本升级"
description: "FastGPT 升级指南"
title: "版本更新/升级操作"
description: "FastGPT 版本更新介绍及升级操作"
icon: upgrade
draft: false
images: []

View File

@@ -7,11 +7,15 @@ toc: true
weight: 10
---
[OpenAI 的 API 官方计费模式](https://openai.com/pricing#language-models)为:按每次 API 请求内容和返回内容 tokens 长度来定价。每个模型具有不同的计价方式,以每 1,000 个 tokens 消耗为单位定价。其中 1,000 个 tokens 约为 750 个英文单词。平台的 tokens 数量计算算法与 OpenAI 一致,您可以随时通过「使用记录」来查看余额消耗明细的说明,来对比计算是否一致。
## Tokens 说明
[OpenAI 的 API 官方计费模式](https://openai.com/pricing#language-models)为:按每次 API 请求内容和返回内容 tokens 长度来定价。每个模型具有不同的计价方式,以每 1,000 个 tokens 消耗为单位定价。其中 1,000 个 tokens 约为 900 个英文,约 600 个中文(不是很准确,与上下长度有关,相同的词出现越多,词:Tokens 的比例越大)。平台的 tokens 数量计算算法与 OpenAI 一致,您可以随时通过「使用记录」来查看余额消耗明细的说明,来对比计算是否一致。
![](/imgs/fastgpt-price.png)
以下是详细的价格表:
## FastGPT 线上计费
目前FastGPT 线上计费也仅按 Tokens 使用数量为准。以下是详细的计费表(最新定价以线上表格为准,可在点击充值后实时获取):
{{< table "table-hover table-striped-columns" >}}
| 计费项 | 价格: 元/ 1K tokens包含上下文 |

View File

@@ -11,16 +11,14 @@ weight: 322
[Feishu OpenAI GitHub 地址](https://github.com/ConnectAI-E/Feishu-OpenAI)
由于 FastGPT 的 API 接口和 OpenAI 的规范一致,可以无需变更第三方应用即可使用 FastGPT 上编排好的应用。API 使用可参考 [这篇文章](/docs/use-cases/openai/)。编排示例,可参考 [高级编排介绍](/docs/workflow/intro)
由于 FastGPT 的 API 接口和 OpenAI 的规范一致,可以无需变更第三方应用即可使用 FastGPT 上编排好的应用。API 使用可参考 [这篇文章](/docs/use-cases/openapi/)。编排示例,可参考 [高级编排介绍](/docs/workflow/intro)
## 1. 获取 FastGPT 的 OpenAPI 秘钥
依次选择应用 -> 「API 访问」然后点击「API 密钥」来创建密钥。 [参考这篇文章](/docs/use-cases/openai/)
依次选择应用 -> 「API 访问」然后点击「API 密钥」来创建密钥。 [参考这篇文章](/docs/use-cases/openapi/)
![](/imgs/fastgpt-api.png)
利用刚复制的 API 秘钥加上 AppId 组合成一个新的秘钥,格式为:`API 秘钥-AppId`,例如:`fastgpt-z51pkjqm9nrk03a1rx2funoy-642adec15f04d67d4613efdb`
## 2. 部署飞书服务
推荐使用 Railway 一键部署
@@ -35,7 +33,7 @@ FastGPT 集成**重点参数:**
```bash
#上一步FastGPT的OpenAPI 秘钥
OPENAI_KEY=fastgpt-z51pkjqm9nrk03a1rx2funoy-642adec15f04d67d4613efdb
OPENAI_KEY=fastgpt-z51pkjqm9nrk03a1rx2funoy
#调用OpenAI的BaseUrl要换成FastGPT的
API_URL=https://fastgpt.run/api/openapi
```

View File

@@ -73,7 +73,7 @@ weight: 340
![手动录入知识库结果](/imgs/9.png)
导入结果如上图。可以看到,我们均采用的是问答对的格式,而不是粗略的直接导入。目的就是为了模拟用户问题,进一步的提高向量搜索的匹配效果。可以为同一个问题设置多种问法,效果更佳。
FastGPT 还提供了 openapi 功能,你可以在本地对特殊格式的文件进行处理后,再上传到 FastGPT具体可以参考[FastGPT Api Docs](https://kjqvjse66l.feishu.cn/docx/DmLedTWtUoNGX8xui9ocdUEjnNh)
FastGPT 还提供了 openapi 功能,你可以在本地对特殊格式的文件进行处理后,再上传到 FastGPT具体可以参考[FastGPT Api Docs](https://doc.fastgpt.run/docs/development/openapi)
## 知识库微调和参数调整

View File

@@ -4,14 +4,14 @@ description: "FastGPT 对接 chatgpt-on-wechat"
icon: "chat"
draft: false
toc: true
weight: 320
weight: 312
---
# 1 分钟对接 chatgpt-on-wechat
[chatgpt-on-wechat GitHub 地址](https://github.com/zhayujie/chatgpt-on-wechat)
由于 FastGPT 的 API 接口和 OpenAI 的规范一致,可以无需变更原来的应用即可使用 FastGPT 上编排好的应用。API 使用可参考 [这篇文章](/docs/use-cases/openai/)。编排示例,可参考 [高级编排介绍](/docs/workflow/intro)
由于 FastGPT 的 API 接口和 OpenAI 的规范一致,可以无需变更原来的应用即可使用 FastGPT 上编排好的应用。API 使用可参考 [这篇文章](/docs/use-cases/openapi/)。编排示例,可参考 [高级编排介绍](/docs/workflow/intro)
## 1. 获取 OpenAPI 秘钥
@@ -23,15 +23,10 @@ weight: 320
![](/imgs/fastgpt-api.png)
## 2. 组合带应用 ID 的秘钥
利用刚复制的 API 秘钥加上 AppId 组合成一个新的秘钥,格式为:`API 秘钥-AppId`,例如:`fastgpt-z51pkjqm9nrk03a1rx2funoy-642adec15f04d67d4613efdb`
这个秘钥将会调用指定的应用。
## 3. 创建 docker-compose.yml 文件
只需要修改 `OPEN_AI_API_KEY``OPEN_AI_API_BASE` 两个环境变量即可。其中 `OPEN_AI_API_KEY` 为第二步的组合秘钥,`OPEN_AI_API_BASE` 为 FastGPT 的 OpenAPI 地址,例如:`https://fastgpt.run/api/openapi/v1`
只需要修改 `OPEN_AI_API_KEY``OPEN_AI_API_BASE` 两个环境变量即可。其中 `OPEN_AI_API_KEY` 为第一步获取的秘钥,`OPEN_AI_API_BASE` 为 FastGPT 的 OpenAPI 地址,例如:`https://fastgpt.run/api/v1`
随便找一个目录,创建一个 docker-compose.yml 文件,将下面的代码复制进去。
@@ -44,8 +39,8 @@ services:
security_opt:
- seccomp:unconfined
environment:
OPEN_AI_API_KEY: 'fastgpt-z51pkjqm9nrk03a1rx2funoy-642adec15f04d67d4613efdb'
OPEN_AI_API_BASE: 'https://fastgpt.run/api/openapi/v1'
OPEN_AI_API_KEY: 'fastgpt-z51pkjqm9nrk03a1rx2funoy'
OPEN_AI_API_BASE: 'https://fastgpt.run/api/v1'
MODEL: 'gpt-3.5-turbo'
CHANNEL_TYPE: 'wx'
PROXY: ''

View File

@@ -4,7 +4,7 @@ description: "通过与 OpenAI 兼容的 API 对接第三方应用"
icon: "model_training"
draft: false
toc: true
weight: 330
weight: 311
---
## 获取 API 秘钥
@@ -17,15 +17,16 @@ weight: 330
![](/imgs/fastgpt-api.png)
## 组合秘钥
{{% alert icon="🍅" context="success" %}}
Tips: 安全起见,你可以设置一个额度或者过期时间,放置 key 被滥用。
{{% /alert %}}
利用刚复制的 API 秘钥加上 AppId 组合成一个新的秘钥,格式为:`API 秘钥-AppId`,例如:`fastgpt-z51pkjqm9nrk03a1rx2funoy-642adec15f04d67d4613efdb`
## 替换三方应用的变量
```bash
OPENAI_API_BASE_URL: https://fastgpt.run/api/openapi (改成自己部署的域名)
OPENAI_API_KEY = 组合秘钥
OPENAI_API_BASE_URL: https://fastgpt.run/api (改成自己部署的域名)
OPENAI_API_KEY = 上一步获取到的秘钥
```
**[ChatGPT Next Web](https://github.com/Yidadaa/ChatGPT-Next-Web) 示例:**

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,6 @@ module fastgpt-docs
go 1.21
require (
github.com/colinwilson/lotusdocs v0.0.0-20230919015602-a9717caaab14 // indirect
github.com/colinwilson/lotusdocs v0.1.0 // indirect
github.com/gohugoio/hugo-mod-bootstrap-scss/v5 v5.20300.20003 // indirect
)

View File

@@ -6,6 +6,8 @@ github.com/colinwilson/lotusdocs v0.0.0-20230821033552-c5bcbdd9df80 h1:jKZF8sqr/
github.com/colinwilson/lotusdocs v0.0.0-20230821033552-c5bcbdd9df80/go.mod h1:9zu2REJDi+zdPRcR5/bRYSUR7gkNF4NQLvV38SEoCP8=
github.com/colinwilson/lotusdocs v0.0.0-20230919015602-a9717caaab14 h1:ORzVQia2njOTCs/5cTQZW0Y+YRZlupgwtGx3umABTcc=
github.com/colinwilson/lotusdocs v0.0.0-20230919015602-a9717caaab14/go.mod h1:9zu2REJDi+zdPRcR5/bRYSUR7gkNF4NQLvV38SEoCP8=
github.com/colinwilson/lotusdocs v0.1.0 h1:oTC8pAYQp9XDNaUwE4SEY+id3ByNELxIIFrktYEGxYA=
github.com/colinwilson/lotusdocs v0.1.0/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=

View File

@@ -18,6 +18,9 @@ defaultContentLanguage = 'zh-cn'
weight = 10
disabled = true
[build]
noJSConfigInAssets = true
[module]
[module.hugoVersion]
extended = true

View File

@@ -11,8 +11,12 @@
{{ end -}}
{{ if .Page.Store.Get "hasMermaid" }}
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs';
{{ $mermaid := resources.Get (printf "%s/%s" ($.Scratch.Get "pathName") "js/mermaid.js") }}
{{ if hugo.IsProduction }}
{{ $mermaid = $mermaid | minify | fingerprint "sha384" }}
{{ end }}
<script src="{{ $mermaid.RelPermalink }}" {{ if hugo.IsProduction }}integrity="{{ $mermaid.Data.Integrity }}"{{ end }}></script>
<script>
const config = {
startOnLoad:true,
logLevel: "error",

View File

@@ -7,11 +7,33 @@
{{ $yearToken := (cond (isset .Site.Params (lower "copyrightYearToken")) $.Site.Params.copyrightYearToken ":YEAR:") }}
{{ replace $.Site.Params.footer.copyright $yearToken (string (now.Format "2006")) | markdownify }}
</p>
<!--change-->
<p class="github-badge">
<span class="badge-subject">云操作系统</span><span class="badge-value bg-blue"><a style="color:#fff" href="https://sealos.io/" target="_blank">Sealos</a></span>
<span class="badge-subject">云开发</span><span class="badge-value bg-brightgreen"><a style="color:#fff" href="https://laf.run" target="_blank">Laf</a></span>
<span class="badge-subject">云原生存储</span><span class="badge-value bg-orange"><a style="color:#fff" href="https://github.com/labring/sealfs" target="_blank">Sealfs</a></span>
</p>
<div id="fixed-box">
<div class="feedback-btn-wrapper">
<a
href="https://fael3z0zfze.feishu.cn/share/base/form/shrcnRxj3utrzjywsom96Px4sud"
style="text-decoration: none"
target="_blank"
>
<button id="feedback-btn" title="Give feedback">
<svg class="inline w-5 h-5" viewBox="0 0 20 20" fill="currentColor">
<path
fill-rule="evenodd"
d="M18 13V5a2 2 0 00-2-2H4a2 2 0 00-2 2v8a2 2 0 002 2h3l3 3 3-3h3a2 2 0 002-2zM5 7a1 1 0 011-1h8a1 1 0 110 2H6a1 1 0 01-1-1zm1 3a1 1 0 100 2h3a1 1 0 100-2H6z"
clip-rule="evenodd"
></path>
</svg>
<span _msttexthash="6039839" _msthash="295">咨询合作</span>
</button>
</a>
</div>
</div>
<!-- End -->
</div>
</div><!--end col-->
</div><!--end row-->

View File

@@ -30,6 +30,8 @@
<meta name="Version" content="v0.1.0" />
<!-- favicon -->
{{ block "favicon" . }}{{ partialCached (printf "%s/%s" ($.Scratch.Get "pathName") "head/favicon.html") . }}{{ end }}
{{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "head/opengraph") . }}
{{- partial (printf "%s/%s" ($.Scratch.Get "pathName") "head/twitter_cards") . }}
<!-- Dark Mode -->
{{ if eq .Site.Params.docs.darkMode true -}}
{{ $darkModeInit := resources.Get (printf "/%s/%s" ($.Scratch.Get "pathName") "js/darkmode-init.js") | js.Build | minify -}}

View File

@@ -42,7 +42,45 @@
<ul>
{{ range .Pages }}
{{ $active := in $currentPage.RelPermalink .RelPermalink }}
<li class="{{ if $active }}current{{ end }} {{ if eq .Site.Params.docs.sidebarIcons true -}}{{ else }}no-icon{{ end }}"><a class="sidebar-nested-link" href="{{ .Permalink }}">{{ .Title }}</a></li>
{{ if .IsSection }}
<li class="sidebar-dropdown nested {{ if eq .Site.Params.docs.sidebarIcons true -}}{{ else }}no-icon{{ end }} {{ if $active }}current active{{ end }}">
<button class="btn">
{{ if eq .Site.Params.docs.sidebarIcons true -}}
<!-- <span class="material-icons me-2">{{- .Params.icon }}</span> -->
{{ end }}
{{- .Title }}
</button>
<div class="sidebar-submenu {{ if $active }}d-block{{ end }}">
<ul>
{{ range .Pages }}
{{ $active := in $currentPage.RelPermalink .RelPermalink }}
{{ if .IsSection }}
<li class="sidebar-dropdown nested {{ if eq .Site.Params.docs.sidebarIcons true -}}{{ else }}no-icon{{ end }} {{ if $active }}current active{{ end }}">
<button class="btn">
{{ if eq .Site.Params.docs.sidebarIcons true -}}
<!-- <span class="material-icons me-2">{{- .Params.icon }}</span> -->
{{ end }}
{{- .Title }}
</button>
<div class="sidebar-submenu {{ if $active }}d-block{{ end }}">
<ul>
{{ range .Pages }}
{{ $active := in $currentPage.RelPermalink .RelPermalink }}
<li class="{{ if $active }}current{{ end }} {{ if eq .Site.Params.docs.sidebarIcons true -}}{{ else }}no-icon{{ end }}"><a class="sidebar-nested-link" href="{{ .Permalink }}">{{ .Title }}</a></li>
{{ end }}
</ul>
</div>
</li>
{{ else }}
<li class="{{ if $active }}current{{ end }} {{ if eq .Site.Params.docs.sidebarIcons true -}}{{ else }}no-icon{{ end }}"><a class="sidebar-nested-link" href="{{ .Permalink }}">{{ .Title }}</a></li>
{{ end }}
{{ end }}
</ul>
</div>
</li>
{{ else }}
<li class="{{ if $active }}current{{ end }} {{ if eq .Site.Params.docs.sidebarIcons true -}}{{ else }}no-icon{{ end }}"><a class="sidebar-nested-link" href="{{ .Permalink }}">{{ .Title }}</a></li>
{{ end }}
{{ end }}
</ul>
</div>

View File

@@ -1 +0,0 @@
{"Target":"docs/scss/style.min.dfae72221c400d9e5816cbed333a16f8ea12c17463fb493c40bab5119dc455b63fe877d0b76b92a7d5c6c595331a243d.css","MediaType":"text/css","Data":{"Integrity":"sha384-365yIhxADZ5YFsvtMzoW+OoSwXRj+0k8QLq1EZ3EVbY/6HfQt2uSp9XGxZUzGiQ9"}}

View File

@@ -1 +0,0 @@
{"Target":"docs/scss/style.css","MediaType":"text/css","Data":{}}

View File

@@ -1 +0,0 @@
{"Target":"scss/style.min.4d48305d7fec6ad346a2319f83fc622c27253ec11be0c970ae5b04baa6074df3868a7239c250d323090fdb718523631c.css","MediaType":"text/css","Data":{"Integrity":"sha384-TUgwXX/satNGojGfg/xiLCclPsEb4MlwrlsEuqYHTfOGinI5wlDTIwkP23GFI2Mc"}}

View File

@@ -1 +0,0 @@
{"Target":"scss/style.css","MediaType":"text/css","Data":{}}

View File

@@ -1,63 +0,0 @@
{
"FeConfig": {
"show_emptyChat": true,
"show_register": false,
"show_appStore": false,
"show_userDetail": false,
"show_contact": true,
"show_git": true,
"show_doc": true,
"systemTitle": "FastGPT",
"authorText": "Made by FastGPT Team.",
"scripts": []
},
"SystemParams": {
"vectorMaxProcess": 15,
"qaMaxProcess": 15,
"pgIvfflatProbe": 20
},
"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": ""
}
],
"VectorModels": [
{
"model": "text-embedding-ada-002",
"name": "Embedding-2",
"price": 0,
"defaultToken": 500,
"maxToken": 3000
}
],
"QAModel": {
"model": "gpt-3.5-turbo-16k",
"name": "GPT35-16k",
"maxToken": 16000,
"price": 0
}
}

View File

@@ -8,4 +8,4 @@ starlette==0.27.0
tiktoken==0.4.0
torch==2.0.1
transformers==4.31.0
uvicorn==0.23.2
uvicorn==0.23.2

View File

@@ -1,6 +1,6 @@
{
"name": "fastgpt",
"version": "3.7",
"version": "4.0",
"private": true,
"scripts": {
"prepare": "husky install",
@@ -11,7 +11,7 @@
"i18next": "^23.2.11",
"lint-staged": "^13.2.1",
"next-i18next": "^14.0.0",
"prettier": "^2.8.7",
"prettier": "^3.0.3",
"react-i18next": "^13.0.2"
},
"lint-staged": {

View File

@@ -0,0 +1 @@
export const PRICE_SCALE = 100000;

View File

@@ -0,0 +1,9 @@
/* bill common */
import { PRICE_SCALE } from './constants';
/**
* dataset price / PRICE_SCALE = real price
*/
export const formatPrice = (val = 0, multiple = 1) => {
return Number(((val / PRICE_SCALE) * multiple).toFixed(10));
};

View File

@@ -0,0 +1,4 @@
{
"name": "@fastgpt/common",
"version": "1.0.0"
}

View File

@@ -0,0 +1,21 @@
{
"compilerOptions": {
"target": "es2015",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"baseUrl": "."
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.d.ts"],
"exclude": ["node_modules"]
}

View File

@@ -1,4 +1,4 @@
import { UserModelSchema } from '@/types/mongoSchema';
import { UserModelSchema } from '../user/type';
import { Configuration, OpenAIApi } from 'openai';
export const openaiBaseUrl = process.env.OPENAI_BASE_URL || 'https://api.openai.com/v1';

View File

@@ -0,0 +1 @@
export { ChatCompletionRequestMessageRoleEnum } from 'openai';

View File

@@ -0,0 +1,57 @@
import { ChatCompletionRequestMessage } from '../type';
import { getAIChatApi } from '../config';
export const Prompt_QuestionGuide = `我不太清楚问你什么问题,请帮我生成 3 个问题引导我继续提问。问题的长度应小于20个字符按 JSON 格式返回: ["问题1", "问题2", "问题3"]`;
export async function createQuestionGuide({
messages,
model
}: {
messages: ChatCompletionRequestMessage[];
model: string;
}) {
const chatAPI = getAIChatApi();
const { data } = await chatAPI.createChatCompletion({
model: model,
temperature: 0,
max_tokens: 200,
messages: [
...messages,
{
role: 'user',
content: Prompt_QuestionGuide
}
],
stream: false
});
const answer = data.choices?.[0].message?.content || '';
const totalTokens = data.usage?.total_tokens || 0;
const start = answer.indexOf('[');
const end = answer.lastIndexOf(']');
if (start === -1 || end === -1) {
return {
result: [],
tokens: totalTokens
};
}
const jsonStr = answer
.substring(start, end + 1)
.replace(/(\\n|\\)/g, '')
.replace(/ /g, '');
try {
return {
result: JSON.parse(jsonStr),
tokens: totalTokens
};
} catch (error) {
return {
result: [],
tokens: totalTokens
};
}
}

1
packages/core/ai/type.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
export type { CreateChatCompletionRequest, ChatCompletionRequestMessage } from 'openai';

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