Compare commits
85 Commits
v4.9.2-alp
...
v4.9.4-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5db894e3a | ||
|
|
4fc96f6534 | ||
|
|
7ee616515d | ||
|
|
4207ecaaaa | ||
|
|
32ae14f281 | ||
|
|
9670cba607 | ||
|
|
95d5c01db1 | ||
|
|
915569fe79 | ||
|
|
252ad8a611 | ||
|
|
85ce23869d | ||
|
|
e4c4941a50 | ||
|
|
c2e088cf39 | ||
|
|
dc73f47486 | ||
|
|
2f9b83d924 | ||
|
|
9fe95da126 | ||
|
|
d171b2d3d8 | ||
|
|
e54fe1eed6 | ||
|
|
27332743c7 | ||
|
|
5839325f77 | ||
|
|
73c997f7c5 | ||
|
|
ff92dced98 | ||
|
|
7a0747947c | ||
|
|
5ad383bc6e | ||
|
|
c85b719384 | ||
|
|
aeedc2fada | ||
|
|
be34b69f9b | ||
|
|
944774ec5f | ||
|
|
5b21b4b674 | ||
|
|
b0f0afabd2 | ||
|
|
d9aea53d13 | ||
|
|
73db92e4ad | ||
|
|
267cc5702c | ||
|
|
540f321fc9 | ||
|
|
a37c75159f | ||
|
|
0ed99d8c9a | ||
|
|
2d3ae7f944 | ||
|
|
565a966d19 | ||
|
|
8323c2d27e | ||
|
|
4f86a0591c | ||
|
|
14895bbcfd | ||
|
|
ccf9f5be2e | ||
|
|
e5b986b4de | ||
|
|
cf119a9f0f | ||
|
|
05b3062204 | ||
|
|
fed04f0b5d | ||
|
|
96aabdf579 | ||
|
|
e9f75c7e66 | ||
|
|
8b29aae238 | ||
|
|
8999dc5b8c | ||
|
|
17b20270e1 | ||
|
|
9d97b60561 | ||
|
|
f483832749 | ||
|
|
0778508908 | ||
|
|
f3a069bc80 | ||
|
|
2ebb2ccc9c | ||
|
|
484b87478c | ||
|
|
a17623d4ea | ||
|
|
dd2f7bdcfd | ||
|
|
4871a6980f | ||
|
|
64fb09146f | ||
|
|
1fdf947a13 | ||
|
|
ff64a3c039 | ||
|
|
37b4a1919b | ||
|
|
826a53dcb6 | ||
|
|
5a47af6fff | ||
|
|
6ea57e4609 | ||
|
|
2fcf421672 | ||
|
|
a680b565ea | ||
|
|
e812ad6e84 | ||
|
|
222ff0d49a | ||
|
|
2c73e9dc12 | ||
|
|
9918133426 | ||
|
|
8eec8566db | ||
|
|
6a4eada85b | ||
|
|
652ec45bbd | ||
|
|
6fee39873d | ||
|
|
87e90c37bd | ||
|
|
73451dbc64 | ||
|
|
077350e651 | ||
|
|
d52700c645 | ||
|
|
ec30d79286 | ||
|
|
cb29076e5b | ||
|
|
29a10c1389 | ||
|
|
28877373ac | ||
|
|
4538f2a9d4 |
30
.github/gh-bot.yml
vendored
@@ -1,30 +0,0 @@
|
|||||||
version: v1
|
|
||||||
debug: true
|
|
||||||
action:
|
|
||||||
printConfig: false
|
|
||||||
release:
|
|
||||||
retry: 15s
|
|
||||||
actionName: Release
|
|
||||||
allowOps:
|
|
||||||
- cuisongliu
|
|
||||||
bot:
|
|
||||||
prefix: /
|
|
||||||
spe: _
|
|
||||||
allowOps:
|
|
||||||
- sealos-ci-robot
|
|
||||||
- sealos-release-robot
|
|
||||||
email: sealos-ci-robot@sealos.io
|
|
||||||
username: sealos-ci-robot
|
|
||||||
repo:
|
|
||||||
org: false
|
|
||||||
|
|
||||||
message:
|
|
||||||
success: |
|
|
||||||
🤖 says: Hooray! The action {{.Body}} has been completed successfully. 🎉
|
|
||||||
format_error: |
|
|
||||||
🤖 says: ‼️ There is a formatting issue with the action, kindly verify the action's format.
|
|
||||||
permission_error: |
|
|
||||||
🤖 says: ‼️ The action doesn't have permission to trigger.
|
|
||||||
release_error: |
|
|
||||||
🤖 says: ‼️ Release action failed.
|
|
||||||
Error details: {{.Error}}
|
|
||||||
19
.github/workflows/docs-deploy-kubeconfig.yml
vendored
@@ -10,6 +10,13 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
build-fastgpt-docs-images:
|
build-fastgpt-docs-images:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -27,7 +34,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
# list of Docker images to use as base name for tags
|
# list of Docker images to use as base name for tags
|
||||||
images: |
|
images: |
|
||||||
${{ secrets.DOCKER_HUB_NAME }}/fastgpt-docs
|
|
||||||
ghcr.io/${{ github.repository_owner }}/fastgpt-docs
|
ghcr.io/${{ github.repository_owner }}/fastgpt-docs
|
||||||
registry.cn-hangzhou.aliyuncs.com/${{ secrets.ALI_HUB_USERNAME }}/fastgpt-docs
|
registry.cn-hangzhou.aliyuncs.com/${{ secrets.ALI_HUB_USERNAME }}/fastgpt-docs
|
||||||
tags: |
|
tags: |
|
||||||
@@ -40,18 +46,12 @@ jobs:
|
|||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Login to DockerHub
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKER_HUB_NAME }}
|
|
||||||
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
|
||||||
|
|
||||||
- name: Login to ghcr.io
|
- name: Login to ghcr.io
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GH_PAT }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Login to Aliyun
|
- name: Login to Aliyun
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
@@ -70,6 +70,7 @@ jobs:
|
|||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
outputs:
|
outputs:
|
||||||
tags: ${{ steps.datetime.outputs.datetime }}
|
tags: ${{ steps.datetime.outputs.datetime }}
|
||||||
|
|
||||||
update-docs-image:
|
update-docs-image:
|
||||||
needs: build-fastgpt-docs-images
|
needs: build-fastgpt-docs-images
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
|
|||||||
10
.github/workflows/docs-deploy-vercel.yml
vendored
@@ -20,6 +20,11 @@ jobs:
|
|||||||
# The type of runner that the job will run on
|
# The type of runner that the job will run on
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
|
||||||
# Job outputs
|
# Job outputs
|
||||||
outputs:
|
outputs:
|
||||||
docs: ${{ steps.filter.outputs.docs }}
|
docs: ${{ steps.filter.outputs.docs }}
|
||||||
@@ -71,7 +76,8 @@ jobs:
|
|||||||
working-directory: docSite/public
|
working-directory: docSite/public
|
||||||
|
|
||||||
- name: Deploy to GitHub Pages
|
- name: Deploy to GitHub Pages
|
||||||
uses: peaceiris/actions-gh-pages@v3
|
uses: peaceiris/actions-gh-pages@v4
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GH_PAT }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
publish_dir: docSite/public
|
publish_dir: docSite/public
|
||||||
|
|||||||
76
.github/workflows/docs-preview.yml
vendored
@@ -1,7 +1,7 @@
|
|||||||
name: Preview FastGPT docs
|
name: Preview FastGPT docs
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request_target:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- 'docSite/**'
|
- 'docSite/**'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@@ -10,6 +10,12 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
# This workflow contains jobs "deploy-production"
|
# This workflow contains jobs "deploy-production"
|
||||||
deploy-preview:
|
deploy-preview:
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
|
pull-requests: write
|
||||||
# The environment this job references
|
# The environment this job references
|
||||||
environment:
|
environment:
|
||||||
name: Preview
|
name: Preview
|
||||||
@@ -32,6 +38,7 @@ jobs:
|
|||||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||||
submodules: recursive # Fetch submodules
|
submodules: recursive # Fetch submodules
|
||||||
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
|
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
# Step 2 Detect changes to Docs Content
|
# Step 2 Detect changes to Docs Content
|
||||||
- name: Detect changes in doc content
|
- name: Detect changes in doc content
|
||||||
@@ -58,39 +65,38 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: cd docSite && hugo mod get -u github.com/colinwilson/lotusdocs@6d0568e && hugo -v --minify
|
run: cd docSite && hugo mod get -u github.com/colinwilson/lotusdocs@6d0568e && hugo -v --minify
|
||||||
|
|
||||||
# Step 5 - Push our generated site to Vercel
|
- name: Test
|
||||||
- name: Deploy to Vercel
|
run: ls ./docSite/public
|
||||||
uses: amondnet/vercel-action@v25
|
|
||||||
id: vercel-action
|
# Step 5 - Push our generated site to Cloudflare
|
||||||
|
- name: Deploy to Cloudflare Pages
|
||||||
|
id: deploy
|
||||||
|
uses: cloudflare/wrangler-action@v3
|
||||||
with:
|
with:
|
||||||
vercel-token: ${{ secrets.VERCEL_TOKEN }} # Required
|
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||||
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }} #Required
|
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||||
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }} #Required
|
command: pages deploy ./docSite/public --project-name=fastgpt-doc
|
||||||
github-comment: false
|
packageManager: npm
|
||||||
vercel-args: '--local-config ../vercel.json' # Optional
|
|
||||||
working-directory: docSite/public
|
- name: Create deployment status comment
|
||||||
alias-domains: | #Optional
|
if: always()
|
||||||
fastgpt-staging.vercel.app
|
|
||||||
docsOutput:
|
|
||||||
needs: [deploy-preview]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.head.ref }}
|
|
||||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
|
||||||
- name: Write md
|
|
||||||
run: |
|
|
||||||
echo "# 🤖 Generated by deploy action" > report.md
|
|
||||||
echo "[👀 Visit Preview](${{ needs.deploy-preview.outputs.url }})" >> report.md
|
|
||||||
cat report.md
|
|
||||||
- name: Gh Rebot for Sealos
|
|
||||||
uses: labring/gh-rebot@v0.0.6
|
|
||||||
if: ${{ (github.event_name == 'pull_request_target') }}
|
|
||||||
with:
|
|
||||||
version: v0.0.6
|
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: '${{ secrets.GH_PAT }}'
|
JOB_STATUS: ${{ job.status }}
|
||||||
SEALOS_TYPE: 'pr_comment'
|
PREVIEW_URL: ${{ steps.deploy.outputs.deployment-url }}
|
||||||
SEALOS_FILENAME: 'report.md'
|
uses: actions/github-script@v6
|
||||||
SEALOS_REPLACE_TAG: 'DEFAULT_REPLACE_DEPLOY'
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
script: |
|
||||||
|
const success = process.env.JOB_STATUS === 'success';
|
||||||
|
const deploymentUrl = `${process.env.PREVIEW_URL}`;
|
||||||
|
const status = success ? '✅ Success' : '❌ Failed';
|
||||||
|
console.log(process.env.JOB_STATUS);
|
||||||
|
|
||||||
|
const commentBody = `**Deployment Status: ${status}**
|
||||||
|
${success ? `🔗 Preview URL: ${deploymentUrl}` : ''}`;
|
||||||
|
|
||||||
|
await github.rest.issues.createComment({
|
||||||
|
...context.repo,
|
||||||
|
issue_number: context.payload.pull_request.number,
|
||||||
|
body: commentBody
|
||||||
|
});
|
||||||
|
|||||||
11
.github/workflows/docs-sync_imgs.yml
vendored
@@ -1,6 +1,6 @@
|
|||||||
name: Sync images
|
name: Sync images
|
||||||
on:
|
on:
|
||||||
pull_request_target:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
paths:
|
paths:
|
||||||
@@ -15,13 +15,6 @@ jobs:
|
|||||||
sync:
|
sync:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
if: ${{ (github.event_name == 'pull_request_target') }}
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.head.ref }}
|
|
||||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
@@ -32,4 +25,4 @@ jobs:
|
|||||||
CONFIG_PATH: .github/sync_imgs.yml
|
CONFIG_PATH: .github/sync_imgs.yml
|
||||||
ORIGINAL_MESSAGE: true
|
ORIGINAL_MESSAGE: true
|
||||||
SKIP_PR: true
|
SKIP_PR: true
|
||||||
COMMIT_EACH_FILE: false
|
COMMIT_EACH_FILE: false
|
||||||
|
|||||||
@@ -9,6 +9,11 @@ on:
|
|||||||
- 'main'
|
- 'main'
|
||||||
jobs:
|
jobs:
|
||||||
build-fastgpt-images:
|
build-fastgpt-images:
|
||||||
|
permissions:
|
||||||
|
packages: write
|
||||||
|
contents: read
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
if: github.repository != 'labring/FastGPT'
|
if: github.repository != 'labring/FastGPT'
|
||||||
steps:
|
steps:
|
||||||
@@ -32,7 +37,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GH_PAT }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Set DOCKER_REPO_TAGGED based on branch or tag
|
- name: Set DOCKER_REPO_TAGGED based on branch or tag
|
||||||
run: |
|
run: |
|
||||||
echo "DOCKER_REPO_TAGGED=ghcr.io/${{ github.repository_owner }}/fastgpt:latest" >> $GITHUB_ENV
|
echo "DOCKER_REPO_TAGGED=ghcr.io/${{ github.repository_owner }}/fastgpt:latest" >> $GITHUB_ENV
|
||||||
|
|||||||
21
.github/workflows/fastgpt-build-image.yml
vendored
@@ -9,6 +9,11 @@ on:
|
|||||||
- 'v*'
|
- 'v*'
|
||||||
jobs:
|
jobs:
|
||||||
build-fastgpt-images:
|
build-fastgpt-images:
|
||||||
|
permissions:
|
||||||
|
packages: write
|
||||||
|
contents: read
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
# install env
|
# install env
|
||||||
@@ -39,7 +44,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GH_PAT }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Login to Ali Hub
|
- name: Login to Ali Hub
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
@@ -91,6 +96,11 @@ jobs:
|
|||||||
-t ${Docker_Hub_Latest} \
|
-t ${Docker_Hub_Latest} \
|
||||||
.
|
.
|
||||||
build-fastgpt-images-sub-route:
|
build-fastgpt-images-sub-route:
|
||||||
|
permissions:
|
||||||
|
packages: write
|
||||||
|
contents: read
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
# install env
|
# install env
|
||||||
@@ -121,7 +131,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GH_PAT }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Login to Ali Hub
|
- name: Login to Ali Hub
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
@@ -174,6 +184,11 @@ jobs:
|
|||||||
-t ${Docker_Hub_Latest} \
|
-t ${Docker_Hub_Latest} \
|
||||||
.
|
.
|
||||||
build-fastgpt-images-sub-route-gchat:
|
build-fastgpt-images-sub-route-gchat:
|
||||||
|
permissions:
|
||||||
|
packages: write
|
||||||
|
contents: read
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
# install env
|
# install env
|
||||||
@@ -204,7 +219,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GH_PAT }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Login to Ali Hub
|
- name: Login to Ali Hub
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
|
|||||||
40
.github/workflows/fastgpt-preview-image.yml
vendored
@@ -5,6 +5,13 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
preview-fastgpt-images:
|
preview-fastgpt-images:
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -12,8 +19,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.ref }}
|
ref: ${{ github.event.pull_request.head.ref }}
|
||||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||||
submodules: recursive # Fetch submodules
|
|
||||||
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
|
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v2
|
||||||
with:
|
with:
|
||||||
@@ -25,15 +33,18 @@ jobs:
|
|||||||
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-buildx-
|
${{ runner.os }}-buildx-
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GH_PAT }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set DOCKER_REPO_TAGGED based on branch or tag
|
- name: Set DOCKER_REPO_TAGGED based on branch or tag
|
||||||
run: |
|
run: |
|
||||||
echo "DOCKER_REPO_TAGGED=ghcr.io/${{ github.repository_owner }}/fastgpt-pr:${{ github.event.pull_request.head.sha }}" >> $GITHUB_ENV
|
echo "DOCKER_REPO_TAGGED=ghcr.io/${{ github.repository_owner }}/fastgpt-pr:${{ github.event.pull_request.head.sha }}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Build image for PR
|
- name: Build image for PR
|
||||||
env:
|
env:
|
||||||
DOCKER_REPO_TAGGED: ${{ env.DOCKER_REPO_TAGGED }}
|
DOCKER_REPO_TAGGED: ${{ env.DOCKER_REPO_TAGGED }}
|
||||||
@@ -48,20 +59,13 @@ jobs:
|
|||||||
--cache-to=type=local,dest=/tmp/.buildx-cache \
|
--cache-to=type=local,dest=/tmp/.buildx-cache \
|
||||||
-t ${DOCKER_REPO_TAGGED} \
|
-t ${DOCKER_REPO_TAGGED} \
|
||||||
.
|
.
|
||||||
# Add write md step after build
|
- uses: actions/github-script@v7
|
||||||
- name: Write md
|
|
||||||
run: |
|
|
||||||
echo "# 🤖 Generated by deploy action" > report.md
|
|
||||||
echo "📦 Preview Image: \`${DOCKER_REPO_TAGGED}\`" >> report.md
|
|
||||||
cat report.md
|
|
||||||
|
|
||||||
- name: Gh Rebot for Sealos
|
|
||||||
uses: labring/gh-rebot@v0.0.6
|
|
||||||
if: ${{ (github.event_name == 'pull_request_target') }}
|
|
||||||
with:
|
with:
|
||||||
version: v0.0.6
|
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||||
env:
|
script: |
|
||||||
GH_TOKEN: '${{ secrets.GH_PAT }}'
|
github.rest.issues.createComment({
|
||||||
SEALOS_TYPE: 'pr_comment'
|
issue_number: context.issue.number,
|
||||||
SEALOS_FILENAME: 'report.md'
|
owner: context.repo.owner,
|
||||||
SEALOS_REPLACE_TAG: 'DEFAULT_REPLACE_DEPLOY'
|
repo: context.repo.repo,
|
||||||
|
body: 'Preview Image: `${{ env.DOCKER_REPO_TAGGED }}`'
|
||||||
|
})
|
||||||
|
|||||||
7
.github/workflows/helm-release.yaml
vendored
@@ -8,6 +8,11 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
helm:
|
helm:
|
||||||
|
permissions:
|
||||||
|
packages: write
|
||||||
|
contents: read
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -20,7 +25,7 @@ jobs:
|
|||||||
run: echo "tag=$(git describe --tags)" >> $GITHUB_OUTPUT
|
run: echo "tag=$(git describe --tags)" >> $GITHUB_OUTPUT
|
||||||
- name: Release Helm
|
- name: Release Helm
|
||||||
run: |
|
run: |
|
||||||
echo ${{ secrets.GH_PAT }} | helm registry login ghcr.io -u ${{ github.repository_owner }} --password-stdin
|
echo ${{ secrets.GITHUB_TOKEN }} | helm registry login ghcr.io -u ${{ github.repository_owner }} --password-stdin
|
||||||
export APP_VERSION=${{ steps.vars.outputs.tag }}
|
export APP_VERSION=${{ steps.vars.outputs.tag }}
|
||||||
export HELM_VERSION=${{ steps.vars.outputs.tag }}
|
export HELM_VERSION=${{ steps.vars.outputs.tag }}
|
||||||
export HELM_REPO=ghcr.io/${{ github.repository_owner }}
|
export HELM_REPO=ghcr.io/${{ github.repository_owner }}
|
||||||
|
|||||||
7
.github/workflows/sandbox-build-image.yml
vendored
@@ -8,6 +8,11 @@ on:
|
|||||||
- 'v*'
|
- 'v*'
|
||||||
jobs:
|
jobs:
|
||||||
build-fastgpt-sandbox-images:
|
build-fastgpt-sandbox-images:
|
||||||
|
permissions:
|
||||||
|
packages: write
|
||||||
|
contents: read
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
# install env
|
# install env
|
||||||
@@ -38,7 +43,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GH_PAT }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Login to Ali Hub
|
- name: Login to Ali Hub
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
|
|||||||
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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -110,19 +110,31 @@ services:
|
|||||||
|
|
||||||
# 等待docker-entrypoint.sh脚本执行的MongoDB服务进程
|
# 等待docker-entrypoint.sh脚本执行的MongoDB服务进程
|
||||||
wait $$!
|
wait $$!
|
||||||
|
redis:
|
||||||
|
image: redis:7.2-alpine
|
||||||
|
container_name: redis
|
||||||
|
# ports:
|
||||||
|
# - 6379:6379
|
||||||
|
networks:
|
||||||
|
- fastgpt
|
||||||
|
restart: always
|
||||||
|
command: |
|
||||||
|
redis-server --requirepass mypassword --loglevel warning --maxclients 10000 --appendonly yes --save 60 10 --maxmemory 4gb --maxmemory-policy noeviction
|
||||||
|
volumes:
|
||||||
|
- ./redis/data:/data
|
||||||
|
|
||||||
# fastgpt
|
# fastgpt
|
||||||
sandbox:
|
sandbox:
|
||||||
container_name: sandbox
|
container_name: sandbox
|
||||||
image: ghcr.io/labring/fastgpt-sandbox:v4.9.1-fix2 # git
|
image: ghcr.io/labring/fastgpt-sandbox:v4.9.3 # git
|
||||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.9.1-fix2 # 阿里云
|
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.9.3 # 阿里云
|
||||||
networks:
|
networks:
|
||||||
- fastgpt
|
- fastgpt
|
||||||
restart: always
|
restart: always
|
||||||
fastgpt:
|
fastgpt:
|
||||||
container_name: fastgpt
|
container_name: fastgpt
|
||||||
image: ghcr.io/labring/fastgpt:v4.9.1-fix2 # git
|
image: ghcr.io/labring/fastgpt:v4.9.3 # git
|
||||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.9.1-fix2 # 阿里云
|
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.9.3 # 阿里云
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000
|
- 3000:3000
|
||||||
networks:
|
networks:
|
||||||
@@ -157,6 +169,8 @@ services:
|
|||||||
# zilliz 连接参数
|
# zilliz 连接参数
|
||||||
- MILVUS_ADDRESS=http://milvusStandalone:19530
|
- MILVUS_ADDRESS=http://milvusStandalone:19530
|
||||||
- MILVUS_TOKEN=none
|
- MILVUS_TOKEN=none
|
||||||
|
# Redis 地址
|
||||||
|
- REDIS_URL=redis://default:mypassword@redis:6379
|
||||||
# sandbox 地址
|
# sandbox 地址
|
||||||
- SANDBOX_URL=http://sandbox:3000
|
- SANDBOX_URL=http://sandbox:3000
|
||||||
# 日志等级: debug, info, warn, error
|
# 日志等级: debug, info, warn, error
|
||||||
|
|||||||
@@ -69,18 +69,31 @@ services:
|
|||||||
# 等待docker-entrypoint.sh脚本执行的MongoDB服务进程
|
# 等待docker-entrypoint.sh脚本执行的MongoDB服务进程
|
||||||
wait $$!
|
wait $$!
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:7.2-alpine
|
||||||
|
container_name: redis
|
||||||
|
# ports:
|
||||||
|
# - 6379:6379
|
||||||
|
networks:
|
||||||
|
- fastgpt
|
||||||
|
restart: always
|
||||||
|
command: |
|
||||||
|
redis-server --requirepass mypassword --loglevel warning --maxclients 10000 --appendonly yes --save 60 10 --maxmemory 4gb --maxmemory-policy noeviction
|
||||||
|
volumes:
|
||||||
|
- ./redis/data:/data
|
||||||
|
|
||||||
# fastgpt
|
# fastgpt
|
||||||
sandbox:
|
sandbox:
|
||||||
container_name: sandbox
|
container_name: sandbox
|
||||||
image: ghcr.io/labring/fastgpt-sandbox:v4.9.1-fix2 # git
|
image: ghcr.io/labring/fastgpt-sandbox:v4.9.3 # git
|
||||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.9.1-fix2 # 阿里云
|
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.9.3 # 阿里云
|
||||||
networks:
|
networks:
|
||||||
- fastgpt
|
- fastgpt
|
||||||
restart: always
|
restart: always
|
||||||
fastgpt:
|
fastgpt:
|
||||||
container_name: fastgpt
|
container_name: fastgpt
|
||||||
image: ghcr.io/labring/fastgpt:v4.9.1-fix2 # git
|
image: ghcr.io/labring/fastgpt:v4.9.3 # git
|
||||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.9.1-fix2 # 阿里云
|
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.9.3 # 阿里云
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000
|
- 3000:3000
|
||||||
networks:
|
networks:
|
||||||
@@ -114,6 +127,8 @@ services:
|
|||||||
- MONGODB_URI=mongodb://myusername:mypassword@mongo:27017/fastgpt?authSource=admin
|
- MONGODB_URI=mongodb://myusername:mypassword@mongo:27017/fastgpt?authSource=admin
|
||||||
# pg 连接参数
|
# pg 连接参数
|
||||||
- PG_URL=postgresql://username:password@pg:5432/postgres
|
- PG_URL=postgresql://username:password@pg:5432/postgres
|
||||||
|
# Redis 连接参数
|
||||||
|
- REDIS_URL=redis://default:mypassword@redis:6379
|
||||||
# sandbox 地址
|
# sandbox 地址
|
||||||
- SANDBOX_URL=http://sandbox:3000
|
- SANDBOX_URL=http://sandbox:3000
|
||||||
# 日志等级: debug, info, warn, error
|
# 日志等级: debug, info, warn, error
|
||||||
@@ -132,7 +147,7 @@ services:
|
|||||||
|
|
||||||
# AI Proxy
|
# AI Proxy
|
||||||
aiproxy:
|
aiproxy:
|
||||||
image: ghcr.io/labring/aiproxy:v0.1.3
|
image: ghcr.io/labring/aiproxy:v0.1.5
|
||||||
# image: registry.cn-hangzhou.aliyuncs.com/labring/aiproxy:v0.1.3 # 阿里云
|
# image: registry.cn-hangzhou.aliyuncs.com/labring/aiproxy:v0.1.3 # 阿里云
|
||||||
container_name: aiproxy
|
container_name: aiproxy
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|||||||
@@ -51,17 +51,30 @@ services:
|
|||||||
|
|
||||||
# 等待docker-entrypoint.sh脚本执行的MongoDB服务进程
|
# 等待docker-entrypoint.sh脚本执行的MongoDB服务进程
|
||||||
wait $$!
|
wait $$!
|
||||||
|
redis:
|
||||||
|
image: redis:7.2-alpine
|
||||||
|
container_name: redis
|
||||||
|
# ports:
|
||||||
|
# - 6379:6379
|
||||||
|
networks:
|
||||||
|
- fastgpt
|
||||||
|
restart: always
|
||||||
|
command: |
|
||||||
|
redis-server --requirepass mypassword --loglevel warning --maxclients 10000 --appendonly yes --save 60 10 --maxmemory 4gb --maxmemory-policy noeviction
|
||||||
|
volumes:
|
||||||
|
- ./redis/data:/data
|
||||||
|
|
||||||
sandbox:
|
sandbox:
|
||||||
container_name: sandbox
|
container_name: sandbox
|
||||||
image: ghcr.io/labring/fastgpt-sandbox:v4.9.1-fix2 # git
|
image: ghcr.io/labring/fastgpt-sandbox:v4.9.3 # git
|
||||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.9.1-fix2 # 阿里云
|
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sandbox:v4.9.3 # 阿里云
|
||||||
networks:
|
networks:
|
||||||
- fastgpt
|
- fastgpt
|
||||||
restart: always
|
restart: always
|
||||||
fastgpt:
|
fastgpt:
|
||||||
container_name: fastgpt
|
container_name: fastgpt
|
||||||
image: ghcr.io/labring/fastgpt:v4.9.1-fix2 # git
|
image: ghcr.io/labring/fastgpt:v4.9.3 # git
|
||||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.9.1-fix2 # 阿里云
|
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.9.3 # 阿里云
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000
|
- 3000:3000
|
||||||
networks:
|
networks:
|
||||||
@@ -92,6 +105,8 @@ services:
|
|||||||
- FILE_TOKEN_KEY=filetoken
|
- FILE_TOKEN_KEY=filetoken
|
||||||
# MongoDB 连接参数. 用户名myusername,密码mypassword。
|
# MongoDB 连接参数. 用户名myusername,密码mypassword。
|
||||||
- MONGODB_URI=mongodb://myusername:mypassword@mongo:27017/fastgpt?authSource=admin
|
- MONGODB_URI=mongodb://myusername:mypassword@mongo:27017/fastgpt?authSource=admin
|
||||||
|
# Redis 连接参数
|
||||||
|
- REDIS_URI=redis://default:mypassword@redis:6379
|
||||||
# zilliz 连接参数
|
# zilliz 连接参数
|
||||||
- MILVUS_ADDRESS=zilliz_cloud_address
|
- MILVUS_ADDRESS=zilliz_cloud_address
|
||||||
- MILVUS_TOKEN=zilliz_cloud_token
|
- MILVUS_TOKEN=zilliz_cloud_token
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ data:
|
|||||||
"vectorMaxProcess": 15,
|
"vectorMaxProcess": 15,
|
||||||
"qaMaxProcess": 15,
|
"qaMaxProcess": 15,
|
||||||
"vlmMaxProcess": 15,
|
"vlmMaxProcess": 15,
|
||||||
"pgHNSWEfSearch": 100
|
"hnswEfSearch": 100
|
||||||
},
|
},
|
||||||
"llmModels": [
|
"llmModels": [
|
||||||
{
|
{
|
||||||
|
|||||||
BIN
docSite/assets/imgs/chunkReader1.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
docSite/assets/imgs/chunkReader2.jpg
Normal file
|
After Width: | Height: | Size: 159 KiB |
BIN
docSite/assets/imgs/chunkReader3.webp
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
docSite/assets/imgs/chunkReader4.jpg
Normal file
|
After Width: | Height: | Size: 139 KiB |
BIN
docSite/assets/imgs/chunkReader5.jpg
Normal file
|
After Width: | Height: | Size: 57 KiB |
BIN
docSite/assets/imgs/chunkReader6.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
docSite/assets/imgs/chunkReader7.jpg
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
docSite/assets/imgs/chunkReader8.png
Normal file
|
After Width: | Height: | Size: 197 KiB |
BIN
docSite/assets/imgs/chunkReader9.jpg
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
docSite/assets/imgs/sealos-redis1.png
Normal file
|
After Width: | Height: | Size: 284 KiB |
BIN
docSite/assets/imgs/sealos-redis2.png
Normal file
|
After Width: | Height: | Size: 294 KiB |
BIN
docSite/assets/imgs/sealos-redis3.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
docSite/assets/imgs/sso1.png
Normal file
|
After Width: | Height: | Size: 133 KiB |
BIN
docSite/assets/imgs/sso10.png
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
docSite/assets/imgs/sso11.png
Normal file
|
After Width: | Height: | Size: 117 KiB |
BIN
docSite/assets/imgs/sso12.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
docSite/assets/imgs/sso13.png
Normal file
|
After Width: | Height: | Size: 319 KiB |
BIN
docSite/assets/imgs/sso14.png
Normal file
|
After Width: | Height: | Size: 174 KiB |
BIN
docSite/assets/imgs/sso15.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
docSite/assets/imgs/sso16.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
docSite/assets/imgs/sso17.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
docSite/assets/imgs/sso18.png
Normal file
|
After Width: | Height: | Size: 177 KiB |
BIN
docSite/assets/imgs/sso2.png
Normal file
|
After Width: | Height: | Size: 255 KiB |
BIN
docSite/assets/imgs/sso3.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
docSite/assets/imgs/sso4.png
Normal file
|
After Width: | Height: | Size: 117 KiB |
BIN
docSite/assets/imgs/sso5.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
docSite/assets/imgs/sso6.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
docSite/assets/imgs/sso7.png
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
docSite/assets/imgs/sso8.png
Normal file
|
After Width: | Height: | Size: 108 KiB |
BIN
docSite/assets/imgs/sso9.png
Normal file
|
After Width: | Height: | Size: 119 KiB |
BIN
docSite/assets/imgs/sso_update1.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
docSite/assets/imgs/teammode.png
Normal file
|
After Width: | Height: | Size: 265 KiB |
@@ -25,7 +25,7 @@ weight: 707
|
|||||||
"qaMaxProcess": 15, // 问答拆分线程数量
|
"qaMaxProcess": 15, // 问答拆分线程数量
|
||||||
"vlmMaxProcess": 15, // 图片理解模型最大处理进程
|
"vlmMaxProcess": 15, // 图片理解模型最大处理进程
|
||||||
"tokenWorkers": 50, // Token 计算线程保持数,会持续占用内存,不能设置太大。
|
"tokenWorkers": 50, // Token 计算线程保持数,会持续占用内存,不能设置太大。
|
||||||
"pgHNSWEfSearch": 100, // 向量搜索参数。越大,搜索越精确,但是速度越慢。设置为100,有99%+精度。
|
"hnswEfSearch": 100, // 向量搜索参数,仅对 PG 和 OB 生效。越大,搜索越精确,但是速度越慢。设置为100,有99%+精度。
|
||||||
"customPdfParse": { // 4.9.0 新增配置
|
"customPdfParse": { // 4.9.0 新增配置
|
||||||
"url": "", // 自定义 PDF 解析服务地址
|
"url": "", // 自定义 PDF 解析服务地址
|
||||||
"key": "", // 自定义 PDF 解析服务密钥
|
"key": "", // 自定义 PDF 解析服务密钥
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ weight: 920
|
|||||||
|
|
||||||
3 个模型代码分别为:
|
3 个模型代码分别为:
|
||||||
|
|
||||||
1. [https://github.com/labring/FastGPT/tree/main/plugins/rerank-bge/bge-reranker-base](https://github.com/labring/FastGPT/tree/main/plugins/rerank-bge/bge-reranker-base)
|
1. [https://github.com/labring/FastGPT/tree/main/plugins/model/rerank-bge/bge-reranker-base](https://github.com/labring/FastGPT/tree/main/plugins/model/rerank-bge/bge-reranker-base)
|
||||||
2. [https://github.com/labring/FastGPT/tree/main/plugins/rerank-bge/bge-reranker-large](https://github.com/labring/FastGPT/tree/main/plugins/rerank-bge/bge-reranker-large)
|
2. [https://github.com/labring/FastGPT/tree/main/plugins/model/rerank-bge/bge-reranker-large](https://github.com/labring/FastGPT/tree/main/plugins/model/rerank-bge/bge-reranker-large)
|
||||||
3. [https://github.com/labring/FastGPT/tree/main/plugins/rerank-bge/bge-reranker-v2-m3](https://github.com/labring/FastGPT/tree/main/plugins/rerank-bge/bge-reranker-v2-m3)
|
3. [https://github.com/labring/FastGPT/tree/main/plugins/model/rerank-bge/bge-reranker-v2-m3](https://github.com/labring/FastGPT/tree/main/plugins/model/rerank-bge/bge-reranker-v2-m3)
|
||||||
|
|
||||||
### 3. 安装依赖
|
### 3. 安装依赖
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ ChatGLM2-6B 是开源中英双语对话模型 ChatGLM-6B 的第二代版本,
|
|||||||
### 源码部署
|
### 源码部署
|
||||||
|
|
||||||
1. 根据上面的环境配置配置好环境,具体教程自行 GPT;
|
1. 根据上面的环境配置配置好环境,具体教程自行 GPT;
|
||||||
2. 下载 [python 文件](https://github.com/labring/FastGPT/blob/main/files/models/ChatGLM2/openai_api.py)
|
2. 下载 [python 文件](https://github.com/labring/FastGPT/blob/main/plugins/model/llm-ChatGLM2/openai_api.py)
|
||||||
3. 在命令行输入命令 `pip install -r requirements.txt`;
|
3. 在命令行输入命令 `pip install -r requirements.txt`;
|
||||||
4. 打开你需要启动的 py 文件,在代码的 `verify_token` 方法中配置 token,这里的 token 只是加一层验证,防止接口被人盗用;
|
4. 打开你需要启动的 py 文件,在代码的 `verify_token` 方法中配置 token,这里的 token 只是加一层验证,防止接口被人盗用;
|
||||||
5. 执行命令 `python openai_api.py --model_name 16`。这里的数字根据上面的配置进行选择。
|
5. 执行命令 `python openai_api.py --model_name 16`。这里的数字根据上面的配置进行选择。
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ Mongo 数据库需要注意,需要注意在连接地址中增加 `directConnec
|
|||||||
- `vectorMaxProcess`: 向量生成最大进程,根据数据库和 key 的并发数来决定,通常单个 120 号,2c4g 服务器设置 10~15。
|
- `vectorMaxProcess`: 向量生成最大进程,根据数据库和 key 的并发数来决定,通常单个 120 号,2c4g 服务器设置 10~15。
|
||||||
- `qaMaxProcess`: QA 生成最大进程
|
- `qaMaxProcess`: QA 生成最大进程
|
||||||
- `vlmMaxProcess`: 图片理解模型最大进程
|
- `vlmMaxProcess`: 图片理解模型最大进程
|
||||||
- `pgHNSWEfSearch`: PostgreSQL vector 索引参数,越大搜索精度越高但是速度越慢,具体可看 pgvector 官方说明。
|
- `hnswEfSearch`: 向量搜索参数,仅对 PG 和 OB 生效,越大搜索精度越高但是速度越慢。
|
||||||
|
|
||||||
### 5. 运行
|
### 5. 运行
|
||||||
|
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ OneAPI 的语言识别接口,无法正确的识别其他模型(会始终识
|
|||||||
"vectorMaxProcess": 15, // 向量处理线程数量
|
"vectorMaxProcess": 15, // 向量处理线程数量
|
||||||
"qaMaxProcess": 15, // 问答拆分线程数量
|
"qaMaxProcess": 15, // 问答拆分线程数量
|
||||||
"tokenWorkers": 50, // Token 计算线程保持数,会持续占用内存,不能设置太大。
|
"tokenWorkers": 50, // Token 计算线程保持数,会持续占用内存,不能设置太大。
|
||||||
"pgHNSWEfSearch": 100 // 向量搜索参数。越大,搜索越精确,但是速度越慢。设置为100,有99%+精度。
|
"hnswEfSearch": 100 // 向量搜索参数,仅对 PG 和 OB 生效。越大,搜索越精确,但是速度越慢。设置为100,有99%+精度。
|
||||||
},
|
},
|
||||||
"llmModels": [
|
"llmModels": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -18,12 +18,14 @@ weight: 852
|
|||||||
{{% alert icon="🤖 " context="success" %}}
|
{{% alert icon="🤖 " context="success" %}}
|
||||||
* 该接口的 API Key 需使用`应用特定的 key`,否则会报错。
|
* 该接口的 API Key 需使用`应用特定的 key`,否则会报错。
|
||||||
|
|
||||||
|
<!-- * 对话现在有`v1`和`v2`两个接口,可以按需使用,v2 自 4.9.4 版本新增,v1 接口同时不再维护 -->
|
||||||
|
|
||||||
* 有些包调用时,`BaseUrl`需要添加`v1`路径,有些不需要,如果出现404情况,可补充`v1`重试。
|
* 有些包调用时,`BaseUrl`需要添加`v1`路径,有些不需要,如果出现404情况,可补充`v1`重试。
|
||||||
{{% /alert %}}
|
{{% /alert %}}
|
||||||
|
|
||||||
## 请求简易应用和工作流
|
## 请求简易应用和工作流
|
||||||
|
|
||||||
对话接口兼容`GPT`的接口!如果你的项目使用的是标准的`GPT`官方接口,可以直接通过修改`BaseUrl`和 `Authorization`来访问 FastGpt 应用,不过需要注意下面几个规则:
|
`v1`对话接口兼容`GPT`的接口!如果你的项目使用的是标准的`GPT`官方接口,可以直接通过修改`BaseUrl`和 `Authorization`来访问 FastGpt 应用,不过需要注意下面几个规则:
|
||||||
|
|
||||||
{{% alert icon="🤖 " context="success" %}}
|
{{% alert icon="🤖 " context="success" %}}
|
||||||
* 传入的`model`,`temperature`等参数字段均无效,这些字段由编排决定,不会根据 API 参数改变。
|
* 传入的`model`,`temperature`等参数字段均无效,这些字段由编排决定,不会根据 API 参数改变。
|
||||||
@@ -32,6 +34,100 @@ weight: 852
|
|||||||
|
|
||||||
### 请求
|
### 请求
|
||||||
|
|
||||||
|
<!-- #### v2
|
||||||
|
|
||||||
|
v1,v2 接口请求参数一致,仅请求地址不一样。
|
||||||
|
|
||||||
|
{{< tabs tabTotal="3" >}}
|
||||||
|
{{< tab tabName="基础请求示例" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl --location --request POST 'http://localhost:3000/api/v2/chat/completions' \
|
||||||
|
--header 'Authorization: fastgpt-xxxxxx' \
|
||||||
|
--header 'Content-Type: application/json' \
|
||||||
|
--data-raw '{
|
||||||
|
"chatId": "my_chatId",
|
||||||
|
"stream": false,
|
||||||
|
"detail": false,
|
||||||
|
"responseChatItemId": "my_responseChatItemId",
|
||||||
|
"variables": {
|
||||||
|
"uid": "asdfadsfasfd2323",
|
||||||
|
"name": "张三"
|
||||||
|
},
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "你是谁"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
|
||||||
|
{{< tab tabName="图片/文件请求示例" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
* 仅`messages`有部分区别,其他参数一致。
|
||||||
|
* 目前不支持上传文件,需上传到自己的对象存储中,获取对应的文件链接。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl --location --request POST 'http://localhost:3000/api/v2/chat/completions' \
|
||||||
|
--header 'Authorization: Bearer fastgpt-xxxxxx' \
|
||||||
|
--header 'Content-Type: application/json' \
|
||||||
|
--data-raw '{
|
||||||
|
"chatId": "abcd",
|
||||||
|
"stream": false,
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"text": "导演是谁"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "image_url",
|
||||||
|
"image_url": {
|
||||||
|
"url": "图片链接"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "file_url",
|
||||||
|
"name": "文件名",
|
||||||
|
"url": "文档链接,支持 txt md html word pdf ppt csv excel"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
|
||||||
|
{{< tab tabName="参数说明" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
{{% alert context="info" %}}
|
||||||
|
- headers.Authorization: Bearer {{apikey}}
|
||||||
|
- chatId: string | undefined 。
|
||||||
|
- 为 `undefined` 时(不传入),不使用 FastGpt 提供的上下文功能,完全通过传入的 messages 构建上下文。
|
||||||
|
- 为`非空字符串`时,意味着使用 chatId 进行对话,自动从 FastGpt 数据库取历史记录,并使用 messages 数组最后一个内容作为用户问题,其余 message 会被忽略。请自行确保 chatId 唯一,长度小于250,通常可以是自己系统的对话框ID。
|
||||||
|
- messages: 结构与 [GPT接口](https://platform.openai.com/docs/api-reference/chat/object) chat模式一致。
|
||||||
|
- responseChatItemId: string | undefined 。如果传入,则会将该值作为本次对话的响应消息的 ID,FastGPT 会自动将该 ID 存入数据库。请确保,在当前`chatId`下,`responseChatItemId`是唯一的。
|
||||||
|
- detail: 是否返回中间值(模块状态,响应的完整结果等),`stream模式`下会通过`event`进行区分,`非stream模式`结果保存在`responseData`中。
|
||||||
|
- variables: 模块变量,一个对象,会替换模块中,输入框内容里的`{{key}}`
|
||||||
|
{{% /alert %}}
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
{{< /tabs >}}
|
||||||
|
|
||||||
|
#### v1
|
||||||
|
|
||||||
{{< tabs tabTotal="3" >}}
|
{{< tabs tabTotal="3" >}}
|
||||||
{{< tab tabName="基础请求示例" >}}
|
{{< tab tabName="基础请求示例" >}}
|
||||||
{{< markdownify >}}
|
{{< markdownify >}}
|
||||||
@@ -65,7 +161,7 @@ curl --location --request POST 'http://localhost:3000/api/v1/chat/completions' \
|
|||||||
{{< markdownify >}}
|
{{< markdownify >}}
|
||||||
|
|
||||||
* 仅`messages`有部分区别,其他参数一致。
|
* 仅`messages`有部分区别,其他参数一致。
|
||||||
* 目前不支持上次文件,需上传到自己的对象存储中,获取对应的文件链接。
|
* 目前不支持上传文件,需上传到自己的对象存储中,获取对应的文件链接。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl --location --request POST 'http://localhost:3000/api/v1/chat/completions' \
|
curl --location --request POST 'http://localhost:3000/api/v1/chat/completions' \
|
||||||
@@ -116,14 +212,188 @@ curl --location --request POST 'http://localhost:3000/api/v1/chat/completions' \
|
|||||||
- variables: 模块变量,一个对象,会替换模块中,输入框内容里的`{{key}}`
|
- variables: 模块变量,一个对象,会替换模块中,输入框内容里的`{{key}}`
|
||||||
{{% /alert %}}
|
{{% /alert %}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{{< /markdownify >}}
|
{{< /markdownify >}}
|
||||||
{{< /tab >}}
|
{{< /tab >}}
|
||||||
{{< /tabs >}}
|
{{< /tabs >}}
|
||||||
|
|
||||||
### 响应
|
### 响应
|
||||||
|
|
||||||
|
#### v2
|
||||||
|
|
||||||
|
v2 接口比起 v1,主要变变化在于:会在每个节点运行结束后及时返回 response,而不是等工作流结束后再统一返回。
|
||||||
|
|
||||||
|
{{< tabs tabTotal="5" >}}
|
||||||
|
{{< tab tabName="detail=false,stream=false 响应" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "",
|
||||||
|
"model": "",
|
||||||
|
"usage": {
|
||||||
|
"prompt_tokens": 1,
|
||||||
|
"completion_tokens": 1,
|
||||||
|
"total_tokens": 1
|
||||||
|
},
|
||||||
|
"choices": [
|
||||||
|
{
|
||||||
|
"message": {
|
||||||
|
"role": "assistant",
|
||||||
|
"content": "我是一个人工智能助手,旨在回答问题和提供信息。如果你有任何问题或者需要帮助,随时问我!"
|
||||||
|
},
|
||||||
|
"finish_reason": "stop",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
|
||||||
|
{{< tab tabName="detail=false,stream=true 响应" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"你好"},"index":0,"finish_reason":null}]}
|
||||||
|
|
||||||
|
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"!"},"index":0,"finish_reason":null}]}
|
||||||
|
|
||||||
|
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"今天"},"index":0,"finish_reason":null}]}
|
||||||
|
|
||||||
|
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"过得怎么样?"},"index":0,"finish_reason":null}]}
|
||||||
|
|
||||||
|
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":null},"index":0,"finish_reason":"stop"}]}
|
||||||
|
|
||||||
|
data: [DONE]
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
|
||||||
|
{{< tab tabName="detail=true,stream=false 响应" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"responseData": [
|
||||||
|
{
|
||||||
|
"id": "iSol79OFrBH1I9kC",
|
||||||
|
"nodeId": "448745",
|
||||||
|
"moduleName": "common:core.module.template.work_start",
|
||||||
|
"moduleType": "workflowStart",
|
||||||
|
"runningTime": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "t1T94WCy6Su3BK4V",
|
||||||
|
"nodeId": "fjLpE3XPegmoGtbU",
|
||||||
|
"moduleName": "AI 对话",
|
||||||
|
"moduleType": "chatNode",
|
||||||
|
"runningTime": 1.46,
|
||||||
|
"totalPoints": 0,
|
||||||
|
"model": "GPT-4o-mini",
|
||||||
|
"tokens": 64,
|
||||||
|
"inputTokens": 10,
|
||||||
|
"outputTokens": 54,
|
||||||
|
"query": "你是谁",
|
||||||
|
"reasoningText": "",
|
||||||
|
"historyPreview": [
|
||||||
|
{
|
||||||
|
"obj": "Human",
|
||||||
|
"value": "你是谁"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"obj": "AI",
|
||||||
|
"value": "我是一个人工智能助手,旨在帮助回答问题和提供信息。如果你有任何问题或需要帮助,请告诉我!"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"contextTotalLen": 2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"newVariables": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"id": "",
|
||||||
|
"model": "",
|
||||||
|
"usage": {
|
||||||
|
"prompt_tokens": 1,
|
||||||
|
"completion_tokens": 1,
|
||||||
|
"total_tokens": 1
|
||||||
|
},
|
||||||
|
"choices": [
|
||||||
|
{
|
||||||
|
"message": {
|
||||||
|
"role": "assistant",
|
||||||
|
"content": "我是一个人工智能助手,旨在帮助回答问题和提供信息。如果你有任何问题或需要帮助,请告诉我!"
|
||||||
|
},
|
||||||
|
"finish_reason": "stop",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
|
||||||
|
|
||||||
|
{{< tab tabName="detail=true,stream=true 响应" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
```bash
|
||||||
|
event: flowNodeResponse
|
||||||
|
data: {"id":"iYv2uA9rCWAtulWo","nodeId":"workflowStartNodeId","moduleName":"流程开始","moduleType":"workflowStart","runningTime":0}
|
||||||
|
|
||||||
|
event: flowNodeStatus
|
||||||
|
data: {"status":"running","name":"AI 对话"}
|
||||||
|
|
||||||
|
event: answer
|
||||||
|
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"你好"},"index":0,"finish_reason":null}]}
|
||||||
|
|
||||||
|
event: answer
|
||||||
|
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"!"},"index":0,"finish_reason":null}]}
|
||||||
|
|
||||||
|
event: answer
|
||||||
|
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"今天"},"index":0,"finish_reason":null}]}
|
||||||
|
|
||||||
|
event: answer
|
||||||
|
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":"过得怎么样?"},"index":0,"finish_reason":null}]}
|
||||||
|
|
||||||
|
event: flowNodeResponse
|
||||||
|
data: {"id":"pVzLBF7M3Ol4n7s6","nodeId":"ixe20AHN3jy74pKf","moduleName":"AI 对话","moduleType":"chatNode","runningTime":1.48,"totalPoints":0.0042,"model":"Qwen-plus","tokens":28,"inputTokens":8,"outputTokens":20,"query":"你好","reasoningText":"","historyPreview":[{"obj":"Human","value":"你好"},{"obj":"AI","value":"你好!今天过得怎么样?"}],"contextTotalLen":2}
|
||||||
|
|
||||||
|
event: answer
|
||||||
|
data: {"id":"","object":"","created":0,"model":"","choices":[{"delta":{"role":"assistant","content":null},"index":0,"finish_reason":"stop"}]}
|
||||||
|
|
||||||
|
event: answer
|
||||||
|
data: [DONE]
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
|
||||||
|
{{< tab tabName="event值" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
event取值:
|
||||||
|
|
||||||
|
- answer: 返回给客户端的文本(最终会算作回答)
|
||||||
|
- fastAnswer: 指定回复返回给客户端的文本(最终会算作回答)
|
||||||
|
- toolCall: 执行工具
|
||||||
|
- toolParams: 工具参数
|
||||||
|
- toolResponse: 工具返回
|
||||||
|
- flowNodeStatus: 运行到的节点状态
|
||||||
|
- flowNodeResponse: 单个节点详细响应
|
||||||
|
- updateVariables: 更新变量
|
||||||
|
- error: 报错
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
{{< /tabs >}}
|
||||||
|
|
||||||
|
#### v1 -->
|
||||||
|
|
||||||
{{< tabs tabTotal="5" >}}
|
{{< tabs tabTotal="5" >}}
|
||||||
{{< tab tabName="detail=false,stream=false 响应" >}}
|
{{< tab tabName="detail=false,stream=false 响应" >}}
|
||||||
{{< markdownify >}}
|
{{< markdownify >}}
|
||||||
@@ -475,6 +745,8 @@ curl --location --request POST 'https://api.fastgpt.in/api/v1/chat/completions'
|
|||||||
|
|
||||||
### 请求示例
|
### 请求示例
|
||||||
|
|
||||||
|
#### v1
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl --location --request POST 'http://localhost:3000/api/v1/chat/completions' \
|
curl --location --request POST 'http://localhost:3000/api/v1/chat/completions' \
|
||||||
--header 'Authorization: Bearer test-xxxxx' \
|
--header 'Authorization: Bearer test-xxxxx' \
|
||||||
@@ -488,8 +760,25 @@ curl --location --request POST 'http://localhost:3000/api/v1/chat/completions' \
|
|||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### v2
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl --location --request POST 'http://localhost:3000/api/v2/chat/completions' \
|
||||||
|
--header 'Authorization: Bearer test-xxxxx' \
|
||||||
|
--header 'Content-Type: application/json' \
|
||||||
|
--data-raw '{
|
||||||
|
"stream": false,
|
||||||
|
"chatId": "test",
|
||||||
|
"variables": {
|
||||||
|
"query":"你好"
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
### 响应示例
|
### 响应示例
|
||||||
|
|
||||||
|
#### v1
|
||||||
|
|
||||||
{{< tabs tabTotal="3" >}}
|
{{< tabs tabTotal="3" >}}
|
||||||
|
|
||||||
{{< tab tabName="detail=true,stream=false 响应" >}}
|
{{< tab tabName="detail=true,stream=false 响应" >}}
|
||||||
@@ -649,6 +938,149 @@ event取值:
|
|||||||
{{< /tabs >}}
|
{{< /tabs >}}
|
||||||
|
|
||||||
|
|
||||||
|
#### v2
|
||||||
|
|
||||||
|
{{< tabs tabTotal="3" >}}
|
||||||
|
|
||||||
|
{{< tab tabName="detail=true,stream=false 响应" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
* 插件的输出可以通过查找`responseData`中, `moduleType=pluginOutput`的元素,其`pluginOutput`是插件的输出。
|
||||||
|
* 流输出,仍可以通过`choices`进行获取。
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"responseData": [
|
||||||
|
{
|
||||||
|
"id": "bsH1ZdbYkz9iJwYa",
|
||||||
|
"nodeId": "pluginInput",
|
||||||
|
"moduleName": "workflow:template.plugin_start",
|
||||||
|
"moduleType": "pluginInput",
|
||||||
|
"runningTime": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "zDgfqSPhbYZFHVIn",
|
||||||
|
"nodeId": "h4Gr4lJtFVQ6qI4c",
|
||||||
|
"moduleName": "AI 对话",
|
||||||
|
"moduleType": "chatNode",
|
||||||
|
"runningTime": 1.44,
|
||||||
|
"totalPoints": 0,
|
||||||
|
"model": "GPT-4o-mini",
|
||||||
|
"tokens": 34,
|
||||||
|
"inputTokens": 8,
|
||||||
|
"outputTokens": 26,
|
||||||
|
"query": "你好",
|
||||||
|
"reasoningText": "",
|
||||||
|
"historyPreview": [
|
||||||
|
{
|
||||||
|
"obj": "Human",
|
||||||
|
"value": "你好"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"obj": "AI",
|
||||||
|
"value": "你好!有什么我可以帮助你的吗?"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"contextTotalLen": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "uLLwKKRZvufXzgF4",
|
||||||
|
"nodeId": "pluginOutput",
|
||||||
|
"moduleName": "common:core.module.template.self_output",
|
||||||
|
"moduleType": "pluginOutput",
|
||||||
|
"runningTime": 0,
|
||||||
|
"totalPoints": 0,
|
||||||
|
"pluginOutput": {
|
||||||
|
"result": "你好!有什么我可以帮助你的吗?"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"newVariables": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"id": "test",
|
||||||
|
"model": "",
|
||||||
|
"usage": {
|
||||||
|
"prompt_tokens": 1,
|
||||||
|
"completion_tokens": 1,
|
||||||
|
"total_tokens": 1
|
||||||
|
},
|
||||||
|
"choices": [
|
||||||
|
{
|
||||||
|
"message": {
|
||||||
|
"role": "assistant",
|
||||||
|
"content": "你好!有什么我可以帮助你的吗?"
|
||||||
|
},
|
||||||
|
"finish_reason": "stop",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
|
||||||
|
|
||||||
|
{{< tab tabName="detail=true,stream=true 响应" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
* 插件的输出可以通过获取`event=flowResponses`中的字符串,并将其反序列化后得到一个数组。同样的,查找 `moduleType=pluginOutput`的元素,其`pluginOutput`是插件的输出。
|
||||||
|
* 流输出,仍和对话接口一样获取。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
data: {"event":"flowNodeResponse","data":"{\"id\":\"q8ablUOqHGgqLIRM\",\"nodeId\":\"pluginInput\",\"moduleName\":\"workflow:template.plugin_start\",\"moduleType\":\"pluginInput\",\"runningTime\":0}"}
|
||||||
|
|
||||||
|
data: {"event":"flowNodeStatus","data":"{\"status\":\"running\",\"name\":\"AI 对话\"}"}
|
||||||
|
|
||||||
|
data: {"event":"answer","data":"{\"id\":\"\",\"object\":\"\",\"created\":0,\"model\":\"\",\"choices\":[{\"delta\":{\"role\":\"assistant\",\"content\":\"你好\"},\"index\":0,\"finish_reason\":null}]}"}
|
||||||
|
|
||||||
|
data: {"event":"answer","data":"{\"id\":\"\",\"object\":\"\",\"created\":0,\"model\":\"\",\"choices\":[{\"delta\":{\"role\":\"assistant\",\"content\":\"!\"},\"index\":0,\"finish_reason\":null}]}"}
|
||||||
|
|
||||||
|
data: {"event":"answer","data":"{\"id\":\"\",\"object\":\"\",\"created\":0,\"model\":\"\",\"choices\":[{\"delta\":{\"role\":\"assistant\",\"content\":\"有什么\"},\"index\":0,\"finish_reason\":null}]}"}
|
||||||
|
|
||||||
|
data: {"event":"answer","data":"{\"id\":\"\",\"object\":\"\",\"created\":0,\"model\":\"\",\"choices\":[{\"delta\":{\"role\":\"assistant\",\"content\":\"我\"},\"index\":0,\"finish_reason\":null}]}"}
|
||||||
|
|
||||||
|
data: {"event":"answer","data":"{\"id\":\"\",\"object\":\"\",\"created\":0,\"model\":\"\",\"choices\":[{\"delta\":{\"role\":\"assistant\",\"content\":\"可以\"},\"index\":0,\"finish_reason\":null}]}"}
|
||||||
|
|
||||||
|
data: {"event":"answer","data":"{\"id\":\"\",\"object\":\"\",\"created\":0,\"model\":\"\",\"choices\":[{\"delta\":{\"role\":\"assistant\",\"content\":\"帮助\"},\"index\":0,\"finish_reason\":null}]}"}
|
||||||
|
|
||||||
|
data: {"event":"answer","data":"{\"id\":\"\",\"object\":\"\",\"created\":0,\"model\":\"\",\"choices\":[{\"delta\":{\"role\":\"assistant\",\"content\":\"你\"},\"index\":0,\"finish_reason\":null}]}"}
|
||||||
|
|
||||||
|
data: {"event":"answer","data":"{\"id\":\"\",\"object\":\"\",\"created\":0,\"model\":\"\",\"choices\":[{\"delta\":{\"role\":\"assistant\",\"content\":\"的吗\"},\"index\":0,\"finish_reason\":null}]}"}
|
||||||
|
|
||||||
|
data: {"event":"answer","data":"{\"id\":\"\",\"object\":\"\",\"created\":0,\"model\":\"\",\"choices\":[{\"delta\":{\"role\":\"assistant\",\"content\":\"?\"},\"index\":0,\"finish_reason\":null}]}"}
|
||||||
|
|
||||||
|
data: {"event":"flowNodeResponse","data":"{\"id\":\"rqlXLUap8QeiN7Kf\",\"nodeId\":\"h4Gr4lJtFVQ6qI4c\",\"moduleName\":\"AI 对话\",\"moduleType\":\"chatNode\",\"runningTime\":1.79,\"totalPoints\":0,\"model\":\"GPT-4o-mini\",\"tokens\":137,\"inputTokens\":111,\"outputTokens\":26,\"query\":\"你好\",\"reasoningText\":\"\",\"historyPreview\":[{\"obj\":\"Human\",\"value\":\"[{\\\"renderTypeList\\\":[\\\"reference\\\"],\\\"selectedTypeInde\\n\\n...[hide 174 chars]...\\n\\ncanSelectImg\\\":true,\\\"required\\\":false,\\\"value\\\":\\\"你好\\\"}]\"},{\"obj\":\"AI\",\"value\":\"你好!有什么我可以帮助你的吗?\"},{\"obj\":\"Human\",\"value\":\"你好\"},{\"obj\":\"AI\",\"value\":\"你好!有什么我可以帮助你的吗?\"}],\"contextTotalLen\":4}"}
|
||||||
|
|
||||||
|
data: {"event":"flowNodeResponse","data":"{\"id\":\"lHCpHI0MrM00HQlX\",\"nodeId\":\"pluginOutput\",\"moduleName\":\"common:core.module.template.self_output\",\"moduleType\":\"pluginOutput\",\"runningTime\":0,\"totalPoints\":0,\"pluginOutput\":{\"result\":\"你好!有什么我可以帮助你的吗?\"}}"}
|
||||||
|
|
||||||
|
data: {"event":"answer","data":"{\"id\":\"\",\"object\":\"\",\"created\":0,\"model\":\"\",\"choices\":[{\"delta\":{\"role\":\"assistant\",\"content\":null},\"index\":0,\"finish_reason\":\"stop\"}]}"}
|
||||||
|
|
||||||
|
data: {"event":"answer","data":"[DONE]"}
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
|
||||||
|
{{< tab tabName="输出获取" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
event取值:
|
||||||
|
|
||||||
|
- answer: 返回给客户端的文本(最终会算作回答)
|
||||||
|
- fastAnswer: 指定回复返回给客户端的文本(最终会算作回答)
|
||||||
|
- toolCall: 执行工具
|
||||||
|
- toolParams: 工具参数
|
||||||
|
- toolResponse: 工具返回
|
||||||
|
- flowNodeStatus: 运行到的节点状态
|
||||||
|
- flowNodeResponse: 单个节点详细响应
|
||||||
|
- updateVariables: 更新变量
|
||||||
|
- error: 报错
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
{{< /tabs >}}
|
||||||
|
|
||||||
# 对话 CRUD
|
# 对话 CRUD
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ curl --location --request POST 'https://{{host}}/api/admin/initv491' \
|
|||||||
3. API 知识库支持 PDF 增强解析。
|
3. API 知识库支持 PDF 增强解析。
|
||||||
4. 邀请团队成员,改为邀请链接模式。
|
4. 邀请团队成员,改为邀请链接模式。
|
||||||
5. 支持混合检索权重设置。
|
5. 支持混合检索权重设置。
|
||||||
6. 支持重排模型选择和权重设置,同时调整了知识库搜索权重计算方式,改成 搜索权重 + 重排权重,而不是向量检索权重+全文检索权重+重排权重。
|
6. 支持重排模型选择和权重设置,同时调整了知识库搜索权重计算方式,改成 搜索权重 + 重排权重,而不是向量检索权重+全文检索权重+重排权重。会对检索结果有一定影响,可以通过调整相关权重来进行数据适配。
|
||||||
|
|
||||||
## ⚙️ 优化
|
## ⚙️ 优化
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,43 @@
|
|||||||
---
|
---
|
||||||
title: 'V4.9.2(进行中)'
|
title: 'V4.9.2'
|
||||||
description: 'FastGPT V4.9.2 更新说明'
|
description: 'FastGPT V4.9.2 更新说明'
|
||||||
icon: 'upgrade'
|
icon: 'upgrade'
|
||||||
draft: false
|
draft: false
|
||||||
toc: true
|
toc: true
|
||||||
weight: 799
|
weight: 798
|
||||||
---
|
---
|
||||||
|
## 更新指南
|
||||||
|
|
||||||
## 重要提示
|
可直接升级v4.9.3,v4.9.2存在一个工作流数据类型转化错误。
|
||||||
|
|
||||||
|
### 1. 做好数据库备份
|
||||||
|
|
||||||
|
### 2. SSO 迁移
|
||||||
|
|
||||||
|
使用了 SSO 或成员同步的商业版用户,并且是对接`钉钉`、`企微`的,需要迁移已有的 SSO 相关配置:
|
||||||
|
|
||||||
|
参考:[SSO & 外部成员同步](/docs/guide/admin/sso)中的配置进行`sso-service`的部署和配置。
|
||||||
|
|
||||||
|
1. 先将原商业版后台中的相关配置项复制备份出来(以企微为例,将 AppId, Secret 等复制出来)再进行镜像升级。
|
||||||
|
2. 参考上述文档,部署 SSO 服务,配置相关的环境变量
|
||||||
|
3. 如果原先使用企微组织架构同步的用户,升级完镜像后,需要在商业版后台切换团队模式为“同步模式”
|
||||||
|
|
||||||
|
### 3. 配置参数变更
|
||||||
|
|
||||||
|
修改`config.json`文件中`systemEnv.pgHNSWEfSearch`参数名,改成`hnswEfSearch`。
|
||||||
|
商业版用户升级镜像后,直接在后台`系统配置-基础配置`中进行变更。
|
||||||
|
|
||||||
|
### 4. 更新镜像
|
||||||
|
|
||||||
|
- 更新 FastGPT 镜像 tag: v4.9.2
|
||||||
|
- 更新 FastGPT 商业版镜像 tag: v4.9.2
|
||||||
|
- Sandbox 镜像,可以不更新
|
||||||
|
- AIProxy 镜像修改为: registry.cn-hangzhou.aliyuncs.com/labring/aiproxy:v0.1.4
|
||||||
|
|
||||||
|
## 重要更新
|
||||||
|
|
||||||
- 知识库导入数据 API 变更,增加`chunkSettingMode`,`chunkSplitMode`,`indexSize`可选参数,具体可参考 [知识库导入数据 API](/docs/development/openapi/dataset) 文档。
|
- 知识库导入数据 API 变更,增加`chunkSettingMode`,`chunkSplitMode`,`indexSize`可选参数,具体可参考 [知识库导入数据 API](/docs/development/openapi/dataset) 文档。
|
||||||
|
|
||||||
|
|
||||||
## 🚀 新增内容
|
## 🚀 新增内容
|
||||||
|
|
||||||
1. 知识库分块优化:支持单独配置分块大小和索引大小,允许进行超大分块,以更大的输入 Tokens 换取完整分块。
|
1. 知识库分块优化:支持单独配置分块大小和索引大小,允许进行超大分块,以更大的输入 Tokens 换取完整分块。
|
||||||
@@ -19,6 +45,9 @@ weight: 799
|
|||||||
3. 外部变量改名:自定义变量。 并且支持在测试时调试,在分享链接中,该变量直接隐藏。
|
3. 外部变量改名:自定义变量。 并且支持在测试时调试,在分享链接中,该变量直接隐藏。
|
||||||
4. 集合同步时,支持同步修改标题。
|
4. 集合同步时,支持同步修改标题。
|
||||||
5. 团队成员管理重构,抽离主流 IM SSO(企微、飞书、钉钉),并支持通过自定义 SSO 接入 FastGPT。同时完善与外部系统的成员同步。
|
5. 团队成员管理重构,抽离主流 IM SSO(企微、飞书、钉钉),并支持通过自定义 SSO 接入 FastGPT。同时完善与外部系统的成员同步。
|
||||||
|
6. 支持 `oceanbase` 向量数据库。填写环境变量`OCEANBASE_URL`即可。
|
||||||
|
7. 基于 mistral-ocr 的 PDF 解析示例。
|
||||||
|
8. 基于 miner-u 的 PDF 解析示例。
|
||||||
|
|
||||||
## ⚙️ 优化
|
## ⚙️ 优化
|
||||||
|
|
||||||
@@ -30,7 +59,9 @@ weight: 799
|
|||||||
6. 工作流节点数组字符串类型,自动适配 string 输入。
|
6. 工作流节点数组字符串类型,自动适配 string 输入。
|
||||||
7. 工作流节点数组类型,自动进行 JSON parse 解析 string 输入。
|
7. 工作流节点数组类型,自动进行 JSON parse 解析 string 输入。
|
||||||
8. AI proxy 日志优化,去除重试失败的日志,仅保留最后一份错误日志。
|
8. AI proxy 日志优化,去除重试失败的日志,仅保留最后一份错误日志。
|
||||||
9. 分块算法小调整:
|
9. 个人信息和通知展示优化。
|
||||||
|
10. 模型测试 loading 动画优化。
|
||||||
|
11. 分块算法小调整:
|
||||||
* 跨处理符号之间连续性更强。
|
* 跨处理符号之间连续性更强。
|
||||||
* 代码块分割时,用 LLM 模型上下文作为分块大小,尽可能保证代码块完整性。
|
* 代码块分割时,用 LLM 模型上下文作为分块大小,尽可能保证代码块完整性。
|
||||||
* 表格分割时,用 LLM 模型上下文作为分块大小,尽可能保证表格完整性。
|
* 表格分割时,用 LLM 模型上下文作为分块大小,尽可能保证表格完整性。
|
||||||
|
|||||||
29
docSite/content/zh-cn/docs/development/upgrading/493.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
title: 'V4.9.3'
|
||||||
|
description: 'FastGPT V4.9.3 更新说明'
|
||||||
|
icon: 'upgrade'
|
||||||
|
draft: false
|
||||||
|
toc: true
|
||||||
|
weight: 797
|
||||||
|
---
|
||||||
|
|
||||||
|
## 更新指南
|
||||||
|
|
||||||
|
### 1. 做好数据库备份
|
||||||
|
|
||||||
|
### 2. 更新镜像
|
||||||
|
|
||||||
|
- 更新 FastGPT 镜像 tag: v4.9.3
|
||||||
|
- 更新 FastGPT 商业版镜像 tag: v4.9.3
|
||||||
|
- Sandbox 镜像tag: v4.9.3
|
||||||
|
- AIProxy 镜像tag: v0.1.5
|
||||||
|
|
||||||
|
|
||||||
|
## 🚀 新增内容
|
||||||
|
|
||||||
|
1. 工作流 debug 模式支持交互节点。
|
||||||
|
2. 代码运行支持 Python3 代码。
|
||||||
|
|
||||||
|
## 🐛 修复
|
||||||
|
|
||||||
|
1. 工作流格式转化异常。
|
||||||
59
docSite/content/zh-cn/docs/development/upgrading/494.md
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
---
|
||||||
|
title: 'V4.9.4(进行中)'
|
||||||
|
description: 'FastGPT V4.9.4 更新说明'
|
||||||
|
icon: 'upgrade'
|
||||||
|
draft: false
|
||||||
|
toc: true
|
||||||
|
weight: 796
|
||||||
|
---
|
||||||
|
|
||||||
|
## 升级指南
|
||||||
|
|
||||||
|
### 1. 做好数据备份
|
||||||
|
|
||||||
|
### 1. 安装 Redis
|
||||||
|
|
||||||
|
* docker 部署的用户,参考最新的 `docker-compose.yml` 文件增加 Redis 配置。增加一个 redis 容器,并配置`fastgpt`,`fastgpt-pro`的环境变量,增加 `REDIS_URL` 环境变量。
|
||||||
|
* Sealos 部署的用户,在数据库里新建一个`redis`数据库,并复制`内网地址的 connection` 作为 `redis` 的链接串。然后配置`fastgpt`,`fastgpt-pro`的环境变量,增加 `REDIS_URL` 环境变量。
|
||||||
|
|
||||||
|
| | | |
|
||||||
|
| --- | --- | --- |
|
||||||
|
|  |  |  |
|
||||||
|
|
||||||
|
### 2. 更新镜像 tag
|
||||||
|
|
||||||
|
|
||||||
|
### 3. 执行升级脚本
|
||||||
|
|
||||||
|
该脚本仅需商业版用户执行。
|
||||||
|
|
||||||
|
从任意终端,发起 1 个 HTTP 请求。其中 {{rootkey}} 替换成环境变量里的 `rootkey`;{{host}} 替换成**FastGPT 域名**。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl --location --request POST 'https://{{host}}/api/admin/initv494' \
|
||||||
|
--header 'rootkey: {{rootkey}}' \
|
||||||
|
--header 'Content-Type: application/json'
|
||||||
|
```
|
||||||
|
|
||||||
|
**脚本功能**
|
||||||
|
|
||||||
|
1. 更新站点同步定时器
|
||||||
|
|
||||||
|
## 🚀 新增内容
|
||||||
|
|
||||||
|
1. 集合数据训练状态展示
|
||||||
|
2. SMTP 发送邮件插件
|
||||||
|
3. BullMQ 消息队列。
|
||||||
|
4. 利用 redis 进行部分数据缓存。
|
||||||
|
5. 站点同步支持配置训练参数。
|
||||||
|
6. AI 对话/工具调用,增加返回模型 finish_reason 字段。
|
||||||
|
|
||||||
|
## ⚙️ 优化
|
||||||
|
|
||||||
|
1. Admin 模板渲染调整。
|
||||||
|
2. 支持环境变量配置对话文件过期时间。
|
||||||
|
3. MongoDB log 库可独立部署。
|
||||||
|
|
||||||
|
## 🐛 修复
|
||||||
|
|
||||||
|
1. 搜索应用/知识库时,无法点击目录进入下一层。
|
||||||
88
docSite/content/zh-cn/docs/guide/DialogBoxes/quoteList.md
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
---
|
||||||
|
title: '知识库引用分块阅读器'
|
||||||
|
description: 'FastGPT 分块阅读器功能介绍'
|
||||||
|
icon: 'description'
|
||||||
|
draft: false
|
||||||
|
toc: true
|
||||||
|
weight: 480
|
||||||
|
---
|
||||||
|
在企业 AI 应用落地过程中,文档知识引用的精确性和透明度一直是用户关注的焦点。FastGPT 4.9.1 版本带来的知识库分块阅读器,巧妙解决了这一痛点,让 AI 引用不再是"黑盒"。
|
||||||
|
|
||||||
|
# 为什么需要分块阅读器?
|
||||||
|
|
||||||
|
传统的 AI 对话中,当模型引用企业知识库内容时,用户往往只能看到被引用的片段,无法获取完整语境,这给内容验证和深入理解带来了挑战。分块阅读器的出现,让用户可以在对话中直接查看引用内容的完整文档,并精确定位到引用位置,实现了引用的"可解释性"。
|
||||||
|
|
||||||
|
## 传统引用体验的局限
|
||||||
|
|
||||||
|
以往在知识库中上传文稿后,当我们在工作流中输入问题时,传统的引用方式只会展示引用到的分块,无法确认分块在文章中的上下文:
|
||||||
|
|
||||||
|
| 问题 | 引用 |
|
||||||
|
| --- | --- |
|
||||||
|
|  |  |
|
||||||
|
|
||||||
|
## FastGPT 分块阅读器:精准定位,无缝阅读
|
||||||
|
|
||||||
|
而在 FastGPT 全新的分块式阅读器中,同样的知识库内容和问题,呈现方式发生了质的飞跃
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
当 AI 引用知识库内容时,用户只需点击引用链接,即可打开一个浮窗,呈现完整的原文内容,并通过醒目的高亮标记精确显示引用的文本片段。这既保证了回答的可溯源性,又提供了便捷的原文查阅体验。
|
||||||
|
|
||||||
|
# 核心功能
|
||||||
|
|
||||||
|
## 全文展示与定位
|
||||||
|
|
||||||
|
"分块阅读器" 让用户能直观查看AI回答引用的知识来源。
|
||||||
|
|
||||||
|
在对话界面中,当 AI 引用了知识库内容,系统会在回复下方展示出处信息。用户只需点击这些引用链接,即可打开一个优雅的浮窗,呈现完整的原文内容,并通过醒目的高亮标记精确显示 AI 引用的文本片段。
|
||||||
|
|
||||||
|
这一设计既保证了回答的可溯源性,又提供了便捷的原文查阅体验,让用户能轻松验证AI回答的准确性和相关上下文。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## 便捷引用导航
|
||||||
|
|
||||||
|
分块阅读器右上角设计了简洁实用的导航控制,用户可以通过这对按钮轻松在多个引用间切换浏览。导航区还直观显示当前查看的引用序号及总引用数量(如 "7/10"),帮助用户随时了解浏览进度和引用内容的整体规模。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 引用质量评分
|
||||||
|
|
||||||
|
每条引用内容旁边都配有智能评分标签,直观展示该引用在所有知识片段中的相关性排名。用户只需将鼠标悬停在评分标签上,即可查看完整的评分详情,了解这段引用内容为何被AI选中以及其相关性的具体构成。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## 文档内容一键导出
|
||||||
|
|
||||||
|
分块阅读器贴心配备了内容导出功能,让有效信息不再流失。只要用户拥有相应知识库的阅读权限,便可通过简单点击将引用涉及的全文直接保存到本地设备。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
# 进阶特性
|
||||||
|
|
||||||
|
## 灵活的可见度控制
|
||||||
|
|
||||||
|
FastGPT提供灵活的引用可见度设置,让知识共享既开放又安全。以免登录链接为例,管理员可精确控制外部访问者能看到的信息范围。
|
||||||
|
|
||||||
|
当设置为"仅引用内容可见"时,外部用户点击引用链接将只能查看 AI 引用的特定文本片段,而非完整原文档。如图所示,分块阅读器此时智能调整显示模式,仅呈现相关引用内容。
|
||||||
|
|
||||||
|
| | |
|
||||||
|
| --- | --- |
|
||||||
|
|  |  |
|
||||||
|
|
||||||
|
## 即时标注优化
|
||||||
|
|
||||||
|
在浏览过程中,授权用户可以直接对引用内容进行即时标注和修正,系统会智能处理这些更新而不打断当前的对话体验。所有修改过的内容会通过醒目的"已更新"标签清晰标识,既保证了引用的准确性,又维持了对话历史的完整性。
|
||||||
|
|
||||||
|
这一无缝的知识优化流程特别适合团队协作场景,让知识库能在实际使用过程中持续进化,确保AI回答始终基于最新、最准确的信息源。
|
||||||
|
|
||||||
|
## 智能文档性能优化
|
||||||
|
|
||||||
|
面对现实业务中可能包含成千上万分块的超长文档,FastGPT采用了先进的性能优化策略,确保分块阅读器始终保持流畅响应。
|
||||||
|
|
||||||
|
系统根据引用相关性排序和数据库索引进行智能加载管理,实现了"按需渲染"机制——根据索引排序和数据库 id,只有当用户实际需要查看的内容才会被加载到内存中。这意味着无论是快速跳转到特定引用,还是自然滚动浏览文档,都能获得丝滑的用户体验,不会因为文档体积庞大而出现卡顿或延迟。
|
||||||
|
|
||||||
|
这一技术优化使FastGPT能够轻松应对企业级的大规模知识库场景,让即使是包含海量信息的专业文档也能高效展示和查阅。
|
||||||
|
|
||||||
581
docSite/content/zh-cn/docs/guide/admin/sso.md
Normal file
@@ -0,0 +1,581 @@
|
|||||||
|
---
|
||||||
|
title: 'SSO & 外部成员同步'
|
||||||
|
description: 'FastGPT 外部成员系统接入设计与配置'
|
||||||
|
icon: ''
|
||||||
|
draft: false
|
||||||
|
toc: true
|
||||||
|
weight: 707
|
||||||
|
---
|
||||||
|
|
||||||
|
如果你不需要用到 SSO/成员同步功能,或者是只需要用 Github、google、microsoft、公众号的快速登录,可以跳过本章节。本章适合需要接入自己的成员系统或主流 办公IM 的用户。
|
||||||
|
|
||||||
|
## 介绍
|
||||||
|
|
||||||
|
为了方便地接入**外部成员系统**,FastGPT 提供一套接入外部系统的**标准接口**,以及一个 FastGPT-SSO-Service 镜像作为**适配器**。
|
||||||
|
|
||||||
|
通过这套标注接口,你可以可以实现:
|
||||||
|
|
||||||
|
1. SSO 登录。从外部系统回调后,在 FastGPT 中创建一个用户。
|
||||||
|
2. 成员和组织架构同步(下面都简称成员同步)。
|
||||||
|
|
||||||
|
**原理**
|
||||||
|
|
||||||
|
FastGPT-pro 中,有一套标准的SSO 和成员同步接口,系统会根据这套接口进行 SSO 和成员同步操作。
|
||||||
|
|
||||||
|
FastGPT-SSO-Service 是为了聚合不同来源的 SSO 和成员同步接口,将他们转成 fastgpt-pro 可识别的接口。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 系统配置教程
|
||||||
|
|
||||||
|
### 1. 部署 SSO-service 镜像
|
||||||
|
|
||||||
|
使用 docker-compose 部署:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
fastgpt-sso:
|
||||||
|
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sso-service:v4.9.0
|
||||||
|
container_name: fastgpt-sso
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- fastgpt
|
||||||
|
environment:
|
||||||
|
- SSO_PROVIDER=example
|
||||||
|
- AUTH_TOKEN=xxxxx # 鉴权信息,fastgpt-pro 会用到。
|
||||||
|
# 具体对接提供商的环境变量。
|
||||||
|
```
|
||||||
|
|
||||||
|
根据不同的提供商,你需要配置不同的环境变量,下面是内置的通用协议/IM:
|
||||||
|
|
||||||
|
{{< table "table-hover table-striped-columns" >}}
|
||||||
|
| 协议/功能 | SSO | 成员同步支持 |
|
||||||
|
|----------------|----------|--------------|
|
||||||
|
| 飞书 | 是 | 是 |
|
||||||
|
| 企业微信 | 是 | 是 |
|
||||||
|
| 钉钉 | 是 | 否 |
|
||||||
|
| Saml2.0 | 是 | 否 |
|
||||||
|
| Oauth2.0 | 是 | 否 |
|
||||||
|
{{< /table >}}
|
||||||
|
|
||||||
|
### 2. 配置 fastgpt-pro
|
||||||
|
|
||||||
|
#### 1. 配置环境变量
|
||||||
|
|
||||||
|
环境变量中的 `EXTERNAL_USER_SYSTEM_BASE_URL` 为内网地址,例如上述例子中的配置,环境变量应该设置为
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
env:
|
||||||
|
- EXTERNAL_USER_SYSTEM_BASE_URL=http://fastgpt-sso:3000
|
||||||
|
- EXTERNAL_USER_SYSTEM_AUTH_TOKEN=xxxxx
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. 在商业版后台配置按钮文字,图标等。
|
||||||
|
|
||||||
|
{{< table "table-hover table-striped-columns" >}}
|
||||||
|
| <div style="text-align:center">企业微信</div> | <div style="text-align:center">钉钉</div> | <div style="text-align:center">飞书</div> |
|
||||||
|
|-----------|-----------------|--------------|
|
||||||
|
|  |  |  |
|
||||||
|
{{< /table >}}
|
||||||
|
|
||||||
|
#### 3. 开启成员同步(可选)
|
||||||
|
|
||||||
|
如果需要同步外部系统的成员,可以选择开启成员同步。团队模式具体可参考:[团队模式说明文档](/docs/guide/admin/teamMode)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### 4. 可选配置
|
||||||
|
|
||||||
|
1. 自动定时成员同步
|
||||||
|
|
||||||
|
设置 fastgpt-pro 环境变量则可开启自动成员同步
|
||||||
|
|
||||||
|
```bash
|
||||||
|
env:
|
||||||
|
- "SYNC_MEMBER_CRON=0 0 * * *" # Cron 表达式,每天 0 点执行
|
||||||
|
```
|
||||||
|
|
||||||
|
## 内置的通用协议/IM 配置示例
|
||||||
|
|
||||||
|
### 飞书
|
||||||
|
|
||||||
|
#### 1. 参数获取
|
||||||
|
|
||||||
|
App ID和App Secret
|
||||||
|
|
||||||
|
进入开发者后台,点击企业自建应用,在凭证与基础信息页面查看应用凭证。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### 2. 权限配置
|
||||||
|
|
||||||
|
进入开发者后台,点击企业自建应用,在开发配置的权限管理页面开通权限。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
对于开通用户SSO登录而言,开启用户身份权限的以下内容
|
||||||
|
|
||||||
|
1. ***获取通讯录基本信息***
|
||||||
|
2. ***获取用户基本信息***
|
||||||
|
3. ***获取用户邮箱信息***
|
||||||
|
4. ***获取用户 user ID***
|
||||||
|
|
||||||
|
对于开启企业同步相关内容而言,开启身份权限的内容与上面一致,但要注意是开启应用权限
|
||||||
|
|
||||||
|
#### 3. 重定向URL
|
||||||
|
|
||||||
|
进入开发者后台,点击企业自建应用,在开发配置的安全设置中设置重定向URL
|
||||||
|

|
||||||
|
|
||||||
|
#### 4. yml 配置示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
fastgpt-sso:
|
||||||
|
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sso-service:v4.9.0
|
||||||
|
container_name: fastgpt-sso
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- fastgpt
|
||||||
|
environment:
|
||||||
|
- SSO_PROVIDER=example
|
||||||
|
- AUTH_TOKEN=xxxxx
|
||||||
|
# 飞书 - feishu -如果是私有化部署,这里的配置前缀可能会有变化
|
||||||
|
- SSO_PROVIDER=feishu
|
||||||
|
# oauth 接口(公开的飞书不用改)
|
||||||
|
- SSO_TARGET_URL=https://accounts.feishu.cn/open-apis/authen/v1/authorize
|
||||||
|
# 获取token 接口(公开的飞书不用改)
|
||||||
|
- FEISHU_TOKEN_URL=https://open.feishu.cn/open-apis/authen/v2/oauth/token
|
||||||
|
# 获取用户信息接口(公开的飞书不用改)
|
||||||
|
- FEISHU_GET_USER_INFO_URL=https://open.feishu.cn/open-apis/authen/v1/user_info
|
||||||
|
# 重定向地址,因为飞书获取用户信息要校验所以需要填
|
||||||
|
- FEISHU_REDIRECT_URI=xxx
|
||||||
|
#飞书APP的应用ID,一般以cli开头
|
||||||
|
- FEISHU_APP_ID=xxx
|
||||||
|
#飞书APP的应用密钥
|
||||||
|
- FEISHU_APP_SECRET=xxx
|
||||||
|
```
|
||||||
|
|
||||||
|
### 钉钉
|
||||||
|
|
||||||
|
#### 1. 参数获取
|
||||||
|
|
||||||
|
CLIENT_ID 与 CLIENT_SECRET
|
||||||
|
|
||||||
|
进入钉钉开放平台,点击应用开发,选择自己的应用进入,记录在凭证与基础信息页面下的Client ID与Client secret。
|
||||||
|

|
||||||
|
|
||||||
|
#### 2. 权限配置
|
||||||
|
|
||||||
|
进入钉钉开放平台,点击应用开发,选择自己的应用进入,在开发配置的权限管理页面操作,需要开通的权限包括:
|
||||||
|
|
||||||
|
1. ***个人手机号信息***
|
||||||
|
2. ***通讯录个人信息读权限***
|
||||||
|
3. ***获取钉钉开放接口用户访问凭证的基础权限***
|
||||||
|
|
||||||
|
#### 3. 重定向URL
|
||||||
|
|
||||||
|
进入钉钉开放平台,点击应用开发,选择自己的应用进入,在开发配置的安全设置页面操作
|
||||||
|
需要填写的内容有两个:
|
||||||
|
|
||||||
|
1. 服务器出口IP (调用钉钉服务端API的服务器IP列表)
|
||||||
|
2. 重定向URL(回调域名)
|
||||||
|
|
||||||
|
#### 4. yml 配置示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
fastgpt-sso:
|
||||||
|
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sso-service:v4.9.0
|
||||||
|
container_name: fastgpt-sso
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- fastgpt
|
||||||
|
environment:
|
||||||
|
- SSO_PROVIDER=dingtalk
|
||||||
|
- AUTH_TOKEN=xxxxx
|
||||||
|
#oauth 接口
|
||||||
|
- SSO_TARGET_URL=https://login.dingtalk.com/oauth2/auth
|
||||||
|
#获取token 接口
|
||||||
|
- DINGTALK_TOKEN_URL=https://api.dingtalk.com/v1.0/oauth2/userAccessToken
|
||||||
|
#获取用户信息接口
|
||||||
|
- DINGTALK_GET_USER_INFO_URL=https://oapi.dingtalk.com/v1.0/contact/users/me
|
||||||
|
#钉钉APP的应用ID
|
||||||
|
- DINGTALK_CLIENT_ID=xxx
|
||||||
|
#钉钉APP的应用密钥
|
||||||
|
- DINGTALK_CLIENT_SECRET=xxx
|
||||||
|
```
|
||||||
|
|
||||||
|
### 企业微信
|
||||||
|
|
||||||
|
#### 1. 参数获取
|
||||||
|
|
||||||
|
1. 企业的 CorpID
|
||||||
|
|
||||||
|
a. 使用管理员账号登陆企业微信管理后台 `https://work.weixin.qq.com/wework_admin/loginpage_wx`
|
||||||
|
|
||||||
|
b. 点击 【我的企业】 页面,查看企业的 **企业ID**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
2. 创建一个供 FastGPT 使用的内部应用:
|
||||||
|
|
||||||
|
a. 获取应用的 AgentID 和 Secret
|
||||||
|
|
||||||
|
b. 保证这个应用的可见范围为全部(也就是根部门)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
3. 一个域名。并且要求:
|
||||||
|
|
||||||
|
a. 解析到可公网访问的服务器上
|
||||||
|
|
||||||
|
b. 可以在该服务的根目录地址上挂载静态文件(以便进行域名归属认证 ,按照配置处的提示进行操作,只需要挂载一个静态文件,认证后可以删除)
|
||||||
|
|
||||||
|
c. 配置网页授权,JS-SDK以及企业微信授权登陆
|
||||||
|
|
||||||
|
d. 可以在【企业微信授权登陆】页面下方设置“在工作台隐藏应用”
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
4. 获取 “通讯录同步助手” secret
|
||||||
|
|
||||||
|
获取通讯录,组织成员 ID 需要使用 “通讯录同步助手” secret
|
||||||
|
|
||||||
|
【安全与管理】-- 【管理工具】 -- 【通讯录同步】
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
5. 开启接口同步
|
||||||
|
|
||||||
|
6. 获取 Secret
|
||||||
|
|
||||||
|
7. 配置企业可信 IP
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### 2. yml 配置示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
fastgpt-sso:
|
||||||
|
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sso-service:v4.9.0
|
||||||
|
container_name: fastgpt-sso
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- fastgpt
|
||||||
|
environment:
|
||||||
|
- AUTH_TOKEN=xxxxx
|
||||||
|
- SSO_PROVIDER=wecom
|
||||||
|
# oauth 接口,在企微终端使用
|
||||||
|
- WECOM_TARGET_URL_OAUTH=https://open.weixin.qq.com/connect/oauth2/authorize
|
||||||
|
# sso 接口,扫码
|
||||||
|
- WECOM_TARGET_URL_SSO=https://login.work.weixin.qq.com/wwlogin/sso/login
|
||||||
|
# 获取用户id(只能拿id)
|
||||||
|
- WECOM_GET_USER_ID_URL=https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo
|
||||||
|
# 获取用户详细信息(除了名字都有)
|
||||||
|
- WECOM_GET_USER_INFO_URL=https://qyapi.weixin.qq.com/cgi-bin/auth/getuserdetail
|
||||||
|
# 获取用户信息(有名字,没其他信息)
|
||||||
|
- WECOM_GET_USER_NAME_URL=https://qyapi.weixin.qq.com/cgi-bin/user/get
|
||||||
|
# 获取组织 id 列表
|
||||||
|
- WECOM_GET_DEPARTMENT_LIST_URL=https://qyapi.weixin.qq.com/cgi-bin/department/list
|
||||||
|
# 获取用户 id 列表
|
||||||
|
- WECOM_GET_USER_LIST_URL=https://qyapi.weixin.qq.com/cgi-bin/user/list_id
|
||||||
|
# 企微 CorpId
|
||||||
|
- WECOM_CORPID=
|
||||||
|
# 企微 App 的 AgentId 一般是 1000xxx
|
||||||
|
- WECOM_AGENTID=
|
||||||
|
# 企微 App 的 Secret
|
||||||
|
- WECOM_APP_SECRET=
|
||||||
|
# 通讯录同步助手的 Secret
|
||||||
|
- WECOM_SYNC_SECRET=
|
||||||
|
```
|
||||||
|
|
||||||
|
### 标准 OAuth2.0
|
||||||
|
|
||||||
|
#### 参数需求
|
||||||
|
|
||||||
|
我们提供一套标准的 OAuth2.0 接入流程。需要三个地址:
|
||||||
|
|
||||||
|
1. 登陆鉴权地址(登陆后将 code 传入 redirect_uri)
|
||||||
|
- 需要将地址完整写好,除了 redirect_uri 以外(会自动补全)
|
||||||
|
2. 获取 access_token 的地址,请求为 GET 方法,参数 code
|
||||||
|
|
||||||
|
```bash
|
||||||
|
http://example.com/oauth/access_token?code=xxxx
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 获取用户信息的地址
|
||||||
|
|
||||||
|
```bash
|
||||||
|
http://example.com/oauth/user_info
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 配置示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
fastgpt-sso:
|
||||||
|
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-sso-service:v4.9.0
|
||||||
|
container_name: fastgpt-sso
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- fastgpt
|
||||||
|
environment:
|
||||||
|
# OAuth2.0
|
||||||
|
- AUTH_TOKEN=xxxxx
|
||||||
|
- SSO_PROVIDER=oauth2
|
||||||
|
# OAuth2 重定向地址
|
||||||
|
- OAUTH2_AUTHORIZE_URL=
|
||||||
|
# OAuth2 获取 AccessToken 地址
|
||||||
|
- OAUTH2_TOKEN_URL=
|
||||||
|
# OAuth2 获取用户信息地址
|
||||||
|
- OAUTH2_USER_INFO_URL=
|
||||||
|
# OAuth2 用户名字段映射(必填)
|
||||||
|
- OAUTH2_USERNAME_MAP=
|
||||||
|
# OAuth2 头像字段映射(选填)
|
||||||
|
- OAUTH2_AVATAR_MAP=
|
||||||
|
# OAuth2 成员名字段映射(选填)
|
||||||
|
- OAUTH2_MEMBER_NAME_MAP=
|
||||||
|
# OAuth2 联系方式字段映射(选填)
|
||||||
|
- OAUTH2_CONTACT_MAP=
|
||||||
|
```
|
||||||
|
|
||||||
|
## 标准接口文档
|
||||||
|
|
||||||
|
以下是 FastGPT-pro 中,SSO 和成员同步的标准接口文档,如果需要对接非标准系统,可以参考该章节进行开发。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
FastGPT 提供如下标准接口支持:
|
||||||
|
|
||||||
|
1. https://example.com/login/oauth/getAuthURL 获取鉴权重定向地址
|
||||||
|
2. https://example.com/login/oauth/getUserInfo?code=xxxxx 消费 code,换取用户信息
|
||||||
|
3. https://example.com/org/list 获取组织列表
|
||||||
|
4. https://example.com/user/list 获取成员列表
|
||||||
|
|
||||||
|
### 获取 SSO 登录重定向地址
|
||||||
|
|
||||||
|
返回一个重定向登录地址,fastgpt 会自动重定向到该地址。redirect_uri 会自动拼接到该地址的 query中。
|
||||||
|
|
||||||
|
{{< tabs tabTotal="2" >}}
|
||||||
|
{{< tab tabName="请求示例" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X GET "https://redict.example/login/oauth/getAuthURL?redirect_uri=xxx&state=xxxx" \
|
||||||
|
-H "Authorization: Bearer your_token_here" \
|
||||||
|
-H "Content-Type: application/json"
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
|
||||||
|
{{< tab tabName="响应示例" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
成功:
|
||||||
|
|
||||||
|
```JSON
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"message": "",
|
||||||
|
"authURL": "https://example.com/somepath/login/oauth?redirect_uri=https%3A%2F%2Ffastgpt.cn%2Flogin%2Fprovider%0A"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
失败:
|
||||||
|
|
||||||
|
```JSON
|
||||||
|
{
|
||||||
|
"success": false,
|
||||||
|
"message": "错误信息",
|
||||||
|
"authURL": ""
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
{{< /tabs >}}
|
||||||
|
|
||||||
|
|
||||||
|
### SSO 获取用户信息
|
||||||
|
|
||||||
|
该接口接受一个 code 参数作为鉴权,消费 code 返回用户信息。
|
||||||
|
|
||||||
|
{{< tabs tabTotal="2" >}}
|
||||||
|
{{< tab tabName="请求示例" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X GET "https://oauth.example/login/oauth/getUserInfo?code=xxxxxx" \
|
||||||
|
-H "Authorization: Bearer your_token_here" \
|
||||||
|
-H "Content-Type: application/json"
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
|
||||||
|
{{< tab tabName="响应示例" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
成功:
|
||||||
|
```JSON
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"message": "",
|
||||||
|
"username": "fastgpt-123456789",
|
||||||
|
"avatar": "https://example.webp",
|
||||||
|
"contact": "+861234567890",
|
||||||
|
"memberName": "成员名(非必填)",
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
失败:
|
||||||
|
```JSON
|
||||||
|
{
|
||||||
|
"success": false,
|
||||||
|
"message": "错误信息",
|
||||||
|
"username": "",
|
||||||
|
"avatar": "",
|
||||||
|
"contact": ""
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
{{< /tabs >}}
|
||||||
|
|
||||||
|
### 获取组织
|
||||||
|
|
||||||
|
{{< tabs tabTotal="2" >}}
|
||||||
|
{{< tab tabName="请求示例" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X GET "https://example.com/org/list" \
|
||||||
|
-H "Authorization: Bearer your_token_here" \
|
||||||
|
-H "Content-Type: application/json"
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
|
||||||
|
{{< tab tabName="响应示例" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
⚠️注意:只能存在一个根部门。如果你的系统中存在多个根部门,需要先进行处理,加一个虚拟的根部门。返回值类型:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
type OrgListResponseType = {
|
||||||
|
message?: string; // 报错信息
|
||||||
|
success: boolean;
|
||||||
|
orgList: {
|
||||||
|
id: string; // 部门的唯一 id
|
||||||
|
name: string; // 名字
|
||||||
|
parentId: string; // parentId,如果为根部门,传空字符串。
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```JSON
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"message": "",
|
||||||
|
"orgList": [
|
||||||
|
{
|
||||||
|
"id": "od-125151515",
|
||||||
|
"name": "根部门",
|
||||||
|
"parentId": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "od-51516152",
|
||||||
|
"name": "子部门",
|
||||||
|
"parentId": "od-125151515"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
{{< /tabs >}}
|
||||||
|
|
||||||
|
|
||||||
|
### 获取成员
|
||||||
|
|
||||||
|
|
||||||
|
{{< tabs tabTotal="2" >}}
|
||||||
|
{{< tab tabName="请求示例" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X GET "https://example.com/user/list" \
|
||||||
|
-H "Authorization: Bearer your_token_here" \
|
||||||
|
-H "Content-Type: application/json"
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
|
||||||
|
{{< tab tabName="响应示例" >}}
|
||||||
|
{{< markdownify >}}
|
||||||
|
|
||||||
|
返回值类型:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type UserListResponseListType = {
|
||||||
|
message?: string; // 报错信息
|
||||||
|
success: boolean;
|
||||||
|
userList: {
|
||||||
|
username: string; // 唯一 id username 必须与 SSO 接口返回的用户 username 相同。并且必须携带一个前缀,例如: sync-aaaaa,和 sso 接口返回的前缀一致
|
||||||
|
memberName?: string; // 名字,作为 tmbname
|
||||||
|
avatar?: string;
|
||||||
|
contact?: string; // email or phone number
|
||||||
|
orgs?: string[]; // 人员所在组织的 ID。没有组织传 []
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
curl示例
|
||||||
|
|
||||||
|
```JSON
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"message": "",
|
||||||
|
"userList": [
|
||||||
|
{
|
||||||
|
"username": "fastgpt-123456789",
|
||||||
|
"memberName": "张三",
|
||||||
|
"avatar": "https://example.webp",
|
||||||
|
"contact": "+861234567890",
|
||||||
|
"orgs": ["od-125151515", "od-51516152"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"username": "fastgpt-12345678999",
|
||||||
|
"memberName": "李四",
|
||||||
|
"avatar": "",
|
||||||
|
"contact": "",
|
||||||
|
"orgs": ["od-125151515"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{{< /markdownify >}}
|
||||||
|
{{< /tab >}}
|
||||||
|
{{< /tabs >}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 如何对接非标准系统
|
||||||
|
|
||||||
|
1. 客户自己开发:按 fastgpt 提供的标准接口进行开发,并将部署后的服务地址填入 fastgpt-pro
|
||||||
|
可以参考该模版库:[fastgpt-sso-template](https://github.com/labring/fastgpt-sso-template) 进行开发
|
||||||
|
2. 由 fastgpt 团队定制开发:
|
||||||
|
a. 提供系统的 SSO 文档、获取成员和组织的文档、以及外网测试地址。
|
||||||
|
b. 在 fastgpt-sso-service 中,增加对应的 provider 和环境变量,并编写代码来对接。
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
---
|
|
||||||
weight: 490
|
|
||||||
title: '钉钉 SSO 配置'
|
|
||||||
description: '钉钉 SSO 登录'
|
|
||||||
icon: 'chat_bubble'
|
|
||||||
draft: false
|
|
||||||
images: []
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. 注册钉钉应用
|
|
||||||
|
|
||||||
登录 [钉钉开放平台](https://open-dev.dingtalk.com/fe/app?hash=%23%2Fcorp%2Fapp#/corp/app),创建一个应用。
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 2. 配置钉钉应用安全设置
|
|
||||||
|
|
||||||
点击进入创建好的应用后,点开`安全设置`,配置出口 IP(服务器 IP),和重定向 URL。重定向 URL 填写逻辑:
|
|
||||||
|
|
||||||
`{{fastgpt 域名}}/login/provider`
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 3. 设置钉钉应用权限
|
|
||||||
|
|
||||||
点击进入创建好的应用后,点开`权限设置`,开放两个权限: `个人手机号信息`和`通讯录个人信息读权限`
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 4. 发布应用
|
|
||||||
|
|
||||||
点击进入创建好的应用后,点开`版本管理与发布`,随便创建一个新版本即可。
|
|
||||||
|
|
||||||
## 5. 在 FastGPT Admin 配置钉钉应用 id
|
|
||||||
|
|
||||||
名字都是对应上,直接填写即可。
|
|
||||||
|
|
||||||
| | |
|
|
||||||
| --- | --- |
|
|
||||||
| |  |
|
|
||||||
|
|
||||||
## 6. 测试
|
|
||||||
|
|
||||||

|
|
||||||
81
docSite/content/zh-cn/docs/guide/admin/teamMode.md
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
---
|
||||||
|
title: '团队模式说明文档'
|
||||||
|
description: 'FastGPT 团队模式说明文档'
|
||||||
|
icon: ''
|
||||||
|
draft: false
|
||||||
|
toc: true
|
||||||
|
weight: 707
|
||||||
|
---
|
||||||
|
|
||||||
|
## 介绍
|
||||||
|
|
||||||
|
目前支持的团队模式:
|
||||||
|
|
||||||
|
1. 多团队模式(默认模式)
|
||||||
|
2. 单团队模式(全局只有一个团队)
|
||||||
|
3. 成员同步模式(所有成员自外部同步)
|
||||||
|
|
||||||
|
<table class="table-hover table-striped-columns" style="text-align: center;">
|
||||||
|
<tr>
|
||||||
|
<th rowspan="2">团队模式</th>
|
||||||
|
<th colspan="2">短信/邮箱 注册</th>
|
||||||
|
<th colspan="2">管理员直接添加</th>
|
||||||
|
<th colspan="2">SSO 注册</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>是否创建默认团队</th>
|
||||||
|
<th>是否加入 Root 团队</th>
|
||||||
|
<th>是否创建默认团队</th>
|
||||||
|
<th>是否加入 Root 团队</th>
|
||||||
|
<th>是否创建默认团队</th>
|
||||||
|
<th>是否加入 Root 团队</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>单团队模式</td>
|
||||||
|
<td>❌</td>
|
||||||
|
<td>✅</td>
|
||||||
|
<td>❌</td>
|
||||||
|
<td>✅</td>
|
||||||
|
<td>❌</td>
|
||||||
|
<td>✅</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>多团队模式</td>
|
||||||
|
<td>✅</td>
|
||||||
|
<td>❌</td>
|
||||||
|
<td>✅</td>
|
||||||
|
<td>❌</td>
|
||||||
|
<td>✅</td>
|
||||||
|
<td>❌</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>同步模式</td>
|
||||||
|
<td>❌</td>
|
||||||
|
<td>❌</td>
|
||||||
|
<td>❌</td>
|
||||||
|
<td>✅</td>
|
||||||
|
<td>❌</td>
|
||||||
|
<td>✅</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
### 多团队模式(默认模式)
|
||||||
|
|
||||||
|
多团队模式下,每个用户创建时默认创建以自己为所有者的默认团队。
|
||||||
|
|
||||||
|
### 单团队模式
|
||||||
|
|
||||||
|
单团队模式是 v4.9 推出的新功能。为了简化企业进行人员和资源的管理,开启单团队模式后,所有新增的用户都不再创建自己的默认团队,而是加入 root 用户所在的团队。
|
||||||
|
|
||||||
|
### 同步模式
|
||||||
|
|
||||||
|
在完成系统配置,开启同步模式的情况下,外部成员系统的成员会自动同步到 FastGPT 中。
|
||||||
|
|
||||||
|
具体的同步方式和规则请参考 [SSO & 外部成员同步](/docs/guide/admin/sso.md)。
|
||||||
|
|
||||||
|
|
||||||
|
## 配置
|
||||||
|
|
||||||
|
在 `fastgpt-pro` 的`系统配置-成员配置`中,可以配置团队模式。
|
||||||
|
|
||||||
|

|
||||||
@@ -7,7 +7,7 @@ toc: true
|
|||||||
weight: -10
|
weight: -10
|
||||||
---
|
---
|
||||||
|
|
||||||
FastGPT 是一个基于 LLM 大语言模型的知识库问答系统,提供开箱即用的数据处理、模型调用等能力。同时可以通过 Flow 可视化进行工作流编排,从而实现复杂的问答场景!
|
FastGPT 是一个AI Agent 构建平台,提供开箱即用的数据处理、模型调用等能力,同时可以通过 Flow 可视化进行工作流编排,从而实现复杂的应用场景!t
|
||||||
|
|
||||||
{{% alert icon="🤖 " context="success" %}}
|
{{% alert icon="🤖 " context="success" %}}
|
||||||
FastGPT 在线使用:[https://tryfastgpt.ai](https://tryfastgpt.ai)
|
FastGPT 在线使用:[https://tryfastgpt.ai](https://tryfastgpt.ai)
|
||||||
|
|||||||
40
env.d.ts
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
declare global {
|
||||||
|
namespace NodeJS {
|
||||||
|
interface ProcessEnv {
|
||||||
|
LOG_DEPTH: string;
|
||||||
|
DEFAULT_ROOT_PSW: string;
|
||||||
|
DB_MAX_LINK: string;
|
||||||
|
TOKEN_KEY: string;
|
||||||
|
FILE_TOKEN_KEY: string;
|
||||||
|
ROOT_KEY: string;
|
||||||
|
OPENAI_BASE_URL: string;
|
||||||
|
CHAT_API_KEY: string;
|
||||||
|
AIPROXY_API_ENDPOINT: string;
|
||||||
|
AIPROXY_API_TOKEN: string;
|
||||||
|
MULTIPLE_DATA_TO_BASE64: string;
|
||||||
|
MONGODB_URI: string;
|
||||||
|
MONGODB_LOG_URI?: string;
|
||||||
|
PG_URL: string;
|
||||||
|
OCEANBASE_URL: string;
|
||||||
|
MILVUS_ADDRESS: string;
|
||||||
|
MILVUS_TOKEN: string;
|
||||||
|
SANDBOX_URL: string;
|
||||||
|
PRO_URL: string;
|
||||||
|
FE_DOMAIN: string;
|
||||||
|
FILE_DOMAIN: string;
|
||||||
|
NEXT_PUBLIC_BASE_URL: string;
|
||||||
|
LOG_LEVEL: string;
|
||||||
|
STORE_LOG_LEVEL: string;
|
||||||
|
USE_IP_LIMIT: string;
|
||||||
|
WORKFLOW_MAX_RUN_TIMES: string;
|
||||||
|
WORKFLOW_MAX_LOOP_TIMES: string;
|
||||||
|
CHECK_INTERNAL_IP: string;
|
||||||
|
CHAT_LOG_URL: string;
|
||||||
|
CHAT_LOG_INTERVAL: string;
|
||||||
|
CHAT_LOG_SOURCE_ID_PREFIX: string;
|
||||||
|
ALLOWED_ORIGINS: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {};
|
||||||
17
packages/global/common/system/types/index.d.ts
vendored
@@ -112,17 +112,18 @@ export type SystemEnvType = {
|
|||||||
vectorMaxProcess: number;
|
vectorMaxProcess: number;
|
||||||
qaMaxProcess: number;
|
qaMaxProcess: number;
|
||||||
vlmMaxProcess: number;
|
vlmMaxProcess: number;
|
||||||
pgHNSWEfSearch: number;
|
hnswEfSearch: number;
|
||||||
tokenWorkers: number; // token count max worker
|
tokenWorkers: number; // token count max worker
|
||||||
|
|
||||||
oneapiUrl?: string;
|
oneapiUrl?: string;
|
||||||
chatApiKey?: string;
|
chatApiKey?: string;
|
||||||
|
|
||||||
customPdfParse?: {
|
customPdfParse?: customPdfParseType;
|
||||||
url?: string;
|
};
|
||||||
key?: string;
|
|
||||||
|
export type customPdfParseType = {
|
||||||
doc2xKey?: string;
|
url?: string;
|
||||||
price?: number; // n points/1 page
|
key?: string;
|
||||||
};
|
doc2xKey?: string;
|
||||||
|
price?: number;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { i18nT } from '../../../web/i18n/utils';
|
||||||
|
|
||||||
export enum ChatCompletionRequestMessageRoleEnum {
|
export enum ChatCompletionRequestMessageRoleEnum {
|
||||||
'System' = 'system',
|
'System' = 'system',
|
||||||
'User' = 'user',
|
'User' = 'user',
|
||||||
@@ -28,3 +30,13 @@ export enum EmbeddingTypeEnm {
|
|||||||
query = 'query',
|
query = 'query',
|
||||||
db = 'db'
|
db = 'db'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const completionFinishReasonMap = {
|
||||||
|
close: i18nT('chat:completion_finish_close'),
|
||||||
|
stop: i18nT('chat:completion_finish_stop'),
|
||||||
|
length: i18nT('chat:completion_finish_length'),
|
||||||
|
tool_calls: i18nT('chat:completion_finish_tool_calls'),
|
||||||
|
content_filter: i18nT('chat:completion_finish_content_filter'),
|
||||||
|
function_call: i18nT('chat:completion_finish_function_call'),
|
||||||
|
null: i18nT('chat:completion_finish_null')
|
||||||
|
};
|
||||||
|
|||||||
9
packages/global/core/ai/type.d.ts
vendored
@@ -73,6 +73,15 @@ export type ChatCompletionMessageFunctionCall =
|
|||||||
export type StreamChatType = Stream<openai.Chat.Completions.ChatCompletionChunk>;
|
export type StreamChatType = Stream<openai.Chat.Completions.ChatCompletionChunk>;
|
||||||
export type UnStreamChatType = openai.Chat.Completions.ChatCompletion;
|
export type UnStreamChatType = openai.Chat.Completions.ChatCompletion;
|
||||||
|
|
||||||
|
export type CompletionFinishReason =
|
||||||
|
| 'close'
|
||||||
|
| 'stop'
|
||||||
|
| 'length'
|
||||||
|
| 'tool_calls'
|
||||||
|
| 'content_filter'
|
||||||
|
| 'function_call'
|
||||||
|
| null;
|
||||||
|
|
||||||
export default openai;
|
export default openai;
|
||||||
export * from 'openai';
|
export * from 'openai';
|
||||||
|
|
||||||
|
|||||||
3
packages/global/core/dataset/api.d.ts
vendored
@@ -15,7 +15,6 @@ export type DatasetUpdateBody = {
|
|||||||
name?: string;
|
name?: string;
|
||||||
avatar?: string;
|
avatar?: string;
|
||||||
intro?: string;
|
intro?: string;
|
||||||
status?: DatasetSchemaType['status'];
|
|
||||||
|
|
||||||
agentModel?: string;
|
agentModel?: string;
|
||||||
vlmModel?: string;
|
vlmModel?: string;
|
||||||
@@ -26,6 +25,7 @@ export type DatasetUpdateBody = {
|
|||||||
apiServer?: DatasetSchemaType['apiServer'];
|
apiServer?: DatasetSchemaType['apiServer'];
|
||||||
yuqueServer?: DatasetSchemaType['yuqueServer'];
|
yuqueServer?: DatasetSchemaType['yuqueServer'];
|
||||||
feishuServer?: DatasetSchemaType['feishuServer'];
|
feishuServer?: DatasetSchemaType['feishuServer'];
|
||||||
|
chunkSettings?: DatasetSchemaType['chunkSettings'];
|
||||||
|
|
||||||
// sync schedule
|
// sync schedule
|
||||||
autoSync?: boolean;
|
autoSync?: boolean;
|
||||||
@@ -141,7 +141,6 @@ export type PushDatasetDataChunkProps = {
|
|||||||
|
|
||||||
export type PostWebsiteSyncParams = {
|
export type PostWebsiteSyncParams = {
|
||||||
datasetId: string;
|
datasetId: string;
|
||||||
billId: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PushDatasetDataProps = {
|
export type PushDatasetDataProps = {
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ export const DatasetTypeMap = {
|
|||||||
|
|
||||||
export enum DatasetStatusEnum {
|
export enum DatasetStatusEnum {
|
||||||
active = 'active',
|
active = 'active',
|
||||||
syncing = 'syncing'
|
syncing = 'syncing',
|
||||||
|
waiting = 'waiting'
|
||||||
}
|
}
|
||||||
export const DatasetStatusMap = {
|
export const DatasetStatusMap = {
|
||||||
[DatasetStatusEnum.active]: {
|
[DatasetStatusEnum.active]: {
|
||||||
@@ -58,6 +59,9 @@ export const DatasetStatusMap = {
|
|||||||
},
|
},
|
||||||
[DatasetStatusEnum.syncing]: {
|
[DatasetStatusEnum.syncing]: {
|
||||||
label: i18nT('common:core.dataset.status.syncing')
|
label: i18nT('common:core.dataset.status.syncing')
|
||||||
|
},
|
||||||
|
[DatasetStatusEnum.waiting]: {
|
||||||
|
label: i18nT('common:core.dataset.status.waiting')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
24
packages/global/core/dataset/type.d.ts
vendored
@@ -17,6 +17,20 @@ import { SourceMemberType } from 'support/user/type';
|
|||||||
import { DatasetDataIndexTypeEnum } from './data/constants';
|
import { DatasetDataIndexTypeEnum } from './data/constants';
|
||||||
import { ChunkSettingModeEnum } from './constants';
|
import { ChunkSettingModeEnum } from './constants';
|
||||||
|
|
||||||
|
export type ChunkSettingsType = {
|
||||||
|
trainingType: DatasetCollectionDataProcessModeEnum;
|
||||||
|
autoIndexes?: boolean;
|
||||||
|
imageIndex?: boolean;
|
||||||
|
|
||||||
|
chunkSettingMode?: ChunkSettingModeEnum;
|
||||||
|
chunkSplitMode?: DataChunkSplitModeEnum;
|
||||||
|
|
||||||
|
chunkSize?: number;
|
||||||
|
indexSize?: number;
|
||||||
|
chunkSplitter?: string;
|
||||||
|
qaPrompt?: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type DatasetSchemaType = {
|
export type DatasetSchemaType = {
|
||||||
_id: string;
|
_id: string;
|
||||||
parentId?: string;
|
parentId?: string;
|
||||||
@@ -29,7 +43,6 @@ export type DatasetSchemaType = {
|
|||||||
name: string;
|
name: string;
|
||||||
intro: string;
|
intro: string;
|
||||||
type: `${DatasetTypeEnum}`;
|
type: `${DatasetTypeEnum}`;
|
||||||
status: `${DatasetStatusEnum}`;
|
|
||||||
|
|
||||||
vectorModel: string;
|
vectorModel: string;
|
||||||
agentModel: string;
|
agentModel: string;
|
||||||
@@ -39,14 +52,16 @@ export type DatasetSchemaType = {
|
|||||||
url: string;
|
url: string;
|
||||||
selector: string;
|
selector: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
chunkSettings?: ChunkSettingsType;
|
||||||
|
|
||||||
inheritPermission: boolean;
|
inheritPermission: boolean;
|
||||||
apiServer?: APIFileServer;
|
apiServer?: APIFileServer;
|
||||||
feishuServer?: FeishuServer;
|
feishuServer?: FeishuServer;
|
||||||
yuqueServer?: YuqueServer;
|
yuqueServer?: YuqueServer;
|
||||||
|
|
||||||
autoSync?: boolean;
|
|
||||||
|
|
||||||
// abandon
|
// abandon
|
||||||
|
autoSync?: boolean;
|
||||||
externalReadUrl?: string;
|
externalReadUrl?: string;
|
||||||
defaultPermission?: number;
|
defaultPermission?: number;
|
||||||
};
|
};
|
||||||
@@ -163,6 +178,7 @@ export type DatasetTrainingSchemaType = {
|
|||||||
weight: number;
|
weight: number;
|
||||||
indexes: Omit<DatasetDataIndexItemType, 'dataId'>[];
|
indexes: Omit<DatasetDataIndexItemType, 'dataId'>[];
|
||||||
retryCount: number;
|
retryCount: number;
|
||||||
|
errorMsg?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CollectionWithDatasetType = DatasetCollectionSchemaType & {
|
export type CollectionWithDatasetType = DatasetCollectionSchemaType & {
|
||||||
@@ -192,6 +208,7 @@ export type DatasetListItemType = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type DatasetItemType = Omit<DatasetSchemaType, 'vectorModel' | 'agentModel' | 'vlmModel'> & {
|
export type DatasetItemType = Omit<DatasetSchemaType, 'vectorModel' | 'agentModel' | 'vlmModel'> & {
|
||||||
|
status: `${DatasetStatusEnum}`;
|
||||||
vectorModel: EmbeddingModelItemType;
|
vectorModel: EmbeddingModelItemType;
|
||||||
agentModel: LLMModelItemType;
|
agentModel: LLMModelItemType;
|
||||||
vlmModel?: LLMModelItemType;
|
vlmModel?: LLMModelItemType;
|
||||||
@@ -216,6 +233,7 @@ export type DatasetCollectionItemType = CollectionWithDatasetType & {
|
|||||||
file?: DatasetFileSchema;
|
file?: DatasetFileSchema;
|
||||||
permission: DatasetPermission;
|
permission: DatasetPermission;
|
||||||
indexAmount: number;
|
indexAmount: number;
|
||||||
|
errorCount?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ================= data ===================== */
|
/* ================= data ===================== */
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export enum SseResponseEventEnum {
|
|||||||
answer = 'answer', // animation stream
|
answer = 'answer', // animation stream
|
||||||
fastAnswer = 'fastAnswer', // direct answer text, not animation
|
fastAnswer = 'fastAnswer', // direct answer text, not animation
|
||||||
flowNodeStatus = 'flowNodeStatus', // update node status
|
flowNodeStatus = 'flowNodeStatus', // update node status
|
||||||
|
flowNodeResponse = 'flowNodeResponse', // node response
|
||||||
|
|
||||||
toolCall = 'toolCall', // tool start
|
toolCall = 'toolCall', // tool start
|
||||||
toolParams = 'toolParams', // tool params return
|
toolParams = 'toolParams', // tool params return
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { UserSelectOptionType } from '../template/system/userSelect/type';
|
|||||||
import { WorkflowResponseType } from '../../../../service/core/workflow/dispatch/type';
|
import { WorkflowResponseType } from '../../../../service/core/workflow/dispatch/type';
|
||||||
import { AiChatQuoteRoleType } from '../template/system/aiChat/type';
|
import { AiChatQuoteRoleType } from '../template/system/aiChat/type';
|
||||||
import { LafAccountType, OpenaiAccountType } from '../../../support/user/team/type';
|
import { LafAccountType, OpenaiAccountType } from '../../../support/user/team/type';
|
||||||
|
import { CompletionFinishReason } from '../../ai/type';
|
||||||
|
|
||||||
export type ExternalProviderType = {
|
export type ExternalProviderType = {
|
||||||
openaiAccount?: OpenaiAccountType;
|
openaiAccount?: OpenaiAccountType;
|
||||||
@@ -40,6 +41,7 @@ export type ChatDispatchProps = {
|
|||||||
id: string; // May be the id of the system plug-in (cannot be used directly to look up the table)
|
id: string; // May be the id of the system plug-in (cannot be used directly to look up the table)
|
||||||
teamId: string;
|
teamId: string;
|
||||||
tmbId: string; // App tmbId
|
tmbId: string; // App tmbId
|
||||||
|
isChildApp?: boolean;
|
||||||
};
|
};
|
||||||
runningUserInfo: {
|
runningUserInfo: {
|
||||||
teamId: string;
|
teamId: string;
|
||||||
@@ -58,6 +60,7 @@ export type ChatDispatchProps = {
|
|||||||
isToolCall?: boolean;
|
isToolCall?: boolean;
|
||||||
workflowStreamResponse?: WorkflowResponseType;
|
workflowStreamResponse?: WorkflowResponseType;
|
||||||
workflowDispatchDeep?: number;
|
workflowDispatchDeep?: number;
|
||||||
|
version?: 'v1' | 'v2';
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ModuleDispatchProps<T> = ChatDispatchProps & {
|
export type ModuleDispatchProps<T> = ChatDispatchProps & {
|
||||||
@@ -128,6 +131,7 @@ export type DispatchNodeResponseType = {
|
|||||||
obj: `${ChatRoleEnum}`;
|
obj: `${ChatRoleEnum}`;
|
||||||
value: string;
|
value: string;
|
||||||
}[]; // completion context array. history will slice
|
}[]; // completion context array. history will slice
|
||||||
|
finishReason?: CompletionFinishReason;
|
||||||
|
|
||||||
// dataset search
|
// dataset search
|
||||||
similarity?: number;
|
similarity?: number;
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import { FlowNodeOutputItemType, ReferenceValueType } from '../type/io';
|
|||||||
import { ChatItemType, NodeOutputItemType } from '../../../core/chat/type';
|
import { ChatItemType, NodeOutputItemType } from '../../../core/chat/type';
|
||||||
import { ChatItemValueTypeEnum, ChatRoleEnum } from '../../../core/chat/constants';
|
import { ChatItemValueTypeEnum, ChatRoleEnum } from '../../../core/chat/constants';
|
||||||
import { replaceVariable, valToStr } from '../../../common/string/tools';
|
import { replaceVariable, valToStr } from '../../../common/string/tools';
|
||||||
import { ChatCompletionChunk } from 'openai/resources';
|
|
||||||
|
|
||||||
export const getMaxHistoryLimitFromNodes = (nodes: StoreNodeItemType[]): number => {
|
export const getMaxHistoryLimitFromNodes = (nodes: StoreNodeItemType[]): number => {
|
||||||
let limit = 10;
|
let limit = 10;
|
||||||
@@ -67,7 +66,7 @@ export const getLastInteractiveValue = (histories: ChatItemType[]) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const initWorkflowEdgeStatus = (
|
export const initWorkflowEdgeStatus = (
|
||||||
edges: StoreEdgeItemType[],
|
edges: StoreEdgeItemType[] | RuntimeEdgeItemType[],
|
||||||
histories?: ChatItemType[]
|
histories?: ChatItemType[]
|
||||||
): RuntimeEdgeItemType[] => {
|
): RuntimeEdgeItemType[] => {
|
||||||
// If there is a history, use the last interactive value
|
// If there is a history, use the last interactive value
|
||||||
|
|||||||
@@ -5,10 +5,36 @@ import { FlowNodeInputTypeEnum } from 'core/workflow/node/constant';
|
|||||||
import { WorkflowIOValueTypeEnum } from 'core/workflow/constants';
|
import { WorkflowIOValueTypeEnum } from 'core/workflow/constants';
|
||||||
import type { ChatCompletionMessageParam } from '../../../../ai/type';
|
import type { ChatCompletionMessageParam } from '../../../../ai/type';
|
||||||
|
|
||||||
|
type InteractiveBasicType = {
|
||||||
|
entryNodeIds: string[];
|
||||||
|
memoryEdges: RuntimeEdgeItemType[];
|
||||||
|
nodeOutputs: NodeOutputItemType[];
|
||||||
|
|
||||||
|
toolParams?: {
|
||||||
|
entryNodeIds: string[]; // 记录工具中,交互节点的 Id,而不是起始工作流的入口
|
||||||
|
memoryMessages: ChatCompletionMessageParam[]; // 这轮工具中,产生的新的 messages
|
||||||
|
toolCallId: string; // 记录对应 tool 的id,用于后续交互节点可以替换掉 tool 的 response
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type InteractiveNodeType = {
|
||||||
|
entryNodeIds?: string[];
|
||||||
|
memoryEdges?: RuntimeEdgeItemType[];
|
||||||
|
nodeOutputs?: NodeOutputItemType[];
|
||||||
|
};
|
||||||
|
|
||||||
export type UserSelectOptionItemType = {
|
export type UserSelectOptionItemType = {
|
||||||
key: string;
|
key: string;
|
||||||
value: string;
|
value: string;
|
||||||
};
|
};
|
||||||
|
type UserSelectInteractive = InteractiveNodeType & {
|
||||||
|
type: 'userSelect';
|
||||||
|
params: {
|
||||||
|
description: string;
|
||||||
|
userSelectOptions: UserSelectOptionItemType[];
|
||||||
|
userSelectedVal?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export type UserInputFormItemType = {
|
export type UserInputFormItemType = {
|
||||||
type: FlowNodeInputTypeEnum;
|
type: FlowNodeInputTypeEnum;
|
||||||
@@ -28,29 +54,7 @@ export type UserInputFormItemType = {
|
|||||||
// select
|
// select
|
||||||
list?: { label: string; value: string }[];
|
list?: { label: string; value: string }[];
|
||||||
};
|
};
|
||||||
|
type UserInputInteractive = InteractiveNodeType & {
|
||||||
type InteractiveBasicType = {
|
|
||||||
entryNodeIds: string[];
|
|
||||||
memoryEdges: RuntimeEdgeItemType[];
|
|
||||||
nodeOutputs: NodeOutputItemType[];
|
|
||||||
|
|
||||||
toolParams?: {
|
|
||||||
entryNodeIds: string[]; // 记录工具中,交互节点的 Id,而不是起始工作流的入口
|
|
||||||
memoryMessages: ChatCompletionMessageParam[]; // 这轮工具中,产生的新的 messages
|
|
||||||
toolCallId: string; // 记录对应 tool 的id,用于后续交互节点可以替换掉 tool 的 response
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
type UserSelectInteractive = {
|
|
||||||
type: 'userSelect';
|
|
||||||
params: {
|
|
||||||
description: string;
|
|
||||||
userSelectOptions: UserSelectOptionItemType[];
|
|
||||||
userSelectedVal?: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
type UserInputInteractive = {
|
|
||||||
type: 'userInput';
|
type: 'userInput';
|
||||||
params: {
|
params: {
|
||||||
description: string;
|
description: string;
|
||||||
@@ -58,6 +62,5 @@ type UserInputInteractive = {
|
|||||||
submitted?: boolean;
|
submitted?: boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type InteractiveNodeResponseType = UserSelectInteractive | UserInputInteractive;
|
export type InteractiveNodeResponseType = UserSelectInteractive | UserInputInteractive;
|
||||||
export type WorkflowInteractiveResponseType = InteractiveBasicType & InteractiveNodeResponseType;
|
export type WorkflowInteractiveResponseType = InteractiveBasicType & InteractiveNodeResponseType;
|
||||||
|
|||||||
@@ -1,7 +1,23 @@
|
|||||||
export const JS_TEMPLATE = `function main({data1, data2}){
|
export const JS_TEMPLATE = `function main({data1, data2}){
|
||||||
|
|
||||||
return {
|
return {
|
||||||
result: data1,
|
result: data1,
|
||||||
data2
|
data2
|
||||||
}
|
}
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
|
export const PY_TEMPLATE = `def main(data1, data2):
|
||||||
|
return {
|
||||||
|
"result": data1,
|
||||||
|
"data2": data2
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export enum SandboxCodeTypeEnum {
|
||||||
|
js = 'js',
|
||||||
|
py = 'py'
|
||||||
|
}
|
||||||
|
export const SNADBOX_CODE_TEMPLATE = {
|
||||||
|
[SandboxCodeTypeEnum.js]: JS_TEMPLATE,
|
||||||
|
[SandboxCodeTypeEnum.py]: PY_TEMPLATE
|
||||||
|
};
|
||||||
|
|||||||
@@ -68,12 +68,14 @@ export const CodeNode: FlowNodeTemplateType = {
|
|||||||
key: NodeInputKeyEnum.codeType,
|
key: NodeInputKeyEnum.codeType,
|
||||||
renderTypeList: [FlowNodeInputTypeEnum.hidden],
|
renderTypeList: [FlowNodeInputTypeEnum.hidden],
|
||||||
label: '',
|
label: '',
|
||||||
|
valueType: WorkflowIOValueTypeEnum.string,
|
||||||
value: 'js'
|
value: 'js'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: NodeInputKeyEnum.code,
|
key: NodeInputKeyEnum.code,
|
||||||
renderTypeList: [FlowNodeInputTypeEnum.custom],
|
renderTypeList: [FlowNodeInputTypeEnum.custom],
|
||||||
label: '',
|
label: '',
|
||||||
|
valueType: WorkflowIOValueTypeEnum.string,
|
||||||
value: JS_TEMPLATE
|
value: JS_TEMPLATE
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
2
packages/global/core/workflow/type/node.d.ts
vendored
@@ -23,6 +23,7 @@ import { NextApiResponse } from 'next';
|
|||||||
import { AppDetailType, AppSchema } from '../../app/type';
|
import { AppDetailType, AppSchema } from '../../app/type';
|
||||||
import { ParentIdType } from 'common/parentFolder/type';
|
import { ParentIdType } from 'common/parentFolder/type';
|
||||||
import { AppTypeEnum } from 'core/app/constants';
|
import { AppTypeEnum } from 'core/app/constants';
|
||||||
|
import { WorkflowInteractiveResponseType } from '../template/system/interactive/type';
|
||||||
|
|
||||||
export type FlowNodeCommonType = {
|
export type FlowNodeCommonType = {
|
||||||
parentNodeId?: string;
|
parentNodeId?: string;
|
||||||
@@ -120,6 +121,7 @@ export type FlowNodeItemType = FlowNodeTemplateType & {
|
|||||||
showResult?: boolean; // show and hide result modal
|
showResult?: boolean; // show and hide result modal
|
||||||
response?: ChatHistoryItemResType;
|
response?: ChatHistoryItemResType;
|
||||||
isExpired?: boolean;
|
isExpired?: boolean;
|
||||||
|
workflowInteractiveResponse?: WorkflowInteractiveResponseType;
|
||||||
};
|
};
|
||||||
isFolded?: boolean;
|
isFolded?: boolean;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"jschardet": "3.1.1",
|
"jschardet": "3.1.1",
|
||||||
"nanoid": "^5.1.3",
|
"nanoid": "^5.1.3",
|
||||||
"next": "14.2.25",
|
"next": "14.2.26",
|
||||||
"openai": "4.61.0",
|
"openai": "4.61.0",
|
||||||
"openapi-types": "^12.1.3",
|
"openapi-types": "^12.1.3",
|
||||||
"json5": "^2.2.3",
|
"json5": "^2.2.3",
|
||||||
|
|||||||
@@ -24,5 +24,6 @@ export enum SendInformTemplateCodeEnum {
|
|||||||
RESET_PASSWORD = 'RESET_PASSWORD',
|
RESET_PASSWORD = 'RESET_PASSWORD',
|
||||||
BIND_NOTIFICATION = 'BIND_NOTIFICATION',
|
BIND_NOTIFICATION = 'BIND_NOTIFICATION',
|
||||||
LACK_OF_POINTS = 'LACK_OF_POINTS',
|
LACK_OF_POINTS = 'LACK_OF_POINTS',
|
||||||
CUSTOM = 'CUSTOM'
|
CUSTOM = 'CUSTOM',
|
||||||
|
MANAGE_RENAME = 'MANAGE_RENAME'
|
||||||
}
|
}
|
||||||
|
|||||||
13
packages/global/support/user/inform/type.d.ts
vendored
@@ -19,6 +19,19 @@ export type SendInform2User = SendInformProps & {
|
|||||||
export type UserInformSchema = {
|
export type UserInformSchema = {
|
||||||
_id: string;
|
_id: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
|
teamId?: string;
|
||||||
|
time: Date;
|
||||||
|
level: `${InformLevelEnum}`;
|
||||||
|
title: string;
|
||||||
|
content: string;
|
||||||
|
read: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UserInformType = {
|
||||||
|
_id: string;
|
||||||
|
userId: string;
|
||||||
|
teamId?: string;
|
||||||
|
teamName?: string;
|
||||||
time: Date;
|
time: Date;
|
||||||
level: `${InformLevelEnum}`;
|
level: `${InformLevelEnum}`;
|
||||||
title: string;
|
title: string;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cheerio": "1.0.0-rc.12",
|
"cheerio": "1.0.0-rc.12",
|
||||||
"@types/pg": "^8.6.6",
|
"@types/pg": "^8.6.6",
|
||||||
|
"@types/nodemailer": "^6.4.17",
|
||||||
"axios": "^1.8.2",
|
"axios": "^1.8.2",
|
||||||
"duck-duck-scrape": "^2.2.5",
|
"duck-duck-scrape": "^2.2.5",
|
||||||
"echarts": "5.4.1",
|
"echarts": "5.4.1",
|
||||||
@@ -13,6 +14,7 @@
|
|||||||
"mssql": "^11.0.1",
|
"mssql": "^11.0.1",
|
||||||
"mysql2": "^3.11.3",
|
"mysql2": "^3.11.3",
|
||||||
"json5": "^2.2.3",
|
"json5": "^2.2.3",
|
||||||
|
"nodemailer": "^6.10.0",
|
||||||
"pg": "^8.10.0",
|
"pg": "^8.10.0",
|
||||||
"wikijs": "^6.4.1"
|
"wikijs": "^6.4.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ const packagePluginList = [
|
|||||||
'databaseConnection',
|
'databaseConnection',
|
||||||
'Doc2X',
|
'Doc2X',
|
||||||
'Doc2X/PDF2text',
|
'Doc2X/PDF2text',
|
||||||
'searchXNG'
|
'searchXNG',
|
||||||
|
'smtpEmail'
|
||||||
];
|
];
|
||||||
|
|
||||||
export const list = [...staticPluginList, ...packagePluginList];
|
export const list = [...staticPluginList, ...packagePluginList];
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ const main = async ({
|
|||||||
port: parseInt(port, 10),
|
port: parseInt(port, 10),
|
||||||
database: databaseName,
|
database: databaseName,
|
||||||
user,
|
user,
|
||||||
password
|
password,
|
||||||
|
connectionTimeoutMillis: 30000
|
||||||
});
|
});
|
||||||
|
|
||||||
await client.connect();
|
await client.connect();
|
||||||
@@ -47,7 +48,8 @@ const main = async ({
|
|||||||
port: parseInt(port, 10),
|
port: parseInt(port, 10),
|
||||||
database: databaseName,
|
database: databaseName,
|
||||||
user,
|
user,
|
||||||
password
|
password,
|
||||||
|
connectTimeout: 30000
|
||||||
});
|
});
|
||||||
|
|
||||||
const [rows] = await connection.execute(sql);
|
const [rows] = await connection.execute(sql);
|
||||||
|
|||||||
122
packages/plugins/src/smtpEmail/index.ts
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||||
|
import nodemailer from 'nodemailer';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
// SMTP配置
|
||||||
|
smtpHost: string;
|
||||||
|
smtpPort: string;
|
||||||
|
SSL: boolean;
|
||||||
|
smtpUser: string;
|
||||||
|
smtpPass: string;
|
||||||
|
fromName?: string;
|
||||||
|
// 邮件参数
|
||||||
|
to: string;
|
||||||
|
subject: string;
|
||||||
|
content: string;
|
||||||
|
cc?: string;
|
||||||
|
bcc?: string;
|
||||||
|
attachments?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Response {
|
||||||
|
success: boolean;
|
||||||
|
messageId?: string;
|
||||||
|
error?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const validateEmail = (email: string) => {
|
||||||
|
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
return regex.test(email);
|
||||||
|
};
|
||||||
|
|
||||||
|
const validateEmails = (emails: string) => {
|
||||||
|
return emails.split(',').every((email) => validateEmail(email.trim()));
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = async ({
|
||||||
|
smtpHost,
|
||||||
|
smtpPort,
|
||||||
|
SSL,
|
||||||
|
smtpUser,
|
||||||
|
smtpPass,
|
||||||
|
fromName,
|
||||||
|
to,
|
||||||
|
subject,
|
||||||
|
content,
|
||||||
|
cc,
|
||||||
|
bcc,
|
||||||
|
attachments
|
||||||
|
}: Props): Promise<Response> => {
|
||||||
|
try {
|
||||||
|
// 验证SMTP配置
|
||||||
|
if (!smtpHost || !smtpPort || !smtpUser || !smtpPass) {
|
||||||
|
throw new Error('Incomplete SMTP configuration');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证必填参数
|
||||||
|
if (!to || !subject || !content) {
|
||||||
|
throw new Error('Recipient, subject, and content are required');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证邮箱格式
|
||||||
|
if (!validateEmails(to)) {
|
||||||
|
throw new Error('Invalid recipient email format');
|
||||||
|
}
|
||||||
|
if (cc && !validateEmails(cc)) {
|
||||||
|
throw new Error('Invalid CC email format');
|
||||||
|
}
|
||||||
|
if (bcc && !validateEmails(bcc)) {
|
||||||
|
throw new Error('Invalid BCC email format');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建SMTP传输对象
|
||||||
|
const transporter = nodemailer.createTransport({
|
||||||
|
host: smtpHost,
|
||||||
|
port: Number(smtpPort),
|
||||||
|
secure: SSL === true,
|
||||||
|
auth: {
|
||||||
|
user: smtpUser,
|
||||||
|
pass: smtpPass
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let attachmentsArray = [];
|
||||||
|
try {
|
||||||
|
attachmentsArray = JSON.parse(attachments || '[]');
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error('Attachment format parsing error, please check attachment configuration');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送邮件
|
||||||
|
const info = await transporter.sendMail({
|
||||||
|
from: `"${fromName || 'FastGPT'}" <${smtpUser}>`,
|
||||||
|
to: to
|
||||||
|
.split(',')
|
||||||
|
.map((email) => email.trim())
|
||||||
|
.join(','),
|
||||||
|
cc: cc
|
||||||
|
?.split(',')
|
||||||
|
.map((email) => email.trim())
|
||||||
|
.join(','),
|
||||||
|
bcc: bcc
|
||||||
|
?.split(',')
|
||||||
|
.map((email) => email.trim())
|
||||||
|
.join(','),
|
||||||
|
subject,
|
||||||
|
html: content,
|
||||||
|
attachments: attachmentsArray || []
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
messageId: info.messageId
|
||||||
|
};
|
||||||
|
} catch (error: any) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: getErrText(error)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default main;
|
||||||
651
packages/plugins/src/smtpEmail/template.json
Normal file
@@ -0,0 +1,651 @@
|
|||||||
|
{
|
||||||
|
"author": "cloudpense",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"name": "Email 邮件发送",
|
||||||
|
"avatar": "plugins/email",
|
||||||
|
"intro": "通过SMTP协议发送电子邮件(nodemailer)",
|
||||||
|
"showStatus": true,
|
||||||
|
"weight": 10,
|
||||||
|
"isTool": true,
|
||||||
|
"templateType": "tools",
|
||||||
|
|
||||||
|
"workflow": {
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"nodeId": "pluginInput",
|
||||||
|
"name": "workflow:template.plugin_start",
|
||||||
|
"intro": "workflow:intro_plugin_input",
|
||||||
|
"avatar": "core/workflow/template/workflowStart",
|
||||||
|
"flowNodeType": "pluginInput",
|
||||||
|
"showStatus": false,
|
||||||
|
"position": {
|
||||||
|
"x": 595.3456736313964,
|
||||||
|
"y": -323.02524442647456
|
||||||
|
},
|
||||||
|
"version": "481",
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"renderTypeList": ["input", "reference"],
|
||||||
|
"selectedTypeIndex": 0,
|
||||||
|
"valueType": "string",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "smtpHost",
|
||||||
|
"label": "smtpHost",
|
||||||
|
"description": "",
|
||||||
|
"defaultValue": "",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"label": "",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxFiles": 5,
|
||||||
|
"canSelectFile": true,
|
||||||
|
"canSelectImg": true,
|
||||||
|
"required": true,
|
||||||
|
"customInputConfig": {
|
||||||
|
"selectValueTypeList": ["string"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"renderTypeList": ["input", "reference"],
|
||||||
|
"selectedTypeIndex": 0,
|
||||||
|
"valueType": "string",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "smtpPort",
|
||||||
|
"label": "smtpPort",
|
||||||
|
"description": "SMTP端口",
|
||||||
|
"defaultValue": "465",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"label": "",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxFiles": 5,
|
||||||
|
"canSelectFile": true,
|
||||||
|
"canSelectImg": true,
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"renderTypeList": ["select", "reference"],
|
||||||
|
"selectedTypeIndex": 0,
|
||||||
|
"valueType": "string",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "SSL",
|
||||||
|
"label": "SSL",
|
||||||
|
"description": "SSL",
|
||||||
|
"defaultValue": "true",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"label": "true",
|
||||||
|
"value": "true"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "false",
|
||||||
|
"value": "false"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxFiles": 5,
|
||||||
|
"canSelectFile": true,
|
||||||
|
"canSelectImg": true,
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"renderTypeList": ["input", "reference"],
|
||||||
|
"selectedTypeIndex": 0,
|
||||||
|
"valueType": "string",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "smtpUser",
|
||||||
|
"label": "smtpUser",
|
||||||
|
"description": "SMTP用户名, 邮箱账号",
|
||||||
|
"defaultValue": "",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"label": "",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxFiles": 5,
|
||||||
|
"canSelectFile": true,
|
||||||
|
"canSelectImg": true,
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"renderTypeList": ["input", "reference"],
|
||||||
|
"selectedTypeIndex": 0,
|
||||||
|
"valueType": "string",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "smtpPass",
|
||||||
|
"label": "smtpPass",
|
||||||
|
"description": "邮箱密码或授权码",
|
||||||
|
"defaultValue": "",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"label": "",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxFiles": 5,
|
||||||
|
"canSelectFile": true,
|
||||||
|
"canSelectImg": true,
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"renderTypeList": ["input", "reference"],
|
||||||
|
"selectedTypeIndex": 0,
|
||||||
|
"valueType": "string",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "fromName",
|
||||||
|
"label": "fromName",
|
||||||
|
"description": "显示的发件人名称",
|
||||||
|
"defaultValue": "",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"label": "",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxFiles": 5,
|
||||||
|
"canSelectFile": true,
|
||||||
|
"canSelectImg": true,
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"renderTypeList": ["input", "reference"],
|
||||||
|
"selectedTypeIndex": 0,
|
||||||
|
"valueType": "string",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "to",
|
||||||
|
"label": "to",
|
||||||
|
"description": "请输入收件人邮箱,多个邮箱用逗号分隔",
|
||||||
|
"defaultValue": "",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"label": "",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxFiles": 5,
|
||||||
|
"canSelectFile": true,
|
||||||
|
"canSelectImg": true,
|
||||||
|
"required": true,
|
||||||
|
"toolDescription": "请输入收件人邮箱,多个邮箱用逗号分隔"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"renderTypeList": ["input", "reference"],
|
||||||
|
"selectedTypeIndex": 0,
|
||||||
|
"valueType": "string",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "subject",
|
||||||
|
"label": "subject",
|
||||||
|
"description": "请输入邮件主题",
|
||||||
|
"defaultValue": "",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"label": "",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxFiles": 5,
|
||||||
|
"canSelectFile": true,
|
||||||
|
"canSelectImg": true,
|
||||||
|
"required": true,
|
||||||
|
"toolDescription": "请输入邮件主题"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"renderTypeList": ["input", "reference"],
|
||||||
|
"selectedTypeIndex": 0,
|
||||||
|
"valueType": "string",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "content",
|
||||||
|
"label": "content",
|
||||||
|
"description": "请输入邮件内容,支持HTML格式",
|
||||||
|
"defaultValue": "",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"label": "",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxFiles": 5,
|
||||||
|
"canSelectFile": true,
|
||||||
|
"canSelectImg": true,
|
||||||
|
"required": true,
|
||||||
|
"toolDescription": "请输入邮件内容,支持HTML格式"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"renderTypeList": ["input", "reference"],
|
||||||
|
"selectedTypeIndex": 0,
|
||||||
|
"valueType": "string",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "cc",
|
||||||
|
"label": "cc",
|
||||||
|
"description": "请输入抄送邮箱,多个邮箱用逗号分隔",
|
||||||
|
"defaultValue": "",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"label": "",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxFiles": 5,
|
||||||
|
"canSelectFile": true,
|
||||||
|
"canSelectImg": true,
|
||||||
|
"required": false,
|
||||||
|
"toolDescription": "请输入抄送邮箱,多个邮箱用逗号分隔"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"renderTypeList": ["input", "reference"],
|
||||||
|
"selectedTypeIndex": 0,
|
||||||
|
"valueType": "string",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "bcc",
|
||||||
|
"label": "bcc",
|
||||||
|
"description": "请输入密送邮箱,多个邮箱用逗号分隔",
|
||||||
|
"defaultValue": "",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"label": "",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxFiles": 5,
|
||||||
|
"canSelectFile": true,
|
||||||
|
"canSelectImg": true,
|
||||||
|
"required": false,
|
||||||
|
"toolDescription": "请输入密送邮箱,多个邮箱用逗号分隔"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"renderTypeList": ["JSONEditor", "reference"],
|
||||||
|
"selectedTypeIndex": 0,
|
||||||
|
"valueType": "string",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "attachments",
|
||||||
|
"label": "attachments",
|
||||||
|
"description": "必须是json数组格式\n[{\"filename\":\"附件名\",\"path\":\"附件url\"}]",
|
||||||
|
"defaultValue": "",
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"label": "",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxFiles": 5,
|
||||||
|
"canSelectFile": true,
|
||||||
|
"canSelectImg": true,
|
||||||
|
"required": false,
|
||||||
|
"customInputConfig": {
|
||||||
|
"selectValueTypeList": ["arrayObject"]
|
||||||
|
},
|
||||||
|
"toolDescription": "必须是json数组格式\n[{\"filename\":\"附件名\",\"path\":\"附件url\"}]",
|
||||||
|
"maxLength": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"id": "smtpHost",
|
||||||
|
"valueType": "string",
|
||||||
|
"key": "smtpHost",
|
||||||
|
"label": "smtpHost",
|
||||||
|
"type": "hidden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "smtpPort",
|
||||||
|
"valueType": "string",
|
||||||
|
"key": "smtpPort",
|
||||||
|
"label": "smtpPort",
|
||||||
|
"type": "hidden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "SSL",
|
||||||
|
"valueType": "string",
|
||||||
|
"key": "SSL",
|
||||||
|
"label": "SSL",
|
||||||
|
"type": "hidden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "smtpUser",
|
||||||
|
"valueType": "string",
|
||||||
|
"key": "smtpUser",
|
||||||
|
"label": "smtpUser",
|
||||||
|
"type": "hidden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "smtpPass",
|
||||||
|
"valueType": "string",
|
||||||
|
"key": "smtpPass",
|
||||||
|
"label": "smtpPass",
|
||||||
|
"type": "hidden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "fromName",
|
||||||
|
"valueType": "string",
|
||||||
|
"key": "fromName",
|
||||||
|
"label": "fromName",
|
||||||
|
"type": "hidden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "to",
|
||||||
|
"valueType": "string",
|
||||||
|
"key": "to",
|
||||||
|
"label": "to",
|
||||||
|
"type": "hidden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "subject",
|
||||||
|
"valueType": "string",
|
||||||
|
"key": "subject",
|
||||||
|
"label": "subject",
|
||||||
|
"type": "hidden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "content",
|
||||||
|
"valueType": "string",
|
||||||
|
"key": "content",
|
||||||
|
"label": "content",
|
||||||
|
"type": "hidden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "cc",
|
||||||
|
"valueType": "string",
|
||||||
|
"key": "cc",
|
||||||
|
"label": "cc",
|
||||||
|
"type": "hidden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "bcc",
|
||||||
|
"valueType": "string",
|
||||||
|
"key": "bcc",
|
||||||
|
"label": "bcc",
|
||||||
|
"type": "hidden"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "attachments",
|
||||||
|
"valueType": "string",
|
||||||
|
"key": "attachments",
|
||||||
|
"label": "attachments",
|
||||||
|
"type": "hidden"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nodeId": "pluginOutput",
|
||||||
|
"name": "common:core.module.template.self_output",
|
||||||
|
"intro": "workflow:intro_custom_plugin_output",
|
||||||
|
"avatar": "core/workflow/template/pluginOutput",
|
||||||
|
"flowNodeType": "pluginOutput",
|
||||||
|
"showStatus": false,
|
||||||
|
"position": {
|
||||||
|
"x": 2135.4991928806685,
|
||||||
|
"y": -98.02524442647456
|
||||||
|
},
|
||||||
|
"version": "481",
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"renderTypeList": ["reference"],
|
||||||
|
"valueType": "string",
|
||||||
|
"canEdit": true,
|
||||||
|
"key": "发送结果",
|
||||||
|
"label": "发送结果",
|
||||||
|
"isToolOutput": true,
|
||||||
|
"description": "",
|
||||||
|
"required": true,
|
||||||
|
"value": ["uOX6ITvPWm9O", "httpRawResponse"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nodeId": "pluginConfig",
|
||||||
|
"name": "common:core.module.template.system_config",
|
||||||
|
"intro": "",
|
||||||
|
"avatar": "core/workflow/template/systemConfig",
|
||||||
|
"flowNodeType": "pluginConfig",
|
||||||
|
"position": {
|
||||||
|
"x": 184.66337662472682,
|
||||||
|
"y": -216.05298493910115
|
||||||
|
},
|
||||||
|
"version": "4811",
|
||||||
|
"inputs": [],
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nodeId": "uOX6ITvPWm9O",
|
||||||
|
"name": "HTTP 请求",
|
||||||
|
"intro": "可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)",
|
||||||
|
"avatar": "core/workflow/template/httpRequest",
|
||||||
|
"flowNodeType": "httpRequest468",
|
||||||
|
"showStatus": true,
|
||||||
|
"position": {
|
||||||
|
"x": 1340.0519095857342,
|
||||||
|
"y": -393.02524442647456
|
||||||
|
},
|
||||||
|
"version": "481",
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"key": "system_addInputParam",
|
||||||
|
"renderTypeList": ["addInputParam"],
|
||||||
|
"valueType": "dynamic",
|
||||||
|
"label": "",
|
||||||
|
"required": false,
|
||||||
|
"description": "common:core.module.input.description.HTTP Dynamic Input",
|
||||||
|
"customInputConfig": {
|
||||||
|
"selectValueTypeList": [
|
||||||
|
"string",
|
||||||
|
"number",
|
||||||
|
"boolean",
|
||||||
|
"object",
|
||||||
|
"arrayString",
|
||||||
|
"arrayNumber",
|
||||||
|
"arrayBoolean",
|
||||||
|
"arrayObject",
|
||||||
|
"arrayAny",
|
||||||
|
"any",
|
||||||
|
"chatHistory",
|
||||||
|
"datasetQuote",
|
||||||
|
"dynamic",
|
||||||
|
"selectDataset",
|
||||||
|
"selectApp"
|
||||||
|
],
|
||||||
|
"showDescription": false,
|
||||||
|
"showDefaultValue": true
|
||||||
|
},
|
||||||
|
"valueDesc": "",
|
||||||
|
"debugLabel": "",
|
||||||
|
"toolDescription": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpMethod",
|
||||||
|
"renderTypeList": ["custom"],
|
||||||
|
"valueType": "string",
|
||||||
|
"label": "",
|
||||||
|
"value": "POST",
|
||||||
|
"required": true,
|
||||||
|
"valueDesc": "",
|
||||||
|
"description": "",
|
||||||
|
"debugLabel": "",
|
||||||
|
"toolDescription": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpTimeout",
|
||||||
|
"renderTypeList": ["custom"],
|
||||||
|
"valueType": "number",
|
||||||
|
"label": "",
|
||||||
|
"value": 30,
|
||||||
|
"min": 5,
|
||||||
|
"max": 600,
|
||||||
|
"required": true,
|
||||||
|
"valueDesc": "",
|
||||||
|
"description": "",
|
||||||
|
"debugLabel": "",
|
||||||
|
"toolDescription": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpReqUrl",
|
||||||
|
"renderTypeList": ["hidden"],
|
||||||
|
"valueType": "string",
|
||||||
|
"label": "",
|
||||||
|
"description": "common:core.module.input.description.Http Request Url",
|
||||||
|
"placeholder": "https://api.ai.com/getInventory",
|
||||||
|
"required": false,
|
||||||
|
"value": "smtpEmail",
|
||||||
|
"valueDesc": "",
|
||||||
|
"debugLabel": "",
|
||||||
|
"toolDescription": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpHeader",
|
||||||
|
"renderTypeList": ["custom"],
|
||||||
|
"valueType": "any",
|
||||||
|
"value": [],
|
||||||
|
"label": "",
|
||||||
|
"description": "common:core.module.input.description.Http Request Header",
|
||||||
|
"placeholder": "common:core.module.input.description.Http Request Header",
|
||||||
|
"required": false,
|
||||||
|
"valueDesc": "",
|
||||||
|
"debugLabel": "",
|
||||||
|
"toolDescription": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpParams",
|
||||||
|
"renderTypeList": ["hidden"],
|
||||||
|
"valueType": "any",
|
||||||
|
"value": [],
|
||||||
|
"label": "",
|
||||||
|
"required": false,
|
||||||
|
"valueDesc": "",
|
||||||
|
"description": "",
|
||||||
|
"debugLabel": "",
|
||||||
|
"toolDescription": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpJsonBody",
|
||||||
|
"renderTypeList": ["hidden"],
|
||||||
|
"valueType": "any",
|
||||||
|
"value": "{\n\"smtpHost\": \"{{$pluginInput.smtpHost$}}\",\n\"smtpPort\": \"{{$pluginInput.smtpPort$}}\",\n\"SSL\": {{$pluginInput.SSL$}},\n\"smtpUser\": \"{{$pluginInput.smtpUser$}}\",\n\"smtpPass\": \"{{$pluginInput.smtpPass$}}\",\n\"fromName\": \"{{$pluginInput.fromName$}}\",\n\"to\": \"{{$pluginInput.to$}}\",\n\"subject\": \"{{$pluginInput.subject$}}\",\n\"content\": \"{{$pluginInput.content$}}\",\n\"cc\": \"{{$pluginInput.cc$}}\",\n\"bcc\": \"{{$pluginInput.bcc$}}\",\n\"attachments\":'{{$pluginInput.attachments$}}'\n}",
|
||||||
|
"label": "",
|
||||||
|
"required": false,
|
||||||
|
"valueDesc": "",
|
||||||
|
"description": "",
|
||||||
|
"debugLabel": "",
|
||||||
|
"toolDescription": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpFormBody",
|
||||||
|
"renderTypeList": ["hidden"],
|
||||||
|
"valueType": "any",
|
||||||
|
"value": [],
|
||||||
|
"label": "",
|
||||||
|
"required": false,
|
||||||
|
"valueDesc": "",
|
||||||
|
"description": "",
|
||||||
|
"debugLabel": "",
|
||||||
|
"toolDescription": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "system_httpContentType",
|
||||||
|
"renderTypeList": ["hidden"],
|
||||||
|
"valueType": "string",
|
||||||
|
"value": "json",
|
||||||
|
"label": "",
|
||||||
|
"required": false,
|
||||||
|
"debugLabel": "",
|
||||||
|
"toolDescription": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"id": "error",
|
||||||
|
"key": "error",
|
||||||
|
"label": "workflow:request_error",
|
||||||
|
"description": "HTTP请求错误信息,成功时返回空",
|
||||||
|
"valueType": "object",
|
||||||
|
"type": "static"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "httpRawResponse",
|
||||||
|
"key": "httpRawResponse",
|
||||||
|
"required": true,
|
||||||
|
"label": "workflow:raw_response",
|
||||||
|
"description": "HTTP请求的原始响应。只能接受字符串或JSON类型响应数据。",
|
||||||
|
"valueType": "any",
|
||||||
|
"type": "static"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "system_addOutputParam",
|
||||||
|
"key": "system_addOutputParam",
|
||||||
|
"type": "dynamic",
|
||||||
|
"valueType": "dynamic",
|
||||||
|
"label": "输出字段提取",
|
||||||
|
"customFieldConfig": {
|
||||||
|
"selectValueTypeList": [
|
||||||
|
"string",
|
||||||
|
"number",
|
||||||
|
"boolean",
|
||||||
|
"object",
|
||||||
|
"arrayString",
|
||||||
|
"arrayNumber",
|
||||||
|
"arrayBoolean",
|
||||||
|
"arrayObject",
|
||||||
|
"arrayAny",
|
||||||
|
"any",
|
||||||
|
"chatHistory",
|
||||||
|
"datasetQuote",
|
||||||
|
"dynamic",
|
||||||
|
"selectApp",
|
||||||
|
"selectDataset"
|
||||||
|
],
|
||||||
|
"showDescription": false,
|
||||||
|
"showDefaultValue": false
|
||||||
|
},
|
||||||
|
"description": "可以通过 JSONPath 语法来提取响应值中的指定字段",
|
||||||
|
"valueDesc": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"edges": [
|
||||||
|
{
|
||||||
|
"source": "uOX6ITvPWm9O",
|
||||||
|
"target": "pluginOutput",
|
||||||
|
"sourceHandle": "uOX6ITvPWm9O-source-right",
|
||||||
|
"targetHandle": "pluginOutput-target-left"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "pluginInput",
|
||||||
|
"target": "uOX6ITvPWm9O",
|
||||||
|
"sourceHandle": "pluginInput-source-right",
|
||||||
|
"targetHandle": "uOX6ITvPWm9O-target-left"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"chatConfig": {
|
||||||
|
"welcomeText": "",
|
||||||
|
"variables": [],
|
||||||
|
"questionGuide": {
|
||||||
|
"open": false,
|
||||||
|
"model": "gpt-4o-mini",
|
||||||
|
"customPrompt": ""
|
||||||
|
},
|
||||||
|
"ttsConfig": {
|
||||||
|
"type": "web"
|
||||||
|
},
|
||||||
|
"whisperConfig": {
|
||||||
|
"open": false,
|
||||||
|
"autoSend": false,
|
||||||
|
"autoTTSResponse": false
|
||||||
|
},
|
||||||
|
"chatInputGuide": {
|
||||||
|
"open": false,
|
||||||
|
"textList": [],
|
||||||
|
"customUrl": ""
|
||||||
|
},
|
||||||
|
"instruction": "通过SMTP协议发送电子邮件",
|
||||||
|
"autoExecute": {
|
||||||
|
"open": false,
|
||||||
|
"defaultPrompt": ""
|
||||||
|
},
|
||||||
|
"_id": "67ad649ea4b6b8eefa9d3d0d"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import { connectionMongo, getMongoModel } from '../../mongo';
|
import { getMongoModel, Schema } from '../../mongo';
|
||||||
const { Schema } = connectionMongo;
|
|
||||||
import { RawTextBufferSchemaType } from './type';
|
import { RawTextBufferSchemaType } from './type';
|
||||||
|
|
||||||
export const collectionName = 'buffer_rawtexts';
|
export const collectionName = 'buffer_rawtexts';
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { connectionMongo, getMongoModel, type Model } from '../../../common/mongo';
|
import { Schema, getMongoModel } from '../../../common/mongo';
|
||||||
const { Schema, model, models } = connectionMongo;
|
|
||||||
import { TTSBufferSchemaType } from './type.d';
|
import { TTSBufferSchemaType } from './type.d';
|
||||||
|
|
||||||
export const collectionName = 'buffer_tts';
|
export const collectionName = 'buffer_tts';
|
||||||
|
|||||||
74
packages/service/common/bullmq/index.ts
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import { ConnectionOptions, Processor, Queue, QueueOptions, Worker, WorkerOptions } from 'bullmq';
|
||||||
|
import { addLog } from '../system/log';
|
||||||
|
import { newQueueRedisConnection, newWorkerRedisConnection } from '../redis';
|
||||||
|
|
||||||
|
const defaultWorkerOpts: Omit<ConnectionOptions, 'connection'> = {
|
||||||
|
removeOnComplete: {
|
||||||
|
count: 0 // Delete jobs immediately on completion
|
||||||
|
},
|
||||||
|
removeOnFail: {
|
||||||
|
count: 0 // Delete jobs immediately on failure
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export enum QueueNames {
|
||||||
|
websiteSync = 'websiteSync'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const queues = (() => {
|
||||||
|
if (!global.queues) {
|
||||||
|
global.queues = new Map<QueueNames, Queue>();
|
||||||
|
}
|
||||||
|
return global.queues;
|
||||||
|
})();
|
||||||
|
export const workers = (() => {
|
||||||
|
if (!global.workers) {
|
||||||
|
global.workers = new Map<QueueNames, Worker>();
|
||||||
|
}
|
||||||
|
return global.workers;
|
||||||
|
})();
|
||||||
|
|
||||||
|
export function getQueue<DataType, ReturnType = void>(
|
||||||
|
name: QueueNames,
|
||||||
|
opts?: Omit<QueueOptions, 'connection'>
|
||||||
|
): Queue<DataType, ReturnType> {
|
||||||
|
// check if global.queues has the queue
|
||||||
|
const queue = queues.get(name);
|
||||||
|
if (queue) {
|
||||||
|
return queue as Queue<DataType, ReturnType>;
|
||||||
|
}
|
||||||
|
const newQueue = new Queue<DataType, ReturnType>(name.toString(), {
|
||||||
|
connection: newQueueRedisConnection(),
|
||||||
|
...opts
|
||||||
|
});
|
||||||
|
|
||||||
|
// default error handler, to avoid unhandled exceptions
|
||||||
|
newQueue.on('error', (error) => {
|
||||||
|
addLog.error(`MQ Queue [${name}]: ${error.message}`, error);
|
||||||
|
});
|
||||||
|
queues.set(name, newQueue);
|
||||||
|
return newQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getWorker<DataType, ReturnType = void>(
|
||||||
|
name: QueueNames,
|
||||||
|
processor: Processor<DataType, ReturnType>,
|
||||||
|
opts?: Omit<WorkerOptions, 'connection'>
|
||||||
|
): Worker<DataType, ReturnType> {
|
||||||
|
const worker = workers.get(name);
|
||||||
|
if (worker) {
|
||||||
|
return worker as Worker<DataType, ReturnType>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newWorker = new Worker<DataType, ReturnType>(name.toString(), processor, {
|
||||||
|
connection: newWorkerRedisConnection(),
|
||||||
|
...defaultWorkerOpts,
|
||||||
|
...opts
|
||||||
|
});
|
||||||
|
// default error handler, to avoid unhandled exceptions
|
||||||
|
newWorker.on('error', (error) => {
|
||||||
|
addLog.error(`MQ Worker [${name}]: ${error.message}`, error);
|
||||||
|
});
|
||||||
|
workers.set(name, newWorker);
|
||||||
|
return newWorker;
|
||||||
|
}
|
||||||
7
packages/service/common/bullmq/type.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { Queue, Worker } from 'bullmq';
|
||||||
|
import { QueueNames } from './index';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
var queues: Map<QueueNames, Queue> | undefined;
|
||||||
|
var workers: Map<QueueNames, Worker> | undefined;
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import { connectionMongo, getMongoModel, type Model } from '../../mongo';
|
import { Schema, getMongoModel } from '../../mongo';
|
||||||
const { Schema } = connectionMongo;
|
|
||||||
|
|
||||||
const DatasetFileSchema = new Schema({});
|
const DatasetFileSchema = new Schema({});
|
||||||
const ChatFileSchema = new Schema({});
|
const ChatFileSchema = new Schema({});
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { TeamCollectionName } from '@fastgpt/global/support/user/team/constant';
|
import { TeamCollectionName } from '@fastgpt/global/support/user/team/constant';
|
||||||
import { connectionMongo, getMongoModel } from '../../mongo';
|
import { Schema, getMongoModel } from '../../mongo';
|
||||||
import { MongoImageSchemaType } from '@fastgpt/global/common/file/image/type.d';
|
import { MongoImageSchemaType } from '@fastgpt/global/common/file/image/type.d';
|
||||||
const { Schema } = connectionMongo;
|
|
||||||
|
|
||||||
const ImageSchema = new Schema({
|
const ImageSchema = new Schema({
|
||||||
teamId: {
|
teamId: {
|
||||||
|
|||||||
@@ -1,17 +1,26 @@
|
|||||||
import { addLog } from '../../common/system/log';
|
import { addLog } from '../../common/system/log';
|
||||||
import mongoose, { Model } from 'mongoose';
|
import mongoose, { Model, Mongoose } from 'mongoose';
|
||||||
|
|
||||||
export default mongoose;
|
export default mongoose;
|
||||||
export * from 'mongoose';
|
export * from 'mongoose';
|
||||||
|
|
||||||
|
export const MONGO_URL = process.env.MONGODB_URI as string;
|
||||||
|
export const MONGO_LOG_URL = (process.env.MONGODB_LOG_URI ?? process.env.MONGODB_URI) as string;
|
||||||
|
|
||||||
export const connectionMongo = (() => {
|
export const connectionMongo = (() => {
|
||||||
if (!global.mongodb) {
|
if (!global.mongodb) {
|
||||||
global.mongodb = mongoose;
|
global.mongodb = new Mongoose();
|
||||||
}
|
}
|
||||||
|
|
||||||
return global.mongodb;
|
return global.mongodb;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
export const connectionLogMongo = (() => {
|
||||||
|
if (!global.mongodbLog) {
|
||||||
|
global.mongodbLog = new Mongoose();
|
||||||
|
}
|
||||||
|
return global.mongodbLog;
|
||||||
|
})();
|
||||||
|
|
||||||
const addCommonMiddleware = (schema: mongoose.Schema) => {
|
const addCommonMiddleware = (schema: mongoose.Schema) => {
|
||||||
const operations = [
|
const operations = [
|
||||||
/^find/,
|
/^find/,
|
||||||
@@ -71,6 +80,19 @@ export const getMongoModel = <T>(name: string, schema: mongoose.Schema) => {
|
|||||||
return model;
|
return model;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getMongoLogModel = <T>(name: string, schema: mongoose.Schema) => {
|
||||||
|
if (connectionLogMongo.models[name]) return connectionLogMongo.models[name] as Model<T>;
|
||||||
|
console.log('Load model======', name);
|
||||||
|
addCommonMiddleware(schema);
|
||||||
|
|
||||||
|
const model = connectionLogMongo.model<T>(name, schema);
|
||||||
|
|
||||||
|
// Sync index
|
||||||
|
syncMongoIndex(model);
|
||||||
|
|
||||||
|
return model;
|
||||||
|
};
|
||||||
|
|
||||||
const syncMongoIndex = async (model: Model<any>) => {
|
const syncMongoIndex = async (model: Model<any>) => {
|
||||||
if (process.env.SYNC_INDEX !== '0' && process.env.NODE_ENV !== 'test') {
|
if (process.env.SYNC_INDEX !== '0' && process.env.NODE_ENV !== 'test') {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { delay } from '@fastgpt/global/common/system/utils';
|
import { delay } from '@fastgpt/global/common/system/utils';
|
||||||
import { addLog } from '../system/log';
|
import { addLog } from '../system/log';
|
||||||
import { connectionMongo } from './index';
|
|
||||||
import type { Mongoose } from 'mongoose';
|
import type { Mongoose } from 'mongoose';
|
||||||
|
|
||||||
const maxConnecting = Math.max(30, Number(process.env.DB_MAX_LINK || 20));
|
const maxConnecting = Math.max(30, Number(process.env.DB_MAX_LINK || 20));
|
||||||
@@ -8,41 +7,41 @@ const maxConnecting = Math.max(30, Number(process.env.DB_MAX_LINK || 20));
|
|||||||
/**
|
/**
|
||||||
* connect MongoDB and init data
|
* connect MongoDB and init data
|
||||||
*/
|
*/
|
||||||
export async function connectMongo(): Promise<Mongoose> {
|
export async function connectMongo(db: Mongoose, url: string): Promise<Mongoose> {
|
||||||
/* Connecting, connected will return */
|
/* Connecting, connected will return */
|
||||||
if (connectionMongo.connection.readyState !== 0) {
|
if (db.connection.readyState !== 0) {
|
||||||
return connectionMongo;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('mongo start connect');
|
console.log('MongoDB start connect');
|
||||||
try {
|
try {
|
||||||
// Remove existing listeners to prevent duplicates
|
// Remove existing listeners to prevent duplicates
|
||||||
connectionMongo.connection.removeAllListeners('error');
|
db.connection.removeAllListeners('error');
|
||||||
connectionMongo.connection.removeAllListeners('disconnected');
|
db.connection.removeAllListeners('disconnected');
|
||||||
connectionMongo.set('strictQuery', 'throw');
|
db.set('strictQuery', 'throw');
|
||||||
|
|
||||||
connectionMongo.connection.on('error', async (error) => {
|
db.connection.on('error', async (error) => {
|
||||||
console.log('mongo error', error);
|
console.log('mongo error', error);
|
||||||
try {
|
try {
|
||||||
if (connectionMongo.connection.readyState !== 0) {
|
if (db.connection.readyState !== 0) {
|
||||||
await connectionMongo.disconnect();
|
await db.disconnect();
|
||||||
await delay(1000);
|
await delay(1000);
|
||||||
await connectMongo();
|
await connectMongo(db, url);
|
||||||
}
|
}
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
});
|
});
|
||||||
connectionMongo.connection.on('disconnected', async () => {
|
db.connection.on('disconnected', async () => {
|
||||||
console.log('mongo disconnected');
|
console.log('mongo disconnected');
|
||||||
try {
|
try {
|
||||||
if (connectionMongo.connection.readyState !== 0) {
|
if (db.connection.readyState !== 0) {
|
||||||
await connectionMongo.disconnect();
|
await db.disconnect();
|
||||||
await delay(1000);
|
await delay(1000);
|
||||||
await connectMongo();
|
await connectMongo(db, url);
|
||||||
}
|
}
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
});
|
});
|
||||||
|
|
||||||
await connectionMongo.connect(process.env.MONGODB_URI as string, {
|
const options = {
|
||||||
bufferCommands: true,
|
bufferCommands: true,
|
||||||
maxConnecting: maxConnecting,
|
maxConnecting: maxConnecting,
|
||||||
maxPoolSize: maxConnecting,
|
maxPoolSize: maxConnecting,
|
||||||
@@ -53,18 +52,18 @@ export async function connectMongo(): Promise<Mongoose> {
|
|||||||
maxIdleTimeMS: 300000,
|
maxIdleTimeMS: 300000,
|
||||||
retryWrites: true,
|
retryWrites: true,
|
||||||
retryReads: true
|
retryReads: true
|
||||||
|
};
|
||||||
|
|
||||||
// readPreference: 'secondaryPreferred',
|
db.connect(url, options);
|
||||||
// readConcern: { level: 'local' },
|
|
||||||
// writeConcern: { w: 'majority', j: true }
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('mongo connected');
|
console.log('mongo connected');
|
||||||
return connectionMongo;
|
return db;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
addLog.error('mongo connect error', error);
|
addLog.error('Mongo connect error', error);
|
||||||
await connectionMongo.disconnect();
|
|
||||||
|
await db.disconnect();
|
||||||
|
|
||||||
await delay(1000);
|
await delay(1000);
|
||||||
return connectMongo();
|
return connectMongo(db, url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
packages/service/common/mongo/type.d.ts
vendored
@@ -3,4 +3,5 @@ import type { Logger } from 'winston';
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
var mongodb: Mongoose | undefined;
|
var mongodb: Mongoose | undefined;
|
||||||
|
var mongodbLog: Mongoose | undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
38
packages/service/common/redis/cache.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { getGlobalRedisCacheConnection } from './index';
|
||||||
|
import { addLog } from '../system/log';
|
||||||
|
import { retryFn } from '@fastgpt/global/common/system/utils';
|
||||||
|
|
||||||
|
export enum CacheKeyEnum {
|
||||||
|
team_vector_count = 'team_vector_count'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const setRedisCache = async (
|
||||||
|
key: string,
|
||||||
|
data: string | Buffer | number,
|
||||||
|
expireSeconds?: number
|
||||||
|
) => {
|
||||||
|
return await retryFn(async () => {
|
||||||
|
try {
|
||||||
|
const redis = getGlobalRedisCacheConnection();
|
||||||
|
|
||||||
|
if (expireSeconds) {
|
||||||
|
await redis.set(key, data, 'EX', expireSeconds);
|
||||||
|
} else {
|
||||||
|
await redis.set(key, data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
addLog.error('Set cache error:', error);
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getRedisCache = async (key: string) => {
|
||||||
|
const redis = getGlobalRedisCacheConnection();
|
||||||
|
return await retryFn(() => redis.get(key));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const delRedisCache = async (key: string) => {
|
||||||
|
const redis = getGlobalRedisCacheConnection();
|
||||||
|
await retryFn(() => redis.del(key));
|
||||||
|
};
|
||||||
43
packages/service/common/redis/index.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { addLog } from '../system/log';
|
||||||
|
import Redis from 'ioredis';
|
||||||
|
|
||||||
|
const REDIS_URL = process.env.REDIS_URL ?? 'redis://localhost:6379';
|
||||||
|
|
||||||
|
export const newQueueRedisConnection = () => {
|
||||||
|
const redis = new Redis(REDIS_URL);
|
||||||
|
redis.on('connect', () => {
|
||||||
|
console.log('Redis connected');
|
||||||
|
});
|
||||||
|
redis.on('error', (error) => {
|
||||||
|
console.error('Redis connection error', error);
|
||||||
|
});
|
||||||
|
return redis;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const newWorkerRedisConnection = () => {
|
||||||
|
const redis = new Redis(REDIS_URL, {
|
||||||
|
maxRetriesPerRequest: null
|
||||||
|
});
|
||||||
|
redis.on('connect', () => {
|
||||||
|
console.log('Redis connected');
|
||||||
|
});
|
||||||
|
redis.on('error', (error) => {
|
||||||
|
console.error('Redis connection error', error);
|
||||||
|
});
|
||||||
|
return redis;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getGlobalRedisCacheConnection = () => {
|
||||||
|
if (global.redisCache) return global.redisCache;
|
||||||
|
|
||||||
|
global.redisCache = new Redis(REDIS_URL, { keyPrefix: 'fastgpt:cache:' });
|
||||||
|
|
||||||
|
global.redisCache.on('connect', () => {
|
||||||
|
addLog.info('Redis connected');
|
||||||
|
});
|
||||||
|
global.redisCache.on('error', (error) => {
|
||||||
|
addLog.error('Redis connection error', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
return global.redisCache;
|
||||||
|
};
|
||||||
5
packages/service/common/redis/type.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import Redis from 'ioredis';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
var redisCache: Redis | null;
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { getMongoModel, Schema } from '../../../common/mongo';
|
import { getMongoLogModel as getMongoModel, Schema } from '../../../common/mongo';
|
||||||
import { SystemLogType } from './type';
|
import { SystemLogType } from './type';
|
||||||
import { LogLevelEnum } from './constant';
|
import { LogLevelEnum } from './constant';
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export enum TimerIdEnum {
|
export enum TimerIdEnum {
|
||||||
checkInValidDatasetFiles = 'checkInValidDatasetFiles',
|
checkExpiredFiles = 'checkExpiredFiles',
|
||||||
checkInvalidDatasetData = 'checkInvalidDatasetData',
|
checkInvalidDatasetData = 'checkInvalidDatasetData',
|
||||||
checkInvalidVector = 'checkInvalidVector',
|
checkInvalidVector = 'checkInvalidVector',
|
||||||
clearExpiredSubPlan = 'clearExpiredSubPlan',
|
clearExpiredSubPlan = 'clearExpiredSubPlan',
|
||||||
|
|||||||
@@ -2,5 +2,6 @@ export const DatasetVectorDbName = 'fastgpt';
|
|||||||
export const DatasetVectorTableName = 'modeldata';
|
export const DatasetVectorTableName = 'modeldata';
|
||||||
|
|
||||||
export const PG_ADDRESS = process.env.PG_URL;
|
export const PG_ADDRESS = process.env.PG_URL;
|
||||||
|
export const OCEANBASE_ADDRESS = process.env.OCEANBASE_URL;
|
||||||
export const MILVUS_ADDRESS = process.env.MILVUS_ADDRESS;
|
export const MILVUS_ADDRESS = process.env.MILVUS_ADDRESS;
|
||||||
export const MILVUS_TOKEN = process.env.MILVUS_TOKEN;
|
export const MILVUS_TOKEN = process.env.MILVUS_TOKEN;
|
||||||
|
|||||||
@@ -1,25 +1,43 @@
|
|||||||
/* vector crud */
|
/* vector crud */
|
||||||
import { PgVectorCtrl } from './pg/class';
|
import { PgVectorCtrl } from './pg/class';
|
||||||
|
import { ObVectorCtrl } from './oceanbase/class';
|
||||||
import { getVectorsByText } from '../../core/ai/embedding';
|
import { getVectorsByText } from '../../core/ai/embedding';
|
||||||
import { InsertVectorProps } from './controller.d';
|
import { DelDatasetVectorCtrlProps, InsertVectorProps } from './controller.d';
|
||||||
import { EmbeddingModelItemType } from '@fastgpt/global/core/ai/model.d';
|
import { EmbeddingModelItemType } from '@fastgpt/global/core/ai/model.d';
|
||||||
import { MILVUS_ADDRESS, PG_ADDRESS } from './constants';
|
import { MILVUS_ADDRESS, PG_ADDRESS, OCEANBASE_ADDRESS } from './constants';
|
||||||
import { MilvusCtrl } from './milvus/class';
|
import { MilvusCtrl } from './milvus/class';
|
||||||
|
import { setRedisCache, getRedisCache, delRedisCache, CacheKeyEnum } from '../redis/cache';
|
||||||
|
|
||||||
const getVectorObj = () => {
|
const getVectorObj = () => {
|
||||||
if (PG_ADDRESS) return new PgVectorCtrl();
|
if (PG_ADDRESS) return new PgVectorCtrl();
|
||||||
|
if (OCEANBASE_ADDRESS) return new ObVectorCtrl();
|
||||||
if (MILVUS_ADDRESS) return new MilvusCtrl();
|
if (MILVUS_ADDRESS) return new MilvusCtrl();
|
||||||
|
|
||||||
return new PgVectorCtrl();
|
return new PgVectorCtrl();
|
||||||
};
|
};
|
||||||
|
const getChcheKey = (teamId: string) => `${CacheKeyEnum.team_vector_count}:${teamId}`;
|
||||||
|
|
||||||
const Vector = getVectorObj();
|
const Vector = getVectorObj();
|
||||||
|
|
||||||
export const initVectorStore = Vector.init;
|
export const initVectorStore = Vector.init;
|
||||||
export const deleteDatasetDataVector = Vector.delete;
|
|
||||||
export const recallFromVectorStore = Vector.embRecall;
|
export const recallFromVectorStore = Vector.embRecall;
|
||||||
export const getVectorDataByTime = Vector.getVectorDataByTime;
|
export const getVectorDataByTime = Vector.getVectorDataByTime;
|
||||||
export const getVectorCountByTeamId = Vector.getVectorCountByTeamId;
|
|
||||||
|
export const getVectorCountByTeamId = async (teamId: string) => {
|
||||||
|
const key = getChcheKey(teamId);
|
||||||
|
|
||||||
|
const countStr = await getRedisCache(key);
|
||||||
|
if (countStr) {
|
||||||
|
return Number(countStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
const count = await Vector.getVectorCountByTeamId(teamId);
|
||||||
|
|
||||||
|
await setRedisCache(key, count, 30 * 60);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
};
|
||||||
|
|
||||||
export const getVectorCountByDatasetId = Vector.getVectorCountByDatasetId;
|
export const getVectorCountByDatasetId = Vector.getVectorCountByDatasetId;
|
||||||
export const getVectorCountByCollectionId = Vector.getVectorCountByCollectionId;
|
export const getVectorCountByCollectionId = Vector.getVectorCountByCollectionId;
|
||||||
|
|
||||||
@@ -41,8 +59,16 @@ export const insertDatasetDataVector = async ({
|
|||||||
vector: vectors[0]
|
vector: vectors[0]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
delRedisCache(getChcheKey(props.teamId));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tokens,
|
tokens,
|
||||||
insertId
|
insertId
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const deleteDatasetDataVector = async (props: DelDatasetVectorCtrlProps) => {
|
||||||
|
const result = await Vector.delete(props);
|
||||||
|
delRedisCache(getChcheKey(props.teamId));
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|||||||