v4.6-3 (#471)
This commit is contained in:
parent
592e1a93a2
commit
bfd8be5df0
52
.github/workflows/fastgpt-image-personal.yml
vendored
Normal file
52
.github/workflows/fastgpt-image-personal.yml
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
name: Build FastGPT images in Personal warehouse
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- 'projects/app/**'
|
||||||
|
- 'packages/**'
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
jobs:
|
||||||
|
build-fastgpt-images:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
if: github.repository != 'labring/FastGPT'
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
with:
|
||||||
|
driver-opts: network=host
|
||||||
|
- name: Cache Docker layers
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: /tmp/.buildx-cache
|
||||||
|
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-buildx-
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GH_PAT }}
|
||||||
|
- name: Set DOCKER_REPO_TAGGED based on branch or tag
|
||||||
|
run: |
|
||||||
|
echo "DOCKER_REPO_TAGGED=ghcr.io/${{ github.repository_owner }}/fastgpt:latest" >> $GITHUB_ENV
|
||||||
|
- name: Build and publish image for main branch or tag push event
|
||||||
|
env:
|
||||||
|
DOCKER_REPO_TAGGED: ${{ env.DOCKER_REPO_TAGGED }}
|
||||||
|
run: |
|
||||||
|
docker buildx build \
|
||||||
|
--build-arg name=app \
|
||||||
|
--label "org.opencontainers.image.source=https://github.com/${{ github.repository_owner }}/FastGPT" \
|
||||||
|
--label "org.opencontainers.image.description=fastgpt image" \
|
||||||
|
--push \
|
||||||
|
--cache-from=type=local,src=/tmp/.buildx-cache \
|
||||||
|
--cache-to=type=local,dest=/tmp/.buildx-cache \
|
||||||
|
-t ${DOCKER_REPO_TAGGED} \
|
||||||
|
-f Dockerfile \
|
||||||
|
.
|
||||||
5
.github/workflows/fastgpt-image.yml
vendored
5
.github/workflows/fastgpt-image.yml
vendored
@ -5,8 +5,6 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- 'projects/app/**'
|
- 'projects/app/**'
|
||||||
- 'packages/**'
|
- 'packages/**'
|
||||||
branches:
|
|
||||||
- 'main'
|
|
||||||
tags:
|
tags:
|
||||||
- 'v*.*.*'
|
- 'v*.*.*'
|
||||||
jobs:
|
jobs:
|
||||||
@ -53,9 +51,8 @@ jobs:
|
|||||||
docker buildx build \
|
docker buildx build \
|
||||||
--build-arg name=app \
|
--build-arg name=app \
|
||||||
--platform linux/amd64,linux/arm64 \
|
--platform linux/amd64,linux/arm64 \
|
||||||
--label "org.opencontainers.image.source= https://github.com/ ${{ github.repository_owner }}/FastGPT" \
|
--label "org.opencontainers.image.source=https://github.com/${{ github.repository_owner }}/FastGPT" \
|
||||||
--label "org.opencontainers.image.description=fastgpt image" \
|
--label "org.opencontainers.image.description=fastgpt image" \
|
||||||
--label "org.opencontainers.image.licenses=Apache" \
|
|
||||||
--push \
|
--push \
|
||||||
--cache-from=type=local,src=/tmp/.buildx-cache \
|
--cache-from=type=local,src=/tmp/.buildx-cache \
|
||||||
--cache-to=type=local,dest=/tmp/.buildx-cache \
|
--cache-to=type=local,dest=/tmp/.buildx-cache \
|
||||||
|
|||||||
3
.github/workflows/preview-image.yml
vendored
3
.github/workflows/preview-image.yml
vendored
@ -24,7 +24,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
driver-opts: network=host
|
driver-opts: network=host
|
||||||
- name: Cache Docker layers
|
- name: Cache Docker layers
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: /tmp/.buildx-cache
|
path: /tmp/.buildx-cache
|
||||||
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
||||||
@ -48,6 +48,7 @@ jobs:
|
|||||||
--label "org.opencontainers.image.source= https://github.com/ ${{ github.repository_owner }}/FastGPT" \
|
--label "org.opencontainers.image.source= https://github.com/ ${{ github.repository_owner }}/FastGPT" \
|
||||||
--label "org.opencontainers.image.description=fastgpt-pr image" \
|
--label "org.opencontainers.image.description=fastgpt-pr image" \
|
||||||
--label "org.opencontainers.image.licenses=Apache" \
|
--label "org.opencontainers.image.licenses=Apache" \
|
||||||
|
--push \
|
||||||
--cache-from=type=local,src=/tmp/.buildx-cache \
|
--cache-from=type=local,src=/tmp/.buildx-cache \
|
||||||
--cache-to=type=local,dest=/tmp/.buildx-cache \
|
--cache-to=type=local,dest=/tmp/.buildx-cache \
|
||||||
-t ${DOCKER_REPO_TAGGED} \
|
-t ${DOCKER_REPO_TAGGED} \
|
||||||
|
|||||||
@ -7,20 +7,20 @@ toc: true
|
|||||||
weight: 836
|
weight: 836
|
||||||
---
|
---
|
||||||
|
|
||||||
未正式发布。
|
# V4.6 版本加入了简单的团队功能,可以邀请其他用户进来管理资源。该版本升级后无法执行旧的升级脚本,且无法回退。
|
||||||
|
|
||||||
V4.6 版本加入了简单的团队功能,可以邀请其他用户进来管理资源。该版本升级后无法执行旧的升级脚本,且无法回退。
|
# 1. 更新镜像并变更配置文件
|
||||||
|
|
||||||
## 1. 更新镜像并变更配置文件
|
更新镜像至 latest 或者 v4.6 版本。商业版镜像更新至 V0.2.1
|
||||||
|
|
||||||
更新镜像至 latest 或者 v4.6 版本。商业版镜像更新至 V0.2.
|
|
||||||
|
|
||||||
最新配置可参考: [V46版本最新 config.json](/docs/development/configuration),商业镜像配置文件也更新,参考最新的飞书文档。
|
最新配置可参考: [V46版本最新 config.json](/docs/development/configuration),商业镜像配置文件也更新,参考最新的飞书文档。
|
||||||
|
|
||||||
|
|
||||||
## 2. 执行初始化 API
|
# 2. 执行初始化 API
|
||||||
|
|
||||||
发起 1 个 HTTP 请求({{rootkey}} 替换成环境变量里的`rootkey`,{{host}}替换成自己域名)
|
发起 2 个 HTTP 请求({{rootkey}} 替换成环境变量里的`rootkey`,{{host}}替换成自己域名)
|
||||||
|
|
||||||
|
**该初始化接口可能速度很慢,返回超时不用管,注意看日志即可,需要注意的是,需确保initv46成功后,在执行initv46-2**
|
||||||
|
|
||||||
1. https://xxxxx/api/admin/initv46
|
1. https://xxxxx/api/admin/initv46
|
||||||
|
|
||||||
@ -30,16 +30,25 @@ curl --location --request POST 'https://{{host}}/api/admin/initv46' \
|
|||||||
--header 'Content-Type: application/json'
|
--header 'Content-Type: application/json'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
2. https://xxxxx/api/admin/initv46-2
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl --location --request POST 'https://{{host}}/api/admin/initv46-2' \
|
||||||
|
--header 'rootkey: {{rootkey}}' \
|
||||||
|
--header 'Content-Type: application/json'
|
||||||
|
```
|
||||||
|
|
||||||
初始化内容:
|
初始化内容:
|
||||||
1. 创建默认团队
|
1. 创建默认团队
|
||||||
2. 初始化 Mongo 所有资源的团队字段
|
2. 初始化 Mongo 所有资源的团队字段
|
||||||
3. 初始化 Pg 的字段
|
3. 初始化 Pg 的字段
|
||||||
|
4. 初始化 Mongo Data
|
||||||
**该初始化接口可能速度很慢,返回超时不用管,注意看日志即可**
|
|
||||||
|
|
||||||
|
|
||||||
## 功能介绍
|
# V4.6功能介绍
|
||||||
|
|
||||||
### Fast GPT V4.6
|
|
||||||
|
|
||||||
1. 新增 - 团队空间
|
1. 新增 - 团队空间
|
||||||
|
2. 新增 - 多路向量(多个向量映射一组数据)
|
||||||
|
3. 新增 - tts语音
|
||||||
|
4. 线上环境新增 - ReRank向量召回,提高召回精度
|
||||||
|
5. 优化 - 知识库导出,可直接触发流下载,无需等待转圈圈
|
||||||
|
|||||||
131
packages/global/common/string/textSplitter.ts
Normal file
131
packages/global/common/string/textSplitter.ts
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
import { getErrText } from '../error/utils';
|
||||||
|
import { countPromptTokens } from './tiktoken';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* text split into chunks
|
||||||
|
* maxLen - one chunk len. max: 3500
|
||||||
|
* overlapLen - The size of the before and after Text
|
||||||
|
* maxLen > overlapLen
|
||||||
|
* markdown
|
||||||
|
*/
|
||||||
|
export const splitText2Chunks = (props: { text: string; maxLen: number; overlapLen?: number }) => {
|
||||||
|
const { text = '', maxLen, overlapLen = Math.floor(maxLen * 0.2) } = props;
|
||||||
|
const tempMarker = 'SPLIT_HERE_SPLIT_HERE';
|
||||||
|
|
||||||
|
const stepReg: Record<number, RegExp> = {
|
||||||
|
0: /^(#\s[^\n]+)\n/gm,
|
||||||
|
1: /^(##\s[^\n]+)\n/gm,
|
||||||
|
2: /^(###\s[^\n]+)\n/gm,
|
||||||
|
3: /^(####\s[^\n]+)\n/gm,
|
||||||
|
|
||||||
|
4: /(\n\n)/g,
|
||||||
|
5: /([\n])/g,
|
||||||
|
6: /[。]|(?!<[^a-zA-Z])\.\s/g,
|
||||||
|
7: /([!?]|!\s|\?\s)/g,
|
||||||
|
8: /([;]|;\s)/g,
|
||||||
|
9: /([,]|,\s)/g
|
||||||
|
};
|
||||||
|
|
||||||
|
const splitTextRecursively = ({
|
||||||
|
text = '',
|
||||||
|
step,
|
||||||
|
lastChunk,
|
||||||
|
overlayChunk
|
||||||
|
}: {
|
||||||
|
text: string;
|
||||||
|
step: number;
|
||||||
|
lastChunk: string;
|
||||||
|
overlayChunk: string;
|
||||||
|
}) => {
|
||||||
|
if (text.length <= maxLen) {
|
||||||
|
return [text];
|
||||||
|
}
|
||||||
|
const reg = stepReg[step];
|
||||||
|
const isMarkdownSplit = step < 4;
|
||||||
|
|
||||||
|
if (!reg) {
|
||||||
|
// use slice-maxLen to split text
|
||||||
|
const chunks: string[] = [];
|
||||||
|
let chunk = '';
|
||||||
|
for (let i = 0; i < text.length; i += maxLen - overlapLen) {
|
||||||
|
chunk = text.slice(i, i + maxLen);
|
||||||
|
chunks.push(chunk);
|
||||||
|
}
|
||||||
|
return chunks;
|
||||||
|
}
|
||||||
|
|
||||||
|
// split text by special char
|
||||||
|
const splitTexts = text
|
||||||
|
.replace(reg, isMarkdownSplit ? `${tempMarker}$1` : `$1${tempMarker}`)
|
||||||
|
.split(`${tempMarker}`)
|
||||||
|
.filter((part) => part);
|
||||||
|
|
||||||
|
let chunks: string[] = [];
|
||||||
|
for (let i = 0; i < splitTexts.length; i++) {
|
||||||
|
let text = splitTexts[i];
|
||||||
|
let chunkToken = countPromptTokens(lastChunk, '');
|
||||||
|
const textToken = countPromptTokens(text, '');
|
||||||
|
|
||||||
|
// next chunk is too large / new chunk is too large(The current chunk must be smaller than maxLen)
|
||||||
|
if (textToken >= maxLen || chunkToken + textToken > maxLen * 1.4) {
|
||||||
|
// last chunk is too large, push it to chunks, not add to next chunk
|
||||||
|
if (chunkToken > maxLen * 0.7) {
|
||||||
|
chunks.push(lastChunk);
|
||||||
|
lastChunk = '';
|
||||||
|
overlayChunk = '';
|
||||||
|
}
|
||||||
|
// chunk is small, insert to next chunks
|
||||||
|
const innerChunks = splitTextRecursively({
|
||||||
|
text,
|
||||||
|
step: step + 1,
|
||||||
|
lastChunk,
|
||||||
|
overlayChunk
|
||||||
|
});
|
||||||
|
if (innerChunks.length === 0) continue;
|
||||||
|
chunks = chunks.concat(innerChunks);
|
||||||
|
lastChunk = '';
|
||||||
|
overlayChunk = '';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// size less than maxLen, push text to last chunk
|
||||||
|
lastChunk += text;
|
||||||
|
chunkToken += textToken; // Definitely less than 1.4 * maxLen
|
||||||
|
|
||||||
|
// size over lapLen, push it to next chunk
|
||||||
|
if (
|
||||||
|
overlapLen !== 0 &&
|
||||||
|
!isMarkdownSplit &&
|
||||||
|
chunkToken >= maxLen - overlapLen &&
|
||||||
|
textToken < overlapLen
|
||||||
|
) {
|
||||||
|
overlayChunk += text;
|
||||||
|
}
|
||||||
|
if (chunkToken >= maxLen) {
|
||||||
|
chunks.push(lastChunk);
|
||||||
|
lastChunk = overlayChunk;
|
||||||
|
overlayChunk = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the last chunk is independent, it needs to be push chunks. */
|
||||||
|
if (lastChunk && chunks[chunks.length - 1] && !chunks[chunks.length - 1].endsWith(lastChunk)) {
|
||||||
|
chunks.push(lastChunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
return chunks;
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const chunks = splitTextRecursively({ text, step: 0, lastChunk: '', overlayChunk: '' });
|
||||||
|
|
||||||
|
const tokens = chunks.reduce((sum, chunk) => sum + countPromptTokens(chunk, 'system'), 0);
|
||||||
|
|
||||||
|
return {
|
||||||
|
chunks,
|
||||||
|
tokens
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(getErrText(err));
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -1,8 +1,8 @@
|
|||||||
/* Only the token of gpt-3.5-turbo is used */
|
/* Only the token of gpt-3.5-turbo is used */
|
||||||
import type { ChatItemType } from '@fastgpt/global/core/chat/type';
|
import type { ChatItemType } from '../../../core/chat/type';
|
||||||
import { Tiktoken } from 'js-tiktoken/lite';
|
import { Tiktoken } from 'js-tiktoken/lite';
|
||||||
import { adaptChat2GptMessages } from '@/utils/common/adapt/message';
|
import { adaptChat2GptMessages } from '../../../core/chat/adapt';
|
||||||
import { ChatCompletionRequestMessageRoleEnum } from '@fastgpt/global/core/ai/constant';
|
import { ChatCompletionRequestMessageRoleEnum } from '../../../core/ai/constant';
|
||||||
import encodingJson from './cl100k_base.json';
|
import encodingJson from './cl100k_base.json';
|
||||||
|
|
||||||
/* init tikToken obj */
|
/* init tikToken obj */
|
||||||
@ -55,17 +55,6 @@ export function countMessagesTokens({ messages }: { messages: ChatItemType[] })
|
|||||||
return totalTokens;
|
return totalTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sliceTextByTokens({ text, length }: { text: string; length: number }) {
|
|
||||||
const enc = getTikTokenEnc();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const encodeText = enc.encode(text);
|
|
||||||
return enc.decode(encodeText.slice(0, length));
|
|
||||||
} catch (error) {
|
|
||||||
return text.slice(0, length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* slice messages from top to bottom by maxTokens */
|
/* slice messages from top to bottom by maxTokens */
|
||||||
export function sliceMessagesTB({
|
export function sliceMessagesTB({
|
||||||
messages,
|
messages,
|
||||||
5
packages/global/common/string/tiktoken/type.d.ts
vendored
Normal file
5
packages/global/common/string/tiktoken/type.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import type { Tiktoken } from 'js-tiktoken';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
var TikToken: Tiktoken;
|
||||||
|
}
|
||||||
@ -1,13 +1,15 @@
|
|||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
|
|
||||||
|
/* check string is a web link */
|
||||||
export function strIsLink(str?: string) {
|
export function strIsLink(str?: string) {
|
||||||
if (!str) return false;
|
if (!str) return false;
|
||||||
if (/^((http|https)?:\/\/|www\.|\/)[^\s/$.?#].[^\s]*$/i.test(str)) return true;
|
if (/^((http|https)?:\/\/|www\.|\/)[^\s/$.?#].[^\s]*$/i.test(str)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const hashStr = (psw: string) => {
|
/* hash string */
|
||||||
return crypto.createHash('sha256').update(psw).digest('hex');
|
export const hashStr = (str: string) => {
|
||||||
|
return crypto.createHash('sha256').update(str).digest('hex');
|
||||||
};
|
};
|
||||||
|
|
||||||
/* simple text, remove chinese space and extra \n */
|
/* simple text, remove chinese space and extra \n */
|
||||||
@ -20,3 +22,16 @@ export const simpleText = (text: string) => {
|
|||||||
|
|
||||||
return text;
|
return text;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
replace {{variable}} to value
|
||||||
|
*/
|
||||||
|
export function replaceVariable(text: string, obj: Record<string, string | number>) {
|
||||||
|
for (const key in obj) {
|
||||||
|
const val = obj[key];
|
||||||
|
if (!['string', 'number'].includes(typeof val)) continue;
|
||||||
|
|
||||||
|
text = text.replace(new RegExp(`{{(${key})}}`, 'g'), String(val));
|
||||||
|
}
|
||||||
|
return text || '';
|
||||||
|
}
|
||||||
|
|||||||
5
packages/global/core/ai/api.d.ts
vendored
Normal file
5
packages/global/core/ai/api.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export type PostReRankProps = {
|
||||||
|
query: string;
|
||||||
|
inputs: { id: string; text: string }[];
|
||||||
|
};
|
||||||
|
export type PostReRankResponse = { id: string; score: number }[];
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import type { ChatItemType } from '@fastgpt/global/core/chat/type.d';
|
import type { ChatItemType } from '../../core/chat/type.d';
|
||||||
import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
|
import { ChatRoleEnum } from '../../core/chat/constants';
|
||||||
import { ChatCompletionRequestMessageRoleEnum } from '@fastgpt/global/core/ai/constant';
|
import { ChatCompletionRequestMessageRoleEnum } from '../../core/ai/constant';
|
||||||
import type { ChatMessageItemType } from '@fastgpt/global/core/ai/type.d';
|
import type { ChatMessageItemType } from '../../core/ai/type.d';
|
||||||
|
|
||||||
const chat2Message = {
|
const chat2Message = {
|
||||||
[ChatRoleEnum.AI]: ChatCompletionRequestMessageRoleEnum.Assistant,
|
[ChatRoleEnum.AI]: ChatCompletionRequestMessageRoleEnum.Assistant,
|
||||||
20
packages/global/core/dataset/api.d.ts
vendored
Normal file
20
packages/global/core/dataset/api.d.ts
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { DatasetDataIndexItemType } from './type';
|
||||||
|
|
||||||
|
/* ================= dataset ===================== */
|
||||||
|
|
||||||
|
/* ================= collection ===================== */
|
||||||
|
|
||||||
|
/* ================= data ===================== */
|
||||||
|
export type PgSearchRawType = {
|
||||||
|
id: string;
|
||||||
|
team_id: string;
|
||||||
|
tmb_id: string;
|
||||||
|
collection_id: string;
|
||||||
|
data_id: string;
|
||||||
|
score: number;
|
||||||
|
};
|
||||||
|
export type PushDatasetDataChunkProps = {
|
||||||
|
q: string; // embedding content
|
||||||
|
a?: string; // bonus content
|
||||||
|
indexes?: Omit<DatasetDataIndexItemType, 'dataId'>[];
|
||||||
|
};
|
||||||
@ -36,29 +36,54 @@ export const DatasetCollectionTypeMap = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export enum TrainingModeEnum {
|
export enum DatasetDataIndexTypeEnum {
|
||||||
'qa' = 'qa',
|
chunk = 'chunk',
|
||||||
'index' = 'index'
|
qa = 'qa',
|
||||||
|
summary = 'summary',
|
||||||
|
hypothetical = 'hypothetical',
|
||||||
|
custom = 'custom'
|
||||||
}
|
}
|
||||||
export const TrainingTypeMap = {
|
export const DatasetDataIndexTypeMap = {
|
||||||
[TrainingModeEnum.qa]: 'qa',
|
[DatasetDataIndexTypeEnum.chunk]: {
|
||||||
[TrainingModeEnum.index]: 'index'
|
name: 'dataset.data.indexes.chunk'
|
||||||
};
|
|
||||||
|
|
||||||
export enum DatasetSpecialIdEnum {
|
|
||||||
manual = 'manual',
|
|
||||||
mark = 'mark'
|
|
||||||
}
|
|
||||||
export const datasetSpecialIdMap = {
|
|
||||||
[DatasetSpecialIdEnum.manual]: {
|
|
||||||
name: 'kb.Manual Data',
|
|
||||||
sourceName: 'kb.Manual Input'
|
|
||||||
},
|
},
|
||||||
[DatasetSpecialIdEnum.mark]: {
|
[DatasetDataIndexTypeEnum.summary]: {
|
||||||
name: 'kb.Mark Data',
|
name: 'dataset.data.indexes.summary'
|
||||||
sourceName: 'kb.Manual Mark'
|
},
|
||||||
|
[DatasetDataIndexTypeEnum.hypothetical]: {
|
||||||
|
name: 'dataset.data.indexes.hypothetical'
|
||||||
|
},
|
||||||
|
[DatasetDataIndexTypeEnum.qa]: {
|
||||||
|
name: 'dataset.data.indexes.qa'
|
||||||
|
},
|
||||||
|
[DatasetDataIndexTypeEnum.custom]: {
|
||||||
|
name: 'dataset.data.indexes.custom'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
export const datasetSpecialIds: string[] = [DatasetSpecialIdEnum.manual, DatasetSpecialIdEnum.mark];
|
|
||||||
|
export enum TrainingModeEnum {
|
||||||
|
'chunk' = 'chunk',
|
||||||
|
'qa' = 'qa'
|
||||||
|
// 'hypothetical' = 'hypothetical',
|
||||||
|
// 'summary' = 'summary',
|
||||||
|
// 'multipleIndex' = 'multipleIndex'
|
||||||
|
}
|
||||||
|
export const TrainingTypeMap = {
|
||||||
|
[TrainingModeEnum.chunk]: {
|
||||||
|
name: 'chunk'
|
||||||
|
},
|
||||||
|
[TrainingModeEnum.qa]: {
|
||||||
|
name: 'qa'
|
||||||
|
}
|
||||||
|
// [TrainingModeEnum.hypothetical]: {
|
||||||
|
// name: 'hypothetical'
|
||||||
|
// },
|
||||||
|
// [TrainingModeEnum.summary]: {
|
||||||
|
// name: 'summary'
|
||||||
|
// },
|
||||||
|
// [TrainingModeEnum.multipleIndex]: {
|
||||||
|
// name: 'multipleIndex'
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
export const FolderAvatarSrc = '/imgs/files/folder.svg';
|
export const FolderAvatarSrc = '/imgs/files/folder.svg';
|
||||||
|
|||||||
27
packages/global/core/dataset/controller.d.ts
vendored
Normal file
27
packages/global/core/dataset/controller.d.ts
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import type { DatasetDataIndexItemType, DatasetDataSchemaType } from './type';
|
||||||
|
|
||||||
|
export type CreateDatasetDataProps = {
|
||||||
|
teamId: string;
|
||||||
|
tmbId: string;
|
||||||
|
datasetId: string;
|
||||||
|
collectionId: string;
|
||||||
|
q: string;
|
||||||
|
a?: string;
|
||||||
|
indexes?: Omit<DatasetDataIndexItemType, 'dataId'>[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UpdateDatasetDataProps = {
|
||||||
|
dataId: string;
|
||||||
|
q?: string;
|
||||||
|
a?: string;
|
||||||
|
indexes?: (Omit<DatasetDataIndexItemType, 'dataId'> & {
|
||||||
|
dataId?: string; // pg data id
|
||||||
|
})[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PatchIndexesProps = {
|
||||||
|
type: 'create' | 'update' | 'delete';
|
||||||
|
index: Omit<DatasetDataIndexItemType, 'dataId'> & {
|
||||||
|
dataId?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
78
packages/global/core/dataset/type.d.ts
vendored
78
packages/global/core/dataset/type.d.ts
vendored
@ -1,6 +1,14 @@
|
|||||||
|
import type { VectorModelItemType } from '../../core/ai/model.d';
|
||||||
import { PermissionTypeEnum } from '../../support/permission/constant';
|
import { PermissionTypeEnum } from '../../support/permission/constant';
|
||||||
import { DatasetCollectionTypeEnum, DatasetTypeEnum, TrainingModeEnum } from './constant';
|
import { PushDatasetDataChunkProps } from './api';
|
||||||
|
import {
|
||||||
|
DatasetCollectionTypeEnum,
|
||||||
|
DatasetDataIndexTypeEnum,
|
||||||
|
DatasetTypeEnum,
|
||||||
|
TrainingModeEnum
|
||||||
|
} from './constant';
|
||||||
|
|
||||||
|
/* schema */
|
||||||
export type DatasetSchemaType = {
|
export type DatasetSchemaType = {
|
||||||
_id: string;
|
_id: string;
|
||||||
parentId: string;
|
parentId: string;
|
||||||
@ -33,13 +41,33 @@ export type DatasetCollectionSchemaType = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type DatasetDataIndexItemType = {
|
||||||
|
defaultIndex: boolean;
|
||||||
|
dataId: string; // pg data id
|
||||||
|
type: `${DatasetDataIndexTypeEnum}`;
|
||||||
|
text: string;
|
||||||
|
};
|
||||||
|
export type DatasetDataSchemaType = {
|
||||||
|
_id: string;
|
||||||
|
userId: string;
|
||||||
|
teamId: string;
|
||||||
|
tmbId: string;
|
||||||
|
datasetId: string;
|
||||||
|
collectionId: string;
|
||||||
|
datasetId: string;
|
||||||
|
collectionId: string;
|
||||||
|
q: string; // large chunks or question
|
||||||
|
a: string; // answer or custom content
|
||||||
|
indexes: DatasetDataIndexItemType[];
|
||||||
|
};
|
||||||
|
|
||||||
export type DatasetTrainingSchemaType = {
|
export type DatasetTrainingSchemaType = {
|
||||||
_id: string;
|
_id: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
teamId: string;
|
teamId: string;
|
||||||
tmbId: string;
|
tmbId: string;
|
||||||
datasetId: string;
|
datasetId: string;
|
||||||
datasetCollectionId: string;
|
collectionId: string;
|
||||||
billId: string;
|
billId: string;
|
||||||
expireAt: Date;
|
expireAt: Date;
|
||||||
lockTime: Date;
|
lockTime: Date;
|
||||||
@ -48,6 +76,7 @@ export type DatasetTrainingSchemaType = {
|
|||||||
prompt: string;
|
prompt: string;
|
||||||
q: string;
|
q: string;
|
||||||
a: string;
|
a: string;
|
||||||
|
indexes: Omit<DatasetDataIndexItemType, 'dataId'>[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CollectionWithDatasetType = Omit<DatasetCollectionSchemaType, 'datasetId'> & {
|
export type CollectionWithDatasetType = Omit<DatasetCollectionSchemaType, 'datasetId'> & {
|
||||||
@ -55,41 +84,31 @@ export type CollectionWithDatasetType = Omit<DatasetCollectionSchemaType, 'datas
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* ================= dataset ===================== */
|
/* ================= dataset ===================== */
|
||||||
|
export type DatasetItemType = Omit<DatasetSchemaType, 'vectorModel'> & {
|
||||||
/* ================= collection ===================== */
|
vectorModel: VectorModelItemType;
|
||||||
export type DatasetCollectionItemType = DatasetCollectionSchemaType & {
|
isOwner: boolean;
|
||||||
canWrite: boolean;
|
canWrite: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ================= collection ===================== */
|
||||||
|
export type DatasetCollectionItemType = CollectionWithDatasetType & {
|
||||||
|
canWrite: boolean;
|
||||||
|
sourceName: string;
|
||||||
|
sourceId?: string;
|
||||||
|
};
|
||||||
|
|
||||||
/* ================= data ===================== */
|
/* ================= data ===================== */
|
||||||
export type PgRawDataItemType = {
|
export type DatasetDataItemType = {
|
||||||
id: string;
|
|
||||||
q: string;
|
|
||||||
a: string;
|
|
||||||
team_id: string;
|
|
||||||
tmb_id: string;
|
|
||||||
dataset_id: string;
|
|
||||||
collection_id: string;
|
|
||||||
};
|
|
||||||
export type PgDataItemType = {
|
|
||||||
id: string;
|
|
||||||
q: string;
|
|
||||||
a: string;
|
|
||||||
teamId: string;
|
|
||||||
tmbId: string;
|
|
||||||
datasetId: string;
|
|
||||||
collectionId: string;
|
|
||||||
};
|
|
||||||
export type DatasetChunkItemType = {
|
|
||||||
q: string;
|
|
||||||
a: string;
|
|
||||||
};
|
|
||||||
export type DatasetDataItemType = DatasetChunkItemType & {
|
|
||||||
id: string;
|
id: string;
|
||||||
datasetId: string;
|
datasetId: string;
|
||||||
collectionId: string;
|
collectionId: string;
|
||||||
sourceName: string;
|
sourceName: string;
|
||||||
sourceId?: string;
|
sourceId?: string;
|
||||||
|
q: string;
|
||||||
|
a: string;
|
||||||
|
indexes: DatasetDataIndexItemType[];
|
||||||
|
isOwner: boolean;
|
||||||
|
canWrite: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* --------------- file ---------------------- */
|
/* --------------- file ---------------------- */
|
||||||
@ -109,9 +128,6 @@ export type DatasetFileSchema = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* ============= search =============== */
|
/* ============= search =============== */
|
||||||
export type SearchDataResultItemType = PgRawDataItemType & {
|
|
||||||
score: number;
|
|
||||||
};
|
|
||||||
export type SearchDataResponseItemType = DatasetDataItemType & {
|
export type SearchDataResponseItemType = DatasetDataItemType & {
|
||||||
score: number;
|
score: number;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { DatasetCollectionTypeEnum } from './constant';
|
import { DatasetCollectionTypeEnum, DatasetDataIndexTypeEnum } from './constant';
|
||||||
import { getFileIcon } from '../../common/file/icon';
|
import { getFileIcon } from '../../common/file/icon';
|
||||||
import { strIsLink } from '../../common/string/tools';
|
import { strIsLink } from '../../common/string/tools';
|
||||||
|
|
||||||
@ -44,3 +44,14 @@ export function getSourceNameIcon({
|
|||||||
}
|
}
|
||||||
return '/imgs/files/collection.svg';
|
return '/imgs/files/collection.svg';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getDefaultIndex(props?: { q?: string; a?: string; dataId?: string }) {
|
||||||
|
const { q = '', a, dataId } = props || {};
|
||||||
|
const qaStr = `${q}\n${a}`.trim();
|
||||||
|
return {
|
||||||
|
defaultIndex: true,
|
||||||
|
type: a ? DatasetDataIndexTypeEnum.qa : DatasetDataIndexTypeEnum.chunk,
|
||||||
|
text: a ? qaStr : q,
|
||||||
|
dataId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
3
packages/global/core/module/api.d.ts
vendored
3
packages/global/core/module/api.d.ts
vendored
@ -0,0 +1,3 @@
|
|||||||
|
import { VectorModelItemType } from '../ai/model.d';
|
||||||
|
|
||||||
|
export type SelectedDatasetType = { datasetId: string; vectorModel: VectorModelItemType }[];
|
||||||
@ -6,7 +6,8 @@
|
|||||||
"timezones-list": "^3.0.2",
|
"timezones-list": "^3.0.2",
|
||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
"encoding": "^0.1.13",
|
"encoding": "^0.1.13",
|
||||||
"openai": "^4.16.1"
|
"openai": "^4.16.1",
|
||||||
|
"js-tiktoken": "^1.0.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.8.5"
|
"@types/node": "^20.8.5"
|
||||||
|
|||||||
@ -24,7 +24,8 @@ export const TeamMemberRoleMap = {
|
|||||||
export enum TeamMemberStatusEnum {
|
export enum TeamMemberStatusEnum {
|
||||||
waiting = 'waiting',
|
waiting = 'waiting',
|
||||||
active = 'active',
|
active = 'active',
|
||||||
reject = 'reject'
|
reject = 'reject',
|
||||||
|
leave = 'leave'
|
||||||
}
|
}
|
||||||
export const TeamMemberStatusMap = {
|
export const TeamMemberStatusMap = {
|
||||||
[TeamMemberStatusEnum.waiting]: {
|
[TeamMemberStatusEnum.waiting]: {
|
||||||
@ -38,5 +39,10 @@ export const TeamMemberStatusMap = {
|
|||||||
[TeamMemberStatusEnum.reject]: {
|
[TeamMemberStatusEnum.reject]: {
|
||||||
label: 'user.team.member.reject',
|
label: 'user.team.member.reject',
|
||||||
color: 'red.600'
|
color: 'red.600'
|
||||||
|
},
|
||||||
|
[TeamMemberStatusEnum.leave]: {
|
||||||
|
label: 'user.team.member.leave',
|
||||||
|
color: 'red.600'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
export const leaveStatus = { $ne: TeamMemberStatusEnum.leave };
|
||||||
|
|||||||
@ -37,4 +37,7 @@ export type UpdateInviteProps = {
|
|||||||
tmbId: string;
|
tmbId: string;
|
||||||
status: TeamMemberSchema['status'];
|
status: TeamMemberSchema['status'];
|
||||||
};
|
};
|
||||||
export type InviteMemberResponse = Record<'invite' | 'inValid' | 'inTeam', string[]>;
|
export type InviteMemberResponse = Record<
|
||||||
|
'invite' | 'inValid' | 'inTeam',
|
||||||
|
{ username: string; userId: string }[]
|
||||||
|
>;
|
||||||
|
|||||||
4
packages/global/support/user/team/type.d.ts
vendored
4
packages/global/support/user/team/type.d.ts
vendored
@ -16,6 +16,7 @@ export type TeamMemberSchema = {
|
|||||||
teamId: string;
|
teamId: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
createTime: Date;
|
createTime: Date;
|
||||||
|
name: string;
|
||||||
role: `${TeamMemberRoleEnum}`;
|
role: `${TeamMemberRoleEnum}`;
|
||||||
status: `${TeamMemberStatusEnum}`;
|
status: `${TeamMemberStatusEnum}`;
|
||||||
defaultTeam: boolean;
|
defaultTeam: boolean;
|
||||||
@ -25,6 +26,7 @@ export type TeamItemType = {
|
|||||||
userId: string;
|
userId: string;
|
||||||
teamId: string;
|
teamId: string;
|
||||||
teamName: string;
|
teamName: string;
|
||||||
|
memberName: string;
|
||||||
avatar: string;
|
avatar: string;
|
||||||
balance: number;
|
balance: number;
|
||||||
tmbId: string;
|
tmbId: string;
|
||||||
@ -39,7 +41,7 @@ export type TeamMemberItemType = {
|
|||||||
userId: string;
|
userId: string;
|
||||||
tmbId: string;
|
tmbId: string;
|
||||||
teamId: string;
|
teamId: string;
|
||||||
memberUsername: string;
|
memberName: string;
|
||||||
avatar: string;
|
avatar: string;
|
||||||
role: `${TeamMemberRoleEnum}`;
|
role: `${TeamMemberRoleEnum}`;
|
||||||
status: `${TeamMemberStatusEnum}`;
|
status: `${TeamMemberStatusEnum}`;
|
||||||
|
|||||||
@ -15,7 +15,7 @@ export type BillSchema = CreateBillProps & {
|
|||||||
|
|
||||||
export type BillItemType = {
|
export type BillItemType = {
|
||||||
id: string;
|
id: string;
|
||||||
username: string;
|
memberName: string;
|
||||||
time: Date;
|
time: Date;
|
||||||
appName: string;
|
appName: string;
|
||||||
source: BillSchema['source'];
|
source: BillSchema['source'];
|
||||||
|
|||||||
@ -15,9 +15,6 @@ interface ResponseDataType {
|
|||||||
* 请求开始
|
* 请求开始
|
||||||
*/
|
*/
|
||||||
function requestStart(config: InternalAxiosRequestConfig): InternalAxiosRequestConfig {
|
function requestStart(config: InternalAxiosRequestConfig): InternalAxiosRequestConfig {
|
||||||
if (config.headers) {
|
|
||||||
config.headers.rootkey = process.env.ROOT_KEY;
|
|
||||||
}
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +59,8 @@ const instance = axios.create({
|
|||||||
timeout: 60000, // 超时时间
|
timeout: 60000, // 超时时间
|
||||||
headers: {
|
headers: {
|
||||||
'content-type': 'application/json',
|
'content-type': 'application/json',
|
||||||
'Cache-Control': 'no-cache'
|
'Cache-Control': 'no-cache',
|
||||||
|
rootkey: process.env.ROOT_KEY
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -171,8 +171,7 @@ export async function initPg() {
|
|||||||
tmb_id VARCHAR(50) NOT NULL,
|
tmb_id VARCHAR(50) NOT NULL,
|
||||||
dataset_id VARCHAR(50) NOT NULL,
|
dataset_id VARCHAR(50) NOT NULL,
|
||||||
collection_id VARCHAR(50) NOT NULL,
|
collection_id VARCHAR(50) NOT NULL,
|
||||||
q TEXT NOT NULL,
|
data_id VARCHAR(50) NOT NULL
|
||||||
a TEXT
|
|
||||||
);
|
);
|
||||||
CREATE INDEX IF NOT EXISTS vector_index ON ${PgDatasetTableName} USING hnsw (vector vector_ip_ops) WITH (m = 24, ef_construction = 64);
|
CREATE INDEX IF NOT EXISTS vector_index ON ${PgDatasetTableName} USING hnsw (vector vector_ip_ops) WITH (m = 24, ef_construction = 64);
|
||||||
`);
|
`);
|
||||||
|
|||||||
@ -1,22 +1,7 @@
|
|||||||
import type { ChatItemType } from '@fastgpt/global/core/chat/type.d';
|
import type { ChatItemType } from '@fastgpt/global/core/chat/type.d';
|
||||||
import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
|
import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
|
||||||
import type { NextApiResponse } from 'next';
|
import { countMessagesTokens, countPromptTokens } from '@fastgpt/global/common/string/tiktoken';
|
||||||
import { countMessagesTokens, countPromptTokens } from '@/global/common/tiktoken';
|
import { adaptRole_Chat2Message } from '@fastgpt/global/core/chat/adapt';
|
||||||
import { adaptRole_Chat2Message } from '@/utils/common/adapt/message';
|
|
||||||
|
|
||||||
export type ChatCompletionResponseType = {
|
|
||||||
streamResponse: any;
|
|
||||||
responseMessages: ChatItemType[];
|
|
||||||
responseText: string;
|
|
||||||
totalTokens: number;
|
|
||||||
};
|
|
||||||
export type StreamResponseType = {
|
|
||||||
chatResponse: any;
|
|
||||||
messages: ChatItemType[];
|
|
||||||
res: NextApiResponse;
|
|
||||||
model: string;
|
|
||||||
[key: string]: any;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* slice chat context by tokens */
|
/* slice chat context by tokens */
|
||||||
export function ChatContextFilter({
|
export function ChatContextFilter({
|
||||||
@ -56,8 +56,7 @@ const DatasetCollectionSchema = new Schema({
|
|||||||
ref: 'dataset.files'
|
ref: 'dataset.files'
|
||||||
},
|
},
|
||||||
rawLink: {
|
rawLink: {
|
||||||
type: String,
|
type: String
|
||||||
default: ''
|
|
||||||
},
|
},
|
||||||
// 451 初始化
|
// 451 初始化
|
||||||
pgCollectionId: {
|
pgCollectionId: {
|
||||||
|
|||||||
@ -1,5 +1,25 @@
|
|||||||
import { CollectionWithDatasetType } from '@fastgpt/global/core/dataset/type';
|
import { CollectionWithDatasetType } from '@fastgpt/global/core/dataset/type';
|
||||||
import { MongoDatasetCollection } from './collection/schema';
|
import { MongoDatasetCollection } from './collection/schema';
|
||||||
|
import { MongoDataset } from './schema';
|
||||||
|
|
||||||
|
/* ============= dataset ========== */
|
||||||
|
/* find all datasetId by top datasetId */
|
||||||
|
export async function findDatasetIdTreeByTopDatasetId(
|
||||||
|
id: string,
|
||||||
|
result: string[] = []
|
||||||
|
): Promise<string[]> {
|
||||||
|
let allChildrenIds = [...result];
|
||||||
|
|
||||||
|
// find children
|
||||||
|
const children = await MongoDataset.find({ parentId: id });
|
||||||
|
|
||||||
|
for (const child of children) {
|
||||||
|
const grandChildrenIds = await findDatasetIdTreeByTopDatasetId(child._id, result);
|
||||||
|
allChildrenIds = allChildrenIds.concat(grandChildrenIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [String(id), ...allChildrenIds];
|
||||||
|
}
|
||||||
|
|
||||||
export async function getCollectionWithDataset(collectionId: string) {
|
export async function getCollectionWithDataset(collectionId: string) {
|
||||||
const data = (
|
const data = (
|
||||||
|
|||||||
78
packages/service/core/dataset/data/schema.ts
Normal file
78
packages/service/core/dataset/data/schema.ts
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import { connectionMongo, type Model } from '../../../common/mongo';
|
||||||
|
const { Schema, model, models } = connectionMongo;
|
||||||
|
import { DatasetDataSchemaType } from '@fastgpt/global/core/dataset/type.d';
|
||||||
|
import {
|
||||||
|
TeamCollectionName,
|
||||||
|
TeamMemberCollectionName
|
||||||
|
} from '@fastgpt/global/support/user/team/constant';
|
||||||
|
import { DatasetCollectionName } from '../schema';
|
||||||
|
import { DatasetColCollectionName } from '../collection/schema';
|
||||||
|
import { DatasetDataIndexTypeMap } from '@fastgpt/global/core/dataset/constant';
|
||||||
|
|
||||||
|
export const DatasetDataCollectionName = 'dataset.datas';
|
||||||
|
|
||||||
|
const DatasetDataSchema = new Schema({
|
||||||
|
teamId: {
|
||||||
|
type: Schema.Types.ObjectId,
|
||||||
|
ref: TeamCollectionName,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
tmbId: {
|
||||||
|
type: Schema.Types.ObjectId,
|
||||||
|
ref: TeamMemberCollectionName,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
datasetId: {
|
||||||
|
type: Schema.Types.ObjectId,
|
||||||
|
ref: DatasetCollectionName,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
collectionId: {
|
||||||
|
type: Schema.Types.ObjectId,
|
||||||
|
ref: DatasetColCollectionName,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
q: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
a: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
indexes: {
|
||||||
|
type: [
|
||||||
|
{
|
||||||
|
defaultIndex: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
enum: Object.keys(DatasetDataIndexTypeMap),
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
dataId: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
default: []
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
DatasetDataSchema.index({ userId: 1 });
|
||||||
|
DatasetDataSchema.index({ datasetId: 1 });
|
||||||
|
DatasetDataSchema.index({ collectionId: 1 });
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MongoDatasetData: Model<DatasetDataSchemaType> =
|
||||||
|
models[DatasetDataCollectionName] || model(DatasetDataCollectionName, DatasetDataSchema);
|
||||||
@ -2,7 +2,7 @@
|
|||||||
import { connectionMongo, type Model } from '../../../common/mongo';
|
import { connectionMongo, type Model } from '../../../common/mongo';
|
||||||
const { Schema, model, models } = connectionMongo;
|
const { Schema, model, models } = connectionMongo;
|
||||||
import { DatasetTrainingSchemaType } from '@fastgpt/global/core/dataset/type';
|
import { DatasetTrainingSchemaType } from '@fastgpt/global/core/dataset/type';
|
||||||
import { TrainingTypeMap } from '@fastgpt/global/core/dataset/constant';
|
import { DatasetDataIndexTypeMap, TrainingTypeMap } from '@fastgpt/global/core/dataset/constant';
|
||||||
import { DatasetColCollectionName } from '../collection/schema';
|
import { DatasetColCollectionName } from '../collection/schema';
|
||||||
import { DatasetCollectionName } from '../schema';
|
import { DatasetCollectionName } from '../schema';
|
||||||
import {
|
import {
|
||||||
@ -33,12 +33,13 @@ const TrainingDataSchema = new Schema({
|
|||||||
ref: DatasetCollectionName,
|
ref: DatasetCollectionName,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
datasetCollectionId: {
|
collectionId: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: DatasetColCollectionName,
|
ref: DatasetColCollectionName,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
billId: {
|
billId: {
|
||||||
|
// concat bill
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
@ -48,6 +49,7 @@ const TrainingDataSchema = new Schema({
|
|||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
expireAt: {
|
expireAt: {
|
||||||
|
// It will be deleted after 7 days
|
||||||
type: Date,
|
type: Date,
|
||||||
default: () => new Date()
|
default: () => new Date()
|
||||||
},
|
},
|
||||||
@ -56,6 +58,7 @@ const TrainingDataSchema = new Schema({
|
|||||||
default: () => new Date('2000/1/1')
|
default: () => new Date('2000/1/1')
|
||||||
},
|
},
|
||||||
model: {
|
model: {
|
||||||
|
// ai model
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
@ -71,13 +74,29 @@ const TrainingDataSchema = new Schema({
|
|||||||
a: {
|
a: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
|
},
|
||||||
|
indexes: {
|
||||||
|
type: [
|
||||||
|
{
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
enum: Object.keys(DatasetDataIndexTypeMap),
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
default: []
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
TrainingDataSchema.index({ lockTime: 1 });
|
TrainingDataSchema.index({ lockTime: 1 });
|
||||||
TrainingDataSchema.index({ userId: 1 });
|
TrainingDataSchema.index({ userId: 1 });
|
||||||
TrainingDataSchema.index({ datasetCollectionId: 1 });
|
TrainingDataSchema.index({ collectionId: 1 });
|
||||||
TrainingDataSchema.index({ expireAt: 1 }, { expireAfterSeconds: 7 * 24 * 60 });
|
TrainingDataSchema.index({ expireAt: 1 }, { expireAfterSeconds: 7 * 24 * 60 });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
|||||||
@ -23,6 +23,7 @@ const PromotionRecordSchema = new Schema({
|
|||||||
enum: ['pay', 'register']
|
enum: ['pay', 'register']
|
||||||
},
|
},
|
||||||
amount: {
|
amount: {
|
||||||
|
// 1 * PRICE_SCALE
|
||||||
type: Number,
|
type: Number,
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,7 +30,7 @@ export const pushResult2Remote = async ({
|
|||||||
shareId?: string;
|
shareId?: string;
|
||||||
responseData?: any[];
|
responseData?: any[];
|
||||||
}) => {
|
}) => {
|
||||||
if (!shareId || !authToken) return;
|
if (!shareId || !authToken || !global.systemEnv.pluginBaseUrl) return;
|
||||||
try {
|
try {
|
||||||
const outLink = await MongoOutLink.findOne({
|
const outLink = await MongoOutLink.findOne({
|
||||||
shareId
|
shareId
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
|
import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||||
import { parseHeaderCert } from '../controller';
|
import { parseHeaderCert } from '../controller';
|
||||||
import { AuthModeType } from '../type';
|
import { AuthModeType } from '../type';
|
||||||
|
import { authOutLinkValid } from './outLink';
|
||||||
|
|
||||||
export const authCert = async (props: AuthModeType) => {
|
export const authCert = async (props: AuthModeType) => {
|
||||||
const result = await parseHeaderCert(props);
|
const result = await parseHeaderCert(props);
|
||||||
@ -10,3 +12,22 @@ export const authCert = async (props: AuthModeType) => {
|
|||||||
canWrite: true
|
canWrite: true
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
export async function authCertAndShareId({
|
||||||
|
shareId,
|
||||||
|
...props
|
||||||
|
}: AuthModeType & { shareId?: string }) {
|
||||||
|
if (!shareId) {
|
||||||
|
return authCert(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { app } = await authOutLinkValid({ shareId });
|
||||||
|
|
||||||
|
return {
|
||||||
|
teamId: String(app.teamId),
|
||||||
|
tmbId: String(app.tmbId),
|
||||||
|
authType: AuthUserTypeEnum.outLink,
|
||||||
|
apikey: '',
|
||||||
|
isOwner: false,
|
||||||
|
canWrite: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@ -27,11 +27,11 @@ export async function authDataset({
|
|||||||
}
|
}
|
||||||
> {
|
> {
|
||||||
const result = await parseHeaderCert(props);
|
const result = await parseHeaderCert(props);
|
||||||
const { userId, teamId, tmbId } = result;
|
const { teamId, tmbId } = result;
|
||||||
const { role } = await getTeamInfoByTmbId({ tmbId });
|
const { role } = await getTeamInfoByTmbId({ tmbId });
|
||||||
|
|
||||||
const { dataset, isOwner, canWrite } = await (async () => {
|
const { dataset, isOwner, canWrite } = await (async () => {
|
||||||
const dataset = (await MongoDataset.findOne({ _id: datasetId, teamId }))?.toJSON();
|
const dataset = (await MongoDataset.findOne({ _id: datasetId, teamId }))?.toObject();
|
||||||
|
|
||||||
if (!dataset) {
|
if (!dataset) {
|
||||||
return Promise.reject(DatasetErrEnum.unAuthDataset);
|
return Promise.reject(DatasetErrEnum.unAuthDataset);
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import { getTeamInfoByTmbId } from '../../user/team/controller';
|
|||||||
import { MongoOpenApi } from '../../openapi/schema';
|
import { MongoOpenApi } from '../../openapi/schema';
|
||||||
import { OpenApiErrEnum } from '@fastgpt/global/common/error/code/openapi';
|
import { OpenApiErrEnum } from '@fastgpt/global/common/error/code/openapi';
|
||||||
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
|
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
|
||||||
import { PermissionTypeEnum } from '@fastgpt/global/support/permission/constant';
|
|
||||||
|
|
||||||
export async function authOpenApiKeyCrud({
|
export async function authOpenApiKeyCrud({
|
||||||
id,
|
id,
|
||||||
|
|||||||
@ -37,13 +37,11 @@ export async function authUserRole(props: AuthModeType): Promise<
|
|||||||
teamOwner: boolean;
|
teamOwner: boolean;
|
||||||
}
|
}
|
||||||
> {
|
> {
|
||||||
const { userId, teamId, tmbId } = await parseHeaderCert(props);
|
const result = await parseHeaderCert(props);
|
||||||
const { role: userRole, canWrite } = await getTeamInfoByTmbId({ tmbId });
|
const { role: userRole, canWrite } = await getTeamInfoByTmbId({ tmbId: result.tmbId });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
userId,
|
...result,
|
||||||
teamId,
|
|
||||||
tmbId,
|
|
||||||
isOwner: true,
|
isOwner: true,
|
||||||
role: userRole,
|
role: userRole,
|
||||||
teamOwner: userRole === TeamMemberRoleEnum.owner,
|
teamOwner: userRole === TeamMemberRoleEnum.owner,
|
||||||
|
|||||||
@ -4,57 +4,42 @@ import {
|
|||||||
TeamMemberRoleEnum,
|
TeamMemberRoleEnum,
|
||||||
TeamMemberStatusEnum,
|
TeamMemberStatusEnum,
|
||||||
TeamCollectionName,
|
TeamCollectionName,
|
||||||
TeamMemberCollectionName
|
TeamMemberCollectionName,
|
||||||
|
leaveStatus
|
||||||
} from '@fastgpt/global/support/user/team/constant';
|
} from '@fastgpt/global/support/user/team/constant';
|
||||||
|
|
||||||
export async function getTeamInfoByTmbId({
|
async function getTeam(match: Record<string, any>): Promise<TeamItemType> {
|
||||||
tmbId,
|
|
||||||
userId
|
|
||||||
}: {
|
|
||||||
tmbId?: string;
|
|
||||||
userId?: string;
|
|
||||||
}): Promise<TeamItemType> {
|
|
||||||
if (!tmbId && !userId) {
|
|
||||||
return Promise.reject('tmbId or userId is required');
|
|
||||||
}
|
|
||||||
|
|
||||||
const db = connectionMongo?.connection?.db;
|
const db = connectionMongo?.connection?.db;
|
||||||
|
|
||||||
const TeamMember = db.collection(TeamMemberCollectionName);
|
const TeamMember = db.collection(TeamMemberCollectionName);
|
||||||
|
|
||||||
const results = await TeamMember.aggregate([
|
const results = await TeamMember.aggregate([
|
||||||
{
|
{
|
||||||
$match: tmbId
|
$match: match
|
||||||
? {
|
|
||||||
_id: new Types.ObjectId(tmbId)
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
userId: new Types.ObjectId(userId),
|
|
||||||
defaultTeam: true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
$lookup: {
|
$lookup: {
|
||||||
from: TeamCollectionName, // 关联的集合名
|
from: TeamCollectionName,
|
||||||
localField: 'teamId', // TeamMember 集合中用于关联的字段
|
localField: 'teamId',
|
||||||
foreignField: '_id', // Team 集合中用于关联的字段
|
foreignField: '_id',
|
||||||
as: 'team' // 查询结果中的字段名,存放关联查询的结果
|
as: 'team'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
$unwind: '$team' // 将查询结果中的 team 字段展开,变成一个对象
|
$unwind: '$team'
|
||||||
}
|
}
|
||||||
]).toArray();
|
]).toArray();
|
||||||
const tmb = results[0];
|
const tmb = results[0];
|
||||||
|
|
||||||
if (!tmb) {
|
if (!tmb) {
|
||||||
return Promise.reject('team not exist');
|
return Promise.reject('member not exist');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
userId: String(tmb.userId),
|
userId: String(tmb.userId),
|
||||||
teamId: String(tmb.teamId),
|
teamId: String(tmb.teamId),
|
||||||
teamName: tmb.team.name,
|
teamName: tmb.team.name,
|
||||||
|
memberName: tmb.name,
|
||||||
avatar: tmb.team.avatar,
|
avatar: tmb.team.avatar,
|
||||||
balance: tmb.team.balance,
|
balance: tmb.team.balance,
|
||||||
tmbId: String(tmb._id),
|
tmbId: String(tmb._id),
|
||||||
@ -65,11 +50,31 @@ export async function getTeamInfoByTmbId({
|
|||||||
maxSize: tmb.team.maxSize
|
maxSize: tmb.team.maxSize
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getTeamInfoByTmbId({ tmbId }: { tmbId: string }) {
|
||||||
|
if (!tmbId) {
|
||||||
|
return Promise.reject('tmbId or userId is required');
|
||||||
|
}
|
||||||
|
return getTeam({
|
||||||
|
_id: new Types.ObjectId(tmbId),
|
||||||
|
status: leaveStatus
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getUserDefaultTeam({ userId }: { userId: string }) {
|
||||||
|
if (!userId) {
|
||||||
|
return Promise.reject('tmbId or userId is required');
|
||||||
|
}
|
||||||
|
return getTeam({
|
||||||
|
userId: new Types.ObjectId(userId),
|
||||||
|
defaultTeam: true
|
||||||
|
});
|
||||||
|
}
|
||||||
export async function createDefaultTeam({
|
export async function createDefaultTeam({
|
||||||
userId,
|
userId,
|
||||||
teamName = 'My Team',
|
teamName = 'My Team',
|
||||||
avatar = '/icon/logo.svg',
|
avatar = '/icon/logo.svg',
|
||||||
balance = 0,
|
balance,
|
||||||
maxSize = 5
|
maxSize = 5
|
||||||
}: {
|
}: {
|
||||||
userId: string;
|
userId: string;
|
||||||
@ -103,6 +108,7 @@ export async function createDefaultTeam({
|
|||||||
await TeamMember.insertOne({
|
await TeamMember.insertOne({
|
||||||
teamId: insertedId,
|
teamId: insertedId,
|
||||||
userId,
|
userId,
|
||||||
|
name: 'Owner',
|
||||||
role: TeamMemberRoleEnum.owner,
|
role: TeamMemberRoleEnum.owner,
|
||||||
status: TeamMemberStatusEnum.active,
|
status: TeamMemberStatusEnum.active,
|
||||||
createTime: new Date(),
|
createTime: new Date(),
|
||||||
@ -116,7 +122,7 @@ export async function createDefaultTeam({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
$set: {
|
$set: {
|
||||||
balance,
|
...(balance !== undefined && { balance }),
|
||||||
maxSize
|
maxSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,7 @@ const BillSchema = new Schema({
|
|||||||
default: () => new Date()
|
default: () => new Date()
|
||||||
},
|
},
|
||||||
total: {
|
total: {
|
||||||
|
// 1 * PRICE_SCALE
|
||||||
type: Number,
|
type: Number,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
|||||||
42
pnpm-lock.yaml
generated
42
pnpm-lock.yaml
generated
@ -51,6 +51,9 @@ importers:
|
|||||||
encoding:
|
encoding:
|
||||||
specifier: ^0.1.13
|
specifier: ^0.1.13
|
||||||
version: registry.npmmirror.com/encoding@0.1.13
|
version: registry.npmmirror.com/encoding@0.1.13
|
||||||
|
js-tiktoken:
|
||||||
|
specifier: ^1.0.7
|
||||||
|
version: registry.npmmirror.com/js-tiktoken@1.0.7
|
||||||
openai:
|
openai:
|
||||||
specifier: ^4.16.1
|
specifier: ^4.16.1
|
||||||
version: registry.npmmirror.com/openai@4.16.1(encoding@0.1.13)
|
version: registry.npmmirror.com/openai@4.16.1(encoding@0.1.13)
|
||||||
@ -200,12 +203,6 @@ importers:
|
|||||||
immer:
|
immer:
|
||||||
specifier: ^9.0.19
|
specifier: ^9.0.19
|
||||||
version: registry.npmmirror.com/immer@9.0.21
|
version: registry.npmmirror.com/immer@9.0.21
|
||||||
js-cookie:
|
|
||||||
specifier: ^3.0.5
|
|
||||||
version: registry.npmmirror.com/js-cookie@3.0.5
|
|
||||||
js-tiktoken:
|
|
||||||
specifier: ^1.0.7
|
|
||||||
version: registry.npmmirror.com/js-tiktoken@1.0.7
|
|
||||||
jschardet:
|
jschardet:
|
||||||
specifier: ^3.0.0
|
specifier: ^3.0.0
|
||||||
version: registry.npmmirror.com/jschardet@3.0.0
|
version: registry.npmmirror.com/jschardet@3.0.0
|
||||||
@ -242,9 +239,6 @@ importers:
|
|||||||
papaparse:
|
papaparse:
|
||||||
specifier: ^5.4.1
|
specifier: ^5.4.1
|
||||||
version: registry.npmmirror.com/papaparse@5.4.1
|
version: registry.npmmirror.com/papaparse@5.4.1
|
||||||
pg-query-stream:
|
|
||||||
specifier: ^4.5.3
|
|
||||||
version: registry.npmmirror.com/pg-query-stream@4.5.3(pg@8.11.3)
|
|
||||||
react:
|
react:
|
||||||
specifier: 18.2.0
|
specifier: 18.2.0
|
||||||
version: registry.npmmirror.com/react@18.2.0
|
version: registry.npmmirror.com/react@18.2.0
|
||||||
@ -8721,13 +8715,6 @@ packages:
|
|||||||
set-function-name: registry.npmmirror.com/set-function-name@2.0.1
|
set-function-name: registry.npmmirror.com/set-function-name@2.0.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
registry.npmmirror.com/js-cookie@3.0.5:
|
|
||||||
resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/js-cookie/-/js-cookie-3.0.5.tgz}
|
|
||||||
name: js-cookie
|
|
||||||
version: 3.0.5
|
|
||||||
engines: {node: '>=14'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
registry.npmmirror.com/js-sdsl@4.4.2:
|
registry.npmmirror.com/js-sdsl@4.4.2:
|
||||||
resolution: {integrity: sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/js-sdsl/-/js-sdsl-4.4.2.tgz}
|
resolution: {integrity: sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/js-sdsl/-/js-sdsl-4.4.2.tgz}
|
||||||
name: js-sdsl
|
name: js-sdsl
|
||||||
@ -10629,17 +10616,6 @@ packages:
|
|||||||
version: 2.6.2
|
version: 2.6.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
registry.npmmirror.com/pg-cursor@2.10.3(pg@8.11.3):
|
|
||||||
resolution: {integrity: sha512-rDyBVoqPVnx/PTmnwQAYgusSeAKlTL++gmpf5klVK+mYMFEqsOc6VHHZnPKc/4lOvr4r6fiMuoxSFuBF1dx4FQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/pg-cursor/-/pg-cursor-2.10.3.tgz}
|
|
||||||
id: registry.npmmirror.com/pg-cursor/2.10.3
|
|
||||||
name: pg-cursor
|
|
||||||
version: 2.10.3
|
|
||||||
peerDependencies:
|
|
||||||
pg: ^8
|
|
||||||
dependencies:
|
|
||||||
pg: registry.npmmirror.com/pg@8.11.3
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
registry.npmmirror.com/pg-int8@1.0.1:
|
registry.npmmirror.com/pg-int8@1.0.1:
|
||||||
resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/pg-int8/-/pg-int8-1.0.1.tgz}
|
resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/pg-int8/-/pg-int8-1.0.1.tgz}
|
||||||
name: pg-int8
|
name: pg-int8
|
||||||
@ -10669,18 +10645,6 @@ packages:
|
|||||||
name: pg-protocol
|
name: pg-protocol
|
||||||
version: 1.6.0
|
version: 1.6.0
|
||||||
|
|
||||||
registry.npmmirror.com/pg-query-stream@4.5.3(pg@8.11.3):
|
|
||||||
resolution: {integrity: sha512-ufa94r/lHJdjAm3+zPZEO0gXAmCb4tZPaOt7O76mjcxdL/HxwTuryy76km+u0odBBgtfdKFYq/9XGfiYeQF0yA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/pg-query-stream/-/pg-query-stream-4.5.3.tgz}
|
|
||||||
id: registry.npmmirror.com/pg-query-stream/4.5.3
|
|
||||||
name: pg-query-stream
|
|
||||||
version: 4.5.3
|
|
||||||
peerDependencies:
|
|
||||||
pg: ^8
|
|
||||||
dependencies:
|
|
||||||
pg: registry.npmmirror.com/pg@8.11.3
|
|
||||||
pg-cursor: registry.npmmirror.com/pg-cursor@2.10.3(pg@8.11.3)
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
registry.npmmirror.com/pg-types@2.2.0:
|
registry.npmmirror.com/pg-types@2.2.0:
|
||||||
resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/pg-types/-/pg-types-2.2.0.tgz}
|
resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/pg-types/-/pg-types-2.2.0.tgz}
|
||||||
name: pg-types
|
name: pg-types
|
||||||
|
|||||||
@ -8,5 +8,8 @@ module.exports = {
|
|||||||
defaultLocale: 'zh',
|
defaultLocale: 'zh',
|
||||||
locales: ['en', 'zh', 'zh-Hans', 'zh-CN'],
|
locales: ['en', 'zh', 'zh-Hans', 'zh-CN'],
|
||||||
localeDetection: false
|
localeDetection: false
|
||||||
}
|
},
|
||||||
|
localePath:
|
||||||
|
typeof window === 'undefined' ? require('path').resolve('./public/locales') : '/locales',
|
||||||
|
reloadOnPrerender: process.env.NODE_ENV === 'development'
|
||||||
};
|
};
|
||||||
|
|||||||
@ -33,8 +33,6 @@
|
|||||||
"hyperdown": "^2.4.29",
|
"hyperdown": "^2.4.29",
|
||||||
"i18next": "^22.5.1",
|
"i18next": "^22.5.1",
|
||||||
"immer": "^9.0.19",
|
"immer": "^9.0.19",
|
||||||
"js-cookie": "^3.0.5",
|
|
||||||
"js-tiktoken": "^1.0.7",
|
|
||||||
"jschardet": "^3.0.0",
|
"jschardet": "^3.0.0",
|
||||||
"jsdom": "^22.1.0",
|
"jsdom": "^22.1.0",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
@ -47,7 +45,6 @@
|
|||||||
"next-i18next": "^13.3.0",
|
"next-i18next": "^13.3.0",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"papaparse": "^5.4.1",
|
"papaparse": "^5.4.1",
|
||||||
"pg-query-stream": "^4.5.3",
|
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-day-picker": "^8.7.1",
|
"react-day-picker": "^8.7.1",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
### Fast GPT V4.6
|
### Fast GPT V4.6
|
||||||
|
|
||||||
1. 新增 - 团队空间试用版。
|
1. 新增 - 团队空间
|
||||||
2. 新增 - OpenAI语音播报。
|
2. 新增 - 多路向量(多个向量映射一组数据)
|
||||||
3. [知识库结构详解](https://doc.fastgpt.in/docs/use-cases/datasetengine/)
|
3. 新增 - tts语音
|
||||||
4. [知识库提示词详解](https://doc.fastgpt.in/docs/use-cases/ai_settings/#引用模板--引用提示词)
|
4. 线上环境新增 - ReRank向量召回,提高召回精度
|
||||||
5. [使用文档](https://doc.fastgpt.in/docs/intro/)
|
5. 优化 - 知识库导出,可直接触发流下载,无需等待转圈圈
|
||||||
6. [点击查看高级编排介绍文档](https://doc.fastgpt.in/docs/workflow)
|
6. [知识库结构详解](https://doc.fastgpt.in/docs/use-cases/datasetengine/)
|
||||||
7. [点击查看商业版](https://doc.fastgpt.in/docs/commercial/)
|
7. [知识库提示词详解](https://doc.fastgpt.in/docs/use-cases/ai_settings/#引用模板--引用提示词)
|
||||||
|
8. [使用文档](https://doc.fastgpt.in/docs/intro/)
|
||||||
|
9. [点击查看高级编排介绍文档](https://doc.fastgpt.in/docs/workflow)
|
||||||
|
10. [点击查看商业版](https://doc.fastgpt.in/docs/commercial/)
|
||||||
|
|||||||
@ -292,17 +292,32 @@
|
|||||||
"Select One Collection To Store": "Select the collection to store"
|
"Select One Collection To Store": "Select the collection to store"
|
||||||
},
|
},
|
||||||
"data": {
|
"data": {
|
||||||
|
"Add Index": "Add Index",
|
||||||
"Can not delete tip": "No modification permission",
|
"Can not delete tip": "No modification permission",
|
||||||
"Can not edit": "No edit permission",
|
"Can not edit": "No edit permission",
|
||||||
|
"Custom Index Number": "Custom index{{number}}",
|
||||||
|
"Default Index": "Default Index",
|
||||||
|
"Delete Success Tip": "",
|
||||||
"Delete Tip": "Confirm to delete the data?",
|
"Delete Tip": "Confirm to delete the data?",
|
||||||
"File import": "File Import",
|
"File import": "File Import",
|
||||||
|
"Index Edit": "Data Index",
|
||||||
|
"Index Placeholder": "Enter the index text content",
|
||||||
"Input Data": "Import Data",
|
"Input Data": "Import Data",
|
||||||
"Input Success Tip": "Succeeded in importing data",
|
"Input Success Tip": "Succeeded in importing data",
|
||||||
"Update Data": "Update Data",
|
"Update Data": "Update Data",
|
||||||
"Update Success Tip": "Update data successfully"
|
"Update Success Tip": "Update data successfully",
|
||||||
|
"edit": {
|
||||||
|
"Content": "Content",
|
||||||
|
"Course": "Document",
|
||||||
|
"Delete": "Delete",
|
||||||
|
"Index": "Index({{amount}})"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"deleteDatasetTips": "Are you sure to delete the knowledge base? Data cannot be recovered after deletion, please confirm!",
|
"deleteDatasetTips": "Are you sure to delete the knowledge base? Data cannot be recovered after deletion, please confirm!",
|
||||||
"deleteFolderTips": "Are you sure to delete this folder and all the knowledge bases it contains? Data cannot be recovered after deletion, please confirm!"
|
"deleteFolderTips": "Are you sure to delete this folder and all the knowledge bases it contains? Data cannot be recovered after deletion, please confirm!",
|
||||||
|
"test": {
|
||||||
|
"noResult": "Search results are empty"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"team": {
|
"team": {
|
||||||
@ -461,9 +476,11 @@
|
|||||||
"Bill Detail": "Bill Detail",
|
"Bill Detail": "Bill Detail",
|
||||||
"Change": "Change",
|
"Change": "Change",
|
||||||
"Copy invite url": "Copy invitation link",
|
"Copy invite url": "Copy invitation link",
|
||||||
|
"Edit name": "Click to modify nickname",
|
||||||
"Invite Url": "Invite Url",
|
"Invite Url": "Invite Url",
|
||||||
"Invite url tip": "Friends who register through this link will be permanently bound to you, and you will get a certain balance reward when they recharge. In addition, when friends register with their mobile phone number, you will get 5 yuan reward immediately.",
|
"Invite url tip": "Friends who register through this link will be permanently bound to you, and you will get a certain balance reward when they recharge. In addition, when friends register with their mobile phone number, you will get 5 yuan reward immediately.",
|
||||||
"Language": "Language",
|
"Language": "Language",
|
||||||
|
"Member Name": "Name",
|
||||||
"Notice": "Notice",
|
"Notice": "Notice",
|
||||||
"Old password is error": "Old password is error",
|
"Old password is error": "Old password is error",
|
||||||
"OpenAI Account Setting": "OpenAI Account Setting",
|
"OpenAI Account Setting": "OpenAI Account Setting",
|
||||||
@ -513,12 +530,15 @@
|
|||||||
"Leave Team Failed": "Leave Team Failed",
|
"Leave Team Failed": "Leave Team Failed",
|
||||||
"Manage": "Team Manage",
|
"Manage": "Team Manage",
|
||||||
"Member": "Member",
|
"Member": "Member",
|
||||||
|
"Member Name": "Member",
|
||||||
"Over Max Member Tip": "Team max {{max}} people",
|
"Over Max Member Tip": "Team max {{max}} people",
|
||||||
"Personal Team": "Personal",
|
"Personal Team": "Personal",
|
||||||
"Processing invitations": "Processing invitations",
|
"Processing invitations": "Processing invitations",
|
||||||
"Processing invitations Tips": "You have {{amount}} of team invitations that need to be processed",
|
"Processing invitations Tips": "You have {{amount}} of team invitations that need to be processed",
|
||||||
"Reinvite": "Reinvite",
|
"Reinvite": "Reinvite",
|
||||||
"Remove Member Confirm Tip": "Confirm to move {{username}} off the team",
|
"Remove Member Confirm Tip": "Are you sure you want to move {{username}} off the team? All its resources are transferred to the team creator's account.",
|
||||||
|
"Remove Member Failed": "Removing a team member failed",
|
||||||
|
"Remove Member Success": "Removing a team member succeeded",
|
||||||
"Remove Member Tip": "Move out team",
|
"Remove Member Tip": "Move out team",
|
||||||
"Role": "Role",
|
"Role": "Role",
|
||||||
"Select Team": "Select Team",
|
"Select Team": "Select Team",
|
||||||
|
|||||||
@ -292,17 +292,32 @@
|
|||||||
"Select One Collection To Store": "选择一个文件进行存储"
|
"Select One Collection To Store": "选择一个文件进行存储"
|
||||||
},
|
},
|
||||||
"data": {
|
"data": {
|
||||||
|
"Add Index": "新增自定义索引",
|
||||||
"Can not delete tip": "无修改权限",
|
"Can not delete tip": "无修改权限",
|
||||||
"Can not edit": "无编辑权限",
|
"Can not edit": "无编辑权限",
|
||||||
|
"Custom Index Number": "自定义索引{{number}}",
|
||||||
|
"Default Index": "默认索引",
|
||||||
|
"Delete Success Tip": "删除成功",
|
||||||
"Delete Tip": "确认删除该条数据?",
|
"Delete Tip": "确认删除该条数据?",
|
||||||
"File import": "文件导入",
|
"File import": "文件导入",
|
||||||
|
"Index Edit": "数据索引",
|
||||||
|
"Index Placeholder": "输入索引文本内容",
|
||||||
"Input Data": "导入新数据",
|
"Input Data": "导入新数据",
|
||||||
"Input Success Tip": "导入数据成功",
|
"Input Success Tip": "导入数据成功",
|
||||||
"Update Data": "更新数据",
|
"Update Data": "更新数据",
|
||||||
"Update Success Tip": "更新数据成功"
|
"Update Success Tip": "更新数据成功",
|
||||||
|
"edit": {
|
||||||
|
"Content": "数据内容",
|
||||||
|
"Course": "说明文档",
|
||||||
|
"Delete": "删除数据",
|
||||||
|
"Index": "数据索引({{amount}})"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"deleteDatasetTips": "确认删除该知识库?删除后数据无法恢复,请确认!",
|
"deleteDatasetTips": "确认删除该知识库?删除后数据无法恢复,请确认!",
|
||||||
"deleteFolderTips": "确认删除该文件夹及其包含的所有知识库?删除后数据无法恢复,请确认!"
|
"deleteFolderTips": "确认删除该文件夹及其包含的所有知识库?删除后数据无法恢复,请确认!",
|
||||||
|
"test": {
|
||||||
|
"noResult": "搜索结果为空"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"team": {
|
"team": {
|
||||||
@ -461,9 +476,11 @@
|
|||||||
"Bill Detail": "账单详情",
|
"Bill Detail": "账单详情",
|
||||||
"Change": "变更",
|
"Change": "变更",
|
||||||
"Copy invite url": "复制邀请链接",
|
"Copy invite url": "复制邀请链接",
|
||||||
|
"Edit name": "点击修改昵称",
|
||||||
"Invite Url": "邀请链接",
|
"Invite Url": "邀请链接",
|
||||||
"Invite url tip": "通过该链接注册的好友将永久与你绑定,其充值时你会获得一定余额奖励。\n此外,好友使用手机号注册时,你将立即获得 5 元奖励。\n奖励会发送到您的默认团队中。",
|
"Invite url tip": "通过该链接注册的好友将永久与你绑定,其充值时你会获得一定余额奖励。\n此外,好友使用手机号注册时,你将立即获得 5 元奖励。\n奖励会发送到您的默认团队中。",
|
||||||
"Language": "语言",
|
"Language": "语言",
|
||||||
|
"Member Name": "昵称",
|
||||||
"Notice": "通知",
|
"Notice": "通知",
|
||||||
"Old password is error": "旧密码错误",
|
"Old password is error": "旧密码错误",
|
||||||
"OpenAI Account Setting": "OpenAI 账号配置",
|
"OpenAI Account Setting": "OpenAI 账号配置",
|
||||||
@ -513,12 +530,15 @@
|
|||||||
"Leave Team Failed": "离开团队异常",
|
"Leave Team Failed": "离开团队异常",
|
||||||
"Manage": "团队管理",
|
"Manage": "团队管理",
|
||||||
"Member": "成员",
|
"Member": "成员",
|
||||||
|
"Member Name": "成员名",
|
||||||
"Over Max Member Tip": "团队最多{{max}}人",
|
"Over Max Member Tip": "团队最多{{max}}人",
|
||||||
"Personal Team": "个人团队",
|
"Personal Team": "个人团队",
|
||||||
"Processing invitations": "处理邀请",
|
"Processing invitations": "处理邀请",
|
||||||
"Processing invitations Tips": "你有{{amount}}个需要处理的团队邀请",
|
"Processing invitations Tips": "你有{{amount}}个需要处理的团队邀请",
|
||||||
"Reinvite": "重新邀请",
|
"Reinvite": "重新邀请",
|
||||||
"Remove Member Confirm Tip": "确认将 {{username}} 移出团队?",
|
"Remove Member Confirm Tip": "确认将 {{username}} 移出团队?其所有资源将转让到团队创建者的账户内。",
|
||||||
|
"Remove Member Failed": "移除团队成员异常",
|
||||||
|
"Remove Member Success": "移除团队成员成功",
|
||||||
"Remove Member Tip": "移出团队",
|
"Remove Member Tip": "移出团队",
|
||||||
"Role": "身份",
|
"Role": "身份",
|
||||||
"Select Team": "团队选择",
|
"Select Team": "团队选择",
|
||||||
|
|||||||
@ -10,13 +10,12 @@ import InputDataModal, {
|
|||||||
type InputDataType
|
type InputDataType
|
||||||
} from '@/pages/dataset/detail/components/InputDataModal';
|
} from '@/pages/dataset/detail/components/InputDataModal';
|
||||||
import MyModal from '../MyModal';
|
import MyModal from '../MyModal';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type';
|
import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type';
|
||||||
import MyTooltip from '../MyTooltip';
|
import MyTooltip from '../MyTooltip';
|
||||||
import NextLink from 'next/link';
|
import NextLink from 'next/link';
|
||||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
|
||||||
|
|
||||||
const QuoteModal = ({
|
const QuoteModal = ({
|
||||||
rawSearch = [],
|
rawSearch = [],
|
||||||
@ -29,10 +28,9 @@ const QuoteModal = ({
|
|||||||
const { isPc } = useSystemStore();
|
const { isPc } = useSystemStore();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { userInfo } = useUserStore();
|
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { setIsLoading, Loading } = useLoading();
|
const { setIsLoading, Loading } = useLoading();
|
||||||
const [editInputData, setEditInputData] = useState<InputDataType & { datasetId: string }>();
|
const [editInputData, setEditInputData] = useState<InputDataType & { collectionId: string }>();
|
||||||
|
|
||||||
const isShare = useMemo(() => router.pathname === '/chat/share', [router.pathname]);
|
const isShare = useMemo(() => router.pathname === '/chat/share', [router.pathname]);
|
||||||
|
|
||||||
@ -99,7 +97,7 @@ const QuoteModal = ({
|
|||||||
color={'black'}
|
color={'black'}
|
||||||
sourceName={item.sourceName}
|
sourceName={item.sourceName}
|
||||||
sourceId={item.sourceId}
|
sourceId={item.sourceId}
|
||||||
addr={!isShare}
|
canView={!isShare}
|
||||||
/>
|
/>
|
||||||
<Box flex={1} />
|
<Box flex={1} />
|
||||||
{!isShare && (
|
{!isShare && (
|
||||||
@ -131,7 +129,7 @@ const QuoteModal = ({
|
|||||||
<MyTooltip label={t('core.dataset.Quote Length')}>
|
<MyTooltip label={t('core.dataset.Quote Length')}>
|
||||||
<Flex alignItems={'center'}>
|
<Flex alignItems={'center'}>
|
||||||
<MyIcon name="common/text/t" w={'14px'} mr={1} color={'myGray.500'} />
|
<MyIcon name="common/text/t" w={'14px'} mr={1} color={'myGray.500'} />
|
||||||
{item.q.length + item.a.length}
|
{item.q.length + (item.a?.length || 0)}
|
||||||
</Flex>
|
</Flex>
|
||||||
</MyTooltip>
|
</MyTooltip>
|
||||||
{!isShare && item.score && (
|
{!isShare && item.score && (
|
||||||
@ -183,7 +181,6 @@ const QuoteModal = ({
|
|||||||
</MyModal>
|
</MyModal>
|
||||||
{editInputData && editInputData.id && (
|
{editInputData && editInputData.id && (
|
||||||
<InputDataModal
|
<InputDataModal
|
||||||
canWrite={userInfo?.team?.canWrite || false}
|
|
||||||
onClose={() => setEditInputData(undefined)}
|
onClose={() => setEditInputData(undefined)}
|
||||||
onSuccess={() => {
|
onSuccess={() => {
|
||||||
console.log('更新引用成功');
|
console.log('更新引用成功');
|
||||||
@ -191,8 +188,8 @@ const QuoteModal = ({
|
|||||||
onDelete={() => {
|
onDelete={() => {
|
||||||
console.log('删除引用成功');
|
console.log('删除引用成功');
|
||||||
}}
|
}}
|
||||||
datasetId={editInputData.datasetId}
|
defaultValue={editInputData}
|
||||||
defaultValues={editInputData}
|
collectionId={editInputData.collectionId}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import React, { useMemo, useState } from 'react';
|
|||||||
import type { ChatHistoryItemResType } from '@fastgpt/global/core/chat/api.d';
|
import type { ChatHistoryItemResType } from '@fastgpt/global/core/chat/api.d';
|
||||||
import type { ChatItemType } from '@fastgpt/global/core/chat/type';
|
import type { ChatItemType } from '@fastgpt/global/core/chat/type';
|
||||||
import { Flex, BoxProps, useDisclosure, Image, useTheme } from '@chakra-ui/react';
|
import { Flex, BoxProps, useDisclosure, Image, useTheme } from '@chakra-ui/react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||||
import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type';
|
import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { ModalBody, useTheme, ModalFooter, Button, Box, Card, Flex, Grid } from '@chakra-ui/react';
|
import { ModalBody, useTheme, ModalFooter, Button, Box, Card, Flex, Grid } from '@chakra-ui/react';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import Avatar from '../Avatar';
|
import Avatar from '../Avatar';
|
||||||
@ -8,6 +8,7 @@ import DatasetSelectModal, { useDatasetSelect } from '@/components/core/dataset/
|
|||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { AdminFbkType } from '@fastgpt/global/core/chat/type.d';
|
import { AdminFbkType } from '@fastgpt/global/core/chat/type.d';
|
||||||
import SelectCollections from '@/web/core/dataset/components/SelectCollections';
|
import SelectCollections from '@/web/core/dataset/components/SelectCollections';
|
||||||
|
import { getDefaultIndex } from '@fastgpt/global/core/dataset/utils';
|
||||||
|
|
||||||
const InputDataModal = dynamic(() => import('@/pages/dataset/detail/components/InputDataModal'));
|
const InputDataModal = dynamic(() => import('@/pages/dataset/detail/components/InputDataModal'));
|
||||||
|
|
||||||
@ -163,15 +164,13 @@ const SelectMarkCollection = ({
|
|||||||
{adminMarkData.datasetId && adminMarkData.collectionId && (
|
{adminMarkData.datasetId && adminMarkData.collectionId && (
|
||||||
<InputDataModal
|
<InputDataModal
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
datasetId={adminMarkData.datasetId}
|
collectionId={adminMarkData.collectionId}
|
||||||
defaultValues={{
|
defaultValue={{
|
||||||
id: adminMarkData.dataId,
|
id: adminMarkData.dataId,
|
||||||
collectionId: adminMarkData.collectionId,
|
|
||||||
sourceName: '手动标注',
|
|
||||||
q: adminMarkData.q,
|
q: adminMarkData.q,
|
||||||
a: adminMarkData.a
|
a: adminMarkData.a,
|
||||||
|
indexes: [getDefaultIndex({ dataId: `${Date.now()}` })]
|
||||||
}}
|
}}
|
||||||
canWrite
|
|
||||||
onSuccess={(data) => {
|
onSuccess={(data) => {
|
||||||
if (!data.q || !adminMarkData.datasetId || !adminMarkData.collectionId || !data.id) {
|
if (!data.q || !adminMarkData.datasetId || !adminMarkData.collectionId || !data.id) {
|
||||||
return onClose();
|
return onClose();
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { Box, useTheme, Flex, Image } from '@chakra-ui/react';
|
import { Box, useTheme, Flex, Image } from '@chakra-ui/react';
|
||||||
import type { ChatHistoryItemResType } from '@fastgpt/global/core/chat/api.d';
|
import type { ChatHistoryItemResType } from '@fastgpt/global/core/chat/api.d';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { ModuleTemplatesFlat } from '@/constants/flow/ModuleTemplate';
|
import { ModuleTemplatesFlat } from '@/constants/flow/ModuleTemplate';
|
||||||
import Tabs from '../Tabs';
|
import Tabs from '../Tabs';
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,7 @@ import {
|
|||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { feConfigs } from '@/web/common/system/staticData';
|
import { feConfigs } from '@/web/common/system/staticData';
|
||||||
import { eventBus } from '@/web/common/utils/eventbus';
|
import { eventBus } from '@/web/common/utils/eventbus';
|
||||||
import { adaptChat2GptMessages } from '@/utils/common/adapt/message';
|
import { adaptChat2GptMessages } from '@fastgpt/global/core/chat/adapt';
|
||||||
import { useMarkdown } from '@/web/common/hooks/useMarkdown';
|
import { useMarkdown } from '@/web/common/hooks/useMarkdown';
|
||||||
import { ModuleItemType } from '@fastgpt/global/core/module/type.d';
|
import { ModuleItemType } from '@fastgpt/global/core/module/type.d';
|
||||||
import { VariableInputEnum } from '@/constants/app';
|
import { VariableInputEnum } from '@/constants/app';
|
||||||
@ -41,7 +41,7 @@ import { htmlTemplate } from '@/constants/common';
|
|||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||||
import { TaskResponseKeyEnum } from '@fastgpt/global/core/chat/constants';
|
import { TaskResponseKeyEnum } from '@fastgpt/global/core/chat/constants';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { customAlphabet } from 'nanoid';
|
import { customAlphabet } from 'nanoid';
|
||||||
import { adminUpdateChatFeedback, userUpdateChatFeedback } from '@/web/core/chat/api';
|
import { adminUpdateChatFeedback, userUpdateChatFeedback } from '@/web/core/chat/api';
|
||||||
import type { AdminMarkType } from './SelectMarkCollection';
|
import type { AdminMarkType } from './SelectMarkCollection';
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Button, ModalFooter, ModalBody } from '@chakra-ui/react';
|
import { Button, ModalFooter, ModalBody } from '@chakra-ui/react';
|
||||||
import MyModal from '../MyModal';
|
import MyModal from '../MyModal';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import Markdown from '../Markdown';
|
import Markdown from '../Markdown';
|
||||||
|
|
||||||
const md = `
|
const md = `
|
||||||
|
|||||||
@ -1,48 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
import { Menu, MenuButton, MenuItem, MenuList, MenuButtonProps } from '@chakra-ui/react';
|
|
||||||
import { getLangStore, LangEnum, setLangStore, langMap } from '@/web/common/utils/i18n';
|
|
||||||
import MyIcon from '@/components/Icon';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { useRouter } from 'next/router';
|
|
||||||
|
|
||||||
const Language = (props: MenuButtonProps) => {
|
|
||||||
const router = useRouter();
|
|
||||||
const { i18n } = useTranslation();
|
|
||||||
|
|
||||||
const [language, setLanguage] = useState<`${LangEnum}`>(getLangStore());
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Menu autoSelect={false}>
|
|
||||||
<MenuButton
|
|
||||||
{...props}
|
|
||||||
sx={{
|
|
||||||
'& span': {
|
|
||||||
flex: 0
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MyIcon name={langMap[language].icon as any} w={['18px', '22px']} />
|
|
||||||
</MenuButton>
|
|
||||||
<MenuList w="max-content" minW="120px">
|
|
||||||
{Object.entries(langMap).map(([key, lang]) => (
|
|
||||||
<MenuItem
|
|
||||||
key={key}
|
|
||||||
display="flex"
|
|
||||||
alignItems="center"
|
|
||||||
onClick={() => {
|
|
||||||
const lang = key as `${LangEnum}`;
|
|
||||||
setLangStore(lang);
|
|
||||||
setLanguage(lang);
|
|
||||||
i18n?.changeLanguage?.(lang);
|
|
||||||
router.reload();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{lang.label}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</MenuList>
|
|
||||||
</Menu>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default React.memo(Language);
|
|
||||||
@ -2,7 +2,7 @@ import React, { useMemo } from 'react';
|
|||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { Flex, Box } from '@chakra-ui/react';
|
import { Flex, Box } from '@chakra-ui/react';
|
||||||
import { useChatStore } from '@/web/core/chat/storeChat';
|
import { useChatStore } from '@/web/core/chat/storeChat';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import Badge from '../Badge';
|
import Badge from '../Badge';
|
||||||
import MyIcon from '../Icon';
|
import MyIcon from '../Icon';
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { Box, Grid } from '@chakra-ui/react';
|
import { Box, Grid } from '@chakra-ui/react';
|
||||||
import type { GridProps } from '@chakra-ui/react';
|
import type { GridProps } from '@chakra-ui/react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
interface Props extends GridProps {
|
interface Props extends GridProps {
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import MyIcon from '@/components/Icon';
|
|||||||
import { Box, Flex } from '@chakra-ui/react';
|
import { Box, Flex } from '@chakra-ui/react';
|
||||||
import { ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type';
|
import { ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type';
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
|
|
||||||
const ParentPaths = (props: {
|
const ParentPaths = (props: {
|
||||||
paths?: ParentTreePathItemType[];
|
paths?: ParentTreePathItemType[];
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import {
|
|||||||
useTheme
|
useTheme
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { useToast } from '@/web/common/hooks/useToast';
|
import { useToast } from '@/web/common/hooks/useToast';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
|
|
||||||
type Props = BoxProps & { defaultValues: string[]; onUpdate: (e: string[]) => void };
|
type Props = BoxProps & { defaultValues: string[]; onUpdate: (e: string[]) => void };
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { getDatasets, getDatasetPaths } from '@/web/core/dataset/api';
|
|||||||
import MyModal from '@/components/MyModal';
|
import MyModal from '@/components/MyModal';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import React, { Dispatch, useMemo, useState } from 'react';
|
import React, { Dispatch, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||||
import { Box, Flex, ModalHeader } from '@chakra-ui/react';
|
import { Box, Flex, ModalHeader } from '@chakra-ui/react';
|
||||||
import MyIcon from '@/components/Icon';
|
import MyIcon from '@/components/Icon';
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import React, { useEffect, useMemo, useState } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import MyModal from '@/components/MyModal';
|
import MyModal from '@/components/MyModal';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { EditFormType } from '@/web/core/app/basicSettings';
|
import { EditFormType } from '@/web/core/app/basicSettings';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@ -14,14 +14,14 @@ import {
|
|||||||
import Avatar from '@/components/Avatar';
|
import Avatar from '@/components/Avatar';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||||
import type { SelectedDatasetType } from '@/types/core/dataset';
|
import type { SelectedDatasetType } from '@fastgpt/global/core/module/api.d';
|
||||||
import { useToast } from '@/web/common/hooks/useToast';
|
import { useToast } from '@/web/common/hooks/useToast';
|
||||||
import MySlider from '@/components/Slider';
|
import MySlider from '@/components/Slider';
|
||||||
import MyTooltip from '@/components/MyTooltip';
|
import MyTooltip from '@/components/MyTooltip';
|
||||||
import MyModal from '@/components/MyModal';
|
import MyModal from '@/components/MyModal';
|
||||||
import MyIcon from '@/components/Icon';
|
import MyIcon from '@/components/Icon';
|
||||||
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constant';
|
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constant';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
|
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
|
||||||
import { feConfigs } from '@/web/common/system/staticData';
|
import { feConfigs } from '@/web/common/system/staticData';
|
||||||
import DatasetSelectContainer, { useDatasetSelect } from '@/components/core/dataset/SelectModal';
|
import DatasetSelectContainer, { useDatasetSelect } from '@/components/core/dataset/SelectModal';
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Textarea, Button, ModalBody, ModalFooter } from '@chakra-ui/react';
|
import { Textarea, Button, ModalBody, ModalFooter } from '@chakra-ui/react';
|
||||||
import MyModal from '@/components/MyModal';
|
import MyModal from '@/components/MyModal';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useToast } from '@/web/common/hooks/useToast';
|
import { useToast } from '@/web/common/hooks/useToast';
|
||||||
import { useFlowProviderStore } from './FlowProvider';
|
import { useFlowProviderStore } from './FlowProvider';
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import MyModal from '@/components/MyModal';
|
|||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import type { SelectAppItemType } from '@fastgpt/global/core/module/type';
|
import type { SelectAppItemType } from '@fastgpt/global/core/module/type';
|
||||||
import Avatar from '@/components/Avatar';
|
import Avatar from '@/components/Avatar';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useLoading } from '@/web/common/hooks/useLoading';
|
import { useLoading } from '@/web/common/hooks/useLoading';
|
||||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||||
import { useAppStore } from '@/web/core/app/store/useAppStore';
|
import { useAppStore } from '@/web/core/app/store/useAppStore';
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import Avatar from '@/components/Avatar';
|
|||||||
import { useFlowProviderStore } from './FlowProvider';
|
import { useFlowProviderStore } from './FlowProvider';
|
||||||
import { customAlphabet } from 'nanoid';
|
import { customAlphabet } from 'nanoid';
|
||||||
import { appModule2FlowNode } from '@/utils/adapt';
|
import { appModule2FlowNode } from '@/utils/adapt';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 6);
|
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 6);
|
||||||
import MyIcon from '@/components/Icon';
|
import MyIcon from '@/components/Icon';
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import { useForm } from 'react-hook-form';
|
|||||||
import MyModal from '@/components/MyModal';
|
import MyModal from '@/components/MyModal';
|
||||||
import Avatar from '@/components/Avatar';
|
import Avatar from '@/components/Avatar';
|
||||||
import { FlowNodeValTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
import { FlowNodeValTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import MySelect from '@/components/Select';
|
import MySelect from '@/components/Select';
|
||||||
|
|
||||||
const typeSelectList = [
|
const typeSelectList = [
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import Avatar from '@/components/Avatar';
|
|||||||
import type { FlowModuleItemType } from '@fastgpt/global/core/module/type.d';
|
import type { FlowModuleItemType } from '@fastgpt/global/core/module/type.d';
|
||||||
import MyTooltip from '@/components/MyTooltip';
|
import MyTooltip from '@/components/MyTooltip';
|
||||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useEditTitle } from '@/web/common/hooks/useEditTitle';
|
import { useEditTitle } from '@/web/common/hooks/useEditTitle';
|
||||||
import { useToast } from '@/web/common/hooks/useToast';
|
import { useToast } from '@/web/common/hooks/useToast';
|
||||||
import { useFlowProviderStore, onChangeNode } from '../../FlowProvider';
|
import { useFlowProviderStore, onChangeNode } from '../../FlowProvider';
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import {
|
|||||||
FlowNodeValTypeEnum,
|
FlowNodeValTypeEnum,
|
||||||
FlowNodeSpecialInputKeyEnum
|
FlowNodeSpecialInputKeyEnum
|
||||||
} from '@fastgpt/global/core/module/node/constant';
|
} from '@fastgpt/global/core/module/node/constant';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import SourceHandle from '../render/SourceHandle';
|
import SourceHandle from '../render/SourceHandle';
|
||||||
import MyTooltip from '@/components/MyTooltip';
|
import MyTooltip from '@/components/MyTooltip';
|
||||||
import { onChangeNode } from '../../FlowProvider';
|
import { onChangeNode } from '../../FlowProvider';
|
||||||
|
|||||||
@ -26,12 +26,12 @@ import MySlider from '@/components/Slider';
|
|||||||
import MyTooltip from '@/components/MyTooltip';
|
import MyTooltip from '@/components/MyTooltip';
|
||||||
import TargetHandle from './TargetHandle';
|
import TargetHandle from './TargetHandle';
|
||||||
import MyIcon from '@/components/Icon';
|
import MyIcon from '@/components/Icon';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { AIChatProps } from '@/types/core/aiChat';
|
import { AIChatProps } from '@/types/core/aiChat';
|
||||||
import { chatModelList } from '@/web/common/system/staticData';
|
import { chatModelList } from '@/web/common/system/staticData';
|
||||||
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
|
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
|
||||||
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
|
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
|
||||||
import { SelectedDatasetType } from '@/types/core/dataset';
|
import type { SelectedDatasetType } from '@fastgpt/global/core/module/api.d';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import type { LLMModelItemType } from '@fastgpt/global/core/ai/model.d';
|
import type { LLMModelItemType } from '@fastgpt/global/core/ai/model.d';
|
||||||
import type { EditFieldModeType, EditFieldType } from '../modules/FieldEditModal';
|
import type { EditFieldModeType, EditFieldType } from '../modules/FieldEditModal';
|
||||||
|
|||||||
@ -33,7 +33,7 @@ import dayjs from 'dayjs';
|
|||||||
import { AddIcon, QuestionOutlineIcon } from '@chakra-ui/icons';
|
import { AddIcon, QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||||
import { useCopyData } from '@/web/common/hooks/useCopyData';
|
import { useCopyData } from '@/web/common/hooks/useCopyData';
|
||||||
import { feConfigs } from '@/web/common/system/staticData';
|
import { feConfigs } from '@/web/common/system/staticData';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import MyIcon from '@/components/Icon';
|
import MyIcon from '@/components/Icon';
|
||||||
import MyModal from '@/components/MyModal';
|
import MyModal from '@/components/MyModal';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
import { PermissionTypeEnum, PermissionTypeMap } from '@fastgpt/global/support/permission/constant';
|
import { PermissionTypeEnum, PermissionTypeMap } from '@fastgpt/global/support/permission/constant';
|
||||||
import { Box, Flex, FlexProps } from '@chakra-ui/react';
|
import { Box, Flex, FlexProps } from '@chakra-ui/react';
|
||||||
import MyIcon from '@/components/Icon';
|
import MyIcon from '@/components/Icon';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
|
|
||||||
const PermissionIconText = ({
|
const PermissionIconText = ({
|
||||||
permission,
|
permission,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import MyRadio from '@/components/Radio';
|
import MyRadio from '@/components/Radio';
|
||||||
import { PermissionTypeEnum } from '@fastgpt/global/support/permission/constant';
|
import { PermissionTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
|
|
||||||
const PermissionRadio = ({
|
const PermissionRadio = ({
|
||||||
value,
|
value,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import React, { useCallback, useState } from 'react';
|
import React, { useCallback, useState } from 'react';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
|
import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
|
||||||
import { compressImgAndUpload } from '@/web/common/file/controller';
|
import { compressImgAndUpload } from '@/web/common/file/controller';
|
||||||
import { useToast } from '@/web/common/hooks/useToast';
|
import { useToast } from '@/web/common/hooks/useToast';
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import MyModal from '@/components/MyModal';
|
import MyModal from '@/components/MyModal';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { ModalCloseButton, ModalBody, Box, ModalFooter, Button } from '@chakra-ui/react';
|
import { ModalCloseButton, ModalBody, Box, ModalFooter, Button } from '@chakra-ui/react';
|
||||||
import TagTextarea from '@/components/common/Textarea/TagTextarea';
|
import TagTextarea from '@/components/common/Textarea/TagTextarea';
|
||||||
import MySelect from '@/components/Select';
|
import MySelect from '@/components/Select';
|
||||||
@ -57,8 +57,8 @@ const InviteModal = ({
|
|||||||
undefined,
|
undefined,
|
||||||
t('user.team.Invite Member Success Tip', {
|
t('user.team.Invite Member Success Tip', {
|
||||||
success: res.invite.length,
|
success: res.invite.length,
|
||||||
inValid: res.inValid.join(', '),
|
inValid: res.inValid.map((item) => item.username).join(', '),
|
||||||
inTeam: res.inTeam.join(', ')
|
inTeam: res.inTeam.map((item) => item.username).join(', ')
|
||||||
})
|
})
|
||||||
)();
|
)();
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import MyModal from '@/components/MyModal';
|
import MyModal from '@/components/MyModal';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import {
|
import {
|
||||||
getTeamList,
|
getTeamList,
|
||||||
@ -100,7 +100,9 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
|||||||
mutationFn: delRemoveMember,
|
mutationFn: delRemoveMember,
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
refetchMembers();
|
refetchMembers();
|
||||||
}
|
},
|
||||||
|
successToast: t('user.team.Remove Member Success'),
|
||||||
|
errorToast: t('user.team.Remove Member Failed')
|
||||||
});
|
});
|
||||||
const { mutate: onLeaveTeam, isLoading: isLoadingLeaveTeam } = useRequest({
|
const { mutate: onLeaveTeam, isLoading: isLoadingLeaveTeam } = useRequest({
|
||||||
mutationFn: async (teamId?: string) => {
|
mutationFn: async (teamId?: string) => {
|
||||||
@ -306,7 +308,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
|||||||
<Td display={'flex'} alignItems={'center'}>
|
<Td display={'flex'} alignItems={'center'}>
|
||||||
<Avatar src={item.avatar} w={['18px', '22px']} />
|
<Avatar src={item.avatar} w={['18px', '22px']} />
|
||||||
<Box flex={'1 0 0'} w={0} ml={1} className={'textEllipsis'}>
|
<Box flex={'1 0 0'} w={0} ml={1} className={'textEllipsis'}>
|
||||||
{item.memberUsername}
|
{item.memberName}
|
||||||
</Box>
|
</Box>
|
||||||
</Td>
|
</Td>
|
||||||
<Td>{t(TeamMemberRoleMap[item.role]?.label || '')}</Td>
|
<Td>{t(TeamMemberRoleMap[item.role]?.label || '')}</Td>
|
||||||
@ -383,7 +385,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
|||||||
}),
|
}),
|
||||||
undefined,
|
undefined,
|
||||||
t('user.team.Remove Member Confirm Tip', {
|
t('user.team.Remove Member Confirm Tip', {
|
||||||
username: item.memberUsername
|
username: item.memberName
|
||||||
})
|
})
|
||||||
)()
|
)()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, Button, Flex, Image, useDisclosure, useTheme } from '@chakra-ui/react';
|
import { Box, Button, Flex, Image, useDisclosure, useTheme } from '@chakra-ui/react';
|
||||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import MyTooltip from '@/components/MyTooltip';
|
import MyTooltip from '@/components/MyTooltip';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { feConfigs } from '@/web/common/system/staticData';
|
import { feConfigs } from '@/web/common/system/staticData';
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import MyModal from '@/components/MyModal';
|
import MyModal from '@/components/MyModal';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
import type { DatasetItemType } from '@/types/core/dataset';
|
import type {
|
||||||
|
DatasetCollectionItemType,
|
||||||
|
DatasetItemType
|
||||||
|
} from '@fastgpt/global/core/dataset/type.d';
|
||||||
|
|
||||||
export const defaultDatasetDetail: DatasetItemType = {
|
export const defaultDatasetDetail: DatasetItemType = {
|
||||||
_id: '',
|
_id: '',
|
||||||
@ -10,7 +13,7 @@ export const defaultDatasetDetail: DatasetItemType = {
|
|||||||
type: 'dataset',
|
type: 'dataset',
|
||||||
avatar: '/icon/logo.svg',
|
avatar: '/icon/logo.svg',
|
||||||
name: '',
|
name: '',
|
||||||
tags: '',
|
tags: [],
|
||||||
permission: 'private',
|
permission: 'private',
|
||||||
isOwner: false,
|
isOwner: false,
|
||||||
canWrite: false,
|
canWrite: false,
|
||||||
@ -22,3 +25,32 @@ export const defaultDatasetDetail: DatasetItemType = {
|
|||||||
maxToken: 3000
|
maxToken: 3000
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const defaultCollectionDetail: DatasetCollectionItemType = {
|
||||||
|
_id: '',
|
||||||
|
userId: '',
|
||||||
|
teamId: '',
|
||||||
|
tmbId: '',
|
||||||
|
datasetId: {
|
||||||
|
_id: '',
|
||||||
|
parentId: '',
|
||||||
|
userId: '',
|
||||||
|
teamId: '',
|
||||||
|
tmbId: '',
|
||||||
|
updateTime: new Date(),
|
||||||
|
type: 'dataset',
|
||||||
|
avatar: '/icon/logo.svg',
|
||||||
|
name: '',
|
||||||
|
tags: [],
|
||||||
|
permission: 'private',
|
||||||
|
vectorModel: 'text-embedding-ada-002'
|
||||||
|
},
|
||||||
|
parentId: '',
|
||||||
|
name: '',
|
||||||
|
type: 'file',
|
||||||
|
updateTime: new Date(),
|
||||||
|
metadata: {},
|
||||||
|
canWrite: false,
|
||||||
|
sourceName: '',
|
||||||
|
sourceId: ''
|
||||||
|
};
|
||||||
|
|||||||
@ -1,108 +0,0 @@
|
|||||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
|
||||||
import { countPromptTokens } from '@/global/common/tiktoken';
|
|
||||||
|
|
||||||
/*
|
|
||||||
replace {{variable}} to value
|
|
||||||
*/
|
|
||||||
export function replaceVariable(text: string, obj: Record<string, string | number>) {
|
|
||||||
for (const key in obj) {
|
|
||||||
const val = obj[key];
|
|
||||||
if (!['string', 'number'].includes(typeof val)) continue;
|
|
||||||
|
|
||||||
text = text.replace(new RegExp(`{{(${key})}}`, 'g'), String(val));
|
|
||||||
}
|
|
||||||
return text || '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* text split into chunks
|
|
||||||
* maxLen - one chunk len. max: 3500
|
|
||||||
* overlapLen - The size of the before and after Text
|
|
||||||
* maxLen > overlapLen
|
|
||||||
*/
|
|
||||||
export const splitText2Chunks = ({ text = '', maxLen }: { text: string; maxLen: number }) => {
|
|
||||||
const overlapLen = Math.floor(maxLen * 0.15); // Overlap length
|
|
||||||
const tempMarker = 'SPLIT_HERE_SPLIT_HERE';
|
|
||||||
|
|
||||||
const stepReg: Record<number, RegExp> = {
|
|
||||||
0: /(\n\n)/g,
|
|
||||||
1: /([\n])/g,
|
|
||||||
2: /[。]|(?!<[^a-zA-Z])\.\s/g,
|
|
||||||
3: /([!?]|!\s|\?\s)/g,
|
|
||||||
4: /([;]|;\s)/g,
|
|
||||||
5: /([,]|,\s)/g
|
|
||||||
};
|
|
||||||
|
|
||||||
const splitTextRecursively = ({ text = '', step }: { text: string; step: number }) => {
|
|
||||||
if (text.length <= maxLen) {
|
|
||||||
return [text];
|
|
||||||
}
|
|
||||||
const reg = stepReg[step];
|
|
||||||
|
|
||||||
if (!reg) {
|
|
||||||
// use slice-maxLen to split text
|
|
||||||
const chunks: string[] = [];
|
|
||||||
let chunk = '';
|
|
||||||
for (let i = 0; i < text.length; i += maxLen - overlapLen) {
|
|
||||||
chunk = text.slice(i, i + maxLen);
|
|
||||||
chunks.push(chunk);
|
|
||||||
}
|
|
||||||
return chunks;
|
|
||||||
}
|
|
||||||
|
|
||||||
// split text by delimiters
|
|
||||||
const splitTexts = text
|
|
||||||
.replace(reg, `$1${tempMarker}`)
|
|
||||||
.split(`${tempMarker}`)
|
|
||||||
.filter((part) => part);
|
|
||||||
|
|
||||||
let chunks: string[] = [];
|
|
||||||
let preChunk = '';
|
|
||||||
let chunk = '';
|
|
||||||
for (let i = 0; i < splitTexts.length; i++) {
|
|
||||||
let text = splitTexts[i];
|
|
||||||
// chunk over size
|
|
||||||
if (text.length > maxLen) {
|
|
||||||
const innerChunks = splitTextRecursively({ text, step: step + 1 });
|
|
||||||
if (innerChunks.length === 0) continue;
|
|
||||||
// If the last chunk is too small, it is merged into the next chunk
|
|
||||||
if (innerChunks[innerChunks.length - 1].length <= maxLen * 0.5) {
|
|
||||||
text = innerChunks.pop() || '';
|
|
||||||
chunks = chunks.concat(innerChunks);
|
|
||||||
} else {
|
|
||||||
chunks = chunks.concat(innerChunks);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
chunk += text;
|
|
||||||
// size over lapLen, push it to next chunk
|
|
||||||
if (chunk.length > maxLen - overlapLen) {
|
|
||||||
preChunk += text;
|
|
||||||
}
|
|
||||||
if (chunk.length >= maxLen) {
|
|
||||||
chunks.push(chunk);
|
|
||||||
chunk = preChunk;
|
|
||||||
preChunk = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chunk && !chunks[chunks.length - 1].endsWith(chunk)) {
|
|
||||||
chunks.push(chunk);
|
|
||||||
}
|
|
||||||
return chunks;
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
const chunks = splitTextRecursively({ text, step: 0 });
|
|
||||||
|
|
||||||
const tokens = chunks.reduce((sum, chunk) => sum + countPromptTokens(chunk, 'system'), 0);
|
|
||||||
|
|
||||||
return {
|
|
||||||
chunks,
|
|
||||||
tokens
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
throw new Error(getErrText(err));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
26
projects/app/src/global/core/api/datasetReq.d.ts
vendored
26
projects/app/src/global/core/api/datasetReq.d.ts
vendored
@ -2,7 +2,7 @@ import { DatasetCollectionTypeEnum, DatasetTypeEnum } from '@fastgpt/global/core
|
|||||||
import type { RequestPaging } from '@/types';
|
import type { RequestPaging } from '@/types';
|
||||||
import { TrainingModeEnum } from '@fastgpt/global/core/dataset/constant';
|
import { TrainingModeEnum } from '@fastgpt/global/core/dataset/constant';
|
||||||
import type { SearchTestItemType } from '@/types/core/dataset';
|
import type { SearchTestItemType } from '@/types/core/dataset';
|
||||||
import { DatasetChunkItemType, UploadChunkItemType } from '@fastgpt/global/core/dataset/type';
|
import { UploadChunkItemType } from '@fastgpt/global/core/dataset/type';
|
||||||
import { DatasetCollectionSchemaType } from '@fastgpt/global/core/dataset/type';
|
import { DatasetCollectionSchemaType } from '@fastgpt/global/core/dataset/type';
|
||||||
import { PermissionTypeEnum } from '@fastgpt/global/support/permission/constant';
|
import { PermissionTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||||
|
|
||||||
@ -10,19 +10,11 @@ import { PermissionTypeEnum } from '@fastgpt/global/support/permission/constant'
|
|||||||
export type DatasetUpdateParams = {
|
export type DatasetUpdateParams = {
|
||||||
id: string;
|
id: string;
|
||||||
parentId?: string;
|
parentId?: string;
|
||||||
tags?: string;
|
tags?: string[];
|
||||||
name?: string;
|
name?: string;
|
||||||
avatar?: string;
|
avatar?: string;
|
||||||
permission?: `${PermissionTypeEnum}`;
|
permission?: `${PermissionTypeEnum}`;
|
||||||
};
|
};
|
||||||
export type CreateDatasetParams = {
|
|
||||||
parentId?: string;
|
|
||||||
name: string;
|
|
||||||
tags: string;
|
|
||||||
avatar: string;
|
|
||||||
vectorModel?: string;
|
|
||||||
type: `${DatasetTypeEnum}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type SearchTestProps = {
|
export type SearchTestProps = {
|
||||||
datasetId: string;
|
datasetId: string;
|
||||||
@ -54,20 +46,6 @@ export type UpdateDatasetCollectionParams = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* ==== data ===== */
|
/* ==== data ===== */
|
||||||
export type SetOneDatasetDataProps = {
|
|
||||||
id?: string;
|
|
||||||
collectionId: string;
|
|
||||||
q?: string; // embedding content
|
|
||||||
a?: string; // bonus content
|
|
||||||
};
|
|
||||||
export type PushDataProps = {
|
|
||||||
collectionId: string;
|
|
||||||
data: DatasetChunkItemType[];
|
|
||||||
mode: `${TrainingModeEnum}`;
|
|
||||||
prompt?: string;
|
|
||||||
billId?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type GetDatasetDataListProps = RequestPaging & {
|
export type GetDatasetDataListProps = RequestPaging & {
|
||||||
searchText?: string;
|
searchText?: string;
|
||||||
collectionId: string;
|
collectionId: string;
|
||||||
|
|||||||
35
projects/app/src/global/core/dataset/api.d.ts
vendored
Normal file
35
projects/app/src/global/core/dataset/api.d.ts
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { PushDatasetDataChunkProps } from '@fastgpt/global/core/dataset/api';
|
||||||
|
import { TrainingModeEnum } from '@fastgpt/global/core/dataset/constant';
|
||||||
|
import { DatasetDataIndexItemType } from '@fastgpt/global/core/dataset/type';
|
||||||
|
|
||||||
|
/* ================= dataset ===================== */
|
||||||
|
export type CreateDatasetParams = {
|
||||||
|
parentId?: string;
|
||||||
|
name: string;
|
||||||
|
tags: string;
|
||||||
|
avatar: string;
|
||||||
|
vectorModel?: string;
|
||||||
|
type: `${DatasetTypeEnum}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ================= collection ===================== */
|
||||||
|
|
||||||
|
/* ================= data ===================== */
|
||||||
|
export type InsertOneDatasetDataProps = PushDatasetDataChunkProps & {
|
||||||
|
collectionId: string;
|
||||||
|
};
|
||||||
|
export type PushDatasetDataProps = {
|
||||||
|
collectionId: string;
|
||||||
|
data: PushDatasetDataChunkProps[];
|
||||||
|
mode: `${TrainingModeEnum}`;
|
||||||
|
prompt?: string;
|
||||||
|
billId?: string;
|
||||||
|
};
|
||||||
|
export type UpdateDatasetDataProps = {
|
||||||
|
id: string;
|
||||||
|
q?: string; // embedding content
|
||||||
|
a?: string; // bonus content
|
||||||
|
indexes: (Omit<DatasetDataIndexItemType, 'dataId'> & {
|
||||||
|
dataId?: string; // pg data id
|
||||||
|
})[];
|
||||||
|
};
|
||||||
@ -1,5 +1,8 @@
|
|||||||
import { ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type';
|
import { ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type';
|
||||||
import { DatasetCollectionSchemaType } from '@fastgpt/global/core/dataset/type.d';
|
import {
|
||||||
|
DatasetCollectionSchemaType,
|
||||||
|
DatasetDataSchemaType
|
||||||
|
} from '@fastgpt/global/core/dataset/type.d';
|
||||||
|
|
||||||
/* ================= dataset ===================== */
|
/* ================= dataset ===================== */
|
||||||
|
|
||||||
@ -11,7 +14,7 @@ export type DatasetCollectionsListItemType = {
|
|||||||
name: string;
|
name: string;
|
||||||
type: DatasetCollectionSchemaType['type'];
|
type: DatasetCollectionSchemaType['type'];
|
||||||
updateTime: Date;
|
updateTime: Date;
|
||||||
dataAmount?: number;
|
dataAmount: number;
|
||||||
trainingAmount: number;
|
trainingAmount: number;
|
||||||
metadata: DatasetCollectionSchemaType['metadata'];
|
metadata: DatasetCollectionSchemaType['metadata'];
|
||||||
canWrite: boolean;
|
canWrite: boolean;
|
||||||
@ -19,7 +22,10 @@ export type DatasetCollectionsListItemType = {
|
|||||||
|
|
||||||
/* ================= data ===================== */
|
/* ================= data ===================== */
|
||||||
export type DatasetDataListItemType = {
|
export type DatasetDataListItemType = {
|
||||||
id: string;
|
_id: string;
|
||||||
|
datasetId: string;
|
||||||
|
collectionId: string;
|
||||||
q: string; // embedding content
|
q: string; // embedding content
|
||||||
a: string; // bonus content
|
a: string; // bonus content
|
||||||
|
indexes: DatasetDataSchemaType['indexes'];
|
||||||
};
|
};
|
||||||
@ -10,10 +10,10 @@ import NProgress from 'nprogress'; //nprogress module
|
|||||||
import Router from 'next/router';
|
import Router from 'next/router';
|
||||||
import { clientInitData, feConfigs } from '@/web/common/system/staticData';
|
import { clientInitData, feConfigs } from '@/web/common/system/staticData';
|
||||||
import { appWithTranslation, useTranslation } from 'next-i18next';
|
import { appWithTranslation, useTranslation } from 'next-i18next';
|
||||||
import { getLangStore, setLangStore } from '@/web/common/utils/i18n';
|
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||||
import type { FeConfigsType } from '@fastgpt/global/common/system/types/index.d';
|
import type { FeConfigsType } from '@fastgpt/global/common/system/types/index.d';
|
||||||
|
import { change2DefaultLng, setLngStore } from '@/web/common/utils/i18n';
|
||||||
|
|
||||||
import 'nprogress/nprogress.css';
|
import 'nprogress/nprogress.css';
|
||||||
import '@/web/styles/reset.scss';
|
import '@/web/styles/reset.scss';
|
||||||
@ -57,6 +57,7 @@ function App({ Component, pageProps }: AppProps) {
|
|||||||
);
|
);
|
||||||
setScripts(scripts || []);
|
setScripts(scripts || []);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// add window error track
|
// add window error track
|
||||||
window.onerror = function (msg, url) {
|
window.onerror = function (msg, url) {
|
||||||
window.umami?.track('windowError', {
|
window.umami?.track('windowError', {
|
||||||
@ -76,23 +77,22 @@ function App({ Component, pageProps }: AppProps) {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
hiId && localStorage.setItem('inviterId', hiId);
|
// get default language
|
||||||
}, [hiId]);
|
const targetLng = change2DefaultLng(i18n.language);
|
||||||
|
if (targetLng) {
|
||||||
|
setLngStore(targetLng);
|
||||||
|
router.replace(router.asPath, undefined, { locale: targetLng });
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const lang = getLangStore() || 'zh';
|
hiId && localStorage.setItem('inviterId', hiId);
|
||||||
i18n?.changeLanguage?.(lang);
|
}, [hiId]);
|
||||||
setLangStore(lang);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
setLastRoute(router.asPath);
|
|
||||||
};
|
|
||||||
}, [router.asPath]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Head>
|
<Head>
|
||||||
<title>{feConfigs?.systemTitle || 'AI'}</title>
|
<title>{feConfigs?.systemTitle || process.env.SYSTEM_NAME || 'GPT'}</title>
|
||||||
<meta
|
<meta
|
||||||
name="description"
|
name="description"
|
||||||
content="FastGPT is a knowledge-based question answering system built on the LLM. It offers out-of-the-box data processing and model invocation capabilities. Moreover, it allows for workflow orchestration through Flow visualization, thereby enabling complex question and answer scenarios!"
|
content="FastGPT is a knowledge-based question answering system built on the LLM. It offers out-of-the-box data processing and model invocation capabilities. Moreover, it allows for workflow orchestration through Flow visualization, thereby enabling complex question and answer scenarios!"
|
||||||
|
|||||||
@ -2,7 +2,8 @@ import { Html, Head, Main, NextScript } from 'next/document';
|
|||||||
|
|
||||||
export default function Document() {
|
export default function Document() {
|
||||||
return (
|
return (
|
||||||
<Html lang="en">
|
<Html>
|
||||||
|
<title>{process.env.SYSTEM_NAME || 'FastGPT'}</title>
|
||||||
<Head />
|
<Head />
|
||||||
<body>
|
<body>
|
||||||
<Main />
|
<Main />
|
||||||
|
|||||||
@ -25,8 +25,9 @@ function Error() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<p>
|
<p>
|
||||||
部分系统不兼容,导致页面崩溃。如果可以,请联系作者,反馈下具体操作和页面。大部分是 苹果 的
|
部分系统不兼容,导致页面崩溃。如果可以,请联系作者,反馈下具体操作和页面。 大部分是 苹果 的
|
||||||
safari 浏览器导致,可以尝试更换 chrome 浏览器。
|
safari 浏览器导致,可以尝试更换 chrome
|
||||||
|
浏览器。或者是因为开了中文翻译导致,请检查并关闭中文翻译。
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import ApiKeyTable from '@/components/support/apikey/Table';
|
import ApiKeyTable from '@/components/support/apikey/Table';
|
||||||
|
|
||||||
const ApiKey = () => {
|
const ApiKey = () => {
|
||||||
|
|||||||
@ -16,7 +16,7 @@ import dayjs from 'dayjs';
|
|||||||
import { BillSourceMap } from '@fastgpt/global/support/wallet/bill/constants';
|
import { BillSourceMap } from '@fastgpt/global/support/wallet/bill/constants';
|
||||||
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
|
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
|
||||||
import MyModal from '@/components/MyModal';
|
import MyModal from '@/components/MyModal';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
|
|
||||||
const BillDetail = ({ bill, onClose }: { bill: BillItemType; onClose: () => void }) => {
|
const BillDetail = ({ bill, onClose }: { bill: BillItemType; onClose: () => void }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -30,7 +30,7 @@ const BillDetail = ({ bill, onClose }: { bill: BillItemType; onClose: () => void
|
|||||||
<ModalBody>
|
<ModalBody>
|
||||||
<Flex alignItems={'center'} pb={4}>
|
<Flex alignItems={'center'} pb={4}>
|
||||||
<Box flex={'0 0 80px'}>用户:</Box>
|
<Box flex={'0 0 80px'}>用户:</Box>
|
||||||
<Box>{bill.username}</Box>
|
<Box>{bill.memberName}</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex alignItems={'center'} pb={4}>
|
<Flex alignItems={'center'} pb={4}>
|
||||||
<Box flex={'0 0 80px'}>订单号:</Box>
|
<Box flex={'0 0 80px'}>订单号:</Box>
|
||||||
|
|||||||
@ -55,7 +55,7 @@ const BillTable = () => {
|
|||||||
<Table>
|
<Table>
|
||||||
<Thead>
|
<Thead>
|
||||||
<Tr>
|
<Tr>
|
||||||
<Th>{t('wallet.bill.bill username')}</Th>
|
<Th>{t('user.team.Member Name')}</Th>
|
||||||
<Th>{t('user.Time')}</Th>
|
<Th>{t('user.Time')}</Th>
|
||||||
<Th>{t('user.Source')}</Th>
|
<Th>{t('user.Source')}</Th>
|
||||||
<Th>{t('user.Application Name')}</Th>
|
<Th>{t('user.Application Name')}</Th>
|
||||||
@ -66,7 +66,7 @@ const BillTable = () => {
|
|||||||
<Tbody fontSize={'sm'}>
|
<Tbody fontSize={'sm'}>
|
||||||
{bills.map((item) => (
|
{bills.map((item) => (
|
||||||
<Tr key={item.id}>
|
<Tr key={item.id}>
|
||||||
<Td>{item.username}</Td>
|
<Td>{item.memberName}</Td>
|
||||||
<Td>{dayjs(item.time).format('YYYY/MM/DD HH:mm:ss')}</Td>
|
<Td>{dayjs(item.time).format('YYYY/MM/DD HH:mm:ss')}</Td>
|
||||||
<Td>{BillSourceMap[item.source]}</Td>
|
<Td>{BillSourceMap[item.source]}</Td>
|
||||||
<Td>{t(item.appName) || '-'}</Td>
|
<Td>{t(item.appName) || '-'}</Td>
|
||||||
|
|||||||
@ -1,5 +1,14 @@
|
|||||||
import React, { useCallback, useRef, useState } from 'react';
|
import React, { useCallback, useRef } from 'react';
|
||||||
import { Box, Flex, Button, useDisclosure, useTheme, Divider, Select } from '@chakra-ui/react';
|
import {
|
||||||
|
Box,
|
||||||
|
Flex,
|
||||||
|
Button,
|
||||||
|
useDisclosure,
|
||||||
|
useTheme,
|
||||||
|
Divider,
|
||||||
|
Select,
|
||||||
|
Input
|
||||||
|
} from '@chakra-ui/react';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { UserUpdateParams } from '@/types/user';
|
import { UserUpdateParams } from '@/types/user';
|
||||||
import { useToast } from '@/web/common/hooks/useToast';
|
import { useToast } from '@/web/common/hooks/useToast';
|
||||||
@ -16,10 +25,11 @@ import Loading from '@/components/Loading';
|
|||||||
import Avatar from '@/components/Avatar';
|
import Avatar from '@/components/Avatar';
|
||||||
import MyIcon from '@/components/Icon';
|
import MyIcon from '@/components/Icon';
|
||||||
import MyTooltip from '@/components/MyTooltip';
|
import MyTooltip from '@/components/MyTooltip';
|
||||||
import { getLangStore, LangEnum, langMap, setLangStore } from '@/web/common/utils/i18n';
|
import { langMap, setLngStore } from '@/web/common/utils/i18n';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import MySelect from '@/components/Select';
|
import MySelect from '@/components/Select';
|
||||||
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
|
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
|
||||||
|
import { putUpdateMemberName } from '@/web/support/user/team/api';
|
||||||
|
|
||||||
const TeamMenu = dynamic(() => import('@/components/support/user/team/TeamMenu'));
|
const TeamMenu = dynamic(() => import('@/components/support/user/team/TeamMenu'));
|
||||||
const PayModal = dynamic(() => import('./PayModal'), {
|
const PayModal = dynamic(() => import('./PayModal'), {
|
||||||
@ -63,8 +73,6 @@ const UserInfo = () => {
|
|||||||
multiple: false
|
multiple: false
|
||||||
});
|
});
|
||||||
|
|
||||||
const [language, setLanguage] = useState<`${LangEnum}`>(getLangStore());
|
|
||||||
|
|
||||||
const onclickSave = useCallback(
|
const onclickSave = useCallback(
|
||||||
async (data: UserType) => {
|
async (data: UserType) => {
|
||||||
await updateUserInfo({
|
await updateUserInfo({
|
||||||
@ -153,6 +161,27 @@ const UserInfo = () => {
|
|||||||
ml={[0, 10]}
|
ml={[0, 10]}
|
||||||
mt={[6, 0]}
|
mt={[6, 0]}
|
||||||
>
|
>
|
||||||
|
{feConfigs.isPlus && (
|
||||||
|
<Flex mb={4} alignItems={'center'} w={['85%', '300px']}>
|
||||||
|
<Box flex={'0 0 80px'}>{t('user.Member Name')}: </Box>
|
||||||
|
<Input
|
||||||
|
flex={1}
|
||||||
|
defaultValue={userInfo?.team?.memberName || 'Member'}
|
||||||
|
title={t('user.Edit name')}
|
||||||
|
borderColor={'transparent'}
|
||||||
|
pl={'10px'}
|
||||||
|
transform={'translateX(-11px)'}
|
||||||
|
maxLength={20}
|
||||||
|
onBlur={(e) => {
|
||||||
|
const val = e.target.value;
|
||||||
|
if (val === userInfo?.team?.memberName) return;
|
||||||
|
try {
|
||||||
|
putUpdateMemberName(val);
|
||||||
|
} catch (error) {}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
<Flex alignItems={'center'} w={['85%', '300px']}>
|
<Flex alignItems={'center'} w={['85%', '300px']}>
|
||||||
<Box flex={'0 0 80px'}>{t('user.Account')}: </Box>
|
<Box flex={'0 0 80px'}>{t('user.Account')}: </Box>
|
||||||
<Box flex={1}>{userInfo?.username}</Box>
|
<Box flex={1}>{userInfo?.username}</Box>
|
||||||
@ -167,17 +196,15 @@ const UserInfo = () => {
|
|||||||
<Box flex={'0 0 80px'}>{t('user.Language')}: </Box>
|
<Box flex={'0 0 80px'}>{t('user.Language')}: </Box>
|
||||||
<Box flex={'1 0 0'}>
|
<Box flex={'1 0 0'}>
|
||||||
<MySelect
|
<MySelect
|
||||||
value={language}
|
value={i18n.language}
|
||||||
list={Object.entries(langMap).map(([key, lang]) => ({
|
list={Object.entries(langMap).map(([key, lang]) => ({
|
||||||
label: lang.label,
|
label: lang.label,
|
||||||
value: key
|
value: key
|
||||||
}))}
|
}))}
|
||||||
onchange={(val: any) => {
|
onchange={(val: any) => {
|
||||||
const lang = val;
|
const lang = val;
|
||||||
setLangStore(lang);
|
setLngStore(lang);
|
||||||
setLanguage(lang);
|
router.replace(router.basePath, router.asPath, { locale: lang });
|
||||||
i18n?.changeLanguage?.(lang);
|
|
||||||
router.reload();
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ModalBody, Box, Flex, Input, ModalFooter, Button } from '@chakra-ui/react';
|
import { ModalBody, Box, Flex, Input, ModalFooter, Button } from '@chakra-ui/react';
|
||||||
import MyModal from '@/components/MyModal';
|
import MyModal from '@/components/MyModal';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||||
import type { UserType } from '@fastgpt/global/support/user/type.d';
|
import type { UserType } from '@fastgpt/global/support/user/type.d';
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { useToast } from '@/web/common/hooks/useToast';
|
|||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import Markdown from '@/components/Markdown';
|
import Markdown from '@/components/Markdown';
|
||||||
import MyModal from '@/components/MyModal';
|
import MyModal from '@/components/MyModal';
|
||||||
import { priceMd } from '@/web/common/system/staticData';
|
import { priceMd } from '@/web/common/system/staticData';
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ModalBody, Box, Flex, Input, ModalFooter, Button } from '@chakra-ui/react';
|
import { ModalBody, Box, Flex, Input, ModalFooter, Button } from '@chakra-ui/react';
|
||||||
import MyModal from '@/components/MyModal';
|
import MyModal from '@/components/MyModal';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||||
import { updatePasswordByOld } from '@/web/support/user/api';
|
import { updatePasswordByOld } from '@/web/support/user/api';
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import Tabs from '@/components/Tabs';
|
|||||||
import UserInfo from './components/Info';
|
import UserInfo from './components/Info';
|
||||||
import { serviceSideProps } from '@/web/common/utils/i18n';
|
import { serviceSideProps } from '@/web/common/utils/i18n';
|
||||||
import { feConfigs } from '@/web/common/system/staticData';
|
import { feConfigs } from '@/web/common/system/staticData';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import Script from 'next/script';
|
import Script from 'next/script';
|
||||||
|
|
||||||
const Promotion = dynamic(() => import('./components/Promotion'));
|
const Promotion = dynamic(() => import('./components/Promotion'));
|
||||||
@ -35,67 +35,64 @@ const Account = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { userInfo, setUserInfo } = useUserStore();
|
const { userInfo, setUserInfo } = useUserStore();
|
||||||
|
|
||||||
const tabList = useMemo(
|
const tabList = [
|
||||||
() => [
|
{
|
||||||
{
|
icon: 'meLight',
|
||||||
icon: 'meLight',
|
label: t('user.Personal Information'),
|
||||||
label: t('user.Personal Information'),
|
id: TabEnum.info
|
||||||
id: TabEnum.info
|
},
|
||||||
},
|
...(feConfigs?.isPlus
|
||||||
...(feConfigs?.isPlus
|
? [
|
||||||
? [
|
{
|
||||||
{
|
icon: 'billRecordLight',
|
||||||
icon: 'billRecordLight',
|
label: t('user.Usage Record'),
|
||||||
label: t('user.Usage Record'),
|
id: TabEnum.bill
|
||||||
id: TabEnum.bill
|
}
|
||||||
}
|
]
|
||||||
]
|
: []),
|
||||||
: []),
|
...(feConfigs?.show_promotion
|
||||||
...(feConfigs?.show_promotion
|
? [
|
||||||
? [
|
{
|
||||||
{
|
icon: 'promotionLight',
|
||||||
icon: 'promotionLight',
|
label: t('user.Promotion Record'),
|
||||||
label: t('user.Promotion Record'),
|
id: TabEnum.promotion
|
||||||
id: TabEnum.promotion
|
}
|
||||||
}
|
]
|
||||||
]
|
: []),
|
||||||
: []),
|
...(feConfigs?.show_pay && userInfo?.team.canWrite
|
||||||
...(feConfigs?.show_pay && userInfo?.team.canWrite
|
? [
|
||||||
? [
|
{
|
||||||
{
|
icon: 'payRecordLight',
|
||||||
icon: 'payRecordLight',
|
label: t('user.Recharge Record'),
|
||||||
label: t('user.Recharge Record'),
|
id: TabEnum.pay
|
||||||
id: TabEnum.pay
|
}
|
||||||
}
|
]
|
||||||
]
|
: []),
|
||||||
: []),
|
...(userInfo?.team.canWrite
|
||||||
...(userInfo?.team.canWrite
|
? [
|
||||||
? [
|
{
|
||||||
{
|
icon: 'apikey',
|
||||||
icon: 'apikey',
|
label: t('user.apikey.key'),
|
||||||
label: t('user.apikey.key'),
|
id: TabEnum.apikey
|
||||||
id: TabEnum.apikey
|
}
|
||||||
}
|
]
|
||||||
]
|
: []),
|
||||||
: []),
|
...(feConfigs.isPlus
|
||||||
...(feConfigs.isPlus
|
? [
|
||||||
? [
|
{
|
||||||
{
|
icon: 'informLight',
|
||||||
icon: 'informLight',
|
label: t('user.Notice'),
|
||||||
label: t('user.Notice'),
|
id: TabEnum.inform
|
||||||
id: TabEnum.inform
|
}
|
||||||
}
|
]
|
||||||
]
|
: []),
|
||||||
: []),
|
|
||||||
|
|
||||||
{
|
{
|
||||||
icon: 'loginoutLight',
|
icon: 'loginoutLight',
|
||||||
label: t('user.Sign Out'),
|
label: t('user.Sign Out'),
|
||||||
id: TabEnum.loginout
|
id: TabEnum.loginout
|
||||||
}
|
}
|
||||||
],
|
];
|
||||||
[t, userInfo?.team.canWrite]
|
|
||||||
);
|
|
||||||
|
|
||||||
const { openConfirm, ConfirmModal } = useConfirm({
|
const { openConfirm, ConfirmModal } = useConfirm({
|
||||||
content: '确认退出登录?'
|
content: '确认退出登录?'
|
||||||
|
|||||||
169
projects/app/src/pages/api/admin/initv46-2.ts
Normal file
169
projects/app/src/pages/api/admin/initv46-2.ts
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
|
import { jsonRes } from '@fastgpt/service/common/response';
|
||||||
|
import { connectToDatabase } from '@/service/mongo';
|
||||||
|
import { delay } from '@/utils/tools';
|
||||||
|
import { PgClient } from '@fastgpt/service/common/pg';
|
||||||
|
import {
|
||||||
|
DatasetDataIndexTypeEnum,
|
||||||
|
PgDatasetTableName
|
||||||
|
} from '@fastgpt/global/core/dataset/constant';
|
||||||
|
|
||||||
|
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
||||||
|
import { MongoDatasetData } from '@fastgpt/service/core/dataset/data/schema';
|
||||||
|
import { getUserDefaultTeam } from '@fastgpt/service/support/user/team/controller';
|
||||||
|
|
||||||
|
let success = 0;
|
||||||
|
/* pg 中的数据搬到 mongo dataset.datas 中,并做映射 */
|
||||||
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
|
try {
|
||||||
|
const { limit = 50 } = req.body as { limit: number };
|
||||||
|
await authCert({ req, authRoot: true });
|
||||||
|
await connectToDatabase();
|
||||||
|
success = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await Promise.allSettled([
|
||||||
|
PgClient.query(`ALTER TABLE ${PgDatasetTableName} ADD COLUMN data_id VARCHAR(50);`),
|
||||||
|
PgClient.query(`ALTER TABLE ${PgDatasetTableName} ALTER COLUMN q DROP NOT NULL;`), // q can null
|
||||||
|
PgClient.query(`ALTER TABLE ${PgDatasetTableName} ALTER COLUMN a DROP NOT NULL;`), // a can null
|
||||||
|
PgClient.query(
|
||||||
|
`ALTER TABLE ${PgDatasetTableName} ALTER COLUMN team_id TYPE VARCHAR(50) USING team_id::VARCHAR(50);`
|
||||||
|
), // team_id varchar
|
||||||
|
PgClient.query(
|
||||||
|
`ALTER TABLE ${PgDatasetTableName} ALTER COLUMN tmb_id TYPE VARCHAR(50) USING tmb_id::VARCHAR(50);`
|
||||||
|
), // tmb_id varchar
|
||||||
|
PgClient.query(`ALTER TABLE ${PgDatasetTableName} ALTER COLUMN team_id SET NOT NULL;`), // team_id not null
|
||||||
|
PgClient.query(`ALTER TABLE ${PgDatasetTableName} ALTER COLUMN tmb_id SET NOT NULL;`), // tmb_id not null
|
||||||
|
PgClient.query(`ALTER TABLE ${PgDatasetTableName} ALTER COLUMN dataset_id SET NOT NULL;`), // dataset_id not null
|
||||||
|
PgClient.query(`ALTER TABLE ${PgDatasetTableName} ALTER COLUMN collection_id SET NOT NULL;`) // collection_id not null
|
||||||
|
]);
|
||||||
|
} catch (error) {}
|
||||||
|
|
||||||
|
await initPgData();
|
||||||
|
|
||||||
|
jsonRes(res, {
|
||||||
|
data: await init(limit),
|
||||||
|
message:
|
||||||
|
'初始化任务已开始,请注意日志进度。可通过 select count(id) from modeldata where data_id is null; 检查是否完全初始化,如果结果为 0 ,则完全初始化。'
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
|
||||||
|
jsonRes(res, {
|
||||||
|
code: 500,
|
||||||
|
error
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PgItemType = {
|
||||||
|
id: string;
|
||||||
|
q: string;
|
||||||
|
a: string;
|
||||||
|
dataset_id: string;
|
||||||
|
collection_id: string;
|
||||||
|
team_id: string;
|
||||||
|
tmb_id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function initPgData() {
|
||||||
|
const limit = 10;
|
||||||
|
const { rows } = await PgClient.query<{ user_id: string }>(`
|
||||||
|
SELECT DISTINCT user_id FROM ${PgDatasetTableName} WHERE team_id='null';
|
||||||
|
`);
|
||||||
|
console.log('init pg', rows.length);
|
||||||
|
let success = 0;
|
||||||
|
for (let i = 0; i < limit; i++) {
|
||||||
|
init(i);
|
||||||
|
}
|
||||||
|
async function init(index: number): Promise<any> {
|
||||||
|
const userId = rows[index]?.user_id;
|
||||||
|
if (!userId) return;
|
||||||
|
try {
|
||||||
|
const tmb = await getUserDefaultTeam({ userId });
|
||||||
|
// update pg
|
||||||
|
await PgClient.query(
|
||||||
|
`Update ${PgDatasetTableName} set team_id = '${tmb.teamId}', tmb_id = '${tmb.tmbId}' where user_id = '${userId}' AND team_id='null';`
|
||||||
|
);
|
||||||
|
console.log(++success);
|
||||||
|
init(index + limit);
|
||||||
|
} catch (error) {
|
||||||
|
if (error === 'default team not exist') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(error);
|
||||||
|
await delay(1000);
|
||||||
|
return init(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function init(limit: number): Promise<any> {
|
||||||
|
const { rows: idList } = await PgClient.query<{ id: string }>(
|
||||||
|
`SELECT id FROM ${PgDatasetTableName} WHERE data_id IS NULL`
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('totalCount', idList.length);
|
||||||
|
if (idList.length === 0) return;
|
||||||
|
|
||||||
|
for (let i = 0; i < limit; i++) {
|
||||||
|
initData(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function initData(index: number): Promise<any> {
|
||||||
|
const dataId = idList[index]?.id;
|
||||||
|
if (!dataId) {
|
||||||
|
console.log('done');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// get limit data where data_id is null
|
||||||
|
const { rows } = await PgClient.query<PgItemType>(
|
||||||
|
`SELECT id,q,a,dataset_id,collection_id,team_id,tmb_id FROM ${PgDatasetTableName} WHERE id=${dataId};`
|
||||||
|
);
|
||||||
|
const data = rows[0];
|
||||||
|
if (!data) {
|
||||||
|
console.log('done');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let id = '';
|
||||||
|
try {
|
||||||
|
// create mongo data and update data_id
|
||||||
|
const { _id } = await MongoDatasetData.create({
|
||||||
|
teamId: data.team_id.trim(),
|
||||||
|
tmbId: data.tmb_id.trim(),
|
||||||
|
datasetId: data.dataset_id,
|
||||||
|
collectionId: data.collection_id,
|
||||||
|
q: data.q,
|
||||||
|
a: data.a,
|
||||||
|
indexes: [
|
||||||
|
{
|
||||||
|
defaultIndex: !data.a,
|
||||||
|
type: data.a ? DatasetDataIndexTypeEnum.qa : DatasetDataIndexTypeEnum.chunk,
|
||||||
|
dataId: data.id,
|
||||||
|
text: data.q
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
id = _id;
|
||||||
|
// update pg data_id
|
||||||
|
await PgClient.query(
|
||||||
|
`UPDATE ${PgDatasetTableName} SET data_id='${String(_id)}' WHERE id=${dataId};`
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(++success);
|
||||||
|
return initData(index + limit);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (id) {
|
||||||
|
await MongoDatasetData.findByIdAndDelete(id);
|
||||||
|
}
|
||||||
|
} catch (error) {}
|
||||||
|
await delay(500);
|
||||||
|
return initData(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,21 +4,14 @@ import { connectToDatabase } from '@/service/mongo';
|
|||||||
import { MongoBill } from '@fastgpt/service/support/wallet/bill/schema';
|
import { MongoBill } from '@fastgpt/service/support/wallet/bill/schema';
|
||||||
import {
|
import {
|
||||||
createDefaultTeam,
|
createDefaultTeam,
|
||||||
getTeamInfoByTmbId
|
getUserDefaultTeam
|
||||||
} from '@fastgpt/service/support/user/team/controller';
|
} from '@fastgpt/service/support/user/team/controller';
|
||||||
import { MongoUser } from '@fastgpt/service/support/user/schema';
|
import { MongoUser } from '@fastgpt/service/support/user/schema';
|
||||||
import { UserModelSchema } from '@fastgpt/global/support/user/type';
|
import { UserModelSchema } from '@fastgpt/global/support/user/type';
|
||||||
import { delay } from '@/utils/tools';
|
import { delay } from '@/utils/tools';
|
||||||
import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
|
import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
|
||||||
import {
|
|
||||||
DatasetCollectionSchemaType,
|
|
||||||
DatasetSchemaType,
|
|
||||||
DatasetTrainingSchemaType
|
|
||||||
} from '@fastgpt/global/core/dataset/type';
|
|
||||||
import { PermissionTypeEnum } from '@fastgpt/global/support/permission/constant';
|
import { PermissionTypeEnum } from '@fastgpt/global/support/permission/constant';
|
||||||
import { MongoDatasetCollection } from '@fastgpt/service/core/dataset/collection/schema';
|
import { MongoDatasetCollection } from '@fastgpt/service/core/dataset/collection/schema';
|
||||||
import { connectionMongo } from '@fastgpt/service/common/mongo';
|
|
||||||
import { Types } from 'mongoose';
|
|
||||||
import { MongoDatasetTraining } from '@fastgpt/service/core/dataset/training/schema';
|
import { MongoDatasetTraining } from '@fastgpt/service/core/dataset/training/schema';
|
||||||
import { PgClient } from '@fastgpt/service/common/pg';
|
import { PgClient } from '@fastgpt/service/common/pg';
|
||||||
import { PgDatasetTableName } from '@fastgpt/global/core/dataset/constant';
|
import { PgDatasetTableName } from '@fastgpt/global/core/dataset/constant';
|
||||||
@ -30,6 +23,7 @@ import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
|
|||||||
import { MongoPlugin } from '@fastgpt/service/core/plugin/schema';
|
import { MongoPlugin } from '@fastgpt/service/core/plugin/schema';
|
||||||
import { POST } from '@fastgpt/service/common/api/plusRequest';
|
import { POST } from '@fastgpt/service/common/api/plusRequest';
|
||||||
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
||||||
|
import { getGFSCollection } from '@fastgpt/service/common/file/gridfs/controller';
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
try {
|
try {
|
||||||
@ -182,7 +176,7 @@ async function initMongoTeamId(limit: number) {
|
|||||||
|
|
||||||
async function init(userId: string): Promise<any> {
|
async function init(userId: string): Promise<any> {
|
||||||
try {
|
try {
|
||||||
const tmb = await getTeamInfoByTmbId({ userId });
|
const tmb = await getUserDefaultTeam({ userId });
|
||||||
|
|
||||||
await schema.updateMany(
|
await schema.updateMany(
|
||||||
{
|
{
|
||||||
@ -225,7 +219,7 @@ async function initDatasetAndApp() {
|
|||||||
}
|
}
|
||||||
async function initCollectionFileTeam(limit: number) {
|
async function initCollectionFileTeam(limit: number) {
|
||||||
/* init user default Team */
|
/* init user default Team */
|
||||||
const DatasetFile = connectionMongo.connection.db.collection(`dataset.files`);
|
const DatasetFile = getGFSCollection('dataset');
|
||||||
const matchWhere = {
|
const matchWhere = {
|
||||||
$or: [{ 'metadata.teamId': { $exists: false } }, { 'metadata.teamId': null }]
|
$or: [{ 'metadata.teamId': { $exists: false } }, { 'metadata.teamId': null }]
|
||||||
};
|
};
|
||||||
@ -264,7 +258,7 @@ async function initCollectionFileTeam(limit: number) {
|
|||||||
|
|
||||||
async function init(userId: string): Promise<any> {
|
async function init(userId: string): Promise<any> {
|
||||||
try {
|
try {
|
||||||
const tmb = await getTeamInfoByTmbId({
|
const tmb = await getUserDefaultTeam({
|
||||||
userId
|
userId
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -295,8 +289,8 @@ async function initPgData() {
|
|||||||
// add column
|
// add column
|
||||||
try {
|
try {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
PgClient.query(`ALTER TABLE ${PgDatasetTableName} ADD COLUMN team_id CHAR(50);`),
|
PgClient.query(`ALTER TABLE ${PgDatasetTableName} ADD COLUMN team_id VARCHAR(50);`),
|
||||||
PgClient.query(`ALTER TABLE ${PgDatasetTableName} ADD COLUMN tmb_id CHAR(50);`),
|
PgClient.query(`ALTER TABLE ${PgDatasetTableName} ADD COLUMN tmb_id VARCHAR(50);`),
|
||||||
PgClient.query(`ALTER TABLE ${PgDatasetTableName} ALTER COLUMN user_id DROP NOT NULL;`)
|
PgClient.query(`ALTER TABLE ${PgDatasetTableName} ALTER COLUMN user_id DROP NOT NULL;`)
|
||||||
]);
|
]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -316,7 +310,7 @@ async function initPgData() {
|
|||||||
const userId = rows[index]?.user_id;
|
const userId = rows[index]?.user_id;
|
||||||
if (!userId) return;
|
if (!userId) return;
|
||||||
try {
|
try {
|
||||||
const tmb = await getTeamInfoByTmbId({ userId });
|
const tmb = await getUserDefaultTeam({ userId });
|
||||||
// update pg
|
// update pg
|
||||||
await PgClient.query(
|
await PgClient.query(
|
||||||
`Update ${PgDatasetTableName} set team_id = '${tmb.teamId}', tmb_id = '${tmb.tmbId}' where user_id = '${userId}' AND team_id IS NULL;`
|
`Update ${PgDatasetTableName} set team_id = '${tmb.teamId}', tmb_id = '${tmb.tmbId}' where user_id = '${userId}' AND team_id IS NULL;`
|
||||||
|
|||||||
@ -80,8 +80,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
try {
|
try {
|
||||||
await connectToDatabase();
|
await connectToDatabase();
|
||||||
const { userId, teamId, tmbId } = await authCert({ req, authToken: true });
|
const { userId, teamId, tmbId } = await authCert({ req, authToken: true });
|
||||||
console.log(req.body);
|
|
||||||
|
|
||||||
const { files, bucketName, metadata } = await upload.doUpload(req, res);
|
const { files, bucketName, metadata } = await upload.doUpload(req, res);
|
||||||
|
|
||||||
const upLoadResults = await Promise.all(
|
const upLoadResults = await Promise.all(
|
||||||
|
|||||||
@ -4,15 +4,16 @@ import { connectToDatabase } from '@/service/mongo';
|
|||||||
import type { CreateQuestionGuideParams } from '@/global/core/ai/api.d';
|
import type { CreateQuestionGuideParams } from '@/global/core/ai/api.d';
|
||||||
import { pushQuestionGuideBill } from '@/service/support/wallet/bill/push';
|
import { pushQuestionGuideBill } from '@/service/support/wallet/bill/push';
|
||||||
import { createQuestionGuide } from '@fastgpt/service/core/ai/functions/createQuestionGuide';
|
import { createQuestionGuide } from '@fastgpt/service/core/ai/functions/createQuestionGuide';
|
||||||
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
import { authCertAndShareId } from '@fastgpt/service/support/permission/auth/common';
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||||
try {
|
try {
|
||||||
await connectToDatabase();
|
await connectToDatabase();
|
||||||
const { messages } = req.body as CreateQuestionGuideParams;
|
const { messages, shareId } = req.body as CreateQuestionGuideParams;
|
||||||
const { tmbId, teamId } = await authCert({
|
const { tmbId, teamId } = await authCertAndShareId({
|
||||||
req,
|
req,
|
||||||
authToken: true
|
authToken: true,
|
||||||
|
shareId
|
||||||
});
|
});
|
||||||
|
|
||||||
const qgModel = global.qgModels[0];
|
const qgModel = global.qgModels[0];
|
||||||
|
|||||||
@ -3,10 +3,11 @@ import { jsonRes } from '@fastgpt/service/common/response';
|
|||||||
import { connectToDatabase } from '@/service/mongo';
|
import { connectToDatabase } from '@/service/mongo';
|
||||||
import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
|
import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
|
||||||
import { getVectorModel } from '@/service/core/ai/model';
|
import { getVectorModel } from '@/service/core/ai/model';
|
||||||
import type { DatasetItemType } from '@/types/core/dataset';
|
import type { DatasetItemType } from '@fastgpt/global/core/dataset/type.d';
|
||||||
import { mongoRPermission } from '@fastgpt/global/support/permission/utils';
|
import { mongoRPermission } from '@fastgpt/global/support/permission/utils';
|
||||||
import { authUserRole } from '@fastgpt/service/support/permission/auth/user';
|
import { authUserRole } from '@fastgpt/service/support/permission/auth/user';
|
||||||
|
|
||||||
|
/* get all dataset by teamId or tmbId */
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||||
try {
|
try {
|
||||||
await connectToDatabase();
|
await connectToDatabase();
|
||||||
@ -20,7 +21,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
|
|
||||||
const data = datasets.map((item) => ({
|
const data = datasets.map((item) => ({
|
||||||
...item.toJSON(),
|
...item.toJSON(),
|
||||||
tags: item.tags.join(' '),
|
|
||||||
vectorModel: getVectorModel(item.vectorModel),
|
vectorModel: getVectorModel(item.vectorModel),
|
||||||
canWrite: String(item.tmbId) === tmbId,
|
canWrite: String(item.tmbId) === tmbId,
|
||||||
isOwner: teamOwner || String(item.tmbId) === tmbId
|
isOwner: teamOwner || String(item.tmbId) === tmbId
|
||||||
|
|||||||
@ -30,15 +30,15 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
const collections = await findCollectionAndChild(collectionId, '_id metadata');
|
const collections = await findCollectionAndChild(collectionId, '_id metadata');
|
||||||
const delIdList = collections.map((item) => item._id);
|
const delIdList = collections.map((item) => item._id);
|
||||||
|
|
||||||
// delete pg data
|
|
||||||
await delDataByCollectionId({ collectionIds: delIdList });
|
|
||||||
|
|
||||||
// delete training data
|
// delete training data
|
||||||
await MongoDatasetTraining.deleteMany({
|
await MongoDatasetTraining.deleteMany({
|
||||||
datasetCollectionId: { $in: delIdList },
|
collectionId: { $in: delIdList },
|
||||||
teamId
|
teamId
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// delete pg data
|
||||||
|
await delDataByCollectionId({ collectionIds: delIdList });
|
||||||
|
|
||||||
// delete file
|
// delete file
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
collections.map((collection) => {
|
collections.map((collection) => {
|
||||||
|
|||||||
@ -27,8 +27,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
jsonRes<DatasetCollectionItemType>(res, {
|
jsonRes<DatasetCollectionItemType>(res, {
|
||||||
data: {
|
data: {
|
||||||
...collection,
|
...collection,
|
||||||
datasetId: collection.datasetId._id,
|
canWrite,
|
||||||
canWrite
|
sourceName: collection?.name,
|
||||||
|
sourceId: collection?.metadata?.fileId || collection?.metadata?.rawLink
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@ -3,15 +3,15 @@ import { jsonRes } from '@fastgpt/service/common/response';
|
|||||||
import { connectToDatabase } from '@/service/mongo';
|
import { connectToDatabase } from '@/service/mongo';
|
||||||
import { DatasetTrainingCollectionName } from '@fastgpt/service/core/dataset/training/schema';
|
import { DatasetTrainingCollectionName } from '@fastgpt/service/core/dataset/training/schema';
|
||||||
import { Types } from '@fastgpt/service/common/mongo';
|
import { Types } from '@fastgpt/service/common/mongo';
|
||||||
import type { DatasetCollectionsListItemType } from '@/global/core/dataset/response';
|
import type { DatasetCollectionsListItemType } from '@/global/core/dataset/type.d';
|
||||||
import type { GetDatasetCollectionsProps } from '@/global/core/api/datasetReq';
|
import type { GetDatasetCollectionsProps } from '@/global/core/api/datasetReq';
|
||||||
import { PagingData } from '@/types';
|
import { PagingData } from '@/types';
|
||||||
import { MongoDatasetCollection } from '@fastgpt/service/core/dataset/collection/schema';
|
import { MongoDatasetCollection } from '@fastgpt/service/core/dataset/collection/schema';
|
||||||
import { countCollectionData } from '@/service/core/dataset/data/utils';
|
|
||||||
import { DatasetCollectionTypeEnum } from '@fastgpt/global/core/dataset/constant';
|
import { DatasetCollectionTypeEnum } from '@fastgpt/global/core/dataset/constant';
|
||||||
import { startQueue } from '@/service/utils/tools';
|
import { startQueue } from '@/service/utils/tools';
|
||||||
import { authDataset } from '@fastgpt/service/support/permission/auth/dataset';
|
import { authDataset } from '@fastgpt/service/support/permission/auth/dataset';
|
||||||
import { getTeamInfoByTmbId } from '@fastgpt/service/support/user/team/controller';
|
import { DatasetDataCollectionName } from '@fastgpt/service/core/dataset/data/schema';
|
||||||
|
import { authUserRole } from '@fastgpt/service/support/permission/auth/user';
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||||
try {
|
try {
|
||||||
@ -30,7 +30,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
|
|
||||||
// auth dataset and get my role
|
// auth dataset and get my role
|
||||||
const { tmbId } = await authDataset({ req, authToken: true, datasetId, per: 'r' });
|
const { tmbId } = await authDataset({ req, authToken: true, datasetId, per: 'r' });
|
||||||
const { canWrite } = await getTeamInfoByTmbId({ tmbId });
|
const { canWrite } = await authUserRole({ req, authToken: true });
|
||||||
|
|
||||||
const match = {
|
const match = {
|
||||||
datasetId: new Types.ObjectId(datasetId),
|
datasetId: new Types.ObjectId(datasetId),
|
||||||
@ -59,7 +59,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
...item,
|
...item,
|
||||||
dataAmount: 0,
|
dataAmount: 0,
|
||||||
trainingAmount: 0,
|
trainingAmount: 0,
|
||||||
canWrite // admin or owner can write
|
canWrite // admin or team owner can write
|
||||||
}))
|
}))
|
||||||
),
|
),
|
||||||
total: await MongoDatasetCollection.countDocuments(match)
|
total: await MongoDatasetCollection.countDocuments(match)
|
||||||
@ -67,51 +67,75 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const collections: DatasetCollectionsListItemType[] = await MongoDatasetCollection.aggregate([
|
const [collections, total]: [DatasetCollectionsListItemType[], number] = await Promise.all([
|
||||||
{
|
MongoDatasetCollection.aggregate([
|
||||||
$match: match
|
{
|
||||||
},
|
$match: match
|
||||||
{
|
},
|
||||||
$lookup: {
|
{
|
||||||
from: DatasetTrainingCollectionName,
|
$lookup: {
|
||||||
localField: '_id',
|
from: DatasetTrainingCollectionName,
|
||||||
foreignField: 'datasetCollectionId',
|
let: { id: '$_id' },
|
||||||
as: 'trainings_amount'
|
pipeline: [
|
||||||
|
{
|
||||||
|
$match: {
|
||||||
|
$expr: {
|
||||||
|
$eq: ['$collectionId', '$$id']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ $project: { _id: 1 } }
|
||||||
|
],
|
||||||
|
as: 'trainings'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$lookup: {
|
||||||
|
from: DatasetDataCollectionName,
|
||||||
|
let: { id: '$_id' },
|
||||||
|
pipeline: [
|
||||||
|
{
|
||||||
|
$match: {
|
||||||
|
$expr: {
|
||||||
|
$eq: ['$collectionId', '$$id']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ $project: { _id: 1 } }
|
||||||
|
],
|
||||||
|
as: 'datas'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 统计子集合的数量和子训练的数量
|
||||||
|
{
|
||||||
|
$project: {
|
||||||
|
_id: 1,
|
||||||
|
parentId: 1,
|
||||||
|
tmbId: 1,
|
||||||
|
name: 1,
|
||||||
|
type: 1,
|
||||||
|
updateTime: 1,
|
||||||
|
trainingAmount: { $size: '$trainings' },
|
||||||
|
dataAmount: { $size: '$datas' },
|
||||||
|
metadata: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$sort: { updateTime: -1 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$skip: (pageNum - 1) * pageSize
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$limit: pageSize
|
||||||
}
|
}
|
||||||
},
|
]),
|
||||||
// 统计子集合的数量和子训练的数量
|
MongoDatasetCollection.countDocuments(match)
|
||||||
{
|
|
||||||
$project: {
|
|
||||||
_id: 1,
|
|
||||||
parentId: 1,
|
|
||||||
tmbId: 1,
|
|
||||||
name: 1,
|
|
||||||
type: 1,
|
|
||||||
updateTime: 1,
|
|
||||||
trainingAmount: { $size: '$trainings_amount' },
|
|
||||||
metadata: 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
$sort: { updateTime: -1 }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
$skip: (pageNum - 1) * pageSize
|
|
||||||
},
|
|
||||||
{
|
|
||||||
$limit: pageSize
|
|
||||||
}
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const counts = await countCollectionData({
|
|
||||||
collectionIds: collections.map((item) => item._id),
|
|
||||||
datasetId
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await Promise.all(
|
const data = await Promise.all(
|
||||||
collections.map(async (item, i) => ({
|
collections.map(async (item, i) => ({
|
||||||
...item,
|
...item,
|
||||||
dataAmount: item.type === DatasetCollectionTypeEnum.folder ? undefined : counts[i],
|
|
||||||
canWrite: String(item.tmbId) === tmbId || canWrite
|
canWrite: String(item.tmbId) === tmbId || canWrite
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
@ -126,7 +150,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
pageNum,
|
pageNum,
|
||||||
pageSize,
|
pageSize,
|
||||||
data,
|
data,
|
||||||
total: await MongoDatasetCollection.countDocuments(match)
|
total
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
import { jsonRes } from '@fastgpt/service/common/response';
|
import { jsonRes } from '@fastgpt/service/common/response';
|
||||||
import { connectToDatabase } from '@/service/mongo';
|
import { connectToDatabase } from '@/service/mongo';
|
||||||
import type { DatasetPathItemType } from '@/types/core/dataset';
|
import type { ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type.d';
|
||||||
import { getDatasetCollectionPaths } from '@fastgpt/service/core/dataset/collection/utils';
|
import { getDatasetCollectionPaths } from '@fastgpt/service/core/dataset/collection/utils';
|
||||||
import { authDatasetCollection } from '@fastgpt/service/support/permission/auth/dataset';
|
import { authDatasetCollection } from '@fastgpt/service/support/permission/auth/dataset';
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
parentId
|
parentId
|
||||||
});
|
});
|
||||||
|
|
||||||
jsonRes<DatasetPathItemType[]>(res, {
|
jsonRes<ParentTreePathItemType[]>(res, {
|
||||||
data: paths
|
data: paths
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
|
|||||||
import { jsonRes } from '@fastgpt/service/common/response';
|
import { jsonRes } from '@fastgpt/service/common/response';
|
||||||
import { connectToDatabase } from '@/service/mongo';
|
import { connectToDatabase } from '@/service/mongo';
|
||||||
import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
|
import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
|
||||||
import type { CreateDatasetParams } from '@/global/core/api/datasetReq.d';
|
import type { CreateDatasetParams } from '@/global/core/dataset/api.d';
|
||||||
import { createDefaultCollection } from './collection/create';
|
import { createDefaultCollection } from './collection/create';
|
||||||
import { authUserNotVisitor } from '@fastgpt/service/support/permission/auth/user';
|
import { authUserNotVisitor } from '@fastgpt/service/support/permission/auth/user';
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
import { jsonRes } from '@fastgpt/service/common/response';
|
import { jsonRes } from '@fastgpt/service/common/response';
|
||||||
import { PgClient } from '@fastgpt/service/common/pg';
|
|
||||||
import { withNextCors } from '@fastgpt/service/common/middle/cors';
|
import { withNextCors } from '@fastgpt/service/common/middle/cors';
|
||||||
import { PgDatasetTableName } from '@fastgpt/global/core/dataset/constant';
|
|
||||||
import { connectToDatabase } from '@/service/mongo';
|
import { connectToDatabase } from '@/service/mongo';
|
||||||
import { authDatasetData } from '@/service/support/permission/auth/dataset';
|
import { authDatasetData } from '@/service/support/permission/auth/dataset';
|
||||||
|
import { deleteDataByDataId } from '@/service/core/dataset/data/controller';
|
||||||
|
|
||||||
export default withNextCors(async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
export default withNextCors(async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||||
try {
|
try {
|
||||||
@ -20,11 +19,11 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
|||||||
// 凭证校验
|
// 凭证校验
|
||||||
await authDatasetData({ req, authToken: true, dataId, per: 'w' });
|
await authDatasetData({ req, authToken: true, dataId, per: 'w' });
|
||||||
|
|
||||||
await PgClient.delete(PgDatasetTableName, {
|
await deleteDataByDataId(dataId);
|
||||||
where: [['id', dataId]]
|
|
||||||
});
|
|
||||||
|
|
||||||
jsonRes(res);
|
jsonRes(res, {
|
||||||
|
data: 'success'
|
||||||
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
jsonRes(res, {
|
jsonRes(res, {
|
||||||
@ -13,12 +13,9 @@ export type Response = {
|
|||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||||
try {
|
try {
|
||||||
await connectToDatabase();
|
await connectToDatabase();
|
||||||
let { dataId } = req.query as {
|
const { dataId } = req.query as {
|
||||||
dataId: string;
|
dataId: string;
|
||||||
};
|
};
|
||||||
if (!dataId) {
|
|
||||||
throw new Error('缺少参数');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 凭证校验
|
// 凭证校验
|
||||||
const { datasetData } = await authDatasetData({ req, authToken: true, dataId, per: 'r' });
|
const { datasetData } = await authDatasetData({ req, authToken: true, dataId, per: 'r' });
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user