faster-clip 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ """faster-clip — dependency-light CPU replacements (pure numpy) for the
2
+ transformers / sentence-transformers models used in the RAG stack:
3
+
4
+ * :class:`ClipModel` — CLIP image + multilingual-text embeddings (512-d).
5
+ * :class:`SparseEncoder` — inference-free SPLADE sparse ``{token_id: weight}`` dicts.
6
+ * :class:`FillMask` — BERT masked-LM autocomplete (en / pt).
7
+
8
+ No PyTorch, no transformers, no ONNX — just numpy + tokenizers (+ safetensors,
9
+ huggingface_hub for weights, pillow for images).
10
+ """
11
+
12
+ from .clip import ClipModel
13
+ from .fillmask import FillMask
14
+ from .sparse import SparseEncoder
15
+
16
+ __all__ = ["ClipModel", "SparseEncoder", "FillMask"]
17
+ __version__ = "0.1.0"
faster_clip/_nn.py ADDED
@@ -0,0 +1,51 @@
1
+ """Minimal numpy neural-net primitives shared by the encoders."""
2
+
3
+ import numpy as np
4
+
5
+
6
+ def layer_norm(x, w, b, eps=1e-5):
7
+ mu = x.mean(-1, keepdims=True)
8
+ var = x.var(-1, keepdims=True) # population variance (ddof=0), matches torch
9
+ return (x - mu) / np.sqrt(var + eps) * w + b
10
+
11
+
12
+ def quick_gelu(x):
13
+ return x * (1.0 / (1.0 + np.exp(-1.702 * x)))
14
+
15
+
16
+ def _erf(x):
17
+ # Abramowitz & Stegun 7.1.26, |error| < 1.5e-7
18
+ s = np.sign(x)
19
+ x = np.abs(x)
20
+ t = 1.0 / (1.0 + 0.3275911 * x)
21
+ y = 1.0 - (((((1.061405429 * t - 1.453152027) * t) + 1.421413741) * t
22
+ - 0.284496736) * t + 0.254829592) * t * np.exp(-x * x)
23
+ return s * y
24
+
25
+
26
+ def gelu(x):
27
+ return 0.5 * x * (1.0 + _erf(x / np.sqrt(2.0)))
28
+
29
+
30
+ def softmax(x, axis=-1):
31
+ x = x - x.max(axis=axis, keepdims=True)
32
+ e = np.exp(x)
33
+ return e / e.sum(axis=axis, keepdims=True)
34
+
35
+
36
+ def multi_head_attention(x, wq, bq, wk, bk, wv, bv, wo, bo, n_heads):
37
+ """Self-attention over a single (seq, dim) sequence. Weights are torch [out, in]."""
38
+ seq, dim = x.shape
39
+ hd = dim // n_heads
40
+ q = (x @ wq.T + bq).reshape(seq, n_heads, hd).transpose(1, 0, 2)
41
+ k = (x @ wk.T + bk).reshape(seq, n_heads, hd).transpose(1, 0, 2)
42
+ v = (x @ wv.T + bv).reshape(seq, n_heads, hd).transpose(1, 0, 2)
43
+ scores = q @ k.transpose(0, 2, 1) / np.sqrt(hd)
44
+ ctx = softmax(scores, -1) @ v # (h, seq, hd)
45
+ ctx = ctx.transpose(1, 0, 2).reshape(seq, dim)
46
+ return ctx @ wo.T + bo
47
+
48
+
49
+ def linear(x, w, b=None):
50
+ y = x @ w.T
51
+ return y if b is None else y + b