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
7a6d0ea6
authored
Mar 28, 2023
by
archer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
perf: 减少聊天内容配置,自动截断上下文
parent
7fb6f62c
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
144 additions
and
172 deletions
+144
-172
src/api/response/chat.d.ts
+0
-2
src/components/Layout/auth.tsx
+1
-2
src/constants/common.ts
+3
-0
src/constants/model.ts
+10
-10
src/pages/api/chat/chatGpt.ts
+14
-14
src/pages/api/chat/generate.ts
+1
-1
src/pages/api/chat/init.ts
+9
-16
src/pages/chat/components/SlideBar.tsx
+2
-2
src/pages/chat/index.tsx
+69
-115
src/pages/data/components/ImportDataModal.tsx
+1
-1
src/pages/model/components/ModelEditForm.tsx
+2
-2
src/service/response.ts
+0
-1
src/service/utils/chat.ts
+4
-6
src/service/utils/tools.ts
+28
-0
No files found.
src/api/response/chat.d.ts
View file @
7a6d0ea6
...
@@ -7,9 +7,7 @@ export type InitChatResponse = {
...
@@ -7,9 +7,7 @@ export type InitChatResponse = {
name
:
string
;
name
:
string
;
avatar
:
string
;
avatar
:
string
;
intro
:
string
;
intro
:
string
;
secret
:
ModelSchema
.
secret
;
chatModel
:
ModelSchema
.
service
.
chatModel
;
// 对话模型名
chatModel
:
ModelSchema
.
service
.
chatModel
;
// 对话模型名
modelName
:
ModelSchema
.
service
.
modelName
;
// 底层模型
modelName
:
ModelSchema
.
service
.
modelName
;
// 底层模型
history
:
ChatItemType
[];
history
:
ChatItemType
[];
isExpiredTime
:
boolean
;
};
};
src/components/Layout/auth.tsx
View file @
7a6d0ea6
...
@@ -7,8 +7,7 @@ import { useQuery } from '@tanstack/react-query';
...
@@ -7,8 +7,7 @@ import { useQuery } from '@tanstack/react-query';
const
unAuthPage
:
{
[
key
:
string
]:
boolean
}
=
{
const
unAuthPage
:
{
[
key
:
string
]:
boolean
}
=
{
'/'
:
true
,
'/'
:
true
,
'/login'
:
true
,
'/login'
:
true
'/chat'
:
true
};
};
const
Auth
=
({
children
}:
{
children
:
JSX
.
Element
})
=>
{
const
Auth
=
({
children
}:
{
children
:
JSX
.
Element
})
=>
{
...
...
src/constants/common.ts
View file @
7a6d0ea6
...
@@ -44,6 +44,9 @@ export const introPage = `
...
@@ -44,6 +44,9 @@ export const introPage = `
`
;
`
;
export
const
chatProblem
=
`
export
const
chatProblem
=
`
**内容长度**
单次最长 4000 tokens, 上下文最长 8000 tokens, 上下文超长时会被截断。
**模型问题**
**模型问题**
一般情况下,请直接选择 chatGPT 模型,价格低效果好。
一般情况下,请直接选择 chatGPT 模型,价格低效果好。
...
...
src/constants/model.ts
View file @
7a6d0ea6
...
@@ -27,17 +27,17 @@ export const modelList: ModelConstantsData[] = [
...
@@ -27,17 +27,17 @@ export const modelList: ModelConstantsData[] = [
trainedMaxToken
:
2000
,
trainedMaxToken
:
2000
,
maxTemperature
:
2
,
maxTemperature
:
2
,
price
:
3
price
:
3
},
{
serviceCompany
:
'openai'
,
name
:
'GPT3'
,
model
:
ChatModelNameEnum
.
GPT3
,
trainName
:
'davinci'
,
maxToken
:
4000
,
trainedMaxToken
:
2000
,
maxTemperature
:
2
,
price
:
30
}
}
// {
// serviceCompany: 'openai',
// name: 'GPT3',
// model: ChatModelNameEnum.GPT3,
// trainName: 'davinci',
// maxToken: 4000,
// trainedMaxToken: 2000,
// maxTemperature: 2,
// price: 30
// }
];
];
export
enum
TrainingStatusEnum
{
export
enum
TrainingStatusEnum
{
...
...
src/pages/api/chat/chatGpt.ts
View file @
7a6d0ea6
...
@@ -10,6 +10,7 @@ import type { ModelSchema } from '@/types/mongoSchema';
...
@@ -10,6 +10,7 @@ import type { ModelSchema } from '@/types/mongoSchema';
import
{
PassThrough
}
from
'stream'
;
import
{
PassThrough
}
from
'stream'
;
import
{
modelList
}
from
'@/constants/model'
;
import
{
modelList
}
from
'@/constants/model'
;
import
{
pushChatBill
}
from
'@/service/events/pushBill'
;
import
{
pushChatBill
}
from
'@/service/events/pushBill'
;
import
{
openaiChatFilter
}
from
'@/service/utils/tools'
;
/* 发送提示词 */
/* 发送提示词 */
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
...
@@ -32,6 +33,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -32,6 +33,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
prompt
:
ChatItemType
;
prompt
:
ChatItemType
;
chatId
:
string
;
chatId
:
string
;
};
};
const
{
authorization
}
=
req
.
headers
;
const
{
authorization
}
=
req
.
headers
;
if
(
!
chatId
||
!
prompt
)
{
if
(
!
chatId
||
!
prompt
)
{
throw
new
Error
(
'缺少参数'
);
throw
new
Error
(
'缺少参数'
);
...
@@ -46,12 +48,18 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -46,12 +48,18 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
// 读取对话内容
// 读取对话内容
const
prompts
=
[...
chat
.
content
,
prompt
];
const
prompts
=
[...
chat
.
content
,
prompt
];
// 上下文长度过滤
// 如果有系统提示词,自动插入
const
maxContext
=
model
.
security
.
contextMaxLen
;
if
(
model
.
systemPrompt
)
{
const
filterPrompts
=
prompts
.
unshift
({
prompts
.
length
>
maxContext
?
prompts
.
slice
(
prompts
.
length
-
maxContext
)
:
prompts
;
obj
:
'SYSTEM'
,
value
:
model
.
systemPrompt
});
}
// 控制在 tokens 数量,防止超出
const
filterPrompts
=
openaiChatFilter
(
prompts
,
7500
);
// 格式化文本内容
// 格式化文本内容
成 chatgpt 格式
const
map
=
{
const
map
=
{
Human
:
ChatCompletionRequestMessageRoleEnum
.
User
,
Human
:
ChatCompletionRequestMessageRoleEnum
.
User
,
AI
:
ChatCompletionRequestMessageRoleEnum
.
Assistant
,
AI
:
ChatCompletionRequestMessageRoleEnum
.
Assistant
,
...
@@ -63,15 +71,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -63,15 +71,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
content
:
item
.
value
content
:
item
.
value
})
})
);
);
// console.log(formatPrompts);
// 如果有系统提示词,自动插入
if
(
model
.
systemPrompt
)
{
formatPrompts
.
unshift
({
role
:
'system'
,
content
:
model
.
systemPrompt
});
}
// 计算温度
// 计算温度
const
modelConstantsData
=
modelList
.
find
((
item
)
=>
item
.
model
===
model
.
service
.
modelName
);
const
modelConstantsData
=
modelList
.
find
((
item
)
=>
item
.
model
===
model
.
service
.
modelName
);
if
(
!
modelConstantsData
)
{
if
(
!
modelConstantsData
)
{
...
...
src/pages/api/chat/generate.ts
View file @
7a6d0ea6
...
@@ -14,7 +14,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
...
@@ -14,7 +14,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
const
{
authorization
}
=
req
.
headers
;
const
{
authorization
}
=
req
.
headers
;
if
(
!
authorization
)
{
if
(
!
authorization
)
{
throw
new
Error
(
'无权
操作
'
);
throw
new
Error
(
'无权
生成对话
'
);
}
}
if
(
!
modelId
)
{
if
(
!
modelId
)
{
...
...
src/pages/api/chat/init.ts
View file @
7a6d0ea6
...
@@ -3,10 +3,14 @@ import { jsonRes } from '@/service/response';
...
@@ -3,10 +3,14 @@ import { jsonRes } from '@/service/response';
import
{
connectToDatabase
,
Chat
}
from
'@/service/mongo'
;
import
{
connectToDatabase
,
Chat
}
from
'@/service/mongo'
;
import
type
{
ChatPopulate
}
from
'@/types/mongoSchema'
;
import
type
{
ChatPopulate
}
from
'@/types/mongoSchema'
;
import
type
{
InitChatResponse
}
from
'@/api/response/chat'
;
import
type
{
InitChatResponse
}
from
'@/api/response/chat'
;
import
{
authToken
}
from
'@/service/utils/tools'
;
/*
获取我的模型
*/
/*
初始化我的聊天框,需要身份验证
*/
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
try
{
const
{
authorization
}
=
req
.
headers
;
const
userId
=
await
authToken
(
authorization
);
const
{
chatId
}
=
req
.
query
as
{
chatId
:
string
};
const
{
chatId
}
=
req
.
query
as
{
chatId
:
string
};
if
(
!
chatId
)
{
if
(
!
chatId
)
{
...
@@ -16,7 +20,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -16,7 +20,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
await
connectToDatabase
();
await
connectToDatabase
();
// 获取 chat 数据
// 获取 chat 数据
const
chat
=
await
Chat
.
findById
<
ChatPopulate
>
(
chatId
).
populate
({
const
chat
=
await
Chat
.
findOne
<
ChatPopulate
>
({
_id
:
chatId
,
userId
}).
populate
({
path
:
'modelId'
,
path
:
'modelId'
,
options
:
{
options
:
{
strictPopulate
:
false
strictPopulate
:
false
...
@@ -27,31 +34,17 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -27,31 +34,17 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
throw
new
Error
(
'聊天框不存在'
);
throw
new
Error
(
'聊天框不存在'
);
}
}
if
(
chat
.
loadAmount
>
0
)
{
await
Chat
.
updateOne
(
{
_id
:
chat
.
_id
},
{
$inc
:
{
loadAmount
:
-
1
}
}
);
}
// filter 掉被 deleted 的内容
// filter 掉被 deleted 的内容
chat
.
content
=
chat
.
content
.
filter
((
item
)
=>
item
.
deleted
!==
true
);
chat
.
content
=
chat
.
content
.
filter
((
item
)
=>
item
.
deleted
!==
true
);
const
model
=
chat
.
modelId
;
const
model
=
chat
.
modelId
;
jsonRes
<
InitChatResponse
>
(
res
,
{
jsonRes
<
InitChatResponse
>
(
res
,
{
code
:
201
,
data
:
{
data
:
{
chatId
:
chat
.
_id
,
chatId
:
chat
.
_id
,
isExpiredTime
:
chat
.
loadAmount
===
0
||
chat
.
expiredTime
<=
Date
.
now
(),
modelId
:
model
.
_id
,
modelId
:
model
.
_id
,
name
:
model
.
name
,
name
:
model
.
name
,
avatar
:
model
.
avatar
,
avatar
:
model
.
avatar
,
intro
:
model
.
intro
,
intro
:
model
.
intro
,
secret
:
model
.
security
,
modelName
:
model
.
service
.
modelName
,
modelName
:
model
.
service
.
modelName
,
chatModel
:
model
.
service
.
chatModel
,
chatModel
:
model
.
service
.
chatModel
,
history
:
chat
.
content
history
:
chat
.
content
...
...
src/pages/chat/components/SlideBar.tsx
View file @
7a6d0ea6
...
@@ -231,12 +231,12 @@ const SlideBar = ({
...
@@ -231,12 +231,12 @@ const SlideBar = ({
</>
</>
</
RenderButton
>
</
RenderButton
>
<
RenderButton
onClick=
{
onOpenShare
}
>
{
/*
<RenderButton onClick={onOpenShare}>
<>
<>
<MyIcon name="share" fill={'white'} w={'16px'} h={'16px'} mr={4} />
<MyIcon name="share" fill={'white'} w={'16px'} h={'16px'} mr={4} />
分享
分享
</>
</>
</
RenderButton
>
</RenderButton>
*/
}
<
RenderButton
onClick=
{
()
=>
router
.
push
(
'/number/setting'
)
}
>
<
RenderButton
onClick=
{
()
=>
router
.
push
(
'/number/setting'
)
}
>
<>
<>
<
MyIcon
name=
"pay"
fill=
{
'white'
}
w=
{
'16px'
}
h=
{
'16px'
}
mr=
{
4
}
/>
<
MyIcon
name=
"pay"
fill=
{
'white'
}
w=
{
'16px'
}
h=
{
'16px'
}
mr=
{
4
}
/>
...
...
src/pages/chat/index.tsx
View file @
7a6d0ea6
...
@@ -14,7 +14,6 @@ import {
...
@@ -14,7 +14,6 @@ import {
Textarea
,
Textarea
,
Box
,
Box
,
Flex
,
Flex
,
Button
,
useDisclosure
,
useDisclosure
,
Drawer
,
Drawer
,
DrawerOverlay
,
DrawerOverlay
,
...
@@ -36,8 +35,8 @@ import { useCopyData } from '@/utils/tools';
...
@@ -36,8 +35,8 @@ import { useCopyData } from '@/utils/tools';
import
{
streamFetch
}
from
'@/api/fetch'
;
import
{
streamFetch
}
from
'@/api/fetch'
;
import
SlideBar
from
'./components/SlideBar'
;
import
SlideBar
from
'./components/SlideBar'
;
import
Empty
from
'./components/Empty'
;
import
Empty
from
'./components/Empty'
;
import
{
getToken
}
from
'@/utils/user'
;
import
Icon
from
'@/components/Icon'
;
import
Icon
from
'@/components/Icon'
;
import
{
encode
}
from
'gpt-token-utils'
;
const
Markdown
=
dynamic
(()
=>
import
(
'@/components/Markdown'
));
const
Markdown
=
dynamic
(()
=>
import
(
'@/components/Markdown'
));
...
@@ -60,11 +59,9 @@ const Chat = ({ chatId }: { chatId: string }) => {
...
@@ -60,11 +59,9 @@ const Chat = ({ chatId }: { chatId: string }) => {
name
:
''
,
name
:
''
,
avatar
:
''
,
avatar
:
''
,
intro
:
''
,
intro
:
''
,
secret
:
{},
chatModel
:
''
,
chatModel
:
''
,
modelName
:
''
,
modelName
:
''
,
history
:
[],
history
:
[]
isExpiredTime
:
false
});
// 聊天框整体数据
});
// 聊天框整体数据
const
[
inputVal
,
setInputVal
]
=
useState
(
''
);
// 输入的内容
const
[
inputVal
,
setInputVal
]
=
useState
(
''
);
// 输入的内容
...
@@ -72,15 +69,6 @@ const Chat = ({ chatId }: { chatId: string }) => {
...
@@ -72,15 +69,6 @@ const Chat = ({ chatId }: { chatId: string }) => {
()
=>
chatData
.
history
[
chatData
.
history
.
length
-
1
]?.
status
===
'loading'
,
()
=>
chatData
.
history
[
chatData
.
history
.
length
-
1
]?.
status
===
'loading'
,
[
chatData
.
history
]
[
chatData
.
history
]
);
);
const
chatWindowError
=
useMemo
(()
=>
{
if
(
chatData
.
isExpiredTime
)
{
return
{
text
:
'聊天框已过期'
};
}
return
''
;
},
[
chatData
]);
const
{
copyData
}
=
useCopyData
();
const
{
copyData
}
=
useCopyData
();
const
{
isPc
,
media
}
=
useScreen
();
const
{
isPc
,
media
}
=
useScreen
();
const
{
setLoading
}
=
useGlobalStore
();
const
{
setLoading
}
=
useGlobalStore
();
...
@@ -125,31 +113,6 @@ const Chat = ({ chatId }: { chatId: string }) => {
...
@@ -125,31 +113,6 @@ const Chat = ({ chatId }: { chatId: string }) => {
onCloseSlider
();
onCloseSlider
();
},
[
chatData
,
onCloseSlider
,
router
,
toast
]);
},
[
chatData
,
onCloseSlider
,
router
,
toast
]);
// gpt3 方法
const
gpt3ChatPrompt
=
useCallback
(
async
(
newChatList
:
ChatSiteItemType
[])
=>
{
// 请求内容
const
response
=
await
postGPT3SendPrompt
({
prompt
:
newChatList
,
chatId
:
chatId
as
string
});
// 更新 AI 的内容
setChatData
((
state
)
=>
({
...
state
,
history
:
state
.
history
.
map
((
item
,
index
)
=>
{
if
(
index
!==
state
.
history
.
length
-
1
)
return
item
;
return
{
...
item
,
status
:
'finish'
,
value
:
response
};
})
}));
},
[
chatId
]
);
// gpt 对话
// gpt 对话
const
gptChatPrompt
=
useCallback
(
const
gptChatPrompt
=
useCallback
(
async
(
prompts
:
ChatSiteItemType
)
=>
{
async
(
prompts
:
ChatSiteItemType
)
=>
{
...
@@ -476,83 +439,74 @@ const Chat = ({ chatId }: { chatId: string }) => {
...
@@ -476,83 +439,74 @@ const Chat = ({ chatId }: { chatId: string }) => {
</
Box
>
</
Box
>
{
/* 发送区 */
}
{
/* 发送区 */
}
<
Box
m=
{
media
(
'20px auto'
,
'0 auto'
)
}
w=
{
'100%'
}
maxW=
{
media
(
'min(750px, 100%)'
,
'auto'
)
}
>
<
Box
m=
{
media
(
'20px auto'
,
'0 auto'
)
}
w=
{
'100%'
}
maxW=
{
media
(
'min(750px, 100%)'
,
'auto'
)
}
>
{
!!
chatWindowError
?
(
<
Box
<
Box
textAlign=
{
'center'
}
>
py=
{
5
}
<
Box
color=
{
'red'
}
>
{
chatWindowError
.
text
}
</
Box
>
position=
{
'relative'
}
<
Flex
py=
{
5
}
justifyContent=
{
'center'
}
>
boxShadow=
{
`0 0 15px rgba(0,0,0,0.1)`
}
{
getToken
()
&&
<
Button
onClick=
{
resetChat
}
>
重开对话
</
Button
>
}
border=
{
media
(
'1px solid'
,
'0'
)
}
</
Flex
>
borderColor=
{
useColorModeValue
(
'gray.200'
,
'gray.700'
)
}
</
Box
>
borderRadius=
{
[
'none'
,
'md'
]
}
)
:
(
backgroundColor=
{
useColorModeValue
(
'white'
,
'gray.700'
)
}
<
Box
>
py=
{
5
}
{
/* 输入框 */
}
position=
{
'relative'
}
<
Textarea
boxShadow=
{
`0 0 15px rgba(0,0,0,0.1)`
}
ref=
{
TextareaDom
}
border=
{
media
(
'1px solid'
,
'0'
)
}
w=
{
'100%'
}
borderColor=
{
useColorModeValue
(
'gray.200'
,
'gray.700'
)
}
pr=
{
'45px'
}
borderRadius=
{
[
'none'
,
'md'
]
}
py=
{
0
}
backgroundColor=
{
useColorModeValue
(
'white'
,
'gray.700'
)
}
border=
{
'none'
}
>
_focusVisible=
{
{
{
/* 输入框 */
}
border
:
'none'
<
Textarea
}
}
ref=
{
TextareaDom
}
placeholder=
"提问"
w=
{
'100%'
}
resize=
{
'none'
}
pr=
{
'45px'
}
value=
{
inputVal
}
py=
{
0
}
rows=
{
1
}
border=
{
'none'
}
height=
{
'22px'
}
_focusVisible=
{
{
lineHeight=
{
'22px'
}
border
:
'none'
maxHeight=
{
'150px'
}
}
}
maxLength=
{
-
1
}
placeholder=
"提问"
overflowY=
{
'auto'
}
resize=
{
'none'
}
color=
{
useColorModeValue
(
'blackAlpha.700'
,
'white'
)
}
value=
{
inputVal
}
onChange=
{
(
e
)
=>
{
rows=
{
1
}
const
textarea
=
e
.
target
;
height=
{
'22px'
}
setInputVal
(
textarea
.
value
);
lineHeight=
{
'22px'
}
textarea
.
style
.
height
=
textareaMinH
;
maxHeight=
{
'150px'
}
textarea
.
style
.
height
=
`${textarea.scrollHeight}px`
;
maxLength=
{
chatData
?.
secret
.
contentMaxLen
||
-
1
}
}
}
overflowY=
{
'auto'
}
onKeyDown=
{
(
e
)
=>
{
color=
{
useColorModeValue
(
'blackAlpha.700'
,
'white'
)
}
// 触发快捷发送
onChange=
{
(
e
)
=>
{
if
(
isPc
&&
e
.
keyCode
===
13
&&
!
e
.
shiftKey
)
{
const
textarea
=
e
.
target
;
sendPrompt
();
setInputVal
(
textarea
.
value
);
e
.
preventDefault
();
textarea
.
style
.
height
=
textareaMinH
;
}
textarea
.
style
.
height
=
`${textarea.scrollHeight}px`
;
// 全选内容
}
}
// @ts-ignore
onKeyDown=
{
(
e
)
=>
{
e
.
key
===
'a'
&&
e
.
ctrlKey
&&
e
.
target
?.
select
();
// 触发快捷发送
}
}
if
(
isPc
&&
e
.
keyCode
===
13
&&
!
e
.
shiftKey
)
{
/>
sendPrompt
();
{
/* 发送和等待按键 */
}
e
.
preventDefault
();
<
Box
position=
{
'absolute'
}
bottom=
{
5
}
right=
{
media
(
'20px'
,
'10px'
)
}
>
}
{
isChatting
?
(
// 全选内容
<
Image
// @ts-ignore
style=
{
{
transform
:
'translateY(4px)'
}
}
e
.
key
===
'a'
&&
e
.
ctrlKey
&&
e
.
target
?.
select
();
src=
{
'/icon/chatting.svg'
}
}
}
width=
{
30
}
/>
height=
{
30
}
{
/* 发送和等待按键 */
}
alt=
{
''
}
<
Box
position=
{
'absolute'
}
bottom=
{
5
}
right=
{
media
(
'20px'
,
'10px'
)
}
>
/>
{
isChatting
?
(
)
:
(
<
Image
<
Box
cursor=
{
'pointer'
}
onClick=
{
sendPrompt
}
>
style=
{
{
transform
:
'translateY(4px)'
}
}
<
Icon
src=
{
'/icon/chatting.svg'
}
name=
{
'chatSend'
}
width=
{
30
}
width=
{
'20px'
}
height=
{
30
}
height=
{
'20px'
}
alt=
{
''
}
fill=
{
useColorModeValue
(
'#718096'
,
'white'
)
}
/>
></
Icon
>
)
:
(
</
Box
>
<
Box
cursor=
{
'pointer'
}
onClick=
{
sendPrompt
}
>
)
}
<
Icon
name=
{
'chatSend'
}
width=
{
'20px'
}
height=
{
'20px'
}
fill=
{
useColorModeValue
(
'#718096'
,
'white'
)
}
></
Icon
>
</
Box
>
)
}
</
Box
>
</
Box
>
</
Box
>
)
}
</
Box
>
</
Box
>
</
Box
>
</
Flex
>
</
Flex
>
</
Flex
>
</
Flex
>
...
...
src/pages/data/components/ImportDataModal.tsx
View file @
7a6d0ea6
...
@@ -22,7 +22,7 @@ import { useToast } from '@/hooks/useToast';
...
@@ -22,7 +22,7 @@ import { useToast } from '@/hooks/useToast';
import
{
useLoading
}
from
'@/hooks/useLoading'
;
import
{
useLoading
}
from
'@/hooks/useLoading'
;
import
{
formatPrice
}
from
'@/utils/user'
;
import
{
formatPrice
}
from
'@/utils/user'
;
import
{
modelList
,
ChatModelNameEnum
}
from
'@/constants/model'
;
import
{
modelList
,
ChatModelNameEnum
}
from
'@/constants/model'
;
import
{
encode
,
decode
}
from
'gpt-token-utils'
;
import
{
encode
}
from
'gpt-token-utils'
;
const
fileExtension
=
'.txt,.doc,.docx,.pdf,.md'
;
const
fileExtension
=
'.txt,.doc,.docx,.pdf,.md'
;
...
...
src/pages/model/components/ModelEditForm.tsx
View file @
7a6d0ea6
...
@@ -105,7 +105,7 @@ const ModelEditForm = ({ formHooks }: { formHooks: UseFormReturn<ModelSchema> })
...
@@ -105,7 +105,7 @@ const ModelEditForm = ({ formHooks }: { formHooks: UseFormReturn<ModelSchema> })
/>
/>
</
Box
>
</
Box
>
</
Card
>
</
Card
>
<
Card
p=
{
4
}
>
{
/*
<Card p={4}>
<Box fontWeight={'bold'}>安全策略</Box>
<Box fontWeight={'bold'}>安全策略</Box>
<FormControl mt={2}>
<FormControl mt={2}>
<Flex alignItems={'center'}>
<Flex alignItems={'center'}>
...
@@ -201,7 +201,7 @@ const ModelEditForm = ({ formHooks }: { formHooks: UseFormReturn<ModelSchema> })
...
@@ -201,7 +201,7 @@ const ModelEditForm = ({ formHooks }: { formHooks: UseFormReturn<ModelSchema> })
<Box ml={3}>次</Box>
<Box ml={3}>次</Box>
</Flex>
</Flex>
</FormControl>
</FormControl>
</
Card
>
</Card>
*/
}
</>
</>
);
);
};
};
...
...
src/service/response.ts
View file @
7a6d0ea6
...
@@ -31,7 +31,6 @@ export const jsonRes = <T = any>(
...
@@ -31,7 +31,6 @@ export const jsonRes = <T = any>(
console
.
log
(
'error->'
);
console
.
log
(
'error->'
);
console
.
log
(
'code:'
,
error
.
code
);
console
.
log
(
'code:'
,
error
.
code
);
console
.
log
(
'statusText:'
,
error
?.
response
?.
statusText
);
console
.
log
(
'statusText:'
,
error
?.
response
?.
statusText
);
console
.
log
(
'data len:'
,
error
?.
response
?.
config
?.
data
.
length
);
console
.
log
(
'msg:'
,
msg
);
console
.
log
(
'msg:'
,
msg
);
}
}
...
...
src/service/utils/chat.ts
View file @
7a6d0ea6
...
@@ -32,14 +32,11 @@ export const authChat = async (chatId: string, authorization?: string) => {
...
@@ -32,14 +32,11 @@ export const authChat = async (chatId: string, authorization?: string) => {
return
Promise
.
reject
(
'模型不存在'
);
return
Promise
.
reject
(
'模型不存在'
);
}
}
// 安全校验
// 凭证校验
if
(
chat
.
loadAmount
===
0
||
chat
.
expiredTime
<=
Date
.
now
())
{
return
Promise
.
reject
(
'聊天框已过期'
);
}
// 分享校验
if
(
!
chat
.
isShare
)
{
if
(
!
chat
.
isShare
)
{
await
authToken
(
authorization
);
await
authToken
(
authorization
);
}
else
if
(
chat
.
loadAmount
===
0
||
chat
.
expiredTime
<=
Date
.
now
())
{
return
Promise
.
reject
(
'聊天框已过期'
);
}
}
// 获取 user 的 apiKey
// 获取 user 的 apiKey
...
@@ -47,6 +44,7 @@ export const authChat = async (chatId: string, authorization?: string) => {
...
@@ -47,6 +44,7 @@ export const authChat = async (chatId: string, authorization?: string) => {
const
userApiKey
=
user
.
accounts
?.
find
((
item
:
any
)
=>
item
.
type
===
'openai'
)?.
value
;
const
userApiKey
=
user
.
accounts
?.
find
((
item
:
any
)
=>
item
.
type
===
'openai'
)?.
value
;
// 没有 apikey ,校验余额
if
(
!
userApiKey
&&
formatPrice
(
user
.
balance
)
<=
0
)
{
if
(
!
userApiKey
&&
formatPrice
(
user
.
balance
)
<=
0
)
{
return
Promise
.
reject
(
'该账号余额不足'
);
return
Promise
.
reject
(
'该账号余额不足'
);
}
}
...
...
src/service/utils/tools.ts
View file @
7a6d0ea6
...
@@ -4,6 +4,8 @@ import { User } from '../models/user';
...
@@ -4,6 +4,8 @@ import { User } from '../models/user';
import
tunnel
from
'tunnel'
;
import
tunnel
from
'tunnel'
;
import
type
{
UserModelSchema
}
from
'@/types/mongoSchema'
;
import
type
{
UserModelSchema
}
from
'@/types/mongoSchema'
;
import
{
formatPrice
}
from
'@/utils/user'
;
import
{
formatPrice
}
from
'@/utils/user'
;
import
{
ChatItemType
}
from
'@/types/chat'
;
import
{
encode
}
from
'gpt-token-utils'
;
/* 密码加密 */
/* 密码加密 */
export
const
hashPassword
=
(
psw
:
string
)
=>
{
export
const
hashPassword
=
(
psw
:
string
)
=>
{
...
@@ -91,3 +93,29 @@ export const httpsAgent =
...
@@ -91,3 +93,29 @@ export const httpsAgent =
}
}
})
})
:
undefined
;
:
undefined
;
/* tokens 截断 */
export
const
openaiChatFilter
=
(
prompts
:
ChatItemType
[],
maxTokens
:
number
)
=>
{
let
res
:
ChatItemType
[]
=
[];
let
systemPrompt
:
ChatItemType
|
null
=
null
;
// System 词保留
if
(
prompts
[
0
]?.
obj
===
'SYSTEM'
)
{
systemPrompt
=
prompts
.
shift
()
as
ChatItemType
;
maxTokens
-=
encode
(
prompts
[
0
].
value
).
length
;
}
// 从后往前截取
for
(
let
i
=
prompts
.
length
-
1
;
i
>=
0
;
i
--
)
{
const
tokens
=
encode
(
prompts
[
i
].
value
).
length
;
if
(
maxTokens
>=
tokens
)
{
res
.
unshift
(
prompts
[
i
]);
maxTokens
-=
tokens
;
}
else
{
break
;
}
}
return
systemPrompt
?
[
systemPrompt
,
...
res
]
:
res
;
};
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