Skip to content

Commit 43bd5cc

Browse files
author
Kerwin
committed
fix: access token 模式多 key (Close #203)
1 parent 3c682c6 commit 43bd5cc

File tree

5 files changed

+50
-13
lines changed

5 files changed

+50
-13
lines changed

service/src/chatgpt/index.ts

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { getCacheApiKeys, getCacheConfig, getOriginConfig } from '../storage/con
1414
import { sendResponse } from '../utils'
1515
import { hasAnyRole, isNotEmptyString } from '../utils/is'
1616
import type { ChatContext, ChatGPTUnofficialProxyAPIOptions, JWT, ModelConfig } from '../types'
17-
import { getChatByMessageId } from '../storage/mongo'
17+
import { getChatByMessageId, updateRoomAccountId } from '../storage/mongo'
1818
import type { RequestOptions } from './types'
1919

2020
const { HttpsProxyAgent } = httpsProxyAgent
@@ -84,13 +84,22 @@ export async function initApi(key: KeyConfig, chatModel: CHATMODEL) {
8484
}
8585
const processThreads: { userId: string; abort: AbortController; messageId: string }[] = []
8686
async function chatReplyProcess(options: RequestOptions) {
87-
const model = options.chatModel
88-
const key = await getRandomApiKey(options.user, options.user.config.chatModel)
87+
const model = options.user.config.chatModel
88+
const key = await getRandomApiKey(options.user, options.user.config.chatModel, options.room.accountId)
8989
const userId = options.user._id.toString()
9090
const messageId = options.messageId
9191
if (key == null || key === undefined)
9292
throw new Error('没有可用的配置。请再试一次 | No available configuration. Please try again.')
9393

94+
if (key.keyModel === 'ChatGPTUnofficialProxyAPI') {
95+
if (!options.room.accountId)
96+
updateRoomAccountId(userId, options.room.roomId, getAccountId(key.key))
97+
98+
if (options.lastContext && ((options.lastContext.conversationId && !options.lastContext.parentMessageId)
99+
|| (!options.lastContext.conversationId && options.lastContext.parentMessageId)))
100+
throw new Error('无法在一个房间同时使用 AccessToken 以及 Api,请联系管理员,或新开聊天室进行对话 | Unable to use AccessToken and Api at the same time in the same room, please contact the administrator or open a new chat room for conversation')
101+
}
102+
94103
const { message, lastContext, process, systemMessage, temperature, top_p } = options
95104

96105
try {
@@ -270,10 +279,10 @@ function formatDate(date) {
270279

271280
async function chatConfig() {
272281
const config = await getOriginConfig() as ModelConfig
273-
if (config.apiModel === 'ChatGPTAPI')
274-
config.balance = await fetchBalance()
275-
else
276-
config.accessTokenExpiredTime = await fetchAccessTokenExpiredTime()
282+
// if (config.apiModel === 'ChatGPTAPI')
283+
// config.balance = await fetchBalance()
284+
// else
285+
// config.accessTokenExpiredTime = await fetchAccessTokenExpiredTime()
277286
return sendResponse<ModelConfig>({
278287
type: 'Success',
279288
data: config,
@@ -354,9 +363,23 @@ async function randomKeyConfig(keys: KeyConfig[]): Promise<KeyConfig | null> {
354363
return thisKey
355364
}
356365

357-
async function getRandomApiKey(user: UserInfo, chatModel: CHATMODEL): Promise<KeyConfig | undefined> {
358-
const keys = (await getCacheApiKeys()).filter(d => hasAnyRole(d.userRoles, user.roles))
359-
return randomKeyConfig(keys.filter(d => d.chatModels.includes(chatModel)))
366+
async function getRandomApiKey(user: UserInfo, chatModel: CHATMODEL, accountId?: string): Promise<KeyConfig | undefined> {
367+
let keys = (await getCacheApiKeys()).filter(d => hasAnyRole(d.userRoles, user.roles))
368+
.filter(d => d.chatModels.includes(chatModel))
369+
if (accountId)
370+
keys = keys.filter(d => d.keyModel === 'ChatGPTUnofficialProxyAPI' && getAccountId(d.key) === accountId)
371+
372+
return randomKeyConfig(keys)
373+
}
374+
375+
function getAccountId(accessToken: string): string {
376+
try {
377+
const jwt = jwt_decode(accessToken) as JWT
378+
return jwt['https://api.openai.com/auth'].user_id
379+
}
380+
catch (error) {
381+
return ''
382+
}
360383
}
361384

362385
export type { ChatContext, ChatMessage }

service/src/chatgpt/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ChatMessage } from 'chatgpt'
2-
import type { CHATMODEL, UserInfo } from 'src/storage/model'
2+
import type { ChatRoom, UserInfo } from 'src/storage/model'
33

44
export interface RequestOptions {
55
message: string
@@ -8,10 +8,10 @@ export interface RequestOptions {
88
systemMessage?: string
99
temperature?: number
1010
top_p?: number
11-
chatModel: CHATMODEL
1211
user: UserInfo
1312
messageId: string
1413
tryCount: number
14+
room: ChatRoom
1515
}
1616

1717
export interface BalanceResponse {

service/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,10 +429,10 @@ router.post('/chat-process', [auth, limiter], async (req, res) => {
429429
systemMessage,
430430
temperature,
431431
top_p,
432-
chatModel: user.config.chatModel,
433432
user,
434433
messageId: message._id.toString(),
435434
tryCount: 0,
435+
room,
436436
})
437437
// return the whole response including usage
438438
res.write(`\n${JSON.stringify(result.data)}`)

service/src/storage/model.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,15 @@ export class ChatRoom {
9696
prompt: string
9797
usingContext: boolean
9898
status: Status = Status.Normal
99+
// only access token used
100+
accountId?: string
99101
constructor(userId: string, title: string, roomId: number) {
100102
this.userId = userId
101103
this.title = title
102104
this.prompt = undefined
103105
this.roomId = roomId
104106
this.usingContext = true
107+
this.accountId = null
105108
}
106109
}
107110

service/src/storage/mongo.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,17 @@ export async function updateRoomUsingContext(userId: string, roomId: number, usi
108108
return result.modifiedCount > 0
109109
}
110110

111+
export async function updateRoomAccountId(userId: string, roomId: number, accountId: string) {
112+
const query = { userId, roomId }
113+
const update = {
114+
$set: {
115+
accountId,
116+
},
117+
}
118+
const result = await roomCol.updateOne(query, update)
119+
return result.modifiedCount > 0
120+
}
121+
111122
export async function getChatRooms(userId: string) {
112123
const cursor = await roomCol.find({ userId, status: { $ne: Status.Deleted } })
113124
const rooms = []

0 commit comments

Comments
 (0)