mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-10-03 23:00:31 +00:00
Enhancement: support separate embedding API key (#14067)
Co-authored-by: Claude Code <noreply@anthropic.com> Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
This commit is contained in:
co-authored by
Claude Code
shamoon
parent
793459b416
commit
e34eda07bb
@@ -245,6 +245,7 @@ class AIConfig(BaseConfig):
|
||||
ai_enabled: bool = dataclasses.field(init=False)
|
||||
llm_embedding_backend: str = dataclasses.field(init=False)
|
||||
llm_embedding_model: str = dataclasses.field(init=False)
|
||||
llm_embedding_api_key: str = dataclasses.field(init=False)
|
||||
llm_embedding_endpoint: str = dataclasses.field(init=False)
|
||||
llm_embedding_chunk_size: int = dataclasses.field(init=False)
|
||||
llm_context_size: int = dataclasses.field(init=False)
|
||||
@@ -271,6 +272,9 @@ class AIConfig(BaseConfig):
|
||||
self.llm_embedding_model = (
|
||||
app_config.llm_embedding_model or settings.LLM_EMBEDDING_MODEL
|
||||
)
|
||||
self.llm_embedding_api_key = (
|
||||
app_config.llm_embedding_api_key or settings.LLM_EMBEDDING_API_KEY
|
||||
)
|
||||
self.llm_embedding_endpoint = (
|
||||
app_config.llm_embedding_endpoint or settings.LLM_EMBEDDING_ENDPOINT
|
||||
)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 5.2.16 on 2026-09-11 09:32
|
||||
|
||||
from django.db import migrations
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("paperless", "0016_alter_applicationconfiguration_ai_enabled"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="applicationconfiguration",
|
||||
name="llm_embedding_api_key",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
max_length=1024,
|
||||
null=True,
|
||||
verbose_name="Sets the LLM embedding API key",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -365,6 +365,13 @@ class ApplicationConfiguration(AbstractSingletonModel):
|
||||
max_length=128,
|
||||
)
|
||||
|
||||
llm_embedding_api_key = models.CharField(
|
||||
verbose_name=_("Sets the LLM embedding API key"),
|
||||
blank=True,
|
||||
null=True,
|
||||
max_length=1024,
|
||||
)
|
||||
|
||||
llm_embedding_endpoint = models.CharField(
|
||||
verbose_name=_("Sets the LLM embedding endpoint, optional"),
|
||||
blank=True,
|
||||
|
||||
@@ -216,6 +216,11 @@ class ApplicationConfigurationSerializer(
|
||||
externally_configured_variables = serializers.SerializerMethodField()
|
||||
user_args = serializers.JSONField(binary=True, allow_null=True)
|
||||
barcode_tag_mapping = serializers.JSONField(binary=True, allow_null=True)
|
||||
llm_embedding_api_key = ObfuscatedPasswordField(
|
||||
required=False,
|
||||
allow_null=True,
|
||||
max_length=1024,
|
||||
)
|
||||
llm_api_key = ObfuscatedPasswordField(
|
||||
required=False,
|
||||
allow_null=True,
|
||||
@@ -227,7 +232,11 @@ class ApplicationConfigurationSerializer(
|
||||
max_length=1024,
|
||||
)
|
||||
|
||||
OBFUSCATED_FIELDS = ("llm_api_key", "remote_ocr_api_key")
|
||||
OBFUSCATED_FIELDS = (
|
||||
"llm_embedding_api_key",
|
||||
"llm_api_key",
|
||||
"remote_ocr_api_key",
|
||||
)
|
||||
|
||||
def get_externally_configured_variables(
|
||||
self,
|
||||
|
||||
@@ -1236,6 +1236,7 @@ LLM_EMBEDDING_BACKEND = get_choice_from_env(
|
||||
{"huggingface", "openai-like", "ollama"},
|
||||
)
|
||||
LLM_EMBEDDING_MODEL = os.getenv("PAPERLESS_AI_LLM_EMBEDDING_MODEL")
|
||||
LLM_EMBEDDING_API_KEY = os.getenv("PAPERLESS_AI_LLM_EMBEDDING_API_KEY")
|
||||
LLM_EMBEDDING_ENDPOINT = os.getenv("PAPERLESS_AI_LLM_EMBEDDING_ENDPOINT")
|
||||
LLM_EMBEDDING_CHUNK_SIZE = get_int_from_env(
|
||||
"PAPERLESS_AI_LLM_EMBEDDING_CHUNK_SIZE",
|
||||
|
||||
@@ -30,3 +30,27 @@ class TestBooleanConfigPrecedence(TestCase):
|
||||
config.save()
|
||||
|
||||
self.assertTrue(AIConfig().ai_enabled)
|
||||
|
||||
|
||||
class TestAIConfigPrecedence(TestCase):
|
||||
@override_settings(LLM_EMBEDDING_API_KEY="environment-embedding-key")
|
||||
def test_database_embedding_api_key_overrides_environment_setting(self) -> None:
|
||||
config, _ = ApplicationConfiguration.objects.get_or_create()
|
||||
config.llm_embedding_api_key = "database-embedding-key"
|
||||
config.save()
|
||||
|
||||
self.assertEqual(
|
||||
AIConfig().llm_embedding_api_key,
|
||||
"database-embedding-key",
|
||||
)
|
||||
|
||||
@override_settings(LLM_EMBEDDING_API_KEY="environment-embedding-key")
|
||||
def test_null_embedding_api_key_uses_environment_setting(self) -> None:
|
||||
config, _ = ApplicationConfiguration.objects.get_or_create()
|
||||
config.llm_embedding_api_key = None
|
||||
config.save()
|
||||
|
||||
self.assertEqual(
|
||||
AIConfig().llm_embedding_api_key,
|
||||
"environment-embedding-key",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user