feat: add seo_meta service for AI-generated SEO metadata with CLI management and database layer
DevPlace CI / test (push) Failing after 2m13s
DevPlace CI / test (push) Failing after 2m13s
Implement a new `SeoMetaService` subservice that generates clean SEO title/description/keywords for published content items, distinct from the existing SEO diagnostics auditor. Add `seo_metadata` polymorphic table with soft-delete support, batch query methods, and usage tracking. Extend the CLI with `seo-meta prune` and `seo-meta clear` commands for job row lifecycle management. Wire `schedule_seo_meta_for_table` into content creation and editing flows in `content.py`. Document the new service in `AGENTS.md` and `README.md`, including the `extra_head` site setting for custom `<head>` injection.
This commit is contained in:
@@ -16,6 +16,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
EMBED_TIMEOUT_SECONDS = 60.0
|
||||
LOCAL_EMBED_DIMS = 256
|
||||
EMBED_CACHE_MAX = 5000
|
||||
TOKEN_PATTERN = re.compile(r"[a-z0-9]+")
|
||||
|
||||
|
||||
@@ -26,10 +27,18 @@ class EmbedResult:
|
||||
latency_ms: int = 0
|
||||
cache_hits: int = 0
|
||||
|
||||
@property
|
||||
def dims(self) -> int:
|
||||
for vector in self.vectors:
|
||||
if vector:
|
||||
return len(vector)
|
||||
return 0
|
||||
|
||||
|
||||
@dataclass
|
||||
class EmbeddingCache:
|
||||
store: dict[str, list[float]] = field(default_factory=dict)
|
||||
max_entries: int = EMBED_CACHE_MAX
|
||||
|
||||
def key(self, text: str) -> str:
|
||||
return hashlib.sha1((text or "").encode("utf-8")).hexdigest()
|
||||
@@ -38,8 +47,11 @@ class EmbeddingCache:
|
||||
return self.store.get(self.key(text))
|
||||
|
||||
def put(self, text: str, vector: list[float]) -> None:
|
||||
if vector:
|
||||
self.store[self.key(text)] = vector
|
||||
if not vector:
|
||||
return
|
||||
if len(self.store) >= self.max_entries:
|
||||
self.store.pop(next(iter(self.store)), None)
|
||||
self.store[self.key(text)] = vector
|
||||
|
||||
|
||||
def _local_vector(text: str) -> list[float]:
|
||||
|
||||
Reference in New Issue
Block a user