Add historical hashtags
This commit is contained in:
parent
5d8b0ecc2d
commit
08618ee9a9
|
|
@ -14,6 +14,14 @@ from .mastodon import MastodonClient
|
||||||
from .openai_client import AltTextGenerator
|
from .openai_client import AltTextGenerator
|
||||||
|
|
||||||
|
|
||||||
|
def _load_hashtag_counts(path: Path) -> str | None:
|
||||||
|
"""Return newline-delimited hashtag counts formatted for prompts."""
|
||||||
|
try:
|
||||||
|
return path.read_text()
|
||||||
|
except FileNotFoundError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def create_app() -> Flask:
|
def create_app() -> Flask:
|
||||||
"""Create and configure the Flask application."""
|
"""Create and configure the Flask application."""
|
||||||
package_path = Path(__file__).resolve().parent
|
package_path = Path(__file__).resolve().parent
|
||||||
|
|
@ -27,6 +35,10 @@ def create_app() -> Flask:
|
||||||
settings = load_settings()
|
settings = load_settings()
|
||||||
app.config.update(settings)
|
app.config.update(settings)
|
||||||
|
|
||||||
|
hashtag_counts = _load_hashtag_counts(project_root / "hash_tag_counts")
|
||||||
|
if hashtag_counts:
|
||||||
|
app.config["HASHTAG_COUNTS_TEXT"] = hashtag_counts
|
||||||
|
|
||||||
secret_key = app.config.get("SECRET_KEY") or "dev-secret-key"
|
secret_key = app.config.get("SECRET_KEY") or "dev-secret-key"
|
||||||
app.config["SECRET_KEY"] = secret_key
|
app.config["SECRET_KEY"] = secret_key
|
||||||
app.config["UNIAUTH_URL"] = "https://edwardbetts.com/UniAuth"
|
app.config["UNIAUTH_URL"] = "https://edwardbetts.com/UniAuth"
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ class TextImprovementError(OpenAIClientError):
|
||||||
class AltTextGenerator:
|
class AltTextGenerator:
|
||||||
"""Request alt text from a GPT-4o compatible OpenAI endpoint."""
|
"""Request alt text from a GPT-4o compatible OpenAI endpoint."""
|
||||||
|
|
||||||
def __init__(self, api_key: str, model: str = "gpt-4o-mini") -> None:
|
def __init__(self, api_key: str, model: str = "gpt-4.1") -> None:
|
||||||
if not api_key:
|
if not api_key:
|
||||||
raise ValueError("OPENAI_API_KEY is required")
|
raise ValueError("OPENAI_API_KEY is required")
|
||||||
self.model = model
|
self.model = model
|
||||||
|
|
@ -102,20 +102,36 @@ class AltTextGenerator:
|
||||||
return content_text.strip()
|
return content_text.strip()
|
||||||
|
|
||||||
def improve_post_text(
|
def improve_post_text(
|
||||||
self, draft_text: str, instructions: Optional[str] = None
|
self,
|
||||||
|
draft_text: str,
|
||||||
|
instructions: Optional[str] = None,
|
||||||
|
hashtag_counts: Optional[str] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
if not draft_text or not draft_text.strip():
|
if not draft_text or not draft_text.strip():
|
||||||
raise TextImprovementError("Post text cannot be empty")
|
raise TextImprovementError("Post text cannot be empty")
|
||||||
|
|
||||||
prompt_parts = [
|
prompt_parts = [
|
||||||
"You review Mastodon drafts and rewrite them in UK English.",
|
"You review Mastodon drafts and improve them. Use UK English spelling.",
|
||||||
"Keep the tone warm, accessible, and descriptive without exaggeration.",
|
"Keep the tone warm, accessible, and descriptive without exaggeration.",
|
||||||
"Ensure clarity, fix spelling or grammar, and keep content suitable for social media.",
|
"Ensure clarity, fix spelling or grammar, and keep content suitable for social media.",
|
||||||
|
"Don't add #TravelVibes if I'm at home in Bristol, okay to add if setting off on a trip.",
|
||||||
|
"Don't add #BetterByRail if not on a rail journey, equally don't remove it if present.",
|
||||||
|
"Always format hashtags in CamelCase (e.g. #BetterByRail).",
|
||||||
]
|
]
|
||||||
if instructions:
|
if instructions:
|
||||||
prompt_parts.append(f"Additional instructions: {instructions.strip()}")
|
prompt_parts.append(f"Additional instructions: {instructions.strip()}")
|
||||||
|
if hashtag_counts:
|
||||||
|
prompt_parts.append(
|
||||||
|
"When you add hashtags, prefer the ones from my history below, "
|
||||||
|
"but feel free to invent new ones."
|
||||||
|
)
|
||||||
prompt_parts.append("Return only the improved post text.")
|
prompt_parts.append("Return only the improved post text.")
|
||||||
user_content = f"Draft post:\\n{draft_text.strip()}"
|
user_content = f"Draft post:\\n{draft_text.strip()}"
|
||||||
|
if hashtag_counts:
|
||||||
|
user_content = (
|
||||||
|
f"{user_content}\n\nHashtag history (tag with past uses):\n"
|
||||||
|
f"{hashtag_counts.strip()}"
|
||||||
|
)
|
||||||
|
|
||||||
payload = {
|
payload = {
|
||||||
"model": self.model,
|
"model": self.model,
|
||||||
|
|
|
||||||
|
|
@ -260,6 +260,7 @@ def compose_draft():
|
||||||
immich_client = current_app.immich_client
|
immich_client = current_app.immich_client
|
||||||
alt_cache = current_app.alt_text_cache
|
alt_cache = current_app.alt_text_cache
|
||||||
generator = current_app.alt_text_generator
|
generator = current_app.alt_text_generator
|
||||||
|
hashtag_counts = current_app.config.get("HASHTAG_COUNTS_TEXT")
|
||||||
|
|
||||||
error_message = None
|
error_message = None
|
||||||
post_text = ""
|
post_text = ""
|
||||||
|
|
@ -351,7 +352,9 @@ def compose_draft():
|
||||||
action = request.form.get("action")
|
action = request.form.get("action")
|
||||||
if action == "refine":
|
if action == "refine":
|
||||||
try:
|
try:
|
||||||
post_text = generator.improve_post_text(post_text, instructions)
|
post_text = generator.improve_post_text(
|
||||||
|
post_text, instructions, hashtag_counts
|
||||||
|
)
|
||||||
flash("Post refined with ChatGPT.")
|
flash("Post refined with ChatGPT.")
|
||||||
except TextImprovementError as exc:
|
except TextImprovementError as exc:
|
||||||
error_message = str(exc)
|
error_message = str(exc)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue