Deterministic offline backend. Used for tests and when no real provider is configured. Embeddings are not semantically meaningful, but they are stable and unit-norm.
| 125 | |
| 126 | |
| 127 | class HashEmbedding: |
| 128 | """Deterministic offline backend. |
| 129 | |
| 130 | Used for tests and when no real provider is configured. Embeddings are |
| 131 | not semantically meaningful, but they are stable and unit-norm. |
| 132 | """ |
| 133 | |
| 134 | name = "hash" |
| 135 | |
| 136 | def __init__(self, dimensions: int = 768, model: str = "hash") -> None: |
| 137 | self.model = model |
| 138 | self.dimensions = dimensions |
| 139 | |
| 140 | def embed(self, text: str) -> List[float]: |
| 141 | digest = hashlib.sha256((text or "").encode("utf-8")).digest() |
| 142 | vector: List[float] = [] |
| 143 | for index in range(self.dimensions): |
| 144 | byte_index = index % len(digest) |
| 145 | bit = (digest[byte_index] >> (index % 8)) & 1 |
| 146 | vector.append(1.0 if bit else -1.0) |
| 147 | norm = sum(value * value for value in vector) ** 0.5 |
| 148 | if norm > 0: |
| 149 | vector = [value / norm for value in vector] |
| 150 | return vector |
| 151 | |
| 152 | def embed_batch(self, texts: Iterable[str]) -> List[List[float]]: |
| 153 | return [self.embed(text) for text in texts] |
| 154 | |
| 155 | |
| 156 | def _is_placeholder(value: Optional[str]) -> bool: |
no outgoing calls