Skip to content

Commit d5a1a09

Browse files
author
Kerwin
committed
chore: max context count (Close #394, Close #221)
1 parent 46275bf commit d5a1a09

File tree

17 files changed

+196
-111
lines changed

17 files changed

+196
-111
lines changed

service/src/chatgpt/index.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const ErrorCodeMessage: Record<string, string> = {
3434
let auditService: TextAuditService
3535
const _lockedKeys: { key: string; lockedTime: number }[] = []
3636

37-
export async function initApi(key: KeyConfig, chatModel: string) {
37+
export async function initApi(key: KeyConfig, chatModel: string, maxContextCount: number) {
3838
// More Info: https://github.com/transitive-bullshit/chatgpt-api
3939

4040
const config = await getCacheConfig()
@@ -43,23 +43,28 @@ export async function initApi(key: KeyConfig, chatModel: string) {
4343
if (key.keyModel === 'ChatGPTAPI') {
4444
const OPENAI_API_BASE_URL = config.apiBaseUrl
4545

46+
let contextCount = 0
4647
const options: ChatGPTAPIOptions = {
4748
apiKey: key.key,
4849
completionParams: { model },
4950
debug: !config.apiDisableDebug,
5051
messageStore: undefined,
51-
getMessageById,
52+
getMessageById: async (id) => {
53+
if (contextCount++ >= maxContextCount)
54+
return null
55+
return await getMessageById(id)
56+
},
5257
}
5358

5459
// Set the token limits based on the model's type. This is because different models have different token limits.
5560
// The token limit includes the token count from both the message array sent and the model response.
5661
// 'gpt-35-turbo' has a limit of 4096 tokens, 'gpt-4' and 'gpt-4-32k' have limits of 8192 and 32768 tokens respectively.
57-
// Check if the model type is GPT-4-turbo
58-
if (model.toLowerCase().includes('1106-preview')) {
59-
//If it's a '1106-preview' model, set the maxModelTokens to 131072
60-
options.maxModelTokens = 131072
61-
options.maxResponseTokens = 32768
62-
}
62+
// Check if the model type is GPT-4-turbo
63+
if (model.toLowerCase().includes('1106-preview')) {
64+
// If it's a '1106-preview' model, set the maxModelTokens to 131072
65+
options.maxModelTokens = 131072
66+
options.maxResponseTokens = 32768
67+
}
6368
// Check if the model type includes '16k'
6469
if (model.toLowerCase().includes('16k')) {
6570
// If it's a '16k' model, set the maxModelTokens to 16384 and maxResponseTokens to 4096
@@ -107,6 +112,7 @@ async function chatReplyProcess(options: RequestOptions) {
107112
const model = options.user.config.chatModel
108113
const key = await getRandomApiKey(options.user, options.user.config.chatModel, options.room.accountId)
109114
const userId = options.user._id.toString()
115+
const maxContextCount = options.user.advanced.maxContextCount ?? 20
110116
const messageId = options.messageId
111117
if (key == null || key === undefined)
112118
throw new Error('没有可用的配置。请再试一次 | No available configuration. Please try again.')
@@ -140,7 +146,7 @@ async function chatReplyProcess(options: RequestOptions) {
140146
else
141147
options = { ...lastContext }
142148
}
143-
const api = await initApi(key, model)
149+
const api = await initApi(key, model, maxContextCount)
144150

145151
const abort = new AbortController()
146152
options.abortSignal = abort.signal

service/src/index.ts

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { abortChatProcess, chatConfig, chatReplyProcess, containsSensitiveWords,
1010
import { auth, getUserId } from './middleware/auth'
1111
import { clearApiKeyCache, clearConfigCache, getApiKeys, getCacheApiKeys, getCacheConfig, getOriginConfig } from './storage/config'
1212
import type { AuditConfig, ChatInfo, ChatOptions, Config, KeyConfig, MailConfig, SiteConfig, UserConfig, UserInfo } from './storage/model'
13-
import { Status, UsageResponse, UserRole } from './storage/model'
13+
import { AdvancedConfig, Status, UsageResponse, UserRole } from './storage/model'
1414
import {
1515
clearChat,
1616
createChatRoom,
@@ -39,6 +39,7 @@ import {
3939
updateRoomUsingContext,
4040
updateUser,
4141
updateUser2FA,
42+
updateUserAdvancedConfig,
4243
updateUserChatModel,
4344
updateUserInfo,
4445
updateUserPassword,
@@ -589,7 +590,7 @@ router.post('/session', async (req, res) => {
589590
}
590591
})
591592

592-
let userInfo: { name: string; description: string; avatar: string; userId: string; root: boolean; roles: UserRole[]; config: UserConfig }
593+
let userInfo: { name: string; description: string; avatar: string; userId: string; root: boolean; roles: UserRole[]; config: UserConfig; advanced: AdvancedConfig }
593594
if (userId != null) {
594595
const user = await getUserById(userId)
595596
userInfo = {
@@ -600,6 +601,7 @@ router.post('/session', async (req, res) => {
600601
root: user.roles.includes(UserRole.Admin),
601602
roles: user.roles,
602603
config: user.config,
604+
advanced: user.advanced,
603605
}
604606

605607
const keys = (await getCacheApiKeys()).filter(d => hasAnyRole(d.userRoles, user.roles))
@@ -1067,6 +1069,55 @@ router.post('/audit-test', rootAuth, async (req, res) => {
10671069
}
10681070
})
10691071

1072+
router.post('/setting-advanced', auth, async (req, res) => {
1073+
try {
1074+
const config = req.body as {
1075+
systemMessage: string
1076+
temperature: number
1077+
top_p: number
1078+
maxContextCount: number
1079+
sync: boolean
1080+
}
1081+
if (config.sync) {
1082+
if (!isAdmin(req.headers.userId as string)) {
1083+
res.send({ status: 'Fail', message: '无权限 | No permission', data: null })
1084+
return
1085+
}
1086+
const thisConfig = await getOriginConfig()
1087+
thisConfig.advancedConfig = new AdvancedConfig(
1088+
config.systemMessage,
1089+
config.temperature,
1090+
config.top_p,
1091+
config.maxContextCount,
1092+
)
1093+
await updateConfig(thisConfig)
1094+
clearConfigCache()
1095+
}
1096+
const userId = req.headers.userId.toString()
1097+
await updateUserAdvancedConfig(userId, new AdvancedConfig(
1098+
config.systemMessage,
1099+
config.temperature,
1100+
config.top_p,
1101+
config.maxContextCount,
1102+
))
1103+
res.send({ status: 'Success', message: '操作成功 | Successfully' })
1104+
}
1105+
catch (error) {
1106+
res.send({ status: 'Fail', message: error.message, data: null })
1107+
}
1108+
})
1109+
1110+
router.post('/setting-reset-advanced', auth, async (req, res) => {
1111+
try {
1112+
const userId = req.headers.userId.toString()
1113+
await updateUserAdvancedConfig(userId, null)
1114+
res.send({ status: 'Success', message: '操作成功 | Successfully' })
1115+
}
1116+
catch (error) {
1117+
res.send({ status: 'Fail', message: error.message, data: null })
1118+
}
1119+
})
1120+
10701121
router.get('/setting-keys', rootAuth, async (req, res) => {
10711122
try {
10721123
const result = await getApiKeys()

service/src/storage/config.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { ObjectId } from 'mongodb'
22
import * as dotenv from 'dotenv'
33
import type { TextAuditServiceProvider } from 'src/utils/textAudit'
44
import { isNotEmptyString, isTextAuditServiceProvider } from '../utils/is'
5-
import { AuditConfig, Config, KeyConfig, MailConfig, SiteConfig, TextAudioType, UserRole } from './model'
5+
import { AdvancedConfig, AuditConfig, Config, KeyConfig, MailConfig, SiteConfig, TextAudioType, UserRole } from './model'
66
import { getConfig, getKeys, upsertKey } from './mongo'
77

88
dotenv.config()
@@ -93,6 +93,16 @@ export async function getOriginConfig() {
9393
'',
9494
)
9595
}
96+
97+
if (!config.advancedConfig) {
98+
config.advancedConfig = new AdvancedConfig(
99+
'You are ChatGPT, a large language model trained by OpenAI. Follow the user\'s instructions carefully.Respond using markdown.',
100+
0.8,
101+
1,
102+
20,
103+
)
104+
}
105+
96106
if (!isNotEmptyString(config.siteConfig.chatModels))
97107
config.siteConfig.chatModels = 'gpt-3.5-turbo,gpt-3.5-turbo-1106,gpt-3.5-turbo-16k,gpt-3.5-turbo-16k-0613,gpt-4,gpt-4-0613,gpt-4-32k,gpt-4-32k-0613,text-davinci-002-render-sha-mobile,text-embedding-ada-002,gpt-4-mobile,gpt-4-browsing,gpt-4-1106-preview,gpt-4-vision-preview'
98108

service/src/storage/model.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export class UserInfo {
3838
roles?: UserRole[]
3939
remark?: string
4040
secretKey?: string // 2fa
41+
advanced?: AdvancedConfig
4142
constructor(email: string, password: string) {
4243
this.name = email
4344
this.email = email
@@ -165,6 +166,7 @@ export class Config {
165166
public siteConfig?: SiteConfig,
166167
public mailConfig?: MailConfig,
167168
public auditConfig?: AuditConfig,
169+
public advancedConfig?: AdvancedConfig,
168170
) { }
169171
}
170172

@@ -202,6 +204,15 @@ export class AuditConfig {
202204
) { }
203205
}
204206

207+
export class AdvancedConfig {
208+
constructor(
209+
public systemMessage: string,
210+
public temperature: number,
211+
public top_p: number,
212+
public maxContextCount: number,
213+
) { }
214+
}
215+
205216
export enum TextAudioType {
206217
None = 0,
207218
Request = 1 << 0, // 二进制 01

service/src/storage/mongo.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import { MongoClient, ObjectId } from 'mongodb'
22
import * as dotenv from 'dotenv'
33
import dayjs from 'dayjs'
44
import { md5 } from '../utils/security'
5+
import type { AdvancedConfig, ChatOptions, Config, KeyConfig, UsageResponse } from './model'
56
import { ChatInfo, ChatRoom, ChatUsage, Status, UserConfig, UserInfo, UserRole } from './model'
6-
import type { ChatOptions, Config, KeyConfig, UsageResponse } from './model'
7+
import { getCacheConfig } from './config'
78

89
dotenv.config()
910

@@ -222,6 +223,11 @@ export async function updateUserChatModel(userId: string, chatModel: string) {
222223
, { $set: { 'config.chatModel': chatModel } })
223224
}
224225

226+
export async function updateUserAdvancedConfig(userId: string, config: AdvancedConfig) {
227+
return userCol.updateOne({ _id: new ObjectId(userId) }
228+
, { $set: { advanced: config } })
229+
}
230+
225231
export async function updateUser2FA(userId: string, secretKey: string) {
226232
return userCol.updateOne({ _id: new ObjectId(userId) }
227233
, { $set: { secretKey, updateTime: new Date().toLocaleString() } })
@@ -245,7 +251,7 @@ export async function updateUserPasswordWithVerifyOld(userId: string, oldPasswor
245251
export async function getUser(email: string): Promise<UserInfo> {
246252
email = email.toLowerCase()
247253
const userInfo = await userCol.findOne({ email }) as UserInfo
248-
initUserInfo(userInfo)
254+
await initUserInfo(userInfo)
249255
return userInfo
250256
}
251257

@@ -266,22 +272,25 @@ export async function getUsers(page: number, size: number): Promise<{ users: Use
266272

267273
export async function getUserById(userId: string): Promise<UserInfo> {
268274
const userInfo = await userCol.findOne({ _id: new ObjectId(userId) }) as UserInfo
269-
initUserInfo(userInfo)
275+
await initUserInfo(userInfo)
270276
return userInfo
271277
}
272278

273-
function initUserInfo(userInfo: UserInfo) {
279+
async function initUserInfo(userInfo: UserInfo) {
274280
if (userInfo == null)
275281
return
276282
if (userInfo.config == null)
277283
userInfo.config = new UserConfig()
278284
if (userInfo.config.chatModel == null)
279285
userInfo.config.chatModel = 'gpt-3.5-turbo'
280286
if (userInfo.roles == null || userInfo.roles.length <= 0) {
281-
userInfo.roles = [UserRole.User]
287+
userInfo.roles = []
282288
if (process.env.ROOT_USER === userInfo.email.toLowerCase())
283289
userInfo.roles.push(UserRole.Admin)
290+
userInfo.roles.push(UserRole.User)
284291
}
292+
if (!userInfo.advanced)
293+
userInfo.advanced = (await getCacheConfig()).advancedConfig
285294
}
286295

287296
export async function verifyUser(email: string, status: Status) {

src/api/index.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import type { AxiosProgressEvent, GenericAbortSignal } from 'axios'
22
import { get, post } from '@/utils/request'
33
import type { AuditConfig, ConfigState, KeyConfig, MailConfig, SiteConfig, Status, UserInfo, UserPassword } from '@/components/common/Setting/model'
4-
import { useAuthStore, useSettingStore } from '@/store'
4+
import { useAuthStore, useUserStore } from '@/store'
5+
import type { SettingsState } from '@/store/modules/user/helper'
56

67
export function fetchChatConfig<T = any>() {
78
return post<T>({
@@ -19,7 +20,7 @@ export function fetchChatAPIProcess<T = any>(
1920
signal?: GenericAbortSignal
2021
onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void },
2122
) {
22-
const settingStore = useSettingStore()
23+
const userStore = useUserStore()
2324
const authStore = useAuthStore()
2425

2526
let data: Record<string, any> = {
@@ -33,9 +34,9 @@ export function fetchChatAPIProcess<T = any>(
3334
if (authStore.isChatGPTAPI) {
3435
data = {
3536
...data,
36-
systemMessage: settingStore.systemMessage,
37-
temperature: settingStore.temperature,
38-
top_p: settingStore.top_p,
37+
systemMessage: userStore.userInfo.advanced.systemMessage,
38+
temperature: userStore.userInfo.advanced.temperature,
39+
top_p: userStore.userInfo.advanced.top_p,
3940
}
4041
}
4142

@@ -274,6 +275,19 @@ export function fetchTestAudit<T = any>(text: string, audit: AuditConfig) {
274275
})
275276
}
276277

278+
export function fetchUpdateAdvanced<T = any>(sync: boolean, advanced: SettingsState) {
279+
const data = { sync, ...advanced }
280+
return post<T>({
281+
url: '/setting-advanced',
282+
data,
283+
})
284+
}
285+
286+
export function fetchResetAdvanced<T = any>() {
287+
return post<T>({
288+
url: '/setting-reset-advanced',
289+
})
290+
}
277291
export function fetchUpdateSite<T = any>(config: SiteConfig) {
278292
return post<T>({
279293
url: '/setting-site',

0 commit comments

Comments
 (0)