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
5249297c
authored
Mar 27, 2023
by
archer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
perf: bill logs
parent
9280a21d
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
160 additions
and
152 deletions
+160
-152
src/pages/api/chat/chatGpt.ts
+7
-7
src/pages/api/chat/gpt3.ts
+7
-7
src/service/events/generateAbstract.ts
+38
-44
src/service/events/generateQA.ts
+43
-36
src/service/events/pushBill.ts
+64
-57
src/service/response.ts
+1
-1
No files found.
src/pages/api/chat/chatGpt.ts
View file @
5249297c
...
...
@@ -148,13 +148,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const
promptsContent
=
formatPrompts
.
map
((
item
)
=>
item
.
content
).
join
(
''
);
// 只有使用平台的 key 才计费
!
userApiKey
&&
pushChatBill
({
modelName
:
model
.
service
.
modelName
,
userId
,
chatId
,
text
:
promptsContent
+
responseContent
});
pushChatBill
({
isPay
:
!
userApiKey
,
modelName
:
model
.
service
.
modelName
,
userId
,
chatId
,
text
:
promptsContent
+
responseContent
});
}
catch
(
err
:
any
)
{
if
(
step
===
1
)
{
// 直接结束流
...
...
src/pages/api/chat/gpt3.ts
View file @
5249297c
...
...
@@ -149,13 +149,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
stream
.
destroy
();
// 只有使用平台的 key 才计费
!
userApiKey
&&
pushChatBill
({
modelName
:
model
.
service
.
modelName
,
userId
,
chatId
,
text
:
promptText
+
responseContent
});
pushChatBill
({
isPay
:
!
userApiKey
,
modelName
:
model
.
service
.
modelName
,
userId
,
chatId
,
text
:
promptText
+
responseContent
});
}
catch
(
err
:
any
)
{
// console.log(err?.response);
if
(
step
===
1
)
{
...
...
src/service/events/generateAbstract.ts
View file @
5249297c
...
...
@@ -12,7 +12,7 @@ export async function generateAbstract(next = false): Promise<any> {
const
systemPrompt
:
ChatCompletionRequestMessage
=
{
role
:
'system'
,
content
:
`总结助手,我会向你发送一段长文本,请从文本中归纳总结5至15条信息,
请直接输出总结内容,并按以下格式输出: 'A1:'\n'A2:'\n'A3:'
\n`
content
:
`总结助手,我会向你发送一段长文本,请从文本中归纳总结5至15条信息,
如果是英文,请增加一条中文的总结,并按以下格式输出: A1:\nA2:\nA3:
\n`
};
let
dataItem
:
DataItemSchema
|
null
=
null
;
...
...
@@ -80,36 +80,36 @@ export async function generateAbstract(next = false): Promise<any> {
const
rawContent
:
string
=
abstractResponse
?.
data
.
choices
[
0
].
message
?.
content
||
''
;
// 从 content 中提取摘要内容
const
splitContents
=
splitText
(
rawContent
);
console
.
log
(
rawContent
);
//
console.log(rawContent);
// 生成词向量
const
vectorResponse
=
await
Promise
.
allSettled
(
splitContents
.
map
((
item
)
=>
chatAPI
.
createEmbedding
(
{
model
:
'text-embedding-ada-002'
,
input
:
item
.
abstract
},
{
timeout
:
120000
,
httpsAgent
}
)
)
);
//
const vectorResponse = await Promise.allSettled(
//
splitContents.map((item) =>
//
chatAPI.createEmbedding(
//
{
//
model: 'text-embedding-ada-002',
//
input: item.abstract
//
},
//
{
//
timeout: 120000,
//
httpsAgent
//
}
//
)
//
)
//
);
// 筛选成功的向量请求
const
vectorSuccessResponse
=
vectorResponse
.
map
((
item
:
any
,
i
)
=>
{
if
(
item
.
status
!==
'fulfilled'
)
{
// 没有词向量的【摘要】不要
console
.
log
(
'获取词向量错误: '
,
item
);
return
''
;
}
return
{
abstract
:
splitContents
[
i
].
abstract
,
abstractVector
:
item
?.
value
?.
data
?.
data
?.[
0
]?.
embedding
};
})
.
filter
((
item
)
=>
item
);
//
const vectorSuccessResponse = vectorResponse
//
.map((item: any, i) => {
//
if (item.status !== 'fulfilled') {
//
// 没有词向量的【摘要】不要
//
console.log('获取词向量错误: ', item);
//
return '';
//
}
//
return {
//
abstract: splitContents[i].abstract,
//
abstractVector: item?.value?.data?.data?.[0]?.embedding
//
};
//
})
//
.filter((item) => item);
// 插入数据库,并修改状态
await
DataItem
.
findByIdAndUpdate
(
dataItem
.
_id
,
{
...
...
@@ -117,28 +117,22 @@ export async function generateAbstract(next = false): Promise<any> {
$push
:
{
rawResponse
:
rawContent
,
result
:
{
$each
:
vectorSuccessResponse
$each
:
splitContents
}
}
});
// 计费
!
userApiKey
&&
vectorSuccessResponse
.
length
>
0
&&
pushSplitDataBill
({
userId
:
dataItem
.
userId
,
type
:
'abstract'
,
text
:
systemPrompt
.
content
+
dataItem
.
text
+
rawContent
+
rawContent
.
substring
(
0
,
Math
.
floor
(
dataItem
.
text
.
length
/
10
))
// 向量价格是 gpt35 的1/10
});
console
.
log
(
`生成摘要成功,time:
${(
Date
.
now
()
-
startTime
)
/
1000
}
s`
,
`摘要匹配数量:
${
splitContents
.
length
}
`
,
`有向量摘要数量:
${
vectorSuccessResponse
.
length
}
`
`摘要匹配数量:
${
splitContents
.
length
}
`
);
// 计费
pushSplitDataBill
({
isPay
:
!
userApiKey
&&
splitContents
.
length
>
0
,
userId
:
dataItem
.
userId
,
type
:
'abstract'
,
text
:
systemPrompt
.
content
+
dataItem
.
text
+
rawContent
});
}
catch
(
error
:
any
)
{
console
.
log
(
'error: 生成摘要错误'
,
dataItem
?.
_id
);
console
.
log
(
'response:'
,
error
);
...
...
src/service/events/generateQA.ts
View file @
5249297c
...
...
@@ -12,7 +12,7 @@ export async function generateQA(next = false): Promise<any> {
const
systemPrompt
:
ChatCompletionRequestMessage
=
{
role
:
'system'
,
content
:
`总结助手。我会向你发送一段长文本,请从中总结出5至15个问题和答案,答案请尽量详细,请按以下格式返回:
"Q1:"\n"A1:"\n"Q2:"\n"A2:"
\n`
content
:
`总结助手。我会向你发送一段长文本,请从中总结出5至15个问题和答案,答案请尽量详细,请按以下格式返回:
Q1:\nA1:\nQ2:\nA2:
\n`
};
let
dataItem
:
DataItemSchema
|
null
=
null
;
...
...
@@ -58,61 +58,68 @@ export async function generateQA(next = false): Promise<any> {
const
chatAPI
=
getOpenAIApi
(
userApiKey
||
systemKey
);
// 请求 chatgpt 获取回答
const
response
=
await
Promise
.
allSettled
(
[
0
,
0.5
,
0.8
].
map
((
temperature
)
=>
chatAPI
.
createChatCompletion
(
{
model
:
ChatModelNameEnum
.
GPT35
,
temperature
:
temperature
,
n
:
1
,
messages
:
[
systemPrompt
,
[
0.2
,
0.8
].
map
(
(
temperature
)
=>
chatAPI
.
createChatCompletion
(
{
role
:
'user'
,
content
:
dataItem
?.
text
||
''
model
:
ChatModelNameEnum
.
GPT35
,
temperature
:
temperature
,
n
:
1
,
messages
:
[
systemPrompt
,
{
role
:
'user'
,
content
:
dataItem
?.
text
||
''
}
]
},
{
timeout
:
120000
,
httpsAgent
}
]
},
{
timeout
:
120000
,
httpsAgent
}
)
)
.
then
((
res
)
=>
({
rawContent
:
res
?.
data
.
choices
[
0
].
message
?.
content
||
''
,
result
:
splitText
(
res
?.
data
.
choices
[
0
].
message
?.
content
||
''
)
}))
// 从 content 中提取 QA
)
);
// 过滤出成功的响应
const
successResponse
=
response
.
filter
((
item
)
=>
item
.
status
===
'fulfilled'
);
// 提取响应内容
const
rawContents
:
string
[]
=
successResponse
.
map
(
(
item
:
any
)
=>
item
?.
value
?.
data
.
choices
[
0
].
message
?.
content
||
''
);
// 从 content 中提取 QA
const
splitResponses
=
rawContents
.
map
((
content
)
=>
splitText
(
content
)).
flat
();
const
successResponse
:
{
rawContent
:
string
;
result
:
{
q
:
string
;
a
:
string
}[];
}[]
=
response
.
filter
((
item
)
=>
item
.
status
===
'fulfilled'
).
map
((
item
:
any
)
=>
item
.
value
);
const
rawContents
=
successResponse
.
map
((
item
)
=>
item
.
rawContent
);
const
results
=
successResponse
.
map
((
item
)
=>
item
.
result
).
flat
();
// 插入数据库,并修改状态
await
DataItem
.
findByIdAndUpdate
(
dataItem
.
_id
,
{
status
:
0
,
$push
:
{
rawResponse
:
{
$each
:
rawContents
$each
:
successResponse
.
map
((
item
)
=>
item
.
rawContent
)
},
result
:
{
$each
:
splitResponse
s
$each
:
result
s
}
}
});
// 计费
!
userApiKey
&&
splitResponses
.
length
>
0
&&
pushSplitDataBill
({
userId
:
dataItem
.
userId
,
type
:
'QA'
,
text
:
systemPrompt
.
content
+
dataItem
.
text
+
rawContents
.
join
(
''
)
});
console
.
log
(
'生成QA成功,time:'
,
`
${(
Date
.
now
()
-
startTime
)
/
1000
}
s`
,
'QA数量:'
,
splitResponse
s
.
length
result
s
.
length
);
// 计费
pushSplitDataBill
({
isPay
:
!
userApiKey
&&
results
.
length
>
0
,
userId
:
dataItem
.
userId
,
type
:
'QA'
,
text
:
systemPrompt
.
content
+
dataItem
.
text
+
rawContents
.
join
(
''
)
});
}
catch
(
error
:
any
)
{
console
.
log
(
'error: 生成QA错误'
,
dataItem
?.
_id
);
console
.
log
(
'response:'
,
error
?.
response
);
...
...
src/service/events/pushBill.ts
View file @
5249297c
...
...
@@ -5,55 +5,58 @@ import { formatPrice } from '@/utils/user';
import
type
{
DataType
}
from
'@/types/data'
;
export
const
pushChatBill
=
async
({
isPay
,
modelName
,
userId
,
chatId
,
text
}:
{
isPay
:
boolean
;
modelName
:
string
;
userId
:
string
;
chatId
:
string
;
text
:
string
;
})
=>
{
await
connectToDatabase
();
let
billId
;
try
{
// 获取模型单价格
const
modelItem
=
modelList
.
find
((
item
)
=>
item
.
model
===
modelName
);
const
unitPrice
=
modelItem
?.
price
||
5
;
// 计算 token 数量
const
tokens
=
encode
(
text
);
// 计算价格
const
price
=
unitPrice
*
tokens
.
length
;
console
.
log
(
'chat bill'
);
console
.
log
(
'token len:'
,
tokens
.
length
);
console
.
log
(
'text len: '
,
text
.
length
);
console
.
log
(
'price: '
,
`
${
formatPrice
(
price
)}
元`
);
console
.
log
(
'token len:'
,
tokens
.
length
);
if
(
isPay
)
{
await
connectToDatabase
();
try
{
// 插入 Bill 记录
const
res
=
await
Bill
.
create
({
userId
,
type
:
'chat'
,
modelName
,
chatId
,
textLen
:
text
.
length
,
tokenLen
:
tokens
.
length
,
price
});
billId
=
res
.
_id
;
// 获取模型单价格
const
modelItem
=
modelList
.
find
((
item
)
=>
item
.
model
===
modelName
);
// 计算价格
const
unitPrice
=
modelItem
?.
price
||
5
;
const
price
=
unitPrice
*
tokens
.
length
;
console
.
log
(
`chat bill, price:
${
formatPrice
(
price
)}
元`
);
// 账号扣费
await
User
.
findByIdAndUpdate
(
userId
,
{
$inc
:
{
balance
:
-
price
}
});
}
catch
(
error
)
{
console
.
log
(
'创建账单失败:'
,
error
);
billId
&&
Bill
.
findByIdAndDelete
(
billId
);
try
{
// 插入 Bill 记录
const
res
=
await
Bill
.
create
({
userId
,
type
:
'chat'
,
modelName
,
chatId
,
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
);
}
}
}
catch
(
error
)
{
console
.
log
(
error
);
...
...
@@ -61,10 +64,12 @@ export const pushChatBill = async ({
};
export
const
pushSplitDataBill
=
async
({
isPay
,
userId
,
text
,
type
}:
{
isPay
:
boolean
;
userId
:
string
;
text
:
string
;
type
:
DataType
;
...
...
@@ -74,39 +79,41 @@ export const pushSplitDataBill = async ({
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
)}
元`
);
console
.
log
(
'token len:'
,
tokens
.
length
);
if
(
isPay
)
{
try
{
// 获取模型单价格, 都是用 gpt35 拆分
const
modelItem
=
modelList
.
find
((
item
)
=>
item
.
model
===
ChatModelNameEnum
.
GPT35
);
const
unitPrice
=
modelItem
?.
price
||
5
;
// 计算价格
const
price
=
unitPrice
*
tokens
.
length
;
console
.
log
(
`splitData bill, price:
${
formatPrice
(
price
)}
元`
);
try
{
// 插入 Bill 记录
const
res
=
await
Bill
.
create
({
userId
,
type
,
modelName
:
ChatModelNameEnum
.
GPT35
,
textLen
:
text
.
length
,
tokenLen
:
tokens
.
length
,
price
});
billId
=
res
.
_id
;
// 插入 Bill 记录
const
res
=
await
Bill
.
create
({
userId
,
type
,
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
);
// 账号扣费
await
User
.
findByIdAndUpdate
(
userId
,
{
$inc
:
{
balance
:
-
price
}
});
}
catch
(
error
)
{
console
.
log
(
'创建账单失败:'
,
error
);
billId
&&
Bill
.
findByIdAndDelete
(
billId
);
}
}
}
catch
(
error
)
{
console
.
log
(
error
);
...
...
src/service/response.ts
View file @
5249297c
...
...
@@ -28,10 +28,10 @@ export const jsonRes = <T = any>(
}
else
if
(
openaiError
[
error
?.
response
?.
statusText
])
{
msg
=
openaiError
[
error
.
response
.
statusText
];
}
error
?.
response
&&
console
.
log
(
'chat err:'
,
error
?.
response
);
console
.
log
(
'error->'
);
console
.
log
(
'code:'
,
error
.
code
);
console
.
log
(
'statusText:'
,
error
?.
response
?.
statusText
);
console
.
log
(
'data len:'
,
error
?.
response
?.
config
?.
data
.
length
);
console
.
log
(
'msg:'
,
msg
);
}
...
...
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