Skip to content

Commit d3c5375

Browse files
feat: add tools and upload file switch
1 parent 5a58cd1 commit d3c5375

File tree

4 files changed

+148
-31
lines changed

4 files changed

+148
-31
lines changed

service/src/chatgpt/index.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,11 @@ const processThreads: { userId: string, chatUuid: number, abort: AbortController
5858

5959
async function chatReplyProcess(options: RequestOptions) {
6060
const globalConfig = await getCacheConfig()
61-
const model = options.room.chatModel
61+
const chatModelWithKeyId = options.room.chatModel
62+
// 解析模型名称,支持格式 "modelName|keyId",提取实际的模型名称用于 API 调用
63+
const model = chatModelWithKeyId.includes('|') ? chatModelWithKeyId.split('|')[0] : chatModelWithKeyId
6264
const searchEnabled = options.room.searchEnabled
63-
const key = await getRandomApiKey(options.user, model)
65+
const key = await getRandomApiKey(options.user, chatModelWithKeyId)
6466
const userId = options.user._id.toString()
6567
const maxContextCount = options.room.maxContextCount ?? 10
6668
const messageId = options.messageId
@@ -560,7 +562,22 @@ async function randomKeyConfig(keys: KeyConfig[]): Promise<KeyConfig | null> {
560562
}
561563

562564
async function getRandomApiKey(user: UserInfo, chatModel: string): Promise<KeyConfig | undefined> {
563-
const keys = (await getCacheApiKeys()).filter(d => hasAnyRole(d.userRoles, user.roles)).filter(d => d.chatModels.includes(chatModel))
565+
// 解析模型名称,支持格式 "modelName|keyId"
566+
let actualModelName = chatModel
567+
let specifiedKeyId: string | undefined
568+
if (chatModel.includes('|')) {
569+
const parts = chatModel.split('|')
570+
actualModelName = parts[0]
571+
specifiedKeyId = parts[1]
572+
}
573+
574+
let keys = (await getCacheApiKeys()).filter(d => hasAnyRole(d.userRoles, user.roles)).filter(d => d.chatModels.includes(actualModelName))
575+
576+
// 如果指定了 keyId,只返回匹配的 key
577+
if (specifiedKeyId) {
578+
keys = keys.filter(key => key._id.toString() === specifiedKeyId)
579+
return keys.length > 0 ? keys[0] : undefined
580+
}
564581

565582
return randomKeyConfig(keys)
566583
}

service/src/index.ts

Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -209,27 +209,81 @@ router.post('/session', async (req, res) => {
209209

210210
const keys = (await getCacheApiKeys()).filter(d => hasAnyRole(d.userRoles, user.roles))
211211

212-
const count: { key: string, count: number }[] = []
212+
// 为每个 key 和模型的组合生成不同的选项
213+
const modelKeyMap = new Map<string, Array<{ keyId: string, toolsEnabled: boolean, imageUploadEnabled: boolean }>>()
213214
chatModelOptions.forEach((chatModel) => {
214215
keys.forEach((key) => {
215216
if (key.chatModels.includes(chatModel.value)) {
216-
if (count.filter(d => d.key === chatModel.value).length <= 0) {
217-
count.push({ key: chatModel.value, count: 1 })
218-
}
219-
else {
220-
const thisCount = count.filter(d => d.key === chatModel.value)[0]
221-
thisCount.count++
217+
const keyId = key._id.toString()
218+
if (!modelKeyMap.has(chatModel.value)) {
219+
modelKeyMap.set(chatModel.value, [])
222220
}
221+
const configs = modelKeyMap.get(chatModel.value)!
222+
configs.push({
223+
keyId,
224+
toolsEnabled: key.toolsEnabled || false,
225+
imageUploadEnabled: key.imageUploadEnabled || false,
226+
})
223227
}
224228
})
225229
})
226-
count.forEach((c) => {
227-
const thisChatModel = chatModelOptions.filter(d => d.value === c.key)[0]
228-
const suffix = c.count > 1 ? ` (${c.count})` : ''
229-
chatModels.push({
230-
label: `${thisChatModel.label}${suffix}`,
231-
key: c.key,
232-
value: c.key,
230+
231+
// 为每个配置组合生成唯一的选项
232+
modelKeyMap.forEach((configs, modelValue) => {
233+
const thisChatModel = chatModelOptions.find(d => d.value === modelValue)
234+
if (!thisChatModel)
235+
return
236+
237+
// 按照功能分组(toolsEnabled 和 imageUploadEnabled)
238+
const configGroups = new Map<string, typeof configs>()
239+
configs.forEach((config) => {
240+
const groupKey = `${config.toolsEnabled}-${config.imageUploadEnabled}`
241+
if (!configGroups.has(groupKey)) {
242+
configGroups.set(groupKey, [])
243+
}
244+
configGroups.get(groupKey)!.push(config)
245+
})
246+
247+
// 为每个功能组生成选项
248+
configGroups.forEach((groupConfigs) => {
249+
const config = groupConfigs[0] // 取第一个作为代表
250+
const suffix = []
251+
if (config.toolsEnabled)
252+
suffix.push('Tools')
253+
if (config.imageUploadEnabled)
254+
suffix.push('Image')
255+
256+
// 构建标签后缀
257+
let labelSuffix = ''
258+
if (suffix.length > 0) {
259+
// 有特殊功能
260+
labelSuffix = groupConfigs.length > 1
261+
? ` (${suffix.join(', ')}, ${groupConfigs.length})`
262+
: ` (${suffix.join(', ')})`
263+
}
264+
else {
265+
// 没有特殊功能
266+
labelSuffix = groupConfigs.length > 1
267+
? ` (${groupConfigs.length})`
268+
: ''
269+
}
270+
271+
// 构建选项
272+
if (suffix.length === 0 && groupConfigs.length > 0) {
273+
chatModels.push({
274+
label: `${thisChatModel.label}${labelSuffix}`,
275+
key: modelValue,
276+
value: modelValue,
277+
})
278+
}
279+
else {
280+
// 需要key来判断用走特殊逻辑
281+
chatModels.push({
282+
label: `${thisChatModel.label}${labelSuffix}`,
283+
key: `${modelValue}|${config.keyId}`,
284+
value: `${modelValue}|${config.keyId}`,
285+
})
286+
}
233287
})
234288
})
235289

service/src/routes/room.ts

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,42 @@ router.post('/room-create', auth, async (req, res) => {
9595
const room = await createChatRoom(userId, title, roomId, user.config?.chatModel, user.config?.maxContextCount)
9696
// 根据chatModel判断并设置imageUploadEnabled
9797
if (user && room.chatModel) {
98+
// 解析模型名称,支持格式 "modelName|keyId"
99+
let actualModelName = room.chatModel
100+
let specifiedKeyId: string | undefined
101+
if (room.chatModel.includes('|')) {
102+
const parts = room.chatModel.split('|')
103+
actualModelName = parts[0]
104+
specifiedKeyId = parts[1]
105+
}
106+
98107
const keys = (await getCacheApiKeys()).filter(d => hasAnyRole(d.userRoles, user.roles))
99-
const imageUploadEnabled = keys.some(key =>
100-
key.chatModels.includes(room.chatModel)
101-
&& key.imageUploadEnabled === true,
102-
)
108+
let imageUploadEnabled = false
109+
let toolsEnabled = false
110+
if (specifiedKeyId) {
111+
// 如果指定了 keyId,使用该 key 的配置
112+
const specifiedKey = keys.find(key => key._id.toString() === specifiedKeyId && key.chatModels.includes(actualModelName))
113+
if (specifiedKey) {
114+
imageUploadEnabled = specifiedKey.imageUploadEnabled || false
115+
toolsEnabled = specifiedKey.toolsEnabled || false
116+
}
117+
}
118+
else {
119+
// 如果没有指定 keyId,使用原有逻辑
120+
imageUploadEnabled = false
121+
toolsEnabled = false
122+
}
123+
103124
await updateRoomImageUploadEnabled(userId, roomId, imageUploadEnabled || false)
125+
await updateRoomToolsEnabled(userId, roomId, toolsEnabled || false)
126+
if (toolsEnabled) {
127+
await updateRoomThinkEnabled(userId, roomId, false)
128+
await updateRoomSearchEnabled(userId, roomId, false)
129+
room.thinkEnabled = false
130+
room.searchEnabled = false
131+
}
104132
room.imageUploadEnabled = imageUploadEnabled || false
133+
room.toolsEnabled = toolsEnabled || false
105134
}
106135
res.send({ status: 'Success', message: null, data: room })
107136
}
@@ -153,17 +182,32 @@ router.post('/room-chatmodel', auth, async (req, res) => {
153182
// 根据新选择的chatModel,动态判断toolsEnabled
154183
const user = await getUserById(userId)
155184
if (user) {
185+
// 解析模型名称,支持格式 "modelName|keyId"
186+
let actualModelName = chatModel
187+
let specifiedKeyId: string | undefined
188+
if (chatModel.includes('|')) {
189+
const parts = chatModel.split('|')
190+
actualModelName = parts[0]
191+
specifiedKeyId = parts[1]
192+
}
193+
156194
const keys = (await getCacheApiKeys()).filter(d => hasAnyRole(d.userRoles, user.roles))
157-
const responsesApiKeysForModel = keys.filter(key =>
158-
key.keyModel === 'ResponsesAPI'
159-
&& key.chatModels.includes(chatModel),
160-
)
161-
const toolsEnabled = responsesApiKeysForModel.length > 0
162-
&& responsesApiKeysForModel.every(key => key.toolsEnabled === true)
163-
const imageUploadEnabled = keys.some(key =>
164-
key.chatModels.includes(chatModel)
165-
&& key.imageUploadEnabled === true,
166-
)
195+
196+
let toolsEnabled = false
197+
let imageUploadEnabled = false
198+
199+
if (specifiedKeyId) {
200+
// 如果指定了 keyId,使用该 key 的配置
201+
const specifiedKey = keys.find(key => key._id.toString() === specifiedKeyId && key.chatModels.includes(actualModelName))
202+
if (specifiedKey) {
203+
toolsEnabled = specifiedKey.toolsEnabled || false
204+
imageUploadEnabled = specifiedKey.imageUploadEnabled || false
205+
}
206+
}
207+
else {
208+
toolsEnabled = false
209+
imageUploadEnabled = false
210+
}
167211

168212
// 更新房间的toolsEnabled状态
169213
await updateRoomToolsEnabled(userId, roomId, toolsEnabled || false)

src/store/modules/chat/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ export const useChatStore = defineStore('chat-store', () => {
6060
maxContextCount: result.data?.maxContextCount ?? 10,
6161
searchEnabled: result.data?.searchEnabled,
6262
thinkEnabled: result.data?.thinkEnabled,
63+
toolsEnabled: result.data?.toolsEnabled,
64+
imageUploadEnabled: result.data?.imageUploadEnabled,
6365
})
6466

6567
state.chat.unshift({ roomId, data: [] })

0 commit comments

Comments
 (0)