Skip to content

Commit 8f5776f

Browse files
authored
feat: add configurable max context count per room (#622)
Signed-off-by: Bob Du <[email protected]>
1 parent 6e01f34 commit 8f5776f

File tree

19 files changed

+186
-51
lines changed

19 files changed

+186
-51
lines changed

service/src/chatgpt/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ async function chatReplyProcess(options: RequestOptions) {
6565
const searchEnabled = options.room.searchEnabled
6666
const key = await getRandomApiKey(options.user, model)
6767
const userId = options.user._id.toString()
68-
const maxContextCount = options.user.advanced.maxContextCount ?? 20
68+
const maxContextCount = options.room.maxContextCount ?? 10
6969
const messageId = options.messageId
7070
if (key == null || key === undefined)
7171
throw new Error('没有对应的apikeys配置。请再试一次 | No available apikeys configuration. Please try again.')

service/src/index.ts

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { AnnounceConfig, AuditConfig, Config, GiftCard, KeyConfig, MailConfig, SiteConfig, UserConfig, UserInfo } from './storage/model'
1+
import type { AnnounceConfig, AuditConfig, Config, GiftCard, KeyConfig, MailConfig, SiteConfig, UserInfo } from './storage/model'
22
import type { AuthJwtPayload } from './types'
33
import * as path from 'node:path'
44
import * as process from 'node:process'
@@ -16,7 +16,7 @@ import { router as promptRouter } from './routes/prompt'
1616
import { router as roomRouter } from './routes/room'
1717
import { router as uploadRouter } from './routes/upload'
1818
import { clearApiKeyCache, clearConfigCache, getApiKeys, getCacheApiKeys, getCacheConfig, getOriginConfig } from './storage/config'
19-
import { AdvancedConfig, Status, UserRole } from './storage/model'
19+
import { AdvancedConfig, Status, UserConfig, UserRole } from './storage/model'
2020
import {
2121
createUser,
2222
disableUser2FA,
@@ -35,6 +35,7 @@ import {
3535
updateUserAmount,
3636
updateUserChatModel,
3737
updateUserInfo,
38+
updateUserMaxContextCount,
3839
updateUserPassword,
3940
updateUserPasswordWithVerifyOld,
4041
updateUserStatus,
@@ -183,6 +184,16 @@ router.post('/session', async (req, res) => {
183184
return
184185
}
185186

187+
if (!user?.config) {
188+
user.config = new UserConfig()
189+
}
190+
if (!user.config?.chatModel) {
191+
user.config.chatModel = config?.siteConfig?.chatModels.split(',')[0]
192+
}
193+
if (user.config?.maxContextCount === undefined) {
194+
user.config.maxContextCount = 10
195+
}
196+
186197
userInfo = {
187198
name: user.name,
188199
description: user.description,
@@ -451,6 +462,22 @@ router.post('/user-chat-model', auth, async (req, res) => {
451462
}
452463
})
453464

465+
router.post('/user-max-context-count', auth, async (req, res) => {
466+
try {
467+
const { maxContextCount } = req.body as { maxContextCount: number }
468+
const userId = req.headers.userId.toString()
469+
470+
const user = await getUserById(userId)
471+
if (user == null || user.status !== Status.Normal)
472+
throw new Error('用户不存在 | User does not exist.')
473+
await updateUserMaxContextCount(userId, maxContextCount)
474+
res.send({ status: 'Success', message: '更新成功 | Update successfully' })
475+
}
476+
catch (error) {
477+
res.send({ status: 'Fail', message: error.message, data: null })
478+
}
479+
})
480+
454481
router.get('/users', rootAuth, async (req, res) => {
455482
try {
456483
const page = +req.query.page
@@ -811,7 +838,6 @@ router.post('/setting-advanced', auth, async (req, res) => {
811838
systemMessage: string
812839
temperature: number
813840
top_p: number
814-
maxContextCount: number
815841
sync: boolean
816842
}
817843
if (config.sync) {
@@ -824,7 +850,6 @@ router.post('/setting-advanced', auth, async (req, res) => {
824850
config.systemMessage,
825851
config.temperature,
826852
config.top_p,
827-
config.maxContextCount,
828853
)
829854
await updateConfig(thisConfig)
830855
clearConfigCache()
@@ -834,7 +859,6 @@ router.post('/setting-advanced', auth, async (req, res) => {
834859
config.systemMessage,
835860
config.temperature,
836861
config.top_p,
837-
config.maxContextCount,
838862
))
839863
res.send({ status: 'Success', message: '操作成功 | Successfully' })
840864
}

service/src/routes/room.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ import {
66
existsChatRoom,
77
getChatRooms,
88
getChatRoomsCount,
9+
getUserById,
910
renameChatRoom,
1011
updateRoomChatModel,
12+
updateRoomMaxContextCount,
1113
updateRoomPrompt,
1214
updateRoomSearchEnabled,
1315
updateRoomThinkEnabled,
@@ -28,6 +30,7 @@ router.get('/chatrooms', auth, async (req, res) => {
2830
isEdit: false,
2931
prompt: r.prompt,
3032
usingContext: r.usingContext === undefined ? true : r.usingContext,
33+
maxContextCount: r.maxContextCount === undefined ? 10 : r.maxContextCount,
3134
chatModel: r.chatModel,
3235
searchEnabled: !!r.searchEnabled,
3336
thinkEnabled: !!r.thinkEnabled,
@@ -81,8 +84,9 @@ router.get('/chatrooms-count', auth, async (req, res) => {
8184
router.post('/room-create', auth, async (req, res) => {
8285
try {
8386
const userId = req.headers.userId as string
84-
const { title, roomId, chatModel } = req.body as { title: string, roomId: number, chatModel: string }
85-
const room = await createChatRoom(userId, title, roomId, chatModel)
87+
const user = await getUserById(userId)
88+
const { title, roomId } = req.body as { title: string, roomId: number }
89+
const room = await createChatRoom(userId, title, roomId, user.config?.chatModel, user.config?.maxContextCount)
8690
res.send({ status: 'Success', message: null, data: room })
8791
}
8892
catch (error) {
@@ -139,6 +143,22 @@ router.post('/room-chatmodel', auth, async (req, res) => {
139143
}
140144
})
141145

146+
router.post('/room-max-context-count', auth, async (req, res) => {
147+
try {
148+
const userId = req.headers.userId as string
149+
const { maxContextCount, roomId } = req.body as { maxContextCount: number, roomId: number }
150+
const success = await updateRoomMaxContextCount(userId, roomId, maxContextCount)
151+
if (success)
152+
res.send({ status: 'Success', message: 'Saved successfully', data: null })
153+
else
154+
res.send({ status: 'Fail', message: 'Saved Failed', data: null })
155+
}
156+
catch (error) {
157+
console.error(error)
158+
res.send({ status: 'Fail', message: 'Update error', data: null })
159+
}
160+
})
161+
142162
router.post('/room-search-enabled', auth, async (req, res) => {
143163
try {
144164
const userId = req.headers.userId as string

service/src/storage/config.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ export async function getOriginConfig() {
8282
'You are a large language model. Follow the user\'s instructions carefully. Respond using markdown (latex start with $).',
8383
0.8,
8484
1,
85-
20,
8685
)
8786
}
8887

service/src/storage/model.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export class UserInfo {
7171

7272
export class UserConfig {
7373
chatModel: string
74+
maxContextCount: number
7475
}
7576

7677
export class ChatRoom {
@@ -80,16 +81,18 @@ export class ChatRoom {
8081
title: string
8182
prompt: string
8283
usingContext: boolean
84+
maxContextCount: number
8385
status: Status = Status.Normal
8486
chatModel: string
8587
searchEnabled: boolean
8688
thinkEnabled: boolean
87-
constructor(userId: string, title: string, roomId: number, chatModel: string, searchEnabled: boolean, thinkEnabled: boolean) {
89+
constructor(userId: string, title: string, roomId: number, chatModel: string, usingContext: boolean, maxContextCount: number, searchEnabled: boolean, thinkEnabled: boolean) {
8890
this.userId = userId
8991
this.title = title
9092
this.prompt = undefined
9193
this.roomId = roomId
92-
this.usingContext = true
94+
this.usingContext = usingContext
95+
this.maxContextCount = maxContextCount
9396
this.chatModel = chatModel
9497
this.searchEnabled = searchEnabled
9598
this.thinkEnabled = thinkEnabled
@@ -263,7 +266,6 @@ export class AdvancedConfig {
263266
public systemMessage: string,
264267
public temperature: number,
265268
public top_p: number,
266-
public maxContextCount: number,
267269
) { }
268270
}
269271

service/src/storage/mongo.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,15 @@ export async function insertChatUsage(userId: ObjectId, roomId: number, chatId:
142142
return chatUsage
143143
}
144144

145-
export async function createChatRoom(userId: string, title: string, roomId: number, chatModel: string) {
146-
const room = new ChatRoom(userId, title, roomId, chatModel, true, false)
145+
export async function createChatRoom(userId: string, title: string, roomId: number, chatModel: string, maxContextCount: number) {
146+
const config = await getCacheConfig()
147+
if (!chatModel) {
148+
chatModel = config?.siteConfig?.chatModels.split(',')[0]
149+
}
150+
if (maxContextCount === undefined) {
151+
maxContextCount = 10
152+
}
153+
const room = new ChatRoom(userId, title, roomId, chatModel, true, maxContextCount, true, false)
147154
await roomCol.insertOne(room)
148155
return room
149156
}
@@ -220,6 +227,17 @@ export async function updateRoomThinkEnabled(userId: string, roomId: number, thi
220227
return result.modifiedCount > 0
221228
}
222229

230+
export async function updateRoomMaxContextCount(userId: string, roomId: number, maxContextCount: number) {
231+
const query = { userId, roomId }
232+
const update = {
233+
$set: {
234+
maxContextCount,
235+
},
236+
}
237+
const result = await roomCol.updateOne(query, update)
238+
return result.modifiedCount > 0
239+
}
240+
223241
export async function getChatRooms(userId: string) {
224242
const cursor = roomCol.find({ userId, status: { $ne: Status.Deleted } })
225243
const rooms = []
@@ -422,6 +440,7 @@ export async function createUser(email: string, password: string, roles?: UserRo
422440
// Use the first item from the globally available chatModel configuration as the default model for new users
423441
userInfo.config = new UserConfig()
424442
userInfo.config.chatModel = config?.siteConfig?.chatModels.split(',')[0]
443+
userInfo.config.maxContextCount = 10
425444

426445
await userCol.insertOne(userInfo)
427446
return userInfo
@@ -440,6 +459,10 @@ export async function updateUserChatModel(userId: string, chatModel: string) {
440459
await userCol.updateOne({ _id: new ObjectId(userId) }, { $set: { 'config.chatModel': chatModel } })
441460
}
442461

462+
export async function updateUserMaxContextCount(userId: string, maxContextCount: number) {
463+
await userCol.updateOne({ _id: new ObjectId(userId) }, { $set: { 'config.maxContextCount': maxContextCount } })
464+
}
465+
443466
export async function updateUserAdvancedConfig(userId: string, config: AdvancedConfig) {
444467
await userCol.updateOne({ _id: new ObjectId(userId) }, { $set: { advanced: config } })
445468
}

src/api/index.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,13 @@ export function fetchUpdateUserChatModel<T = any>(chatModel: string) {
161161
})
162162
}
163163

164+
export function fetchUpdateUserMaxContextCount<T = any>(maxContextCount: number) {
165+
return post<T>({
166+
url: '/user-max-context-count',
167+
data: { maxContextCount },
168+
})
169+
}
170+
164171
export function fetchGetUsers<T = any>(page: number, size: number) {
165172
return get<T>({
166173
url: '/users',
@@ -258,6 +265,13 @@ export function fetchUpdateChatRoomChatModel<T = any>(chatModel: string, roomId:
258265
})
259266
}
260267

268+
export function fetchUpdateChatRoomMaxContextCount<T = any>(maxContextCount: number, roomId: number) {
269+
return post<T>({
270+
url: '/room-max-context-count',
271+
data: { maxContextCount, roomId },
272+
})
273+
}
274+
261275
export function fetchUpdateChatRoomUsingContext<T = any>(using: boolean, roomId: number) {
262276
return post<T>({
263277
url: '/room-context',

src/components/common/Setting/Advanced.vue

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,6 @@ function handleReset() {
4141
</div>
4242
<span>{{ userStore.userInfo.advanced.top_p }}</span>
4343
</div>
44-
<div class="flex items-center space-x-4">
45-
<span class="shrink-0 w-[120px]">{{ $t('setting.maxContextCount') }} </span>
46-
<div class="flex-1">
47-
<NSlider v-model:value="userStore.userInfo.advanced.maxContextCount" :max="100" :min="0" :step="1" />
48-
</div>
49-
<span>{{ userStore.userInfo.advanced.maxContextCount }}</span>
50-
</div>
5144
<div class="flex items-center space-x-4">
5245
<span class="shrink-0 w-[120px]">&nbsp;</span>
5346
<NButton type="primary" @click="updateSettings(false)">

src/components/common/Setting/General.vue

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script lang="ts" setup>
22
import type { Language, Theme } from '@/store/modules/app/helper'
33
import type { UserInfo } from '@/store/modules/user/helper'
4-
import { decode_redeemcard, fetchClearAllChat, fetchUpdateUserChatModel } from '@/api'
4+
import { decode_redeemcard, fetchClearAllChat, fetchUpdateUserChatModel, fetchUpdateUserMaxContextCount } from '@/api'
55
import { SvgIcon } from '@/components/common'
66
import { UserConfig } from '@/components/common/Setting/model'
77
import { useBasicLayout } from '@/hooks/useBasicLayout'
@@ -104,6 +104,19 @@ async function updateUserChatModel(chatModel: string) {
104104
await fetchUpdateUserChatModel(chatModel)
105105
}
106106
107+
async function updateUserMaxContextCount(maxContextCount: number) {
108+
if (!userStore.userInfo.config)
109+
userStore.userInfo.config = new UserConfig()
110+
userStore.userInfo.config.maxContextCount = maxContextCount
111+
userStore.recordState()
112+
}
113+
114+
async function syncUserMaxContextCount() {
115+
if (userStore.userInfo.config.maxContextCount) {
116+
await fetchUpdateUserMaxContextCount(userStore.userInfo.config.maxContextCount)
117+
}
118+
}
119+
107120
function exportData(): void {
108121
const date = getCurrentDate()
109122
const data: string = localStorage.getItem('chatStorage') || '{}'
@@ -206,6 +219,20 @@ function handleImportButtonClick(): void {
206219
/>
207220
</div>
208221
</div>
222+
<div class="flex items-center space-x-4">
223+
<span class="shrink-0 w-[100px]">{{ $t('setting.maxContextCount') }}</span>
224+
<div class="w-[300px]">
225+
<NSlider
226+
:value="userInfo.config.maxContextCount"
227+
:max="40"
228+
:min="0"
229+
:step="1"
230+
style="width: 300px"
231+
:on-dragend="syncUserMaxContextCount"
232+
@update:value="(val) => updateUserMaxContextCount(val)"
233+
/>
234+
</div>
235+
</div>
209236
<div
210237
class="flex items-center space-x-4"
211238
:class="isMobile && 'items-start'"

src/components/common/Setting/model.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export class ConfigState {
1616

1717
export class UserConfig {
1818
chatModel?: string
19+
maxContextCount?: number
1920
}
2021

2122
// https://platform.openai.com/docs/models/overview

src/locales/en-US.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ export default {
7070
thinkHelp: 'After enabling deep thinking, the model will use more computational resources and take longer time to simulate more complex thinking chains for logical reasoning.\nSuitable for complex tasks or high-requirement scenarios, such as mathematical derivations and project planning.\nDaily simple queries do not need to be enabled.',
7171
showOnContext: 'Include context',
7272
showOffContext: 'Not include context',
73+
maxContextCount: 'Maximum number of messages included in the context window',
7374
searchEnabled: 'Search enabled',
7475
searchDisabled: 'Search disabled',
7576
thinkEnabled: 'Think enabled',
@@ -214,7 +215,7 @@ export default {
214215
info2FAStep3Tip1: 'Note: How to turn off two-step verification?',
215216
info2FAStep3Tip2: '1. After logging in, use the two-step verification on the Two-Step Verification page to disable it.',
216217
info2FAStep3Tip3: '2. Contact the administrator to disable two-step verification.',
217-
maxContextCount: 'Number of context messages included in the conversation',
218+
maxContextCount: 'Maximum number of messages included in the context window for default new sessions',
218219
fastDelMsg: 'Fast Delete Message',
219220
},
220221
store: {

src/locales/ko-KR.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ export default {
7070
thinkHelp: '깊은 사고를 활성화한 후 모델은 더 많은 계산 리소스를 사용하고 더 오랜 시간을 소비하여 더 복잡한 사고 체인을 시뮬레이션하여 논리적 추론을 수행합니다.\n복잡한 작업이나 높은 요구 사항 시나리오에 적합합니다. 예: 수학 문제 유도, 프로젝트 계획.\n일상적인 간단한 조회는 활성화할 필요가 없습니다.',
7171
showOnContext: '컨텍스트 포함됨',
7272
showOffContext: '컨텍스트 미포함',
73+
maxContextCount: '컨텍스트 창에 포함된 최대 메시지 수',
7374
searchEnabled: '검색 활성화됨',
7475
searchDisabled: '검색 비활성화됨',
7576
thinkEnabled: '사고 활성화됨',
@@ -200,7 +201,7 @@ export default {
200201
info2FAStep3Tip1: 'Note: How to turn off two-step verification?',
201202
info2FAStep3Tip2: '1. After logging in, use the two-step verification on the Two-Step Verification page to disable it.',
202203
info2FAStep3Tip3: '2. Contact the administrator to disable two-step verification.',
203-
maxContextCount: '대화에 포함된 컨텍스트 메시지 수량',
204+
maxContextCount: '기본 새 세션의 컨텍스트 창에 포함된 최대 메시지 ',
204205
fastDelMsg: '빠르게 메시지 삭제',
205206
},
206207
store: {

0 commit comments

Comments
 (0)