feat(03-04): retire flat-file settings; wire per-user AI config via DB lookup
- config.py: Remove SETTINGS_FILE, DEFAULT_SYSTEM_PROMPT, DEFAULT_SETTINGS constants; add system_prompt, default_ai_provider, default_ai_model to Settings - services/classifier.py: Add _DEFAULT_SYSTEM_PROMPT module constant; classify_document and suggest_topics_for_document accept ai_provider/ai_model kwargs; no longer calls storage.load_settings() — uses app_settings defaults with DB-supplied overrides (D-14, D-15) - services/storage.py: Delete load_settings, save_settings, mask_api_key, settings_masked; remove from __all__; remove import copy, json, DEFAULT_SETTINGS, SETTINGS_FILE (D-12) - tasks/document_tasks.py: _run resolves user.ai_provider/ai_model via session.get(User, doc.user_id) and passes through to classifier; task signature unchanged (T-03-19) - api/settings.py: Deleted — /api/settings endpoint removed (D-12) - main.py: Remove settings_router import and include_router call - tests/test_settings.py: Replace all tests with test_settings_endpoint_removed (404, green) - tests/test_classifier.py: Implement test_per_user_provider, test_celery_task_uses_user_provider, test_default_provider_fallback; remove xfail markers (DOC-03, DOC-05)
This commit is contained in:
+5
-39
@@ -1,5 +1,3 @@
|
||||
from pathlib import Path
|
||||
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
|
||||
@@ -13,9 +11,6 @@ class Settings(BaseSettings):
|
||||
env_list_separator=",",
|
||||
)
|
||||
|
||||
# Data directory — used only for the flat-file settings.json path (Phase 1)
|
||||
data_dir: str = "/app/data"
|
||||
|
||||
# PostgreSQL
|
||||
database_url: str = "postgresql+psycopg://docuvault_app:changeme_app@postgres:5432/docuvault"
|
||||
database_migrate_url: str = "postgresql+psycopg://docuvault_migrate:changeme_migrate@postgres:5432/docuvault"
|
||||
@@ -56,39 +51,10 @@ class Settings(BaseSettings):
|
||||
# Frontend URL — used to build password reset links (D-02, D-03)
|
||||
frontend_url: str = "http://localhost:5173"
|
||||
|
||||
# AI classification defaults (Phase 3 — D-13, D-15)
|
||||
system_prompt: str = "" # SYSTEM_PROMPT env var; hardcoded fallback lives in classifier.py
|
||||
default_ai_provider: str = "ollama" # DEFAULT_AI_PROVIDER env var
|
||||
default_ai_model: str = "llama3.2" # DEFAULT_AI_MODEL env var
|
||||
|
||||
|
||||
settings = Settings()
|
||||
|
||||
# SETTINGS_FILE: still flat-file in Phase 1; migrates to users.ai_provider in Phase 2
|
||||
SETTINGS_FILE = Path(settings.data_dir) / "settings.json"
|
||||
|
||||
DEFAULT_SYSTEM_PROMPT = """You are a document classification assistant. When given a document's text content and a list of existing topics, you must:
|
||||
1. Assign the document to one or more relevant topics from the list.
|
||||
2. If no existing topics fit well, suggest new topic names.
|
||||
Return ONLY valid JSON in this exact format, with no additional text or explanation:
|
||||
{"assigned_topics": ["topic1"], "new_topic_suggestions": ["new topic name"]}
|
||||
If the document fits no topics and you have no suggestions, return: {"assigned_topics": [], "new_topic_suggestions": []}"""
|
||||
|
||||
DEFAULT_SETTINGS = {
|
||||
"system_prompt": DEFAULT_SYSTEM_PROMPT,
|
||||
"active_provider": "lmstudio",
|
||||
"providers": {
|
||||
"anthropic": {
|
||||
"api_key": "",
|
||||
"model": "claude-sonnet-4-6"
|
||||
},
|
||||
"openai": {
|
||||
"api_key": "",
|
||||
"model": "gpt-4o",
|
||||
"base_url": None
|
||||
},
|
||||
"ollama": {
|
||||
"base_url": "http://host.docker.internal:11434",
|
||||
"model": "llama3.2"
|
||||
},
|
||||
"lmstudio": {
|
||||
"base_url": "http://host.docker.internal:1234",
|
||||
"model": "gemma-4-e4b-it"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user