Add Claude AI Telegram bot enhancement (Phase 6)
Some checks failed
Validate / Hassfest (push) Has been cancelled
Some checks failed
Validate / Hassfest (push) Has been cancelled
Integrate Claude AI into the notification system for intelligent conversational interactions and AI-powered captions. New modules: - ai/service.py: Claude API client with conversation history, caption generation, and album activity summarization - ai/telegram_webhook.py: Telegram webhook handler for incoming bot messages, routes to AI service for responses Features: - Conversational bot: users chat with the bot about albums - AI captions: intelligent notification messages based on album context (people, locations, dates) - enabled per target via "ai_captions" config flag - Album summaries: "what's new?" triggers AI-generated overview - /start command with welcome message - Webhook register/unregister endpoints Architecture: - Per-chat conversation history (in-memory, capped at 20 messages) - Graceful degradation: AI features completely disabled without IMMICH_WATCHER_ANTHROPIC_API_KEY env var (zero impact) - AI caption failure falls back to Jinja2 template rendering - Health endpoint reports ai_enabled status Config: IMMICH_WATCHER_ANTHROPIC_API_KEY, IMMICH_WATCHER_AI_MODEL, IMMICH_WATCHER_AI_MAX_TOKENS Server now has 45 API routes (was 42 after Phase 5). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -33,6 +33,7 @@ async def send_notification(
|
||||
target: NotificationTarget,
|
||||
event_data: dict[str, Any],
|
||||
template: MessageTemplate | None = None,
|
||||
use_ai_caption: bool = False,
|
||||
) -> dict[str, Any]:
|
||||
"""Send a notification to a target using event data.
|
||||
|
||||
@@ -40,13 +41,24 @@ async def send_notification(
|
||||
target: Notification destination (telegram or webhook)
|
||||
event_data: Album change event data (album_name, added_count, etc.)
|
||||
template: Optional message template (uses default if None)
|
||||
use_ai_caption: If True, generate caption with Claude AI instead of template
|
||||
"""
|
||||
template_body = template.body if template else DEFAULT_TEMPLATE
|
||||
try:
|
||||
message = render_template(template_body, event_data)
|
||||
except jinja2.TemplateError as e:
|
||||
_LOGGER.error("Template rendering failed: %s", e)
|
||||
message = f"Album changed: {event_data.get('album_name', 'unknown')}"
|
||||
message = None
|
||||
|
||||
# Try AI caption first if enabled
|
||||
if use_ai_caption:
|
||||
from ..ai.service import generate_caption, is_ai_enabled
|
||||
if is_ai_enabled():
|
||||
message = await generate_caption(event_data)
|
||||
|
||||
# Fall back to template rendering
|
||||
if message is None:
|
||||
template_body = template.body if template else DEFAULT_TEMPLATE
|
||||
try:
|
||||
message = render_template(template_body, event_data)
|
||||
except jinja2.TemplateError as e:
|
||||
_LOGGER.error("Template rendering failed: %s", e)
|
||||
message = f"Album changed: {event_data.get('album_name', 'unknown')}"
|
||||
|
||||
if target.type == "telegram":
|
||||
return await _send_telegram(target, message, event_data)
|
||||
|
||||
@@ -161,7 +161,8 @@ async def _check_album(
|
||||
template = await session.get(MessageTemplate, tracker.template_id)
|
||||
|
||||
try:
|
||||
await send_notification(target, event_data, template)
|
||||
use_ai = target.config.get("ai_captions", False)
|
||||
await send_notification(target, event_data, template, use_ai_caption=use_ai)
|
||||
except Exception:
|
||||
_LOGGER.exception("Failed to send notification to target %d", target_id)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user