feat(07-02): singleton OpenAIProvider + GenericOpenAIProvider + MAX_AI_CHARS removal

- openai_provider.py: singleton self._client=AsyncOpenAI(...) in __init__ (D-07),
  _truncate() 60/40 smart truncation (D-13), removed MAX_AI_CHARS constant,
  changed __init__ signature to include context_chars, removed _client() method
- generic_openai_provider.py: new class, subclasses OpenAIProvider, conditional
  response_format={"type":"json_object"} on supports_json_mode flag (D-01/D-02),
  imports parse_classification + parse_suggestions from ai.utils (D-02 contract)
- ollama_provider.py: added context_chars kwarg with default 8000, passes through
- lmstudio_provider.py: added context_chars kwarg with default 8000, passes through
- classifier.py: removed MAX_AI_CHARS constant and text[:MAX_AI_CHARS] slices;
  truncation now handled inside each provider via _truncate()
- requirements.txt: bumped anthropic floor to >=0.95.0 (D-03 output_config support)
This commit is contained in:
curo1305
2026-06-04 18:58:19 +02:00
parent beb5b5e49d
commit 02bcbb9143
6 changed files with 152 additions and 20 deletions
+2 -4
View File
@@ -25,8 +25,6 @@ from db.models import Document
from services import storage
from ai import get_provider
MAX_AI_CHARS = 8_000
_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.
@@ -82,7 +80,7 @@ async def classify_document(
topic_names = [t["name"] for t in all_topics]
text = meta.get("extracted_text", "")
result = await provider.classify(text[:MAX_AI_CHARS], topic_names, system_prompt)
result = await provider.classify(text, topic_names, system_prompt)
# Collect all topic names to persist (assigned + suggested)
all_new_names = set(result.suggested_new_topics) | set(result.topics)
@@ -124,4 +122,4 @@ async def suggest_topics_for_document(
}
provider = get_provider(_settings)
text = meta.get("extracted_text", "")
return await provider.suggest_topics(text[:MAX_AI_CHARS], system_prompt)
return await provider.suggest_topics(text, system_prompt)