diff --git a/README.md b/README.md index f55aefc..e8e9e95 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,14 @@ Station Announcer is a small Flask app that keeps your Immich library and Mastod IMMICH_API_URL=https://photos.4angle.com/ IMMICH_API_KEY=your-immich-api-key OPENAI_API_KEY=your-openai-api-key + OPENAI_MODEL=gpt-4o-mini MASTODON_BASE_URL=http://localhost:3000 MASTODON_ACCESS_TOKEN=your-mastodon-token ``` + `OPENAI_MODEL` is optional; set it to override the default model used for both + alt-text generation and copy refinement. + 2. Install dependencies and run the development server: ```bash diff --git a/station_announcer/__init__.py b/station_announcer/__init__.py index f05ada8..ace6bfc 100644 --- a/station_announcer/__init__.py +++ b/station_announcer/__init__.py @@ -8,7 +8,7 @@ from flask import Flask sys.path.append("/home/edward/src/2024/UniAuth") # isort:skip from .cache import AltTextCache -from .config import load_settings +from .config import DEFAULT_OPENAI_MODEL, load_settings from .immich import ImmichClient from .mastodon import MastodonClient from .openai_client import AltTextGenerator @@ -60,7 +60,7 @@ def create_app() -> Flask: app.alt_text_cache = AltTextCache(db_path) app.alt_text_generator = AltTextGenerator( api_key=app.config["OPENAI_API_KEY"], - model=app.config.get("OPENAI_MODEL", "gpt-4o-mini"), + model=app.config.get("OPENAI_MODEL", DEFAULT_OPENAI_MODEL), ) mastodon_token = app.config.get("MASTODON_ACCESS_TOKEN") if mastodon_token: diff --git a/station_announcer/config.py b/station_announcer/config.py index 9abb2b2..dc82c59 100644 --- a/station_announcer/config.py +++ b/station_announcer/config.py @@ -8,6 +8,7 @@ from typing import Dict from dotenv import load_dotenv DEFAULT_IMMICH_URL = "https://photos.4angle.com/" +DEFAULT_OPENAI_MODEL = "gpt-4o-mini" class ConfigError(RuntimeError): @@ -26,7 +27,7 @@ def load_settings() -> Dict[str, str]: "IMMICH_API_KEY": os.getenv("IMMICH_API_KEY", ""), "OPENAI_API_KEY": os.getenv("OPENAI_API_KEY", ""), "RECENT_DAYS": int(os.getenv("RECENT_DAYS", "3")), - "OPENAI_MODEL": os.getenv("OPENAI_MODEL", "gpt-4o-mini"), + "OPENAI_MODEL": os.getenv("OPENAI_MODEL", DEFAULT_OPENAI_MODEL), "STATION_DB": db_path, "SECRET_KEY": os.getenv("SECRET_KEY", ""), "MASTODON_BASE_URL": os.getenv( diff --git a/station_announcer/openai_client.py b/station_announcer/openai_client.py index 3e68a28..4474f6b 100644 --- a/station_announcer/openai_client.py +++ b/station_announcer/openai_client.py @@ -5,6 +5,7 @@ from __future__ import annotations import requests import typing +from .config import DEFAULT_OPENAI_MODEL class OpenAIClientError(RuntimeError): """Raised when the OpenAI API cannot fulfill a request.""" @@ -21,7 +22,7 @@ class TextImprovementError(OpenAIClientError): class AltTextGenerator: """Request alt text from a GPT compatible OpenAI endpoint.""" - def __init__(self, api_key: str, model: str = "gpt-4.1") -> None: + def __init__(self, api_key: str, model: str = DEFAULT_OPENAI_MODEL) -> None: if not api_key: raise ValueError("OPENAI_API_KEY is required") self.model = model @@ -106,6 +107,7 @@ class AltTextGenerator: instructions: str | None = None, hashtag_counts: str | None = None, thread_context: list[str] | None = None, + alt_texts: list[str] | None = None, ) -> str: if not draft_text or not draft_text.strip(): raise TextImprovementError("Post text cannot be empty") @@ -150,6 +152,16 @@ class AltTextGenerator: f"{user_content}\n\nHashtag history (tag with past uses):\n" f"{hashtag_counts.strip()}" ) + if alt_texts: + cleaned_alt_texts = [entry.strip() for entry in alt_texts if entry.strip()] + if cleaned_alt_texts: + alt_text_block = "\n".join( + f"{index + 1}. {value}" + for index, value in enumerate(cleaned_alt_texts) + ) + user_content = ( + f"{user_content}\n\nAlt text for attached images:\n{alt_text_block}" + ) payload = { "model": self.model, diff --git a/station_announcer/routes.py b/station_announcer/routes.py index 948862d..c38c3f0 100644 --- a/station_announcer/routes.py +++ b/station_announcer/routes.py @@ -397,9 +397,18 @@ def compose_draft(): context_entries.append(latest_text) if context_entries: thread_context = context_entries + alt_texts = [ + entry["alt_text"].strip() + for entry in asset_entries + if entry.get("alt_text") + ] try: post_text = generator.improve_post_text( - post_text, instructions, hashtag_counts, thread_context + post_text, + instructions, + hashtag_counts, + thread_context, + alt_texts, ) flash("Post refined with ChatGPT.") except TextImprovementError as exc: