mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-01 20:03:30 +02:00
commit
39243fac41
2 changed files with 89 additions and 35 deletions
|
|
@ -617,48 +617,88 @@ const ChatPage = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function to get a citation source by ID
|
// Function to get a citation source by ID
|
||||||
const getCitationSource = (citationId: number): Source | null => {
|
const getCitationSource = (citationId: number, messageIndex?: number): Source | null => {
|
||||||
if (!messages || messages.length === 0) return null;
|
if (!messages || messages.length === 0) return null;
|
||||||
|
|
||||||
// Find the latest assistant message
|
// If no specific message index is provided, use the latest assistant message
|
||||||
const assistantMessages = messages.filter(msg => msg.role === 'assistant');
|
if (messageIndex === undefined) {
|
||||||
if (assistantMessages.length === 0) return null;
|
// Find the latest assistant message
|
||||||
|
const assistantMessages = messages.filter(msg => msg.role === 'assistant');
|
||||||
|
if (assistantMessages.length === 0) return null;
|
||||||
|
|
||||||
const latestAssistantMessage = assistantMessages[assistantMessages.length - 1];
|
const latestAssistantMessage = assistantMessages[assistantMessages.length - 1];
|
||||||
if (!latestAssistantMessage?.annotations) return null;
|
if (!latestAssistantMessage?.annotations) return null;
|
||||||
|
|
||||||
// Find all SOURCES annotations
|
// Find all SOURCES annotations
|
||||||
const annotations = latestAssistantMessage.annotations as any[];
|
const annotations = latestAssistantMessage.annotations as any[];
|
||||||
const sourcesAnnotations = annotations.filter(
|
const sourcesAnnotations = annotations.filter(
|
||||||
(annotation) => annotation.type === 'SOURCES'
|
(annotation) => annotation.type === 'SOURCES'
|
||||||
);
|
);
|
||||||
|
|
||||||
// Get the latest SOURCES annotation
|
// Get the latest SOURCES annotation
|
||||||
if (sourcesAnnotations.length === 0) return null;
|
if (sourcesAnnotations.length === 0) return null;
|
||||||
const latestSourcesAnnotation = sourcesAnnotations[sourcesAnnotations.length - 1];
|
const latestSourcesAnnotation = sourcesAnnotations[sourcesAnnotations.length - 1];
|
||||||
|
|
||||||
if (!latestSourcesAnnotation.content) return null;
|
if (!latestSourcesAnnotation.content) return null;
|
||||||
|
|
||||||
// Flatten all sources from all connectors
|
// Flatten all sources from all connectors
|
||||||
const allSources: Source[] = [];
|
const allSources: Source[] = [];
|
||||||
latestSourcesAnnotation.content.forEach((connector: ConnectorSource) => {
|
latestSourcesAnnotation.content.forEach((connector: ConnectorSource) => {
|
||||||
if (connector.sources && Array.isArray(connector.sources)) {
|
if (connector.sources && Array.isArray(connector.sources)) {
|
||||||
connector.sources.forEach((source: SourceItem) => {
|
connector.sources.forEach((source: SourceItem) => {
|
||||||
allSources.push({
|
allSources.push({
|
||||||
id: source.id,
|
id: source.id,
|
||||||
title: source.title,
|
title: source.title,
|
||||||
description: source.description,
|
description: source.description,
|
||||||
url: source.url,
|
url: source.url,
|
||||||
connectorType: connector.type
|
connectorType: connector.type
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
|
||||||
// Find the source with the matching ID
|
// Find the source with the matching ID
|
||||||
const foundSource = allSources.find(source => source.id === citationId);
|
const foundSource = allSources.find(source => source.id === citationId);
|
||||||
|
|
||||||
return foundSource || null;
|
return foundSource || null;
|
||||||
|
} else {
|
||||||
|
// Use the specific message by index
|
||||||
|
const message = messages[messageIndex];
|
||||||
|
if (!message || message.role !== 'assistant' || !message.annotations) return null;
|
||||||
|
|
||||||
|
// Find all SOURCES annotations
|
||||||
|
const annotations = message.annotations as any[];
|
||||||
|
const sourcesAnnotations = annotations.filter(
|
||||||
|
(annotation) => annotation.type === 'SOURCES'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get the latest SOURCES annotation
|
||||||
|
if (sourcesAnnotations.length === 0) return null;
|
||||||
|
const latestSourcesAnnotation = sourcesAnnotations[sourcesAnnotations.length - 1];
|
||||||
|
|
||||||
|
if (!latestSourcesAnnotation.content) return null;
|
||||||
|
|
||||||
|
// Flatten all sources from all connectors
|
||||||
|
const allSources: Source[] = [];
|
||||||
|
latestSourcesAnnotation.content.forEach((connector: ConnectorSource) => {
|
||||||
|
if (connector.sources && Array.isArray(connector.sources)) {
|
||||||
|
connector.sources.forEach((source: SourceItem) => {
|
||||||
|
allSources.push({
|
||||||
|
id: source.id,
|
||||||
|
title: source.title,
|
||||||
|
description: source.description,
|
||||||
|
url: source.url,
|
||||||
|
connectorType: connector.type
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Find the source with the matching ID
|
||||||
|
const foundSource = allSources.find(source => source.id === citationId);
|
||||||
|
|
||||||
|
return foundSource || null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -685,7 +725,11 @@ const ChatPage = () => {
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<Card className="border-gray-300 dark:border-gray-700">
|
<Card className="border-gray-300 dark:border-gray-700">
|
||||||
<CardContent className="p-3">
|
<CardContent className="p-3">
|
||||||
<MarkdownViewer content={message.content} getCitationSource={getCitationSource} className="text-sm" />
|
<MarkdownViewer
|
||||||
|
content={message.content}
|
||||||
|
getCitationSource={(id) => getCitationSource(id, index)}
|
||||||
|
className="text-sm"
|
||||||
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -901,13 +945,16 @@ const ChatPage = () => {
|
||||||
return (
|
return (
|
||||||
<MarkdownViewer
|
<MarkdownViewer
|
||||||
content={latestAnswer.content.join('\n')}
|
content={latestAnswer.content.join('\n')}
|
||||||
getCitationSource={getCitationSource}
|
getCitationSource={(id) => getCitationSource(id, index)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback to the message content if no ANSWER annotation is available
|
// Fallback to the message content if no ANSWER annotation is available
|
||||||
return <MarkdownViewer content={message.content} getCitationSource={getCitationSource} />;
|
return <MarkdownViewer
|
||||||
|
content={message.content}
|
||||||
|
getCitationSource={(id) => getCitationSource(id, index)}
|
||||||
|
/>;
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,13 @@ export function MarkdownViewer({ content, className, getCitationSource }: Markdo
|
||||||
: children;
|
: children;
|
||||||
return <a className="text-primary hover:underline" {...props}>{processedChildren}</a>;
|
return <a className="text-primary hover:underline" {...props}>{processedChildren}</a>;
|
||||||
},
|
},
|
||||||
|
li: ({node, children, ...props}) => {
|
||||||
|
// Process citations within list item content
|
||||||
|
const processedChildren = getCitationSource
|
||||||
|
? processCitationsInReactChildren(children, getCitationSource)
|
||||||
|
: children;
|
||||||
|
return <li {...props}>{processedChildren}</li>;
|
||||||
|
},
|
||||||
ul: ({node, ...props}) => <ul className="list-disc pl-5 my-2" {...props} />,
|
ul: ({node, ...props}) => <ul className="list-disc pl-5 my-2" {...props} />,
|
||||||
ol: ({node, ...props}) => <ol className="list-decimal pl-5 my-2" {...props} />,
|
ol: ({node, ...props}) => <ol className="list-decimal pl-5 my-2" {...props} />,
|
||||||
h1: ({node, children, ...props}) => {
|
h1: ({node, children, ...props}) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue