Skip to content

Commit 6495f17

Browse files
fix(lightspeed): Make Source card links as external links (#947)
* make source card links external * add changeset * add more unit tests
1 parent 555ef5b commit 6495f17

5 files changed

Lines changed: 126 additions & 1 deletion

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@red-hat-developer-hub/backstage-plugin-lightspeed': patch
3+
---
4+
5+
Make source card links as external links

workspaces/lightspeed/plugins/lightspeed/src/hooks/useConversationMessages.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
createUserMessage,
3232
getMessageData,
3333
getTimestamp,
34+
transformDocumentsToSources,
3435
} from '../utils/lightspeed-chatbox-utils';
3536
import { useCreateConversationMessage } from './useCreateCoversationMessage';
3637

@@ -126,6 +127,7 @@ export const useConversationMessages = (
126127
model,
127128
content: botMessage,
128129
timestamp: botTimestamp,
130+
referencedDocuments,
129131
} = getMessageData(aiMessage);
130132

131133
_conversations[currentConversation].push(
@@ -142,6 +144,7 @@ export const useConversationMessages = (
142144
name: model ?? selectedModel,
143145
content: botMessage,
144146
timestamp: botTimestamp,
147+
sources: transformDocumentsToSources(referencedDocuments),
145148
}),
146149
],
147150
);

workspaces/lightspeed/plugins/lightspeed/src/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ export type Conversations = {
2929
};
3030
};
3131

32+
export type ReferencedDocuments = {
33+
doc_title: string;
34+
doc_url: string;
35+
}[];
3236
export interface BaseMessage {
3337
name: string;
3438
type: string;
@@ -41,6 +45,7 @@ export interface BaseMessage {
4145
};
4246
sources?: SourcesCardProps;
4347
additional_kwargs: {
48+
referenced_documents?: ReferencedDocuments;
4449
[_key: string]: any;
4550
};
4651
error?: AlertProps;

workspaces/lightspeed/plugins/lightspeed/src/utils/__tests__/lightspeed-chatbot-utils.test.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,22 @@ import {
2424
getTimestamp,
2525
getTimestampVariablesString,
2626
splitJsonStrings,
27+
transformDocumentsToSources,
2728
} from '../lightspeed-chatbox-utils';
2829

30+
const referenced_documents = [
31+
{
32+
doc_title: 'About Red Hat Developer Hub',
33+
doc_url:
34+
'https://docs.redhat.com/en/documentation/red_hat_developer_hub/1.6/html-single/about_red_hat_developer_hub/index',
35+
},
36+
{
37+
doc_title: 'Adoption Insights in Red Hat Developer Hub',
38+
doc_url:
39+
'https://docs.redhat.com/en/documentation/red_hat_developer_hub/1.6/html-single/adoption_insights_in_red_hat_developer_hub/index',
40+
},
41+
];
42+
2943
describe('getTimestampVariablesString', () => {
3044
it('should add a leading zero if the number is less than 10', () => {
3145
expect(getTimestampVariablesString(5)).toBe('05');
@@ -203,6 +217,38 @@ describe('createBotMessage', () => {
203217
timestamp: '2024-10-30T14:00:00Z',
204218
});
205219
});
220+
221+
it('should create a bot message with source links', () => {
222+
const message = createBotMessage({
223+
name: 'BotMaster',
224+
avatar: 'bot-avatar.png',
225+
content: 'Bot message content',
226+
timestamp: '2024-10-30T14:00:00Z',
227+
isLoading: true,
228+
sources: transformDocumentsToSources(referenced_documents),
229+
});
230+
231+
expect(message?.sources?.sources).toHaveLength(2);
232+
expect(message).toEqual(
233+
expect.objectContaining({
234+
role: 'bot',
235+
name: 'BotMaster',
236+
avatar: 'bot-avatar.png',
237+
isLoading: true,
238+
content: 'Bot message content',
239+
timestamp: '2024-10-30T14:00:00Z',
240+
sources: {
241+
sources: expect.arrayContaining([
242+
expect.objectContaining({
243+
isExternal: true,
244+
link: expect.anything(),
245+
title: expect.anything(),
246+
}),
247+
]),
248+
},
249+
}),
250+
);
251+
});
206252
});
207253

208254
describe('getMessageData', () => {
@@ -223,6 +269,7 @@ describe('getMessageData', () => {
223269
content: 'This is the message content',
224270
model: 'granite3-dense:8b',
225271
timestamp: '15/04/2025, 05:39:08',
272+
referencedDocuments: [],
226273
});
227274
});
228275

@@ -232,10 +279,52 @@ describe('getMessageData', () => {
232279
expect(result).toEqual({
233280
content: '',
234281
timestamp: '',
282+
model: undefined,
283+
referencedDocuments: [],
284+
});
285+
});
286+
287+
it('should return referenced_documents as sources from additional_kwargs', () => {
288+
const message = {
289+
additional_kwargs: {
290+
referenced_documents,
291+
},
292+
};
293+
const result = getMessageData(message as any);
294+
expect(result).toEqual({
295+
content: '',
296+
timestamp: '',
297+
model: undefined,
298+
referencedDocuments: referenced_documents,
235299
});
236300
});
237301
});
238302

