]> git.ipfire.org Git - thirdparty/paperless-ngx.git/commitdiff
Individual doc chat
authorshamoon <4887959+shamoon@users.noreply.github.com>
Fri, 25 Apr 2025 06:56:51 +0000 (23:56 -0700)
committershamoon <4887959+shamoon@users.noreply.github.com>
Wed, 2 Jul 2025 18:01:55 +0000 (11:01 -0700)
[ci skip]

src/documents/views.py
src/paperless/ai/chat.py

index cbac570b232a136bef0a0c13458e0473c3115993..a645709090e47b9b3fa1c4413002b1164896c094 100644 (file)
@@ -174,6 +174,7 @@ from documents.utils import get_boolean
 from paperless import version
 from paperless.ai.ai_classifier import get_ai_document_classification
 from paperless.ai.chat import chat_with_documents
+from paperless.ai.chat import chat_with_single_document
 from paperless.ai.matching import extract_unmatched_names
 from paperless.ai.matching import match_correspondents_by_name
 from paperless.ai.matching import match_document_types_by_name
@@ -1175,7 +1176,15 @@ class DocumentViewSet(
             return HttpResponseBadRequest("AI is required for this feature")
 
         question = request.data["q"]
-        result = chat_with_documents(question, request.user)
+        doc_id = request.data.get("document_id", None)
+        if doc_id:
+            document = Document.objects.get(id=doc_id)
+            if not has_perms_owner_aware(request.user, "view_document", document):
+                return HttpResponseForbidden("Insufficient permissions")
+
+            result = chat_with_single_document(document, question, request.user)
+        else:
+            result = chat_with_documents(question, request.user)
 
         return Response({"answer": result})
 
index eb485b64185c13b81e464f14263dfab2f4a2ebea..6e75884d99b0e56c3c29323c7a9a42afc52fc305 100644 (file)
@@ -1,10 +1,12 @@
 import logging
 
 from django.contrib.auth.models import User
+from llama_index.core import VectorStoreIndex
 from llama_index.core.query_engine import RetrieverQueryEngine
 
 from paperless.ai.client import AIClient
 from paperless.ai.indexing import get_document_retriever
+from paperless.ai.indexing import load_index
 
 logger = logging.getLogger("paperless.ai.chat")
 
@@ -22,3 +24,29 @@ def chat_with_documents(prompt: str, user: User) -> str:
     response = query_engine.query(prompt)
     logger.debug("Document chat response: %s", response)
     return str(response)
+
+
+def chat_with_single_document(document, question: str, user):
+    index = load_index()
+
+    # Filter only the node(s) belonging to this doc
+    nodes = [
+        node
+        for node in index.docstore.docs.values()
+        if node.metadata.get("document_id") == str(document.id)
+    ]
+
+    if not nodes:
+        raise Exception("This document is not indexed yet.")
+
+    local_index = VectorStoreIndex.from_documents(nodes)
+
+    client = AIClient()
+
+    engine = RetrieverQueryEngine.from_args(
+        retriever=local_index.as_retriever(similarity_top_k=3),
+        llm=client.llm,
+    )
+
+    response = engine.query(question)
+    return str(response)