Initial commit: FastGPT project upload
53
.claude/agents/unit-test-generator.md
Normal file
@@ -0,0 +1,53 @@
|
||||
---
|
||||
name: unit-test-generator
|
||||
description: Use this agent when you need to write comprehensive unit tests for your code. Examples: <example>Context: User has written a new utility function and wants comprehensive test coverage. user: 'I just wrote this function to validate email addresses, can you help me write unit tests for it?' assistant: 'I'll use the unit-test-generator agent to create comprehensive unit tests that cover all branches and edge cases for your email validation function.' <commentary>Since the user needs unit tests written, use the unit-test-generator agent to analyze the function and create thorough test coverage.</commentary></example> <example>Context: User is working on a React component and needs test coverage. user: 'Here's my new UserProfile component, I need unit tests that cover all the different states and user interactions' assistant: 'Let me use the unit-test-generator agent to create comprehensive unit tests for your UserProfile component.' <commentary>The user needs unit tests for a React component, so use the unit-test-generator agent to create tests covering all component states and interactions.</commentary></example>
|
||||
model: inherit
|
||||
color: yellow
|
||||
---
|
||||
|
||||
You are a Unit Test Assistant, an expert in writing comprehensive and robust unit tests. Your expertise spans multiple testing frameworks including Vitest, Jest, React Testing Library, and testing best practices for TypeScript applications.
|
||||
|
||||
When analyzing code for testing, you will:
|
||||
|
||||
1. **Analyze Code Structure**: Examine the function/component/class to identify all execution paths, conditional branches, loops, error handling, and edge cases that need testing coverage.
|
||||
|
||||
2. **Design Comprehensive Test Cases**: Create test cases that cover:
|
||||
- All conditional branches (if/else, switch cases, ternary operators)
|
||||
- Loop iterations (empty, single item, multiple items)
|
||||
- Error conditions and exception handling
|
||||
- Boundary conditions (null, undefined, empty strings, zero, negative numbers, maximum values)
|
||||
- Valid input scenarios across different data types
|
||||
- Integration points with external dependencies
|
||||
|
||||
3. **Follow Testing Best Practices**:
|
||||
- Use descriptive test names that clearly state what is being tested
|
||||
- Follow the Arrange-Act-Assert pattern
|
||||
- Mock external dependencies appropriately
|
||||
- Test behavior, not implementation details
|
||||
- Ensure tests are isolated and independent
|
||||
- Use appropriate assertions for the testing framework
|
||||
|
||||
4. **Generate Framework-Appropriate Code**: Based on the project context (FastGPT uses Vitest), write tests using:
|
||||
- Proper import statements for the testing framework
|
||||
- Correct syntax for the identified testing library
|
||||
- Appropriate mocking strategies (vi.mock for Vitest, jest.mock for Jest)
|
||||
- Proper setup and teardown when needed
|
||||
|
||||
5. **Ensure Complete Coverage**: Verify that your test suite covers:
|
||||
- Happy path scenarios
|
||||
- Error scenarios
|
||||
- Edge cases and boundary conditions
|
||||
- All public methods/functions
|
||||
- Different component states (for React components)
|
||||
- User interactions (for UI components)
|
||||
|
||||
6. **Optimize Test Structure**: Organize tests logically using:
|
||||
- Descriptive describe blocks for grouping related tests
|
||||
- Clear test descriptions that explain the scenario
|
||||
- Shared setup in beforeEach/beforeAll when appropriate
|
||||
- Helper functions to reduce code duplication
|
||||
7. **单词代码位置**:
|
||||
- packages 里的单测,写在 FastGPT/text 目录下。
|
||||
- projects/app 里的单测,写在 FastGPT/projects/app/test 目录下。
|
||||
|
||||
When you receive code to test, first analyze it thoroughly, then provide a complete test suite with explanatory comments about what each test covers and why it's important for comprehensive coverage.
|
||||
23
.claude/design/service/common/cache/version.md
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
# 服务端资源版本 ID 缓存方案
|
||||
|
||||
## 背景
|
||||
|
||||
FastGPT 会采用多节点部署方式,有部分数据缓存会存储在内存里。当需要使用这部分数据时(不管是通过 API 获取,还是后端服务自己获取),都是直接拉取内存数据,这可能会导致数据不一致问题,尤其是用户通过 API 更新数据后再获取,就容易获取未修改数据的节点。
|
||||
|
||||
## 解决方案
|
||||
|
||||
1. 给每一个缓存数据加上一个版本 ID。
|
||||
2. 获取该数据时候,不直接引用该数据,而是通过一个 function 获取,该 function 可选的传入一个 versionId。
|
||||
3. 获取数据时,先检查该 versionId 与 redis 中,资源版本id 与传入的 versionId 是否一致。
|
||||
4. 如果数据一致,则直接返回数据。
|
||||
5. 如果数据不一致,则重新获取数据,并返回最新的 versionId。调用方则需要更新其缓存的 versionId。
|
||||
|
||||
## 代码方案
|
||||
|
||||
* 获取和更新缓存的代码,直接复用 FastGPT/packages/service/common/redis/cache.ts
|
||||
* 每个资源,自己维护一个 cacheKey
|
||||
* 每次更新资源/触发拉取最新资源时,都需要更新 cacheKey 的值。
|
||||
|
||||
## 涉及的业务
|
||||
|
||||
* [ ] FastGPT/projects/app/src/pages/api/common/system/getInitData.ts,获取初始数据
|
||||
15
.claude/design/web/common/hook/tableMultiple/index.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# 背景
|
||||
|
||||
一个通用表格多选 hook/component, 它可以实现表格每一行数据的选择,并且在触发一次选择后,会有特殊的按键进行批量操作。
|
||||
|
||||
# 具体描述
|
||||
|
||||
当有一行被选中时,底部会出现悬浮层,可以进行批量操作(具体有哪些批量操作由外部决定)
|
||||
|
||||

