a548266461
- Add backend/ai/utils.py — parse_classification, parse_suggestions, strip_code_fences shared by all AI providers; removes duplicated private functions from anthropic_provider.py and openai_provider.py - Add backend/deps/utils.py — get_client_ip, parse_uuid request-parsing helpers; removes local _ip() variants from admin.py, auth.py, shares.py, folders.py - Add backend/storage/exceptions.py — canonical CloudConnectionError definition; all routers and backends import from here instead of redefining - Move validate_password_strength to backend/services/auth.py; removes duplicated _validate_password_strength from admin.py and auth.py Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
70 lines
2.1 KiB
Python
70 lines
2.1 KiB
Python
import anthropic
|
|
from ai.base import AIProvider, ClassificationResult
|
|
from ai.utils import parse_classification, parse_suggestions
|
|
|
|
MAX_AI_CHARS = 8_000
|
|
|
|
|
|
class AnthropicProvider(AIProvider):
|
|
def __init__(self, api_key: str, model: str = "claude-sonnet-4-6"):
|
|
self._api_key = api_key
|
|
self._model = model
|
|
|
|
def _client(self):
|
|
return anthropic.AsyncAnthropic(api_key=self._api_key)
|
|
|
|
async def classify(
|
|
self,
|
|
document_text: str,
|
|
existing_topics: list[str],
|
|
system_prompt: str,
|
|
) -> ClassificationResult:
|
|
topics_str = ", ".join(existing_topics) if existing_topics else "(none yet)"
|
|
user_msg = (
|
|
f"Existing topics: [{topics_str}]\n\n"
|
|
f"Document text:\n{document_text[:MAX_AI_CHARS]}"
|
|
)
|
|
client = self._client()
|
|
response = await client.messages.create(
|
|
model=self._model,
|
|
max_tokens=1024,
|
|
system=system_prompt,
|
|
messages=[{"role": "user", "content": user_msg}],
|
|
)
|
|
raw = response.content[0].text
|
|
return parse_classification(raw)
|
|
|
|
async def suggest_topics(
|
|
self,
|
|
document_text: str,
|
|
system_prompt: str,
|
|
) -> list[str]:
|
|
user_msg = (
|
|
"Suggest 3-5 topic names for this document. "
|
|
"Return ONLY valid JSON: {\"suggested_topics\": [\"topic1\", \"topic2\"]}\n\n"
|
|
f"Document text:\n{document_text[:MAX_AI_CHARS]}"
|
|
)
|
|
client = self._client()
|
|
response = await client.messages.create(
|
|
model=self._model,
|
|
max_tokens=256,
|
|
system=system_prompt,
|
|
messages=[{"role": "user", "content": user_msg}],
|
|
)
|
|
raw = response.content[0].text
|
|
return parse_suggestions(raw)
|
|
|
|
async def health_check(self) -> bool:
|
|
try:
|
|
client = self._client()
|
|
await client.messages.create(
|
|
model=self._model,
|
|
max_tokens=5,
|
|
messages=[{"role": "user", "content": "ping"}],
|
|
)
|
|
return True
|
|
except Exception:
|
|
return False
|
|
|
|
|