Skip to content

Commit 6abd31f

Browse files
authored
Merge pull request #672 from jeff-phillips-18/chat-eval-fixes
Fixes for chat eval layout and auto-scroll
2 parents e0a3ea8 + 5a1169e commit 6abd31f

27 files changed

+1018
-1305
lines changed

package-lock.json

Lines changed: 6 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313
"lint": "next lint",
1414
"type-check": "tsc --noEmit",
1515
"lint:fix": "npx eslint --fix 'src/**/*.{js,jsx,ts,tsx}'",
16-
"pretty": "prettier --write 'src/**/*.{js,jsx,ts,tsx,css,md}'",
16+
"pretty": "prettier --write 'src/**/*.{js,jsx,ts,tsx,css,scss,md}'",
1717
"test:e2e": "npx playwright test"
1818
},
1919
"dependencies": {
2020
"@fortawesome/fontawesome-svg-core": "^6.7.2",
2121
"@next/env": "^15.3.2",
22-
"@patternfly/chatbot": "^2.2.1",
22+
"@patternfly/chatbot": "6.3.0-prerelease.14",
2323
"@patternfly/react-core": "^6.2.2",
2424
"@patternfly/react-icons": "^6.2.0",
2525
"@patternfly/react-styles": "^6.2.0",

src/app/experimental/chat-eval/page.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
import * as React from 'react';
55
import '@patternfly/react-core/dist/styles/base.css';
66
import { AppLayout } from '@/components/AppLayout';
7-
import ChatModelEval from '@/components/Experimental/ChatEval/ChatEval';
7+
import ChatEval from '@/components/Experimental/ChatEval/ChatEval';
88

9-
const ChatEval: React.FunctionComponent = () => {
9+
const ChatEvalPage: React.FunctionComponent = () => {
1010
return (
11-
<AppLayout className="chat-eval-page">
12-
<ChatModelEval />
11+
<AppLayout className="chatBotPage">
12+
<ChatEval />
1313
</AppLayout>
1414
);
1515
};
1616

17-
export default ChatEval;
17+
export default ChatEvalPage;

src/app/playground/endpoints/EditEndpointModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
ValidatedOptions
2020
} from '@patternfly/react-core';
2121
import { ExclamationCircleIcon, OutlinedQuestionCircleIcon } from '@patternfly/react-icons';
22-
import { fetchEndpointStatus } from '@/components/Chat/modelService';
22+
import { fetchEndpointStatus } from '@/services/modelService';
2323

2424
const removeTrailingSlash = (inputUrl: string): string => {
2525
if (inputUrl.slice(-1) === '/') {

src/app/playground/endpoints/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { Endpoint, ModelEndpointStatus } from '@/types';
2424
import EditEndpointModal from '@/app/playground/endpoints/EditEndpointModal';
2525
import DeleteEndpointModal from '@/app/playground/endpoints/DeleteEndpoinModal';
2626
import EndpointActions from '@/app/playground/endpoints/EndpointActions';
27-
import { fetchEndpointStatus } from '@/components/Chat/modelService';
27+
import { fetchEndpointStatus } from '@/services/modelService';
2828

2929
const iconForStatus = (status: ModelEndpointStatus) => {
3030
switch (status) {

src/components/AppLayout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ const AppLayout: React.FunctionComponent<IAppLayout> = ({ children, className })
106106
path: '/experimental',
107107
label: 'Experimental features',
108108
children: [
109-
{ path: '/experimental/fine-tune/', label: 'Fine-tuning' },
110-
{ path: '/experimental/chat-eval/', label: 'Model chat eval' }
109+
{ path: '/experimental/fine-tune', label: 'Fine-tuning' },
110+
{ path: '/experimental/chat-eval', label: 'Model chat eval' }
111111
]
112112
}
113113
]

src/components/Chat/ChatBotComponent.tsx

Lines changed: 19 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,11 @@ import {
3232
MessageProps
3333
} from '@patternfly/chatbot';
3434
import { Model } from '@/types';
35-
import { modelFetcher } from '@/components/Chat/modelService';
36-
const botAvatar = '/bot-icon-chat-32x32.svg';
37-
38-
import { EllipsisVIcon, OutlinedQuestionCircleIcon, TimesIcon } from '@patternfly/react-icons';
39-
import styles from '@/components/Chat/chat.module.css';
35+
import { modelFetcher } from '@/services/modelService';
4036
import { ModelsContext } from '@/components/Chat/ModelsContext';
41-
import { useSession } from 'next-auth/react';
42-
import { useEffect, useState } from 'react';
37+
import { EllipsisVIcon, OutlinedQuestionCircleIcon, TimesIcon } from '@patternfly/react-icons';
38+
39+
const botAvatar = '/bot-icon-chat-32x32.svg';
4340

4441
export const getId = () => {
4542
const date = Date.now() + Math.random();
@@ -48,20 +45,22 @@ export const getId = () => {
4845

4946
type ChatbotComponentProps = {
5047
model: Model;
48+
userName: string;
5149
messages: MessageProps[];
5250
setMessages: React.Dispatch<React.SetStateAction<MessageProps[]>>;
5351
showCompare: boolean;
5452
onCompare: () => void;
5553
onChangeModel: (model: Model) => void;
5654
onClose?: () => void;
57-
submittedMessage?: string;
55+
submittedMessage?: MessageProps;
5856
setFetching: (fetching: boolean) => void;
5957
setStopCallback: (stopFn: () => void) => void;
6058
setController: (controller: AbortController) => void;
6159
};
6260

6361
const ChatBotComponent: React.FunctionComponent<ChatbotComponentProps> = ({
6462
model,
63+
userName,
6564
messages,
6665
setMessages,
6766
showCompare,
@@ -74,7 +73,6 @@ const ChatBotComponent: React.FunctionComponent<ChatbotComponentProps> = ({
7473
setController
7574
}) => {
7675
const router = useRouter();
77-
const { data: session } = useSession();
7876
const { availableModels } = React.useContext(ModelsContext);
7977
const [isLoading, setIsLoading] = React.useState(false);
8078
const [isSelectOpen, setIsSelectOpen] = React.useState(false);
@@ -84,18 +82,7 @@ const ChatBotComponent: React.FunctionComponent<ChatbotComponentProps> = ({
8482
const [announcement, setAnnouncement] = React.useState<string>();
8583
const [isActionsOpen, setActionsOpen] = React.useState<boolean>(false);
8684
const stopped = React.useRef<boolean>(false);
87-
const [userName, setUserName] = useState<string>('');
88-
const [userImage, setUserImage] = useState<string>('');
89-
90-
useEffect(() => {
91-
if (session?.user?.name === 'Admin') {
92-
setUserName(session?.user?.name);
93-
setUserImage('/default-avatar.png');
94-
} else {
95-
setUserName(session?.user?.name ?? '');
96-
setUserImage(session?.user?.image || '');
97-
}
98-
}, [session?.user?.name, session?.user?.image]);
85+
const lastQuestionRef = React.useRef<string>();
9986

10087
React.useEffect(() => {
10188
setStopCallback(() => {
@@ -106,32 +93,24 @@ const ChatBotComponent: React.FunctionComponent<ChatbotComponentProps> = ({
10693
}, []);
10794

10895
const handleSubmit = React.useCallback(
109-
async (input: string) => {
96+
async (message: MessageProps) => {
11097
if (!model) {
11198
setShowNoModelAlert(true);
11299
return;
113100
}
114-
if (!input.trim()) {
101+
if (!message.content?.trim()) {
115102
setShowNoQuestionAlert(true);
116103
return;
117104
}
118105

119106
const date = new Date();
120107

121108
setMessages((prevMessages) => {
122-
const newMessage: MessageProps = {
123-
avatar: userImage,
124-
id: getId(),
125-
name: userName,
126-
role: 'user',
127-
content: input,
128-
timestamp: `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`
129-
};
130-
return [...prevMessages, newMessage];
109+
return [...prevMessages, message];
131110
});
132111

133112
// make announcement to assistive devices that new messages have been added
134-
setAnnouncement(`Message from You: ${input}. Message from Chatbot is loading.`);
113+
setAnnouncement(`Message from You: ${message.content}. Message from Chatbot is loading.`);
135114

136115
setIsLoading(true);
137116
setFetching(true);
@@ -157,24 +136,25 @@ const ChatBotComponent: React.FunctionComponent<ChatbotComponentProps> = ({
157136

158137
stopped.current = false;
159138
try {
160-
await modelFetcher(model, input, setCurrentMessage, setController);
139+
await modelFetcher(model, message.content, setCurrentMessage, setController);
161140
} catch (e) {
162141
console.error(`Model fetch failed: `, e);
163142
}
164143

165144
setIsLoading(false);
166145
setFetching(false);
167146
},
168-
[model, setController, setFetching, setMessages, userImage, userName]
147+
[model, setController, setFetching, setMessages]
169148
);
170149

171150
React.useEffect(() => {
172-
if (submittedMessage) {
151+
if (submittedMessage && submittedMessage.id !== lastQuestionRef.current) {
152+
lastQuestionRef.current = submittedMessage.id;
173153
handleSubmit(submittedMessage);
174154
}
175155
// Do not update when handleSubmit changes
176156
// eslint-disable-next-line react-hooks/exhaustive-deps
177-
}, [submittedMessage]);
157+
}, [submittedMessage, handleSubmit]);
178158

179159
const onToggleClick = () => {
180160
setIsSelectOpen(!isSelectOpen);
@@ -221,7 +201,7 @@ const ChatBotComponent: React.FunctionComponent<ChatbotComponentProps> = ({
221201

222202
return (
223203
<Chatbot displayMode={ChatbotDisplayMode.embedded}>
224-
<ChatbotHeader className={styles.chatHeader}>
204+
<ChatbotHeader>
225205
<ChatbotHeaderMain>
226206
<Select
227207
id="single-select"
@@ -284,7 +264,7 @@ const ChatBotComponent: React.FunctionComponent<ChatbotComponentProps> = ({
284264
</ChatbotHeaderActions>
285265
</ChatbotHeader>
286266
<ChatbotContent>
287-
<MessageBox announcement={announcement} className={styles.chatBotMessage}>
267+
<MessageBox announcement={announcement}>
288268
<ChatbotWelcomePrompt title={`Hello, ${userName}`} description="Go ahead and ask me a question." />
289269
{messages.map((message) => (
290270
<Message key={message.id} {...message} />

src/components/Chat/ChatBotContainer.tsx

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import { useRouter, useSearchParams } from 'next/navigation';
66
import { ChatbotFooter, ChatbotFootnote, Compare, MessageBar, MessageProps } from '@patternfly/chatbot';
77
import { Model } from '@/types';
88
import { ModelsContext } from './ModelsContext';
9-
import { ChatBotComponent } from './ChatBotComponent';
9+
import { ChatBotComponent, getId } from './ChatBotComponent';
10+
import { useUserInfo } from '@/hooks/useUserInfo';
1011

11-
import '@patternfly/chatbot/dist/css/main.css';
1212
import styles from './chat.module.css';
1313

1414
const MAX_COMPARES = 2;
@@ -21,7 +21,9 @@ const ChatBotContainer: React.FC = () => {
2121
() => searchParams.get('models')?.split(',') ?? [availableModels[0]?.name],
2222
[searchParams, availableModels]
2323
);
24-
const [submittedMessage, setSubmittedMessage] = React.useState<string>();
24+
const [submittedMessage, setSubmittedMessage] = React.useState<MessageProps>();
25+
const { userName, userImage } = useUserInfo();
26+
const [question, setQuestion] = React.useState<string>('');
2527

2628
const [mainChatMessages, setMainChatMessages] = React.useState<MessageProps[]>([]);
2729
const [mainChatFetching, setMainChatFetching] = React.useState<boolean>();
@@ -45,6 +47,24 @@ const ChatBotContainer: React.FC = () => {
4547
[modelNames, availableModels]
4648
);
4749

50+
const onSubmitMessage = React.useCallback(
51+
(message: string | number) => {
52+
const date = new Date();
53+
54+
const newMessage: MessageProps = {
55+
avatar: userImage,
56+
id: getId(),
57+
name: userName,
58+
role: 'user',
59+
content: typeof message === 'string' ? message : String(message),
60+
timestamp: `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`
61+
};
62+
63+
setSubmittedMessage(newMessage);
64+
},
65+
[userImage, userName]
66+
);
67+
4868
const onCloseChat = (indexToRemove: number) => {
4969
const remaining = [...modelNames.slice(0, indexToRemove), ...modelNames.slice(indexToRemove + 1)];
5070

@@ -87,7 +107,8 @@ const ChatBotContainer: React.FC = () => {
87107
const mainChat = (
88108
<ChatBotComponent
89109
model={selectedModels[0]}
90-
showCompare={selectedModels.length < MAX_COMPARES}
110+
userName={userName}
111+
showCompare={selectedModels.length < MAX_COMPARES && availableModels.length > 1}
91112
onCompare={onCompare}
92113
messages={mainChatMessages}
93114
setMessages={setMainChatMessages}
@@ -106,6 +127,7 @@ const ChatBotContainer: React.FC = () => {
106127
selectedModels.length > 1 ? (
107128
<ChatBotComponent
108129
model={selectedModels[1]}
130+
userName={userName}
109131
showCompare={false}
110132
onCompare={onCompare}
111133
messages={altChatMessages}
@@ -124,7 +146,7 @@ const ChatBotContainer: React.FC = () => {
124146
return (
125147
<>
126148
{altChat ? (
127-
<div className="pf-chatbot__compare-container">
149+
<div className="pf-chatbot__compare-container m-is-unified">
128150
<Compare
129151
firstChild={mainChat}
130152
secondChild={altChat}
@@ -137,13 +159,14 @@ const ChatBotContainer: React.FC = () => {
137159
)}
138160
<ChatbotFooter>
139161
<MessageBar
140-
className={styles.chatBotMessageBar}
141-
onSendMessage={(message) => {
142-
setSubmittedMessage(typeof message === 'string' ? message : String(message));
143-
}}
162+
onSendMessage={onSubmitMessage}
144163
hasMicrophoneButton
145164
hasAttachButton={false}
146-
isSendButtonDisabled={mainChatFetching || altChatFetching}
165+
onChange={(_, val) => {
166+
setQuestion(typeof val === 'string' ? val : String(val));
167+
}}
168+
alwayShowSendButton
169+
isSendButtonDisabled={!question.trim() || mainChatFetching || altChatFetching}
147170
hasStopButton={mainChatFetching || altChatFetching}
148171
handleStopButton={handleStopButton}
149172
/>

src/components/Chat/chat.module.css

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
11
/* Chat Bot Container */
2-
.chatHeader {
3-
border-top: 1px solid var(--pf-t--global--border--color--100);
4-
border-bottom: 1px solid var(--pf-t--global--border--color--100);
5-
}
6-
.chatBotMessageBar {
7-
border: 1px solid var(--pf-t--global--border--color--100);
8-
}
92
.chatBotContainer {
103
flex: 1;
114
overflow-y: hidden;

src/components/Contribute/ContributionLabels.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.pf-v6-c-label {
2-
&.knowledge-contribution-label {
3-
--pf-v6-c-label--m-outline--BorderColor: var(--pf-t--global--color--status--custom--default);
2+
&.knowledge-contribution-label {
3+
--pf-v6-c-label--m-outline--BorderColor: var(--pf-t--global--color--status--custom--default);
44
}
55
&.skill-contribution-label {
66
--pf-v6-c-label--m-outline--BorderColor: var(--pf-t--global--border--color--nonstatus--orange--default);

0 commit comments

Comments
 (0)