Skip to content

Commit 858794d

Browse files
committed
model now based on prompt, not course
1 parent b46a9eb commit 858794d

File tree

10 files changed

+71
-85
lines changed

10 files changed

+71
-85
lines changed

src/client/components/Admin/ChatInstances/ChatInstanceTable.tsx

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,6 @@ const headCells: readonly HeadCell[] = [
4343
disablePadding: false,
4444
label: 'Description',
4545
},
46-
{
47-
id: 'model',
48-
numeric: true,
49-
disablePadding: false,
50-
label: 'Model',
51-
},
5246
{
5347
id: 'usageLimit',
5448
numeric: true,
@@ -139,7 +133,6 @@ const ChatInstanceTableChatInstanceWithTokens = React.memo(
139133
</Link>
140134
</TableCell>
141135
<TableCell align="right">{row.description}</TableCell>
142-
<TableCell align="right">{row.model}</TableCell>
143136
<TableCell sx={{ fontFamily: 'monospace' }} align="right">
144137
{row.usageLimit}
145138
</TableCell>

src/client/components/ChatV2/ChatV2.tsx

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ const ChatV2Content = () => {
9494
const [fileName, setFileName] = useState<string>('')
9595
const [tokenUsageWarning, setTokenUsageWarning] = useState<string>('')
9696
const [tokenUsageAlertOpen, setTokenUsageAlertOpen] = useState<boolean>(false)
97-
const [allowedModels, setAllowedModels] = useState<ValidModelName[]>([])
9897
const [chatLeftSidePanelOpen, setChatLeftSidePanelOpen] = useState<boolean>(false)
9998
const [activeToolResult, setActiveToolResult0] = useState<ToolCallResultEvent | undefined>()
10099

@@ -263,27 +262,7 @@ const ChatV2Content = () => {
263262
useEffect(() => {
264263
if (!userStatus) return
265264

266-
const { usage, limit, model: defaultCourseModel, models: courseModels } = userStatus
267-
268-
let allowedModels: ValidModelName[] = []
269-
270-
if (course && courseModels) {
271-
allowedModels = courseModels
272-
273-
if (courseModels.includes(activeModel)) {
274-
setActiveModel(activeModel)
275-
} else {
276-
setActiveModel(defaultCourseModel ?? courseModels[0])
277-
}
278-
} else {
279-
allowedModels = validModels.map((m) => m.name) // [gpt-5, gpt-4o, gpt-4o-mini, mock] 23.7.2025
280-
}
281-
282-
// Mock model is only visible to admins in production
283-
if (!user?.isAdmin && inProduction) {
284-
allowedModels = allowedModels.filter((model) => model !== 'mock')
285-
}
286-
setAllowedModels(allowedModels)
265+
const { usage, limit } = userStatus
287266

288267
const tokenUseExceeded = usage >= limit
289268

@@ -388,7 +367,6 @@ const ChatV2Content = () => {
388367
messages={messages}
389368
currentModel={activeModel}
390369
setModel={setActiveModel}
391-
availableModels={allowedModels}
392370
/>
393371
</Drawer>
394372
) : (
@@ -404,7 +382,6 @@ const ChatV2Content = () => {
404382
messages={messages}
405383
currentModel={activeModel}
406384
setModel={setActiveModel}
407-
availableModels={allowedModels}
408385
/>
409386
))}
410387

@@ -579,7 +556,6 @@ const LeftMenu = ({
579556
messages,
580557
currentModel,
581558
setModel,
582-
availableModels,
583559
}: {
584560
sx?: object
585561
course?: Course
@@ -590,7 +566,6 @@ const LeftMenu = ({
590566
messages: ChatMessage[]
591567
currentModel: ValidModelName
592568
setModel: (model: ValidModelName) => void
593-
availableModels: ValidModelName[]
594569
}) => {
595570
const { t } = useTranslation()
596571
const { courseId } = useParams()
@@ -623,7 +598,7 @@ const LeftMenu = ({
623598
<OutlineButtonBlack startIcon={<RestartAltIcon />} onClick={handleReset} data-testid="empty-conversation-button">
624599
{t('chat:emptyConversation')}
625600
</OutlineButtonBlack>
626-
<ModelSelector currentModel={currentModel} setModel={setModel} availableModels={availableModels} isTokenLimitExceeded={isTokenLimitExceeded} />
601+
<ModelSelector currentModel={currentModel} setModel={setModel} isTokenLimitExceeded={isTokenLimitExceeded} />
627602
<PromptSelector sx={{ width: '100%' }} />
628603
<EmailButton messages={messages} disabled={!messages?.length} />
629604
<OutlineButtonBlack startIcon={<Tune />} onClick={() => setSettingsModalOpen(true)} data-testid="settings-button">

src/client/components/ChatV2/ModelSelector.tsx

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,25 @@ import React from 'react'
22
import { useTranslation } from 'react-i18next'
33
import { MenuItem, Typography, Tooltip, Menu } from '@mui/material'
44
import { KeyboardArrowDown, SmartToy } from '@mui/icons-material'
5-
import { FREE_MODEL, ValidModelName } from '../../../config'
5+
import { FREE_MODEL, ValidModelName, validModels } from '../../../config'
66
import { OutlineButtonBlack } from './general/Buttons'
7+
import { usePromptState } from './PromptState'
8+
import useCurrentUser from '../../hooks/useCurrentUser'
79

810
const ModelSelector = ({
911
currentModel,
1012
setModel,
11-
availableModels,
1213
isTokenLimitExceeded,
1314
}: {
1415
currentModel: ValidModelName
1516
setModel: (model: ValidModelName) => void
16-
availableModels: ValidModelName[]
1717
isTokenLimitExceeded: boolean
1818
}) => {
1919
const { t } = useTranslation()
2020
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null)
2121
const open = Boolean(anchorEl)
22-
const validModel = availableModels.includes(currentModel) ? currentModel : ''
22+
const { user } = useCurrentUser()
23+
const { activePrompt } = usePromptState()
2324

2425
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
2526
setAnchorEl(event.currentTarget)
@@ -30,10 +31,26 @@ const ModelSelector = ({
3031
setAnchorEl(null)
3132
}
3233

34+
const availableModels = React.useMemo(() => {
35+
if (activePrompt?.model) {
36+
return [activePrompt.model]
37+
}
38+
const models = validModels.map((model) => model.name)
39+
return models.filter((model) => !isTokenLimitExceeded || model === FREE_MODEL).filter((model) => user?.isAdmin || model !== 'mock')
40+
}, [isTokenLimitExceeded, user, activePrompt])
41+
42+
console.log(availableModels, activePrompt)
43+
3344
return (
3445
<>
35-
<OutlineButtonBlack startIcon={<SmartToy />} endIcon={<KeyboardArrowDown />} onClick={handleClick} data-testid="model-selector">
36-
{`${t('admin:model')}: ${validModel}`}
46+
<OutlineButtonBlack
47+
startIcon={<SmartToy />}
48+
endIcon={<KeyboardArrowDown />}
49+
onClick={handleClick}
50+
data-testid="model-selector"
51+
disabled={availableModels.length === 1}
52+
>
53+
{`${t('admin:model')}: ${currentModel}`}
3754
</OutlineButtonBlack>
3855
<Menu
3956
anchorEl={anchorEl}
@@ -48,13 +65,7 @@ const ModelSelector = ({
4865
}}
4966
>
5067
{availableModels.map((model) => (
51-
<MenuItem
52-
key={model}
53-
value={model}
54-
onClick={() => handleSelect(model)}
55-
disabled={isTokenLimitExceeded && model !== FREE_MODEL}
56-
data-testid={`${model}-option`}
57-
>
68+
<MenuItem key={model} value={model} onClick={() => handleSelect(model)} data-testid={`${model}-option`}>
5869
<Typography>
5970
{model}
6071
{model === FREE_MODEL && (

src/client/components/Courses/Course/EditCourseForm.tsx

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,13 @@ const EditCourseForm = forwardRef(({ course, setOpen, user }: { course: Course;
1313
const { t } = useTranslation()
1414
const mutation = useEditCourseMutation(course?.courseId as string)
1515

16-
const { model: currentModel, usageLimit: currentUsageLimit } = course
16+
const { usageLimit: currentUsageLimit } = course
1717

1818
const currentDate = new Date().toISOString()
1919
const { startDate: defaultStart, endDate: defaultEnd } = course?.activityPeriod || { startDate: currentDate, endDate: currentDate }
2020

2121
const [startDate, setStartDate] = useState(new Date(defaultStart))
2222
const [endDate, setEndDate] = useState(new Date(defaultEnd))
23-
const [model, setModel] = useState(currentModel)
2423
const [usageLimit, setUsageLimit] = useState(currentUsageLimit)
2524
const [saveDiscussions, setSaveDiscussions] = useState(course.saveDiscussions)
2625
const [notOptoutSaving, setNotOptoutSaving] = useState(course.notOptoutSaving)
@@ -35,7 +34,6 @@ const EditCourseForm = forwardRef(({ course, setOpen, user }: { course: Course;
3534
try {
3635
mutation.mutate({
3736
activityPeriod,
38-
model,
3937
usageLimit,
4038
saveDiscussions,
4139
notOptoutSaving,
@@ -59,27 +57,11 @@ const EditCourseForm = forwardRef(({ course, setOpen, user }: { course: Course;
5957
</Box>
6058

6159
<Box my={3} display="flex" justifyContent="space-between" flexDirection="row">
62-
<Box>
63-
<Typography mb={1} variant="h5">
64-
{t('admin:model')}
65-
</Typography>
66-
<Typography mb={1}>{t('admin:modelInfo')}</Typography>
67-
<Select sx={{ m: 1, width: '300px' }} value={model} onChange={(e) => setModel(e.target.value as ValidModelName)}>
68-
{validModels.map(({ name: modelName }) => (
69-
<MenuItem key={modelName} value={modelName}>
70-
{modelName}
71-
</MenuItem>
72-
))}
73-
</Select>
74-
</Box>
75-
76-
<Box>
77-
<Typography mb={1} variant="h5">
78-
{t('admin:usageLimit')}
79-
</Typography>
80-
<Typography mb={1}>{t('admin:usageLimitInfo')}</Typography>
81-
<TextField sx={{ m: 1, width: '300px' }} value={usageLimit} type="number" onChange={(e) => setUsageLimit(Number(e.target.value))} />
82-
</Box>
60+
<Typography mb={1} variant="h5">
61+
{t('admin:usageLimit')}
62+
</Typography>
63+
<Typography mb={1}>{t('admin:usageLimitInfo')}</Typography>
64+
<TextField sx={{ m: 1, width: '300px' }} value={usageLimit} type="number" onChange={(e) => setUsageLimit(Number(e.target.value))} />
8365
</Box>
8466

8567
{user.isAdmin && (

src/client/components/Courses/Course/index.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ const Course = () => {
139139
const usersResponsibility: Responsebility | undefined = responsibilities.find((r: Responsebility) => {
140140
return r.user.id === user.id
141141
})
142-
const isResponsible = usersResponsibility != undefined
142+
const isResponsible = usersResponsibility !== undefined
143143
return (
144144
<>
145145
{!isResponsible ? (
@@ -204,7 +204,6 @@ const Course = () => {
204204
{courseEnabled && (
205205
<div style={{ ...left, boxSizing: 'border-box' }}>
206206
<Typography>
207-
{t('admin:model')}: {chatInstance.model} <span style={{ marginRight: 20 }} />
208207
{t('admin:usageLimit')}: {chatInstance.usageLimit}
209208
</Typography>
210209
</div>

src/client/hooks/useCourseMutation.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import { useMutation } from '@tanstack/react-query'
22

3-
import { ActivityPeriod } from '../types'
3+
import type { ActivityPeriod } from '../types'
44
import queryClient from '../util/queryClient'
55
import apiClient from '../util/apiClient'
66

77
interface UpdatedCourseData {
88
activityPeriod: ActivityPeriod
9-
model: string
109
usageLimit: number
1110
saveDiscussions: boolean
1211
notOptoutSaving: boolean

src/client/types.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,14 @@ export type Prompt = {
6666
type: 'CHAT_INSTANCE' | 'PERSONAL'
6767
createdAt: string
6868
ragIndexId?: number
69+
model?: ValidModelName
6970
}
7071

7172
export interface ChatInstance {
7273
promptCount?: number
7374
id: string
7475
name: Locales
7576
description: string
76-
model: ValidModelName
7777
usageLimit: number
7878
resetCron?: string
7979
courseId?: string
@@ -82,14 +82,6 @@ export interface ChatInstance {
8282
activityPeriod: ActivityPeriod
8383
}
8484

85-
export interface AccessGroup {
86-
id: string
87-
iamGroup: string
88-
model: ValidModelName
89-
usageLimit: number | null
90-
resetCron: string | null
91-
}
92-
9385
export type ActivityPeriod = {
9486
startDate: string
9587
endDate: string
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { DataTypes } from 'sequelize'
2+
3+
import type { Migration } from '../connection'
4+
5+
export const up: Migration = async ({ context: queryInterface }) => {
6+
await queryInterface.addColumn('prompts', 'model', {
7+
type: DataTypes.STRING,
8+
allowNull: true,
9+
})
10+
11+
await queryInterface.addColumn('prompts', 'temperature', {
12+
type: DataTypes.FLOAT,
13+
allowNull: true,
14+
})
15+
}
16+
17+
export const down: Migration = async ({ context: queryInterface }) => {
18+
await queryInterface.removeColumn('prompts', 'model')
19+
await queryInterface.removeColumn('prompts', 'temperature')
20+
}

src/server/db/models/prompt.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { type CreationOptional, DataTypes, type InferAttributes, type InferCreat
33
import type { CustomMessage } from '../../types'
44
import { sequelize } from '../connection'
55
import RagIndex from './ragIndex'
6+
import type { ValidModelName } from '@config'
67

78
export const PromptTypeValues = ['CHAT_INSTANCE', 'PERSONAL'] as const
89
export type PromptType = (typeof PromptTypeValues)[number]
@@ -28,6 +29,10 @@ class Prompt extends Model<InferAttributes<Prompt>, InferCreationAttributes<Prom
2829

2930
declare mandatory: CreationOptional<boolean>
3031

32+
declare model?: CreationOptional<ValidModelName>
33+
34+
declare temperature?: CreationOptional<number>
35+
3136
declare ragIndex?: NonAttribute<RagIndex>
3237
}
3338

@@ -82,6 +87,14 @@ Prompt.init(
8287
allowNull: false,
8388
defaultValue: false,
8489
},
90+
model: {
91+
type: DataTypes.STRING,
92+
allowNull: true,
93+
},
94+
temperature: {
95+
type: DataTypes.FLOAT,
96+
allowNull: true,
97+
},
8598
},
8699
{
87100
underscored: true,

src/server/routes/prompt.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ promptRouter.put('/:id', async (req, res) => {
170170
const { id } = req.params
171171
const { user } = req as unknown as RequestWithUser
172172
const updates = PromptUpdateableParamsSchema.parse(req.body)
173-
const { systemMessage, name, hidden, mandatory, ragIndexId } = updates
173+
const { systemMessage, name, hidden, mandatory, ragIndexId, model, temperature } = updates
174174

175175
const prompt = await Prompt.findByPk(id)
176176

@@ -190,6 +190,8 @@ promptRouter.put('/:id', async (req, res) => {
190190
prompt.name = name
191191
prompt.hidden = hidden
192192
prompt.mandatory = mandatory
193+
prompt.model = model
194+
prompt.temperature = temperature
193195

194196
await prompt.save()
195197

0 commit comments

Comments
 (0)