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
75cf3d1e
authored
Mar 25, 2023
by
archer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 拆分文本账单结算
parent
02cee35a
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
128 additions
and
26 deletions
+128
-26
src/constants/user.ts
+11
-0
src/pages/api/chat/chatGpt.ts
+4
-3
src/pages/api/chat/gpt3.ts
+2
-2
src/pages/api/data/delData.ts
+11
-1
src/pages/api/data/getDataItems.ts
+1
-1
src/pages/api/data/getDataList.ts
+1
-1
src/pages/api/user/getBill.ts
+1
-1
src/pages/data/components/ImportDataModal.tsx
+25
-3
src/pages/data/list.tsx
+5
-1
src/pages/number/setting.tsx
+3
-0
src/service/events/generateQA.ts
+10
-8
src/service/events/pushBill.ts
+49
-2
src/service/models/bill.ts
+2
-3
src/types/mongoSchema.d.ts
+1
-0
src/types/user.d.ts
+1
-0
src/utils/adapt.ts
+1
-0
No files found.
src/constants/user.ts
View file @
75cf3d1e
export
enum
BillTypeEnum
{
chat
=
'chat'
,
splitData
=
'splitData'
,
return
=
'return'
}
export
enum
PageTypeEnum
{
export
enum
PageTypeEnum
{
login
=
'login'
,
login
=
'login'
,
register
=
'register'
,
register
=
'register'
,
forgetPassword
=
'forgetPassword'
forgetPassword
=
'forgetPassword'
}
}
export
const
BillTypeMap
:
Record
<
`
${
BillTypeEnum
}
`
,
string
>
=
{
[
BillTypeEnum
.
chat
]:
'对话'
,
[
BillTypeEnum
.
splitData
]:
'文本拆分'
,
[
BillTypeEnum
.
return
]:
'退款'
};
src/pages/api/chat/chatGpt.ts
View file @
75cf3d1e
...
@@ -9,7 +9,7 @@ import { jsonRes } from '@/service/response';
...
@@ -9,7 +9,7 @@ import { jsonRes } from '@/service/response';
import
type
{
ModelSchema
}
from
'@/types/mongoSchema'
;
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
{
push
Bill
}
from
'@/service/events/pushChat
Bill'
;
import
{
push
ChatBill
}
from
'@/service/events/push
Bill'
;
/* 发送提示词 */
/* 发送提示词 */
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
...
@@ -91,7 +91,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -91,7 +91,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
messages
:
formatPrompts
,
messages
:
formatPrompts
,
frequency_penalty
:
0.5
,
// 越大,重复内容越少
frequency_penalty
:
0.5
,
// 越大,重复内容越少
presence_penalty
:
-
0.5
,
// 越大,越容易出现新内容
presence_penalty
:
-
0.5
,
// 越大,越容易出现新内容
stream
:
true
stream
:
true
,
stop
:
[
'。!?.!.'
]
},
},
{
{
timeout
:
40000
,
timeout
:
40000
,
...
@@ -149,7 +150,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -149,7 +150,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const
promptsContent
=
formatPrompts
.
map
((
item
)
=>
item
.
content
).
join
(
''
);
const
promptsContent
=
formatPrompts
.
map
((
item
)
=>
item
.
content
).
join
(
''
);
// 只有使用平台的 key 才计费
// 只有使用平台的 key 才计费
!
userApiKey
&&
!
userApiKey
&&
pushBill
({
push
Chat
Bill
({
modelName
:
model
.
service
.
modelName
,
modelName
:
model
.
service
.
modelName
,
userId
,
userId
,
chatId
,
chatId
,
...
...
src/pages/api/chat/gpt3.ts
View file @
75cf3d1e
...
@@ -8,7 +8,7 @@ import { jsonRes } from '@/service/response';
...
@@ -8,7 +8,7 @@ import { jsonRes } from '@/service/response';
import
type
{
ModelSchema
}
from
'@/types/mongoSchema'
;
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
{
push
Bill
}
from
'@/service/events/pushChat
Bill'
;
import
{
push
ChatBill
}
from
'@/service/events/push
Bill'
;
/* 发送提示词 */
/* 发送提示词 */
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
...
@@ -142,7 +142,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -142,7 +142,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
// 只有使用平台的 key 才计费
// 只有使用平台的 key 才计费
!
userApiKey
&&
!
userApiKey
&&
pushBill
({
push
Chat
Bill
({
modelName
:
model
.
service
.
modelName
,
modelName
:
model
.
service
.
modelName
,
userId
,
userId
,
chatId
,
chatId
,
...
...
src/pages/api/data/delData.ts
View file @
75cf3d1e
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
{
jsonRes
}
from
'@/service/response'
;
import
{
jsonRes
}
from
'@/service/response'
;
import
{
connectToDatabase
,
Data
}
from
'@/service/mongo'
;
import
{
connectToDatabase
,
Data
,
DataItem
}
from
'@/service/mongo'
;
import
{
authToken
}
from
'@/service/utils/tools'
;
import
{
authToken
}
from
'@/service/utils/tools'
;
import
type
{
DataListItem
}
from
'@/types/data'
;
import
type
{
DataListItem
}
from
'@/types/data'
;
import
type
{
PagingData
}
from
'@/types'
;
import
type
{
PagingData
}
from
'@/types'
;
...
@@ -27,6 +27,16 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -27,6 +27,16 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
isDeleted
:
true
isDeleted
:
true
});
});
// 改变 dataItem 状态为 0
await
DataItem
.
updateMany
(
{
dataId
},
{
status
:
0
}
);
jsonRes
<
PagingData
<
DataListItem
>>
(
res
);
jsonRes
<
PagingData
<
DataListItem
>>
(
res
);
}
catch
(
err
)
{
}
catch
(
err
)
{
jsonRes
(
res
,
{
jsonRes
(
res
,
{
...
...
src/pages/api/data/getDataItems.ts
View file @
75cf3d1e
...
@@ -26,7 +26,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -26,7 +26,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
dataId
,
dataId
,
status
:
0
status
:
0
})
})
.
sort
({
time
:
-
1
})
// 按照创建时间倒序排列
.
sort
({
_id
:
-
1
})
// 按照创建时间倒序排列
.
skip
((
pageNum
-
1
)
*
pageSize
)
.
skip
((
pageNum
-
1
)
*
pageSize
)
.
limit
(
pageSize
);
.
limit
(
pageSize
);
...
...
src/pages/api/data/getDataList.ts
View file @
75cf3d1e
...
@@ -58,7 +58,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -58,7 +58,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
$filter
:
{
$filter
:
{
input
:
'$items'
,
input
:
'$items'
,
as
:
'item'
,
as
:
'item'
,
cond
:
{
$
eq
:
[
'$$item.status'
,
1
]
}
// 统计status为1
的数量
cond
:
{
$
ne
:
[
'$$item.status'
,
0
]
}
// 统计 status 不为0
的数量
}
}
}
}
}
}
...
...
src/pages/api/user/getBill.ts
View file @
75cf3d1e
...
@@ -25,7 +25,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -25,7 +25,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const
bills
=
await
Bill
.
find
<
BillSchema
>
({
const
bills
=
await
Bill
.
find
<
BillSchema
>
({
userId
userId
})
})
.
sort
({
time
:
-
1
})
// 按照创建时间倒序排列
.
sort
({
_id
:
-
1
})
// 按照创建时间倒序排列
.
skip
((
pageNum
-
1
)
*
pageSize
)
.
skip
((
pageNum
-
1
)
*
pageSize
)
.
limit
(
pageSize
);
.
limit
(
pageSize
);
...
...
src/pages/data/components/ImportDataModal.tsx
View file @
75cf3d1e
...
@@ -8,7 +8,6 @@ import {
...
@@ -8,7 +8,6 @@ import {
ModalBody
,
ModalBody
,
ModalCloseButton
,
ModalCloseButton
,
Button
,
Button
,
Input
,
Box
,
Box
,
Flex
,
Flex
,
Textarea
Textarea
...
@@ -21,10 +20,20 @@ import { postSplitData } from '@/api/data';
...
@@ -21,10 +20,20 @@ import { postSplitData } from '@/api/data';
import
{
useMutation
}
from
'@tanstack/react-query'
;
import
{
useMutation
}
from
'@tanstack/react-query'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
import
{
useLoading
}
from
'@/hooks/useLoading'
;
import
{
useLoading
}
from
'@/hooks/useLoading'
;
import
{
formatPrice
}
from
'@/utils/user'
;
import
{
modelList
,
ChatModelNameEnum
}
from
'@/constants/model'
;
const
fileExtension
=
'.txt,.doc,.docx,.pdf,.md'
;
const
fileExtension
=
'.txt,.doc,.docx,.pdf,.md'
;
const
ImportDataModal
=
({
dataId
,
onClose
}:
{
dataId
:
string
;
onClose
:
()
=>
void
})
=>
{
const
ImportDataModal
=
({
dataId
,
onClose
,
onSuccess
}:
{
dataId
:
string
;
onClose
:
()
=>
void
;
onSuccess
:
()
=>
void
;
})
=>
{
const
{
openConfirm
,
ConfirmChild
}
=
useConfirm
({
const
{
openConfirm
,
ConfirmChild
}
=
useConfirm
({
content
:
'确认提交生成任务?该任务无法终止!'
content
:
'确认提交生成任务?该任务无法终止!'
});
});
...
@@ -60,6 +69,7 @@ const ImportDataModal = ({ dataId, onClose }: { dataId: string; onClose: () => v
...
@@ -60,6 +69,7 @@ const ImportDataModal = ({ dataId, onClose }: { dataId: string; onClose: () => v
status
:
'success'
status
:
'success'
});
});
onClose
();
onClose
();
onSuccess
();
},
},
onError
(
err
:
any
)
{
onError
(
err
:
any
)
{
toast
({
toast
({
...
@@ -110,7 +120,16 @@ const ImportDataModal = ({ dataId, onClose }: { dataId: string; onClose: () => v
...
@@ -110,7 +120,16 @@ const ImportDataModal = ({ dataId, onClose }: { dataId: string; onClose: () => v
<
Modal
isOpen=
{
true
}
onClose=
{
onClose
}
>
<
Modal
isOpen=
{
true
}
onClose=
{
onClose
}
>
<
ModalOverlay
/>
<
ModalOverlay
/>
<
ModalContent
position=
{
'relative'
}
maxW=
{
[
'90vw'
,
'800px'
]
}
>
<
ModalContent
position=
{
'relative'
}
maxW=
{
[
'90vw'
,
'800px'
]
}
>
<
ModalHeader
>
导入数据,生成QA
</
ModalHeader
>
<
ModalHeader
>
导入数据,生成QA
<
Box
ml=
{
2
}
as=
{
'span'
}
fontSize=
{
'sm'
}
color=
{
'blackAlpha.600'
}
>
{
formatPrice
(
modelList
.
find
((
item
)
=>
item
.
model
===
ChatModelNameEnum
.
GPT35
)?.
price
||
0
,
1000
)
}
元/1K tokens
</
Box
>
</
ModalHeader
>
<
ModalCloseButton
/>
<
ModalCloseButton
/>
<
ModalBody
display=
{
'flex'
}
>
<
ModalBody
display=
{
'flex'
}
>
...
@@ -132,6 +151,7 @@ const ImportDataModal = ({ dataId, onClose }: { dataId: string; onClose: () => v
...
@@ -132,6 +151,7 @@ const ImportDataModal = ({ dataId, onClose }: { dataId: string; onClose: () => v
<
Box
flex=
{
'1 0 0'
}
w=
{
0
}
ml=
{
3
}
minH=
{
'200px'
}
>
<
Box
flex=
{
'1 0 0'
}
w=
{
0
}
ml=
{
3
}
minH=
{
'200px'
}
>
{
activeTab
===
'text'
&&
(
{
activeTab
===
'text'
&&
(
<>
<
Textarea
<
Textarea
h=
{
'100%'
}
h=
{
'100%'
}
maxLength=
{
-
1
}
maxLength=
{
-
1
}
...
@@ -139,6 +159,8 @@ const ImportDataModal = ({ dataId, onClose }: { dataId: string; onClose: () => v
...
@@ -139,6 +159,8 @@ const ImportDataModal = ({ dataId, onClose }: { dataId: string; onClose: () => v
placeholder=
{
'请粘贴或输入需要处理的文本'
}
placeholder=
{
'请粘贴或输入需要处理的文本'
}
onChange=
{
(
e
)
=>
setTextInput
(
e
.
target
.
value
)
}
onChange=
{
(
e
)
=>
setTextInput
(
e
.
target
.
value
)
}
/>
/>
<
Box
mt=
{
2
}
>
一共
{
textInput
.
length
}
个字
</
Box
>
</>
)
}
)
}
{
activeTab
===
'doc'
&&
(
{
activeTab
===
'doc'
&&
(
<
Flex
<
Flex
...
...
src/pages/data/list.tsx
View file @
75cf3d1e
...
@@ -209,7 +209,11 @@ const DataList = () => {
...
@@ -209,7 +209,11 @@ const DataList = () => {
</
Card
>
</
Card
>
{
ImportDataId
&&
(
{
ImportDataId
&&
(
<
ImportDataModal
dataId=
{
ImportDataId
}
onClose=
{
()
=>
setImportDataId
(
undefined
)
}
/>
<
ImportDataModal
dataId=
{
ImportDataId
}
onClose=
{
()
=>
setImportDataId
(
undefined
)
}
onSuccess=
{
()
=>
getData
(
1
,
true
)
}
/>
)
}
)
}
{
isOpenCreateDataModal
&&
(
{
isOpenCreateDataModal
&&
(
<
CreateDataModal
onClose=
{
onCloseCreateDataModal
}
onSuccess=
{
()
=>
getData
(
1
,
true
)
}
/>
<
CreateDataModal
onClose=
{
onCloseCreateDataModal
}
onSuccess=
{
()
=>
getData
(
1
,
true
)
}
/>
...
...
src/pages/number/setting.tsx
View file @
75cf3d1e
...
@@ -33,6 +33,7 @@ import dayjs from 'dayjs';
...
@@ -33,6 +33,7 @@ import dayjs from 'dayjs';
import
{
formatPrice
}
from
'@/utils/user'
;
import
{
formatPrice
}
from
'@/utils/user'
;
import
WxConcat
from
'@/components/WxConcat'
;
import
WxConcat
from
'@/components/WxConcat'
;
import
ScrollData
from
'@/components/ScrollData'
;
import
ScrollData
from
'@/components/ScrollData'
;
import
{
BillTypeMap
}
from
'@/constants/user'
;
const
PayModal
=
dynamic
(()
=>
import
(
'./components/PayModal'
));
const
PayModal
=
dynamic
(()
=>
import
(
'./components/PayModal'
));
...
@@ -266,6 +267,7 @@ const NumberSetting = () => {
...
@@ -266,6 +267,7 @@ const NumberSetting = () => {
<
Thead
>
<
Thead
>
<
Tr
>
<
Tr
>
<
Th
>
时间
</
Th
>
<
Th
>
时间
</
Th
>
<
Th
>
类型
</
Th
>
<
Th
>
内容长度
</
Th
>
<
Th
>
内容长度
</
Th
>
<
Th
>
Tokens 长度
</
Th
>
<
Th
>
Tokens 长度
</
Th
>
<
Th
>
消费
</
Th
>
<
Th
>
消费
</
Th
>
...
@@ -275,6 +277,7 @@ const NumberSetting = () => {
...
@@ -275,6 +277,7 @@ const NumberSetting = () => {
{
bills
.
map
((
item
)
=>
(
{
bills
.
map
((
item
)
=>
(
<
Tr
key=
{
item
.
id
}
>
<
Tr
key=
{
item
.
id
}
>
<
Td
>
{
item
.
time
}
</
Td
>
<
Td
>
{
item
.
time
}
</
Td
>
<
Td
>
{
BillTypeMap
[
item
.
type
]
}
</
Td
>
<
Td
>
{
item
.
textLen
}
</
Td
>
<
Td
>
{
item
.
textLen
}
</
Td
>
<
Td
>
{
item
.
tokenLen
}
</
Td
>
<
Td
>
{
item
.
tokenLen
}
</
Td
>
<
Td
>
{
item
.
price
}
元
</
Td
>
<
Td
>
{
item
.
price
}
元
</
Td
>
...
...
src/service/events/generateQA.ts
View file @
75cf3d1e
...
@@ -4,6 +4,7 @@ import { httpsAgent, getOpenApiKey } from '@/service/utils/tools';
...
@@ -4,6 +4,7 @@ import { httpsAgent, getOpenApiKey } from '@/service/utils/tools';
import
type
{
ChatCompletionRequestMessage
}
from
'openai'
;
import
type
{
ChatCompletionRequestMessage
}
from
'openai'
;
import
{
DataItemSchema
}
from
'@/types/mongoSchema'
;
import
{
DataItemSchema
}
from
'@/types/mongoSchema'
;
import
{
ChatModelNameEnum
}
from
'@/constants/model'
;
import
{
ChatModelNameEnum
}
from
'@/constants/model'
;
import
{
pushSplitDataBill
}
from
'@/service/events/pushBill'
;
export
async
function
generateQA
(
next
=
false
):
Promise
<
any
>
{
export
async
function
generateQA
(
next
=
false
):
Promise
<
any
>
{
if
(
global
.
generatingQA
&&
!
next
)
return
;
if
(
global
.
generatingQA
&&
!
next
)
return
;
...
@@ -83,20 +84,21 @@ export async function generateQA(next = false): Promise<any> {
...
@@ -83,20 +84,21 @@ export async function generateQA(next = false): Promise<any> {
const
splitResponse
=
splitText
(
content
||
''
);
const
splitResponse
=
splitText
(
content
||
''
);
// 插入数据库,并修改状态
// 插入数据库,并修改状态
await
DataItem
.
findByIdAndUpdate
(
dataItem
.
_id
,
{
await
DataItem
.
findByIdAndUpdate
(
dataItem
.
_id
,
{
status
:
dataItem
.
temperature
>=
80
?
0
:
1
,
// 需要生成 5 组内容。0,0.2,0.4,0.6,0.8
status
:
dataItem
.
temperature
>=
90
?
0
:
1
,
// 需要生成 4 组内容。0,0.3,0.6,0.9
temperature
:
dataItem
.
temperature
>=
80
?
dataItem
.
temperature
:
dataItem
.
temperature
+
2
0
,
temperature
:
dataItem
.
temperature
>=
90
?
dataItem
.
temperature
:
dataItem
.
temperature
+
3
0
,
$push
:
{
$push
:
{
result
:
{
result
:
{
$each
:
splitResponse
$each
:
splitResponse
}
}
}
}
});
});
console
.
log
(
// 计费
'生成成功,time:'
,
!
userApiKey
&&
`
${(
Date
.
now
()
-
startTime
)
/
1000
}
s`
,
pushSplitDataBill
({
'result length: '
,
userId
:
dataItem
.
userId
,
splitResponse
.
length
text
:
systemPrompt
.
content
+
dataItem
.
text
+
content
);
});
console
.
log
(
'生成QA成功,time:'
,
`
${(
Date
.
now
()
-
startTime
)
/
1000
}
s`
);
}
catch
(
error
:
any
)
{
}
catch
(
error
:
any
)
{
console
.
log
(
'error: 生成QA错误'
,
dataItem
?.
_id
);
console
.
log
(
'error: 生成QA错误'
,
dataItem
?.
_id
);
console
.
log
(
'response:'
,
error
?.
response
);
console
.
log
(
'response:'
,
error
?.
response
);
...
...
src/service/events/push
Chat
Bill.ts
→
src/service/events/pushBill.ts
View file @
75cf3d1e
import
{
connectToDatabase
,
Bill
,
User
}
from
'../mongo'
;
import
{
connectToDatabase
,
Bill
,
User
}
from
'../mongo'
;
import
{
modelList
}
from
'@/constants/model'
;
import
{
modelList
,
ChatModelNameEnum
}
from
'@/constants/model'
;
import
{
encode
}
from
'gpt-token-utils'
;
import
{
encode
}
from
'gpt-token-utils'
;
import
{
formatPrice
}
from
'@/utils/user'
;
import
{
formatPrice
}
from
'@/utils/user'
;
export
const
pushBill
=
async
({
export
const
push
Chat
Bill
=
async
({
modelName
,
modelName
,
userId
,
userId
,
chatId
,
chatId
,
...
@@ -28,6 +28,7 @@ export const pushBill = async ({
...
@@ -28,6 +28,7 @@ export const pushBill = async ({
// 计算价格
// 计算价格
const
price
=
unitPrice
*
tokens
.
length
;
const
price
=
unitPrice
*
tokens
.
length
;
console
.
log
(
'chat bill'
);
console
.
log
(
'token len:'
,
tokens
.
length
);
console
.
log
(
'token len:'
,
tokens
.
length
);
console
.
log
(
'text len: '
,
text
.
length
);
console
.
log
(
'text len: '
,
text
.
length
);
console
.
log
(
'price: '
,
`
${
formatPrice
(
price
)}
元`
);
console
.
log
(
'price: '
,
`
${
formatPrice
(
price
)}
元`
);
...
@@ -50,6 +51,52 @@ export const pushBill = async ({
...
@@ -50,6 +51,52 @@ export const pushBill = async ({
$inc
:
{
balance
:
-
price
}
$inc
:
{
balance
:
-
price
}
});
});
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
log
(
'创建账单失败:'
,
error
);
billId
&&
Bill
.
findByIdAndDelete
(
billId
);
}
}
catch
(
error
)
{
console
.
log
(
error
);
}
};
export
const
pushSplitDataBill
=
async
({
userId
,
text
}:
{
userId
:
string
;
text
:
string
})
=>
{
await
connectToDatabase
();
let
billId
;
try
{
// 获取模型单价格, 都是用 gpt35 拆分
const
modelItem
=
modelList
.
find
((
item
)
=>
item
.
model
===
ChatModelNameEnum
.
GPT35
);
const
unitPrice
=
modelItem
?.
price
||
5
;
// 计算 token 数量
const
tokens
=
encode
(
text
);
// 计算价格
const
price
=
unitPrice
*
tokens
.
length
;
console
.
log
(
'splitData bill'
);
console
.
log
(
'token len:'
,
tokens
.
length
);
console
.
log
(
'text len: '
,
text
.
length
);
console
.
log
(
'price: '
,
`
${
formatPrice
(
price
)}
元`
);
try
{
// 插入 Bill 记录
const
res
=
await
Bill
.
create
({
userId
,
type
:
'splitData'
,
modelName
:
ChatModelNameEnum
.
GPT35
,
textLen
:
text
.
length
,
tokenLen
:
tokens
.
length
,
price
});
billId
=
res
.
_id
;
// 账号扣费
await
User
.
findByIdAndUpdate
(
userId
,
{
$inc
:
{
balance
:
-
price
}
});
}
catch
(
error
)
{
console
.
log
(
'创建账单失败:'
,
error
);
billId
&&
Bill
.
findByIdAndDelete
(
billId
);
billId
&&
Bill
.
findByIdAndDelete
(
billId
);
}
}
}
catch
(
error
)
{
}
catch
(
error
)
{
...
...
src/service/models/bill.ts
View file @
75cf3d1e
...
@@ -10,7 +10,7 @@ const BillSchema = new Schema({
...
@@ -10,7 +10,7 @@ const BillSchema = new Schema({
},
},
type
:
{
type
:
{
type
:
String
,
type
:
String
,
enum
:
[
'chat'
,
'
generate
Data'
,
'return'
],
enum
:
[
'chat'
,
'
split
Data'
,
'return'
],
required
:
true
required
:
true
},
},
modelName
:
{
modelName
:
{
...
@@ -20,8 +20,7 @@ const BillSchema = new Schema({
...
@@ -20,8 +20,7 @@ const BillSchema = new Schema({
},
},
chatId
:
{
chatId
:
{
type
:
Schema
.
Types
.
ObjectId
,
type
:
Schema
.
Types
.
ObjectId
,
ref
:
'chat'
,
ref
:
'chat'
required
:
true
},
},
time
:
{
time
:
{
type
:
Date
,
type
:
Date
,
...
...
src/types/mongoSchema.d.ts
View file @
75cf3d1e
...
@@ -80,6 +80,7 @@ export interface ChatPopulate extends ChatSchema {
...
@@ -80,6 +80,7 @@ export interface ChatPopulate extends ChatSchema {
export
interface
BillSchema
{
export
interface
BillSchema
{
_id
:
string
;
_id
:
string
;
userId
:
string
;
userId
:
string
;
type
:
'chat'
|
'splitData'
|
'return'
;
chatId
:
string
;
chatId
:
string
;
time
:
Date
;
time
:
Date
;
textLen
:
number
;
textLen
:
number
;
...
...
src/types/user.d.ts
View file @
75cf3d1e
...
@@ -24,6 +24,7 @@ export interface UserUpdateParams {
...
@@ -24,6 +24,7 @@ export interface UserUpdateParams {
export
interface
UserBillType
{
export
interface
UserBillType
{
id
:
string
;
id
:
string
;
time
:
string
;
time
:
string
;
type
:
'chat'
|
'splitData'
|
'return'
;
textLen
:
number
;
textLen
:
number
;
tokenLen
:
number
;
tokenLen
:
number
;
userId
:
string
;
userId
:
string
;
...
...
src/utils/adapt.ts
View file @
75cf3d1e
...
@@ -6,6 +6,7 @@ import type { UserBillType } from '@/types/user';
...
@@ -6,6 +6,7 @@ import type { UserBillType } from '@/types/user';
export
const
adaptBill
=
(
bill
:
BillSchema
):
UserBillType
=>
{
export
const
adaptBill
=
(
bill
:
BillSchema
):
UserBillType
=>
{
return
{
return
{
id
:
bill
.
_id
,
id
:
bill
.
_id
,
type
:
bill
.
type
,
userId
:
bill
.
userId
,
userId
:
bill
.
userId
,
chatId
:
bill
.
chatId
,
chatId
:
bill
.
chatId
,
time
:
dayjs
(
bill
.
time
).
format
(
'YYYY/MM/DD HH:mm:ss'
),
time
:
dayjs
(
bill
.
time
).
format
(
'YYYY/MM/DD HH:mm:ss'
),
...
...
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