mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-11-10 08:21:01 +00:00
Enhancement: AI LLM chunk size and context window config (#12891)
This commit is contained in:
1 parent
bb860a5834
commit
f6c865bf47
15 files changed
+318
-36
No files matched your search
@@ -11,6 +11,7 @@ from llama_index.core.base.embeddings.base import BaseEmbedding
|
||||
from documents.models import Document
|
||||
from documents.models import PaperlessTask
|
||||
from documents.tests.factories import PaperlessTaskFactory
|
||||
from paperless.models import ApplicationConfiguration
|
||||
from paperless_ai import indexing
|
||||
|
||||
|
||||
@@ -81,20 +82,32 @@ def test_build_document_node_excludes_metadata_from_embedding(real_document) ->
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_build_document_node_uses_rag_chunk_settings(real_document) -> None:
|
||||
app_config, _ = ApplicationConfiguration.objects.get_or_create()
|
||||
app_config.llm_embedding_chunk_size = 512
|
||||
app_config.save()
|
||||
|
||||
with patch("llama_index.core.node_parser.SimpleNodeParser") as mock_parser:
|
||||
mock_parser.return_value.get_nodes_from_documents.return_value = []
|
||||
|
||||
indexing.build_document_node(real_document)
|
||||
|
||||
mock_parser.assert_called_once_with(chunk_size=1024, chunk_overlap=200)
|
||||
mock_parser.assert_called_once_with(chunk_size=512, chunk_overlap=200)
|
||||
|
||||
|
||||
def test_get_rag_chunk_overlap_clamps_to_chunk_size() -> None:
|
||||
with (
|
||||
patch("paperless_ai.indexing.RAG_CHUNK_SIZE", 64),
|
||||
patch("paperless_ai.indexing.RAG_CHUNK_OVERLAP", 128),
|
||||
):
|
||||
assert indexing.get_rag_chunk_overlap() == 63
|
||||
with patch("paperless_ai.indexing.RAG_CHUNK_OVERLAP", 128):
|
||||
assert indexing.get_rag_chunk_overlap(64) == 63
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_get_rag_prompt_helper_uses_context_setting() -> None:
|
||||
app_config, _ = ApplicationConfiguration.objects.get_or_create()
|
||||
app_config.llm_context_size = 4096
|
||||
app_config.save()
|
||||
|
||||
prompt_helper = indexing.get_rag_prompt_helper()
|
||||
|
||||
assert prompt_helper.context_window == 4096
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -103,13 +116,22 @@ def test_update_llm_index(
|
||||
real_document,
|
||||
mock_embed_model,
|
||||
) -> None:
|
||||
with patch("documents.models.Document.objects.all") as mock_all:
|
||||
mock_config = MagicMock()
|
||||
mock_config.llm_embedding_chunk_size = 512
|
||||
with (
|
||||
patch("documents.models.Document.objects.all") as mock_all,
|
||||
patch("paperless_ai.indexing.AIConfig", return_value=mock_config) as ai_config,
|
||||
patch("paperless_ai.indexing.build_document_node") as build_document_node,
|
||||
):
|
||||
mock_queryset = MagicMock()
|
||||
mock_queryset.exists.return_value = True
|
||||
mock_queryset.__iter__.return_value = iter([real_document])
|
||||
mock_all.return_value = mock_queryset
|
||||
build_document_node.return_value = []
|
||||
indexing.update_llm_index(rebuild=True)
|
||||
|
||||
ai_config.assert_called_once()
|
||||
build_document_node.assert_called_once_with(real_document, chunk_size=512)
|
||||
assert any(temp_llm_index_dir.glob("*.json"))
|
||||
|
||||
|
||||
|
||||
@@ -143,6 +143,7 @@ def test_document_filtered_retriever_handles_empty_faiss_index() -> None:
|
||||
mock_index.vector_store.query.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_stream_chat_with_one_document_retrieval(
|
||||
mock_document,
|
||||
patch_embed_nodes,
|
||||
@@ -186,6 +187,7 @@ def test_stream_chat_with_one_document_retrieval(
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_stream_chat_with_multiple_documents_retrieval(patch_embed_nodes) -> None:
|
||||
with (
|
||||
patch("paperless_ai.chat.AIClient") as mock_client_cls,
|
||||
|
||||
@@ -15,6 +15,7 @@ def mock_ai_config():
|
||||
with patch("paperless_ai.client.AIConfig") as MockAIConfig:
|
||||
mock_config = MagicMock()
|
||||
mock_config.llm_allow_internal_endpoints = True
|
||||
mock_config.llm_context_size = 8192
|
||||
MockAIConfig.return_value = mock_config
|
||||
yield mock_config
|
||||
|
||||
@@ -41,6 +42,7 @@ def test_get_llm_ollama(mock_ai_config, mock_ollama_llm):
|
||||
mock_ollama_llm.assert_called_once_with(
|
||||
model="test_model",
|
||||
base_url="http://test-url",
|
||||
context_window=8192,
|
||||
request_timeout=120,
|
||||
system_prompt=LLM_SYSTEM_PROMPT,
|
||||
client=ANY,
|
||||
|
||||
@@ -19,6 +19,7 @@ def mock_ai_config():
|
||||
with patch("paperless_ai.embedding.AIConfig") as MockAIConfig:
|
||||
MockAIConfig.return_value.llm_embedding_endpoint = None
|
||||
MockAIConfig.return_value.llm_allow_internal_endpoints = True
|
||||
MockAIConfig.return_value.llm_context_size = 8192
|
||||
yield MockAIConfig
|
||||
|
||||
|
||||
@@ -140,6 +141,7 @@ def test_get_embedding_model_ollama(mock_ai_config):
|
||||
MockOllamaEmbedding.assert_called_once_with(
|
||||
model_name="embeddinggemma",
|
||||
base_url="http://test-url",
|
||||
ollama_additional_kwargs={"num_ctx": 8192},
|
||||
)
|
||||
assert model == MockOllamaEmbedding.return_value
|
||||
|
||||
@@ -157,6 +159,7 @@ def test_get_embedding_model_ollama_prefers_embedding_endpoint(mock_ai_config):
|
||||
MockOllamaEmbedding.assert_called_once_with(
|
||||
model_name="embeddinggemma",
|
||||
base_url="http://embedding-url",
|
||||
ollama_additional_kwargs={"num_ctx": 8192},
|
||||
)
|
||||
assert model == MockOllamaEmbedding.return_value
|
||||
|
||||
|
||||
Reference in new issue
Block a user