ruvector-ruvllm 0.2.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,68 @@
|
|
|
1
|
+
"""Bounded full precision token caches backed by native ruvllm Rust code."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
from numpy.typing import ArrayLike, NDArray
|
|
6
|
+
from ruvector import KVCache
|
|
7
|
+
|
|
8
|
+
__all__ = ["KVCache", "TokenCache"]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TokenCache:
|
|
12
|
+
"""Row-shaped interface to the native KVCache.
|
|
13
|
+
|
|
14
|
+
append accepts (tokens, dimensions) arrays. Attention is a single
|
|
15
|
+
flattened head, not a model inference or text generation API.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, dimensions: int, max_tokens: int = 4096) -> None:
|
|
19
|
+
if isinstance(dimensions, bool) or isinstance(max_tokens, bool):
|
|
20
|
+
raise ValueError("dimensions and max_tokens must be integers, not booleans")
|
|
21
|
+
self._cache = KVCache(dimensions, max_tokens)
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def dimensions(self) -> int:
|
|
25
|
+
return self._cache.dimensions
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def max_tokens(self) -> int:
|
|
29
|
+
return self._cache.max_tokens
|
|
30
|
+
|
|
31
|
+
def __len__(self) -> int:
|
|
32
|
+
return len(self._cache)
|
|
33
|
+
|
|
34
|
+
def append(self, keys: ArrayLike, values: ArrayLike) -> None:
|
|
35
|
+
"""Append matching token matrices, without eviction or quantization.
|
|
36
|
+
|
|
37
|
+
Finite values must have magnitude at most 1e10. Conversion to
|
|
38
|
+
float32 may copy input arrays. Invalid input never changes the cache.
|
|
39
|
+
"""
|
|
40
|
+
k = np.asarray(keys)
|
|
41
|
+
v = np.asarray(values)
|
|
42
|
+
if k.ndim != 2 or v.shape != k.shape or k.shape[1] != self.dimensions:
|
|
43
|
+
raise ValueError("keys and values must share shape (tokens, dimensions)")
|
|
44
|
+
if k.shape[0] == 0 or k.shape[0] > self.max_tokens - len(self):
|
|
45
|
+
raise ValueError("empty batch or cache capacity exceeded")
|
|
46
|
+
for data in (k, v):
|
|
47
|
+
if data.dtype.kind not in "iuf" or not np.isfinite(data).all() or (np.abs(data.astype(np.float64)) > 1e10).any():
|
|
48
|
+
raise ValueError("coordinates must be finite real numbers with magnitude <= 1e10")
|
|
49
|
+
self._cache.append(k.astype(np.float32).ravel().tolist(), v.astype(np.float32).ravel().tolist())
|
|
50
|
+
|
|
51
|
+
def attend(self, query: ArrayLike, scale: float | None = None) -> NDArray[np.float32]:
|
|
52
|
+
"""Return softmax attention output; default scale = 1/sqrt(dimensions)."""
|
|
53
|
+
q = np.asarray(query)
|
|
54
|
+
if q.shape != (self.dimensions,) or q.dtype.kind not in "iuf":
|
|
55
|
+
raise ValueError("query must be a real vector with shape (dimensions,)")
|
|
56
|
+
if not np.isfinite(q).all() or (np.abs(q.astype(np.float64)) > 1e10).any():
|
|
57
|
+
raise ValueError("query must be finite with magnitude <= 1e10")
|
|
58
|
+
return np.asarray(self._cache.attend(q.astype(np.float32).tolist(), scale), dtype=np.float32)
|
|
59
|
+
|
|
60
|
+
def get_all(self) -> tuple[NDArray[np.float32], NDArray[np.float32]]:
|
|
61
|
+
"""Return copied (keys, values) matrices in insertion order."""
|
|
62
|
+
keys, values = self._cache.get_all()
|
|
63
|
+
return (np.asarray(keys, dtype=np.float32).reshape(-1, self.dimensions),
|
|
64
|
+
np.asarray(values, dtype=np.float32).reshape(-1, self.dimensions))
|
|
65
|
+
|
|
66
|
+
def clear(self) -> None:
|
|
67
|
+
"""Discard all cached tokens."""
|
|
68
|
+
self._cache.clear()
|
ruvector_ruvllm/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ruvector-ruvllm
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Bounded native Rust key value cache and attention primitives for Python LLM pipelines
|
|
5
|
+
Project-URL: Homepage, https://github.com/ruvnet/RuVector
|
|
6
|
+
Project-URL: Documentation, https://github.com/ruvnet/RuVector/tree/main/python/portfolio/ruvector-ruvllm
|
|
7
|
+
Project-URL: Repository, https://github.com/ruvnet/RuVector
|
|
8
|
+
Project-URL: Issues, https://github.com/ruvnet/RuVector/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/ruvnet/RuVector/blob/main/python/portfolio/CHANGELOG.md
|
|
10
|
+
Author: RuVector Team
|
|
11
|
+
License-Expression: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: attention,kv-cache,llm,rust,ruvector
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Rust
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Requires-Dist: numpy>=1.21
|
|
20
|
+
Requires-Dist: ruvector==0.1.3
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# ruvector-ruvllm: Native Rust KV cache for Python
|
|
24
|
+
|
|
25
|
+

