diff --git a/src-ui/src/app/components/chat/chat/chat.component.html b/src-ui/src/app/components/chat/chat/chat.component.html index f0e08782e0..f05a3ed949 100644 --- a/src-ui/src/app/components/chat/chat/chat.component.html +++ b/src-ui/src/app/components/chat/chat/chat.component.html @@ -42,11 +42,16 @@ {{ message.content }} } @if (message.role === 'assistant' && !message.isStreaming && message.references?.length) { -
-
Sources
- @for (reference of message.references; track reference.id) { - - {{ reference.title }} +
+
+ Sources + @if (hiddenReferenceCount(message) > 0 && !expandedReferences().has(message)) { + + } +
+ @for (reference of visibleReferences(message); track reference.id) { +
+ {{ reference.title }} }
diff --git a/src-ui/src/app/components/chat/chat/chat.component.scss b/src-ui/src/app/components/chat/chat/chat.component.scss index 64c3737340..3431e7e9b6 100644 --- a/src-ui/src/app/components/chat/chat/chat.component.scss +++ b/src-ui/src/app/components/chat/chat/chat.component.scss @@ -12,6 +12,10 @@ display: none; } +.message .flex-grow-1 { + min-width: 0; +} + .dropdown-item { white-space: initial; } diff --git a/src-ui/src/app/components/chat/chat/chat.component.ts b/src-ui/src/app/components/chat/chat/chat.component.ts index f4fbaafb0f..cdd3f8473d 100644 --- a/src-ui/src/app/components/chat/chat/chat.component.ts +++ b/src-ui/src/app/components/chat/chat/chat.component.ts @@ -14,6 +14,7 @@ import { BootstrapIconComponent } from 'src/app/components/common/bootstrap-icon import { MarkdownPipe } from 'src/app/pipes/markdown.pipe' import { ChatMessage, + ChatReference, ChatService, parseChatResponse, } from 'src/app/services/chat.service' @@ -40,8 +41,29 @@ export class ChatComponent implements OnInit { readonly input = signal('') readonly documentId = signal(undefined) readonly slowResponse = signal(false) + readonly expandedReferences = signal>(new Set()) public popperOptions = pngxPopperOptions + static readonly COLLAPSED_REFERENCE_COUNT = 2 + + public visibleReferences(message: ChatMessage): ChatReference[] { + if (this.expandedReferences().has(message)) { + return message.references + } + return message.references.slice(0, ChatComponent.COLLAPSED_REFERENCE_COUNT) + } + + public hiddenReferenceCount(message: ChatMessage): number { + return Math.max( + 0, + message.references.length - ChatComponent.COLLAPSED_REFERENCE_COUNT + ) + } + + public expandReferences(message: ChatMessage): void { + this.expandedReferences.update((expanded) => new Set(expanded).add(message)) + } + private chatService: ChatService = inject(ChatService) private router: Router = inject(Router) diff --git a/src/paperless_ai/chat.py b/src/paperless_ai/chat.py index df6ea7b638..088a5b285f 100644 --- a/src/paperless_ai/chat.py +++ b/src/paperless_ai/chat.py @@ -22,8 +22,8 @@ logger = logging.getLogger("paperless_ai.chat") CHAT_METADATA_DELIMITER = "\n\n__PAPERLESS_CHAT_METADATA__" CHAT_ERROR_MESSAGE = "Sorry, something went wrong while generating a response." CHAT_NO_CONTENT_MESSAGE = "Sorry, I couldn't find any content to answer your question." -MAX_CHAT_REFERENCES = 3 CHAT_RETRIEVER_TOP_K = 5 +MAX_CHAT_REFERENCES = CHAT_RETRIEVER_TOP_K def _build_chat_prompt(output_language: str | None) -> str: