feat(api): add memoir image prompt settings and optimization service

Made-with: Cursor
This commit is contained in:
Kevin
2026-03-10 16:00:25 +08:00
parent 5b51d104b4
commit f8283b398e
3 changed files with 147 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
import json
from typing import Any, Optional
from .settings import MemoirImageSettings
class MemoirImagePromptService:
CATEGORY_STYLE_MAP = {
"childhood": "watercolor",
"family": "watercolor",
"career_early": "realistic",
"career_achievement": "realistic",
"career_challenge": "realistic",
"beliefs": "editorial illustration",
"summary": "editorial illustration",
}
def __init__(self, llm: Optional[Any], settings: MemoirImageSettings):
self.llm = llm
self.settings = settings
def build_prompt(
self,
chapter_title: str,
chapter_category: str,
description: str,
context_excerpt: str,
) -> dict[str, str]:
style = self.CATEGORY_STYLE_MAP.get(chapter_category, self.settings.default_style)
prompt_context = f"{chapter_category}: {chapter_title}"
llm_input = {
"chapter_title": chapter_title,
"chapter_category": chapter_category,
"description": description,
"context_excerpt": context_excerpt,
"default_style": style,
"default_size": self.settings.default_size,
}
if self.llm:
try:
response = self.llm.invoke(
"Return JSON only with keys prompt, style, size. "
"Convert the memoir scene into an image-generation prompt.\n"
+ json.dumps(llm_input, ensure_ascii=False)
)
parsed = json.loads(response.content)
return {
"prompt": parsed["prompt"],
"style": parsed.get("style", style),
"size": parsed.get("size", self.settings.default_size),
"prompt_context": prompt_context,
}
except Exception:
pass
return {
"prompt": f"{description}\n\nScene context: {context_excerpt}",
"style": style,
"size": self.settings.default_size,
"prompt_context": prompt_context,
}

View File

@@ -0,0 +1,25 @@
import os
from dataclasses import dataclass
@dataclass(frozen=True)
class MemoirImageSettings:
enabled: bool
max_per_chapter: int
provider: str
default_style: str
default_size: str
poll_interval_seconds: int
max_attempts: int
@classmethod
def from_env(cls) -> "MemoirImageSettings":
return cls(
enabled=os.getenv("MEMOIR_IMAGE_ENABLED", "").lower() in {"1", "true", "yes"},
max_per_chapter=int(os.getenv("MEMOIR_IMAGE_MAX_PER_CHAPTER", "2")),
provider=os.getenv("MEMOIR_IMAGE_PROVIDER", "liblib"),
default_style=os.getenv("MEMOIR_IMAGE_STYLE_DEFAULT", "watercolor"),
default_size=os.getenv("MEMOIR_IMAGE_SIZE_DEFAULT", "1024x1024"),
poll_interval_seconds=int(os.getenv("MEMOIR_IMAGE_POLL_INTERVAL", "3")),
max_attempts=int(os.getenv("MEMOIR_IMAGE_MAX_ATTEMPTS", "20")),
)