@@ -31,6 +31,7 @@ const ErrorCodeMessage: Record<string, string> = {
3131}
3232
3333let auditService : TextAuditService
34+ const _lockedKeys : { key : string ; lockedTime : number } [ ] = [ ]
3435
3536export async function initApi ( key : KeyConfig , chatModel : CHATMODEL ) {
3637 // More Info: https://github.com/transitive-bullshit/chatgpt-api
@@ -84,8 +85,8 @@ export async function initApi(key: KeyConfig, chatModel: CHATMODEL) {
8485const processThreads : { userId : string ; abort : AbortController ; messageId : string } [ ] = [ ]
8586async function chatReplyProcess ( options : RequestOptions ) {
8687 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 ( )
8990 const messageId = options . messageId
9091 if ( key == null || key === undefined )
9192 throw new Error ( '没有可用的配置。请再试一次 | No available configuration. Please try again.' )
@@ -124,13 +125,20 @@ async function chatReplyProcess(options: RequestOptions) {
124125 }
125126 catch ( error : any ) {
126127 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 )
128137 if ( Reflect . has ( ErrorCodeMessage , code ) )
129138 return sendResponse ( { type : 'Fail' , message : ErrorCodeMessage [ code ] } )
130139 return sendResponse ( { type : 'Fail' , message : error . message ?? 'Please check the back-end console' } )
131140 }
132141 finally {
133- releaseApiKey ( key )
134142 const index = processThreads . findIndex ( d => d . userId === userId )
135143 if ( index > - 1 )
136144 processThreads . splice ( index , 1 )
@@ -326,29 +334,23 @@ async function getMessageById(id: string): Promise<ChatMessage | undefined> {
326334 else { return undefined }
327335}
328336
329- const _lockedKeys : { key : string ; count : number } [ ] = [ ]
330- const _oneTimeCount = 3 // api
331337async function randomKeyConfig ( keys : KeyConfig [ ] ) : Promise < KeyConfig | null > {
332338 if ( keys . length <= 0 )
333339 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 )
336344 const start = Date . now ( )
337345 while ( unsedKeys . length <= 0 ) {
338346 if ( Date . now ( ) - start > 3000 )
339347 break
340348 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 )
343350 }
344351 if ( unsedKeys . length <= 0 )
345352 return null
346353 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 ++
352354 return thisKey
353355}
354356
@@ -357,23 +359,6 @@ async function getRandomApiKey(user: UserInfo, chatModel: CHATMODEL): Promise<Ke
357359 return randomKeyConfig ( keys . filter ( d => d . chatModels . includes ( chatModel ) ) )
358360}
359361
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-
377362export type { ChatContext , ChatMessage }
378363
379- export { chatReplyProcess , chatConfig , containsSensitiveWords , getRandomApiKey }
364+ export { chatReplyProcess , chatConfig , containsSensitiveWords }
0 commit comments