cajpany's picture
Deploy agentic SFX/music pipeline + traces (item 1)
c88b023 verified
Raw
History Blame Contribute Delete
1.98 kB
"""Text embedding interface for SFX/music matching.
The production target is a small sentence-embedding model (e.g. bge-small,
33M). To keep the fixture pipeline dependency-free and offline, the default
`HashingEmbedder` produces stable, comparable vectors with no model download.
Both satisfy the `Embedder` protocol, so the real model drops in later.
"""
from __future__ import annotations
import hashlib
import re
from typing import Protocol
import numpy as np
_TOKEN_RE = re.compile(r"[a-z0-9]+")
class Embedder(Protocol):
"""Anything that turns text into a fixed-length, comparable vector."""
def embed(self, text: str) -> np.ndarray: ...
class HashingEmbedder:
"""Deterministic bag-of-words hashing embedder, L2-normalized.
Shared tokens raise cosine similarity, so semantically similar prompts land
near each other without any learned model. Hashing uses md5 (not Python's
salted `hash`) so vectors are stable across processes and runs.
"""
def __init__(self, dim: int = 128) -> None:
self.dim = dim
def embed(self, text: str) -> np.ndarray:
vector = np.zeros(self.dim, dtype=np.float32)
for token in _TOKEN_RE.findall(text.lower()):
digest = hashlib.md5(token.encode("utf-8")).digest()
index = int.from_bytes(digest[:4], "big") % self.dim
sign = 1.0 if digest[4] & 1 else -1.0
vector[index] += sign
return _l2_normalize(vector)
def _l2_normalize(vector: np.ndarray) -> np.ndarray:
norm = float(np.linalg.norm(vector))
if norm == 0.0:
return vector
return (vector / norm).astype(np.float32)
def cosine_similarity(a: np.ndarray, b: np.ndarray) -> float:
"""Cosine similarity of two vectors (0.0 when either is empty/zero)."""
if a.size == 0 or b.size == 0:
return 0.0
denom = float(np.linalg.norm(a) * np.linalg.norm(b))
if denom == 0.0:
return 0.0
return float(np.dot(a, b) / denom)