@@ -31,6 +31,7 @@ const ErrorCodeMessage: Record<string, string> = {
31
31
}
32
32
33
33
let auditService : TextAuditService
34
+ const _lockedKeys : { key : string ; lockedTime : number } [ ] = [ ]
34
35
35
36
export async function initApi ( key : KeyConfig , chatModel : CHATMODEL ) {
36
37
// More Info: https://github.com/transitive-bullshit/chatgpt-api
@@ -84,8 +85,8 @@ export async function initApi(key: KeyConfig, chatModel: CHATMODEL) {
84
85
const processThreads : { userId : string ; abort : AbortController ; messageId : string } [ ] = [ ]
85
86
async function chatReplyProcess ( options : RequestOptions ) {
86
87
const model = options . chatModel
87
- const key = options . key
88
- const userId = options . userId
88
+ const key = await getRandomApiKey ( options . user , options . user . config . chatModel )
89
+ const userId = options . user . _id . toString ( )
89
90
const messageId = options . messageId
90
91
if ( key == null || key === undefined )
91
92
throw new Error ( '没有可用的配置。请再试一次 | No available configuration. Please try again.' )
@@ -124,13 +125,20 @@ async function chatReplyProcess(options: RequestOptions) {
124
125
}
125
126
catch ( error : any ) {
126
127
const code = error . statusCode
127
- global . console . log ( error )
128
+ if ( code === 429 && ( error . message . includes ( 'Too Many Requests' ) || error . message . includes ( 'Rate limit' ) ) ) {
129
+ // access token Only one message at a time
130
+ if ( options . tryCount ++ < 3 ) {
131
+ _lockedKeys . push ( { key : key . key , lockedTime : Date . now ( ) } )
132
+ await new Promise ( resolve => setTimeout ( resolve , 2000 ) )
133
+ return await chatReplyProcess ( options )
134
+ }
135
+ }
136
+ global . console . error ( error )
128
137
if ( Reflect . has ( ErrorCodeMessage , code ) )
129
138
return sendResponse ( { type : 'Fail' , message : ErrorCodeMessage [ code ] } )
130
139
return sendResponse ( { type : 'Fail' , message : error . message ?? 'Please check the back-end console' } )
131
140
}
132
141
finally {
133
- releaseApiKey ( key )
134
142
const index = processThreads . findIndex ( d => d . userId === userId )
135
143
if ( index > - 1 )
136
144
processThreads . splice ( index , 1 )
@@ -326,29 +334,23 @@ async function getMessageById(id: string): Promise<ChatMessage | undefined> {
326
334
else { return undefined }
327
335
}
328
336
329
- const _lockedKeys : { key : string ; count : number } [ ] = [ ]
330
- const _oneTimeCount = 3 // api
331
337
async function randomKeyConfig ( keys : KeyConfig [ ] ) : Promise < KeyConfig | null > {
332
338
if ( keys . length <= 0 )
333
339
return null
334
- let unsedKeys = keys . filter ( d => _lockedKeys . filter ( l => d . key === l . key ) . length <= 0
335
- || _lockedKeys . filter ( l => d . key === l . key ) [ 0 ] . count < _oneTimeCount )
340
+ // cleanup old locked keys
341
+ _lockedKeys . filter ( d => d . lockedTime <= Date . now ( ) - 1000 * 20 ) . forEach ( d => _lockedKeys . splice ( _lockedKeys . indexOf ( d ) , 1 ) )
342
+
343
+ let unsedKeys = keys . filter ( d => _lockedKeys . filter ( l => d . key === l . key ) . length <= 0 )
336
344
const start = Date . now ( )
337
345
while ( unsedKeys . length <= 0 ) {
338
346
if ( Date . now ( ) - start > 3000 )
339
347
break
340
348
await new Promise ( resolve => setTimeout ( resolve , 1000 ) )
341
- unsedKeys = keys . filter ( d => _lockedKeys . filter ( l => d . key === l . key ) . length <= 0
342
- || _lockedKeys . filter ( l => d . key === l . key ) [ 0 ] . count < _oneTimeCount )
349
+ unsedKeys = keys . filter ( d => _lockedKeys . filter ( l => d . key === l . key ) . length <= 0 )
343
350
}
344
351
if ( unsedKeys . length <= 0 )
345
352
return null
346
353
const thisKey = unsedKeys [ Math . floor ( Math . random ( ) * unsedKeys . length ) ]
347
- const thisLockedKey = _lockedKeys . filter ( d => d . key === thisKey . key )
348
- if ( thisLockedKey . length <= 0 )
349
- _lockedKeys . push ( { key : thisKey . key , count : 1 } )
350
- else
351
- thisLockedKey [ 0 ] . count ++
352
354
return thisKey
353
355
}
354
356
@@ -357,23 +359,6 @@ async function getRandomApiKey(user: UserInfo, chatModel: CHATMODEL): Promise<Ke
357
359
return randomKeyConfig ( keys . filter ( d => d . chatModels . includes ( chatModel ) ) )
358
360
}
359
361
360
- async function releaseApiKey ( key : KeyConfig ) {
361
- if ( key == null || key === undefined )
362
- return
363
-
364
- const lockedKeys = _lockedKeys . filter ( d => d . key === key . key )
365
- if ( lockedKeys . length > 0 ) {
366
- if ( lockedKeys [ 0 ] . count <= 1 ) {
367
- const index = _lockedKeys . findIndex ( item => item . key === key . key )
368
- if ( index !== - 1 )
369
- _lockedKeys . splice ( index , 1 )
370
- }
371
- else {
372
- lockedKeys [ 0 ] . count --
373
- }
374
- }
375
- }
376
-
377
362
export type { ChatContext , ChatMessage }
378
363
379
- export { chatReplyProcess , chatConfig , containsSensitiveWords , getRandomApiKey }
364
+ export { chatReplyProcess , chatConfig , containsSensitiveWords }
0 commit comments