Add chat sources and citations
This commit is contained in:
@@ -11,7 +11,9 @@ import {
|
||||
buildReasoningSteps,
|
||||
getToolTraceSummary,
|
||||
type AgentChatMessage,
|
||||
type AgentCitation,
|
||||
type AgentReasoningStep,
|
||||
type AgentSource,
|
||||
type AgentToolTrace,
|
||||
} from "./agentChatModel";
|
||||
export type { AgentChatMessage, AgentToolTrace } from "./agentChatModel";
|
||||
@@ -80,15 +82,78 @@ export function AgentMessage({ message, className, ...props }: AgentMessageProps
|
||||
<p className="text-[0.7rem] font-medium uppercase text-muted-foreground">
|
||||
{isUser ? "User" : "Assistant"}
|
||||
</p>
|
||||
<p className="mt-1 whitespace-pre-wrap leading-6">{message.content}</p>
|
||||
<p className="mt-1 whitespace-pre-wrap leading-6">
|
||||
<MessageContentWithCitations
|
||||
content={message.content}
|
||||
citations={message.citations}
|
||||
/>
|
||||
</p>
|
||||
{!isUser && message.toolTrace && message.toolTrace.length > 0 && (
|
||||
<AgentToolTracePanel toolTrace={message.toolTrace} />
|
||||
)}
|
||||
{!isUser && message.sources && message.sources.length > 0 && (
|
||||
<AgentSources sources={message.sources} />
|
||||
)}
|
||||
</div>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
|
||||
function MessageContentWithCitations({
|
||||
content,
|
||||
citations,
|
||||
}: {
|
||||
content: string;
|
||||
citations?: AgentCitation[];
|
||||
}) {
|
||||
if (!citations || citations.length === 0) return content;
|
||||
const citationByMarker = new Map(citations.map((citation) => [citation.marker, citation]));
|
||||
const parts = content.split(/(\[\d+\])/g);
|
||||
|
||||
return (
|
||||
<>
|
||||
{parts.map((part, index) => {
|
||||
const marker = part.match(/^\[(\d+)\]$/)?.[1];
|
||||
const citation = marker ? citationByMarker.get(marker) : undefined;
|
||||
if (!citation) return <span key={`${part}-${index}`}>{part}</span>;
|
||||
|
||||
return (
|
||||
<span
|
||||
className="font-medium text-foreground"
|
||||
aria-label={`Quelle ${citation.marker}: ${citation.sourceId}`}
|
||||
data-source-id={citation.sourceId}
|
||||
key={`${citation.sourceId}-${index}`}
|
||||
>
|
||||
{part}
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function AgentSources({ sources }: { sources: AgentSource[] }) {
|
||||
return (
|
||||
<div className="mt-3 rounded-md border bg-muted/20 p-2">
|
||||
<p className="text-xs font-medium text-muted-foreground">Quellen</p>
|
||||
<div className="mt-2 space-y-2">
|
||||
{sources.map((source) => (
|
||||
<div
|
||||
className="rounded-md bg-background/80 p-2 text-xs"
|
||||
data-source-id={source.id}
|
||||
key={source.id}
|
||||
>
|
||||
<p className="font-medium text-foreground">{source.title}</p>
|
||||
{source.description && (
|
||||
<p className="mt-1 text-muted-foreground">{source.description}</p>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function AgentToolTracePanel({ toolTrace }: { toolTrace: AgentToolTrace[] }) {
|
||||
const steps = buildReasoningSteps(toolTrace);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user