303+
describe('transformDocumentsToSources', () => {
304+
it('should return undefined if invalid values are passed to referenced_documents', () => {
305+
expect(
306+
transformDocumentsToSources(undefined as unknown as any),
307+
).toBeUndefined();
308+
expect(transformDocumentsToSources(null as unknown as any)).toBeUndefined();
309+
expect(transformDocumentsToSources([] as unknown as any)).toBeUndefined();
310+
});
311+
312+
it('should transform referenced documents into message sources', () => {
313+
const sources = transformDocumentsToSources(referenced_documents);
314+
expect(sources?.sources).toHaveLength(2);
315+
expect(sources).toEqual(
316+
expect.objectContaining({
317+
sources: expect.arrayContaining([
318+
expect.objectContaining({
319+
isExternal: true,
320+
link: expect.anything(),
321+
title: expect.anything(),
322+
}),
323+
]),
324+
}),
325+
);
326+
});
327+
});
239328
describe('getCategorizeMessages', () => {
240329
const addProps = (c: ConversationSummary) => ({
241330
customProp: `prop-${c.conversation_id}`,

workspaces/lightspeed/plugins/lightspeed/src/utils/lightspeed-chatbox-utils.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@
1616
import { Conversation, SourcesCardProps } from '@patternfly/chatbot';
1717
import { PopoverProps } from '@patternfly/react-core';
1818

19-
import { BaseMessage, ConversationList, ConversationSummary } from '../types';
19+
import {
20+
BaseMessage,
21+
ConversationList,
22+
ConversationSummary,
23+
ReferencedDocuments,
24+
} from '../types';
2025

2126
export const getFootnoteProps = (additionalClassName: string) => ({
2227
label: 'Always check AI/LLM generated responses for accuracy prior to use.',
@@ -133,6 +138,24 @@ export const getMessageData = (message: BaseMessage) => {
133138
model: message?.response_metadata?.model,
134139
content: message?.content || '',
135140
timestamp: getTimestamp(message?.response_metadata?.created_at * 1000),
141+
referencedDocuments: message?.additional_kwargs?.referenced_documents ?? [],
142+
};
143+
};
144+
145+
export const transformDocumentsToSources = (
146+
referenced_documents: ReferencedDocuments,
147+
): SourcesCardProps | undefined => {
148+
if (!referenced_documents || referenced_documents?.length === 0) {
149+
return undefined;
150+
}
151+
return {
152+
sources: referenced_documents.map(
153+
(doc: { doc_title: string; doc_url: string }) => ({
154+
title: doc.doc_title,
155+
link: doc?.doc_url,
156+
isExternal: true,
157+
}),
158+
),
136159
};
137160
};
138161

0 commit comments

Comments
 (0)