Skip to content

Commit 35ad71c

Browse files
authored
Merge branch 'main' into fix/autorag-max-pred-length
2 parents e74126b + 7ac9748 commit 35ad71c

9 files changed

Lines changed: 82 additions & 28 deletions

File tree

packages/cypress/cypress/tests/mocked/modelServing/modelServingLlmd.cy.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,7 @@ describe('Model Serving LLMD', () => {
11071107
expect(interception.request.url).to.include('?dryRun=All');
11081108
expect(interception.request.body.spec.baseRefs).to.have.length(1);
11091109
expect(interception.request.body.spec.baseRefs).to.deep.include({ name: deploymentName });
1110+
expect(interception.request.body.spec.router).to.not.have.property('scheduler');
11101111
});
11111112

11121113
// Actual: config created with same resource name as deployment, cloned from the selected template
@@ -1123,6 +1124,7 @@ describe('Model Serving LLMD', () => {
11231124
expect(interception.request.url).not.to.include('?dryRun=All');
11241125
expect(interception.request.body.spec.baseRefs).to.have.length(1);
11251126
expect(interception.request.body.spec.baseRefs).to.deep.include({ name: deploymentName });
1127+
expect(interception.request.body.spec.router).to.not.have.property('scheduler');
11261128
});
11271129
});
11281130

@@ -1213,6 +1215,7 @@ describe('Model Serving LLMD', () => {
12131215
expect(interception.request.url).to.include('?dryRun=All');
12141216
expect(interception.request.body.spec.baseRefs).to.have.length(1);
12151217
expect(interception.request.body.spec.baseRefs).to.deep.include({ name: 'test-vllm-gpu' });
1218+
expect(interception.request.body.spec.router).to.not.have.property('scheduler');
12161219
});
12171220

12181221
// Actual: config updated (preserved), IS updated with exactly one baseRef preserved
@@ -1224,6 +1227,7 @@ describe('Model Serving LLMD', () => {
12241227
expect(interception.request.url).not.to.include('?dryRun=All');
12251228
expect(interception.request.body.spec.baseRefs).to.have.length(1);
12261229
expect(interception.request.body.spec.baseRefs).to.deep.include({ name: 'test-vllm-gpu' });
1230+
expect(interception.request.body.spec.router).to.not.have.property('scheduler');
12271231
});
12281232
});
12291233

