Files
deepset-ai--haystack/haystack/components/embedders/mock_utils.py
T
wehub-resource-sync c56bef871b
CodeQL / Analyze (python) (push) Has been cancelled
Update Platform Components Table / update (push) Has been cancelled
Docker image release / Build base image (push) Has been cancelled
Sync docs with Docusaurus / sync (push) Has been cancelled
Tests / Check if changed (push) Has been cancelled
Tests / format (push) Has been cancelled
Tests / check-imports (push) Has been cancelled
Tests / Unit / macos-latest (push) Has been cancelled
Tests / Unit / ubuntu-latest (push) Has been cancelled
Tests / Unit / windows-latest (push) Has been cancelled
Tests / mypy (push) Has been cancelled
Tests / Integration / ubuntu-latest (push) Has been cancelled
Tests / Integration / macos-latest (push) Has been cancelled
Tests / Integration / windows-latest (push) Has been cancelled
Tests / notify-slack-on-failure (push) Has been cancelled
Tests / Mark tests as completed (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:22:28 +08:00

64 lines
2.6 KiB
Python

# SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
#
# SPDX-License-Identifier: Apache-2.0
import hashlib
import math
import random
from collections.abc import Callable
# A callable that derives an embedding from the (prepared) text to embed. It receives the text and returns the
# embedding as a list of floats.
EmbeddingFn = Callable[[str], list[float]]
def _l2_normalize(vector: list[float]) -> list[float]:
"""Return the L2-normalized vector, so that mock embeddings behave like real (unit-length) ones."""
norm = math.sqrt(sum(value * value for value in vector))
if norm == 0.0:
return vector
return [value / norm for value in vector]
def _deterministic_embedding(text: str, dimension: int) -> list[float]:
"""
Generate a deterministic, unit-length embedding from the given text.
The same text always yields the same embedding, and different texts yield different embeddings, which makes mock
embeddings usable in retrieval pipelines and reproducible across runs and processes. The seed is derived from a
SHA-256 digest of the text (not the process-salted built-in `hash`) to guarantee cross-process stability.
:param text: The text to embed.
:param dimension: The number of dimensions of the resulting embedding.
:returns: A deterministic, L2-normalized embedding of length `dimension`.
"""
digest = hashlib.sha256(text.encode("utf-8")).digest()
seed = int.from_bytes(digest[:8], "big")
rng = random.Random(seed)
vector = [rng.uniform(-1.0, 1.0) for _ in range(dimension)]
return _l2_normalize(vector)
def _coerce_embedding(value: object, *, name: str) -> list[float]:
"""
Validate that `value` is a non-empty sequence of numbers and coerce it into a list of floats.
:param value: The value to validate, e.g. a user-provided fixed embedding or the output of an `embedding_fn`.
:param name: How to refer to `value` in error messages, e.g. ``"'embedding'"``.
"""
if not isinstance(value, (list, tuple)) or not all(isinstance(item, (int, float)) for item in value):
raise TypeError(f"{name} must be a sequence of numbers, got {type(value)}.")
if len(value) == 0:
raise ValueError(f"{name} must not be empty.")
return [float(item) for item in value]
def _estimate_usage(texts: list[str]) -> dict[str, int]:
"""
Roughly estimate token usage as whitespace-separated word counts.
This is an approximation (not real tokenization) intended to give downstream code realistic-looking metadata.
"""
prompt_tokens = sum(len(text.split()) for text in texts)
return {"prompt_tokens": prompt_tokens, "total_tokens": prompt_tokens}