Add Claude AI Telegram bot enhancement (Phase 6)
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:
2026-03-19 14:38:51 +03:00
parent 43f83acda9
commit 88ffd5d077
10 changed files with 507 additions and 9 deletions

View File

@@ -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)