packages/gen-ai/frontend/src/app/Chatbot/ChatbotMain.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ const ChatbotMain: React.FunctionComponent = () => {
3939
aiModelsError,
4040
maasModels,
4141
maasModelsLoaded,
42+
maasModelsError,
4243
models,
4344
modelsLoaded,
45+
modelsError,
4446
} = React.useContext(ChatbotContext);
4547
const { namespace } = React.useContext(GenAiContext);
4648
const { data: bffConfig } = useFetchBFFConfig();
@@ -105,9 +107,9 @@ const ChatbotMain: React.FunctionComponent = () => {
105107
title={<ChatbotHeader />}
106108
loaded={
107109
lsdStatusLoaded &&
108-
aiModelsLoaded &&
109-
maasModelsLoaded &&
110-
(lsdStatus?.phase !== 'Ready' || modelsLoaded)
110+
(aiModelsLoaded || !!aiModelsError) &&
111+
(maasModelsLoaded || !!maasModelsError) &&
112+
(lsdStatus?.phase !== 'Ready' || !!modelsLoaded || !!modelsError)
111113
}
112114
empty={!lsdStatus}
113115
emptyStatePage={

packages/gen-ai/frontend/src/app/Chatbot/components/PromptAssistantFormGroup.tsx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import * as React from 'react';
2-
import { get } from 'lodash';
32
import {
43
Button,
54
Flex,
@@ -105,14 +104,9 @@ export default function PromptAssistantFormGroup({
105104

106105
function buildPromptStub(): MLflowPromptVersion {
107106
const now = new Date();
108-
const pad = (n: number) => String(n).padStart(2, '0');
109-
const month = now.toLocaleString('en', { month: 'short' });
110-
const date = [month, pad(now.getDate()), now.getFullYear()].join('.');
111-
const time = [pad(now.getHours()), pad(now.getMinutes())].join('.');
112-
const name = `${date}_${time}`;
113107
/* eslint-disable camelcase */
114108
return {
115-
name,
109+
name: '',
116110
version: 0,
117111
template: '',
118112
commit_message: '',
@@ -143,7 +137,7 @@ export default function PromptAssistantFormGroup({
143137
}}
144138
>
145139
<Flex>
146-
<Title headingLevel="h6">{get(dirtyPrompt, 'name', 'New Prompt')}</Title>
140+
<Title headingLevel="h6">{dirtyPrompt?.name || 'New Prompt'}</Title>
147141
{!!activePrompt?.version && (
148142
<Label
149143
isCompact

packages/gen-ai/frontend/src/app/Chatbot/components/promptManagementModal/__tests__/promptDrawer.spec.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,7 @@ describe('PromptDrawer', () => {
6666
it('should display prompt template in text area', () => {
6767
render(<PromptDrawer {...defaultProps} selectedVersion={2} />);
6868

69-
expect(screen.getByLabelText('prompt template')).toHaveValue(
70-
JSON.stringify('You are a helpful assistant.', null, 2),
71-
);
69+
expect(screen.getByLabelText('prompt template')).toHaveValue('You are a helpful assistant.');
7270
});
7371

7472
it('should display commit message', () => {

packages/gen-ai/frontend/src/app/Chatbot/components/promptManagementModal/__tests__/usePromptQueries.spec.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ jest.mock('~/app/hooks/useGenAiAPI', () => ({
3333
})),
3434
}));
3535

36+
jest.mock('~/app/context/GenAiContext', () => {
37+
const React = jest.requireActual('react');
38+
return {
39+
GenAiContext: React.createContext({ namespace: { name: 'test-namespace' } }),
40+
};
41+
});
42+
3643
const mockUseQuery = jest.mocked(useQuery);
3744
const mockUseInfiniteQuery = jest.mocked(useInfiniteQuery);
3845

@@ -165,7 +172,7 @@ describe('usePromptsList', () => {
165172

166173
expect(mockUseInfiniteQuery).toHaveBeenCalledWith(
167174
expect.objectContaining({
168-
queryKey: ['prompts', 'list', { maxResults: 10, filterName: 'test' }],
175+
queryKey: ['test-namespace_prompts', 'list', { maxResults: 10, filterName: 'test' }],
169176
}),
170177
);
171178

@@ -264,7 +271,7 @@ describe('usePromptVersions', () => {
264271
expect(result.current.error).toEqual(mockError);
265272
});
266273

267-
it('should include prompt name in query key', () => {
274+
it('should include namespace and prompt name in query key', () => {
268275
mockUseQuery.mockReturnValue({
269276
data: [],
270277
isLoading: false,
@@ -275,7 +282,7 @@ describe('usePromptVersions', () => {
275282

276283
expect(mockUseQuery).toHaveBeenCalledWith(
277284
expect.objectContaining({
278-
queryKey: ['prompts', 'my-prompt', 'versions'],
285+
queryKey: ['test-namespace_prompts', 'my-prompt', 'versions'],
279286
}),
280287
);
281288
});

packages/gen-ai/frontend/src/app/Chatbot/components/promptManagementModal/promptDrawer.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,19 +108,19 @@ export default function PromptDrawer({
108108
style={{ minHeight: '200px' }}
109109
resizeOrientation="vertical"
110110
aria-label="prompt template"
111-
value={JSON.stringify(
112-
template || messages?.find((m) => m.role === 'system')?.content,
113-
null,
114-
2,
115-
)}
111+
value={template || messages?.find((m) => m.role === 'system')?.content}
116112
readOnlyVariant="default"
117113
/>
118114
</div>
119115
<DescriptionList isHorizontal horizontalTermWidthModifier={{ default: '20ch' }}>
120116
<DescriptionListGroup>
121117
<DescriptionListTerm>Last Modified:</DescriptionListTerm>
122118
<DescriptionListDescription>
123-
<Timestamp date={new Date(updatedAt)} dateFormat={TimestampFormat.full} />
119+
<Timestamp
120+
date={new Date(updatedAt)}
121+
dateFormat={TimestampFormat.full}
122+
style={{ fontSize: '14px' }}
123+
/>
124124
</DescriptionListDescription>
125125
</DescriptionListGroup>
126126
<DescriptionListGroup>

packages/gen-ai/frontend/src/app/Chatbot/components/promptManagementModal/usePromptQueries.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
2+
import { useContext } from 'react';
23
import { useGenAiAPI } from '~/app/hooks/useGenAiAPI';
4+
import { GenAiContext } from '~/app/context/GenAiContext';
35
import {
46
MLflowPrompt,
57
MLflowPromptsResponse,
@@ -24,6 +26,7 @@ type UsePromptsListResult = {
2426
export function usePromptsList(options: UsePromptsListOptions = {}): UsePromptsListResult {
2527
const { api, apiAvailable } = useGenAiAPI();
2628
const { maxResults, filterName } = options;
29+
const { namespace } = useContext(GenAiContext);
2730

2831
const { data, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage, error } =
2932
useInfiniteQuery<
@@ -33,7 +36,7 @@ export function usePromptsList(options: UsePromptsListOptions = {}): UsePromptsL
3336
[string, string, { maxResults?: number; filterName?: string }],
3437
string | undefined
3538
>({
36-
queryKey: ['prompts', 'list', { maxResults, filterName }],
39+
queryKey: [`${namespace?.name}_prompts`, 'list', { maxResults, filterName }],
3740
queryFn: async ({ pageParam }) => {
3841
const queryParams: Record<string, unknown> = {};
3942
if (maxResults !== undefined) {
@@ -75,9 +78,10 @@ type UsePromptVersionsResult = {
7578

7679
export function usePromptVersions(promptName: string | null): UsePromptVersionsResult {
7780
const { api, apiAvailable } = useGenAiAPI();
81+
const { namespace } = useContext(GenAiContext);
7882

7983
const { data, isLoading, error } = useQuery({
80-
queryKey: ['prompts', promptName, 'versions'],
84+
queryKey: [`${namespace?.name}_prompts`, promptName, 'versions'],
8185
queryFn: async () => {
8286
if (!promptName) {
8387
return [];
@@ -109,9 +113,10 @@ type UseLatestPromptVersionResult = {
109113

110114
export function useLatestPromptVersion(promptName: string | null): UseLatestPromptVersionResult {
111115
const { api, apiAvailable } = useGenAiAPI();
116+
const { namespace } = useContext(GenAiContext);
112117

113118
const { data, isLoading, error } = useQuery({
114-
queryKey: ['prompts', promptName, 'latest'],
119+
queryKey: [`${namespace?.name}_prompts`, promptName, 'latest'],
115120
queryFn: () => api.getMLflowPrompt({ name: promptName! }),
116121
enabled: !!promptName && apiAvailable,
117122
staleTime: 0,
@@ -138,6 +143,7 @@ type UseCreatePromptResult = {
138143
export function useCreatePrompt(options: UseCreatePromptOptions = {}): UseCreatePromptResult {
139144
const { api, apiAvailable } = useGenAiAPI();
140145
const queryClient = useQueryClient();
146+
const { namespace } = useContext(GenAiContext);
141147
const { onSuccess, onError } = options;
142148

143149
const { mutate, isPending, error } = useMutation<
@@ -152,8 +158,10 @@ export function useCreatePrompt(options: UseCreatePromptOptions = {}): UseCreate
152158
return api.registerMLflowPrompt(request);
153159
},
154160
onSuccess: (data) => {
155-
queryClient.invalidateQueries({ queryKey: ['prompts', 'list'] });
156-
queryClient.invalidateQueries({ queryKey: ['prompts', data.name, 'versions'] });
161+
queryClient.invalidateQueries({ queryKey: [`${namespace?.name}_prompts`, 'list'] });
162+
queryClient.invalidateQueries({
163+
queryKey: [`${namespace?.name}_prompts`, data.name, 'versions'],
164+
});
157165
onSuccess?.(data);
158166
},
159167
onError,

packages/llmd-serving/src/deployments/__tests__/server.spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,33 @@ describe('applyConfigBaseRef', () => {
3535
const result = applyConfigBaseRef(svc, undefined);
3636
expect(result.spec.baseRefs).toEqual([{ name: 'other-config' }]);
3737
});
38+
39+
it('should keep scheduler when baseRef is undefined (llm-d selection)', () => {
40+
const svc = mockLLMInferenceServiceK8sResource({ name: 'my-deployment' });
41+
const result = applyConfigBaseRef(svc, undefined);
42+
expect(result.spec.router?.scheduler).toEqual({});
43+
});
44+
45+
it('should keep scheduler when baseRef does not match the resource name', () => {
46+
const svc = mockLLMInferenceServiceK8sResource({});
47+
const result = applyConfigBaseRef(svc, 'unrelated-config');
48+
expect(result.spec.router?.scheduler).toEqual({});
49+
});
50+
51+
it('should remove scheduler when baseRef matches the resource name (non-llm-d selection)', () => {
52+
const svc = mockLLMInferenceServiceK8sResource({ name: 'my-deployment' });
53+
const result = applyConfigBaseRef(svc, 'my-deployment');
54+
expect(result.spec.router?.scheduler).toBeUndefined();
55+
expect(result.spec.router?.route).toBeDefined();
56+
expect(result.spec.router?.gateway).toBeDefined();
57+
});
58+
59+
it('should remove scheduler when resource already has a self-referencing baseRef', () => {
60+
const svc = mockLLMInferenceServiceK8sResource({
61+
name: 'my-deployment',
62+
baseRefs: [{ name: 'my-deployment' }],
63+
});
64+
const result = applyConfigBaseRef(svc, 'my-deployment');
65+
expect(result.spec.router?.scheduler).toBeUndefined();
66+
});
3867
});

packages/llmd-serving/src/deployments/server.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,22 @@ export const applyConfigBaseRef = (
4747
);
4848
}
4949

50+
// Add or remove baseRef
5051
if (baseRef && !result.spec.baseRefs?.some((ref) => ref.name === baseRef)) {
5152
result.spec.baseRefs = [...(result.spec.baseRefs ?? []), { name: baseRef }];
5253
} else if (!baseRef && result.spec.baseRefs?.find((ref) => ref.name === k8sName)) {
5354
result.spec.baseRefs = result.spec.baseRefs.filter((ref) => ref.name !== k8sName);
5455
}
56+
57+
// Remove scheduler if no baseRef (llmd-serving basically)
58+
if (baseRef && result.spec.baseRefs?.find((ref) => ref.name === k8sName)) {
59+
delete result.spec.router?.scheduler;
60+
} else {
61+
result.spec.router = {
62+
...result.spec.router,
63+
scheduler: {},
64+
};
65+
}
66+
5567
return result;
5668
};

0 commit comments

Comments
 (0)