|
|
26
|
+
|
|
27
|
+
## What is ruvector-ruvllm?
|
|
28
|
+
|
|
29
|
+
A bounded CPU key/value cache and attention primitive for Python LLM pipelines, backed by the actual `ruvllm` Rust crate. Store key/value token vectors and query them with scaled dot product attention. This focused Python package exposes cache operations, **not text generation or full npm ruvllm feature parity**. No model weights or hosted services are required.
|
|
30
|
+
|
|
31
|
+
## Getting started
|
|
32
|
+
|
|
33
|
+
Requires Python 3.10 or newer and a platform supported by `ruvector==0.1.3` native wheels.
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install ruvector-ruvllm==0.2.0
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
This version requires publication of both the package and its pinned native runtime before that command works. In a source checkout, build/install the native SDK first, then install `./python/portfolio/ruvector-ruvllm`.
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from ruvector_ruvllm import TokenCache
|
|
43
|
+
|
|
44
|
+
cache = TokenCache(dimensions=2, max_tokens=128)
|
|
45
|
+
cache.append(keys=[[1.0, 0.0], [0.0, 1.0]],
|
|
46
|
+
values=[[2.0, 4.0], [8.0, 10.0]])
|
|
47
|
+
answer = cache.attend([1.0, 0.0])
|
|
48
|
+
assert answer.shape == (2,)
|
|
49
|
+
assert len(cache) == 2
|
|
50
|
+
keys, values = cache.get_all()
|
|
51
|
+
assert keys.shape == values.shape == (2, 2)
|
|
52
|
+
cache.clear()
|
|
53
|
+
assert len(cache) == 0
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Architecture
|
|
57
|
+
|
|
58
|
+
```mermaid
|
|
59
|
+
flowchart TD
|
|
60
|
+
A[Python token matrices] --> B[Shape and finite value validation]
|
|
61
|
+
B --> C[PyO3 KVCache]
|
|
62
|
+
C --> D[ruvllm full precision cache]
|
|
63
|
+
D --> E[Scaled softmax attention output]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The shared runtime keeps computation in Rust. The row-shaped Python interface converts inputs to float32. For flat inputs, `from ruvector_ruvllm import KVCache` exposes the native class directly.
|
|
67
|
+
|
|
68
|
+
## API and limits
|
|
69
|
+
|
|
70
|
+
| Operation | Behavior |
|
|
71
|
+
| --- | --- |
|
|
72
|
+
| `TokenCache(dimensions, max_tokens=4096)` | Create an empty bounded cache |
|
|
73
|
+
| `append(keys, values)` | Add matching matrices shaped `(tokens, dimensions)` |
|
|
74
|
+
| `attend(query, scale=None)` | Return float32 vector; default scale is `1/sqrt(dimensions)` |
|
|
75
|
+
| `get_all()` | Copy all keys and values into matrices |
|
|
76
|
+
| `clear()` | Remove all tokens |
|
|
77
|
+
| `len(cache)` | Number of stored tokens |
|
|
78
|
+
|
|
79
|
+
Attention treats each token as one vector, not independent attention heads. The implementation retains full float32 precision, with no quantization, sliding window or automatic eviction. Capacity errors leave the cache unchanged. Empty-cache attention returns zeros.
|
|
80
|
+
|
|
81
|
+
Dimensions are limited to 4096, tokens to 65536, and their product to 8388608. Raw keys and values therefore occupy at most 64 MiB, excluding objects, conversion buffers and returned copies. Coordinates must be finite and have absolute value at most `1e10`. Isolate untrusted workloads with process memory limits because Python conversion can allocate before native validation.
|
|
82
|
+
|
|
83
|
+
## Relationship to npm and Rust
|
|
84
|
+
|
|
85
|
+
Inspired by the popular npm `ruvllm` package, using the repository's real Rust cache implementation. This release does not expose model loading, tokenization, GPU inference, serving, learning or text generation. It ships a focused wrapper over the shared `ruvector` native runtime rather than a separate binary engine.
|
|
86
|
+
|
|
87
|
+
Source: [RuVector](https://github.com/ruvnet/RuVector). [Security policy](https://github.com/ruvnet/RuVector/blob/main/python/portfolio/SECURITY.md). License: MIT.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
ruvector_ruvllm/__init__.py,sha256=yw3LdI7yOzzghDAlOKm7IVpvQLE_FwSpf3k_2hKCIR8,3092
|
|
2
|
+
ruvector_ruvllm/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
ruvector_ruvllm-0.2.0.dist-info/METADATA,sha256=RDwBAq_jzyt1esDPiqlaG67caht1IYCnhib34UpSZDA,4382
|
|
4
|
+
ruvector_ruvllm-0.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
5
|
+
ruvector_ruvllm-0.2.0.dist-info/licenses/LICENSE,sha256=UP77k1YK9EITacmck8whTNg1sxgat_FjI_nm8t7YcOM,1060
|
|
6
|
+
ruvector_ruvllm-0.2.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 rUv
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|