From 7e466d1f71eb99b268d6d9b13493699965dc7a2c Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Mon, 10 Aug 2026 09:03:35 -0700 Subject: [PATCH] remote_ocr_mode config setting --- src-ui/src/app/data/paperless-config.ts | 16 +++++++++++ src/documents/tests/test_api_app_config.py | 1 + src/paperless/config.py | 5 ++++ ...pplicationconfiguration_remote_ocr_mode.py | 27 +++++++++++++++++++ src/paperless/models.py | 18 +++++++++++++ src/paperless/settings/__init__.py | 1 + 6 files changed, 68 insertions(+) create mode 100644 src/paperless/migrations/0015_applicationconfiguration_remote_ocr_mode.py diff --git a/src-ui/src/app/data/paperless-config.ts b/src-ui/src/app/data/paperless-config.ts index 575525f1b..92af2cec5 100644 --- a/src-ui/src/app/data/paperless-config.ts +++ b/src-ui/src/app/data/paperless-config.ts @@ -73,6 +73,11 @@ export const RemoteOCREngineConfig = { AZURE_AI: 'azureai', } +export const RemoteOCRModeConfig = { + ALWAYS: 'always', + WORKFLOW_ONLY: 'workflow_only', +} + export interface ConfigOption { key: string title: string @@ -217,6 +222,16 @@ export const PaperlessConfigOptions: ConfigOption[] = [ section: ConfigSection.RemoteOCR, note: $localize`Required when using the Azure AI engine.`, }, + { + key: 'remote_ocr_mode', + title: $localize`Remote OCR Mode`, + type: ConfigOptionType.Select, + choices: mapToItems(RemoteOCRModeConfig), + config_key: 'PAPERLESS_REMOTE_OCR_MODE', + category: ConfigCategory.OCR, + section: ConfigSection.RemoteOCR, + note: $localize`Which documents are sent to the remote engine. Use 'workflow_only' to keep remote OCR off unless a workflow enables it for a document.`, + }, { key: 'app_logo', title: $localize`Application Logo`, @@ -437,6 +452,7 @@ export interface PaperlessConfig extends ObjectWithId { remote_ocr_engine: string remote_ocr_api_key: string remote_ocr_endpoint: string + remote_ocr_mode: string ai_enabled: boolean llm_embedding_backend: string llm_embedding_model: string diff --git a/src/documents/tests/test_api_app_config.py b/src/documents/tests/test_api_app_config.py index d4cc4b6d2..2b9d56d32 100644 --- a/src/documents/tests/test_api_app_config.py +++ b/src/documents/tests/test_api_app_config.py @@ -75,6 +75,7 @@ class TestApiAppConfig(DirectoriesMixin, APITestCase): "remote_ocr_engine": None, "remote_ocr_api_key": None, "remote_ocr_endpoint": None, + "remote_ocr_mode": None, "ai_enabled": False, "llm_embedding_backend": None, "llm_embedding_model": None, diff --git a/src/paperless/config.py b/src/paperless/config.py index c3dcc3f15..f55c23bf7 100644 --- a/src/paperless/config.py +++ b/src/paperless/config.py @@ -9,6 +9,7 @@ from paperless.models import CleanChoices from paperless.models import ColorConvertChoices from paperless.models import ModeChoices from paperless.models import OutputTypeChoices +from paperless.models import RemoteOCRMode @dataclasses.dataclass @@ -194,6 +195,7 @@ class RemoteOCRConfig(BaseConfig): remote_ocr_engine: str | None = dataclasses.field(init=False) remote_ocr_api_key: str | None = dataclasses.field(init=False) remote_ocr_endpoint: str | None = dataclasses.field(init=False) + remote_ocr_mode: RemoteOCRMode = dataclasses.field(init=False) def __post_init__(self) -> None: app_config = self._get_config_instance() @@ -207,6 +209,9 @@ class RemoteOCRConfig(BaseConfig): self.remote_ocr_endpoint = ( app_config.remote_ocr_endpoint or settings.REMOTE_OCR_ENDPOINT ) + self.remote_ocr_mode = app_config.remote_ocr_mode or RemoteOCRMode( + settings.REMOTE_OCR_MODE, + ) @dataclasses.dataclass diff --git a/src/paperless/migrations/0015_applicationconfiguration_remote_ocr_mode.py b/src/paperless/migrations/0015_applicationconfiguration_remote_ocr_mode.py new file mode 100644 index 000000000..16b38e086 --- /dev/null +++ b/src/paperless/migrations/0015_applicationconfiguration_remote_ocr_mode.py @@ -0,0 +1,27 @@ +# Generated by Django 5.2.16 on 2026-08-10 15:43 + +from django.db import migrations +from django.db import models + + +class Migration(migrations.Migration): + dependencies = [ + ("paperless", "0014_applicationconfiguration_remote_ocr_api_key_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="applicationconfiguration", + name="remote_ocr_mode", + field=models.CharField( + blank=True, + choices=[ + ("always", "All supported documents"), + ("workflow_only", "Only when a workflow enables it"), + ], + max_length=32, + null=True, + verbose_name="Sets which documents are sent to the remote OCR engine", + ), + ), + ] diff --git a/src/paperless/models.py b/src/paperless/models.py index 7c230daba..73eaabfee 100644 --- a/src/paperless/models.py +++ b/src/paperless/models.py @@ -82,6 +82,15 @@ class RemoteOCREngine(models.TextChoices): AZURE_AI = ("azureai", _("Azure AI Document Intelligence")) +class RemoteOCRMode(models.TextChoices): + """ + Matches to PAPERLESS_REMOTE_OCR_MODE + """ + + ALWAYS = ("always", _("All supported documents")) + WORKFLOW_ONLY = ("workflow_only", _("Only when a workflow enables it")) + + class LLMEmbeddingBackend(models.TextChoices): OPENAI_LIKE = ("openai-like", _("OpenAI-compatible")) HUGGINGFACE = ("huggingface", _("Huggingface")) @@ -323,6 +332,15 @@ class ApplicationConfiguration(AbstractSingletonModel): max_length=256, ) + # PAPERLESS_REMOTE_OCR_MODE + remote_ocr_mode = models.CharField( + verbose_name=_("Sets which documents are sent to the remote OCR engine"), + blank=True, + null=True, + max_length=32, + choices=RemoteOCRMode.choices, + ) + """ AI related settings """ diff --git a/src/paperless/settings/__init__.py b/src/paperless/settings/__init__.py index 55aac5a91..732f330e0 100644 --- a/src/paperless/settings/__init__.py +++ b/src/paperless/settings/__init__.py @@ -1197,6 +1197,7 @@ WEBHOOKS_ALLOW_INTERNAL_REQUESTS = get_bool_from_env( REMOTE_OCR_ENGINE = os.getenv("PAPERLESS_REMOTE_OCR_ENGINE") REMOTE_OCR_API_KEY = os.getenv("PAPERLESS_REMOTE_OCR_API_KEY") REMOTE_OCR_ENDPOINT = os.getenv("PAPERLESS_REMOTE_OCR_ENDPOINT") +REMOTE_OCR_MODE = os.getenv("PAPERLESS_REMOTE_OCR_MODE", "always") ################################################################################ # AI Settings #