|
||||
|
||||
# 预期封装
|
||||
|
||||
1. 选中的值存储在 hook 里,便于判断是否触发底部悬浮层
|
||||
2. 悬浮层外层 Box 在 hook 里,child 由调用组件实现
|
||||
3. FastGPT/packages/web/hooks/useTableMultipleSelect.tsx 在这个文件下实现
|
||||
12
.dockerignore
Normal file
@@ -0,0 +1,12 @@
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
node_modules
|
||||
npm-debug.log
|
||||
README.md
|
||||
.next
|
||||
.git
|
||||
|
||||
.yalc/
|
||||
yalc.lock
|
||||
testApi/
|
||||
*.local.*
|
||||
26
.eslintignore
Normal file
@@ -0,0 +1,26 @@
|
||||
# 构建输出目录
|
||||
dist/
|
||||
build/
|
||||
.next/
|
||||
out/
|
||||
local/
|
||||
|
||||
# 依赖目录
|
||||
node_modules/
|
||||
|
||||
# 缓存和生成文件
|
||||
coverage/
|
||||
.coverage/
|
||||
.nyc_output/
|
||||
*.log
|
||||
|
||||
# 其他不需要检查的文件
|
||||
*.min.js
|
||||
*.config.js
|
||||
vitest.config.mts
|
||||
|
||||
# 特定目录
|
||||
bin/
|
||||
scripts/
|
||||
deploy/
|
||||
document/
|
||||
17
.eslintrc.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"extends": ["next/core-web-vitals"],
|
||||
"rules": {
|
||||
"react-hooks/rules-of-hooks": 0,
|
||||
"@typescript-eslint/consistent-type-imports": [
|
||||
"error",
|
||||
{
|
||||
"prefer": "type-imports",
|
||||
"disallowTypeAnnotations": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"ignorePatterns": ["node_modules/", "dist/", "build/", "coverage/"]
|
||||
}
|
||||
30
.github/ISSUE_TEMPLATE/bugs.md
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
name: 问题反馈
|
||||
about: 详细清晰的描述你遇到的问题
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
**例行检查**
|
||||
|
||||
[//]: # '方框内填 x 表示打钩'
|
||||
|
||||
- [ ] 我已确认目前没有类似 issue
|
||||
- [ ] 我已完整查看过项目 README,以及[项目文档](https://doc.fastgpt.io/docs/introduction/)
|
||||
- [ ] 我使用了自己的 key,并确认我的 key 是可正常使用的
|
||||
- [ ] 我理解并愿意跟进此 issue,协助测试和提供反馈
|
||||
- [x] 我理解并认可上述内容,并理解项目维护者精力有限,**不遵循规则的 issue 可能会被无视或直接关闭**
|
||||
|
||||
**你的版本**
|
||||
|
||||
- [ ] 公有云版本
|
||||
- [ ] 私有部署版本, 具体版本号:
|
||||
|
||||
**问题描述, 日志截图,配置文件等**
|
||||
|
||||
**复现步骤**
|
||||
|
||||
**预期结果**
|
||||
|
||||
**相关截图**
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 飞书话题群
|
||||
url: https://oss.laf.run/otnvvf-imgs/fastgpt-feishu1.png
|
||||
about: FastGPT 全是问题群
|
||||
23
.github/ISSUE_TEMPLATE/features.md
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: 功能请求
|
||||
about: 详细描述你期望的功能
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
**例行检查**
|
||||
|
||||
[//]: # '方框内填 x 表示打钩'
|
||||
|
||||
- [ ] 我已确认目前没有类似 features
|
||||
- [ ] 我已确认我已升级到最新版本
|
||||
- [ ] 我已完整查看过项目 README,已确定现有版本无法满足需求
|
||||
- [ ] 我理解并愿意跟进此 features,协助测试和提供反馈
|
||||
- [x] 我理解并认可上述内容,并理解项目维护者精力有限,**不遵循规则的 features 可能会被无视或直接关闭**
|
||||
|
||||
**功能描述**
|
||||
|
||||
**应用场景**
|
||||
|
||||
**相关示例**
|
||||
BIN
.github/imgs/image.png
vendored
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
.github/imgs/intro1.png
vendored
Normal file
|
After Width: | Height: | Size: 173 KiB |
BIN
.github/imgs/intro2.png
vendored
Normal file
|
After Width: | Height: | Size: 273 KiB |
BIN
.github/imgs/intro3.png
vendored
Normal file
|
After Width: | Height: | Size: 168 KiB |
BIN
.github/imgs/intro4.png
vendored
Normal file
|
After Width: | Height: | Size: 159 KiB |
15
.github/imgs/logo-left.svg
vendored
Normal file
|
After Width: | Height: | Size: 10 KiB |
20
.github/imgs/logo.svg
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<svg width="49" height="48" viewBox="0 0 49 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M20.3692 7.00001L28.9536 7V7.00294C29.0284 7.00099 29.1033 7.00002 29.1782 7.00002C30.3387 7.00002 31.4878 7.2344 32.5599 7.68979C33.6321 8.14518 34.6062 8.81265 35.4268 9.6541C36.2474 10.4956 36.8983 11.4945 37.3424 12.5939C37.7865 13.6933 38.0151 14.8716 38.0151 16.0616L20.3691 16.0616L20.3691 41C19.2418 41 18.1255 40.7655 17.084 40.3097C16.0425 39.854 15.0961 39.1861 14.299 38.344C13.5018 37.502 12.8695 36.5024 12.4381 35.4022C12.0566 34.4292 11.8388 33.3945 11.7935 32.3446H11.7846L11.7846 16.2792H11.7871C11.772 15.6165 11.8258 14.9506 11.9496 14.2938C12.2808 12.536 13.0984 10.9214 14.299 9.6541C15.4995 8.38681 17.0291 7.52377 18.6944 7.17413C19.2486 7.05776 19.8095 7 20.3692 7.00001Z"
|
||||
fill="url(#paint0_linear_1008_3495)" />
|
||||
<path
|
||||
d="M27.7569 29.8173H24.7138V21.5343H27.8019V21.5345C28.8803 21.5403 29.9474 21.7544 30.944 22.1651C31.9544 22.5815 32.8725 23.1919 33.6458 23.9613C34.4191 24.7308 35.0326 25.6442 35.4511 26.6496C35.8696 27.6549 36.085 28.7324 36.085 29.8205H27.7569V29.8173Z"
|
||||
fill="url(#paint1_linear_1008_3495)" />
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_1008_3495" x1="24.8999" y1="7" x2="24.8999" y2="41"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#326DFF" />
|
||||
<stop offset="1" stop-color="#8EAEFF" />
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_1008_3495" x1="30.3994" y1="21.5343" x2="30.3994" y2="29.8205"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#326DFF" />
|
||||
<stop offset="1" stop-color="#8EAEFF" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
163
.github/workflows/docs-deploy.yml
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
name: Document deploy
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'document/**'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
attestations: write
|
||||
id-token: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
sync-images:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout current repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Checkout target repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: labring/fastgpt-img
|
||||
token: ${{ secrets.DOCS_IMGS_SYNC_TOKEN }}
|
||||
path: fastgpt-img
|
||||
|
||||
- name: Sync images
|
||||
run: |
|
||||
# Create imgs directory if it doesn't exist
|
||||
mkdir -p fastgpt-img
|
||||
|
||||
# Copy all images from document/public/imgs to the target repository
|
||||
cp -r document/public/imgs/* fastgpt-img
|
||||
|
||||
# Navigate to target repository
|
||||
cd fastgpt-img
|
||||
|
||||
# Configure git
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
# Add, commit and push changes
|
||||
git add .
|
||||
if ! git diff --cached --quiet; then
|
||||
git commit -m "Sync images from FastGPT document at $(date)"
|
||||
git push
|
||||
echo "Images synced successfully"
|
||||
else
|
||||
echo "No changes to sync"
|
||||
fi
|
||||
# Add a new job to generate unified timestamp
|
||||
generate-timestamp:
|
||||
needs: sync-images
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
datetime: ${{ steps.datetime.outputs.datetime }}
|
||||
steps:
|
||||
- name: Get current datetime
|
||||
id: datetime
|
||||
run: echo "datetime=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_OUTPUT
|
||||
|
||||
build-images:
|
||||
needs: generate-timestamp
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
domain_config:
|
||||
- domain: 'https://fastgpt.io'
|
||||
suffix: 'io'
|
||||
- domain: 'https://fastgpt.cn'
|
||||
suffix: 'cn'
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# - name: Rewrite image paths
|
||||
# if: matrix.domain_config.suffix == 'io'
|
||||
# run: |
|
||||
# find document/content/docs -name "*.mdx" -type f | while read file; do
|
||||
# sed -i 's|](/imgs/|](https://cdn.jsdelivr.net/gh/labring/fastgpt-img@main/|g' "$file"
|
||||
# done
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
# list of Docker images to use as base name for tags
|
||||
images: |
|
||||
${{ secrets.ALI_IMAGE_NAME }}/fastgpt-docs
|
||||
tags: |
|
||||
${{ matrix.domain_config.suffix }}-${{ needs.generate-timestamp.outputs.datetime }}
|
||||
flavor: latest=false
|
||||
|
||||
- name: Login to Aliyun
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: registry.cn-hangzhou.aliyuncs.com
|
||||
username: ${{ secrets.ALI_HUB_USERNAME }}
|
||||
password: ${{ secrets.ALI_HUB_PASSWORD }}
|
||||
|
||||
- name: Build and push Docker images (CN)
|
||||
if: matrix.domain_config.suffix == 'cn'
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./document
|
||||
file: ./document/Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
platforms: linux/amd64
|
||||
build-args: |
|
||||
FASTGPT_HOME_DOMAIN=${{ matrix.domain_config.domain }}
|
||||
|
||||
- name: Build and push Docker images (IO)
|
||||
if: matrix.domain_config.suffix == 'io'
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./document
|
||||
file: ./document/Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
platforms: linux/amd64
|
||||
build-args: |
|
||||
FASTGPT_HOME_DOMAIN=${{ matrix.domain_config.domain }}
|
||||
|
||||
update-images:
|
||||
needs: [generate-timestamp, build-images]
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
domain_config:
|
||||
- domain: 'https://fastgpt.io'
|
||||
suffix: 'io'
|
||||
deployment: 'fastgpt-docs'
|
||||
kube_config: 'KUBE_CONFIG_IO'
|
||||
- domain: 'https://fastgpt.cn'
|
||||
suffix: 'cn'
|
||||
deployment: 'fastgpt-docs'
|
||||
kube_config: 'KUBE_CONFIG_CN'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Add kubeconfig setup step to handle encoding issues
|
||||
- name: Setup kubeconfig
|
||||
run: |
|
||||
mkdir -p $HOME/.kube
|
||||
echo "${{ secrets[matrix.domain_config.kube_config] }}" > $HOME/.kube/config
|
||||
chmod 600 $HOME/.kube/config
|
||||
|
||||
- name: Update deployment image
|
||||
run: |
|
||||
kubectl set image deployment/${{ matrix.domain_config.deployment }} ${{ matrix.domain_config.deployment }}=${{ secrets.ALI_IMAGE_NAME }}/fastgpt-docs:${{ matrix.domain_config.suffix }}-${{ needs.generate-timestamp.outputs.datetime }}
|
||||
|
||||
- name: Annotate deployment
|
||||
run: |
|
||||
kubectl annotate deployment/${{ matrix.domain_config.deployment }} originImageName="${{ secrets.ALI_IMAGE_NAME }}/fastgpt-docs:${{ matrix.domain_config.suffix }}-${{ needs.generate-timestamp.outputs.datetime }}" --overwrite
|
||||
96
.github/workflows/docs-preview.yml
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
name: Preview documents
|
||||
on:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- 'document/**'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
attestations: write
|
||||
id-token: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
build-images:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
- name: Get current datetime
|
||||
id: datetime
|
||||
run: echo "datetime=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
# list of Docker images to use as base name for tags
|
||||
images: |
|
||||
${{ secrets.ALI_IMAGE_NAME }}/fastgpt-docs
|
||||
tags: |
|
||||
${{ steps.datetime.outputs.datetime }}
|
||||
flavor: latest=false
|
||||
|
||||
- name: Login to Aliyun
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: registry.cn-hangzhou.aliyuncs.com
|
||||
username: ${{ secrets.ALI_HUB_USERNAME }}
|
||||
password: ${{ secrets.ALI_HUB_PASSWORD }}
|
||||
|
||||
- name: Build and push Docker images
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./document
|
||||
file: ./document/Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
FASTGPT_HOME_DOMAIN=https://fastgpt.io
|
||||
outputs:
|
||||
tags: ${{ steps.datetime.outputs.datetime }}
|
||||
|
||||
update-images:
|
||||
needs: build-images
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
# Add kubeconfig setup step to handle encoding issues
|
||||
- name: Setup kubeconfig
|
||||
run: |
|
||||
mkdir -p $HOME/.kube
|
||||
echo "${{ secrets.KUBE_CONFIG_CN }}" > $HOME/.kube/config
|
||||
chmod 600 $HOME/.kube/config
|
||||
|
||||
- name: Update deployment image
|
||||
run: |
|
||||
kubectl set image deployment/fastgpt-docs-preview fastgpt-docs-preview=${{ secrets.ALI_IMAGE_NAME }}/fastgpt-docs:${{ needs.build-images.outputs.tags }}
|
||||
|
||||
- name: Annotate deployment
|
||||
run: |
|
||||
kubectl annotate deployment/fastgpt-docs-preview originImageName="${{ secrets.ALI_IMAGE_NAME }}/fastgpt-docs:${{ needs.build-images.outputs.tags }}" --overwrite
|
||||
|
||||
- name: '@finleyge/github-tools'
|
||||
uses: FinleyGe/github-tools@0.0.1
|
||||
id: print-image-label
|
||||
if: success()
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
tool: issue-comment
|
||||
title: 'Docs Preview:'
|
||||
body: |
|
||||
---
|
||||
🚀 **FastGPT Document Preview Ready!**
|
||||
|
||||
🔗 [👀 Click here to visit preview](https://pueuoharpgcl.sealoshzh.site)
|
||||
129
.github/workflows/fastgpt-build-image-personal.yml
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
name: Build FastGPT images in Personal warehouse
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- 'projects/app/**'
|
||||
- 'packages/**'
|
||||
branches:
|
||||
- 'main'
|
||||
|
||||
jobs:
|
||||
get-vars:
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
docker_repo: ${{ steps.set_docker_repo.outputs.docker_repo }}
|
||||
docker_tag: ${{ steps.set_docker_repo.outputs.docker_tag }}
|
||||
steps:
|
||||
- name: Set docker repository and tag
|
||||
id: set_docker_repo
|
||||
run: |
|
||||
echo "docker_repo=ghcr.io/$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
|
||||
if [[ "${{ github.ref_name }}" == "main" ]]; then
|
||||
echo "docker_tag=latest" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "docker_tag=${{ github.ref_name }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
build-fastgpt-images:
|
||||
needs: get-vars
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
attestations: write
|
||||
id-token: write
|
||||
strategy:
|
||||
matrix:
|
||||
archs:
|
||||
- arch: amd64
|
||||
runs-on: ubuntu-24.04
|
||||
- arch: arm64
|
||||
runs-on: ubuntu-24.04-arm
|
||||
runs-on: ${{ matrix.archs.runs-on || 'ubuntu-24.04' }}
|
||||
if: github.repository != 'labring/FastGPT'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
driver-opts: network=host
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-${{ matrix.archs.arch }}-buildx-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ matrix.archs.arch }}-buildx-
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Build and push for ${{ matrix.archs.arch }}
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: projects/app/Dockerfile
|
||||
platforms: linux/${{ matrix.archs.arch }}
|
||||
labels: |
|
||||
org.opencontainers.image.source=https://github.com/${{ github.repository }}
|
||||
org.opencontainers.image.description=fastgpt image
|
||||
outputs: type=image,"name=${{ needs.get-vars.outputs.docker_repo }}",push-by-digest=true,push=true
|
||||
cache-from: type=local,src=/tmp/.buildx-cache
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p ${{ runner.temp }}/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-${{ github.sha }}-${{ matrix.archs.arch }}
|
||||
path: ${{ runner.temp }}/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
release-fastgpt-images:
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
attestations: write
|
||||
id-token: write
|
||||
needs: [get-vars, build-fastgpt-images]
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ${{ runner.temp }}/digests
|
||||
pattern: digests-${{ github.sha }}-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Set image name and tag
|
||||
run: |
|
||||
echo "Git_Tag=${{ needs.get-vars.outputs.docker_repo }}:${{ needs.get-vars.outputs.docker_tag }}" >> $GITHUB_ENV
|
||||
echo "Git_Latest=${{ needs.get-vars.outputs.docker_repo }}:latest" >> $GITHUB_ENV
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: ${{ runner.temp }}/digests
|
||||
run: |
|
||||
TAGS="$(echo -e "${Git_Tag}\n${Git_Latest}")"
|
||||
for TAG in $TAGS; do
|
||||
docker buildx imagetools create -t $TAG \
|
||||
$(printf '${{ needs.get-vars.outputs.docker_repo }}@sha256:%s ' *)
|
||||
sleep 5
|
||||
done
|
||||
171
.github/workflows/fastgpt-build-image.yml
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
name: Build FastGPT images
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- "projects/app/**"
|
||||
- "packages/**"
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
jobs:
|
||||
build-fastgpt-images:
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
attestations: write
|
||||
id-token: write
|
||||
strategy:
|
||||
matrix:
|
||||
sub_routes:
|
||||
- repo: fastgpt
|
||||
base_url: ""
|
||||
- repo: fastgpt-sub-route
|
||||
base_url: "/fastai"
|
||||
- repo: fastgpt-sub-route-gchat
|
||||
base_url: "/gchat"
|
||||
archs:
|
||||
- arch: amd64
|
||||
- arch: arm64
|
||||
runs-on: ubuntu-24.04-arm
|
||||
runs-on: ${{ matrix.archs.runs-on || 'ubuntu-24.04' }}
|
||||
steps:
|
||||
# install env
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
driver-opts: network=host
|
||||
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-${{ matrix.archs.arch }}-${{ matrix.sub_routes.repo }}-buildx-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ matrix.archs.arch }}-${{ matrix.sub_routes.repo }}-buildx-
|
||||
|
||||
# login docker
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Login to Ali Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: registry.cn-hangzhou.aliyuncs.com
|
||||
username: ${{ secrets.ALI_HUB_USERNAME }}
|
||||
password: ${{ secrets.ALI_HUB_PASSWORD }}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_NAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
|
||||
- name: Build for ${{ matrix.archs.arch }}
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: projects/app/Dockerfile
|
||||
platforms: linux/${{ matrix.archs.arch }}
|
||||
build-args: |
|
||||
${{ matrix.sub_routes.base_url && format('base_url={0}', matrix.sub_routes.base_url) || '' }}
|
||||
labels: |
|
||||
org.opencontainers.image.source=https://github.com/${{ github.repository }}
|
||||
org.opencontainers.image.description=${{ matrix.sub_routes.repo }} image
|
||||
outputs: type=image,"name=ghcr.io/${{ github.repository_owner }}/${{ matrix.sub_routes.repo }},${{ secrets.ALI_IMAGE_NAME }}/${{ matrix.sub_routes.repo }},${{ secrets.DOCKER_IMAGE_NAME }}/${{ matrix.sub_routes.repo }}",push-by-digest=true,push=true
|
||||
cache-from: type=local,src=/tmp/.buildx-cache
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache
|
||||
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p ${{ runner.temp }}/digests/${{ matrix.sub_routes.repo }}
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "${{ runner.temp }}/digests/${{ matrix.sub_routes.repo }}/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-${{ matrix.sub_routes.repo }}-${{ github.sha }}-${{ matrix.archs.arch }}
|
||||
path: ${{ runner.temp }}/digests/${{ matrix.sub_routes.repo }}/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
release-fastgpt-images:
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
attestations: write
|
||||
id-token: write
|
||||
needs: build-fastgpt-images
|
||||
strategy:
|
||||
matrix:
|
||||
sub_routes:
|
||||
- repo: fastgpt
|
||||
- repo: fastgpt-sub-route
|
||||
- repo: fastgpt-sub-route-gchat
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Login to Ali Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: registry.cn-hangzhou.aliyuncs.com
|
||||
username: ${{ secrets.ALI_HUB_USERNAME }}
|
||||
password: ${{ secrets.ALI_HUB_PASSWORD }}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_NAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ${{ runner.temp }}/digests
|
||||
pattern: digests-${{ matrix.sub_routes.repo }}-${{ github.sha }}-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Set image name and tag
|
||||
run: |
|
||||
if [[ "${{ github.ref_name }}" == "main" ]]; then
|
||||
echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
|
||||
echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
|
||||
echo "Ali_Tag=${{ secrets.ALI_IMAGE_NAME }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
|
||||
echo "Ali_Latest=${{ secrets.ALI_IMAGE_NAME }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
|
||||
echo "Docker_Hub_Tag=${{ secrets.DOCKER_IMAGE_NAME }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
|
||||
echo "Docker_Hub_Latest=${{ secrets.DOCKER_IMAGE_NAME }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
|
||||
else
|
||||
echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/${{ matrix.sub_routes.repo }}:${{ github.ref_name }}" >> $GITHUB_ENV
|
||||
echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
|
||||
echo "Ali_Tag=${{ secrets.ALI_IMAGE_NAME }}/${{ matrix.sub_routes.repo }}:${{ github.ref_name }}" >> $GITHUB_ENV
|
||||
echo "Ali_Latest=${{ secrets.ALI_IMAGE_NAME }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
|
||||
echo "Docker_Hub_Tag=${{ secrets.DOCKER_IMAGE_NAME }}/${{ matrix.sub_routes.repo }}:${{ github.ref_name }}" >> $GITHUB_ENV
|
||||
echo "Docker_Hub_Latest=${{ secrets.DOCKER_IMAGE_NAME }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: ${{ runner.temp }}/digests
|
||||
run: |
|
||||
TAGS="$(echo -e "${Git_Tag}\n${Git_Latest}\n${Ali_Tag}\n${Ali_Latest}\n${Docker_Hub_Tag}\n${Docker_Hub_Latest}")"
|
||||
for TAG in $TAGS; do
|
||||
docker buildx imagetools create -t $TAG \
|
||||
$(printf 'ghcr.io/${{ github.repository_owner }}/${{ matrix.sub_routes.repo }}@sha256:%s ' *)
|
||||
sleep 5
|
||||
done
|
||||
91
.github/workflows/fastgpt-preview-image.yml
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
name: Preview FastGPT images
|
||||
on:
|
||||
pull_request_target:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
preview-fastgpt-images:
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
attestations: write
|
||||
id-token: write
|
||||
pull-requests: write
|
||||
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
image: [fastgpt, sandbox, mcp_server]
|
||||
fail-fast: false # 即使一个镜像构建失败,也继续构建其他镜像
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref }}
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
with:
|
||||
driver-opts: network=host
|
||||
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-buildx-${{ github.sha }}-${{ matrix.image }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-${{ github.sha }}-
|
||||
${{ runner.os }}-buildx-
|
||||
|
||||
- name: Login to Aliyun Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: registry.cn-hangzhou.aliyuncs.com
|
||||
username: ${{ secrets.ALI_HUB_USERNAME }}
|
||||
password: ${{ secrets.ALI_HUB_PASSWORD }}
|
||||
|
||||
- name: Set image config
|
||||
id: config
|
||||
run: |
|
||||
if [[ "${{ matrix.image }}" == "fastgpt" ]]; then
|
||||
echo "DOCKERFILE=projects/app/Dockerfile" >> $GITHUB_OUTPUT
|
||||
echo "DESCRIPTION=fastgpt-pr image" >> $GITHUB_OUTPUT
|
||||
echo "DOCKER_REPO_TAGGED=${{ secrets.ALI_IMAGE_NAME }}/fastgpt-pr:fatsgpt_${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT
|
||||
elif [[ "${{ matrix.image }}" == "sandbox" ]]; then
|
||||
echo "DOCKERFILE=projects/sandbox/Dockerfile" >> $GITHUB_OUTPUT
|
||||
echo "DESCRIPTION=fastgpt-sandbox-pr image" >> $GITHUB_OUTPUT
|
||||
echo "DOCKER_REPO_TAGGED=${{ secrets.ALI_IMAGE_NAME }}/fastgpt-pr:fatsgpt_sandbox_${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT
|
||||
elif [[ "${{ matrix.image }}" == "mcp_server" ]]; then
|
||||
echo "DOCKERFILE=projects/mcp_server/Dockerfile" >> $GITHUB_OUTPUT
|
||||
echo "DESCRIPTION=fastgpt-mcp_server-pr image" >> $GITHUB_OUTPUT
|
||||
echo "DOCKER_REPO_TAGGED=${{ secrets.ALI_IMAGE_NAME }}/fastgpt-pr:fatsgpt_mcp_server_${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Build ${{ matrix.image }} image for PR
|
||||
run: |
|
||||
docker buildx build \
|
||||
-f ${{ steps.config.outputs.DOCKERFILE }} \
|
||||
--label "org.opencontainers.image.source=https://github.com/${{ github.repository_owner }}/FastGPT" \
|
||||
--label "org.opencontainers.image.description=${{ steps.config.outputs.DESCRIPTION }}" \
|
||||
--push \
|
||||
--cache-from=type=local,src=/tmp/.buildx-cache \
|
||||
--cache-to=type=local,dest=/tmp/.buildx-cache \
|
||||
-t ${{ steps.config.outputs.DOCKER_REPO_TAGGED }} \
|
||||
.
|
||||
|
||||
- name: '@finleyge/github-tools'
|
||||
uses: FinleyGe/github-tools@0.0.1
|
||||
id: print-image-label
|
||||
if: success()
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
tool: issue-comment
|
||||
title: 'Preview ${{ matrix.image }} Image:'
|
||||
body: |
|
||||
```
|
||||
${{ steps.config.outputs.DOCKER_REPO_TAGGED }}
|
||||
```
|
||||
32
.github/workflows/fastgpt-test.yaml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: 'FastGPT-Test'
|
||||
on:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
# Required to checkout the code
|
||||
contents: read
|
||||
# Required to put a comment into the pull-request
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref }}
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10
|
||||
- name: 'Install Deps'
|
||||
run: pnpm install
|
||||
- name: 'Test'
|
||||
run: pnpm run test
|
||||
- name: 'Report Coverage'
|
||||
# Set if: always() to also generate the report if tests are failing
|
||||
# Only works if you set `reportOnFailure: true` in your vite config as specified above
|
||||
if: always()
|
||||
uses: davelosert/vitest-coverage-report-action@v2
|
||||
34
.github/workflows/helm-release.yaml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
name: Release helm chart
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*.*.*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
helm:
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
attestations: write
|
||||
id-token: write
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-tags: true
|
||||
fetch-depth: 0
|
||||
- name: Set output
|
||||
id: vars
|
||||
run: echo "tag=$(git describe --tags)" >> $GITHUB_OUTPUT
|
||||
- name: Release Helm
|
||||
run: |
|
||||
echo ${{ secrets.GITHUB_TOKEN }} | helm registry login ghcr.io -u ${{ github.repository_owner }} --password-stdin
|
||||
export APP_VERSION=${{ steps.vars.outputs.tag }}
|
||||
export HELM_VERSION=${{ steps.vars.outputs.tag }}
|
||||
export HELM_REPO=ghcr.io/${{ github.repository_owner }}
|
||||
helm dependency update deploy/helm/fastgpt
|
||||
helm package deploy/helm/fastgpt --version ${HELM_VERSION}-helm --app-version ${APP_VERSION} -d bin
|
||||
helm push bin/fastgpt-${HELM_VERSION}-helm.tgz oci://${HELM_REPO}
|
||||
151
.github/workflows/mcp_server-build-image.yml
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
name: Build fastgpt-mcp-server images
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- 'projects/mcp_server/**'
|
||||
tags:
|
||||
- 'v*'
|
||||
jobs:
|
||||
build-fastgpt-mcp_server-images:
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
attestations: write
|
||||
id-token: write
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: amd64
|
||||
- arch: arm64
|
||||
runs-on: ubuntu-24.04-arm
|
||||
runs-on: ${{ matrix.runs-on || 'ubuntu-24.04' }}
|
||||
steps:
|
||||
# install env
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
driver-opts: network=host
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-mcp-server-buildx-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-mcp_server-buildx-
|
||||
|
||||
# login docker
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Login to Ali Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: registry.cn-hangzhou.aliyuncs.com
|
||||
username: ${{ secrets.ALI_HUB_USERNAME }}
|
||||
password: ${{ secrets.ALI_HUB_PASSWORD }}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_NAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
|
||||
- name: Build for ${{ matrix.arch }}
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: projects/mcp_server/Dockerfile
|
||||
platforms: linux/${{ matrix.arch }}
|
||||
labels: |
|
||||
org.opencontainers.image.source=https://github.com/${{ github.repository }}
|
||||
org.opencontainers.image.description=fastgpt-mcp_server image
|
||||
outputs: type=image,"name=ghcr.io/${{ github.repository_owner }}/fastgpt-mcp_server,${{ secrets.ALI_IMAGE_NAME }}/fastgpt-mcp_server,${{ secrets.DOCKER_IMAGE_NAME }}/fastgpt-mcp_server",push-by-digest=true,push=true
|
||||
cache-from: type=local,src=/tmp/.buildx-cache
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache
|
||||
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p ${{ runner.temp }}/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-fastgpt-mcp_server-${{ github.sha }}-${{ matrix.arch }}
|
||||
path: ${{ runner.temp }}/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
release-fastgpt-mcp_server-images:
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
attestations: write
|
||||
id-token: write
|
||||
needs: build-fastgpt-mcp_server-images
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Login to Ali Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: registry.cn-hangzhou.aliyuncs.com
|
||||
username: ${{ secrets.ALI_HUB_USERNAME }}
|
||||
password: ${{ secrets.ALI_HUB_PASSWORD }}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_NAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ${{ runner.temp }}/digests
|
||||
pattern: digests-fastgpt-mcp_server-${{ github.sha }}-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Set image name and tag
|
||||
run: |
|
||||
if [[ "${{ github.ref_name }}" == "main" ]]; then
|
||||
echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV
|
||||
echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV
|
||||
echo "Ali_Tag=${{ secrets.ALI_IMAGE_NAME }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV
|
||||
echo "Ali_Latest=${{ secrets.ALI_IMAGE_NAME }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV
|
||||
echo "Docker_Hub_Tag=${{ secrets.DOCKER_IMAGE_NAME }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV
|
||||
echo "Docker_Hub_Latest=${{ secrets.DOCKER_IMAGE_NAME }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV
|
||||
else
|
||||
echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/fastgpt-mcp_server:${{ github.ref_name }}" >> $GITHUB_ENV
|
||||
echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV
|
||||
echo "Ali_Tag=${{ secrets.ALI_IMAGE_NAME }}/fastgpt-mcp_server:${{ github.ref_name }}" >> $GITHUB_ENV
|
||||
echo "Ali_Latest=${{ secrets.ALI_IMAGE_NAME }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV
|
||||
echo "Docker_Hub_Tag=${{ secrets.DOCKER_IMAGE_NAME }}/fastgpt-mcp_server:${{ github.ref_name }}" >> $GITHUB_ENV
|
||||
echo "Docker_Hub_Latest=${{ secrets.DOCKER_IMAGE_NAME }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: ${{ runner.temp }}/digests
|
||||
run: |
|
||||
TAGS="$(echo -e "${Git_Tag}\n${Git_Latest}\n${Ali_Tag}\n${Ali_Latest}\n${Docker_Hub_Tag}\n${Docker_Hub_Latest}")"
|
||||
for TAG in $TAGS; do
|
||||
docker buildx imagetools create -t $TAG \
|
||||
$(printf 'ghcr.io/${{ github.repository_owner }}/fastgpt-mcp_server@sha256:%s ' *)
|
||||
sleep 5
|
||||
done
|
||||
151
.github/workflows/sandbox-build-image.yml
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
name: Build fastgpt-sandbox images
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- 'projects/sandbox/**'
|
||||
tags:
|
||||
- 'v*'
|
||||
jobs:
|
||||
build-fastgpt-sandbox-images:
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
attestations: write
|
||||
id-token: write
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: amd64
|
||||
- arch: arm64
|
||||
runs-on: ubuntu-24.04-arm
|
||||
runs-on: ${{ matrix.runs-on || 'ubuntu-24.04' }}
|
||||
steps:
|
||||
# install env
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
driver-opts: network=host
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-sandbox-buildx-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-sandbox-buildx-
|
||||
|
||||
# login docker
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Login to Ali Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: registry.cn-hangzhou.aliyuncs.com
|
||||
username: ${{ secrets.ALI_HUB_USERNAME }}
|
||||
password: ${{ secrets.ALI_HUB_PASSWORD }}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_NAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
|
||||
- name: Build for ${{ matrix.arch }}
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: projects/sandbox/Dockerfile
|
||||
platforms: linux/${{ matrix.arch }}
|
||||
labels: |
|
||||
org.opencontainers.image.source=https://github.com/${{ github.repository }}
|
||||
org.opencontainers.image.description=fastgpt-sandbox image
|
||||
outputs: type=image,"name=ghcr.io/${{ github.repository_owner }}/fastgpt-sandbox,${{ secrets.ALI_IMAGE_NAME }}/fastgpt-sandbox,${{ secrets.DOCKER_IMAGE_NAME }}/fastgpt-sandbox",push-by-digest=true,push=true
|
||||
cache-from: type=local,src=/tmp/.buildx-cache
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache
|
||||
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p ${{ runner.temp }}/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-fastgpt-sandbox-${{ github.sha }}-${{ matrix.arch }}
|
||||
path: ${{ runner.temp }}/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
release-fastgpt-sandbox-images:
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
attestations: write
|
||||
id-token: write
|
||||
needs: build-fastgpt-sandbox-images
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Login to Ali Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: registry.cn-hangzhou.aliyuncs.com
|
||||
username: ${{ secrets.ALI_HUB_USERNAME }}
|
||||
password: ${{ secrets.ALI_HUB_PASSWORD }}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_NAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ${{ runner.temp }}/digests
|
||||
pattern: digests-fastgpt-sandbox-${{ github.sha }}-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Set image name and tag
|
||||
run: |
|
||||
if [[ "${{ github.ref_name }}" == "main" ]]; then
|
||||
echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/fastgpt-sandbox:latest" >> $GITHUB_ENV
|
||||
echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/fastgpt-sandbox:latest" >> $GITHUB_ENV
|
||||
echo "Ali_Tag=${{ secrets.ALI_IMAGE_NAME }}/fastgpt-sandbox:latest" >> $GITHUB_ENV
|
||||
echo "Ali_Latest=${{ secrets.ALI_IMAGE_NAME }}/fastgpt-sandbox:latest" >> $GITHUB_ENV
|
||||
echo "Docker_Hub_Tag=${{ secrets.DOCKER_IMAGE_NAME }}/fastgpt-sandbox:latest" >> $GITHUB_ENV
|
||||
echo "Docker_Hub_Latest=${{ secrets.DOCKER_IMAGE_NAME }}/fastgpt-sandbox:latest" >> $GITHUB_ENV
|
||||
else
|
||||
echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/fastgpt-sandbox:${{ github.ref_name }}" >> $GITHUB_ENV
|
||||
echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/fastgpt-sandbox:latest" >> $GITHUB_ENV
|
||||
echo "Ali_Tag=${{ secrets.ALI_IMAGE_NAME }}/fastgpt-sandbox:${{ github.ref_name }}" >> $GITHUB_ENV
|
||||
echo "Ali_Latest=${{ secrets.ALI_IMAGE_NAME }}/fastgpt-sandbox:latest" >> $GITHUB_ENV
|
||||
echo "Docker_Hub_Tag=${{ secrets.DOCKER_IMAGE_NAME }}/fastgpt-sandbox:${{ github.ref_name }}" >> $GITHUB_ENV
|
||||
echo "Docker_Hub_Latest=${{ secrets.DOCKER_IMAGE_NAME }}/fastgpt-sandbox:latest" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: ${{ runner.temp }}/digests
|
||||
run: |
|
||||
TAGS="$(echo -e "${Git_Tag}\n${Git_Latest}\n${Ali_Tag}\n${Ali_Latest}\n${Docker_Hub_Tag}\n${Docker_Hub_Latest}")"
|
||||
for TAG in $TAGS; do
|
||||
docker buildx imagetools create -t $TAG \
|
||||
$(printf 'ghcr.io/${{ github.repository_owner }}/fastgpt-sandbox@sha256:%s ' *)
|
||||
sleep 5
|
||||
done
|
||||
40
.gitignore
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
# dependencies
|
||||
node_modules/
|
||||
# next.js
|
||||
.next/
|
||||
out/
|
||||
# production
|
||||
build/
|
||||
.astro/
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
platform.json
|
||||
testApi/
|
||||
local/
|
||||
dist/
|
||||
|
||||
.idea/
|
||||
files/helm/fastgpt/fastgpt-0.1.0.tgz
|
||||
files/helm/fastgpt/charts/*.tgz
|
||||
|
||||
tmp/
|
||||
coverage
|
||||
document/.source
|
||||
8
.husky/pre-commit
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
if command -v pnpm >/dev/null 2>&1; then
|
||||
pnpm lint-staged
|
||||
elif command -v npx >/dev/null 2>&1; then
|
||||
npx lint-staged
|
||||
fi
|
||||
9
.imgbotconfig
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"schedule": "daily", // daily|weekly|monthly
|
||||
"ignoredFiles": [
|
||||
"*.svg",
|
||||
"packages/*",
|
||||
"projects/*",
|
||||
],
|
||||
"minKBReduced": 200, // delay new prs until size reduction meets this threshold (default to 10)
|
||||
}
|
||||
3
.npmrc
Normal file
@@ -0,0 +1,3 @@
|
||||
public-hoist-pattern[]=*tiktoken*
|
||||
public-hoist-pattern[]=*@zilliz/milvus2-sdk-node*
|
||||
registry=https://registry.npmjs.org/
|
||||
11
.prettierignore
Normal file
@@ -0,0 +1,11 @@
|
||||
dist
|
||||
.vscode
|
||||
**/.DS_Store
|
||||
node_modules
|
||||
document/
|
||||
*.md
|
||||
*.mdx
|
||||
|
||||
pnpm-lock.yaml
|
||||
cl100l_base.ts
|
||||
dict.json
|
||||
20
.prettierrc.js
Normal file
@@ -0,0 +1,20 @@
|
||||
module.exports = {
|
||||
printWidth: 100,
|
||||
tabWidth: 2,
|
||||
useTabs: false,
|
||||
semi: true,
|
||||
singleQuote: true,
|
||||
quoteProps: 'as-needed',
|
||||
jsxSingleQuote: false,
|
||||
trailingComma: 'none',
|
||||
bracketSpacing: true,
|
||||
jsxBracketSameLine: false,
|
||||
arrowParens: 'always',
|
||||
rangeStart: 0,
|
||||
rangeEnd: Infinity,
|
||||
requirePragma: false,
|
||||
insertPragma: false,
|
||||
proseWrap: 'preserve',
|
||||
htmlWhitespaceSensitivity: 'css',
|
||||
endOfLine: 'lf'
|
||||
};
|
||||
36
.vscode/i18n-ally-custom-framework.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
# .vscode/i18n-ally-custom-framework.yml
|
||||
|
||||
# An array of strings which contain Language Ids defined by VS Code
|
||||
# You can check available language ids here: https://code.visualstudio.com/docs/languages/identifiers
|
||||
languageIds:
|
||||
- javascript
|
||||
- typescript
|
||||
- javascriptreact
|
||||
- typescriptreact
|
||||
|
||||
# An array of RegExes to find the key usage. **The key should be captured in the first match group**.
|
||||
# You should unescape RegEx strings in order to fit in the YAML file
|
||||
# To help with this, you can use https://www.freeformatter.com/json-escape.html
|
||||
usageMatchRegex:
|
||||
# The following example shows how to detect `t("your.i18n.keys")`
|
||||
# the `{key}` will be placed by a proper keypath matching regex,
|
||||
# you can ignore it and use your own matching rules as well
|
||||
- "[^\\w\\d]t\\(['\"`]({key})['\"`]"
|
||||
- "[^\\w\\d]i18nT\\(['\"`]({key})['\"`]"
|
||||
|
||||
# A RegEx to set a custom scope range. This scope will be used as a prefix when detecting keys
|
||||
# and works like how the i18next framework identifies the namespace scope from the
|
||||
# useTranslation() hook.
|
||||
# You should unescape RegEx strings in order to fit in the YAML file
|
||||
# To help with this, you can use https://www.freeformatter.com/json-escape.html
|
||||
scopeRangeRegex: "([^:]+):"
|
||||
|
||||
# An array of strings containing refactor templates.
|
||||
# The "$1" will be replaced by the keypath specified.
|
||||
# Optional: uncomment the following two lines to use
|
||||
|
||||
# refactorTemplates:
|
||||
# - i18n.get("$1")
|
||||
|
||||
# If set to true, only enables this custom framework (will disable all built-in frameworks)
|
||||
monopoly: false
|
||||
39
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Next.js: debug server-side",
|
||||
"type": "node-terminal",
|
||||
"request": "launch",
|
||||
"command": "pnpm run dev",
|
||||
"cwd": "${workspaceFolder}/projects/app"
|
||||
},
|
||||
{
|
||||
"name": "Next.js: debug client-side",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"url": "http://localhost:3000"
|
||||
},
|
||||
{
|
||||
"name": "Next.js: debug client-side (Edge)",
|
||||
"type": "msedge",
|
||||
"request": "launch",
|
||||
"url": "http://localhost:3000"
|
||||
},
|
||||
{
|
||||
"name": "Next.js: debug full stack",
|
||||
"type": "node-terminal",
|
||||
"request": "launch",
|
||||
"command": "pnpm run dev",
|
||||
"cwd": "${workspaceFolder}/projects/app",
|
||||
"skipFiles": ["<node_internals>/**"],
|
||||
"serverReadyAction": {
|
||||
"action": "debugWithEdge",
|
||||
"killOnServerStop": true,
|
||||
"pattern": "- Local:.+(https?://.+)",
|
||||
"uriFormat": "%s",
|
||||
"webRoot": "${workspaceFolder}/projects/app"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
68
.vscode/nextapi.code-snippets
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
{
|
||||
// Place your FastGPT 工作区 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
|
||||
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
|
||||
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
|
||||
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
|
||||
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
|
||||
// Placeholders with the same ids are connected.
|
||||
// Example:
|
||||
"Next api template": {
|
||||
"scope": "javascript,typescript",
|
||||
"prefix": "nextapi",
|
||||
"body": [
|
||||
"import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';",
|
||||
"import { NextAPI } from '@/service/middleware/entry';",
|
||||
"",
|
||||
"export type ${TM_FILENAME_BASE}Query = {};",
|
||||
"",
|
||||
"export type ${TM_FILENAME_BASE}Body = {};",
|
||||
"",
|
||||
"export type ${TM_FILENAME_BASE}Response = {};",
|
||||
"",
|
||||
"async function handler(",
|
||||
" req: ApiRequestProps<${TM_FILENAME_BASE}Body, ${TM_FILENAME_BASE}Query>,",
|
||||
" res: ApiResponseType<any>",
|
||||
"): Promise<${TM_FILENAME_BASE}Response> {",
|
||||
" $1",
|
||||
" return {}",
|
||||
"}",
|
||||
"",
|
||||
"export default NextAPI(handler);"
|
||||
],
|
||||
"description": "FastGPT Next API template"
|
||||
},
|
||||
"use context template": {
|
||||
"scope": "typescriptreact",
|
||||
"prefix": "context",
|
||||
"body": [
|
||||
"import React, { ReactNode } from 'react';",
|
||||
"import { createContext } from 'use-context-selector';",
|
||||
"",
|
||||
"type ContextType = {$1};",
|
||||
"",
|
||||
"export const Context = createContext<ContextType>({});",
|
||||
"",
|
||||
"const ContextProvider = ({ children }: { children: ReactNode }) => {",
|
||||
" const contextValue: ContextType = {};",
|
||||
" return <Context.Provider value={contextValue}>{children}</Context.Provider>;",
|
||||
"};",
|
||||
"",
|
||||
"export default ContextProvider"
|
||||
],
|
||||
"description": "FastGPT usecontext template"
|
||||
},
|
||||
|
||||
"Vitest test case template": {
|
||||
"scope": "typescript",
|
||||
"prefix": "template_test",
|
||||
"body": [
|
||||
"import { describe, it, expect } from 'vitest';",
|
||||
"",
|
||||
"describe('authType2UsageSource', () => {",
|
||||
" it('Test description', () => {",
|
||||
" expect().toBe();",
|
||||
" });",
|
||||
"});"
|
||||
]
|
||||
}
|
||||
}
|
||||
37
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"editor.mouseWheelZoom": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"prettier.prettierPath": "node_modules/prettier",
|
||||
"typescript.preferences.includePackageJsonAutoImports": "on",
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"i18n-ally.localesPaths": [
|
||||
"packages/web/i18n",
|
||||
],
|
||||
"i18n-ally.enabledParsers": [
|
||||
"json",
|
||||
"yaml",
|
||||
"js",
|
||||
"ts"
|
||||
],
|
||||
"i18n-ally.keystyle": "flat",
|
||||
"i18n-ally.sortKeys": true,
|
||||
"i18n-ally.keepFulfilled": false,
|
||||
"i18n-ally.sourceLanguage": "zh-CN", // 根据此语言文件翻译其他语言文件的变量和内容
|
||||
"i18n-ally.displayLanguage": "zh-CN", // 显示语言
|
||||
"i18n-ally.namespace": true,
|
||||
"i18n-ally.pathMatcher": "{locale}/{namespaces}.json",
|
||||
"i18n-ally.extract.targetPickingStrategy": "most-similar-by-key",
|
||||
"i18n-ally.translate.engines": ["deepl","google"],
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"mdx.server.enable": true,
|
||||
"markdown.copyFiles.overwriteBehavior": "nameIncrementally",
|
||||
"markdown.copyFiles.destination": {
|
||||
"/document/content/docs/**/*": "${documentWorkspaceFolder}/document/public/imgs/"
|
||||
},
|
||||
"files.associations": {
|
||||
"*.mdx": "markdown"
|
||||
}
|
||||
}
|
||||
116
CLAUDE.md
Normal file
@@ -0,0 +1,116 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
FastGPT is an AI Agent construction platform providing out-of-the-box data processing, model invocation capabilities, and visual workflow orchestration through Flow. This is a full-stack TypeScript application built on NextJS with MongoDB/PostgreSQL backends.
|
||||
|
||||
**Tech Stack**: NextJS + TypeScript + ChakraUI + MongoDB + PostgreSQL (PG Vector)/Milvus
|
||||
|
||||
## Architecture
|
||||
|
||||
This is a monorepo using pnpm workspaces with the following key structure:
|
||||
|
||||
### Packages (Library Code)
|
||||
- `packages/global/` - Shared types, constants, utilities used across all projects
|
||||
- `packages/service/` - Backend services, database schemas, API controllers, workflow engine
|
||||
- `packages/web/` - Shared frontend components, hooks, styles, i18n
|
||||
- `packages/templates/` - Application templates for the template market
|
||||
|
||||
### Projects (Applications)
|
||||
- `projects/app/` - Main NextJS web application (frontend + API routes)
|
||||
- `projects/sandbox/` - NestJS code execution sandbox service
|
||||
- `projects/mcp_server/` - Model Context Protocol server implementation
|
||||
|
||||
### Key Directories
|
||||
- `document/` - Documentation site (NextJS app with content)
|
||||
- `plugins/` - External plugins (models, crawlers, etc.)
|
||||
- `deploy/` - Docker and Helm deployment configurations
|
||||
- `test/` - Centralized test files and utilities
|
||||
|
||||
## Development Commands
|
||||
|
||||
### Main Commands (run from project root)
|
||||
- `pnpm dev` - Start development for all projects (uses package.json workspace scripts)
|
||||
- `pnpm build` - Build all projects
|
||||
- `pnpm test` - Run tests using Vitest
|
||||
- `pnpm test:workflow` - Run workflow-specific tests
|
||||
- `pnpm lint` - Run ESLint across all TypeScript files with auto-fix
|
||||
- `pnpm format-code` - Format code using Prettier
|
||||
|
||||
### Project-Specific Commands
|
||||
**Main App (projects/app/)**:
|
||||
- `cd projects/app && pnpm dev` - Start NextJS dev server
|
||||
- `cd projects/app && pnpm build` - Build NextJS app
|
||||
- `cd projects/app && pnpm start` - Start production server
|
||||
|
||||
**Sandbox (projects/sandbox/)**:
|
||||
- `cd projects/sandbox && pnpm dev` - Start NestJS dev server with watch mode
|
||||
- `cd projects/sandbox && pnpm build` - Build NestJS app
|
||||
- `cd projects/sandbox && pnpm test` - Run Jest tests
|
||||
|
||||
**MCP Server (projects/mcp_server/)**:
|
||||
- `cd projects/mcp_server && bun dev` - Start with Bun in watch mode
|
||||
- `cd projects/mcp_server && bun build` - Build MCP server
|
||||
- `cd projects/mcp_server && bun start` - Start MCP server
|
||||
|
||||
### Utility Commands
|
||||
- `pnpm create:i18n` - Generate i18n translation files
|
||||
- `pnpm api:gen` - Generate OpenAPI documentation
|
||||
- `pnpm initIcon` - Initialize icon assets
|
||||
- `pnpm gen:theme-typings` - Generate Chakra UI theme typings
|
||||
|
||||
## Testing
|
||||
|
||||
The project uses Vitest for testing with coverage reporting. Key test commands:
|
||||
- `pnpm test` - Run all tests
|
||||
- `pnpm test:workflow` - Run workflow tests specifically
|
||||
- Test files are located in `test/` directory and `projects/app/test/`
|
||||
- Coverage reports are generated in `coverage/` directory
|
||||
|
||||
## Code Organization Patterns
|
||||
|
||||
### Monorepo Structure
|
||||
- Shared code lives in `packages/` and is imported using workspace references
|
||||
- Each project in `projects/` is a standalone application
|
||||
- Use `@fastgpt/global`, `@fastgpt/service`, `@fastgpt/web` imports for shared packages
|
||||
|
||||
### API Structure
|
||||
- NextJS API routes in `projects/app/src/pages/api/`
|
||||
- Core business logic in `packages/service/core/`
|
||||
- Database schemas in `packages/service/` with MongoDB/Mongoose
|
||||
|
||||
### Frontend Architecture
|
||||
- React components in `projects/app/src/components/` and `packages/web/components/`
|
||||
- Chakra UI for styling with custom theme in `packages/web/styles/theme.ts`
|
||||
- i18n support with files in `packages/web/i18n/`
|
||||
- State management using React Context and Zustand
|
||||
|
||||
### Workflow System
|
||||
- Visual workflow editor using ReactFlow
|
||||
- Workflow engine in `packages/service/core/workflow/`
|
||||
- Node definitions in `packages/global/core/workflow/template/`
|
||||
- Dispatch system for executing workflow nodes
|
||||
|
||||
## Development Notes
|
||||
|
||||
- **Package Manager**: Uses pnpm with workspace configuration
|
||||
- **Node Version**: Requires Node.js >=18.16.0, pnpm >=9.0.0
|
||||
- **Database**: Supports MongoDB, PostgreSQL with pgvector, or Milvus for vector storage
|
||||
- **AI Integration**: Supports multiple AI providers through unified interface
|
||||
- **Internationalization**: Full i18n support for Chinese, English, and Japanese
|
||||
|
||||
## Key File Patterns
|
||||
|
||||
- `.ts` and `.tsx` files use TypeScript throughout
|
||||
- Database schemas use Mongoose with TypeScript
|
||||
- API routes follow NextJS conventions
|
||||
- Component files use React functional components with hooks
|
||||
- Shared types defined in `packages/global/` with `.d.ts` files
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
- Configuration files in `projects/app/data/config.json`
|
||||
- Environment-specific configs supported
|
||||
- Model configurations in `packages/service/core/ai/config/`
|
||||
35
LICENSE
Normal file
@@ -0,0 +1,35 @@
|
||||
# FastGPT Open Source License
|
||||
|
||||
The FastGPT is licensed under the Apache License 2.0, with the following additional conditions:
|
||||
|
||||
1. FastGPT is permitted to be used for commercialization. You can use FastGPT as a "backend-as-a-service" for your other applications, or delivering it to enterprises as an application development platform. However, when the following conditions are met, you must contact the producer to obtain a commercial license:
|
||||
|
||||
a. Multi-tenant SaaS service: Unless explicitly authorized by FastGPT in writing, you may not use the FastGPT.AI source code to operate a multi-tenant SaaS service that is similar to the FastGPT.
|
||||
b. LOGO and copyright information: In the process of using FastGPT, you may not remove or modify the LOGO or copyright information in the FastGPT console.
|
||||
|
||||
Please contact dennis@sealos.io by email to inquire about licensing matters.
|
||||
|
||||
2. As a contributor, you should agree that your contributed code:
|
||||
|
||||
a. The producer can adjust the open-source agreement to be more strict or relaxed.
|
||||
b. Can be used for commercial purposes, such as FastGPT's cloud business.
|
||||
|
||||
Apart from this, all other rights and restrictions follow the Apache License 2.0. If you need more detailed information, you can refer to the full version of Apache License 2.0.
|
||||
|
||||
The interactive design of this product is protected by appearance patent.
|
||||
|
||||
© 2023 Sealos.
|
||||
|
||||
---
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
25
Makefile
Normal file
@@ -0,0 +1,25 @@
|
||||
# 定义默认变量
|
||||
proxy=null
|
||||
image=null
|
||||
|
||||
# 定义目标
|
||||
.PHONY: build
|
||||
|
||||
# 检查 target 是否定义
|
||||
ifndef name
|
||||
$(error name is not defined)
|
||||
endif
|
||||
|
||||
filePath=./projects/$(name)/Dockerfile
|
||||
|
||||
dev:
|
||||
pnpm --prefix ./projects/$(name) dev
|
||||
|
||||
build:
|
||||
ifeq ($(proxy), taobao)
|
||||
docker build -f $(filePath) -t $(image) . --build-arg proxy=taobao
|
||||
else ifeq ($(proxy), clash)
|
||||
docker build -f $(filePath) -t $(image) . --network host --build-arg HTTP_PROXY=http://127.0.0.1:7890 --build-arg HTTPS_PROXY=http://127.0.0.1:7890
|
||||
else
|
||||
docker build -f $(filePath) -t $(image) .
|
||||
endif
|
||||
218
README.md
Normal file
@@ -0,0 +1,218 @@
|
||||
<div align="center">
|
||||
|
||||
<a href="https://fastgpt.io/"><img src="/.github/imgs/logo.svg" width="120" height="120" alt="fastgpt logo"></a>
|
||||
|
||||
# FastGPT
|
||||
|
||||
<p align="center">
|
||||
<a href="./README_en.md">English</a> |
|
||||
<a href="./README.md">简体中文</a> |
|
||||
<a href="./README_ja.md">日语</a>
|
||||
</p>
|
||||
|
||||
FastGPT 是一个 AI Agent 构建平台,提供开箱即用的数据处理、模型调用等能力,同时可以通过 Flow 可视化进行工作流编排,从而实现复杂的应用场景!
|
||||
|
||||
</div>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://fastgpt.io/">
|
||||
<img height="21" src="https://img.shields.io/badge/在线使用-d4eaf7?style=flat-square&logo=spoj&logoColor=7d09f1" alt="cloud">
|
||||
</a>
|
||||
<a href="https://doc.fastgpt.io/docs/introduction">
|
||||
<img height="21" src="https://img.shields.io/badge/相关文档-7d09f1?style=flat-square" alt="document">
|
||||
</a>
|
||||
<a href="https://doc.fastgpt.io/docs/introduction/development/intro">
|
||||
<img height="21" src="https://img.shields.io/badge/本地开发-%23d4eaf7?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>
|
||||
</p>
|
||||
|
||||
https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409bd33f6d4
|
||||
|
||||
## 🛸 在线使用
|
||||
|
||||
- 🌍 国际版:[fastgpt.io](https://fastgpt.io/)
|
||||
|
||||
| | |
|
||||
| ---------------------------------- | ---------------------------------- |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|
||||
<a href="#readme">
|
||||
<img src="https://img.shields.io/badge/-返回顶部-7d09f1.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
## 💡 RoadMap
|
||||
|
||||
`1` 应用编排能力
|
||||
- [x] 对话工作流、插件工作流,包含基础的 RPA 节点。
|
||||
- [x] 用户交互
|
||||
- [x] 双向 MCP
|
||||
- [ ] Agent 模式
|
||||
- [ ] AI 生成工作流
|
||||
|
||||
`2` 应用调试能力
|
||||
- [x] 知识库单点搜索测试
|
||||
- [x] 对话时反馈引用并可修改与删除
|
||||
- [x] 完整调用链路日志
|
||||
- [ ] 应用评测
|
||||
- [ ] 高级编排 DeBug 调试模式
|
||||
- [ ] 应用节点日志
|
||||
|
||||
`3` 知识库能力
|
||||
- [x] 多库复用,混用
|
||||
- [x] chunk 记录修改和删除
|
||||
- [x] 支持手动输入,直接分段,QA 拆分导入
|
||||
- [x] 支持 txt,md,html,pdf,docx,pptx,csv,xlsx (有需要更多可 PR file loader),支持 url 读取、CSV 批量导入
|
||||
- [x] 混合检索 & 重排
|
||||
- [x] API 知识库
|
||||
- [ ] RAG 模块热插拔
|
||||
|
||||
`4` OpenAPI 接口
|
||||
- [x] completions 接口 (chat 模式对齐 GPT 接口)
|
||||
- [x] 知识库 CRUD
|
||||
- [x] 对话 CRUD
|
||||
- [ ] 自动化 OpenAPI 接口
|
||||
|
||||
`5` 运营能力
|
||||
- [x] 免登录分享窗口
|
||||
- [x] Iframe 一键嵌入
|
||||
- [x] 统一查阅对话记录,并对数据进行标注
|
||||
- [x] 应用运营日志
|
||||
|
||||
`6` 其他
|
||||
- [x] 可视化模型配置。
|
||||
- [x] 支持语音输入和输出 (可配置语音输入语音回答)
|
||||
- [x] 模糊输入提示
|
||||
- [x] 模板市场
|
||||
|
||||
<a href="#readme">
|
||||
<img src="https://img.shields.io/badge/-返回顶部-7d09f1.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
## 👨💻 开发
|
||||
|
||||
项目技术栈:NextJs + TS + ChakraUI + MongoDB + PostgreSQL (PG Vector 插件)/Milvus
|
||||
|
||||
- **⚡ 快速部署**
|
||||
|
||||
> 使用 [Sealos](https://sealos.io) 服务,无需采购服务器、无需域名,支持高并发 & 动态伸缩,并且数据库应用采用 kubeblocks 的数据库,在 IO 性能方面,远超于简单的 Docker 容器部署。
|
||||
|
||||
[点击查看 Sealos 一键部署 FastGPT 教程](https://doc.fastgpt.io/docs/introduction/development/sealos/)
|
||||
|
||||
* [快速开始本地开发](https://doc.fastgpt.io/docs/introduction/development/intro/)
|
||||
* [部署 FastGPT](https://doc.fastgpt.io/docs/introduction/development/sealos/)
|
||||
* [系统配置文件说明](https://doc.fastgpt.io/docs/introduction/development/configuration/)
|
||||
* [多模型配置方案](https://doc.fastgpt.io/docs/introduction/development/modelConfig/one-api/)
|
||||
* [版本更新/升级介绍](https://doc.fastgpt.io/docs/introduction/development/upgrading/index)
|
||||
* [OpenAPI API 文档](https://doc.fastgpt.io/docs/introduction/development/openapi/)
|
||||
* [知识库结构详解](https://doc.fastgpt.io/docs/introduction/guide/knowledge_base/RAG/)
|
||||
|
||||
<a href="#readme">
|
||||
<img src="https://img.shields.io/badge/-返回顶部-7d09f1.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
## 🏘️ 加入我们
|
||||
|
||||
我们正在寻找志同道合的小伙伴,加速 FastGPT 的发展。你可以通过 [FastGPT 2025 招聘](https://fael3z0zfze.feishu.cn/wiki/P7FOwEmPziVcaYkvVaacnVX1nvg)了解 FastGPT 的招聘信息。
|
||||
|
||||
## 💪 相关项目
|
||||
|
||||
- [FastGPT-plugin](https://github.com/labring/fastgpt-plugin)
|
||||
- [Laf:3 分钟快速接入三方应用](https://github.com/labring/laf)
|
||||
- [Sealos:快速部署集群应用](https://github.com/labring/sealos)
|
||||
- [One API:多模型管理,支持 Azure、文心一言等](https://github.com/songquanpeng/one-api)
|
||||
|
||||
<a href="#readme">
|
||||
<img src="https://img.shields.io/badge/-返回顶部-7d09f1.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
## 🌿 第三方生态
|
||||
- [PPIO 派欧云:一键调用高性价比的开源模型 API 和 GPU 容器](https://ppinfra.com/user/register?invited_by=VITYVU&utm_source=github_fastgpt)
|
||||
- [AI Proxy:国内模型聚合服务](https://sealos.run/aiproxy/?k=fastgpt-github/)
|
||||
- [SiliconCloud (硅基流动) —— 开源模型在线体验平台](https://cloud.siliconflow.cn/i/TR9Ym0c4)
|
||||
|
||||
<a href="#readme">
|
||||
<img src="https://img.shields.io/badge/-返回顶部-7d09f1.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
## 🏘️ 社区交流群
|
||||
|
||||
扫码加入飞书话题群:
|
||||
|
||||

|
||||
|
||||
<a href="#readme">
|
||||
<img src="https://img.shields.io/badge/-返回顶部-7d09f1.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
## 👀 其他
|
||||
|
||||
- [保姆级 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)
|
||||
|
||||
<a href="#readme">
|
||||
<img src="https://img.shields.io/badge/-返回顶部-7d09f1.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
## 🤝 参与贡献
|
||||
|
||||
我们非常欢迎各种形式的贡献。如果你对贡献代码感兴趣,可以查看我们的 GitHub [Issues](https://github.com/labring/FastGPT/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc),大展身手,向我们展示你的奇思妙想。
|
||||
|
||||
<a href="https://github.com/labring/FastGPT/graphs/contributors" target="_blank">
|
||||
<table>
|
||||
<tr>
|
||||
<th colspan="2">
|
||||
<br><img src="https://contrib.rocks/image?repo=labring/FastGPT"><br><br>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=active&period=past_28_days&owner_id=102226726&repo_ids=605673387&image_size=2x3&color_scheme=dark">
|
||||
<img alt="Active participants of labring - past 28 days" src="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=active&period=past_28_days&owner_id=102226726&repo_ids=605673387&image_size=2x3&color_scheme=light">
|
||||
</picture>****
|
||||
</td>
|
||||
<td rowspan="2">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-participants-growth/thumbnail.png?activity=new&period=past_28_days&owner_id=102226726&repo_ids=605673387&image_size=4x7&color_scheme=dark">
|
||||
<img alt="New trends of labring" src="https://next.ossinsight.io/widgets/official/compose-org-participants-growth/thumbnail.png?activity=new&period=past_28_days&owner_id=102226726&repo_ids=605673387&image_size=4x7&color_scheme=light">
|
||||
</picture>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=new&period=past_28_days&owner_id=102226726&repo_ids=605673387&image_size=2x3&color_scheme=dark">
|
||||
<img alt="New participants of labring - past 28 days" src="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=new&period=past_28_days&owner_id=102226726&repo_ids=605673387&image_size=2x3&color_scheme=light">
|
||||
</picture>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</a>
|
||||
|
||||
## 🌟 Star History
|
||||
|
||||
<a href="https://github.com/labring/FastGPT/stargazers" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=labring/FastGPT&type=Date&theme=dark" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=labring/FastGPT&type=Date" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=labring/FastGPT&type=Date" />
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
<a href="#readme">
|
||||
<img src="https://img.shields.io/badge/-返回顶部-7d09f1.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
## 使用协议
|
||||
|
||||
本仓库遵循 [FastGPT Open Source License](./LICENSE) 开源协议。
|
||||
|
||||
1. 允许作为后台服务直接商用,但不允许提供 SaaS 服务。
|
||||
2. 未经商业授权,任何形式的商用服务均需保留相关版权信息。
|
||||
3. 完整请查看 [FastGPT Open Source License](./LICENSE)
|
||||
4. 联系方式:Dennis@sealos.io,[点击查看商业版定价策略](https://doc.fastgpt.io/docs/introduction/commercial/)
|
||||
192
README_en.md
Normal file
@@ -0,0 +1,192 @@
|
||||
<div align="center">
|
||||
|
||||
<a href="https://fastgpt.io/"><img src="/.github/imgs/logo.svg" width="120" height="120" alt="fastgpt logo"></a>
|
||||
|
||||
# FastGPT
|
||||
|
||||

|
||||
|
||||
<p align="center">
|
||||
<a href="./README_en.md">English</a> |
|
||||
<a href="./README.md">简体中文</a> |
|
||||
<a href="./README_ja.md">日语</a>
|
||||
</p>
|
||||
|
||||
FastGPT is a knowledge-based platform built on the LLMs, offers a comprehensive suite of out-of-the-box capabilities such as data processing, RAG retrieval, and visual AI workflow orchestration, letting you easily develop and deploy complex question-answering systems without the need for extensive setup or configuration.
|
||||
|
||||
[](https://github.com/labring/FastGPT/stargazers)
|
||||
[](https://github.com/labring/FastGPT/pulls)
|
||||
[](https://github.com/labring/FastGPT/pulls)
|
||||
[](https://github.com/labring/FastGPT/blob/main/LICENSE)
|
||||
[](https://doc.fastgpt.io/docs/introduction)
|
||||
[](https://doc.fastgpt.io/docs/introduction/development/intro)
|
||||
[](https://fastgpt.io/)
|
||||
|
||||
[](https://discord.gg/mp68xkZn2Q)
|
||||
[](https://oss.laf.run/otnvvf-imgs/feishu3.png)
|
||||
|
||||
</div>
|
||||
|
||||
## 🎥 Comprehensive Feature Demonstration
|
||||
|
||||
https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409bd33f6d4
|
||||
|
||||
## 🛸 Online Use
|
||||
|
||||
Website: [fastgpt.io](https://fastgpt.io/)
|
||||
|
||||
| | |
|
||||
| ---------------------------------- | ---------------------------------- |
|
||||
| Conversational AI Setup | Workflow Automation |
|
||||
|  |  |
|
||||
| Knowledge Base Setup | Integration Process |
|
||||
|  |  |
|
||||
|
||||
<a href="#FastGPT">
|
||||
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
## 💡 Features
|
||||
|
||||
| **Features** | **Details** |
|
||||
|--------------------------------------------|---------------------------------------------------|
|
||||
| **Application Orchestration Features** | ✅ Offers a straightforward mode, eliminating the need for complex orchestration <br> ✅ Provides clear next-step instructions in dialogues <br> ✅ Facilitates workflow orchestration <br> ✅ Tracks references in source files <br> ✅ Encapsulates modules for enhanced reuse at multiple levels <br> ✅ Combines search and reordering functions <br> 🔜 Includes a tool module <br> 🔜 Integrates [Laf](https://github.com/labring/laf) for online HTTP module creation <br> 🔜 Plugin encapsulation capabilities |
|
||||
| **Knowledge Base Features** | ✅ Allows for the mixed use of multiple databases <br> ✅ Keeps track of modifications and deletions in data chunks <br> ✅ Enables specific vector models for each knowledge base <br> ✅ Stores original source files <br> ✅ Supports direct input and segment-based QA import <br> ✅ Compatible with a variety of file formats: pdf, docx, txt, html, md, csv <br> ✅ Facilitates URL reading and bulk CSV importing <br> 🔜 Supports PPT and Excel file import <br> 🔜 Features a file reader <br> 🔜 Offers diverse data preprocessing options |
|
||||
| **Application Debugging Features** | ✅ Enables targeted search testing within the knowledge base <br> ✅ Allows feedback, editing, and deletion during conversations <br> ✅ Presents the full context of interactions <br> ✅ Displays all intermediate values within modules <br> 🔜 Advanced Debug mode for orchestration |
|
||||
| **OpenAPI Interface** | ✅ The completions interface (aligned with GPT's chat mode interface) <br> ✅ CRUD operations for the knowledge base <br> 🔜 CRUD operations for conversation |
|
||||
| **Operational Features** | ✅ Share without requiring login <br> ✅ Easy embedding with Iframe <br> ✅ Customizable chat window embedding with features like default open, drag-and-drop <br> ✅ Centralizes conversation records for review and annotation |
|
||||
|
||||
|
||||
<a href="#FastGPT">
|
||||
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
## 👨💻 Development
|
||||
|
||||
Project tech stack: NextJs + TS + ChakraUI + MongoDB + PostgreSQL (PG Vector plug-in)/Milvus
|
||||
|
||||
- **⚡ Fast Deployment**
|
||||
|
||||
> When using [Sealos](https://sealos.io) services, there is no need to purchase servers or domain names. It supports high concurrency and dynamic scaling, and the database application uses the kubeblocks database, which far exceeds the simple Docker container deployment in terms of IO performance.
|
||||
<div align="center">
|
||||
[](https://cloud.sealos.io/?openapp=system-fastdeploy%3FtemplateName%3Dfastgpt&uid=fnWRt09fZP)
|
||||
</div>
|
||||
|
||||
Give it a 2-4 minute wait after deployment as it sets up the database. Initially, it might be a too slow since we're using the basic settings.
|
||||
|
||||
[sealos one click deployment tutorial](https://doc.fastgpt.io/docs/introduction/development/sealos/)
|
||||
|
||||
- [Getting Started with Local Development](https://doc.fastgpt.io/docs/introduction/development/intro)
|
||||
- [Deploying FastGPT](https://doc.fastgpt.io/docs/introduction/development/docker)
|
||||
- [Guide on System Configs](https://doc.fastgpt.io/docs/introduction/development/configuration)
|
||||
- [Configuring Multiple Models](https://doc.fastgpt.io/docs//introduction/development/modelConfig/intro)
|
||||
- [Version Updates & Upgrades](https://doc.fastgpt.io/docs/introduction/development/upgrading/index)
|
||||
|
||||
<a href="#FastGPT">
|
||||
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
## 💪 Related Projects
|
||||
|
||||
- [Laf: 3-minute quick access to third-party applications](https://github.com/labring/laf)
|
||||
- [Sealos: Rapid deployment of cluster applications](https://github.com/labring/sealos)
|
||||
- [One API: Multi-model management, supports Azure, Wenxin Yiyuan, etc.](https://github.com/songquanpeng/one-api)
|
||||
- [TuShan: Build a backend management system in 5 minutes](https://github.com/msgbyte/tushan)
|
||||
|
||||
<a href="#FastGPT">
|
||||
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
## 🤝 Third-party Ecosystem
|
||||
|
||||
- [luolinAI: Enterprise WeChat bot, ready to use](https://github.com/luolin-ai/FastGPT-Enterprise-WeChatbot)
|
||||
|
||||
<a href="#FastGPT">
|
||||
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
|
||||
## 🏘️ Community & Support
|
||||
|
||||
+ 🌐 Visit the [FastGPT website](https://fastgpt.io/) for full documentation and useful links.
|
||||
+ 💬 Join our [Discord server](https://discord.gg/mp68xkZn2Q) is to chat with FastGPT developers and other FastGPT users. This is a good place to learn about FastGPT, ask questions, and share your experiences.
|
||||
+ 🐞 Create [GitHub Issues](https://github.com/labring/FastGPT/issues/new/choose) for bug reports and feature requests.
|
||||
|
||||
<a href="#FastGPT">
|
||||
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
## 👀 Others
|
||||
|
||||
- [FastGPT FAQ](https://kjqvjse66l.feishu.cn/docx/HtrgdT0pkonP4kxGx8qcu6XDnGh)
|
||||
- [Docker Deployment Tutorial Video](https://www.bilibili.com/video/BV1jo4y147fT/)
|
||||
- [Official Account Integration Video Tutorial](https://www.bilibili.com/video/BV1xh4y1t7fy/)
|
||||
- [FastGPT Knowledge Base Demo](https://www.bilibili.com/video/BV1Wo4y1p7i1/)
|
||||
|
||||
<a href="#FastGPT">
|
||||
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
## 🌱 Contributors
|
||||
|
||||
We welcome all forms of contributions. If you are interested in contributing code, you can check out our GitHub [Issues](https://github.com/labring/FastGPT/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) to show us your ideas.
|
||||
|
||||
<a href="https://github.com/labring/FastGPT/graphs/contributors" target="_blank">
|
||||
<table>
|
||||
<tr>
|
||||
<th colspan="2">
|
||||
<br><img src="https://contrib.rocks/image?repo=labring/FastGPT"><br><br>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=active&period=past_28_days&owner_id=102226726&repo_ids=605673387&image_size=2x3&color_scheme=dark">
|
||||
<img alt="Active participants of labring - past 28 days" src="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=active&period=past_28_days&owner_id=102226726&repo_ids=605673387&image_size=2x3&color_scheme=light">
|
||||
</picture>
|
||||
</td>
|
||||
<td rowspan="2">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-participants-growth/thumbnail.png?activity=new&period=past_28_days&owner_id=102226726&repo_ids=605673387&image_size=4x7&color_scheme=dark">
|
||||
<img alt="New trends of labring" src="https://next.ossinsight.io/widgets/official/compose-org-participants-growth/thumbnail.png?activity=new&period=past_28_days&owner_id=102226726&repo_ids=605673387&image_size=4x7&color_scheme=light">
|
||||
</picture>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=new&period=past_28_days&owner_id=102226726&repo_ids=605673387&image_size=2x3&color_scheme=dark">
|
||||
<img alt="New participants of labring - past 28 days" src="https://next.ossinsight.io/widgets/official/compose-org-active-contributors/thumbnail.png?activity=new&period=past_28_days&owner_id=102226726&repo_ids=605673387&image_size=2x3&color_scheme=light">
|
||||
</picture>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</a>
|
||||
|
||||
|
||||
## 🌟 Star History
|
||||
|
||||
<a href="https://github.com/labring/FastGPT/stargazers" target="_blank" style="display: block" align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=labring/FastGPT&type=Date&theme=dark" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=labring/FastGPT&type=Date" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=labring/FastGPT&type=Date" />
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
<a href="#FastGPT">
|
||||
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
|
||||
</a>
|
||||
|
||||
## 📄 Usage Agreement
|
||||
|
||||
This repository complies with the [FastGPT Open Source License](./LICENSE) open source agreement.
|
||||
|
||||
1. Direct commercial use as a backend service is allowed, but provision of SaaS services is not allowed.
|
||||
2. Without commercial authorization, any form of commercial service must retain relevant copyright information.
|
||||
3. For full details, please see [FastGPT Open Source License](./LICENSE)
|
||||
4. Contact: Dennis@sealos.io , [click to view commercial version pricing strategy](https://doc.fastgpt.io/docs/introduction/commercial/)
|
||||
|
||||
<a href="#FastGPT">
|
||||
<img src="https://img.shields.io/badge/-Back_to_Top-7d09f1.svg" alt="#" align="right">
|
||||
</a>
|
||||
136
README_ja.md
Normal file
@@ -0,0 +1,136 @@
|
||||
<div align="center">
|
||||
|
||||
<a href="https://fastgpt.io/"><img src="/.github/imgs/logo.svg" width="120" height="120" alt="fastgpt logo"></a>
|
||||
|
||||
# FastGPT
|
||||
|
||||
<p align="center">
|
||||
<a href="./README_en.md">English</a> |
|
||||
<a href="./README.md">简体中文</a> |
|
||||
<a href="./README_ja.md">日语</a>
|
||||
</p>
|
||||
|
||||
FastGPT は、LLM 上 に 構築 された 知識 ベースの Q&A システムで、すぐに 使 えるデータ 処理 とモデル 呼 び 出 し 機能 を 提供 し、Flow の 可視化 を 通 じてワークフローのオーケストレーションを 可能 にします!
|
||||
|
||||
</div>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://fastgpt.io/">
|
||||
<img height="21" src="https://img.shields.io/badge/在线使用-d4eaf7?style=flat-square&logo=spoj&logoColor=7d09f1" alt="cloud">
|
||||
</a>
|
||||
<a href="https://doc.fastgpt.io/docs/introduction">
|
||||
<img height="21" src="https://img.shields.io/badge/相关文档-7d09f1?style=flat-square" alt="document">
|
||||
</a>
|
||||
<a href="https://doc.fastgpt.io/docs/introduction/development/intro">
|
||||
<img height="21" src="https://img.shields.io/badge/本地开发-%23d4eaf7?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=d4eaf7&color=7d09f1" alt="license">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409bd33f6d4
|
||||
|
||||
## 🛸 クラウドサービスの 利用
|
||||
|
||||
[fastgpt.io](https://fastgpt.io/)
|
||||
|
||||
| | |
|
||||
| ---------------------------------- | ---------------------------------- |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|
||||
## 💡 機能
|
||||
|
||||
1. パワフルなビジュアルワークフロー:AI アプリケーションを 簡単 に 作成
|
||||
|
||||
- [x] デッキのシンプルモード - マニュアルアレンジ 不要
|
||||
- [x] ユーザ 対話事前 ガイダンス
|
||||
- [x] グローバル 変数
|
||||
- [x] ナレッジベース 検索
|
||||
- [x] 複数 の LLM モデルによる 対話
|
||||
- [x] テキストマジック - 構造化 データへの 変換
|
||||
- [x] HTTP による 拡張
|
||||
- [ ] on-the-fly HTTP モジュールのための 埋 め 込 みLaf
|
||||
- [x] 次 の 対話 ステップへの 指示
|
||||
- [x] ソースファイル 参照 の 追跡
|
||||
- [ ] カスタムファイルリーダー
|
||||
- [ ] モジュールをプラグインにパッケージして 再利用 する
|
||||
|
||||
2. 広範 なナレッジベースの 前処理
|
||||
|
||||
- [x] 複数 のナレッジベースの 再利用 と 混合
|
||||
- [x] チャンクの 変更 と 削除 を 追跡
|
||||
- [x] 手動入力、直接分割、QA 分割 インポートをサポート
|
||||
- [x] URL フェッチとバッチ CSV インポートをサポート
|
||||
- [x] ナレッジベースにユニークなベクトルモデルを 設定可能
|
||||
- [x] オリジナルファイルの 保存
|
||||
- [ ] ファイル 学習 エージェント
|
||||
|
||||
3. 複数 の 効果測定 チャンネル
|
||||
|
||||
- [x] シングルポイントナレッジベース 検索 テスト
|
||||
- [x] 対話中 のフィードバック 参照 と 修正 ・ 削除機能
|
||||
- [x] 完全 なコンテキストの 提示
|
||||
- [ ] 完全 なモジュール 中間値提示
|
||||
|
||||
4. OpenAPI
|
||||
|
||||
- [x] 補完 インターフェイス (GPT インターフェイスに 合 わせる)
|
||||
- [ ] ナレッジベース CRUD
|
||||
|
||||
5. オペレーション 機能
|
||||
|
||||
- [x] ログイン 不要 の 共有 ウィンドウ
|
||||
- [x] Iframe によるワンクリック 埋 め 込 み
|
||||
- [ ] 対話記録 への 統一 されたアクセス
|
||||
|
||||
## 👨💻 開発
|
||||
|
||||
プロジェクトの 技術 スタック:NextJs + TS + ChakraUI + Mongo + Postgres (Vector プラグイン)
|
||||
|
||||
- **⚡ デプロイ**
|
||||
|
||||
[](https://cloud.sealos.io/?openapp=system-fastdeploy%3FtemplateName%3Dfastgpt&uid=fnWRt09fZP)
|
||||
|
||||
デプロイ 後、データベースをセットアップするので、2~4分待 ってください。基本設定 を 使 っているので、最初 は 少 し 遅 いかもしれません。
|
||||
|
||||
- [ローカル 開発入門](https://doc.fastgpt.io/docs/introduction/development/intro)
|
||||
- [FastGPT のデプロイ](https://doc.fastgpt.io/docs/introduction/development/docker)
|
||||
- [システム 設定 ガイド](https://doc.fastgpt.io/docs/introduction/development/configuration)
|
||||
- [複数 モデルの 設定](https://doc.fastgpt.io/docs/introduction/development/modelConfig/ai-proxy)
|
||||
- [バージョン 更新 とアップグレード](https://doc.fastgpt.io/docs/introduction/development/upgrading/index)
|
||||
|
||||
<!-- ## :point_right: ロードマップ
|
||||
- [FastGPT ロードマップ](https://kjqvjse66l.feishu.cn/docx/RVUxdqE2WolDYyxEKATcM0XXnte) -->
|
||||
|
||||
<!-- ## 🏘️ コミュニティ
|
||||
|
||||
| コミュニティグループ | アシスタント |
|
||||
| ------------------------------------------------- | ---------------------------------------------- |
|
||||
|  |  | -->
|
||||
|
||||
## 👀 その 他
|
||||
|
||||
- [FastGPT FAQ](https://kjqvjse66l.feishu.cn/docx/HtrgdT0pkonP4kxGx8qcu6XDnGh)
|
||||
- [Docker 導入 チュートリアル 動画](https://www.bilibili.com/video/BV1jo4y147fT/)
|
||||
- [公式 アカウント 統合 ビデオチュートリアル](https://www.bilibili.com/video/BV1xh4y1t7fy/)
|
||||
- [FastGPT ナレッジベースデモ](https://www.bilibili.com/video/BV1Wo4y1p7i1/)
|
||||
|
||||
## 💪 関連 プロジェクト
|
||||
|
||||
- [Laf:サードパーティ 製 アプリケーションに 3 分 でクイックアクセス](https://github.com/labring/laf)
|
||||
- [Sealos:クラスタアプリケーションの 迅速 な 展開](https://github.com/labring/sealos)
|
||||
- [One API:マルチモデル 管理、Azure、Wenxin Yiyuan などをサポートします。](https://github.com/songquanpeng/one-api)
|
||||
- [TuShan:5 分 でバックエンド 管理 システムを 構築](https://github.com/msgbyte/tushan)
|
||||
|
||||
## 🤝 サードパーティエコシステム
|
||||
|
||||
- [luolinAI:すぐに 使 える 企業向 け WeChat ボット](https://github.com/luolin-ai/FastGPT-Enterprise-WeChatbot)
|
||||
|
||||
## 🌟 Star History
|
||||
|
||||
[](https://star-history.com/#labring/FastGPT&Date)
|
||||
26
SECURITY.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# 安全策略
|
||||
|
||||
## 漏洞报告
|
||||
|
||||
如果您发现了 FastGPT 的安全漏洞,请按照以下步骤进行报告:
|
||||
|
||||
1. **报告方式**
|
||||
发送邮件至:yujinlong@sealos.io
|
||||
请备注版本以及您的 GitHub 账号
|
||||
|
||||
3. **响应时间**
|
||||
- 我们会在 48 小时内确认收到您的报告
|
||||
- 一般在 3 个工作日内给出初步评估结果
|
||||
|
||||
4. **漏洞处理流程**
|
||||
- 确认漏洞:我们会验证漏洞的存在性和影响范围
|
||||
- 修复开发:针对已确认的漏洞进行修复
|
||||
- 版本发布:在下一个版本更新中发布安全补丁
|
||||
- 公开披露:在修复完成后,我们会在更新日志中公布相关信息
|
||||
|
||||
5. **注意事项**
|
||||
- 在漏洞未修复前,请勿公开披露漏洞详情
|
||||
- 我们欢迎负责任的漏洞披露
|
||||
- 对于重大贡献者,我们会在项目致谢名单中提及
|
||||
|
||||
感谢您为 FastGPT 的安全性做出贡献!
|
||||
BIN
bin/fastgpt-v1.0.0-helm.tgz
Normal file
302
deploy/docker/docker-compose-milvus.yml
Normal file
@@ -0,0 +1,302 @@
|
||||
# 数据库的默认账号和密码仅首次运行时设置有效
|
||||
# 如果修改了账号密码,记得改数据库和项目连接参数,别只改一处~
|
||||
# 该配置文件只是给快速启动,测试使用。正式使用,记得务必修改账号密码,以及调整合适的知识库参数,共享内存等。
|
||||
# 如何无法访问 dockerhub 和 git,可以用阿里云(阿里云没有arm包)
|
||||
|
||||
version: '3.3'
|
||||
services:
|
||||
# Vector DB
|
||||
milvus-minio:
|
||||
container_name: milvus-minio
|
||||
image: minio/minio:RELEASE.2023-03-20T20-16-18Z
|
||||
environment:
|
||||
MINIO_ACCESS_KEY: minioadmin
|
||||
MINIO_SECRET_KEY: minioadmin
|
||||
# ports:
|
||||
# - '9001:9001'
|
||||
# - '9000:9000'
|
||||
networks:
|
||||
- fastgpt
|
||||
volumes:
|
||||
- ./milvus-minio:/minio_data
|
||||
command: minio server /minio_data --console-address ":9001"
|
||||
healthcheck:
|
||||
test: ['CMD', 'curl', '-f', 'http://localhost:9000/minio/health/live']
|
||||
interval: 30s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
# milvus
|
||||
milvusEtcd:
|
||||
container_name: milvusEtcd
|
||||
image: quay.io/coreos/etcd:v3.5.5
|
||||
environment:
|
||||
- ETCD_AUTO_COMPACTION_MODE=revision
|
||||
- ETCD_AUTO_COMPACTION_RETENTION=1000
|
||||
- ETCD_QUOTA_BACKEND_BYTES=4294967296
|
||||
- ETCD_SNAPSHOT_COUNT=50000
|
||||
networks:
|
||||
- fastgpt
|
||||
volumes:
|
||||
- ./milvus/etcd:/etcd
|
||||
command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
|
||||
healthcheck:
|
||||
test: ['CMD', 'etcdctl', 'endpoint', 'health']
|
||||
interval: 30s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
milvusStandalone:
|
||||
container_name: milvusStandalone
|
||||
image: milvusdb/milvus:v2.4.3
|
||||
command: ['milvus', 'run', 'standalone']
|
||||
security_opt:
|
||||
- seccomp:unconfined
|
||||
environment:
|
||||
ETCD_ENDPOINTS: milvusEtcd:2379
|
||||
MINIO_ADDRESS: milvus-minio:9000
|
||||
networks:
|
||||
- fastgpt
|
||||
volumes:
|
||||
- ./milvus/data:/var/lib/milvus
|
||||
healthcheck:
|
||||
test: ['CMD', 'curl', '-f', 'http://localhost:9091/healthz']
|
||||
interval: 30s
|
||||
start_period: 90s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
depends_on:
|
||||
- 'milvusEtcd'
|
||||
- 'milvus-minio'
|
||||
|
||||
# DB
|
||||
mongo:
|
||||
image: mongo:5.0.18 # dockerhub
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/mongo:5.0.18 # 阿里云
|
||||
# image: mongo:4.4.29 # cpu不支持AVX时候使用
|
||||
container_name: mongo
|
||||
restart: always
|
||||
networks:
|
||||
- fastgpt
|
||||
command: mongod --keyFile /data/mongodb.key --replSet rs0
|
||||
environment:
|
||||
- MONGO_INITDB_ROOT_USERNAME=myusername
|
||||
- MONGO_INITDB_ROOT_PASSWORD=mypassword
|
||||
volumes:
|
||||
- ./mongo/data:/data/db
|
||||
entrypoint:
|
||||
- bash
|
||||
- -c
|
||||
- |
|
||||
openssl rand -base64 128 > /data/mongodb.key
|
||||
chmod 400 /data/mongodb.key
|
||||
chown 999:999 /data/mongodb.key
|
||||
echo 'const isInited = rs.status().ok === 1
|
||||
if(!isInited){
|
||||
rs.initiate({
|
||||
_id: "rs0",
|
||||
members: [
|
||||
{ _id: 0, host: "mongo:27017" }
|
||||
]
|
||||
})
|
||||
}' > /data/initReplicaSet.js
|
||||
# 启动MongoDB服务
|
||||
exec docker-entrypoint.sh "$$@" &
|
||||
|
||||
# 等待MongoDB服务启动
|
||||
until mongo -u myusername -p mypassword --authenticationDatabase admin --eval "print('waited for connection')"; do
|
||||
echo "Waiting for MongoDB to start..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# 执行初始化副本集的脚本
|
||||
mongo -u myusername -p mypassword --authenticationDatabase admin /data/initReplicaSet.js
|
||||
|
||||
# 等待docker-entrypoint.sh脚本执行的MongoDB服务进程
|
||||
wait $$!
|
||||
redis:
|
||||
image: redis:7.2-alpine
|
||||
container_name: redis
|
||||
networks:
|
||||
- fastgpt
|
||||
restart: always
|
||||
command: |
|
||||
redis-server --requirepass mypassword --loglevel warning --maxclients 10000 --appendonly yes --save 60 10 --maxmemory 4gb --maxmemory-policy noeviction
|
||||
healthcheck:
|
||||
test: ['CMD', 'redis-cli', '-a', 'mypassword', 'ping']
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
volumes:
|
||||
- ./redis/data:/data
|
||||
fastgpt-minio:
|
||||
image: minio/minio:latest
|
||||
container_name: fastgpt-minio
|
||||
restart: always
|
||||
networks:
|
||||
- fastgpt
|
||||
ports: # comment out if you do not need to expose the port (in production environment, you should not expose the port)
|
||||
- '9000:9000'
|
||||
- '9001:9001'
|
||||
environment:
|
||||
- MINIO_ROOT_USER=minioadmin
|
||||
- MINIO_ROOT_PASSWORD=minioadmin
|
||||
volumes:
|
||||
- ./fastgpt-minio:/data
|
||||
command: server /data --console-address ":9001"
|
||||
healthcheck:
|
||||
test: ['CMD', 'curl', '-f', 'http://localhost:9000/minio/health/live']
|
||||
interval: 30s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
|
||||
fastgpt:
|
||||
container_name: fastgpt
|
||||
image: ghcr.io/labring/fastgpt:v4.12.1-fix # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.12.1-fix # 阿里云
|
||||
ports:
|
||||
- 3000:3000
|
||||
networks:
|
||||
- fastgpt
|
||||
depends_on:
|
||||
- mongo
|
||||
- sandbox
|
||||
- milvusStandalone
|
||||
restart: always
|
||||
environment:
|
||||
# 前端外部可访问的地址,用于自动补全文件资源路径。例如 https:fastgpt.cn,不能填 localhost。这个值可以不填,不填则发给模型的图片会是一个相对路径,而不是全路径,模型可能伪造Host。
|
||||
- FE_DOMAIN=
|
||||
# root 密码,用户名为: root。如果需要修改 root 密码,直接修改这个环境变量,并重启即可。
|
||||
- DEFAULT_ROOT_PSW=1234
|
||||
# 登录凭证密钥
|
||||
- TOKEN_KEY=any
|
||||
# root的密钥,常用于升级时候的初始化请求
|
||||
- ROOT_KEY=root_key
|
||||
# 文件阅读加密
|
||||
- FILE_TOKEN_KEY=filetoken
|
||||
# 密钥加密key
|
||||
- AES256_SECRET_KEY=fastgptkey
|
||||
|
||||
# plugin 地址
|
||||
- PLUGIN_BASE_URL=http://fastgpt-plugin:3000
|
||||
- PLUGIN_TOKEN=xxxxxx
|
||||
# sandbox 地址
|
||||
- SANDBOX_URL=http://sandbox:3000
|
||||
# AI Proxy 的地址,如果配了该地址,优先使用
|
||||
- AIPROXY_API_ENDPOINT=http://aiproxy:3000
|
||||
# AI Proxy 的 Admin Token,与 AI Proxy 中的环境变量 ADMIN_KEY
|
||||
- AIPROXY_API_TOKEN=aiproxy
|
||||
|
||||
# 数据库最大连接数
|
||||
- DB_MAX_LINK=30
|
||||
# MongoDB 连接参数. 用户名myusername,密码mypassword。
|
||||
- MONGODB_URI=mongodb://myusername:mypassword@mongo:27017/fastgpt?authSource=admin
|
||||
# Redis 连接参数
|
||||
- REDIS_URL=redis://default:mypassword@redis:6379
|
||||
# 向量库 连接参数
|
||||
- MILVUS_ADDRESS=http://milvusStandalone:19530
|
||||
- MILVUS_TOKEN=none
|
||||
|
||||
# 日志等级: debug, info, warn, error
|
||||
- LOG_LEVEL=info
|
||||
- STORE_LOG_LEVEL=warn
|
||||
# 工作流最大运行次数
|
||||
- WORKFLOW_MAX_RUN_TIMES=1000
|
||||
# 批量执行节点,最大输入长度
|
||||
- WORKFLOW_MAX_LOOP_TIMES=100
|
||||
# 对话文件过期天数
|
||||
- CHAT_FILE_EXPIRE_TIME=7
|
||||
volumes:
|
||||
- ./config.json:/app/data/config.json
|
||||
sandbox:
|
||||
container_name: sandbox
|
||||
image: ghcr.io/labring/fastgpt-sandbox:v4.12.1 # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.12.1 # 阿里云
|
||||
networks:
|
||||
- fastgpt
|
||||
restart: always
|
||||
fastgpt-mcp-server:
|
||||
container_name: fastgpt-mcp-server
|
||||
image: ghcr.io/labring/fastgpt-mcp_server:v4.12.1 # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-mcp_server:v4.12.1 # 阿里云
|
||||
ports:
|
||||
- 3005:3000
|
||||
networks:
|
||||
- fastgpt
|
||||
restart: always
|
||||
environment:
|
||||
- FASTGPT_ENDPOINT=http://fastgpt:3000
|
||||
fastgpt-plugin:
|
||||
image: ghcr.io/labring/fastgpt-plugin:v0.1.10 # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-plugin:v0.1.10 # 阿里云
|
||||
container_name: fastgpt-plugin
|
||||
restart: always
|
||||
networks:
|
||||
- fastgpt
|
||||
environment:
|
||||
- AUTH_TOKEN=xxxxxx # 如果不需要鉴权可以直接去掉这个环境变量
|
||||
|
||||
# 改成 minio 可访问地址,例如 http://192.168.2.2:9000/fastgpt-plugins
|
||||
# 必须指向 Minio 的桶的地址
|
||||
# 如果 Minio 可以直接通过外网访问,可以不设置这个环境变量
|
||||
# - MINIO_CUSTOM_ENDPOINT=http://192.168.2.2:9000
|
||||
|
||||
- MINIO_ENDPOINT=fastgpt-minio
|
||||
- MINIO_PORT=9000
|
||||
- MINIO_USE_SSL=false
|
||||
- MINIO_ACCESS_KEY=minioadmin
|
||||
- MINIO_SECRET_KEY=minioadmin
|
||||
- MINIO_BUCKET=fastgpt-plugins
|
||||
depends_on:
|
||||
fastgpt-minio:
|
||||
condition: service_healthy
|
||||
|
||||
# AI Proxy
|
||||
aiproxy:
|
||||
image: ghcr.io/labring/aiproxy:v0.2.2
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/labring/aiproxy:v0.2.2 # 阿里云
|
||||
container_name: aiproxy
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
aiproxy_pg:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- fastgpt
|
||||
environment:
|
||||
# 对应 fastgpt 里的AIPROXY_API_TOKEN
|
||||
- ADMIN_KEY=aiproxy
|
||||
# 错误日志详情保存时间(小时)
|
||||
- LOG_DETAIL_STORAGE_HOURS=1
|
||||
# 数据库连接地址
|
||||
- SQL_DSN=postgres://postgres:aiproxy@aiproxy_pg:5432/aiproxy
|
||||
# 最大重试次数
|
||||
- RETRY_TIMES=3
|
||||
# 不需要计费
|
||||
- BILLING_ENABLED=false
|
||||
# 不需要严格检测模型
|
||||
- DISABLE_MODEL_CONFIG=true
|
||||
healthcheck:
|
||||
test: ['CMD', 'curl', '-f', 'http://localhost:3000/api/status']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
aiproxy_pg:
|
||||
image: pgvector/pgvector:0.8.0-pg15 # docker hub
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/pgvector:v0.8.0-pg15 # 阿里云
|
||||
restart: unless-stopped
|
||||
container_name: aiproxy_pg
|
||||
volumes:
|
||||
- ./aiproxy_pg:/var/lib/postgresql/data
|
||||
networks:
|
||||
- fastgpt
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_DB: aiproxy
|
||||
POSTGRES_PASSWORD: aiproxy
|
||||
healthcheck:
|
||||
test: ['CMD', 'pg_isready', '-U', 'postgres', '-d', 'aiproxy']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
networks:
|
||||
fastgpt:
|
||||
276
deploy/docker/docker-compose-oceanbase/docker-compose.yml
Normal file
@@ -0,0 +1,276 @@
|
||||
# 数据库的默认账号和密码仅首次运行时设置有效
|
||||
# 如果修改了账号密码,记得改数据库和项目连接参数,别只改一处~
|
||||
# 该配置文件只是给快速启动,测试使用。正式使用,记得务必修改账号密码,以及调整合适的知识库参数,共享内存等。
|
||||
# 如何无法访问 dockerhub 和 git,可以用阿里云(阿里云没有arm包)
|
||||
|
||||
version: '3.3'
|
||||
services:
|
||||
# Vector DB
|
||||
ob:
|
||||
image: oceanbase/oceanbase-ce:4.3.5-lts # docker hub
|
||||
# image: quay.io/oceanbase/oceanbase-ce:4.3.5-lts # 镜像
|
||||
container_name: ob
|
||||
restart: always
|
||||
# ports: # 生产环境建议不要暴露
|
||||
# - 2881:2881
|
||||
networks:
|
||||
- fastgpt
|
||||
environment:
|
||||
# 这里的配置只有首次运行生效。修改后,重启镜像是不会生效的。需要把持久化数据删除再重启,才有效果
|
||||
- OB_SYS_PASSWORD=obsyspassword
|
||||
# 不同于传统数据库,OceanBase 数据库的账号包含更多字段,包括用户名、租户名和集群名。经典格式为"用户名@租户名#集群名"
|
||||
# 比如用mysql客户端连接时,根据本文件的默认配置,应该指定 "-uroot@tenantname"
|
||||
- OB_TENANT_NAME=tenantname
|
||||
- OB_TENANT_PASSWORD=tenantpassword
|
||||
# MODE分为MINI和NORMAL, 后者会最大程度使用主机资源
|
||||
- MODE=MINI
|
||||
- OB_SERVER_IP=127.0.0.1
|
||||
# 更多环境变量配置见oceanbase官方文档: https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000002013494
|
||||
volumes:
|
||||
- ./ob/data:/root/ob
|
||||
- ./ob/config:/root/.obd/cluster
|
||||
- ./init.sql:/root/boot/init.d/init.sql
|
||||
healthcheck:
|
||||
# obclient -h127.0.0.1 -P2881 -uroot@tenantname -ptenantpassword -e "SELECT 1;"
|
||||
test:
|
||||
[
|
||||
'CMD-SHELL',
|
||||
'obclient -h$${OB_SERVER_IP} -P2881 -uroot@$${OB_TENANT_NAME} -p$${OB_TENANT_PASSWORD} -e "SELECT 1;"'
|
||||
]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 1000
|
||||
start_period: 10s
|
||||
|
||||
# DB
|
||||
mongo:
|
||||
image: mongo:5.0.18 # dockerhub
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/mongo:5.0.18 # 阿里云
|
||||
# image: mongo:4.4.29 # cpu不支持AVX时候使用
|
||||
container_name: mongo
|
||||
restart: always
|
||||
networks:
|
||||
- fastgpt
|
||||
command: mongod --keyFile /data/mongodb.key --replSet rs0
|
||||
environment:
|
||||
- MONGO_INITDB_ROOT_USERNAME=myusername
|
||||
- MONGO_INITDB_ROOT_PASSWORD=mypassword
|
||||
volumes:
|
||||
- ./mongo/data:/data/db
|
||||
entrypoint:
|
||||
- bash
|
||||
- -c
|
||||
- |
|
||||
openssl rand -base64 128 > /data/mongodb.key
|
||||
chmod 400 /data/mongodb.key
|
||||
chown 999:999 /data/mongodb.key
|
||||
echo 'const isInited = rs.status().ok === 1
|
||||
if(!isInited){
|
||||
rs.initiate({
|
||||
_id: "rs0",
|
||||
members: [
|
||||
{ _id: 0, host: "mongo:27017" }
|
||||
]
|
||||
})
|
||||
}' > /data/initReplicaSet.js
|
||||
# 启动MongoDB服务
|
||||
exec docker-entrypoint.sh "$$@" &
|
||||
|
||||
# 等待MongoDB服务启动
|
||||
until mongo -u myusername -p mypassword --authenticationDatabase admin --eval "print('waited for connection')"; do
|
||||
echo "Waiting for MongoDB to start..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# 执行初始化副本集的脚本
|
||||
mongo -u myusername -p mypassword --authenticationDatabase admin /data/initReplicaSet.js
|
||||
|
||||
# 等待docker-entrypoint.sh脚本执行的MongoDB服务进程
|
||||
wait $$!
|
||||
redis:
|
||||
image: redis:7.2-alpine
|
||||
container_name: redis
|
||||
networks:
|
||||
- fastgpt
|
||||
restart: always
|
||||
command: |
|
||||
redis-server --requirepass mypassword --loglevel warning --maxclients 10000 --appendonly yes --save 60 10 --maxmemory 4gb --maxmemory-policy noeviction
|
||||
healthcheck:
|
||||
test: ['CMD', 'redis-cli', '-a', 'mypassword', 'ping']
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
volumes:
|
||||
- ./redis/data:/data
|
||||
fastgpt-minio:
|
||||
image: minio/minio:latest
|
||||
container_name: fastgpt-minio
|
||||
restart: always
|
||||
networks:
|
||||
- fastgpt
|
||||
ports: # comment out if you do not need to expose the port (in production environment, you should not expose the port)
|
||||
- '9000:9000'
|
||||
- '9001:9001'
|
||||
environment:
|
||||
- MINIO_ROOT_USER=minioadmin
|
||||
- MINIO_ROOT_PASSWORD=minioadmin
|
||||
volumes:
|
||||
- ./fastgpt-minio:/data
|
||||
command: server /data --console-address ":9001"
|
||||
healthcheck:
|
||||
test: ['CMD', 'curl', '-f', 'http://localhost:9000/minio/health/live']
|
||||
interval: 30s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
|
||||
fastgpt:
|
||||
container_name: fastgpt
|
||||
image: ghcr.io/labring/fastgpt:v4.12.1-fix # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.12.1-fix # 阿里云
|
||||
ports:
|
||||
- 3000:3000
|
||||
networks:
|
||||
- fastgpt
|
||||
depends_on:
|
||||
- mongo
|
||||
- sandbox
|
||||
- ob
|
||||
restart: always
|
||||
environment:
|
||||
# 前端外部可访问的地址,用于自动补全文件资源路径。例如 https:fastgpt.cn,不能填 localhost。这个值可以不填,不填则发给模型的图片会是一个相对路径,而不是全路径,模型可能伪造Host。
|
||||
- FE_DOMAIN=
|
||||
# root 密码,用户名为: root。如果需要修改 root 密码,直接修改这个环境变量,并重启即可。
|
||||
- DEFAULT_ROOT_PSW=1234
|
||||
# 登录凭证密钥
|
||||
- TOKEN_KEY=any
|
||||
# root的密钥,常用于升级时候的初始化请求
|
||||
- ROOT_KEY=root_key
|
||||
# 文件阅读加密
|
||||
- FILE_TOKEN_KEY=filetoken
|
||||
# 密钥加密key
|
||||
- AES256_SECRET_KEY=fastgptkey
|
||||
|
||||
# plugin 地址
|
||||
- PLUGIN_BASE_URL=http://fastgpt-plugin:3000
|
||||
- PLUGIN_TOKEN=xxxxxx
|
||||
# sandbox 地址
|
||||
- SANDBOX_URL=http://sandbox:3000
|
||||
# AI Proxy 的地址,如果配了该地址,优先使用
|
||||
- AIPROXY_API_ENDPOINT=http://aiproxy:3000
|
||||
# AI Proxy 的 Admin Token,与 AI Proxy 中的环境变量 ADMIN_KEY
|
||||
- AIPROXY_API_TOKEN=aiproxy
|
||||
|
||||
# 数据库最大连接数
|
||||
- DB_MAX_LINK=30
|
||||
# MongoDB 连接参数. 用户名myusername,密码mypassword。
|
||||
- MONGODB_URI=mongodb://myusername:mypassword@mongo:27017/fastgpt?authSource=admin
|
||||
# Redis 连接参数
|
||||
- REDIS_URL=redis://default:mypassword@redis:6379
|
||||
# 向量库 连接参数
|
||||
- OCEANBASE_URL=mysql://root%40tenantname:tenantpassword@ob:2881/test
|
||||
|
||||
# 日志等级: debug, info, warn, error
|
||||
- LOG_LEVEL=info
|
||||
- STORE_LOG_LEVEL=warn
|
||||
# 工作流最大运行次数
|
||||
- WORKFLOW_MAX_RUN_TIMES=1000
|
||||
# 批量执行节点,最大输入长度
|
||||
- WORKFLOW_MAX_LOOP_TIMES=100
|
||||
# 对话文件过期天数
|
||||
- CHAT_FILE_EXPIRE_TIME=7
|
||||
volumes:
|
||||
- ./config.json:/app/data/config.json
|
||||
sandbox:
|
||||
container_name: sandbox
|
||||
image: ghcr.io/labring/fastgpt-sandbox:v4.12.1 # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.12.1 # 阿里云
|
||||
networks:
|
||||
- fastgpt
|
||||
restart: always
|
||||
fastgpt-mcp-server:
|
||||
container_name: fastgpt-mcp-server
|
||||
image: ghcr.io/labring/fastgpt-mcp_server:v4.12.1 # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-mcp_server:v4.12.1 # 阿里云
|
||||
ports:
|
||||
- 3005:3000
|
||||
networks:
|
||||
- fastgpt
|
||||
restart: always
|
||||
environment:
|
||||
- FASTGPT_ENDPOINT=http://fastgpt:3000
|
||||
fastgpt-plugin:
|
||||
image: ghcr.io/labring/fastgpt-plugin:v0.1.10 # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-plugin:v0.1.10 # 阿里云
|
||||
container_name: fastgpt-plugin
|
||||
restart: always
|
||||
networks:
|
||||
- fastgpt
|
||||
environment:
|
||||
- AUTH_TOKEN=xxxxxx # 如果不需要鉴权可以直接去掉这个环境变量
|
||||
|
||||
# 改成 minio 可访问地址,例如 http://192.168.2.2:9000/fastgpt-plugins
|
||||
# 必须指向 Minio 的桶的地址
|
||||
# 如果 Minio 可以直接通过外网访问,可以不设置这个环境变量
|
||||
# - MINIO_CUSTOM_ENDPOINT=http://192.168.2.2:9000
|
||||
|
||||
- MINIO_ENDPOINT=fastgpt-minio
|
||||
- MINIO_PORT=9000
|
||||
- MINIO_USE_SSL=false
|
||||
- MINIO_ACCESS_KEY=minioadmin
|
||||
- MINIO_SECRET_KEY=minioadmin
|
||||
- MINIO_BUCKET=fastgpt-plugins
|
||||
depends_on:
|
||||
fastgpt-minio:
|
||||
condition: service_healthy
|
||||
|
||||
# AI Proxy
|
||||
aiproxy:
|
||||
image: ghcr.io/labring/aiproxy:v0.2.2
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/labring/aiproxy:v0.2.2 # 阿里云
|
||||
container_name: aiproxy
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
aiproxy_pg:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- fastgpt
|
||||
environment:
|
||||
# 对应 fastgpt 里的AIPROXY_API_TOKEN
|
||||
- ADMIN_KEY=aiproxy
|
||||
# 错误日志详情保存时间(小时)
|
||||
- LOG_DETAIL_STORAGE_HOURS=1
|
||||
# 数据库连接地址
|
||||
- SQL_DSN=postgres://postgres:aiproxy@aiproxy_pg:5432/aiproxy
|
||||
# 最大重试次数
|
||||
- RETRY_TIMES=3
|
||||
# 不需要计费
|
||||
- BILLING_ENABLED=false
|
||||
# 不需要严格检测模型
|
||||
- DISABLE_MODEL_CONFIG=true
|
||||
healthcheck:
|
||||
test: ['CMD', 'curl', '-f', 'http://localhost:3000/api/status']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
aiproxy_pg:
|
||||
image: pgvector/pgvector:0.8.0-pg15 # docker hub
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/pgvector:v0.8.0-pg15 # 阿里云
|
||||
restart: unless-stopped
|
||||
container_name: aiproxy_pg
|
||||
volumes:
|
||||
- ./aiproxy_pg:/var/lib/postgresql/data
|
||||
networks:
|
||||
- fastgpt
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_DB: aiproxy
|
||||
POSTGRES_PASSWORD: aiproxy
|
||||
healthcheck:
|
||||
test: ['CMD', 'pg_isready', '-U', 'postgres', '-d', 'aiproxy']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
networks:
|
||||
fastgpt:
|
||||
2
deploy/docker/docker-compose-oceanbase/init.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER SYSTEM SET ob_vector_memory_limit_percentage = 30;
|
||||
|
||||
262
deploy/docker/docker-compose-pgvector.yml
Normal file
@@ -0,0 +1,262 @@
|
||||
# 数据库的默认账号和密码仅首次运行时设置有效
|
||||
# 如果修改了账号密码,记得改数据库和项目连接参数,别只改一处~
|
||||
# 该配置文件只是给快速启动,测试使用。正式使用,记得务必修改账号密码,以及调整合适的知识库参数,共享内存等。
|
||||
# 如何无法访问 dockerhub 和 git,可以用阿里云(阿里云没有arm包)
|
||||
|
||||
version: '3.3'
|
||||
services:
|
||||
# Vector DB
|
||||
pg:
|
||||
image: pgvector/pgvector:0.8.0-pg15 # docker hub
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/pgvector:v0.8.0-pg15 # 阿里云
|
||||
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
|
||||
healthcheck:
|
||||
test: ['CMD', 'pg_isready', '-U', 'username', '-d', 'postgres']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
# DB
|
||||
mongo:
|
||||
image: mongo:5.0.18 # dockerhub
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/mongo:5.0.18 # 阿里云
|
||||
# image: mongo:4.4.29 # cpu不支持AVX时候使用
|
||||
container_name: mongo
|
||||
restart: always
|
||||
networks:
|
||||
- fastgpt
|
||||
command: mongod --keyFile /data/mongodb.key --replSet rs0
|
||||
environment:
|
||||
- MONGO_INITDB_ROOT_USERNAME=myusername
|
||||
- MONGO_INITDB_ROOT_PASSWORD=mypassword
|
||||
volumes:
|
||||
- ./mongo/data:/data/db
|
||||
entrypoint:
|
||||
- bash
|
||||
- -c
|
||||
- |
|
||||
openssl rand -base64 128 > /data/mongodb.key
|
||||
chmod 400 /data/mongodb.key
|
||||
chown 999:999 /data/mongodb.key
|
||||
echo 'const isInited = rs.status().ok === 1
|
||||
if(!isInited){
|
||||
rs.initiate({
|
||||
_id: "rs0",
|
||||
members: [
|
||||
{ _id: 0, host: "mongo:27017" }
|
||||
]
|
||||
})
|
||||
}' > /data/initReplicaSet.js
|
||||
# 启动MongoDB服务
|
||||
exec docker-entrypoint.sh "$$@" &
|
||||
|
||||
# 等待MongoDB服务启动
|
||||
until mongo -u myusername -p mypassword --authenticationDatabase admin --eval "print('waited for connection')"; do
|
||||
echo "Waiting for MongoDB to start..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# 执行初始化副本集的脚本
|
||||
mongo -u myusername -p mypassword --authenticationDatabase admin /data/initReplicaSet.js
|
||||
|
||||
# 等待docker-entrypoint.sh脚本执行的MongoDB服务进程
|
||||
wait $$!
|
||||
redis:
|
||||
image: redis:7.2-alpine
|
||||
container_name: redis
|
||||
networks:
|
||||
- fastgpt
|
||||
restart: always
|
||||
command: |
|
||||
redis-server --requirepass mypassword --loglevel warning --maxclients 10000 --appendonly yes --save 60 10 --maxmemory 4gb --maxmemory-policy noeviction
|
||||
healthcheck:
|
||||
test: ['CMD', 'redis-cli', '-a', 'mypassword', 'ping']
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
volumes:
|
||||
- ./redis/data:/data
|
||||
fastgpt-minio:
|
||||
image: minio/minio:latest
|
||||
container_name: fastgpt-minio
|
||||
restart: always
|
||||
networks:
|
||||
- fastgpt
|
||||
ports: # comment out if you do not need to expose the port (in production environment, you should not expose the port)
|
||||
- '9000:9000'
|
||||
- '9001:9001'
|
||||
environment:
|
||||
- MINIO_ROOT_USER=minioadmin
|
||||
- MINIO_ROOT_PASSWORD=minioadmin
|
||||
volumes:
|
||||
- ./fastgpt-minio:/data
|
||||
command: server /data --console-address ":9001"
|
||||
healthcheck:
|
||||
test: ['CMD', 'curl', '-f', 'http://localhost:9000/minio/health/live']
|
||||
interval: 30s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
|
||||
fastgpt:
|
||||
container_name: fastgpt
|
||||
image: ghcr.io/labring/fastgpt:v4.12.1-fix # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.12.1-fix # 阿里云
|
||||
ports:
|
||||
- 3000:3000
|
||||
networks:
|
||||
- fastgpt
|
||||
depends_on:
|
||||
- mongo
|
||||
- sandbox
|
||||
- pg
|
||||
restart: always
|
||||
environment:
|
||||
# 前端外部可访问的地址,用于自动补全文件资源路径。例如 https:fastgpt.cn,不能填 localhost。这个值可以不填,不填则发给模型的图片会是一个相对路径,而不是全路径,模型可能伪造Host。
|
||||
- FE_DOMAIN=
|
||||
# root 密码,用户名为: root。如果需要修改 root 密码,直接修改这个环境变量,并重启即可。
|
||||
- DEFAULT_ROOT_PSW=1234
|
||||
# 登录凭证密钥
|
||||
- TOKEN_KEY=any
|
||||
# root的密钥,常用于升级时候的初始化请求
|
||||
- ROOT_KEY=root_key
|
||||
# 文件阅读加密
|
||||
- FILE_TOKEN_KEY=filetoken
|
||||
# 密钥加密key
|
||||
- AES256_SECRET_KEY=fastgptkey
|
||||
|
||||
# plugin 地址
|
||||
- PLUGIN_BASE_URL=http://fastgpt-plugin:3000
|
||||
- PLUGIN_TOKEN=xxxxxx
|
||||
# sandbox 地址
|
||||
- SANDBOX_URL=http://sandbox:3000
|
||||
# AI Proxy 的地址,如果配了该地址,优先使用
|
||||
- AIPROXY_API_ENDPOINT=http://aiproxy:3000
|
||||
# AI Proxy 的 Admin Token,与 AI Proxy 中的环境变量 ADMIN_KEY
|
||||
- AIPROXY_API_TOKEN=aiproxy
|
||||
|
||||
# 数据库最大连接数
|
||||
- DB_MAX_LINK=30
|
||||
# MongoDB 连接参数. 用户名myusername,密码mypassword。
|
||||
- MONGODB_URI=mongodb://myusername:mypassword@mongo:27017/fastgpt?authSource=admin
|
||||
# Redis 连接参数
|
||||
- REDIS_URL=redis://default:mypassword@redis:6379
|
||||
# 向量库 连接参数
|
||||
- PG_URL=postgresql://username:password@pg:5432/postgres
|
||||
|
||||
# 日志等级: debug, info, warn, error
|
||||
- LOG_LEVEL=info
|
||||
- STORE_LOG_LEVEL=warn
|
||||
# 工作流最大运行次数
|
||||
- WORKFLOW_MAX_RUN_TIMES=1000
|
||||
# 批量执行节点,最大输入长度
|
||||
- WORKFLOW_MAX_LOOP_TIMES=100
|
||||
# 对话文件过期天数
|
||||
- CHAT_FILE_EXPIRE_TIME=7
|
||||
volumes:
|
||||
- ./config.json:/app/data/config.json
|
||||
sandbox:
|
||||
container_name: sandbox
|
||||
image: ghcr.io/labring/fastgpt-sandbox:v4.12.1 # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.12.1 # 阿里云
|
||||
networks:
|
||||
- fastgpt
|
||||
restart: always
|
||||
fastgpt-mcp-server:
|
||||
container_name: fastgpt-mcp-server
|
||||
image: ghcr.io/labring/fastgpt-mcp_server:v4.12.1 # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-mcp_server:v4.12.1 # 阿里云
|
||||
ports:
|
||||
- 3005:3000
|
||||
networks:
|
||||
- fastgpt
|
||||
restart: always
|
||||
environment:
|
||||
- FASTGPT_ENDPOINT=http://fastgpt:3000
|
||||
fastgpt-plugin:
|
||||
image: ghcr.io/labring/fastgpt-plugin:v0.1.10 # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-plugin:v0.1.10 # 阿里云
|
||||
container_name: fastgpt-plugin
|
||||
restart: always
|
||||
networks:
|
||||
- fastgpt
|
||||
environment:
|
||||
- AUTH_TOKEN=xxxxxx # 如果不需要鉴权可以直接去掉这个环境变量
|
||||
|
||||
# 改成 minio 可访问地址,例如 http://192.168.2.2:9000/fastgpt-plugins
|
||||
# 必须指向 Minio 的桶的地址
|
||||
# 如果 Minio 可以直接通过外网访问,可以不设置这个环境变量
|
||||
# - MINIO_CUSTOM_ENDPOINT=http://192.168.2.2:9000
|
||||
|
||||
- MINIO_ENDPOINT=fastgpt-minio
|
||||
- MINIO_PORT=9000
|
||||
- MINIO_USE_SSL=false
|
||||
- MINIO_ACCESS_KEY=minioadmin
|
||||
- MINIO_SECRET_KEY=minioadmin
|
||||
- MINIO_BUCKET=fastgpt-plugins
|
||||
depends_on:
|
||||
fastgpt-minio:
|
||||
condition: service_healthy
|
||||
|
||||
# AI Proxy
|
||||
aiproxy:
|
||||
image: ghcr.io/labring/aiproxy:v0.2.2
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/labring/aiproxy:v0.2.2 # 阿里云
|
||||
container_name: aiproxy
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
aiproxy_pg:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- fastgpt
|
||||
environment:
|
||||
# 对应 fastgpt 里的AIPROXY_API_TOKEN
|
||||
- ADMIN_KEY=aiproxy
|
||||
# 错误日志详情保存时间(小时)
|
||||
- LOG_DETAIL_STORAGE_HOURS=1
|
||||
# 数据库连接地址
|
||||
- SQL_DSN=postgres://postgres:aiproxy@aiproxy_pg:5432/aiproxy
|
||||
# 最大重试次数
|
||||
- RETRY_TIMES=3
|
||||
# 不需要计费
|
||||
- BILLING_ENABLED=false
|
||||
# 不需要严格检测模型
|
||||
- DISABLE_MODEL_CONFIG=true
|
||||
healthcheck:
|
||||
test: ['CMD', 'curl', '-f', 'http://localhost:3000/api/status']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
aiproxy_pg:
|
||||
image: pgvector/pgvector:0.8.0-pg15 # docker hub
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/pgvector:v0.8.0-pg15 # 阿里云
|
||||
restart: unless-stopped
|
||||
container_name: aiproxy_pg
|
||||
volumes:
|
||||
- ./aiproxy_pg:/var/lib/postgresql/data
|
||||
networks:
|
||||
- fastgpt
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_DB: aiproxy
|
||||
POSTGRES_PASSWORD: aiproxy
|
||||
healthcheck:
|
||||
test: ['CMD', 'pg_isready', '-U', 'postgres', '-d', 'aiproxy']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
networks:
|
||||
fastgpt:
|
||||
244
deploy/docker/docker-compose-zilliz.yml
Normal file
@@ -0,0 +1,244 @@
|
||||
# 数据库的默认账号和密码仅首次运行时设置有效
|
||||
# 如果修改了账号密码,记得改数据库和项目连接参数,别只改一处~
|
||||
# 该配置文件只是给快速启动,测试使用。正式使用,记得务必修改账号密码,以及调整合适的知识库参数,共享内存等。
|
||||
# 如何无法访问 dockerhub 和 git,可以用阿里云(阿里云没有arm包)
|
||||
|
||||
version: '3.3'
|
||||
services:
|
||||
# Vector DB
|
||||
|
||||
|
||||
# DB
|
||||
mongo:
|
||||
image: mongo:5.0.18 # dockerhub
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/mongo:5.0.18 # 阿里云
|
||||
# image: mongo:4.4.29 # cpu不支持AVX时候使用
|
||||
container_name: mongo
|
||||
restart: always
|
||||
networks:
|
||||
- fastgpt
|
||||
command: mongod --keyFile /data/mongodb.key --replSet rs0
|
||||
environment:
|
||||
- MONGO_INITDB_ROOT_USERNAME=myusername
|
||||
- MONGO_INITDB_ROOT_PASSWORD=mypassword
|
||||
volumes:
|
||||
- ./mongo/data:/data/db
|
||||
entrypoint:
|
||||
- bash
|
||||
- -c
|
||||
- |
|
||||
openssl rand -base64 128 > /data/mongodb.key
|
||||
chmod 400 /data/mongodb.key
|
||||
chown 999:999 /data/mongodb.key
|
||||
echo 'const isInited = rs.status().ok === 1
|
||||
if(!isInited){
|
||||
rs.initiate({
|
||||
_id: "rs0",
|
||||
members: [
|
||||
{ _id: 0, host: "mongo:27017" }
|
||||
]
|
||||
})
|
||||
}' > /data/initReplicaSet.js
|
||||
# 启动MongoDB服务
|
||||
exec docker-entrypoint.sh "$$@" &
|
||||
|
||||
# 等待MongoDB服务启动
|
||||
until mongo -u myusername -p mypassword --authenticationDatabase admin --eval "print('waited for connection')"; do
|
||||
echo "Waiting for MongoDB to start..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# 执行初始化副本集的脚本
|
||||
mongo -u myusername -p mypassword --authenticationDatabase admin /data/initReplicaSet.js
|
||||
|
||||
# 等待docker-entrypoint.sh脚本执行的MongoDB服务进程
|
||||
wait $$!
|
||||
redis:
|
||||
image: redis:7.2-alpine
|
||||
container_name: redis
|
||||
networks:
|
||||
- fastgpt
|
||||
restart: always
|
||||
command: |
|
||||
redis-server --requirepass mypassword --loglevel warning --maxclients 10000 --appendonly yes --save 60 10 --maxmemory 4gb --maxmemory-policy noeviction
|
||||
healthcheck:
|
||||
test: ['CMD', 'redis-cli', '-a', 'mypassword', 'ping']
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
volumes:
|
||||
- ./redis/data:/data
|
||||
fastgpt-minio:
|
||||
image: minio/minio:latest
|
||||
container_name: fastgpt-minio
|
||||
restart: always
|
||||
networks:
|
||||
- fastgpt
|
||||
ports: # comment out if you do not need to expose the port (in production environment, you should not expose the port)
|
||||
- '9000:9000'
|
||||
- '9001:9001'
|
||||
environment:
|
||||
- MINIO_ROOT_USER=minioadmin
|
||||
- MINIO_ROOT_PASSWORD=minioadmin
|
||||
volumes:
|
||||
- ./fastgpt-minio:/data
|
||||
command: server /data --console-address ":9001"
|
||||
healthcheck:
|
||||
test: ['CMD', 'curl', '-f', 'http://localhost:9000/minio/health/live']
|
||||
interval: 30s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
|
||||
fastgpt:
|
||||
container_name: fastgpt
|
||||
image: ghcr.io/labring/fastgpt:v4.12.1-fix # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.12.1-fix # 阿里云
|
||||
ports:
|
||||
- 3000:3000
|
||||
networks:
|
||||
- fastgpt
|
||||
depends_on:
|
||||
- mongo
|
||||
- sandbox
|
||||
|
||||
restart: always
|
||||
environment:
|
||||
# 前端外部可访问的地址,用于自动补全文件资源路径。例如 https:fastgpt.cn,不能填 localhost。这个值可以不填,不填则发给模型的图片会是一个相对路径,而不是全路径,模型可能伪造Host。
|
||||
- FE_DOMAIN=
|
||||
# root 密码,用户名为: root。如果需要修改 root 密码,直接修改这个环境变量,并重启即可。
|
||||
- DEFAULT_ROOT_PSW=1234
|
||||
# 登录凭证密钥
|
||||
- TOKEN_KEY=any
|
||||
# root的密钥,常用于升级时候的初始化请求
|
||||
- ROOT_KEY=root_key
|
||||
# 文件阅读加密
|
||||
- FILE_TOKEN_KEY=filetoken
|
||||
# 密钥加密key
|
||||
- AES256_SECRET_KEY=fastgptkey
|
||||
|
||||
# plugin 地址
|
||||
- PLUGIN_BASE_URL=http://fastgpt-plugin:3000
|
||||
- PLUGIN_TOKEN=xxxxxx
|
||||
# sandbox 地址
|
||||
- SANDBOX_URL=http://sandbox:3000
|
||||
# AI Proxy 的地址,如果配了该地址,优先使用
|
||||
- AIPROXY_API_ENDPOINT=http://aiproxy:3000
|
||||
# AI Proxy 的 Admin Token,与 AI Proxy 中的环境变量 ADMIN_KEY
|
||||
- AIPROXY_API_TOKEN=aiproxy
|
||||
|
||||
# 数据库最大连接数
|
||||
- DB_MAX_LINK=30
|
||||
# MongoDB 连接参数. 用户名myusername,密码mypassword。
|
||||
- MONGODB_URI=mongodb://myusername:mypassword@mongo:27017/fastgpt?authSource=admin
|
||||
# Redis 连接参数
|
||||
- REDIS_URL=redis://default:mypassword@redis:6379
|
||||
# 向量库 连接参数
|
||||
# zilliz 连接参数
|
||||
- MILVUS_ADDRESS=zilliz_cloud_address
|
||||
- MILVUS_TOKEN=zilliz_cloud_token
|
||||
|
||||
# 日志等级: debug, info, warn, error
|
||||
- LOG_LEVEL=info
|
||||
- STORE_LOG_LEVEL=warn
|
||||
# 工作流最大运行次数
|
||||
- WORKFLOW_MAX_RUN_TIMES=1000
|
||||
# 批量执行节点,最大输入长度
|
||||
- WORKFLOW_MAX_LOOP_TIMES=100
|
||||
# 对话文件过期天数
|
||||
- CHAT_FILE_EXPIRE_TIME=7
|
||||
volumes:
|
||||
- ./config.json:/app/data/config.json
|
||||
sandbox:
|
||||
container_name: sandbox
|
||||
image: ghcr.io/labring/fastgpt-sandbox:v4.12.1 # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.12.1 # 阿里云
|
||||
networks:
|
||||
- fastgpt
|
||||
restart: always
|
||||
fastgpt-mcp-server:
|
||||
container_name: fastgpt-mcp-server
|
||||
image: ghcr.io/labring/fastgpt-mcp_server:v4.12.1 # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-mcp_server:v4.12.1 # 阿里云
|
||||
ports:
|
||||
- 3005:3000
|
||||
networks:
|
||||
- fastgpt
|
||||
restart: always
|
||||
environment:
|
||||
- FASTGPT_ENDPOINT=http://fastgpt:3000
|
||||
fastgpt-plugin:
|
||||
image: ghcr.io/labring/fastgpt-plugin:v0.1.10 # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-plugin:v0.1.10 # 阿里云
|
||||
container_name: fastgpt-plugin
|
||||
restart: always
|
||||
networks:
|
||||
- fastgpt
|
||||
environment:
|
||||
- AUTH_TOKEN=xxxxxx # 如果不需要鉴权可以直接去掉这个环境变量
|
||||
|
||||
# 改成 minio 可访问地址,例如 http://192.168.2.2:9000/fastgpt-plugins
|
||||
# 必须指向 Minio 的桶的地址
|
||||
# 如果 Minio 可以直接通过外网访问,可以不设置这个环境变量
|
||||
# - MINIO_CUSTOM_ENDPOINT=http://192.168.2.2:9000
|
||||
|
||||
- MINIO_ENDPOINT=fastgpt-minio
|
||||
- MINIO_PORT=9000
|
||||
- MINIO_USE_SSL=false
|
||||
- MINIO_ACCESS_KEY=minioadmin
|
||||
- MINIO_SECRET_KEY=minioadmin
|
||||
- MINIO_BUCKET=fastgpt-plugins
|
||||
depends_on:
|
||||
fastgpt-minio:
|
||||
condition: service_healthy
|
||||
|
||||
# AI Proxy
|
||||
aiproxy:
|
||||
image: ghcr.io/labring/aiproxy:v0.2.2
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/labring/aiproxy:v0.2.2 # 阿里云
|
||||
container_name: aiproxy
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
aiproxy_pg:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- fastgpt
|
||||
environment:
|
||||
# 对应 fastgpt 里的AIPROXY_API_TOKEN
|
||||
- ADMIN_KEY=aiproxy
|
||||
# 错误日志详情保存时间(小时)
|
||||
- LOG_DETAIL_STORAGE_HOURS=1
|
||||
# 数据库连接地址
|
||||
- SQL_DSN=postgres://postgres:aiproxy@aiproxy_pg:5432/aiproxy
|
||||
# 最大重试次数
|
||||
- RETRY_TIMES=3
|
||||
# 不需要计费
|
||||
- BILLING_ENABLED=false
|
||||
# 不需要严格检测模型
|
||||
- DISABLE_MODEL_CONFIG=true
|
||||
healthcheck:
|
||||
test: ['CMD', 'curl', '-f', 'http://localhost:3000/api/status']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
aiproxy_pg:
|
||||
image: pgvector/pgvector:0.8.0-pg15 # docker hub
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/pgvector:v0.8.0-pg15 # 阿里云
|
||||
restart: unless-stopped
|
||||
container_name: aiproxy_pg
|
||||
volumes:
|
||||
- ./aiproxy_pg:/var/lib/postgresql/data
|
||||
networks:
|
||||
- fastgpt
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_DB: aiproxy
|
||||
POSTGRES_PASSWORD: aiproxy
|
||||
healthcheck:
|
||||
test: ['CMD', 'pg_isready', '-U', 'postgres', '-d', 'aiproxy']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
networks:
|
||||
fastgpt:
|
||||
19
deploy/docker/run.sh
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
docker-compose pull
|
||||
docker-compose up -d
|
||||
|
||||
echo "Docker Compose 重新拉取镜像完成!"
|
||||
|
||||
# 删除本地旧镜像
|
||||
images=$(docker images --format "{{.ID}} {{.Repository}}" | grep fastgpt)
|
||||
|
||||
# 将镜像 ID 和名称放入数组中
|
||||
IFS=$'\n' read -rd '' -a image_array <<<"$images"
|
||||
|
||||
# 遍历数组并删除所有旧的镜像
|
||||
for ((i=1; i<${#image_array[@]}; i++))
|
||||
do
|
||||
image=${image_array[$i]}
|
||||
image_id=${image%% *}
|
||||
docker rmi $image_id
|
||||
done
|
||||
398
deploy/docker/yml.js
Normal file
@@ -0,0 +1,398 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const template = `# 数据库的默认账号和密码仅首次运行时设置有效
|
||||
# 如果修改了账号密码,记得改数据库和项目连接参数,别只改一处~
|
||||
# 该配置文件只是给快速启动,测试使用。正式使用,记得务必修改账号密码,以及调整合适的知识库参数,共享内存等。
|
||||
# 如何无法访问 dockerhub 和 git,可以用阿里云(阿里云没有arm包)
|
||||
|
||||
version: '3.3'
|
||||
services:
|
||||
# Vector DB
|
||||
{{Vector_DB_Service}}
|
||||
|
||||
# DB
|
||||
mongo:
|
||||
image: mongo:5.0.18 # dockerhub
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/mongo:5.0.18 # 阿里云
|
||||
# image: mongo:4.4.29 # cpu不支持AVX时候使用
|
||||
container_name: mongo
|
||||
restart: always
|
||||
networks:
|
||||
- fastgpt
|
||||
command: mongod --keyFile /data/mongodb.key --replSet rs0
|
||||
environment:
|
||||
- MONGO_INITDB_ROOT_USERNAME=myusername
|
||||
- MONGO_INITDB_ROOT_PASSWORD=mypassword
|
||||
volumes:
|
||||
- ./mongo/data:/data/db
|
||||
entrypoint:
|
||||
- bash
|
||||
- -c
|
||||
- |
|
||||
openssl rand -base64 128 > /data/mongodb.key
|
||||
chmod 400 /data/mongodb.key
|
||||
chown 999:999 /data/mongodb.key
|
||||
echo 'const isInited = rs.status().ok === 1
|
||||
if(!isInited){
|
||||
rs.initiate({
|
||||
_id: "rs0",
|
||||
members: [
|
||||
{ _id: 0, host: "mongo:27017" }
|
||||
]
|
||||
})
|
||||
}' > /data/initReplicaSet.js
|
||||
# 启动MongoDB服务
|
||||
exec docker-entrypoint.sh "$$@" &
|
||||
|
||||
# 等待MongoDB服务启动
|
||||
until mongo -u myusername -p mypassword --authenticationDatabase admin --eval "print('waited for connection')"; do
|
||||
echo "Waiting for MongoDB to start..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# 执行初始化副本集的脚本
|
||||
mongo -u myusername -p mypassword --authenticationDatabase admin /data/initReplicaSet.js
|
||||
|
||||
# 等待docker-entrypoint.sh脚本执行的MongoDB服务进程
|
||||
wait $$!
|
||||
redis:
|
||||
image: redis:7.2-alpine
|
||||
container_name: redis
|
||||
networks:
|
||||
- fastgpt
|
||||
restart: always
|
||||
command: |
|
||||
redis-server --requirepass mypassword --loglevel warning --maxclients 10000 --appendonly yes --save 60 10 --maxmemory 4gb --maxmemory-policy noeviction
|
||||
healthcheck:
|
||||
test: ['CMD', 'redis-cli', '-a', 'mypassword', 'ping']
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
volumes:
|
||||
- ./redis/data:/data
|
||||
fastgpt-minio:
|
||||
image: minio/minio:latest
|
||||
container_name: fastgpt-minio
|
||||
restart: always
|
||||
networks:
|
||||
- fastgpt
|
||||
ports: # comment out if you do not need to expose the port (in production environment, you should not expose the port)
|
||||
- '9000:9000'
|
||||
- '9001:9001'
|
||||
environment:
|
||||
- MINIO_ROOT_USER=minioadmin
|
||||
- MINIO_ROOT_PASSWORD=minioadmin
|
||||
volumes:
|
||||
- ./fastgpt-minio:/data
|
||||
command: server /data --console-address ":9001"
|
||||
healthcheck:
|
||||
test: ['CMD', 'curl', '-f', 'http://localhost:9000/minio/health/live']
|
||||
interval: 30s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
|
||||
fastgpt:
|
||||
container_name: fastgpt
|
||||
image: ghcr.io/labring/fastgpt:v4.12.1-fix # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.12.1-fix # 阿里云
|
||||
ports:
|
||||
- 3000:3000
|
||||
networks:
|
||||
- fastgpt
|
||||
depends_on:
|
||||
- mongo
|
||||
- sandbox
|
||||
{{Vector_DB_Depends}}
|
||||
restart: always
|
||||
environment:
|
||||
# 前端外部可访问的地址,用于自动补全文件资源路径。例如 https:fastgpt.cn,不能填 localhost。这个值可以不填,不填则发给模型的图片会是一个相对路径,而不是全路径,模型可能伪造Host。
|
||||
- FE_DOMAIN=
|
||||
# root 密码,用户名为: root。如果需要修改 root 密码,直接修改这个环境变量,并重启即可。
|
||||
- DEFAULT_ROOT_PSW=1234
|
||||
# 登录凭证密钥
|
||||
- TOKEN_KEY=any
|
||||
# root的密钥,常用于升级时候的初始化请求
|
||||
- ROOT_KEY=root_key
|
||||
# 文件阅读加密
|
||||
- FILE_TOKEN_KEY=filetoken
|
||||
# 密钥加密key
|
||||
- AES256_SECRET_KEY=fastgptkey
|
||||
|
||||
# plugin 地址
|
||||
- PLUGIN_BASE_URL=http://fastgpt-plugin:3000
|
||||
- PLUGIN_TOKEN=xxxxxx
|
||||
# sandbox 地址
|
||||
- SANDBOX_URL=http://sandbox:3000
|
||||
# AI Proxy 的地址,如果配了该地址,优先使用
|
||||
- AIPROXY_API_ENDPOINT=http://aiproxy:3000
|
||||
# AI Proxy 的 Admin Token,与 AI Proxy 中的环境变量 ADMIN_KEY
|
||||
- AIPROXY_API_TOKEN=aiproxy
|
||||
|
||||
# 数据库最大连接数
|
||||
- DB_MAX_LINK=30
|
||||
# MongoDB 连接参数. 用户名myusername,密码mypassword。
|
||||
- MONGODB_URI=mongodb://myusername:mypassword@mongo:27017/fastgpt?authSource=admin
|
||||
# Redis 连接参数
|
||||
- REDIS_URL=redis://default:mypassword@redis:6379
|
||||
# 向量库 连接参数
|
||||
{{Vector_DB_ENV}}
|
||||
|
||||
# 日志等级: debug, info, warn, error
|
||||
- LOG_LEVEL=info
|
||||
- STORE_LOG_LEVEL=warn
|
||||
# 工作流最大运行次数
|
||||
- WORKFLOW_MAX_RUN_TIMES=1000
|
||||
# 批量执行节点,最大输入长度
|
||||
- WORKFLOW_MAX_LOOP_TIMES=100
|
||||
# 对话文件过期天数
|
||||
- CHAT_FILE_EXPIRE_TIME=7
|
||||
volumes:
|
||||
- ./config.json:/app/data/config.json
|
||||
sandbox:
|
||||
container_name: sandbox
|
||||
image: ghcr.io/labring/fastgpt-sandbox:v4.12.1 # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.12.1 # 阿里云
|
||||
networks:
|
||||
- fastgpt
|
||||
restart: always
|
||||
fastgpt-mcp-server:
|
||||
container_name: fastgpt-mcp-server
|
||||
image: ghcr.io/labring/fastgpt-mcp_server:v4.12.1 # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-mcp_server:v4.12.1 # 阿里云
|
||||
ports:
|
||||
- 3005:3000
|
||||
networks:
|
||||
- fastgpt
|
||||
restart: always
|
||||
environment:
|
||||
- FASTGPT_ENDPOINT=http://fastgpt:3000
|
||||
fastgpt-plugin:
|
||||
image: ghcr.io/labring/fastgpt-plugin:v0.1.10 # git
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-plugin:v0.1.10 # 阿里云
|
||||
container_name: fastgpt-plugin
|
||||
restart: always
|
||||
networks:
|
||||
- fastgpt
|
||||
environment:
|
||||
- AUTH_TOKEN=xxxxxx # 如果不需要鉴权可以直接去掉这个环境变量
|
||||
|
||||
# 改成 minio 可访问地址,例如 http://192.168.2.2:9000/fastgpt-plugins
|
||||
# 必须指向 Minio 的桶的地址
|
||||
# 如果 Minio 可以直接通过外网访问,可以不设置这个环境变量
|
||||
# - MINIO_CUSTOM_ENDPOINT=http://192.168.2.2:9000
|
||||
|
||||
- MINIO_ENDPOINT=fastgpt-minio
|
||||
- MINIO_PORT=9000
|
||||
- MINIO_USE_SSL=false
|
||||
- MINIO_ACCESS_KEY=minioadmin
|
||||
- MINIO_SECRET_KEY=minioadmin
|
||||
- MINIO_BUCKET=fastgpt-plugins
|
||||
depends_on:
|
||||
fastgpt-minio:
|
||||
condition: service_healthy
|
||||
|
||||
# AI Proxy
|
||||
aiproxy:
|
||||
image: ghcr.io/labring/aiproxy:v0.2.2
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/labring/aiproxy:v0.2.2 # 阿里云
|
||||
container_name: aiproxy
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
aiproxy_pg:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- fastgpt
|
||||
environment:
|
||||
# 对应 fastgpt 里的AIPROXY_API_TOKEN
|
||||
- ADMIN_KEY=aiproxy
|
||||
# 错误日志详情保存时间(小时)
|
||||
- LOG_DETAIL_STORAGE_HOURS=1
|
||||
# 数据库连接地址
|
||||
- SQL_DSN=postgres://postgres:aiproxy@aiproxy_pg:5432/aiproxy
|
||||
# 最大重试次数
|
||||
- RETRY_TIMES=3
|
||||
# 不需要计费
|
||||
- BILLING_ENABLED=false
|
||||
# 不需要严格检测模型
|
||||
- DISABLE_MODEL_CONFIG=true
|
||||
healthcheck:
|
||||
test: ['CMD', 'curl', '-f', 'http://localhost:3000/api/status']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
aiproxy_pg:
|
||||
image: pgvector/pgvector:0.8.0-pg15 # docker hub
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/pgvector:v0.8.0-pg15 # 阿里云
|
||||
restart: unless-stopped
|
||||
container_name: aiproxy_pg
|
||||
volumes:
|
||||
- ./aiproxy_pg:/var/lib/postgresql/data
|
||||
networks:
|
||||
- fastgpt
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_DB: aiproxy
|
||||
POSTGRES_PASSWORD: aiproxy
|
||||
healthcheck:
|
||||
test: ['CMD', 'pg_isready', '-U', 'postgres', '-d', 'aiproxy']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
networks:
|
||||
fastgpt:
|
||||
`;
|
||||
|
||||
const list = [
|
||||
{
|
||||
filename: './docker-compose-pgvector.yml',
|
||||
depends: `- pg`,
|
||||
service: `pg:
|
||||
image: pgvector/pgvector:0.8.0-pg15 # docker hub
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/pgvector:v0.8.0-pg15 # 阿里云
|
||||
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
|
||||
healthcheck:
|
||||
test: ['CMD', 'pg_isready', '-U', 'username', '-d', 'postgres']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10`,
|
||||
env: `- PG_URL=postgresql://username:password@pg:5432/postgres`
|
||||
},
|
||||
{
|
||||
filename: './docker-compose-zilliz.yml',
|
||||
depends: ``,
|
||||
service: ``,
|
||||
env: `# zilliz 连接参数
|
||||
- MILVUS_ADDRESS=zilliz_cloud_address
|
||||
- MILVUS_TOKEN=zilliz_cloud_token`
|
||||
},
|
||||
{
|
||||
filename: './docker-compose-milvus.yml',
|
||||
depends: `- milvusStandalone`,
|
||||
service: `milvus-minio:
|
||||
container_name: milvus-minio
|
||||
image: minio/minio:RELEASE.2023-03-20T20-16-18Z
|
||||
environment:
|
||||
MINIO_ACCESS_KEY: minioadmin
|
||||
MINIO_SECRET_KEY: minioadmin
|
||||
# ports:
|
||||
# - '9001:9001'
|
||||
# - '9000:9000'
|
||||
networks:
|
||||
- fastgpt
|
||||
volumes:
|
||||
- ./milvus-minio:/minio_data
|
||||
command: minio server /minio_data --console-address ":9001"
|
||||
healthcheck:
|
||||
test: ['CMD', 'curl', '-f', 'http://localhost:9000/minio/health/live']
|
||||
interval: 30s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
# milvus
|
||||
milvusEtcd:
|
||||
container_name: milvusEtcd
|
||||
image: quay.io/coreos/etcd:v3.5.5
|
||||
environment:
|
||||
- ETCD_AUTO_COMPACTION_MODE=revision
|
||||
- ETCD_AUTO_COMPACTION_RETENTION=1000
|
||||
- ETCD_QUOTA_BACKEND_BYTES=4294967296
|
||||
- ETCD_SNAPSHOT_COUNT=50000
|
||||
networks:
|
||||
- fastgpt
|
||||
volumes:
|
||||
- ./milvus/etcd:/etcd
|
||||
command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
|
||||
healthcheck:
|
||||
test: ['CMD', 'etcdctl', 'endpoint', 'health']
|
||||
interval: 30s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
milvusStandalone:
|
||||
container_name: milvusStandalone
|
||||
image: milvusdb/milvus:v2.4.3
|
||||
command: ['milvus', 'run', 'standalone']
|
||||
security_opt:
|
||||
- seccomp:unconfined
|
||||
environment:
|
||||
ETCD_ENDPOINTS: milvusEtcd:2379
|
||||
MINIO_ADDRESS: milvus-minio:9000
|
||||
networks:
|
||||
- fastgpt
|
||||
volumes:
|
||||
- ./milvus/data:/var/lib/milvus
|
||||
healthcheck:
|
||||
test: ['CMD', 'curl', '-f', 'http://localhost:9091/healthz']
|
||||
interval: 30s
|
||||
start_period: 90s
|
||||
timeout: 20s
|
||||
retries: 3
|
||||
depends_on:
|
||||
- 'milvusEtcd'
|
||||
- 'milvus-minio'`,
|
||||
env: `- MILVUS_ADDRESS=http://milvusStandalone:19530
|
||||
- MILVUS_TOKEN=none`
|
||||
},
|
||||
{
|
||||
filename: './docker-compose-oceanbase/docker-compose.yml',
|
||||
depends: `- ob`,
|
||||
service: `ob:
|
||||
image: oceanbase/oceanbase-ce:4.3.5-lts # docker hub
|
||||
# image: quay.io/oceanbase/oceanbase-ce:4.3.5-lts # 镜像
|
||||
container_name: ob
|
||||
restart: always
|
||||
# ports: # 生产环境建议不要暴露
|
||||
# - 2881:2881
|
||||
networks:
|
||||
- fastgpt
|
||||
environment:
|
||||
# 这里的配置只有首次运行生效。修改后,重启镜像是不会生效的。需要把持久化数据删除再重启,才有效果
|
||||
- OB_SYS_PASSWORD=obsyspassword
|
||||
# 不同于传统数据库,OceanBase 数据库的账号包含更多字段,包括用户名、租户名和集群名。经典格式为"用户名@租户名#集群名"
|
||||
# 比如用mysql客户端连接时,根据本文件的默认配置,应该指定 "-uroot@tenantname"
|
||||
- OB_TENANT_NAME=tenantname
|
||||
- OB_TENANT_PASSWORD=tenantpassword
|
||||
# MODE分为MINI和NORMAL, 后者会最大程度使用主机资源
|
||||
- MODE=MINI
|
||||
- OB_SERVER_IP=127.0.0.1
|
||||
# 更多环境变量配置见oceanbase官方文档: https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000002013494
|
||||
volumes:
|
||||
- ./ob/data:/root/ob
|
||||
- ./ob/config:/root/.obd/cluster
|
||||
- ./init.sql:/root/boot/init.d/init.sql
|
||||
healthcheck:
|
||||
# obclient -h127.0.0.1 -P2881 -uroot@tenantname -ptenantpassword -e "SELECT 1;"
|
||||
test:
|
||||
[
|
||||
'CMD-SHELL',
|
||||
'obclient -h\$\$\$\${OB_SERVER_IP} -P2881 -uroot@\$\$\$\${OB_TENANT_NAME} -p\$\$\$\${OB_TENANT_PASSWORD} -e "SELECT 1;"'
|
||||
]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 1000
|
||||
start_period: 10s`,
|
||||
env: `- OCEANBASE_URL=mysql://root%40tenantname:tenantpassword@ob:2881/test`
|
||||
}
|
||||
];
|
||||
|
||||
list.forEach((item) => {
|
||||
const { filename, service, env, depends } = item;
|
||||
const content = template
|
||||
.replace('{{Vector_DB_Service}}', service)
|
||||
.replace('{{Vector_DB_ENV}}', env)
|
||||
.replace('{{Vector_DB_Depends}}', depends);
|
||||
fs.writeFileSync(path.join(__dirname, filename), content, 'utf-8');
|
||||
});
|
||||
23
deploy/helm/fastgpt/.helmignore
Normal file
@@ -0,0 +1,23 @@
|
||||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*.orig
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
.vscode/
|
||||
9
deploy/helm/fastgpt/Chart.lock
Normal file
@@ -0,0 +1,9 @@
|
||||
dependencies:
|
||||
- name: mongodb
|
||||
repository: oci://registry-1.docker.io/bitnamicharts
|
||||
version: 15.0.1
|
||||
- name: postgresql
|
||||
repository: oci://registry-1.docker.io/bitnamicharts
|
||||
version: 15.0.0
|
||||
digest: sha256:eaee52dc30a5f0e8e65e30a99240707c8493fa2773a4afcfb54d286fb4fa6306
|
||||
generated: "2024-03-19T13:47:47.7518066+08:00"
|
||||
32
deploy/helm/fastgpt/Chart.yaml
Normal file
@@ -0,0 +1,32 @@
|
||||
apiVersion: v2
|
||||
name: fastgpt
|
||||
description: A Helm chart for FastGPT
|
||||
|
||||
# A chart can be either an 'application' or a 'library' chart.
|
||||
#
|
||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
||||
# to be deployed.
|
||||
#
|
||||
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
||||
# a dependency of application charts to inject those utilities and functions into the rendering
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.1.0
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "v4.6.6"
|
||||
|
||||
dependencies:
|
||||
- name: mongodb
|
||||
version: 15.0.1
|
||||
repository: oci://registry-1.docker.io/bitnamicharts
|
||||
- name: postgresql
|
||||
version: 15.0.0
|
||||
repository: oci://registry-1.docker.io/bitnamicharts
|
||||
67
deploy/helm/fastgpt/README.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# fastgpt
|
||||
|
||||
  
|
||||
|
||||
A Helm chart for FastGPT
|
||||
|
||||
## Requirements
|
||||
|
||||
| Repository | Name | Version |
|
||||
|------------|------|---------|
|
||||
| oci://registry-1.docker.io/bitnamicharts | mongodb | 15.0.1 |
|
||||
| oci://registry-1.docker.io/bitnamicharts | postgresql | 15.0.0 |
|
||||
|
||||
## Values
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
|-----|------|---------|-------------|
|
||||
| affinity | object | `{}` | |
|
||||
| autoscaling.enabled | bool | `false` | |
|
||||
| autoscaling.maxReplicas | int | `100` | |
|
||||
| autoscaling.minReplicas | int | `1` | |
|
||||
| autoscaling.targetCPUUtilizationPercentage | int | `80` | |
|
||||
| fullnameOverride | string | `""` | |
|
||||
| image.pullPolicy | string | `"IfNotPresent"` | |
|
||||
| image.repository | string | `"ghcr.io/labring/fastgpt"` | |
|
||||
| image.tag | string | `""` | |
|
||||
| imagePullSecrets | list | `[]` | |
|
||||
| ingress.annotations | object | `{}` | |
|
||||
| ingress.className | string | `""` | |
|
||||
| ingress.enabled | bool | `false` | |
|
||||
| ingress.hosts[0].host | string | `"chart-example.local"` | |
|
||||
| ingress.hosts[0].paths[0].path | string | `"/"` | |
|
||||
| ingress.hosts[0].paths[0].pathType | string | `"ImplementationSpecific"` | |
|
||||
| ingress.tls | list | `[]` | |
|
||||
| livenessProbe.httpGet.path | string | `"/"` | |
|
||||
| livenessProbe.httpGet.port | string | `"http"` | |
|
||||
| mongodb.architecture | string | `"replicaset"` | |
|
||||
| mongodb.auth.rootPassword | string | `"123456"` | |
|
||||
| mongodb.auth.rootUser | string | `"root"` | |
|
||||
| mongodb.enabled | bool | `true` | Enable or disable the built-in MangoDB |
|
||||
| nameOverride | string | `""` | |
|
||||
| nodeSelector | object | `{}` | |
|
||||
| podAnnotations | object | `{}` | |
|
||||
| podLabels | object | `{}` | |
|
||||
| podSecurityContext | object | `{}` | |
|
||||
| postgresql.enabled | bool | `true` | Enable or disable the built-in PostgreSQL |
|
||||
| postgresql.global.postgresql.auth.database | string | `"postgres"` | The default database of PostgreSQL |
|
||||
| postgresql.global.postgresql.auth.postgresPassword | string | `"postgres"` | The password of PostgreSQL, default username is `postgres` |
|
||||
| postgresql.image.repository | string | `"linuxsuren/pgvector"` | The PostgreSQL image which include the pgvector extension. See also the source code from https://github.com/LinuxSuRen/pgvector-docker |
|
||||
| postgresql.image.tag | string | `"v0.0.1"` | |
|
||||
| readinessProbe.httpGet.path | string | `"/"` | |
|
||||
| readinessProbe.httpGet.port | string | `"http"` | |
|
||||
| replicaCount | int | `1` | |
|
||||
| resources | object | `{}` | |
|
||||
| securityContext | object | `{}` | |
|
||||
| service.port | int | `3000` | |
|
||||
| service.type | string | `"ClusterIP"` | |
|
||||
| serviceAccount.annotations | object | `{}` | |
|
||||
| serviceAccount.automount | bool | `true` | |
|
||||
| serviceAccount.create | bool | `true` | |
|
||||
| serviceAccount.name | string | `""` | |
|
||||
| tolerations | list | `[]` | |
|
||||
| volumeMounts | list | `[]` | |
|
||||
| volumes | list | `[]` | |
|
||||
|
||||
----------------------------------------------
|
||||
Autogenerated from chart metadata using [helm-docs v1.13.1](https://github.com/norwoodj/helm-docs/releases/v1.13.1)
|
||||
22
deploy/helm/fastgpt/templates/NOTES.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
1. Get the application URL by running these commands:
|
||||
{{- if .Values.ingress.enabled }}
|
||||
{{- range $host := .Values.ingress.hosts }}
|
||||
{{- range .paths }}
|
||||
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- else if contains "NodePort" .Values.service.type }}
|
||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "fastgpt.fullname" . }})
|
||||
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||
echo http://$NODE_IP:$NODE_PORT
|
||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "fastgpt.fullname" . }}'
|
||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "fastgpt.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
||||
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "fastgpt.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
||||
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
||||
echo "Visit http://127.0.0.1:8080 to use your application"
|
||||
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
||||
{{- end }}
|
||||
62
deploy/helm/fastgpt/templates/_helpers.tpl
Normal file
@@ -0,0 +1,62 @@
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "fastgpt.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "fastgpt.fullname" -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "fastgpt.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "fastgpt.labels" -}}
|
||||
helm.sh/chart: {{ include "fastgpt.chart" . }}
|
||||
{{ include "fastgpt.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "fastgpt.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "fastgpt.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "fastgpt.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
{{- default (include "fastgpt.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else }}
|
||||
{{- default "default" .Values.serviceAccount.name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
178
deploy/helm/fastgpt/templates/configmap-config.yaml
Normal file
@@ -0,0 +1,178 @@
|
||||
apiVersion: v1
|
||||
data:
|
||||
config.json: |
|
||||
{
|
||||
"systemEnv": {
|
||||
"openapiPrefix": "fastgpt",
|
||||
"vectorMaxProcess": 15,
|
||||
"qaMaxProcess": 15,
|
||||
"vlmMaxProcess": 15,
|
||||
"hnswEfSearch": 100
|
||||
},
|
||||
"llmModels": [
|
||||
{
|
||||
"model": "gpt-3.5-turbo",
|
||||
"name": "gpt-3.5-turbo",
|
||||
"maxContext": 16000,
|
||||
"maxResponse": 4000,
|
||||
"quoteMaxToken": 13000,
|
||||
"maxTemperature": 1.2,
|
||||
"charsPointsPrice": 0,
|
||||
"censor": false,
|
||||
"vision": false,
|
||||
"datasetProcess": true,
|
||||
"usedInClassify": true,
|
||||
"usedInExtractFields": true,
|
||||
"usedInToolCall": true,
|
||||
"toolChoice": true,
|
||||
"functionCall": false,
|
||||
"defaultSystemChatPrompt": "",
|
||||
"defaultConfig": {}
|
||||
},
|
||||
{
|
||||
"model": "gpt-3.5-turbo-16k",
|
||||
"name": "gpt-3.5-turbo-16k",
|
||||
"maxContext": 16000,
|
||||
"maxResponse": 16000,
|
||||
"quoteMaxToken": 13000,
|
||||
"maxTemperature": 1.2,
|
||||
"charsPointsPrice": 0,
|
||||
"censor": false,
|
||||
"vision": false,
|
||||
"datasetProcess": true,
|
||||
"usedInClassify": true,
|
||||
"usedInExtractFields": true,
|
||||
"usedInToolCall": true,
|
||||
"toolChoice": true,
|
||||
"functionCall": false,
|
||||
"defaultSystemChatPrompt": "",
|
||||
"defaultConfig": {}
|
||||
},
|
||||
{
|
||||
"model": "gpt-4-0125-preview",
|
||||
"name": "gpt-4-turbo",
|
||||
"maxContext": 125000,
|
||||
"maxResponse": 4000,
|
||||
"quoteMaxToken": 100000,
|
||||
"maxTemperature": 1.2,
|
||||
"charsPointsPrice": 0,
|
||||
"censor": false,
|
||||
"vision": false,
|
||||
"datasetProcess": true,
|
||||
"usedInClassify": true,
|
||||
"usedInExtractFields": true,
|
||||
"usedInToolCall": true,
|
||||
"toolChoice": true,
|
||||
"functionCall": false,
|
||||
"defaultSystemChatPrompt": "",
|
||||
"defaultConfig": {}
|
||||
},
|
||||
{
|
||||
"model": "gpt-4-vision-preview",
|
||||
"name": "gpt-4-vision",
|
||||
"maxContext": 128000,
|
||||
"maxResponse": 4000,
|
||||
"quoteMaxToken": 100000,
|
||||
"maxTemperature": 1.2,
|
||||
"charsPointsPrice": 0,
|
||||
"censor": false,
|
||||
"vision": true,
|
||||
"datasetProcess": true,
|
||||
"usedInClassify": false,
|
||||
"usedInExtractFields": false,
|
||||
"usedInToolCall": false,
|
||||
"toolChoice": true,
|
||||
"functionCall": false,
|
||||
"defaultSystemChatPrompt": "",
|
||||
"defaultConfig": {}
|
||||
}
|
||||
],
|
||||
"vectorModels": [
|
||||
{
|
||||
"model": "text-embedding-3-large",
|
||||
"name": "Embedding-2",
|
||||
"avatar": "/imgs/model/openai.svg",
|
||||
"charsPointsPrice": 0,
|
||||
"defaultToken": 512,
|
||||
"maxToken": 3000,
|
||||
"weight": 100,
|
||||
"dbConfig": {},
|
||||
"queryConfig": {},
|
||||
"defaultConfig": {
|
||||
"dimensions": 1024
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "text-embedding-3-small",
|
||||
"name": "Embedding-2",
|
||||
"avatar": "/imgs/model/openai.svg",
|
||||
"charsPointsPrice": 0,
|
||||
"defaultToken": 512,
|
||||
"maxToken": 3000,
|
||||
"weight": 100,
|
||||
"dbConfig": {},
|
||||
"queryConfig": {}
|
||||
},
|
||||
{
|
||||
"model": "text-embedding-ada-002",
|
||||
"name": "Embedding-2",
|
||||
"avatar": "/imgs/model/openai.svg",
|
||||
"charsPointsPrice": 0,
|
||||
"defaultToken": 512,
|
||||
"maxToken": 3000,
|
||||
"weight": 100,
|
||||
"dbConfig": {},
|
||||
"queryConfig": {}
|
||||
}
|
||||
],
|
||||
"reRankModels": [],
|
||||
"audioSpeechModels": [
|
||||
{
|
||||
"model": "tts-1",
|
||||
"name": "OpenAI TTS1",
|
||||
"charsPointsPrice": 0,
|
||||
"voices": [
|
||||
{
|
||||
"label": "Alloy",
|
||||
"value": "alloy",
|
||||
"bufferId": "openai-Alloy"
|
||||
},
|
||||
{
|
||||
"label": "Echo",
|
||||
"value": "echo",
|
||||
"bufferId": "openai-Echo"
|
||||
},
|
||||
{
|
||||
"label": "Fable",
|
||||
"value": "fable",
|
||||
"bufferId": "openai-Fable"
|
||||
},
|
||||
{
|
||||
"label": "Onyx",
|
||||
"value": "onyx",
|
||||
"bufferId": "openai-Onyx"
|
||||
},
|
||||
{
|
||||
"label": "Nova",
|
||||
"value": "nova",
|
||||
"bufferId": "openai-Nova"
|
||||
},
|
||||
{
|
||||
"label": "Shimmer",
|
||||
"value": "shimmer",
|
||||
"bufferId": "openai-Shimmer"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"whisperModel": {
|
||||
"model": "whisper-1",
|
||||
"name": "Whisper1",
|
||||
"charsPointsPrice": 0
|
||||
}
|
||||
}
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
{{ include "fastgpt.labels" . | nindent 4 }}
|
||||
name: {{ include "fastgpt.fullname" . }}-config
|
||||
67
deploy/helm/fastgpt/templates/deployment.yaml
Normal file
@@ -0,0 +1,67 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "fastgpt.fullname" . }}
|
||||
labels:
|
||||
{{- include "fastgpt.labels" . | nindent 4 }}
|
||||
spec:
|
||||
{{- if not .Values.autoscaling.enabled }}
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
{{- end }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "fastgpt.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
{{- with .Values.podAnnotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "fastgpt.labels" . | nindent 8 }}
|
||||
{{- with .Values.podLabels }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "fastgpt.serviceAccountName" . }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ include "fastgpt.fullname" . }}-env
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {{ .Values.service.port }}
|
||||
protocol: TCP
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
volumeMounts:
|
||||
- mountPath: /app/data/config.json
|
||||
name: config
|
||||
subPath: config.json
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: {{ include "fastgpt.fullname" . }}-config
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
32
deploy/helm/fastgpt/templates/hpa.yaml
Normal file
@@ -0,0 +1,32 @@
|
||||
{{- if .Values.autoscaling.enabled }}
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: {{ include "fastgpt.fullname" . }}
|
||||
labels:
|
||||
{{- include "fastgpt.labels" . | nindent 4 }}
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: {{ include "fastgpt.fullname" . }}
|
||||
minReplicas: {{ .Values.autoscaling.minReplicas }}
|
||||
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
|
||||
metrics:
|
||||
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
61
deploy/helm/fastgpt/templates/ingress.yaml
Normal file
@@ -0,0 +1,61 @@
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
{{- $fullName := include "fastgpt.fullname" . -}}
|
||||
{{- $svcPort := .Values.service.port -}}
|
||||
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
|
||||
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
|
||||
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
{{- else -}}
|
||||
apiVersion: extensions/v1beta1
|
||||
{{- end }}
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
labels:
|
||||
{{- include "fastgpt.labels" . | nindent 4 }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
|
||||
ingressClassName: {{ .Values.ingress.className }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingress.tls }}
|
||||
tls:
|
||||
{{- range .Values.ingress.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ .host | quote }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ .path }}
|
||||
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
|
||||
pathType: {{ .pathType }}
|
||||
{{- end }}
|
||||
backend:
|
||||
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||
service:
|
||||
name: {{ $fullName }}
|
||||
port:
|
||||
number: {{ $svcPort }}
|
||||
{{- else }}
|
||||
serviceName: {{ $fullName }}
|
||||
servicePort: {{ $svcPort }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
17
deploy/helm/fastgpt/templates/secret-env.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
apiVersion: v1
|
||||
stringData:
|
||||
DEFAULT_ROOT_PSW: "1234"
|
||||
OPENAI_BASE_URL: "https://api.openai.com/v1"
|
||||
CHAT_API_KEY: "sk-xxxx"
|
||||
DB_MAX_LINK: "5"
|
||||
TOKEN_KEY: "any"
|
||||
ROOT_KEY: "root_key"
|
||||
FILE_TOKEN_KEY: "filetoken"
|
||||
MONGODB_URI: "mongodb://{{ .Values.mongodb.auth.rootUser }}:{{ .Values.mongodb.auth.rootPassword }}@{{ include "fastgpt.fullname" . }}-mongodb-headless:27017/fastgpt?authSource=admin"
|
||||
PG_URL: "postgresql://postgres:{{ .Values.postgresql.auth.rootPassword }}@{{ include "fastgpt.fullname" . }}-postgresql:5432/{{ .Values.postgresql.global.postgresql.auth.database }}"
|
||||
kind: Secret
|
||||
type: Opaque
|
||||
metadata:
|
||||
labels:
|
||||
{{ include "fastgpt.labels" . | nindent 4 }}
|
||||
name: {{ include "fastgpt.fullname" . }}-env
|
||||
18
deploy/helm/fastgpt/templates/service.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "fastgpt.fullname" . }}
|
||||
labels:
|
||||
{{- include "fastgpt.labels" . | nindent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.service.port }}
|
||||
{{- if .Values.service.nodePort }}
|
||||
nodePort: {{ .Values.service.nodePort }}
|
||||
{{- end}}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
{{- include "fastgpt.selectorLabels" . | nindent 4 }}
|
||||
13
deploy/helm/fastgpt/templates/serviceaccount.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "fastgpt.serviceAccountName" . }}
|
||||
labels:
|
||||
{{- include "fastgpt.labels" . | nindent 4 }}
|
||||
{{- with .Values.serviceAccount.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
automountServiceAccountToken: {{ .Values.serviceAccount.automount }}
|
||||
{{- end }}
|
||||
15
deploy/helm/fastgpt/templates/tests/test-connection.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: "{{ include "fastgpt.fullname" . }}-test-connection"
|
||||
labels:
|
||||
{{- include "fastgpt.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
"helm.sh/hook": test
|
||||
spec:
|
||||
containers:
|
||||
- name: wget
|
||||
image: busybox
|
||||
command: ['wget']
|
||||
args: ['{{ include "fastgpt.fullname" . }}:{{ .Values.service.port }}']
|
||||
restartPolicy: Never
|
||||
136
deploy/helm/fastgpt/values.yaml
Normal file
@@ -0,0 +1,136 @@
|
||||
# Default values for fastgpt.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: ghcr.io/labring/fastgpt
|
||||
pullPolicy: IfNotPresent
|
||||
# Overrides the image tag whose default is the chart appVersion.
|
||||
tag: ""
|
||||
|
||||
imagePullSecrets: []
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
create: true
|
||||
# Automatically mount a ServiceAccount's API credentials?
|
||||
automount: true
|
||||
# Annotations to add to the service account
|
||||
annotations: {}
|
||||
# The name of the service account to use.
|
||||
# If not set and create is true, a name is generated using the fullname template
|
||||
name: ""
|
||||
|
||||
podAnnotations: {}
|
||||
podLabels: {}
|
||||
|
||||
podSecurityContext:
|
||||
{}
|
||||
# fsGroup: 2000
|
||||
|
||||
securityContext:
|
||||
{}
|
||||
# capabilities:
|
||||
# drop:
|
||||
# - ALL
|
||||
# readOnlyRootFilesystem: true
|
||||
# runAsNonRoot: true
|
||||
# runAsUser: 1000
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 3000
|
||||
# nodePort: 31440
|
||||
|
||||
ingress:
|
||||
enabled: false
|
||||
className: ""
|
||||
annotations:
|
||||
{}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
hosts:
|
||||
- host: chart-example.local
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
tls: []
|
||||
# - secretName: chart-example-tls
|
||||
# hosts:
|
||||
# - chart-example.local
|
||||
|
||||
resources:
|
||||
{}
|
||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||
# choice for the user. This also increases chances charts run on environments with little
|
||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
|
||||
autoscaling:
|
||||
enabled: false
|
||||
minReplicas: 1
|
||||
maxReplicas: 100
|
||||
targetCPUUtilizationPercentage: 80
|
||||
# targetMemoryUtilizationPercentage: 80
|
||||
|
||||
# Additional volumes on the output Deployment definition.
|
||||
volumes: []
|
||||
# - name: foo
|
||||
# secret:
|
||||
# secretName: mysecret
|
||||
# optional: false
|
||||
|
||||
# Additional volumeMounts on the output Deployment definition.
|
||||
volumeMounts: []
|
||||
# - name: foo
|
||||
# mountPath: "/etc/foo"
|
||||
# readOnly: true
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
||||
|
||||
mongodb:
|
||||
# -- Enable or disable the built-in MangoDB
|
||||
enabled: true
|
||||
architecture: replicaset
|
||||
auth:
|
||||
rootUser: root
|
||||
rootPassword: "123456"
|
||||
|
||||
postgresql:
|
||||
# -- Enable or disable the built-in PostgreSQL
|
||||
enabled: true
|
||||
image:
|
||||
# registry: 172.11.0.6:30002
|
||||
# -- The PostgreSQL image which include the pgvector extension. See also the source code from https://github.com/LinuxSuRen/pgvector-docker
|
||||
repository: linuxsuren/pgvector
|
||||
tag: v0.0.1
|
||||
global:
|
||||
postgresql:
|
||||
auth:
|
||||
# -- The password of PostgreSQL, default username is `postgres`
|
||||
postgresPassword: postgres
|
||||
# -- The default database of PostgreSQL
|
||||
database: postgres
|
||||
118
dev.md
Normal file
@@ -0,0 +1,118 @@
|
||||
## Premise
|
||||
|
||||
Since FastGPT is managed in the same way as monorepo, it is recommended to install ‘make’ first during development.
|
||||
|
||||
monorepo Project Name:
|
||||
|
||||
- app: main project
|
||||
-......
|
||||
|
||||
## Dev
|
||||
|
||||
```sh
|
||||
# Give automatic script code execution permission (on non-Linux systems, you can manually execute the postinstall.sh file content)
|
||||
chmod -R +x ./scripts/
|
||||
# Executing under the code root directory installs all dependencies within the root package, projects, and packages
|
||||
pnpm i
|
||||
|
||||
# Not make cmd
|
||||
cd projects/app
|
||||
pnpm dev
|
||||
|
||||
# Make cmd
|
||||
make dev name=app
|
||||
```
|
||||
|
||||
Note: If the Node version is >= 20, you need to pass the `--no-node-snapshot` parameter to Node when running `pnpm i`
|
||||
|
||||
```sh
|
||||
NODE_OPTIONS=--no-node-snapshot pnpm i
|
||||
```
|
||||
|
||||
### Jest
|
||||
|
||||
https://fael3z0zfze.feishu.cn/docx/ZOI1dABpxoGhS7xzhkXcKPxZnDL
|
||||
|
||||
## I18N
|
||||
|
||||
### Install i18n-ally Plugin
|
||||
|
||||
1. Open the Extensions Marketplace in VSCode, search for and install the `i18n Ally` plugin.
|
||||
|
||||
### Code Optimization Examples
|
||||
|
||||
#### Fetch Specific Namespace Translations in `getServerSideProps`
|
||||
|
||||
```typescript
|
||||
// pages/yourPage.tsx
|
||||
export async function getServerSideProps(context: any) {
|
||||
return {
|
||||
props: {
|
||||
currentTab: context?.query?.currentTab || TabEnum.info,
|
||||
...(await serverSideTranslations(context.locale, ['publish', 'user']))
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
#### Use useTranslation Hook in Page
|
||||
|
||||
```typescript
|
||||
// pages/yourPage.tsx
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
const YourComponent = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
mr={2}
|
||||
onClick={() => setShowSelected(false)}
|
||||
>
|
||||
{t('common:close')}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export default YourComponent;
|
||||
```
|
||||
|
||||
#### Handle Static File Translations
|
||||
|
||||
```typescript
|
||||
// utils/i18n.ts
|
||||
import { i18nT } from '@fastgpt/web/i18n/utils';
|
||||
|
||||
const staticContent = {
|
||||
id: 'simpleChat',
|
||||
avatar: 'core/workflow/template/aiChat',
|
||||
name: i18nT('app:template.simple_robot'),
|
||||
};
|
||||
|
||||
export default staticContent;
|
||||
```
|
||||
|
||||
### Standardize Translation Format
|
||||
|
||||
- Use the t(namespace:key) format to ensure consistent naming.
|
||||
- Translation keys should use lowercase letters and underscores, e.g., common.close.
|
||||
|
||||
## audit
|
||||
|
||||
Please fill the AuditEventEnum and audit function is added to the ts, and on the corresponding position to fill i18n, at the same time to add the location of the log using addOpearationLog function add function
|
||||
|
||||
## Build
|
||||
|
||||
```sh
|
||||
# Docker cmd: Build image, not proxy
|
||||
docker build -f ./projects/app/Dockerfile -t registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.1 . --build-arg name=app
|
||||
# Make cmd: Build image, not proxy
|
||||
make build name=app image=registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.1
|
||||
|
||||
# Docker cmd: Build image with proxy
|
||||
docker build -f ./projects/app/Dockerfile -t registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.1 . --build-arg name=app --build-arg proxy=taobao
|
||||
# Make cmd: Build image with proxy
|
||||
make build name=app image=registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.1 proxy=taobao
|
||||
```
|
||||
68
document/.dockerignore
Normal file
@@ -0,0 +1,68 @@
|
||||
# Dependencies
|
||||
node_modules
|
||||
npm-debug.log*
|
||||
pnpm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Local env files
|
||||
.env
|
||||
.env.local
|
||||
.env.production.local
|
||||
.env.test.local
|
||||
|
||||
# Vercel
|
||||
.vercel
|
||||
|
||||
# Typescript
|
||||
*.tsbuildinfo
|
||||
|
||||
# Next.js
|
||||
.next/
|
||||
out/
|
||||
|
||||
# Production
|
||||
build
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# Debug
|
||||
debug.log*
|
||||
|
||||
# Git
|
||||
.git
|
||||
.gitignore
|
||||
|
||||
# Testing
|
||||
coverage
|
||||
.nyc_output
|
||||
|
||||
# Cache
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage/
|
||||
|
||||
# IDE
|
||||
.vscode
|
||||
.idea
|
||||
|
||||
# OS
|
||||
Thumbs.db
|
||||
|
||||
# Temporary folders
|
||||
tmp/
|
||||
temp/
|
||||
1
document/.env.template
Normal file
@@ -0,0 +1 @@
|
||||
FASTGPT_HOME_DOMAIN=
|
||||
1
document/.zhlintignore
Normal file
@@ -0,0 +1 @@
|
||||
*.html
|
||||
6
document/.zhlintrc
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"preset": "default",
|
||||
"rules": {
|
||||
"adjustedFullWidthPunctuation": ""
|
||||
}
|
||||
}
|
||||
47
document/Dockerfile
Normal file
@@ -0,0 +1,47 @@
|
||||
FROM node:20-alpine AS base
|
||||
|
||||
FROM base AS builder
|
||||
RUN apk add --no-cache \
|
||||
libc6-compat \
|
||||
git \
|
||||
build-base \
|
||||
g++ \
|
||||
cairo-dev \
|
||||
jpeg-dev \
|
||||
pango-dev \
|
||||
giflib-dev \
|
||||
librsvg-dev \
|
||||
freetype-dev \
|
||||
harfbuzz-dev \
|
||||
fribidi-dev \
|
||||
udev \
|
||||
ttf-opensans \
|
||||
fontconfig
|
||||
WORKDIR /app
|
||||
|
||||
ARG FASTGPT_HOME_DOMAIN
|
||||
|
||||
ENV FASTGPT_HOME_DOMAIN=$FASTGPT_HOME_DOMAIN
|
||||
|
||||
COPY . .
|
||||
RUN npm install
|
||||
RUN npm run build
|
||||
|
||||
|
||||
FROM base AS runner
|
||||
RUN apk add --no-cache curl
|
||||
ENV NODE_ENV=production
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/public ./public
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
USER nextjs
|
||||
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
ENV PORT=3000
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
CMD ["node", "server.js"]
|
||||
74
document/README.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# FastGPT 文档
|
||||
|
||||
这是FastGPT的官方文档,采用fumadoc框架。
|
||||
## 运行项目
|
||||
|
||||
要运行文档,首先需要进行环境变量配置,在文档的根目录下创建`.env.local`文件,填写以下环境变量:
|
||||
|
||||
```bash
|
||||
FASTGPT_HOME_DOMAIN = #要跳转的FastGPT项目的域名,默认海外版
|
||||
```
|
||||
|
||||
你可以在FastGPT项目根目录下执行以下命令来运行文档。
|
||||
|
||||
```bash
|
||||
npm install #只能npm install,不能pnpm
|
||||
npm run dev
|
||||
```
|
||||
项目会默认跑在`http:localhost:3000`端口
|
||||
|
||||
## 书写文档
|
||||
|
||||
文档采用`mdx`格式,大体和`md`一致,但是现在文档的元数据只支持`title` `description`和`icon`三个字段,参考以下示例代码:
|
||||
|
||||
```bash
|
||||
---
|
||||
title: FastGPT 文档
|
||||
description: FastGPT 官方文档
|
||||
icon: menu #icon采用`lucide-react`第三方库。
|
||||
---
|
||||
|
||||
import { Alert } from '@/components/docs/Alert'; #高亮块组件
|
||||
|
||||
<Alert icon="🤖" context="success">
|
||||
快速开始体验
|
||||
- 海外版:[https://fastgpt.io](https://fastgpt.io)
|
||||
- 国内版:[https://fastgpt.cn](https://fastgpt.cn)
|
||||
</Alert>
|
||||
|
||||
import {Redirect} from '@/components/docs/Redirect' #重定向组件,如果你希望用户点击这个文件跳转到别的文件的话,详情参考 `FAQ`的`Docker 部署问题`文档。
|
||||
|
||||
<Redirect to="/docs/introduction/development/docker/#faq" />
|
||||
|
||||
<Tabs items={['Javascript', 'Rust']}> #tabs组件用法,渲染效果参考`introduction`下`development`的`faq`文档
|
||||
<Tab value="Javascript">Javascript is weird</Tab>
|
||||
<Tab value="Rust">Rust is fast</Tab>
|
||||
|
||||
|
||||
import FastGPTLink from '@/components/docs/linkFastGPT'; #FastGPT跳转链接组件,通过接收一个域名环境变量,来实现跳转到海外或者国内
|
||||
|
||||
本文档介绍了如何设置开发环境以构建和测试 <FastGPTLink>FastGPT</FastGPTLink>。
|
||||
</Tabs>
|
||||
|
||||
```
|
||||
|
||||
在书写完文档后,需要在对应的目录下的`meta.json`文件的`pages`字段合适位置添加自己的文件名。例如在`content/docs`(默认这是所有文档的根目录)的`introduction`目录下书写了一个`hello.mdx`文件。则需要去`introduction`目录下的`meta.json`添加以下内容:
|
||||
|
||||
```bash
|
||||
{
|
||||
"title": "FastGPT Docs",
|
||||
"root": true,
|
||||
"pages": ["[Handshake][联系我们](https://fael3z0zfze.feishu.cn/share/base/form/shrcnjJWtKqjOI9NbQTzhNyzljc)","index","guide","development","FAQ","shopping_cart","community","hello"], #"hello"原本没有,此外,这里的顺序就是最后文档的展示顺序,现在"hello"文档将会在`introduction`的最后展示
|
||||
"order": 1
|
||||
}
|
||||
```
|
||||
|
||||
## i18n
|
||||
|
||||
在`content/docs`下的所有`.mdx`文件为默认语言文件(当前默认语言中文),`.en.mdx`文件为`i18n`支持的英文文件,例如,你可以将`hello.mdx`文档翻译后,写一个`hello.en.mdx`,同时,在对应目录的`meta.en.json`的`"pages"`字段写下对应的文件名来支持英文文档。
|
||||
|
||||
## 特殊配置
|
||||
|
||||
### 增加顶层导航栏
|
||||
|
||||
1. 在 `FastGPT/document/app/[lang]/docs/layout.tsx` 文件中新增导航。
|
||||
5
document/app/[lang]/(home)/[...not-found]/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import { redirect } from 'next/navigation';
|
||||
|
||||
export default function HomePage() {
|
||||
redirect(`/docs/introduction`);
|
||||
}
|
||||
27
document/app/[lang]/(home)/layout.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import { HomeLayout } from 'fumadocs-ui/layouts/home';
|
||||
import LogoLight from '@/components/docs/logo';
|
||||
|
||||
export default async function Layout({
|
||||
params,
|
||||
children
|
||||
}: {
|
||||
params: Promise<{ lang: string }>;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
const lang = (await params).lang;
|
||||
return (
|
||||
<HomeLayout
|
||||
nav={{
|
||||
title: (
|
||||
<div className="flex flex-row items-center gap-2 h-14">
|
||||
<LogoLight />
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
i18n
|
||||
>
|
||||
{children}
|
||||
</HomeLayout>
|
||||
);
|
||||
}
|
||||
5
document/app/[lang]/(home)/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import { redirect } from 'next/navigation';
|
||||
|
||||
export default function HomePage() {
|
||||
redirect(`/docs/introduction`);
|
||||
}
|
||||
90
document/app/[lang]/docs/[[...slug]]/page.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import { source } from '@/lib/source';
|
||||
import { DocsPage, DocsBody, DocsDescription, DocsTitle } from 'fumadocs-ui/page';
|
||||
import { notFound } from 'next/navigation';
|
||||
import NotFound from '@/components/docs/not-found';
|
||||
import { createRelativeLink } from 'fumadocs-ui/mdx';
|
||||
import { getMDXComponents } from '@/mdx-components';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
// 读取文档修改时间数据
|
||||
function getDocLastModifiedData(): Record<string, string> {
|
||||
try {
|
||||
const dataPath = path.join(process.cwd(), 'data', 'doc-last-modified.json');
|
||||
|
||||
if (!fs.existsSync(dataPath)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const data = fs.readFileSync(dataPath, 'utf8');
|
||||
return JSON.parse(data);
|
||||
} catch (error) {
|
||||
console.error('读取文档修改时间数据失败:', error);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
export default async function Page({
|
||||
params
|
||||
}: {
|
||||
params: Promise<{ lang: string; slug?: string[] }>;
|
||||
}) {
|
||||
const { lang, slug } = await params;
|
||||
const page = source.getPage(slug, lang);
|
||||
|
||||
// 如果页面不存在,调用 notFound()
|
||||
if (!page || !page.data || !page.file) {
|
||||
return <NotFound />;
|
||||
}
|
||||
|
||||
const MDXContent = page.data.body;
|
||||
|
||||
// 获取文档的最后修改时间
|
||||
const docLastModifiedData = getDocLastModifiedData();
|
||||
const filePath = `content/docs/${page.file.path}`;
|
||||
const lastModified = docLastModifiedData[filePath] || page.data.lastModified;
|
||||
|
||||
return (
|
||||
<DocsPage
|
||||
toc={page.data.toc}
|
||||
full={page.data.full}
|
||||
tableOfContent={{
|
||||
style: 'clerk'
|
||||
}}
|
||||
editOnGithub={{
|
||||
owner: 'labring',
|
||||
repo: 'FastGPT',
|
||||
sha: 'main',
|
||||
path: `document/content/docs/${page.file.path}`
|
||||
}}
|
||||
lastUpdate={lastModified ? new Date(lastModified) : undefined}
|
||||
>
|
||||
<DocsTitle>{page.data.title}</DocsTitle>
|
||||
<DocsDescription>{page.data.description}</DocsDescription>
|
||||
<DocsBody>
|
||||
<MDXContent
|
||||
components={getMDXComponents({
|
||||
a: createRelativeLink(source, page)
|
||||
})}
|
||||
/>
|
||||
</DocsBody>
|
||||
</DocsPage>
|
||||
);
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
return source.generateParams();
|
||||
}
|
||||
|
||||
export async function generateMetadata(props: {
|
||||
params: Promise<{ lang: string; slug?: string[] }>;
|
||||
}) {
|
||||
const { lang, slug } = await props.params;
|
||||
const page = source.getPage(slug, lang);
|
||||
if (!page || !page.data) notFound();
|
||||
|
||||
return {
|
||||
title: `${page.data.title} | FastGPT`,
|
||||
description: page.data.description
|
||||
};
|
||||
}
|
||||
109
document/app/[lang]/docs/layout.tsx
Normal file
@@ -0,0 +1,109 @@
|
||||
import { type ReactNode } from 'react';
|
||||
import { source } from '@/lib/source';
|
||||
import { DocsLayout } from 'fumadocs-ui/layouts/notebook';
|
||||
import { baseOptions } from '@/app/layout.config';
|
||||
import { t } from '@/lib/i18n';
|
||||
import LogoLight from '@/components/docs/logo';
|
||||
import LogoDark from '@/components/docs/logoDark';
|
||||
import '@/app/global.css';
|
||||
import { CustomSidebarComponents } from '@/components/sideBar';
|
||||
import FeishuLogoLight from '@/components/docs/feishuLogoLIght';
|
||||
import FeishuLogoDark from '@/components/docs/feishuLogoDark';
|
||||
import GithubLogoLight from '@/components/docs/githubLogoLight';
|
||||
import GithubLogoDark from '@/components/docs/githubLogoDark';
|
||||
|
||||
export default async function Layout({
|
||||
params,
|
||||
children
|
||||
}: {
|
||||
params: Promise<{ lang: string }>;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
const { lang } = await params;
|
||||
|
||||
const tab = [
|
||||
{
|
||||
title: t('common:introduction', lang),
|
||||
url: lang === 'zh-CN' ? '/docs/introduction' : '/en/docs/introduction'
|
||||
},
|
||||
{
|
||||
title: t('common:use-cases', lang),
|
||||
url: lang === 'zh-CN' ? '/docs/use-cases' : '/en/docs/use-cases'
|
||||
},
|
||||
{
|
||||
title: t('common:faq', lang),
|
||||
url: lang === 'zh-CN' ? '/docs/faq' : '/en/docs/faq'
|
||||
},
|
||||
{
|
||||
title: t('common:protocol', lang),
|
||||
url: lang === 'zh-CN' ? '/docs/protocol' : '/en/docs/protocol'
|
||||
},
|
||||
{
|
||||
title: t('common:upgrading', lang),
|
||||
url: lang === 'zh-CN' ? '/docs/upgrading' : '/en/docs/upgrading'
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<DocsLayout
|
||||
{...baseOptions(lang)}
|
||||
nav={{
|
||||
title: (
|
||||
<div className="flex flex-row items-center gap-2 h-14 ml-1">
|
||||
<div className="block dark:hidden">
|
||||
<LogoLight className="w-48 h-auto" />
|
||||
</div>
|
||||
<div className="hidden dark:block">
|
||||
<LogoDark className="w-48 h-auto" />
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
mode: 'top'
|
||||
}}
|
||||
links={[
|
||||
{
|
||||
type: 'icon',
|
||||
icon: (
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<div className="block dark:hidden">
|
||||
<FeishuLogoLight />
|
||||
</div>
|
||||
<div className="hidden dark:block">
|
||||
<FeishuLogoDark />
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
url: 'https://oss.laf.run/otnvvf-imgs/fastgpt-feishu1.png',
|
||||
text: '飞书群'
|
||||
},
|
||||
{
|
||||
type: 'icon',
|
||||
icon: (
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<div className="block dark:hidden">
|
||||
<GithubLogoLight />
|
||||
</div>
|
||||
<div className="hidden dark:block">
|
||||
<GithubLogoDark />
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
url: 'https://github.com/labring/FastGPT',
|
||||
text: 'github'
|
||||
}
|
||||
]}
|
||||
tree={source.pageTree[lang]}
|
||||
searchToggle={{
|
||||
enabled: true
|
||||
}}
|
||||
sidebar={{
|
||||
tabs: tab,
|
||||
collapsible: false,
|
||||
components: CustomSidebarComponents
|
||||
}}
|
||||
tabMode="navbar"
|
||||
>
|
||||
{children}
|
||||
</DocsLayout>
|
||||
);
|
||||
}
|
||||
79
document/app/[lang]/layout.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
import '@/app/global.css';
|
||||
import { RootProvider } from 'fumadocs-ui/provider';
|
||||
import { Inter } from 'next/font/google';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { Translations } from 'fumadocs-ui/i18n';
|
||||
import CustomSearchDialog from '@/components/CustomSearchDialog';
|
||||
|
||||
const inter = Inter({
|
||||
subsets: ['latin']
|
||||
});
|
||||
|
||||
const zh_CN: Partial<Translations> = {
|
||||
search: '搜索',
|
||||
nextPage: '下一页',
|
||||
previousPage: '上一页',
|
||||
lastUpdate: '最后更新于',
|
||||
editOnGithub: '在 GitHub 上编辑',
|
||||
searchNoResult: '没有找到相关内容',
|
||||
toc: '本页导航',
|
||||
tocNoHeadings: '本页没有导航',
|
||||
chooseLanguage: '选择语言'
|
||||
};
|
||||
|
||||
const locales = [
|
||||
{
|
||||
name: 'English',
|
||||
locale: 'en'
|
||||
},
|
||||
{
|
||||
name: '简体中文',
|
||||
locale: 'zh-CN'
|
||||
}
|
||||
];
|
||||
|
||||
export default async function Layout({
|
||||
children,
|
||||
params
|
||||
}: {
|
||||
children: ReactNode;
|
||||
params: Promise<{ lang: string }>;
|
||||
}) {
|
||||
const { lang } = await params;
|
||||
|
||||
return (
|
||||
<html lang={lang} className={inter.className} suppressHydrationWarning>
|
||||
<body className="flex flex-col min-h-screen">
|
||||
<RootProvider
|
||||
i18n={{
|
||||
locale: lang,
|
||||
locales,
|
||||
translations: {
|
||||
'zh-CN': zh_CN,
|
||||
en: {
|
||||
search: 'Search',
|
||||
nextPage: 'Next Page',
|
||||
previousPage: 'Previous Page',
|
||||
lastUpdate: 'Last Updated',
|
||||
editOnGithub: 'Edit on GitHub',
|
||||
searchNoResult: 'No results found',
|
||||
toc: 'On this page',
|
||||
tocNoHeadings: 'No headings',
|
||||
chooseLanguage: 'Choose Language'
|
||||
}
|
||||
}[lang]
|
||||
}}
|
||||
search={{
|
||||
enabled: true,
|
||||
SearchDialog: CustomSearchDialog
|
||||
}}
|
||||
theme={{
|
||||
enabled: true
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</RootProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
56
document/app/[lang]/llms.txt/route.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import * as fs from 'node:fs/promises';
|
||||
import fg from 'fast-glob';
|
||||
import matter from 'gray-matter';
|
||||
import { remark } from 'remark';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import remarkStringify from 'remark-stringify';
|
||||
import remarkMdx from 'remark-mdx';
|
||||
import { remarkInclude } from 'fumadocs-mdx/config';
|
||||
import { i18n } from '@/lib/i18n';
|
||||
|
||||
export const revalidate = false;
|
||||
|
||||
const processor = remark()
|
||||
.use(remarkMdx)
|
||||
// https://fumadocs.vercel.app/docs/mdx/include
|
||||
.use(remarkInclude)
|
||||
// gfm styles
|
||||
.use(remarkGfm)
|
||||
// .use(your remark plugins)
|
||||
.use(remarkStringify); // to string
|
||||
|
||||
export async function GET() {
|
||||
// all scanned content
|
||||
// Select files based on the default language
|
||||
const defaultLanguage = i18n.defaultLanguage;
|
||||
let globPattern;
|
||||
|
||||
if (defaultLanguage === 'zh-CN') {
|
||||
// For Chinese, select *.mdx files
|
||||
globPattern = ['./content/docs/**/*.mdx'];
|
||||
} else {
|
||||
// For other languages (default English), select *.en.mdx files that don't have .mdx. in their path
|
||||
globPattern = ['./content/docs/**/*.en.mdx'];
|
||||
}
|
||||
|
||||
const files = await fg(globPattern);
|
||||
|
||||
const scan = files.map(async (file: string) => {
|
||||
const fileContent = await fs.readFile(file);
|
||||
const { content, data } = matter(fileContent.toString());
|
||||
|
||||
const processed = await processor.process({
|
||||
path: file,
|
||||
value: content
|
||||
});
|
||||
|
||||
return `file: ${file}
|
||||
meta: ${JSON.stringify(data, null, 2)}
|
||||
|
||||
${processed}`;
|
||||
});
|
||||
|
||||
const scanned = await Promise.all(scan);
|
||||
|
||||
return new Response(scanned.join('\n\n'));
|
||||
}
|
||||
86
document/app/api/meta/route.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import type { NextRequest } from 'next/server';
|
||||
import { NextResponse } from 'next/server';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
const docsRoot = path.resolve(process.cwd(), 'content/docs');
|
||||
|
||||
function isInvalidPage(str: string): boolean {
|
||||
if (!str || typeof str !== 'string') return true;
|
||||
if (/\[.*?\]\(.*?\)/.test(str) || /^https?:\/\//.test(str) || /[()]/.test(str)) return true;
|
||||
if (/^\s*---[\s\S]*---\s*$/.test(str)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function getPageName(str: string): string {
|
||||
return str.startsWith('...') ? str.slice(3) : str;
|
||||
}
|
||||
|
||||
async function findFirstValidPage(dirRelPath: string): Promise<string | null> {
|
||||
const absDir = path.join(docsRoot, dirRelPath);
|
||||
const metaPath = path.join(absDir, 'meta.json');
|
||||
|
||||
try {
|
||||
const metaRaw = await fs.readFile(metaPath, 'utf-8');
|
||||
const meta = JSON.parse(metaRaw);
|
||||
if (!Array.isArray(meta.pages)) return null;
|
||||
|
||||
for (const page of meta.pages) {
|
||||
if (isInvalidPage(page)) continue;
|
||||
|
||||
const pageName = getPageName(page);
|
||||
const pagePath = path.join(dirRelPath, pageName);
|
||||
|
||||
const candidateDir = path.join(docsRoot, pagePath);
|
||||
const candidateFile = candidateDir + '.mdx';
|
||||
|
||||
try {
|
||||
await fs.access(candidateFile);
|
||||
return pagePath;
|
||||
} catch {
|
||||
try {
|
||||
const stat = await fs.stat(candidateDir);
|
||||
if (stat.isDirectory()) {
|
||||
const recursiveResult = await findFirstValidPage(pagePath);
|
||||
if (recursiveResult) return recursiveResult;
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const url = new URL(req.url);
|
||||
const rawPath = url.searchParams.get('path');
|
||||
|
||||
if (!rawPath || !rawPath.startsWith('/docs')) {
|
||||
return NextResponse.json({ error: 'Invalid path' }, { status: 400 });
|
||||
}
|
||||
|
||||
// 去除 /docs 前缀,且清理首尾斜杠
|
||||
const relPath = rawPath.replace(/^\/docs\/?/, '').replace(/^\/|\/$/g, '');
|
||||
|
||||
try {
|
||||
// 先检测是否有该 mdx 文件
|
||||
const maybeFile = path.join(docsRoot, relPath + '.mdx');
|
||||
await fs.access(maybeFile);
|
||||
// 如果存在,返回完整路径(带 /docs)
|
||||
return NextResponse.json('/docs/' + relPath);
|
||||
} catch {
|
||||
// 不存在,尝试递归寻找第一个有效页面
|
||||
const found = await findFirstValidPage(relPath);
|
||||
if (found) {
|
||||
// 返回带 /docs 前缀的完整路径
|
||||
return NextResponse.json('/docs/' + found.replace(/\\/g, '/'));
|
||||
} else {
|
||||
return NextResponse.json({ error: 'No valid mdx page found' }, { status: 404 });
|
||||
}
|
||||
}
|
||||
}
|
||||
21
document/app/api/search/route.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { source } from '@/lib/source';
|
||||
import { enhancedTokenizer } from '@/lib/tokenizer';
|
||||
import { createFromSource } from 'fumadocs-core/search/server';
|
||||
|
||||
export const { GET } = createFromSource(source, {
|
||||
// 使用中文分词器时不能设置 language 选项
|
||||
localeMap: {
|
||||
en: {
|
||||
language: 'english'
|
||||
},
|
||||
'zh-CN': {
|
||||
components: {
|
||||
tokenizer: enhancedTokenizer()
|
||||
},
|
||||
search: {
|
||||
threshold: 0,
|
||||
tolerance: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
478
document/app/global.css
Normal file
@@ -0,0 +1,478 @@
|
||||
@import 'tailwindcss';
|
||||
@import 'fumadocs-ui/css/preset.css';
|
||||
|
||||
@font-face {
|
||||
font-family: 'Alef';
|
||||
src: url('/fonts/Alef-Regular.ttf') format('truetype');
|
||||
}
|
||||
|
||||
/* 在文件开头添加这些基础变量 */
|
||||
:root {
|
||||
/* 基础颜色 */
|
||||
--primary-50-hsl: 210, 40%, 98%;
|
||||
--primary-hsl: 217, 91%, 60%;
|
||||
--emerald-50-hsl: 152, 81%, 96%;
|
||||
--emerald-500-hsl: 152, 76%, 40%;
|
||||
--cardinal-50-hsl: 0, 86%, 97%;
|
||||
--cardinal-500-hsl: 0, 74%, 42%;
|
||||
--yellow-50-hsl: 55, 92%, 95%;
|
||||
--yellow-500-hsl: 45, 93%, 47%;
|
||||
--blue-500-hsl: 217, 91%, 60%;
|
||||
--fd-layout-width: 1400px;
|
||||
|
||||
/* 文本颜色 */
|
||||
--text-default: #374151;
|
||||
--text-default-inv: #ffffff;
|
||||
--text-muted: #6b7280;
|
||||
--content-link-color: #2563eb;
|
||||
|
||||
/* 其他变量 */
|
||||
--font-size-sm: 0.875rem;
|
||||
--gray-200: #e5e7eb;
|
||||
--gray-700: #374151;
|
||||
--gray-800: #1f2937;
|
||||
--gray-900: #111827;
|
||||
|
||||
/* 组件颜色 */
|
||||
--primary-200: #bfdbfe;
|
||||
--blue-200: #bfdbfe;
|
||||
--blue-800: #1e40af;
|
||||
--emerald-200: #a7f3d0;
|
||||
--emerald-800: #065f46;
|
||||
--cardinal-200: #fecaca;
|
||||
--cardinal-800: #991b1b;
|
||||
--yellow-200: #fde68a;
|
||||
--yellow-800: #92400e;
|
||||
|
||||
/* Tabs 样式 */
|
||||
--nav-tabs-border-width: none;
|
||||
--nav-tabs-link-active-bg: none;
|
||||
--nav-tabs-link-active-color: var(--text-default);
|
||||
--nav-tabs-border-color: var(--gray-400);
|
||||
}
|
||||
|
||||
[data-dark-mode] {
|
||||
/* Tabs 样式 */
|
||||
--nav-tabs-border-color: var(--gray-800);
|
||||
|
||||
--text-muted: #9ca3af;
|
||||
--content-link-color: #60a5fa;
|
||||
}
|
||||
|
||||
/* 全局代码块样式 */
|
||||
pre,
|
||||
code {
|
||||
border-radius: 16px;
|
||||
background: #F5F6F7;
|
||||
font-family: Alef;
|
||||
font-size: 1.0rem;
|
||||
font-weight: 400;
|
||||
line-height: 16px;
|
||||
letter-spacing: 0.48px;
|
||||
}
|
||||
|
||||
div[role='tabpanel'] figure:has(+ p) pre,
|
||||
div[role='tabpanel'] figure:has(+ p) pre code {
|
||||
background-color: #ececec;
|
||||
}
|
||||
|
||||
.dark div[role='tabpanel'] figure:has(+ p) pre,
|
||||
.dark div[role='tabpanel'] figure:has(+ p) pre code {
|
||||
background-color: #3d3d3d;
|
||||
}
|
||||
|
||||
.dark pre,
|
||||
.dark code {
|
||||
background: #1e1e1e;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 24px 0 24px 24px ;
|
||||
}
|
||||
|
||||
pre code {
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
code span {
|
||||
padding-left: 0 !important;
|
||||
}
|
||||
|
||||
/* 去除代码块内层边框 */
|
||||
.bg-fd-secondary.border {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* 去除代码块外层边框 */
|
||||
.shiki {
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* 行内代码样式 */
|
||||
/* 行内代码样式 */
|
||||
:not(pre) > code {
|
||||
display: inline-block;
|
||||
height: 25px;
|
||||
padding: 0 10px;
|
||||
margin: 0 0.2em;
|
||||
color: #272727;
|
||||
background: #f5f6f7;
|
||||
font-family: "PingFang SC";
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 180%;
|
||||
letter-spacing: 0.056px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.dark :not(pre) > code {
|
||||
color: #E6E6E6 !important;
|
||||
background: #282828 !important;
|
||||
}
|
||||
|
||||
div[role="tablist"] ~ div:has(figure, p, ul) {
|
||||
border-radius: 0 !important;
|
||||
border: solid 1.5px #e5e5e5;
|
||||
border-radius: 0.75rem !important;
|
||||
}
|
||||
|
||||
.dark div[role="tablist"] ~ div:has(figure, p, ul) {
|
||||
border: solid 1.5px #535353;
|
||||
}
|
||||
|
||||
.dark div[role="tablist"] {
|
||||
background-color: #1E1E1E;
|
||||
}
|
||||
|
||||
/* 代码块下方的滚动条样式 */
|
||||
div.bg-fd-secondary:has(pre) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.dark div.bg-fd-secondary:has(pre) {
|
||||
background-color: #1E1E1E;
|
||||
}
|
||||
|
||||
div.bg-fd-secondary:has(pre)::-webkit-scrollbar-track {
|
||||
background: #e8e8e8;
|
||||
}
|
||||
|
||||
div.bg-fd-secondary:has(pre)::-webkit-scrollbar-thumb {
|
||||
background: #b0b0b0;
|
||||
}
|
||||
|
||||
div.bg-fd-secondary:has(pre)::-webkit-scrollbar-thumb:hover {
|
||||
background: #909090;
|
||||
}
|
||||
|
||||
.dark div.bg-fd-secondary:has(pre)::-webkit-scrollbar-track {
|
||||
background: #1a1a1a;
|
||||
}
|
||||
|
||||
.dark div.bg-fd-secondary:has(pre)::-webkit-scrollbar-thumb {
|
||||
background: #404040;
|
||||
}
|
||||
|
||||
.dark div.bg-fd-secondary:has(pre)::-webkit-scrollbar-thumb:hover {
|
||||
background: #606060;
|
||||
}
|
||||
|
||||
/* 代码块中的滚动条样式优化 */
|
||||
|
||||
/* 图片居中显示 */
|
||||
.fumadocs-content img,
|
||||
.mdx-content img,
|
||||
.prose img,
|
||||
img {
|
||||
display: block !important;
|
||||
margin-left: auto !important;
|
||||
margin-right: auto !important;
|
||||
max-width: 100% !important;
|
||||
height: auto !important;
|
||||
border-radius: 8px !important;
|
||||
box-shadow:
|
||||
0 4px 6px -1px rgba(0, 0, 0, 0.1),
|
||||
0 2px 4px -1px rgba(0, 0, 0, 0.06) !important;
|
||||
}
|
||||
|
||||
/* MDX 表格样式 */
|
||||
.fumadocs-content table,
|
||||
.mdx-content table,
|
||||
.prose table {
|
||||
width: 100% !important;
|
||||
border-collapse: separate !important;
|
||||
margin: 1rem 0 !important;
|
||||
}
|
||||
|
||||
.fumadocs-content table td,
|
||||
.fumadocs-content table th,
|
||||
.mdx-content table td,
|
||||
.mdx-content table th,
|
||||
.prose table td,
|
||||
.prose table th {
|
||||
padding: 0.75rem 1rem !important;
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
/* Tabs 样式 */
|
||||
.nav-tabs {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
border-bottom: 1px solid var(--nav-tabs-border-color);
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link {
|
||||
color: var(--text-muted) !important;
|
||||
margin-bottom: -1px;
|
||||
padding: 0.75rem 1.5rem;
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link:hover {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link.active {
|
||||
border-bottom: 2px solid var(--content-link-color);
|
||||
color: var(--content-link-color) !important;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
margin-bottom: 0.8rem;
|
||||
padding: 1rem 0;
|
||||
}
|
||||
|
||||
div[data-state='open'].fixed.inset-0.z-50 {
|
||||
background-color: rgba(255, 255, 255, 0.4) !important;
|
||||
}
|
||||
|
||||
#nd-subnav > div:nth-of-type(1) button:nth-of-type(1) {
|
||||
box-shadow:
|
||||
0px 1px 2px 0px rgba(19, 51, 107, 0.05),
|
||||
0px 0px 1px 0px rgba(19, 51, 107, 0.08) !important;
|
||||
background-color: none !important;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
/* 复制按钮容器和按钮样式 */
|
||||
div[class*="bg-fd-card"]:has(button[aria-label='Copy Text']),
|
||||
div[class*="bg-fd-card"]:has(button[aria-label='Copied Text']) {
|
||||
right: 26px;
|
||||
top: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #818181;
|
||||
color: #818181;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
background: rgba(0, 0, 0, 0.01);
|
||||
-webkit-backdrop-filter: blur(5px);
|
||||
backdrop-filter: blur(5px);
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
/* 按钮内部样式 */
|
||||
button[aria-label='Copy Text'],
|
||||
button[aria-label='Copied Text'] {
|
||||
color: #818181;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
padding: 0;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
button[aria-label='Copy Text'] svg {
|
||||
display: none;
|
||||
}
|
||||
|
||||
button[aria-label='Copy Text']::before {
|
||||
content: '';
|
||||
background-image: url('../public/icons/copy.svg');
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
transition: filter 0.2s ease;
|
||||
}
|
||||
|
||||
/* 鼠标悬停时使复制图标颜色变深 */
|
||||
button[aria-label='Copy Text']:hover::before {
|
||||
filter: brightness(0.7); /* 降低亮度使颜色变深 */
|
||||
}
|
||||
|
||||
button[aria-label='Copied Text'] {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
/* transition: filter 0.2s ease; */
|
||||
}
|
||||
|
||||
button[aria-label='Copied Text'] svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
transition: filter 0.2s ease;
|
||||
}
|
||||
|
||||
#nd-subnav > div:nth-of-type(1) button {
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
#nd-subnav > div:nth-of-type(1) {
|
||||
border-bottom: 0.1px solid #e8ebf0 !important;
|
||||
}
|
||||
#nd-subnav > div:nth-of-type(2) {
|
||||
border-bottom: 0.1px solid #e8ebf0 !important;
|
||||
height: 100%;
|
||||
}
|
||||
.dark #nd-subnav > div:nth-of-type(1) {
|
||||
border-bottom: 0.1px solid #363b4a58 !important;
|
||||
}
|
||||
.dark #nd-subnav > div:nth-of-type(2) {
|
||||
border-bottom: 0.1px solid #363b4a58 !important;
|
||||
}
|
||||
|
||||
div[data-rmiz-modal-content] {
|
||||
background-color: none !important;
|
||||
}
|
||||
|
||||
div[data-rmiz-modal-overlay='visible'] {
|
||||
background-color: #ffffff00 !important;
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
.dark div[data-rmiz-modal-overlay='visible'] {
|
||||
background-color: #060c1a00 !important;
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
.dark div[data-rmiz-modal-content] {
|
||||
background-color: #060c1a00 !important;
|
||||
}
|
||||
|
||||
#nd-tocnav {
|
||||
border-bottom-color: #e8ebf0 !important;
|
||||
}
|
||||
.dark #nd-tocnav {
|
||||
border-bottom-color: #1d2532 !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
#nd-subnav > div:nth-of-type(2) a {
|
||||
text-decoration: none;
|
||||
color: #485264;
|
||||
transition: color 0.2s ease;
|
||||
background-color: transparent !important;
|
||||
font-weight: 400;
|
||||
/* 先清除默认下划线 */
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
text-decoration-color: #dfe2ea;
|
||||
text-decoration-thickness: 3px; /* 下划线粗细 */
|
||||
text-underline-offset: 17px; /* 下划线与文字距离 */
|
||||
}
|
||||
&.text-fd-primary {
|
||||
text-decoration: underline;
|
||||
text-decoration-color: #3370ff;
|
||||
text-decoration-thickness: 3px; /* 下划线粗细 */
|
||||
text-underline-offset: 17px; /* 下划线与文字距离 */
|
||||
background-color: transparent !important;
|
||||
font-weight: 600;
|
||||
color: #111824;
|
||||
}
|
||||
}
|
||||
.dark #nd-subnav > div:nth-of-type(2) a {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
@theme {
|
||||
--color-fd-muted: hsl(0, 0%, 96.1%);
|
||||
--color-fd-popover: hsl(0, 0%, 100%);
|
||||
--color-fd-popover-foreground: hsl(0, 0%, 15.1%);
|
||||
--color-fd-card-foreground: hsl(0, 0%, 3.9%);
|
||||
--color-fd-border: hsl(0, 0%, 89.8%);
|
||||
--color-fd-primary-foreground: hsl(0, 0%, 98%);
|
||||
--color-fd-secondary-foreground: hsl(0, 0%, 9%);
|
||||
--color-fd-accent: hsl(0, 0%, 94.1%);
|
||||
--color-fd-ring: hsl(0, 0%, 63.9%);
|
||||
|
||||
--color-fd-background: hsl(0, 0%, 100%);
|
||||
--color-fd-card: hsl(0, 0%, 100%);
|
||||
--color-fd-foreground: hsl(240, 6%, 25%);
|
||||
--color-fd-muted-foreground: hsl(240, 6%, 50%);
|
||||
--color-fd-secondary: hsl(240, 6%, 97%);
|
||||
--color-fd-accent-foreground: hsl(240, 6%, 25%);
|
||||
--color-fd-primary: hsl(226, 55%, 45%);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--color-fd-background: #000000;
|
||||
--color-fd-foreground: hsl(220, 60%, 94.5%);
|
||||
--color-fd-muted: hsl(220, 50%, 10%);
|
||||
--color-fd-muted-foreground: #B0B0B0;
|
||||
--color-fd-popover: hsl(220, 50%, 10%);
|
||||
--color-fd-popover-foreground: hsl(220, 60%, 94.5%);
|
||||
--color-fd-card: hsla(220, 56%, 15%, 0.4);
|
||||
--color-fd-card-foreground: hsl(220, 60%, 94.5%);
|
||||
--color-fd-border: hsla(220, 50%, 50%, 0.2);
|
||||
--color-fd-primary: #C2D3FF; /* 文本高亮色 */
|
||||
--color-fd-primary-foreground: hsl(0, 0%, 9%);
|
||||
--color-fd-secondary: hsl(220, 50%, 20%);
|
||||
--color-fd-secondary-foreground: hsl(220, 80%, 90%);
|
||||
--color-fd-accent: hsl(220, 40%, 20%);
|
||||
--color-fd-accent-foreground: hsl(220, 80%, 90%);
|
||||
--color-fd-ring: hsl(205, 100%, 85%);
|
||||
}
|
||||
|
||||
#nd-sidebar {
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
button[data-search-full] {
|
||||
background-color: var(--color-fd-background);
|
||||
}
|
||||
|
||||
.dark\:text-blue-400:where(.dark, .dark *) {
|
||||
color: #C2D3FF;
|
||||
background-color: #434548;
|
||||
}
|
||||
|
||||
|
||||
.dark div[role="tabpanel"].bg-fd-background {
|
||||
background-color: #1E1E1E;
|
||||
}
|
||||
|
||||
div[role="tabpanel"].bg-fd-background {
|
||||
background-color: #F7F7F8;
|
||||
}
|
||||
|
||||
div[role="tabpanel"].bg-fd-background > div > ul {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.dark div[role="tabpanel"].bg-fd-background > div > ul {
|
||||
margin: 0;
|
||||
background-color: #1E1E1E;
|
||||
}
|
||||
|
||||
div[role="tabpanel"].bg-fd-background > div > ul > li {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button[role="tab"] {
|
||||
padding-top: 16px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
35
document/app/layout.config.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
|
||||
import { i18n } from '@/lib/i18n';
|
||||
|
||||
/**
|
||||
* Shared layout configurations
|
||||
*
|
||||
* you can customise layouts individually from:
|
||||
* Home Layout: app/(home)/layout.tsx
|
||||
* Docs Layout: app/docs/layout.tsx
|
||||
*/
|
||||
export const baseOptions = (locale: string): BaseLayoutProps => {
|
||||
return {
|
||||
themeSwitch: {
|
||||
enabled: true,
|
||||
mode: 'light-dark'
|
||||
},
|
||||
nav: {
|
||||
title: (
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<img src="/FastGPT-full.svg" alt="FastGPT" width={49} height={48} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
// i18n: {
|
||||
// languages: ['zh-CN', 'en'],
|
||||
// defaultLanguage: 'zh-CN',
|
||||
// hideLocale: 'always'
|
||||
// },
|
||||
searchToggle: {
|
||||
enabled: true
|
||||
}
|
||||
};
|
||||
};
|
||||
21
document/app/static.json/route.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { type DocumentRecord } from 'fumadocs-core/search/algolia';
|
||||
import { source } from '@/lib/source';
|
||||
|
||||
export const revalidate = false;
|
||||
|
||||
export function GET() {
|
||||
const results: DocumentRecord[] = [];
|
||||
|
||||
for (const page of source.getPages()) {
|
||||
results.push({
|
||||
_id: page.url,
|
||||
structured: page.data.structuredData,
|
||||
url: page.url,
|
||||
title: page.data.title,
|
||||
description: page.data.description
|
||||
});
|
||||
}
|
||||
|
||||
return NextResponse.json(results);
|
||||
}
|
||||
38
document/components/CustomSearchDialog.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
'use client';
|
||||
// components/CustomSearchDialog.tsx
|
||||
import { useDocsSearch } from 'fumadocs-core/search/client';
|
||||
import {
|
||||
SearchDialog,
|
||||
SearchDialogOverlay,
|
||||
SearchDialogContent,
|
||||
SearchDialogHeader,
|
||||
SearchDialogIcon,
|
||||
SearchDialogInput,
|
||||
SearchDialogClose,
|
||||
SearchDialogList,
|
||||
type SharedProps
|
||||
} from 'fumadocs-ui/components/dialog/search';
|
||||
import { useI18n } from 'fumadocs-ui/contexts/i18n';
|
||||
|
||||
export default function CustomSearchDialog(props: SharedProps) {
|
||||
const { locale } = useI18n();
|
||||
const { search, setSearch, query } = useDocsSearch({
|
||||
type: 'fetch',
|
||||
api: '/api/search',
|
||||
locale
|
||||
});
|
||||
|
||||
return (
|
||||
<SearchDialog search={search} onSearchChange={setSearch} isLoading={query.isLoading} {...props}>
|
||||
<SearchDialogOverlay />
|
||||
<SearchDialogContent>
|
||||
<SearchDialogHeader>
|
||||
<SearchDialogIcon />
|
||||
<SearchDialogInput />
|
||||
<SearchDialogClose />
|
||||
</SearchDialogHeader>
|
||||
<SearchDialogList items={query.data !== 'empty' ? query.data : null} />
|
||||
</SearchDialogContent>
|
||||
</SearchDialog>
|
||||
);
|
||||
}
|
||||
35
document/components/docs/Alert.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
interface AlertProps {
|
||||
icon: ReactNode;
|
||||
context: 'success' | 'warning' | 'error' | 'info';
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export function Alert({ icon, context = 'info', children }: AlertProps) {
|
||||
const contextStyles = {
|
||||
success:
|
||||
'bg-green-50 border-green-200 text-green-700 dark:bg-white/5 dark:border-teal-300 dark:text-gray-200',
|
||||
warning:
|
||||
'bg-yellow-50 border-yellow-200 text-yellow-700 dark:dark:bg-white/5 dark:border-indigo-500 dark:text-gray-200',
|
||||
error:
|
||||
'bg-red-50 border-red-200 text-red-700 dark:bg-white/5 dark:border-red-800 dark:text-gray-200',
|
||||
info: 'bg-blue-50 border-blue-200 text-blue-700 dark:bg-white/5 dark:border-blue-400 dark:text-gray-200'
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`
|
||||
${contextStyles[context]}
|
||||
p-4 rounded-lg border
|
||||
flex gap-3 items-baseline
|
||||
shadow-sm
|
||||
transition-all duration-200 ease-in-out
|
||||
hover:shadow-md
|
||||
`}
|
||||
>
|
||||
<div className="text-2xl flex-shrink-0 mt-0.5">{icon}</div>
|
||||
<div className="space-y-2 text-sm leading-relaxed flex-grow">{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
18
document/components/docs/Redirect.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
interface RedirectProps {
|
||||
to: string;
|
||||
}
|
||||
|
||||
export function Redirect({ to }: RedirectProps) {
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
router.push(to);
|
||||
}, [to, router]);
|
||||
|
||||
return null;
|
||||
}
|
||||
38
document/components/docs/Tabs.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState } from 'react';
|
||||
|
||||
interface TabProps {
|
||||
title: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
interface TabsProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const Tab: React.FC<TabProps> = ({ children }) => {
|
||||
return <div>{children}</div>;
|
||||
};
|
||||
|
||||
export const Tabs: React.FC<TabsProps> = ({ children }) => {
|
||||
const tabs = React.Children.toArray(children) as React.ReactElement<TabProps>[];
|
||||
const [activeTab, setActiveTab] = useState(0);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<nav className="nav-tabs">
|
||||
{tabs.map((tab, index) => (
|
||||
<button
|
||||
key={index}
|
||||
className={`nav-link ${activeTab === index ? 'active' : ''}`}
|
||||
onClick={() => setActiveTab(index)}
|
||||
>
|
||||
{tab.props.title}
|
||||
</button>
|
||||
))}
|
||||
</nav>
|
||||
<div className="tab-content">{tabs[activeTab]}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
12
document/components/docs/Video.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
export default function YouTube({ id }: { id: string }) {
|
||||
return (
|
||||
<div className="border-2 border-black">
|
||||
<iframe
|
||||
className="aspect-video w-full"
|
||||
src={`https://www.youtube.com/embed/${id}`}
|
||||
title="YouTube Video Player"
|
||||
allowFullScreen
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
28
document/components/docs/feishuLogoDark.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
const feishuLogoDark: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M17 29C21 29 25 26.9339 28 23.4065C36 14 41.4242 16.8166 44 17.9998C38.5 20.9998 40.5 29.6233 33 35.9998C28.382 39.9259 23.4945 41.014 19 41C12.5231 40.9799 6.86226 37.7637 4 35.4063V16.9998"
|
||||
stroke="#8b9dc1"
|
||||
strokeWidth="4"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M5.64808 15.8669C5.02231 14.9567 3.77715 14.7261 2.86694 15.3519C1.95673 15.9777 1.72615 17.2228 2.35192 18.1331L5.64808 15.8669ZM36.0021 35.7309C36.958 35.1774 37.2843 33.9539 36.7309 32.9979C36.1774 32.042 34.9539 31.7157 33.9979 32.2691L36.0021 35.7309ZM2.35192 18.1331C5.2435 22.339 10.7992 28.144 16.8865 32.2239C19.9345 34.2667 23.217 35.946 26.449 36.7324C29.6946 37.522 33.0451 37.4428 36.0021 35.7309L33.9979 32.2691C32.2049 33.3072 29.9929 33.478 27.3947 32.8458C24.783 32.2103 21.9405 30.7958 19.1135 28.9011C13.4508 25.106 8.2565 19.661 5.64808 15.8669L2.35192 18.1331Z"
|
||||
fill="#8b9dc1"
|
||||
/>
|
||||
<path
|
||||
d="M33.5947 17C32.84 14.7027 30.8551 9.94054 27.5947 7H11.5947C15.2174 10.6757 23.0002 16 27.0002 24"
|
||||
stroke="#8b9dc1"
|
||||
strokeWidth="4"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default feishuLogoDark;
|
||||
28
document/components/docs/feishuLogoLIght.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
const feishuLogoLight: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M17 29C21 29 25 26.9339 28 23.4065C36 14 41.4242 16.8166 44 17.9998C38.5 20.9998 40.5 29.6233 33 35.9998C28.382 39.9259 23.4945 41.014 19 41C12.5231 40.9799 6.86226 37.7637 4 35.4063V16.9998"
|
||||
stroke="#8a8a8a"
|
||||
strokeWidth="4"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M5.64808 15.8669C5.02231 14.9567 3.77715 14.7261 2.86694 15.3519C1.95673 15.9777 1.72615 17.2228 2.35192 18.1331L5.64808 15.8669ZM36.0021 35.7309C36.958 35.1774 37.2843 33.9539 36.7309 32.9979C36.1774 32.042 34.9539 31.7157 33.9979 32.2691L36.0021 35.7309ZM2.35192 18.1331C5.2435 22.339 10.7992 28.144 16.8865 32.2239C19.9345 34.2667 23.217 35.946 26.449 36.7324C29.6946 37.522 33.0451 37.4428 36.0021 35.7309L33.9979 32.2691C32.2049 33.3072 29.9929 33.478 27.3947 32.8458C24.783 32.2103 21.9405 30.7958 19.1135 28.9011C13.4508 25.106 8.2565 19.661 5.64808 15.8669L2.35192 18.1331Z"
|
||||
fill="#8a8a8a"
|
||||
/>
|
||||
<path
|
||||
d="M33.5947 17C32.84 14.7027 30.8551 9.94054 27.5947 7H11.5947C15.2174 10.6757 23.0002 16 27.0002 24"
|
||||
stroke="#8a8a8a"
|
||||
strokeWidth="4"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default feishuLogoLight;
|
||||
16
document/components/docs/githubLogoDark.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
const githubLogoLight: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (
|
||||
<svg width="98" height="98" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 98 98">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z"
|
||||
fill="#8b9dc1"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default githubLogoLight;
|
||||
16
document/components/docs/githubLogoLight.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
const githubLogoLight: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (
|
||||
<svg width="98" height="98" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 98 98">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z"
|
||||
fill="#8a8a8a"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default githubLogoLight;
|
||||
58
document/components/docs/linkFastGPT.tsx
Normal file
@@ -0,0 +1,58 @@
|
||||
'use client';
|
||||
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
type FastGPTLinkProps = {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void;
|
||||
};
|
||||
|
||||
const defaultStyles: React.CSSProperties = {
|
||||
color: '#3370ff',
|
||||
textDecoration: 'none',
|
||||
transition: 'all 0.2s ease-in-out'
|
||||
};
|
||||
|
||||
const hoverStyles: React.CSSProperties = {
|
||||
color: '#2152d9',
|
||||
textDecoration: 'underline'
|
||||
};
|
||||
|
||||
const FastGPTLink = ({ children, className, style, onClick, ...props }: FastGPTLinkProps) => {
|
||||
const href = useMemo(() => {
|
||||
return process.env.FASTGPT_HOME_DOMAIN ?? 'https://fastgpt.io';
|
||||
}, []);
|
||||
|
||||
const [isHovered, setIsHovered] = React.useState(false);
|
||||
|
||||
const combinedStyles = {
|
||||
...defaultStyles,
|
||||
...(isHovered ? hoverStyles : {}),
|
||||
...style
|
||||
};
|
||||
|
||||
return (
|
||||
<a
|
||||
href={href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={className}
|
||||
style={combinedStyles}
|
||||
onMouseEnter={() => setIsHovered(true)}
|
||||
onMouseLeave={() => setIsHovered(false)}
|
||||
onClick={(e) => {
|
||||
if (onClick) {
|
||||
e.preventDefault();
|
||||
onClick(e);
|
||||
}
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(FastGPTLink);
|
||||
127
document/components/docs/logo.tsx
Normal file
127
document/components/docs/logoDark.tsx
Normal file
70
document/components/docs/not-found.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
'use client';
|
||||
import { useEffect } from 'react';
|
||||
import { usePathname, useRouter } from 'next/navigation';
|
||||
|
||||
const exactMap: Record<string, string> = {
|
||||
'/docs': '/docs/introduction',
|
||||
'/docs/intro': '/docs/introduction',
|
||||
'/docs/guide/dashboard/workflow/coreferenceresolution':
|
||||
'/docs/introduction/guide/dashboard/workflow/coreferenceResolution',
|
||||
'/docs/guide/admin/sso_dingtalk':
|
||||
'/docs/introduction/guide/admin/sso#/docs/introduction/guide/admin/sso#钉钉',
|
||||
'/docs/guide/knowledge_base/rag': '/docs/introduction/guide/knowledge_base/RAG',
|
||||
'/docs/commercial/intro/': '/docs/introduction/commercial',
|
||||
'/docs/upgrading/intro/': '/docs/upgrading',
|
||||
'/docs/introduction/shopping_cart/intro/': '/docs/introduction/commercial'
|
||||
};
|
||||
|
||||
const prefixMap: Record<string, string> = {
|
||||
'/docs/development': '/docs/introduction/development',
|
||||
'/docs/FAQ': '/docs/faq',
|
||||
'/docs/guide': '/docs/introduction/guide',
|
||||
'/docs/shopping_cart': '/docs/introduction/shopping_cart',
|
||||
'/docs/agreement': '/docs/protocol'
|
||||
};
|
||||
|
||||
const fallbackRedirect = '/docs/introduction';
|
||||
|
||||
export default function NotFound() {
|
||||
const pathname = usePathname();
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
if (exactMap[pathname]) {
|
||||
window.location.replace(exactMap[pathname]);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const [oldPrefix, newPrefix] of Object.entries(prefixMap)) {
|
||||
if (pathname.startsWith(oldPrefix)) {
|
||||
const rest = pathname.slice(oldPrefix.length);
|
||||
window.location.replace(newPrefix + rest);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const basePath = pathname.replace(/\/$/, '');
|
||||
const res = await fetch(`/api/meta?path=${basePath}`);
|
||||
console.log('res', res);
|
||||
|
||||
if (!res.ok) throw new Error('meta API not found');
|
||||
|
||||
const validPage = await res.json();
|
||||
|
||||
if (validPage) {
|
||||
console.log('validPage', validPage);
|
||||
window.location.replace(validPage);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('meta.json fallback failed:', e);
|
||||
}
|
||||
|
||||
window.location.replace(fallbackRedirect);
|
||||
})();
|
||||
}, [pathname, router]);
|
||||
|
||||
return null;
|
||||
}
|
||||
81
document/components/sideBar.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
'use client';
|
||||
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { useEffect, type FC, type ReactNode } from 'react';
|
||||
import {
|
||||
SidebarItem,
|
||||
SidebarFolder,
|
||||
SidebarFolderTrigger,
|
||||
SidebarFolderContent
|
||||
} from 'fumadocs-ui/components/layout/sidebar';
|
||||
import { type SidebarComponents } from 'fumadocs-ui/components/layout/sidebar';
|
||||
import { type PageTree } from 'fumadocs-core/server';
|
||||
|
||||
const isInFolder = (folder: PageTree.Folder, pathname: string): boolean => {
|
||||
const check = (item: PageTree.Item | PageTree.Folder): boolean => {
|
||||
if ('children' in item) {
|
||||
return item.children
|
||||
.filter(
|
||||
(child): child is PageTree.Item | PageTree.Folder => 'url' in child || 'children' in child
|
||||
)
|
||||
.some(check);
|
||||
}
|
||||
return 'url' in item && item.url === pathname;
|
||||
};
|
||||
return check(folder);
|
||||
};
|
||||
|
||||
const CustomItem: FC<{ item: PageTree.Item }> = ({ item }) => {
|
||||
const pathname = usePathname();
|
||||
const isActive = pathname === item.url;
|
||||
|
||||
useEffect(() => {
|
||||
if (isActive) {
|
||||
const anchor = document.querySelector(`a[href='${item.url}']`);
|
||||
if (anchor) {
|
||||
setTimeout(() => {
|
||||
anchor.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
}, [isActive, item.url]);
|
||||
|
||||
return (
|
||||
<SidebarItem
|
||||
href={item.url}
|
||||
className={`rounded-lg hover:cursor-pointer ${isActive && 'bg-blue-50 font-bold text-[#3370FF] dark:bg-[rgba(104,143,232,0.1)] dark:text-blue-400'}
|
||||
`}
|
||||
>
|
||||
{item.icon}
|
||||
{item.name}
|
||||
</SidebarItem>
|
||||
);
|
||||
};
|
||||
|
||||
const CustomFolder: FC<{ item: PageTree.Folder; level: number; children: ReactNode }> = ({
|
||||
item,
|
||||
level,
|
||||
children
|
||||
}) => {
|
||||
const pathname = usePathname();
|
||||
const shouldExpand = isInFolder(item, pathname);
|
||||
|
||||
return (
|
||||
<SidebarFolder defaultOpen={shouldExpand} className="bg-blue hover:cursor-pointer">
|
||||
<SidebarFolderTrigger className="hover:cursor-pointer">{item.name}</SidebarFolderTrigger>
|
||||
<SidebarFolderContent className="bg-blue hover:cursor-pointer">
|
||||
{children}
|
||||
</SidebarFolderContent>
|
||||
</SidebarFolder>
|
||||
);
|
||||
};
|
||||
|
||||
const CustomSeparator: FC<{ item: PageTree.Separator }> = ({ item }) => (
|
||||
<div className="text-sm font-semibold px-2 py-2 mt-4 mb-2">{item.name}</div>
|
||||
);
|
||||
|
||||
export const CustomSidebarComponents: SidebarComponents = {
|
||||
Item: CustomItem,
|
||||
Folder: CustomFolder,
|
||||
Separator: CustomSeparator
|
||||
};
|
||||
78
document/content/docs/faq/app.mdx
Normal file
@@ -0,0 +1,78 @@
|
||||
---
|
||||
title: 应用使用问题
|
||||
description: FastGPT 常见应用使用问题,包括简易应用、工作流和插件
|
||||
---
|
||||
|
||||
## 多轮对话中如何使连续问题被问题分类节点正确的归类
|
||||
|
||||
问题分类节点具有获取上下文信息的能力,当处理两个关联性较大的问题时,模型的判断准确性往往依赖于这两个问题之间的联系和模型的能力。例如,当用户先问“我该如何使用这个功能?”接着又询问“这个功能有什么限制?”时,模型借助上下文信息,就能够更精准地理解并响应。
|
||||
|
||||
但是,当连续问题之间的关联性较小,模型判断的准确度可能会受到限制。在这种情况下,我们可以引入全局变量的概念来记录分类结果。在后续的问题分类阶段,首先检查全局变量是否存有分类结果。如果有,那么直接沿用该结果;若没有,则让模型自行判断。
|
||||
|
||||
建议:构建批量运行脚本进行测试,评估问题分类的准确性。
|
||||
|
||||
## 定时执行的时机问题
|
||||
|
||||
系统编排配置中的定时执行,如果用户打开分享的连接,停留在那个页面,定时执行触发问题:
|
||||
|
||||
定时执行会在应用发布后生效,会在后台生效。
|
||||
|
||||
## V4.8.18-FIX2中提到“ 1. 修复 HTTP 节点, `{{}}` 格式引用变量兼容问题。建议尽快替换 / 模式取变量,`{{}}` 语法已弃用。”替换`{{}}`引用格式是仅仅只有在http节点,还是所有节点的都会有影响?
|
||||
|
||||
只有 http 节点用到这个语法。
|
||||
|
||||
## 工作流类型的应用在运行预览可以正常提问返回,但是发布免登录窗口之后有问题。
|
||||
|
||||
一般是没正确发布,在工作流右上角点击【保存并发布】。
|
||||
|
||||
## 如何解决猜你想问使用中文回答显示
|
||||
|
||||
注意需要更新到V4.8.17及以上,把猜你想问的提示词改成中文。
|
||||

|
||||
|
||||
## AI对话回答要求中的Markdown语法取消
|
||||
|
||||
修改知识库默认提示词, 默认用的是标准模板提示词,会要求按 Markdown 输出,可以去除该要求:
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
|  |  |
|
||||
|
||||
## 应用在不同来源效果不一致
|
||||
|
||||
Q: 应用在调试和正式发布后,效果不一致;在 API 调用时,效果不一致。
|
||||
|
||||
A: 通常是由于上下文不一致导致,可以在对话日志中,找到对应的记录,并查看运行详情来进行比对。
|
||||
|
||||
| | | |
|
||||
| --- | --- | --- |
|
||||
|  |  |  |
|
||||
在针对知识库的回答要求里有, 要给它配置提示词,不然他就是默认的,默认的里面就有该语法。
|
||||
|
||||
## 工作流操作:一个工作流,以一个问题分类节点开始,根据不同的分类导入到不同的分支,访问相应的知识库和AI对话,AI对话返回内容后,怎么样不进入问题分类节点,而是将问题到知识库搜索,然后把历史记录一起作为背景再次AI查询。
|
||||
|
||||
做个判断器,如果是初次开始对话也就是历史记录为0,就走问题分类;不为零直接走知识库和ai。
|
||||
|
||||
## 实时对话,设置 fastgpt 定时,比如每隔 3000MS 去拿一次 webhook发送过来的消息到AI页面
|
||||
|
||||
定时执行没有这么高频率的去拿信息的,想要实现在企微里面的实时对话的机器人,
|
||||
目前通过低代码的工作流构建应该是不行的,只能自己写代码,然后去调用 FastGPT 的 APIKey 回复。企业微信似乎没有提供「自动监听」群聊消息的接口(或是通过 at 机器人这种触发消息推送)。应该只能发消息给应用,接收这个 https://developer.work.weixin.qq.com/document/path/90238 文档中的消息推送实现实时对话。或者是定时去拿群聊消息,通过这个文档所示的接口https://developer.work.weixin.qq.com/document/path/98914,然后用这个接口 https://developer.work.weixin.qq.com/document/path/90248 去推送消息。
|
||||
|
||||
## 工作流连接数据库
|
||||
|
||||
工作流提供该连接数据库功能,用这个数据库连接的 plugin 可以实现 text2SQL,但是相对危险,不建议做写入等操作。
|
||||
|
||||

|
||||
|
||||
## 关于循环体,协助理解循环体的循环条件和终止条件、循环的方式,循环体内参数调用后、在循环体内属于是局部作用域的参数还是全局作用域的参数
|
||||
|
||||
可理解为 for 函数,传一个数组,每个数据都执行一次。
|
||||
|
||||
## 公式无法正常显示
|
||||
|
||||
添加相关提示词,引导模型按 Markdown 输出公式
|
||||
|
||||
```bash
|
||||
Latex inline: \(x^2\)
|
||||
Latex block: $$e=mc^2$$
|
||||
```
|
||||
14
document/content/docs/faq/chat.mdx
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
title: 聊天框问题
|
||||
description: FastGPT 常见聊天框问题
|
||||
---
|
||||
|
||||
## 我修改了工作台的应用,为什么在“聊天”时没有更新配置?
|
||||
|
||||
应用需要点击发布后,聊天才会更新应用。
|
||||
|
||||
## 浏览器不支持语音输入
|
||||
|
||||
1. 首先需要确保浏览器、电脑本身麦克风权限的开启。
|
||||
2. 确认浏览器允许该站点使用麦克风,并且选择正确的麦克风来源。
|
||||
3. 需有 SSL 证书的站点才可以使用麦克风。
|
||||