Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
赵月辉
/
fastgpt-migrated
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
aab6ee51
authored
Jan 22, 2024
by
Archer
Committed by
GitHub
Jan 22, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
V4.6.7-production (#759)
parent
91b7d81c
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
41 changed files
with
365 additions
and
581 deletions
+365
-581
README.md
+6
-6
README_en.md
+46
-42
docSite/content/docs/development/openapi/chat.md
+2
-2
docSite/content/docs/development/openapi/dataset.md
+0
-0
docSite/content/docs/development/upgrading/467.md
+5
-4
packages/global/common/error/utils.ts
+3
-1
packages/global/common/string/tools.ts
+6
-0
packages/service/common/file/utils.ts
+1
-1
packages/service/common/response/index.ts
+3
-2
packages/service/support/permission/controller.ts
+4
-0
packages/web/components/common/Icon/icons/support/account/loginoutLight.svg
+13
-2
projects/app/public/docs/versionIntro.md
+6
-5
projects/app/public/locales/zh/common.json
+3
-2
projects/app/src/components/ChatBox/MessageInput.tsx
+20
-6
projects/app/src/components/ChatBox/index.tsx
+0
-0
projects/app/src/components/Markdown/index.tsx
+69
-60
projects/app/src/components/common/Textarea/TagTextarea.tsx
+2
-0
projects/app/src/components/core/module/AIChatSettingsModal.tsx
+9
-4
projects/app/src/components/support/user/team/TeamManageModal/InviteModal.tsx
+7
-5
projects/app/src/components/support/user/team/TeamManageModal/index.tsx
+2
-8
projects/app/src/pages/account/components/Info.tsx
+24
-20
projects/app/src/pages/api/core/dataset/collection/create/file.ts
+0
-85
projects/app/src/pages/api/core/dataset/collection/create/link.ts
+0
-91
projects/app/src/pages/api/core/dataset/collection/create/text.ts
+0
-117
projects/app/src/pages/api/core/dataset/create.ts
+5
-4
projects/app/src/pages/api/core/dataset/delete.ts
+7
-1
projects/app/src/pages/api/plusApi/[...path].ts
+0
-64
projects/app/src/pages/api/proApi/[...path].ts
+56
-0
projects/app/src/pages/dataset/detail/index.tsx
+1
-1
projects/app/src/pages/dataset/list/index.tsx
+17
-4
projects/app/src/pages/login/provider.tsx
+3
-3
projects/app/src/web/common/hooks/useConfirm.tsx
+3
-3
projects/app/src/web/core/dataset/api.ts
+2
-2
projects/app/src/web/core/dataset/utils.ts
+14
-10
projects/app/src/web/support/activity/promotion/api.ts
+2
-2
projects/app/src/web/support/user/api.ts
+5
-5
projects/app/src/web/support/user/inform/api.ts
+3
-3
projects/app/src/web/support/user/team/api.ts
+11
-11
projects/app/src/web/support/wallet/bill/api.ts
+1
-1
projects/app/src/web/support/wallet/pay/api.ts
+3
-3
projects/app/src/web/support/wallet/sub/api.ts
+1
-1
No files found.
README.md
View file @
aab6ee51
...
...
@@ -57,7 +57,7 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
-
[
x
]
源文件引用追踪
-
[
x
]
模块封装,实现多级复用
-
[
x
]
混合检索 & 重排
-
[
]
自查询规划
-
[
]
Tool 模块
-
[
]
嵌入
[
Laf
](
https://github.com/labring/laf
)
,实现在线编写 HTTP 模块
-
[
]
插件封装功能
...
...
@@ -67,10 +67,10 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
-
[
x
]
支持知识库单独设置向量模型
-
[
x
]
源文件存储
-
[
x
]
支持手动输入,直接分段,QA 拆分导入
-
[
x
]
支持 pdf、word、txt、md 等常用文件,支持 url 读取、CSV 批量导入
-
[
]
支持 HTML、csv、PPT、Excel 导入
-
[
x
]
支持 pdf,docx,txt,html,md,csv
-
[
x
]
支持 url 读取、CSV 批量导入
-
[
]
支持 PPT、Excel 导入
-
[
]
支持文件阅读器
-
[
]
支持差异性文件同步
-
[
]
更多的数据预处理方案
`3`
应用调试能力
...
...
@@ -81,8 +81,8 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
-
[
]
高级编排 DeBug 模式
`4`
OpenAPI 接口
-
[
x
]
completions 接口 (对齐 GPT 接口)
-
[
]
知识库 CRUD
-
[
x
]
completions 接口 (
chat 模式
对齐 GPT 接口)
-
[
x
]
知识库 CRUD
-
[
]
对话 CRUD
`5`
运营能力
...
...
README_en.md
View file @
aab6ee51
...
...
@@ -49,48 +49,52 @@ Cloud: [fastgpt.in](https://fastgpt.in/)
## 💡 Features
1.
Powerful visual workflows: Effortlessly craft AI applications
-
[
x
]
Simple mode on deck - no need for manual arrangement
-
[
x
]
User dialogue pre-guidance
-
[
x
]
Global variables
-
[
x
]
Knowledge base search
-
[
x
]
Dialogue via multiple LLM models
-
[
x
]
Text magic - convert to structured data
-
[
x
]
Extend with HTTP
-
[
]
Embed Laf for on-the-fly HTTP module crafting
-
[
x
]
Directions for the next dialogue steps
-
[
x
]
Tracking source file references
-
[
]
Custom file reader
-
[
]
Modules are packaged into plug-ins to achieve reuse
2.
Extensive knowledge base preprocessing
-
[
x
]
Reuse and mix multiple knowledge bases
-
[
x
]
Track chunk modifications and deletions
-
[
x
]
Supports manual entries, direct segmentation, and QA split imports
-
[
x
]
Supports URL fetching and batch CSV imports
-
[
x
]
Supports Set unique vector models for knowledge bases
-
[
x
]
Store original files
-
[
]
File learning Agent
3.
Multiple effect testing channels
-
[
x
]
Single-point knowledge base search test
-
[
x
]
Feedback references and ability to modify and delete during dialogue
-
[
x
]
Complete context presentation
-
[
]
Complete module intermediate value presentation
4.
OpenAPI
-
[
x
]
completions interface (aligned with GPT interface)
-
[
]
Knowledge base CRUD
5.
Operational functions
-
[
x
]
Login-free sharing window
-
[
x
]
One-click embedding with Iframe
-
[
]
Unified access to dialogue records
`1`
Application Orchestration Features
-
[
x
]
Offers a straightforward mode, eliminating the need for complex orchestration
-
[
x
]
Provides clear next-step instructions in dialogues
-
[
x
]
Facilitates workflow orchestration
-
[
x
]
Tracks references in source files
-
[
x
]
Encapsulates modules for enhanced reuse at multiple levels
-
[
x
]
Combines search and reordering functions
-
[
]
Includes a tool module
-
[
]
Integrates
[
Laf
](
https://github.com/labring/laf
)
for online HTTP module creation
-
[
]
Plugin encapsulation capabilities
`2`
Knowledge Base Features
-
[
x
]
Allows for the mixed use of multiple databases
-
[
x
]
Keeps track of modifications and deletions in data chunks
-
[
x
]
Enables specific vector models for each knowledge base
-
[
x
]
Stores original source files
-
[
x
]
Supports direct input and segment-based QA import
-
[
x
]
Compatible with a variety of file formats: pdf, docx, txt, html, md, csv
-
[
x
]
Facilitates URL reading and bulk CSV importing
-
[
]
Supports PPT and Excel file import
-
[
]
Features a file reader
-
[
]
Offers diverse data preprocessing options
`3`
Application Debugging Features
-
[
x
]
Enables targeted search testing within the knowledge base
-
[
x
]
Allows feedback, editing, and deletion during conversations
-
[
x
]
Presents the full context of interactions
-
[
x
]
Displays all intermediate values within modules
-
[
]
Advanced DeBug mode for orchestration
`4`
OpenAPI Interface
-
[
x
]
The completions interface (aligned with GPT's chat mode interface)
-
[
x
]
CRUD operations for the knowledge base
-
[
]
CRUD operations for conversations
`5`
Operational Features
-
[
x
]
Share without requiring login
-
[
x
]
Easy embedding with Iframe
-
[
x
]
Customizable chat window embedding with features like default open, drag-and-drop
-
[
x
]
Centralizes conversation records for review and annotation
<a
href=
"#readme"
>
<img
src=
"https://img.shields.io/badge/-Back_to_Top-7d09f1.svg"
alt=
"#"
align=
"right"
>
...
...
docSite/content/docs/development/openapi/chat.md
View file @
aab6ee51
...
...
@@ -48,7 +48,7 @@ curl --location --request POST 'https://api.fastgpt.in/api/v1/chat/completions'
{{
<
/
markdownify
>
}}
{{
<
/
tab
>
}}
{{
<
tab
tabName=
"
detail=true 响应
"
>
}}
{{
<
tab
tabName=
"
参数说明
"
>
}}
{{
<
markdownify
>
}}
{{% alert context="info" %}}
...
...
@@ -56,7 +56,7 @@ curl --location --request POST 'https://api.fastgpt.in/api/v1/chat/completions'
-
chatId: string | undefined 。
-
为
`undefined`
时(不传入),不使用 FastGpt 提供的上下文功能,完全通过传入的 messages 构建上下文。 不会将你的记录存储到数据库中,你也无法在记录汇总中查阅到。
-
为
`非空字符串`
时,意味着使用 chatId 进行对话,自动从 FastGpt 数据库取历史记录,并使用 messages 数组最后一个内容作为用户问题。请自行确保 chatId 唯一,长度小于250,通常可以是自己系统的对话框ID。
-
messages: 结构与
[
GPT接口
](
https://platform.openai.com/docs/api-reference/chat/object
)
完全
一致。
-
messages: 结构与
[
GPT接口
](
https://platform.openai.com/docs/api-reference/chat/object
)
chat模式
一致。
-
detail: 是否返回中间值(模块状态,响应的完整结果等),
`stream模式`
下会通过
`event`
进行区分,
`非stream模式`
结果保存在
`responseData`
中。
-
variables: 模块变量,一个对象,会替换模块中,输入框内容里的
`{{key}}`
{{% /alert %}}
...
...
docSite/content/docs/development/openapi/dataset.md
View file @
aab6ee51
This diff is collapsed.
Click to expand it.
docSite/content/docs/development/upgrading/467.md
View file @
aab6ee51
...
...
@@ -27,7 +27,8 @@ curl --location --request POST 'https://{{host}}/api/admin/initv467' \
1.
修改了知识库UI及新的导入交互方式。
2.
优化知识库和对话的数据索引。
3.
知识库 openAPI,支持通过
API 操作知识库。(文档待补充)
3.
知识库 openAPI,支持通过
[
API 操作知识库
](
/docs/development/openapi/dataset
)
。
4.
新增 - 输入框变量提示。输入 { 号后将会获得可用变量提示。根据社区针对高级编排的反馈,我们计划于 2 月份的版本中,优化变量内容,支持模块的局部变量以及更多全局变量写入。
5.
修复 - API 对话时,chatId 冲突问题。
6.
修复 - Iframe 嵌入网页可能导致的 window.onLoad 冲突。
\ No newline at end of file
5.
优化 - 切换团队后会保存记录,下次登录时优先登录该团队。
6.
修复 - API 对话时,chatId 冲突问题。
7.
修复 - Iframe 嵌入网页可能导致的 window.onLoad 冲突。
\ No newline at end of file
packages/global/common/error/utils.ts
View file @
aab6ee51
import
{
replaceSensitiveLink
}
from
'../string/tools'
;
export
const
getErrText
=
(
err
:
any
,
def
=
''
)
=>
{
const
msg
:
string
=
typeof
err
===
'string'
?
err
:
err
?.
message
||
def
||
''
;
msg
&&
console
.
log
(
'error =>'
,
msg
);
return
msg
;
return
replaceSensitiveLink
(
msg
)
;
};
packages/global/common/string/tools.ts
View file @
aab6ee51
...
...
@@ -38,6 +38,12 @@ export function replaceVariable(text: string, obj: Record<string, string | numbe
return
text
||
''
;
}
/* replace sensitive link */
export
const
replaceSensitiveLink
=
(
text
:
string
)
=>
{
const
urlRegex
=
/
(?<
=https
?
:
\/\/)[^\s]
+/g
;
return
text
.
replace
(
urlRegex
,
'xxx'
);
};
export
const
getNanoid
=
(
size
=
12
)
=>
{
return
customAlphabet
(
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
,
size
)();
};
packages/service/common/file/utils.ts
View file @
aab6ee51
...
...
@@ -4,7 +4,7 @@ export const removeFilesByPaths = (paths: string[]) => {
paths
.
forEach
((
path
)
=>
{
fs
.
unlink
(
path
,
(
err
)
=>
{
if
(
err
)
{
console
.
error
(
err
);
//
console.error(err);
}
});
});
...
...
packages/service/common/response/index.ts
View file @
aab6ee51
...
...
@@ -3,6 +3,7 @@ import { sseResponseEventEnum } from './constant';
import
{
proxyError
,
ERROR_RESPONSE
,
ERROR_ENUM
}
from
'@fastgpt/global/common/error/errorCode'
;
import
{
addLog
}
from
'../system/log'
;
import
{
clearCookie
}
from
'../../support/permission/controller'
;
import
{
replaceSensitiveLink
}
from
'@fastgpt/global/common/string/tools'
;
export
interface
ResponseType
<
T
=
any
>
{
code
:
number
;
...
...
@@ -52,7 +53,7 @@ export const jsonRes = <T = any>(
res
.
status
(
code
).
json
({
code
,
statusText
:
''
,
message
:
message
||
msg
,
message
:
replaceSensitiveLink
(
message
||
msg
)
,
data
:
data
!==
undefined
?
data
:
null
});
};
...
...
@@ -90,7 +91,7 @@ export const sseErrRes = (res: NextApiResponse, error: any) => {
responseWrite({
res,
event: sseResponseEventEnum.error,
data: JSON.stringify({ message:
msg
})
data: JSON.stringify({ message:
replaceSensitiveLink(msg)
})
});
};
...
...
packages/service/support/permission/controller.ts
View file @
aab6ee51
...
...
@@ -168,6 +168,10 @@ export async function parseHeaderCert({
return
Promise
.
reject
(
ERROR_ENUM
.
unAuthorization
);
})();
if
(
!
authRoot
&&
(
!
teamId
||
!
tmbId
))
{
return
Promise
.
reject
(
ERROR_ENUM
.
unAuthorization
);
}
return
{
userId
:
String
(
uid
),
teamId
:
String
(
teamId
),
...
...
packages/web/components/common/Icon/icons/support/account/loginoutLight.svg
View file @
aab6ee51
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
t=
"1689855121257"
class=
"icon"
viewBox=
"0 0 1024 1024"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
p-id=
"3135"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
width=
"64"
height=
"64"
><path
d=
"M952.7 492.1c-1.4-1.8-3.1-3.4-4.8-4.9l-179-178.9c-12.5-12.5-32.9-12.5-45.4 0s-12.5 32.9 0 45.4l126 126H421.3h-0.1c-18.2 0-32.9 14.8-32.9 33s14.7 33 32.9 33c0.3 0.1 0.5 0 0.7 0h427.8l-126 126c-12.3 12.3-12.3 32.4 0 44.7l0.7 0.7c12.3 12.3 32.4 12.3 44.7 0l182-182c11.7-11.7 12.3-30.6 1.6-43z"
fill=
"#515151"
p-id=
"3136"
></path><path
d=
"M562.3 799c-18 0-32.7 14.7-32.7 32.7v63.8H129.2V128.7h400.4v63.1c0 18 14.7 32.7 32.7 32.7s32.7-14.7 32.7-32.7V96.3c0-3.5-0.6-6.8-1.6-10-4.2-13.3-16.6-23-31.2-23H96.6c-18 0-32.7 14.7-32.7 32.7v831.9c0 14.2 9.2 26.3 21.8 30.8 3.6 1.4 7.5 2.1 11.5 2.1h463.2c0.6 0 1.3 0.1 1.9 0.1 18 0 32.7-14.7 32.7-32.7v-96.5c0-18-14.7-32.7-32.7-32.7z"
fill=
"#515151"
p-id=
"3137"
></path><path
d=
"M256.8 512.7a32.9 33 0 1 0 65.8 0 32.9 33 0 1 0-65.8 0Z"
fill=
"#515151"
p-id=
"3138"
></path></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
t=
"1689855121257"
class=
"icon"
viewBox=
"0 0 1024 1024"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
p-id=
"3135"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
width=
"64"
height=
"64"
>
<path
d=
"M952.7 492.1c-1.4-1.8-3.1-3.4-4.8-4.9l-179-178.9c-12.5-12.5-32.9-12.5-45.4 0s-12.5 32.9 0 45.4l126 126H421.3h-0.1c-18.2 0-32.9 14.8-32.9 33s14.7 33 32.9 33c0.3 0.1 0.5 0 0.7 0h427.8l-126 126c-12.3 12.3-12.3 32.4 0 44.7l0.7 0.7c12.3 12.3 32.4 12.3 44.7 0l182-182c11.7-11.7 12.3-30.6 1.6-43z"
p-id=
"3136"
></path>
<path
d=
"M562.3 799c-18 0-32.7 14.7-32.7 32.7v63.8H129.2V128.7h400.4v63.1c0 18 14.7 32.7 32.7 32.7s32.7-14.7 32.7-32.7V96.3c0-3.5-0.6-6.8-1.6-10-4.2-13.3-16.6-23-31.2-23H96.6c-18 0-32.7 14.7-32.7 32.7v831.9c0 14.2 9.2 26.3 21.8 30.8 3.6 1.4 7.5 2.1 11.5 2.1h463.2c0.6 0 1.3 0.1 1.9 0.1 18 0 32.7-14.7 32.7-32.7v-96.5c0-18-14.7-32.7-32.7-32.7z"
p-id=
"3137"
></path>
<path
d=
"M256.8 512.7a32.9 33 0 1 0 65.8 0 32.9 33 0 1 0-65.8 0Z"
p-id=
"3138"
></path>
</svg>
\ No newline at end of file
projects/app/public/docs/versionIntro.md
View file @
aab6ee51
...
...
@@ -4,8 +4,9 @@
2.
优化知识库和对话的数据索引,加快数据操作。
3.
知识库 openAPI,支持通过 API 操作知识库。
4.
新增 - 输入框变量提示。输入 { 号后将会获得可用变量提示。根据社区针对高级编排的反馈,我们计划于 2 月份的版本中,优化变量内容,支持模块的局部变量以及更多全局变量写入。
5.
修复 - API 对话时,chatId 冲突问题。
6.
修复 - Iframe 嵌入网页可能导致的 window.onLoad 冲突。
7.
[
使用文档
](
https://doc.fastgpt.in/docs/intro/
)
8.
[
点击查看高级编排介绍文档
](
https://doc.fastgpt.in/docs/workflow
)
9.
[
点击查看商业版
](
https://doc.fastgpt.in/docs/commercial/
)
5.
优化 - 切换团队后会保存记录,下次登录时优先登录该团队。
6.
修复 - API 对话时,chatId 冲突问题。
7.
修复 - Iframe 嵌入网页可能导致的 window.onLoad 冲突。
8.
[
使用文档
](
https://doc.fastgpt.in/docs/intro/
)
9.
[
点击查看高级编排介绍文档
](
https://doc.fastgpt.in/docs/workflow
)
10.
[
点击查看商业版
](
https://doc.fastgpt.in/docs/commercial/
)
projects/app/public/locales/zh/common.json
View file @
aab6ee51
...
...
@@ -95,7 +95,7 @@
"Last Step"
:
"上一步"
,
"Last use time"
:
"最后使用时间"
,
"Load Failed"
:
"加载失败"
,
"Loading"
:
"加载中"
,
"Loading"
:
"加载中
...
"
,
"Max credit"
:
"最大金额"
,
"Max credit tips"
:
"该链接最大可消耗多少金额,超出后链接将被禁止使用。-1 代表无限制。"
,
"More settings"
:
"更多设置"
,
...
...
@@ -541,7 +541,8 @@
"success"
:
"开始同步"
}
},
"training"
:
{}
"training"
:
{
}
},
"data"
:
{
"Auxiliary Data"
:
"辅助数据"
,
...
...
projects/app/src/components/ChatBox/MessageInput.tsx
View file @
aab6ee51
import
{
useSpeech
}
from
'@/web/common/hooks/useSpeech'
;
import
{
useSystemStore
}
from
'@/web/common/system/useSystemStore'
;
import
{
Box
,
Flex
,
Image
,
Spinner
,
Textarea
}
from
'@chakra-ui/react'
;
import
React
,
{
useRef
,
useEffect
,
useCallback
,
useState
}
from
'react'
;
import
React
,
{
useRef
,
useEffect
,
useCallback
,
useState
,
useTransition
}
from
'react'
;
import
{
useTranslation
}
from
'next-i18next'
;
import
MyTooltip
from
'../MyTooltip'
;
import
MyIcon
from
'@fastgpt/web/components/common/Icon'
;
...
...
@@ -37,7 +37,7 @@ const MessageInput = ({
showFileSelector
=
false
,
resetInputVal
}:
{
onChange
:
(
e
:
string
)
=>
void
;
onChange
?
:
(
e
:
string
)
=>
void
;
onSendMessage
:
(
e
:
string
)
=>
void
;
onStop
:
()
=>
void
;
isChatting
:
boolean
;
...
...
@@ -45,6 +45,8 @@ const MessageInput = ({
TextareaDom
:
React
.
MutableRefObject
<
HTMLTextAreaElement
|
null
>
;
resetInputVal
:
(
val
:
string
)
=>
void
;
})
=>
{
const
[,
startSts
]
=
useTransition
();
const
{
shareId
}
=
useRouter
().
query
as
{
shareId
?:
string
};
const
{
isSpeaking
,
...
...
@@ -330,17 +332,29 @@ ${images.map((img) => JSON.stringify({ src: img.src })).join('\n')}
const
textarea
=
e
.
target
;
textarea
.
style
.
height
=
textareaMinH
;
textarea
.
style
.
height
=
`${textarea.scrollHeight}px`
;
onChange
(
textarea
.
value
);
startSts
(()
=>
{
onChange
?.(
textarea
.
value
);
});
}
}
onKeyDown=
{
(
e
)
=>
{
// enter send.(pc or iframe && enter and unPress shift)
if
((
isPc
||
window
!==
parent
)
&&
e
.
keyCode
===
13
&&
!
e
.
shiftKey
)
{
handleSend
();
e
.
preventDefault
();
const
isEnter
=
e
.
keyCode
===
13
;
if
(
isEnter
&&
TextareaDom
.
current
&&
(
e
.
ctrlKey
||
e
.
altKey
))
{
TextareaDom
.
current
.
value
+=
'\n'
;
TextareaDom
.
current
.
style
.
height
=
textareaMinH
;
TextareaDom
.
current
.
style
.
height
=
`${TextareaDom.current.scrollHeight}px`
;
return
;
}
// 全选内容
// @ts-ignore
e
.
key
===
'a'
&&
e
.
ctrlKey
&&
e
.
target
?.
select
();
if
((
isPc
||
window
!==
parent
)
&&
e
.
keyCode
===
13
&&
!
e
.
shiftKey
)
{
handleSend
();
e
.
preventDefault
();
}
}
}
onPaste=
{
(
e
)
=>
{
const
clipboardData
=
e
.
clipboardData
;
...
...
projects/app/src/components/ChatBox/index.tsx
View file @
aab6ee51
This diff is collapsed.
Click to expand it.
projects/app/src/components/Markdown/index.tsx
View file @
aab6ee51
...
...
@@ -35,36 +35,79 @@ export enum CodeClassName {
img
=
'img'
}
function
Code
({
inline
,
className
,
children
}:
any
)
{
const
match
=
/language-
(\w
+
)
/
.
exec
(
className
||
''
);
const
codeType
=
match
?.[
1
];
const
Markdown
=
({
source
,
isChatting
=
false
}:
{
source
:
string
;
isChatting
?:
boolean
})
=>
{
const
components
=
useMemo
<
any
>
(
()
=>
({
img
:
Image
,
pre
:
'div'
,
p
:
(
pProps
:
any
)
=>
<
p
{
...
pProps
}
dir=
"auto"
/>,
code
:
Code
,
a
:
A
}),
[]
);
if
(
codeType
===
CodeClassName
.
mermaid
)
{
return
<
MermaidCodeBlock
code=
{
String
(
children
)
}
/>;
}
const
formatSource
=
source
.
replace
(
/
\\
n/g
,
'\n '
)
.
replace
(
/
(
http
[
s
]?
:
\/\/[^\s
,。
]
+
)([
。,
])
/g
,
'$1 $2'
)
.
replace
(
/
\n
*
(\[
QUOTE SIGN
\]\(
.*
\))
/g
,
'$1'
);
if
(
codeType
===
CodeClassName
.
guide
)
{
return
<
ChatGuide
text=
{
String
(
children
)
}
/>;
}
if
(
codeType
===
CodeClassName
.
questionGuide
)
{
return
<
QuestionGuide
text=
{
String
(
children
)
}
/>;
}
if
(
codeType
===
CodeClassName
.
echarts
)
{
return
<
EChartsCodeBlock
code=
{
String
(
children
)
}
/>;
}
if
(
codeType
===
CodeClassName
.
img
)
{
return
<
ImageBlock
images=
{
String
(
children
)
}
/>;
}
return
(
<
CodeLight
className=
{
className
}
inline=
{
inline
}
match=
{
match
}
>
{
children
}
</
CodeLight
>
<
ReactMarkdown
className=
{
`markdown ${styles.markdown}
${isChatting ? `
$
{
formatSource
?
styles
.
waitingAnimation
:
styles
.
animation
}
` : ''}
`
}
remarkPlugins=
{
[
RemarkMath
,
RemarkGfm
,
RemarkBreaks
]
}
rehypePlugins=
{
[
RehypeKatex
]
}
components=
{
components
}
linkTarget=
{
'_blank'
}
>
{
formatSource
}
</
ReactMarkdown
>
);
}
function
Image
({
src
}:
{
src
?:
string
})
{
};
export
default
React
.
memo
(
Markdown
);
const
Code
=
React
.
memo
(
function
Code
(
e
:
any
)
{
const
{
inline
,
className
,
children
}
=
e
;
const
match
=
/language-
(\w
+
)
/
.
exec
(
className
||
''
);
const
codeType
=
match
?.[
1
];
const
strChildren
=
String
(
children
);
const
Component
=
useMemo
(()
=>
{
if
(
codeType
===
CodeClassName
.
mermaid
)
{
return
<
MermaidCodeBlock
code=
{
strChildren
}
/>;
}
if
(
codeType
===
CodeClassName
.
guide
)
{
return
<
ChatGuide
text=
{
strChildren
}
/>;
}
if
(
codeType
===
CodeClassName
.
questionGuide
)
{
return
<
QuestionGuide
text=
{
strChildren
}
/>;
}
if
(
codeType
===
CodeClassName
.
echarts
)
{
return
<
EChartsCodeBlock
code=
{
strChildren
}
/>;
}
if
(
codeType
===
CodeClassName
.
img
)
{
return
<
ImageBlock
images=
{
strChildren
}
/>;
}
return
(
<
CodeLight
className=
{
className
}
inline=
{
inline
}
match=
{
match
}
>
{
children
}
</
CodeLight
>
);
},
[
codeType
,
className
,
inline
,
match
,
strChildren
]);
return
Component
;
});
const
Image
=
React
.
memo
(
function
Image
({
src
}:
{
src
?:
string
})
{
return
<
MdImage
src=
{
src
}
/>;
}
function
A
({
children
,
...
props
}:
any
)
{
}
);
const
A
=
React
.
memo
(
function
A
({
children
,
...
props
}:
any
)
{
const
{
t
}
=
useTranslation
();
// empty href link
...
...
@@ -109,38 +152,4 @@ function A({ children, ...props }: any) {
}
return
<
Link
{
...
props
}
>
{
children
}
</
Link
>;
}
const
Markdown
=
({
source
,
isChatting
=
false
}:
{
source
:
string
;
isChatting
?:
boolean
})
=>
{
const
components
=
useMemo
<
any
>
(
()
=>
({
img
:
Image
,
pre
:
'div'
,
p
:
(
pProps
:
any
)
=>
<
p
{
...
pProps
}
dir=
"auto"
/>,
code
:
Code
,
a
:
A
}),
[]
);
const
formatSource
=
source
.
replace
(
/
\\
n/g
,
'\n '
)
.
replace
(
/
(
http
[
s
]?
:
\/\/[^\s
,。
]
+
)([
。,
])
/g
,
'$1 $2'
)
.
replace
(
/
\n
*
(\[
QUOTE SIGN
\]\(
.*
\))
/g
,
'$1'
);
return
(
<
ReactMarkdown
className=
{
`markdown ${styles.markdown}
${isChatting ? `
$
{
formatSource
?
styles
.
waitingAnimation
:
styles
.
animation
}
` : ''}
`
}
remarkPlugins=
{
[
RemarkMath
,
RemarkGfm
,
RemarkBreaks
]
}
rehypePlugins=
{
[
RehypeKatex
]
}
components=
{
components
}
linkTarget=
{
'_blank'
}
>
{
formatSource
}
</
ReactMarkdown
>
);
};
export
default
React
.
memo
(
Markdown
);
});
projects/app/src/components/common/Textarea/TagTextarea.tsx
View file @
aab6ee51
...
...
@@ -79,6 +79,8 @@ const TagTextarea = ({ defaultValues, onUpdate, ...props }: Props) => {
ref=
{
InputRef
}
variant=
{
'unstyled'
}
display=
{
'inline-block'
}
h=
{
'24px'
}
borderRadius=
{
'none'
}
w=
"auto"
onBlur=
{
(
e
)
=>
{
const
value
=
e
.
target
.
value
;
...
...
projects/app/src/components/core/module/AIChatSettingsModal.tsx
View file @
aab6ee51
...
...
@@ -66,7 +66,6 @@ const AIChatSettingsModal = ({
},
[
getValues
]);
const
quoteTemplateVariables
=
(()
=>
[
...
pickerMenu
,
{
key
:
'q'
,
label
:
'q'
,
...
...
@@ -91,15 +90,21 @@ const AIChatSettingsModal = ({
key
:
'index'
,
label
:
t
(
'core.dataset.search.Quote index'
),
icon
:
'core/app/simpleMode/variable'
}
},
...
pickerMenu
])();
const
quotePromptVariables
=
(()
=>
[
...
pickerMenu
,
{
key
:
'quote'
,
label
:
t
(
'core.app.Quote templates'
),
icon
:
'core/app/simpleMode/variable'
}
},
{
key
:
'question'
,
label
:
t
(
'core.module.input.label.user question'
),
icon
:
'core/app/simpleMode/variable'
},
...
pickerMenu
])();
const
LabelStyles
:
BoxProps
=
{
...
...
projects/app/src/components/support/user/team/TeamManageModal/InviteModal.tsx
View file @
aab6ee51
...
...
@@ -55,11 +55,13 @@ const InviteModal = ({
openConfirm
(
()
=>
onClose
(),
undefined
,
t
(
'user.team.Invite Member Success Tip'
,
{
success
:
res
.
invite
.
length
,
inValid
:
res
.
inValid
.
map
((
item
)
=>
item
.
username
).
join
(
', '
),
inTeam
:
res
.
inTeam
.
map
((
item
)
=>
item
.
username
).
join
(
', '
)
})
<
Box
whiteSpace=
{
'pre-wrap'
}
>
{
t
(
'user.team.Invite Member Success Tip'
,
{
success
:
res
.
invite
.
length
,
inValid
:
res
.
inValid
.
map
((
item
)
=>
item
.
username
).
join
(
', '
),
inTeam
:
res
.
inTeam
.
map
((
item
)
=>
item
.
username
).
join
(
', '
)
})
}
</
Box
>
)();
},
errorToast
:
t
(
'user.team.Invite Member Failed Tip'
)
...
...
projects/app/src/components/support/user/team/TeamManageModal/index.tsx
View file @
aab6ee51
...
...
@@ -75,7 +75,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
const
{
mutate
:
onSwitchTeam
,
isLoading
:
isSwitchTeam
}
=
useRequest
({
mutationFn
:
async
(
teamId
:
string
)
=>
{
const
token
=
await
putSwitchTeam
(
teamId
);
setToken
(
token
);
token
&&
setToken
(
token
);
return
initUserInfo
();
},
errorToast
:
t
(
'user.team.Switch Team Failed'
)
...
...
@@ -286,13 +286,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
size=
"sm"
borderRadius=
{
'md'
}
ml=
{
3
}
leftIcon=
{
<
MyIcon
name=
{
'support/account/loginoutLight'
}
w=
{
'14px'
}
color=
{
'primary.500'
}
/>
}
leftIcon=
{
<
MyIcon
name=
{
'support/account/loginoutLight'
}
w=
{
'14px'
}
/>
}
onClick=
{
()
=>
{
openLeaveConfirm
(()
=>
onLeaveTeam
(
userInfo
?.
team
?.
teamId
))();
}
}
...
...
projects/app/src/pages/account/components/Info.tsx
View file @
aab6ee51
...
...
@@ -271,28 +271,32 @@ const UserInfo = () => {
)
}
</
Flex
>
</
Box
>
<
Box
mt=
{
6
}
whiteSpace=
{
'nowrap'
}
w=
{
[
'85%'
,
'300px'
]
}
>
<
Flex
alignItems=
{
'center'
}
>
<
Box
flex=
{
'1 0 0'
}
fontSize=
{
'md'
}
>
{
t
(
'support.user.team.Dataset usage'
)
}
:
{
datasetUsageMap
.
usedSize
}
/
{
datasetSub
.
maxSize
}
{
feConfigs
?.
show_pay
&&
(
<
Box
mt=
{
6
}
whiteSpace=
{
'nowrap'
}
w=
{
[
'85%'
,
'300px'
]
}
>
<
Flex
alignItems=
{
'center'
}
>
<
Box
flex=
{
'1 0 0'
}
fontSize=
{
'md'
}
>
{
t
(
'support.user.team.Dataset usage'
)
}
:
{
datasetUsageMap
.
usedSize
}
/
{
datasetSub
.
maxSize
}
</
Box
>
{
userInfo
?.
team
?.
canWrite
&&
(
<
Button
size=
{
'sm'
}
onClick=
{
onOpenSubDatasetModal
}
>
{
t
(
'support.wallet.Buy more'
)
}
</
Button
>
)
}
</
Flex
>
<
Box
mt=
{
1
}
>
<
Progress
value=
{
datasetUsageMap
.
value
}
colorScheme=
{
datasetUsageMap
.
colorScheme
}
borderRadius=
{
'md'
}
isAnimated
hasStripe
borderWidth=
{
'1px'
}
borderColor=
{
'borderColor.base'
}
/>
</
Box
>
<
Button
size=
{
'sm'
}
onClick=
{
onOpenSubDatasetModal
}
>
{
t
(
'support.wallet.Buy more'
)
}
</
Button
>
</
Flex
>
<
Box
mt=
{
1
}
>
<
Progress
value=
{
datasetUsageMap
.
value
}
colorScheme=
{
datasetUsageMap
.
colorScheme
}
borderRadius=
{
'md'
}
isAnimated
hasStripe
borderWidth=
{
'1px'
}
borderColor=
{
'borderColor.base'
}
/>
</
Box
>
</
Box
>
)
}
</>
)
}
...
...
projects/app/src/pages/api/core/dataset/collection/create/file.ts
deleted
100644 → 0
View file @
91b7d81c
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
{
jsonRes
}
from
'@fastgpt/service/common/response'
;
import
{
connectToDatabase
}
from
'@/service/mongo'
;
import
{
uploadFile
}
from
'@fastgpt/service/common/file/gridfs/controller'
;
import
{
getUploadModel
}
from
'@fastgpt/service/common/file/multer'
;
import
{
authDataset
}
from
'@fastgpt/service/support/permission/auth/dataset'
;
import
{
FileCreateDatasetCollectionParams
}
from
'@fastgpt/global/core/dataset/api'
;
import
{
removeFilesByPaths
}
from
'@fastgpt/service/common/file/utils'
;
import
{
createOneCollection
}
from
'@fastgpt/service/core/dataset/collection/controller'
;
import
{
DatasetCollectionTypeEnum
}
from
'@fastgpt/global/core/dataset/constants'
;
/**
* Creates the multer uploader
*/
const
upload
=
getUploadModel
({
maxSize
:
500
*
1024
*
1024
});
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
let
filePaths
:
string
[]
=
[];
const
{
datasetId
}
=
req
.
query
as
{
datasetId
:
string
};
try
{
await
connectToDatabase
();
const
{
teamId
,
tmbId
}
=
await
authDataset
({
req
,
authToken
:
true
,
authApiKey
:
true
,
per
:
'w'
,
datasetId
});
const
{
file
,
bucketName
,
data
}
=
await
upload
.
doUpload
<
FileCreateDatasetCollectionParams
>
(
req
,
res
);
filePaths
=
[
file
.
path
];
if
(
!
file
||
!
bucketName
)
{
throw
new
Error
(
'file is empty'
);
}
const
{
fileMetadata
,
collectionMetadata
,
...
collectionData
}
=
data
;
// upload file and create collection
const
fileId
=
await
uploadFile
({
teamId
,
tmbId
,
bucketName
,
path
:
file
.
path
,
filename
:
file
.
originalname
,
contentType
:
file
.
mimetype
,
metadata
:
fileMetadata
});
// create collection
const
collectionId
=
await
createOneCollection
({
...
collectionData
,
metadata
:
collectionMetadata
,
teamId
,
tmbId
,
type
:
DatasetCollectionTypeEnum
.
file
,
fileId
});
jsonRes
(
res
,
{
data
:
collectionId
});
}
catch
(
error
)
{
jsonRes
(
res
,
{
code
:
500
,
error
});
}
removeFilesByPaths
(
filePaths
);
}
export
const
config
=
{
api
:
{
bodyParser
:
false
}
};
projects/app/src/pages/api/core/dataset/collection/create/link.ts
deleted
100644 → 0
View file @
91b7d81c
/*
Create one dataset collection
*/
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
{
jsonRes
}
from
'@fastgpt/service/common/response'
;
import
{
connectToDatabase
}
from
'@/service/mongo'
;
import
type
{
LinkCreateDatasetCollectionParams
}
from
'@fastgpt/global/core/dataset/api.d'
;
import
{
authDataset
}
from
'@fastgpt/service/support/permission/auth/dataset'
;
import
{
createOneCollection
}
from
'@fastgpt/service/core/dataset/collection/controller'
;
import
{
TrainingModeEnum
,
DatasetCollectionTypeEnum
}
from
'@fastgpt/global/core/dataset/constants'
;
import
{
checkDatasetLimit
}
from
'@fastgpt/service/support/permission/limit/dataset'
;
import
{
predictDataLimitLength
}
from
'@fastgpt/global/core/dataset/utils'
;
import
{
createTrainingBill
}
from
'@fastgpt/service/support/wallet/bill/controller'
;
import
{
BillSourceEnum
}
from
'@fastgpt/global/support/wallet/bill/constants'
;
import
{
getQAModel
,
getVectorModel
}
from
'@/service/core/ai/model'
;
import
{
reloadCollectionChunks
}
from
'@fastgpt/service/core/dataset/collection/utils'
;
import
{
startQueue
}
from
'@/service/utils/tools'
;
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
try
{
await
connectToDatabase
();
const
{
link
,
trainingType
=
TrainingModeEnum
.
chunk
,
chunkSize
=
512
,
chunkSplitter
,
qaPrompt
,
...
body
}
=
req
.
body
as
LinkCreateDatasetCollectionParams
;
const
{
teamId
,
tmbId
,
dataset
}
=
await
authDataset
({
req
,
authToken
:
true
,
authApiKey
:
true
,
datasetId
:
body
.
datasetId
,
per
:
'w'
});
// 1. check dataset limit
await
checkDatasetLimit
({
teamId
,
freeSize
:
global
.
feConfigs
?.
subscription
?.
datasetStoreFreeSize
,
insertLen
:
predictDataLimitLength
(
trainingType
,
new
Array
(
10
))
});
// 2. create collection
const
collectionId
=
await
createOneCollection
({
...
body
,
name
:
link
,
teamId
,
tmbId
,
type
:
DatasetCollectionTypeEnum
.
link
,
trainingType
,
chunkSize
,
chunkSplitter
,
qaPrompt
,
rawLink
:
link
});
// 3. create bill and start sync
const
{
billId
}
=
await
createTrainingBill
({
teamId
,
tmbId
,
appName
:
'core.dataset.collection.Sync Collection'
,
billSource
:
BillSourceEnum
.
training
,
vectorModel
:
getVectorModel
(
dataset
.
vectorModel
).
name
,
agentModel
:
getQAModel
(
dataset
.
agentModel
).
name
});
await
reloadCollectionChunks
({
collectionId
,
tmbId
,
billId
});
startQueue
();
jsonRes
(
res
,
{
data
:
{
collectionId
}
});
}
catch
(
err
)
{
jsonRes
(
res
,
{
code
:
500
,
error
:
err
});
}
}
projects/app/src/pages/api/core/dataset/collection/create/text.ts
deleted
100644 → 0
View file @
91b7d81c
/*
Create one dataset collection
*/
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
{
jsonRes
}
from
'@fastgpt/service/common/response'
;
import
{
connectToDatabase
}
from
'@/service/mongo'
;
import
type
{
TextCreateDatasetCollectionParams
}
from
'@fastgpt/global/core/dataset/api.d'
;
import
{
authDataset
}
from
'@fastgpt/service/support/permission/auth/dataset'
;
import
{
createOneCollection
}
from
'@fastgpt/service/core/dataset/collection/controller'
;
import
{
TrainingModeEnum
,
DatasetCollectionTypeEnum
}
from
'@fastgpt/global/core/dataset/constants'
;
import
{
splitText2Chunks
}
from
'@fastgpt/global/common/string/textSplitter'
;
import
{
checkDatasetLimit
}
from
'@fastgpt/service/support/permission/limit/dataset'
;
import
{
predictDataLimitLength
}
from
'@fastgpt/global/core/dataset/utils'
;
import
{
pushDataToTrainingQueue
}
from
'@/service/core/dataset/data/controller'
;
import
{
hashStr
}
from
'@fastgpt/global/common/string/tools'
;
import
{
createTrainingBill
}
from
'@fastgpt/service/support/wallet/bill/controller'
;
import
{
BillSourceEnum
}
from
'@fastgpt/global/support/wallet/bill/constants'
;
import
{
getQAModel
,
getVectorModel
}
from
'@/service/core/ai/model'
;
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
try
{
await
connectToDatabase
();
const
{
name
,
text
,
trainingType
=
TrainingModeEnum
.
chunk
,
chunkSize
=
512
,
chunkSplitter
,
qaPrompt
,
...
body
}
=
req
.
body
as
TextCreateDatasetCollectionParams
;
const
{
teamId
,
tmbId
,
dataset
}
=
await
authDataset
({
req
,
authToken
:
true
,
authApiKey
:
true
,
datasetId
:
body
.
datasetId
,
per
:
'w'
});
// 1. split text to chunks
const
{
chunks
}
=
splitText2Chunks
({
text
,
chunkLen
:
chunkSize
,
overlapRatio
:
trainingType
===
TrainingModeEnum
.
chunk
?
0.2
:
0
,
customReg
:
chunkSplitter
?
[
chunkSplitter
]
:
[]
});
// 2. check dataset limit
await
checkDatasetLimit
({
teamId
,
freeSize
:
global
.
feConfigs
?.
subscription
?.
datasetStoreFreeSize
,
insertLen
:
predictDataLimitLength
(
trainingType
,
chunks
)
});
// 3. create collection and training bill
const
[
collectionId
,
{
billId
}]
=
await
Promise
.
all
([
createOneCollection
({
...
body
,
teamId
,
tmbId
,
type
:
DatasetCollectionTypeEnum
.
virtual
,
name
,
trainingType
,
chunkSize
,
chunkSplitter
,
qaPrompt
,
hashRawText
:
hashStr
(
text
),
rawTextLength
:
text
.
length
}),
createTrainingBill
({
teamId
,
tmbId
,
appName
:
name
,
billSource
:
BillSourceEnum
.
training
,
vectorModel
:
getVectorModel
(
dataset
.
vectorModel
)?.
name
,
agentModel
:
getQAModel
(
dataset
.
agentModel
)?.
name
})
]);
// 4. push chunks to training queue
const
insertResults
=
await
pushDataToTrainingQueue
({
teamId
,
tmbId
,
collectionId
,
trainingMode
:
trainingType
,
prompt
:
qaPrompt
,
billId
,
data
:
chunks
.
map
((
text
,
index
)
=>
({
q
:
text
,
chunkIndex
:
index
}))
});
jsonRes
(
res
,
{
data
:
{
collectionId
,
results
:
insertResults
}
});
}
catch
(
err
)
{
jsonRes
(
res
,
{
code
:
500
,
error
:
err
});
}
}
export
const
config
=
{
api
:
{
bodyParser
:
{
sizeLimit
:
'10mb'
}
}
};
projects/app/src/pages/api/core/dataset/create.ts
View file @
aab6ee51
...
...
@@ -6,6 +6,7 @@ import type { CreateDatasetParams } from '@/global/core/dataset/api.d';
import
{
createDefaultCollection
}
from
'@fastgpt/service/core/dataset/collection/controller'
;
import
{
authUserNotVisitor
}
from
'@fastgpt/service/support/permission/auth/user'
;
import
{
DatasetTypeEnum
}
from
'@fastgpt/global/core/dataset/constants'
;
import
{
getQAModel
,
getVectorModel
}
from
'@/service/core/ai/model'
;
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
try
{
...
...
@@ -13,18 +14,18 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
const
{
parentId
,
name
,
type
,
type
=
DatasetTypeEnum
.
dataset
,
avatar
,
vectorModel
=
global
.
vectorModels
[
0
].
model
,
agentModel
=
global
.
qaModels
[
0
].
model
}
=
req
.
body
as
CreateDatasetParams
;
// auth
const
{
teamId
,
tmbId
}
=
await
authUserNotVisitor
({
req
,
authToken
:
true
});
const
{
teamId
,
tmbId
}
=
await
authUserNotVisitor
({
req
,
authToken
:
true
,
authApiKey
:
true
});
// check model valid
const
vectorModelStore
=
g
lobal
.
vectorModels
.
find
((
item
)
=>
item
.
model
===
vectorModel
);
const
agentModelStore
=
g
lobal
.
qaModels
.
find
((
item
)
=>
item
.
model
===
agentModel
);
const
vectorModelStore
=
g
etVectorModel
(
vectorModel
);
const
agentModelStore
=
g
etQAModel
(
agentModel
);
if
(
!
vectorModelStore
||
!
agentModelStore
)
{
throw
new
Error
(
'vectorModel or qaModel is invalid'
);
}
...
...
projects/app/src/pages/api/core/dataset/delete.ts
View file @
aab6ee51
...
...
@@ -18,7 +18,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
}
// auth owner
const
{
teamId
}
=
await
authDataset
({
req
,
authToken
:
true
,
datasetId
,
per
:
'owner'
});
const
{
teamId
}
=
await
authDataset
({
req
,
authToken
:
true
,
authApiKey
:
true
,
datasetId
,
per
:
'owner'
});
const
datasets
=
await
findDatasetAndAllChildren
({
teamId
,
...
...
projects/app/src/pages/api/plusApi/[...path].ts
deleted
100644 → 0
View file @
91b7d81c
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
{
jsonRes
}
from
'@fastgpt/service/common/response'
;
import
{
request
}
from
'@fastgpt/service/common/api/plusRequest'
;
import
type
{
Method
}
from
'axios'
;
import
{
setCookie
}
from
'@fastgpt/service/support/permission/controller'
;
import
{
connectToDatabase
}
from
'@/service/mongo'
;
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
await
connectToDatabase
();
const
method
=
(
req
.
method
||
'POST'
)
as
Method
;
const
{
path
=
[],
...
query
}
=
req
.
query
as
any
;
const
url
=
`/
${
path
?.
join
(
'/'
)}?
$
{
new
URLSearchParams
(
query
).
toString
()}
`;
if (!url) {
throw new Error('url is empty');
}
const data = req.body || query;
const repose = await request(
url,
data,
{
headers: {
...req.headers,
// @ts-ignore
rootkey: undefined
}
},
method
);
/* special response */
// response cookie
if (repose?.cookie) {
setCookie(res, repose.cookie);
return jsonRes(res, {
data: repose?.cookie
});
}
jsonRes(res, {
data: repose
});
} catch (error) {
jsonRes(res, {
code: 500,
error
});
}
}
export const config = {
api: {
bodyParser: {
sizeLimit: '10mb'
},
responseLimit: '10mb'
}
};
projects/app/src/pages/api/proApi/[...path].ts
0 → 100644
View file @
aab6ee51
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
{
jsonRes
}
from
'@fastgpt/service/common/response'
;
import
{
connectToDatabase
}
from
'@/service/mongo'
;
import
{
request
}
from
'http'
;
import
{
FastGPTProUrl
}
from
'@fastgpt/service/common/system/constants'
;
import
url
from
'url'
;
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
await
connectToDatabase
();
const
{
path
=
[],
...
query
}
=
req
.
query
as
any
;
const
requestPath
=
`/api/
${
path
?.
join
(
'/'
)}?
$
{
new
URLSearchParams
(
query
).
toString
()}
`;
if (!requestPath) {
throw new Error('url is empty');
}
const parsedUrl = url.parse(FastGPTProUrl);
delete req.headers?.rootkey;
const requestResult = request({
protocol: parsedUrl.protocol,
hostname: parsedUrl.hostname,
port: parsedUrl.port,
path: requestPath,
method: req.method,
headers: req.headers
});
req.pipe(requestResult);
requestResult.on('response', (response) => {
Object.keys(response.headers).forEach((key) => {
// @ts-ignore
res.setHeader(key, response.headers[key]);
});
response.statusCode && res.writeHead(response.statusCode);
response.pipe(res);
});
requestResult.on('error', (e) => {
res.send(e);
res.end();
});
} catch (error) {
jsonRes(res, {
code: 500,
error
});
}
}
export const config = {
api: {
bodyParser: false
}
};
projects/app/src/pages/dataset/detail/index.tsx
View file @
aab6ee51
...
...
@@ -87,7 +87,7 @@ const Detail = ({ datasetId, currentTab }: { datasetId: string; currentTab: `${T
onError
(
err
:
any
)
{
router
.
replace
(
`/dataset/list`
);
toast
({
title
:
getErrText
(
err
,
t
(
'common.Load Failed'
)),
title
:
t
(
getErrText
(
err
,
t
(
'common.Load Failed'
)
)),
status
:
'error'
});
}
...
...
projects/app/src/pages/dataset/list/index.tsx
View file @
aab6ee51
...
...
@@ -46,13 +46,15 @@ import { PermissionTypeEnum } from '@fastgpt/global/support/permission/constant'
import
{
DatasetItemType
}
from
'@fastgpt/global/core/dataset/type'
;
import
ParentPaths
from
'@/components/common/ParentPaths'
;
import
DatasetTypeTag
from
'@/components/core/dataset/DatasetTypeTag'
;
import
{
useToast
}
from
'@/web/common/hooks/useToast'
;
import
{
getErrText
}
from
'@fastgpt/global/common/error/utils'
;
const
CreateModal
=
dynamic
(()
=>
import
(
'./component/CreateModal'
),
{
ssr
:
false
});
const
MoveModal
=
dynamic
(()
=>
import
(
'./component/MoveModal'
),
{
ssr
:
false
});
const
Kb
=
()
=>
{
const
{
t
}
=
useTranslation
();
const
theme
=
useTheme
();
const
{
toast
}
=
useToast
();
const
router
=
useRouter
();
const
{
parentId
}
=
router
.
query
as
{
parentId
:
string
};
const
{
setLoading
}
=
useSystemStore
();
...
...
@@ -115,9 +117,20 @@ const Kb = () => {
errorToast
:
t
(
'dataset.Export Dataset Limit Error'
)
});
const
{
data
,
refetch
,
isFetching
}
=
useQuery
([
'loadDataset'
,
parentId
],
()
=>
{
return
Promise
.
all
([
loadDatasets
(
parentId
),
getDatasetPaths
(
parentId
)]);
});
const
{
data
,
refetch
,
isFetching
}
=
useQuery
(
[
'loadDataset'
,
parentId
],
()
=>
{
return
Promise
.
all
([
loadDatasets
(
parentId
),
getDatasetPaths
(
parentId
)]);
},
{
onError
(
err
)
{
toast
({
status
:
'error'
,
title
:
t
(
getErrText
(
err
))
});
}
}
);
const
paths
=
data
?.[
1
]
||
[];
...
...
projects/app/src/pages/login/provider.tsx
View file @
aab6ee51
...
...
@@ -106,9 +106,9 @@ const provider = ({ code, state, error }: { code: string; state: string; error?:
export
async
function
getServerSideProps
(
content
:
any
)
{
return
{
props
:
{
code
:
content
?.
query
?.
code
,
state
:
content
?.
query
?.
state
,
error
:
content
?.
query
?.
error
,
code
:
content
?.
query
?.
code
||
''
,
state
:
content
?.
query
?.
state
||
''
,
error
:
content
?.
query
?.
error
||
''
,
...(
await
serviceSideProps
(
content
))
}
};
...
...
projects/app/src/web/common/hooks/useConfirm.tsx
View file @
aab6ee51
import
{
useCallback
,
useEffect
,
useMemo
,
useRef
,
useState
}
from
'react'
;
import
React
,
{
useCallback
,
useEffect
,
useMemo
,
useRef
,
useState
}
from
'react'
;
import
{
useDisclosure
,
Button
,
ModalBody
,
ModalFooter
}
from
'@chakra-ui/react'
;
import
{
useTranslation
}
from
'next-i18next'
;
import
MyModal
from
'@/components/MyModal'
;
...
...
@@ -35,7 +35,7 @@ export const useConfirm = (props?: {
content
,
showCancel
=
true
}
=
props
||
{};
const
[
customContent
,
setCustomContent
]
=
useState
(
content
);
const
[
customContent
,
setCustomContent
]
=
useState
<
string
|
React
.
ReactNode
>
(
content
);
const
{
isOpen
,
onOpen
,
onClose
}
=
useDisclosure
();
...
...
@@ -44,7 +44,7 @@ export const useConfirm = (props?: {
return
{
openConfirm
:
useCallback
(
(
confirm
?:
any
,
cancel
?:
any
,
customContent
?:
string
)
=>
{
(
confirm
?:
any
,
cancel
?:
any
,
customContent
?:
string
|
React
.
ReactNode
)
=>
{
confirmCb
.
current
=
confirm
;
cancelCb
.
current
=
cancel
;
...
...
projects/app/src/web/core/dataset/api.ts
View file @
aab6ee51
...
...
@@ -58,7 +58,7 @@ export const putDatasetById = (data: DatasetUpdateBody) => PUT<void>(`/core/data
export
const
delDatasetById
=
(
id
:
string
)
=>
DELETE
(
`/core/dataset/delete?id=
${
id
}
`
);
export
const
postWebsiteSync
=
(
data
:
PostWebsiteSyncParams
)
=>
POST
(
`/p
lus
Api/core/dataset/websiteSync`
,
data
,
{
POST
(
`/p
ro
Api/core/dataset/websiteSync`
,
data
,
{
timeout
:
600000
}).
catch
();
...
...
@@ -76,7 +76,7 @@ export const getDatasetCollectionById = (id: string) =>
export
const
postDatasetCollection
=
(
data
:
CreateDatasetCollectionParams
)
=>
POST
<
string
>
(
`/core/dataset/collection/create`
,
data
);
export
const
postCreateDatasetLinkCollection
=
(
data
:
LinkCreateDatasetCollectionParams
)
=>
POST
<
{
collectionId
:
string
}
>
(
`/core/dataset/collection/create/link`
,
data
);
POST
<
{
collectionId
:
string
}
>
(
`/
proApi/
core/dataset/collection/create/link`
,
data
);
export
const
putDatasetCollectionById
=
(
data
:
UpdateDatasetCollectionParams
)
=>
POST
(
`/core/dataset/collection/update`
,
data
);
...
...
projects/app/src/web/core/dataset/utils.ts
View file @
aab6ee51
...
...
@@ -27,18 +27,22 @@ export const fileCollectionCreate = ({
form
.
append
(
'bucketName'
,
BucketNameEnum
.
dataset
);
form
.
append
(
'file'
,
file
,
encodeURIComponent
(
file
.
name
));
return
POST
<
string
>
(
`/core/dataset/collection/create/file?datasetId=
${
data
.
datasetId
}
`
,
form
,
{
timeout
:
480000
,
onUploadProgress
:
(
e
)
=>
{
if
(
!
e
.
total
)
return
;
return
POST
<
string
>
(
`/proApi/core/dataset/collection/create/emptyFile?datasetId=
${
data
.
datasetId
}
`
,
form
,
{
timeout
:
480000
,
onUploadProgress
:
(
e
)
=>
{
if
(
!
e
.
total
)
return
;
const
percent
=
Math
.
round
((
e
.
loaded
/
e
.
total
)
*
100
);
percentListen
&&
percentListen
(
percent
);
},
headers
:
{
'Content-Type'
:
'multipart/form-data; charset=utf-8'
const
percent
=
Math
.
round
((
e
.
loaded
/
e
.
total
)
*
100
);
percentListen
&&
percentListen
(
percent
);
},
headers
:
{
'Content-Type'
:
'multipart/form-data; charset=utf-8'
}
}
}
);
);
};
export
async
function
chunksUpload
({
...
...
projects/app/src/web/support/activity/promotion/api.ts
View file @
aab6ee51
...
...
@@ -7,8 +7,8 @@ export const getPromotionInitData = () =>
GET
<
{
invitedAmount
:
number
;
earningsAmount
:
number
;
}
>
(
'/p
lus
Api/support/activity/promotion/getPromotionData'
);
}
>
(
'/p
ro
Api/support/activity/promotion/getPromotionData'
);
/* promotion records */
export
const
getPromotionRecords
=
(
data
:
RequestPaging
)
=>
POST
<
PromotionRecordType
>
(
`/p
lus
Api/support/activity/promotion/getPromotions`
,
data
);
POST
<
PromotionRecordType
>
(
`/p
ro
Api/support/activity/promotion/getPromotions`
,
data
);
projects/app/src/web/support/user/api.ts
View file @
aab6ee51
...
...
@@ -14,14 +14,14 @@ export const sendAuthCode = (data: {
username
:
string
;
type
:
`
${
UserAuthTypeEnum
}
`
;
googleToken
:
string
;
})
=>
POST
(
`/p
lus
Api/support/user/inform/sendAuthCode`
,
data
);
})
=>
POST
(
`/p
ro
Api/support/user/inform/sendAuthCode`
,
data
);
export
const
getTokenLogin
=
()
=>
GET
<
UserType
>
(
'/support/user/account/tokenLogin'
,
{},
{
maxQuantity
:
1
});
export
const
oauthLogin
=
(
params
:
OauthLoginProps
)
=>
POST
<
ResLogin
>
(
'/p
lus
Api/support/user/account/login/oauth'
,
params
);
POST
<
ResLogin
>
(
'/p
ro
Api/support/user/account/login/oauth'
,
params
);
export
const
postFastLogin
=
(
params
:
FastLoginProps
)
=>
POST
<
ResLogin
>
(
'/p
lus
Api/support/user/account/login/fastLogin'
,
params
);
POST
<
ResLogin
>
(
'/p
ro
Api/support/user/account/login/fastLogin'
,
params
);
export
const
postRegister
=
({
username
,
...
...
@@ -34,7 +34,7 @@ export const postRegister = ({
password
:
string
;
inviterId
?:
string
;
})
=>
POST
<
ResLogin
>
(
`/p
lus
Api/support/user/account/register/emailAndPhone`
,
{
POST
<
ResLogin
>
(
`/p
ro
Api/support/user/account/register/emailAndPhone`
,
{
username
,
code
,
inviterId
,
...
...
@@ -50,7 +50,7 @@ export const postFindPassword = ({
code
:
string
;
password
:
string
;
})
=>
POST
<
ResLogin
>
(
`/p
lus
Api/support/user/account/password/updateByCode`
,
{
POST
<
ResLogin
>
(
`/p
ro
Api/support/user/account/password/updateByCode`
,
{
username
,
code
,
password
:
hashStr
(
password
)
...
...
projects/app/src/web/support/user/inform/api.ts
View file @
aab6ee51
...
...
@@ -3,7 +3,7 @@ import type { PagingData, RequestPaging } from '@/types';
import
type
{
UserInformSchema
}
from
'@fastgpt/global/support/user/inform/type'
;
export
const
getInforms
=
(
data
:
RequestPaging
)
=>
POST
<
PagingData
<
UserInformSchema
>>
(
`/p
lus
Api/support/user/inform/list`
,
data
);
POST
<
PagingData
<
UserInformSchema
>>
(
`/p
ro
Api/support/user/inform/list`
,
data
);
export
const
getUnreadCount
=
()
=>
GET
<
number
>
(
`/p
lus
Api/support/user/inform/countUnread`
);
export
const
readInform
=
(
id
:
string
)
=>
GET
(
`/p
lus
Api/support/user/inform/read`
,
{
id
});
export
const
getUnreadCount
=
()
=>
GET
<
number
>
(
`/p
ro
Api/support/user/inform/countUnread`
);
export
const
readInform
=
(
id
:
string
)
=>
GET
(
`/p
ro
Api/support/user/inform/read`
,
{
id
});
projects/app/src/web/support/user/team/api.ts
View file @
aab6ee51
...
...
@@ -16,29 +16,29 @@ import {
/* --------------- team ---------------- */
export
const
getTeamList
=
(
status
:
`
${
TeamMemberSchema
[
'status'
]}
`
)
=>
GET
<
TeamItemType
[]
>
(
`/p
lus
Api/support/user/team/list`
,
{
status
});
GET
<
TeamItemType
[]
>
(
`/p
ro
Api/support/user/team/list`
,
{
status
});
export
const
postCreateTeam
=
(
data
:
CreateTeamProps
)
=>
POST
<
string
>
(
`/p
lus
Api/support/user/team/create`
,
data
);
POST
<
string
>
(
`/p
ro
Api/support/user/team/create`
,
data
);
export
const
putUpdateTeam
=
(
data
:
UpdateTeamProps
)
=>
PUT
(
`/p
lus
Api/support/user/team/update`
,
data
);
PUT
(
`/p
ro
Api/support/user/team/update`
,
data
);
export
const
putSwitchTeam
=
(
teamId
:
string
)
=>
PUT
<
string
>
(
`/p
lus
Api/support/user/team/switch`
,
{
teamId
});
PUT
<
string
>
(
`/p
ro
Api/support/user/team/switch`
,
{
teamId
});
/* --------------- team member ---------------- */
export
const
getTeamMembers
=
(
teamId
:
string
)
=>
GET
<
TeamMemberItemType
[]
>
(
`/p
lus
Api/support/user/team/member/list`
,
{
teamId
});
GET
<
TeamMemberItemType
[]
>
(
`/p
ro
Api/support/user/team/member/list`
,
{
teamId
});
export
const
postInviteTeamMember
=
(
data
:
InviteMemberProps
)
=>
POST
<
InviteMemberResponse
>
(
`/p
lus
Api/support/user/team/member/invite`
,
data
);
POST
<
InviteMemberResponse
>
(
`/p
ro
Api/support/user/team/member/invite`
,
data
);
export
const
putUpdateMember
=
(
data
:
UpdateTeamMemberProps
)
=>
PUT
(
`/p
lus
Api/support/user/team/member/update`
,
data
);
PUT
(
`/p
ro
Api/support/user/team/member/update`
,
data
);
export
const
putUpdateMemberName
=
(
name
:
string
)
=>
PUT
(
`/p
lus
Api/support/user/team/member/updateName`
,
{
name
});
PUT
(
`/p
ro
Api/support/user/team/member/updateName`
,
{
name
});
export
const
delRemoveMember
=
(
props
:
DelMemberProps
)
=>
DELETE
(
`/p
lus
Api/support/user/team/member/delete`
,
props
);
DELETE
(
`/p
ro
Api/support/user/team/member/delete`
,
props
);
export
const
updateInviteResult
=
(
data
:
UpdateInviteProps
)
=>
PUT
(
'/p
lus
Api/support/user/team/member/updateInvite'
,
data
);
PUT
(
'/p
ro
Api/support/user/team/member/updateInvite'
,
data
);
export
const
delLeaveTeam
=
(
teamId
:
string
)
=>
DELETE
(
'/p
lus
Api/support/user/team/member/leave'
,
{
teamId
});
DELETE
(
'/p
ro
Api/support/user/team/member/leave'
,
{
teamId
});
/* team limit */
export
const
checkTeamExportDatasetLimit
=
(
datasetId
:
string
)
=>
...
...
projects/app/src/web/support/wallet/bill/api.ts
View file @
aab6ee51
...
...
@@ -4,7 +4,7 @@ import type { PagingData, RequestPaging } from '@/types';
import
type
{
BillItemType
}
from
'@fastgpt/global/support/wallet/bill/type'
;
export
const
getUserBills
=
(
data
:
RequestPaging
)
=>
POST
<
PagingData
<
BillItemType
>>
(
`/p
lus
Api/support/wallet/bill/getBill`
,
data
);
POST
<
PagingData
<
BillItemType
>>
(
`/p
ro
Api/support/wallet/bill/getBill`
,
data
);
export
const
postCreateTrainingBill
=
(
data
:
CreateTrainingBillProps
)
=>
POST
<
string
>
(
`/support/wallet/bill/createTrainingBill`
,
data
);
projects/app/src/web/support/wallet/pay/api.ts
View file @
aab6ee51
import
{
GET
}
from
'@/web/common/api/request'
;
import
type
{
PaySchema
}
from
'@fastgpt/global/support/wallet/pay/type.d'
;
export
const
getPayOrders
=
()
=>
GET
<
PaySchema
[]
>
(
`/p
lus
Api/support/wallet/pay/getPayOrders`
);
export
const
getPayOrders
=
()
=>
GET
<
PaySchema
[]
>
(
`/p
ro
Api/support/wallet/pay/getPayOrders`
);
export
const
getPayCode
=
(
amount
:
number
)
=>
GET
<
{
codeUrl
:
string
;
payId
:
string
;
}
>
(
`/p
lus
Api/support/wallet/pay/getPayCode`
,
{
amount
});
}
>
(
`/p
ro
Api/support/wallet/pay/getPayCode`
,
{
amount
});
export
const
checkPayResult
=
(
payId
:
string
)
=>
GET
<
string
>
(
`/p
lus
Api/support/wallet/pay/checkPayResult`
,
{
payId
}).
then
((
data
)
=>
{
GET
<
string
>
(
`/p
ro
Api/support/wallet/pay/checkPayResult`
,
{
payId
}).
then
((
data
)
=>
{
try
{
GET
(
'/common/system/unlockTask'
);
}
catch
(
error
)
{}
...
...
projects/app/src/web/support/wallet/sub/api.ts
View file @
aab6ee51
...
...
@@ -10,4 +10,4 @@ export const getTeamDatasetValidSub = () =>
}
>
(
`/support/wallet/sub/getDatasetSub`
);
export
const
postExpandTeamDatasetSub
=
(
data
:
SubDatasetSizeParams
)
=>
POST
(
'/p
lus
Api/support/wallet/sub/datasetSize/expand'
,
data
);
POST
(
'/p
ro
Api/support/wallet/sub/datasetSize/expand'
,
data
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment