ruvector 0.1.0__tar.gz → 0.1.2__tar.gz
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.
- {ruvector-0.1.0 → ruvector-0.1.2}/Cargo.lock +1 -1
- {ruvector-0.1.0 → ruvector-0.1.2}/PKG-INFO +13 -1
- {ruvector-0.1.0 → ruvector-0.1.2}/README.md +11 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/Cargo.toml +1 -1
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/README.md +11 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/src/rabitq.rs +94 -8
- ruvector-0.1.2/crates/ruvector-py/tests/perf/bench_collection.py +84 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/tests/test_cli.py +72 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/tests/test_mcp_server.py +104 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/tests/test_smoke.py +87 -1
- {ruvector-0.1.0 → ruvector-0.1.2}/pyproject.toml +2 -1
- {ruvector-0.1.0 → ruvector-0.1.2}/python/ruvector/_native.pyi +7 -4
- {ruvector-0.1.0 → ruvector-0.1.2}/python/ruvector/cli.py +81 -7
- {ruvector-0.1.0 → ruvector-0.1.2}/python/ruvector/mcp_server.py +103 -7
- {ruvector-0.1.0 → ruvector-0.1.2}/Cargo.toml +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/LICENSE +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/Cargo.toml +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/LICENSE +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/README.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/benches/attention_bench.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/benches/attention_benchmarks.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/docs/IMPLEMENTATION_SUMMARY.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/docs/SDK_GUIDE.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/examples/hyperbolic_bench.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/attention/flash.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/attention/kv_cache.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/attention/mla.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/attention/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/attention/multi_head.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/attention/scaled_dot_product.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/attention/speculative.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/attention/ssm.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/config.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/curvature/component_quantizer.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/curvature/fused_attention.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/curvature/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/curvature/tangent_space.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/error.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/graph/dual_space.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/graph/edge_featured.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/graph/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/graph/rope.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/hyperbolic/hyperbolic_attention.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/hyperbolic/lorentz_cascade.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/hyperbolic/mixed_curvature.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/hyperbolic/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/hyperbolic/poincare.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/info_bottleneck/bottleneck.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/info_bottleneck/kl_divergence.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/info_bottleneck/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/info_geometry/fisher.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/info_geometry/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/info_geometry/natural_gradient.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/lib.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/moe/expert.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/moe/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/moe/moe_attention.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/moe/router.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/pde_attention/diffusion.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/pde_attention/laplacian.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/pde_attention/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/sdk/builder.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/sdk/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/sdk/pipeline.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/sdk/presets.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/sheaf/attention.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/sheaf/early_exit.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/sheaf/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/sheaf/restriction.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/sheaf/router.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/sheaf/sparse.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/sparse/flash.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/sparse/linear.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/sparse/local_global.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/sparse/mask.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/sparse/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/topology/coherence.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/topology/gated_attention.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/topology/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/topology/policy.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/training/curriculum.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/training/loss.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/training/mining.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/training/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/training/optimizer.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/traits.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/transport/cached_projections.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/transport/centroid_ot.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/transport/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/transport/sliced_wasserstein.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/unified_report/metrics.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/unified_report/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/unified_report/report.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-attention/src/utils.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-cluster/Cargo.toml +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-cluster/README.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-cluster/package.json +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-cluster/src/consensus.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-cluster/src/discovery.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-cluster/src/lib.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-cluster/src/shard.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-cluster/tests/integration_tests.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-cluster-rag/Cargo.toml +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-cluster-rag/README.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-cluster-rag/src/bench.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-cluster-rag/src/bin/benchmark.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-cluster-rag/src/cluster.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-cluster-rag/src/dataset.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-cluster-rag/src/lib.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-cluster-rag/src/search.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-cluster-rag/src/tree.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/Cargo.toml +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/README.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/benches/batch_operations.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/benches/bench_memory.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/benches/bench_simd.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/benches/comprehensive_bench.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/benches/distance_metrics.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/benches/hnsw_search.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/benches/pdx_vs_rowmajor.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/benches/quantization_bench.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/benches/real_benchmark.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/docs/EMBEDDINGS.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/examples/embeddings_example.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/examples/lattice_embedding_example.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/examples/neon_benchmark.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/advanced/hypergraph.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/advanced/learned_index.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/advanced/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/advanced/neural_hash.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/advanced/tda.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/compaction.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/conformal_prediction.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/diskann.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/filtered_search.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/graph_rag.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/hybrid_search.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/matryoshka.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/mmr.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/multi_vector.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/opq.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/product_quantization.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/sparse_vector.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/agenticdb.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/arena.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/cache_optimized.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/distance.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/embeddings.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/encoding/codecs.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/encoding.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/error.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/index/flat.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/index/hnsw.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/index/turbo4.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/index.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/integration.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/lib.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/lockfree.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/memory.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/pdx.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/quantization.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/simd_intrinsics.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/storage.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/storage_compat.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/storage_memory.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/types.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/src/vector_db.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/tests/README.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/tests/advanced_features_integration.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/tests/concurrent_tests.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/tests/embeddings_role_test.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/tests/embeddings_test.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/tests/hnsw_773_recall_distributions.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/tests/hnsw_integration_test.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/tests/hnsw_issue_773_regression.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/tests/hnsw_issue_773_structural.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/tests/integration_tests.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/tests/property_tests.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/tests/stress_tests.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/tests/test_memory_pool.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/tests/test_quantization.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/tests/test_simd_correctness.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-core/tests/unit_tests.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-diskann/Cargo.toml +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-diskann/examples/bench_delete_recall.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-diskann/examples/bench_search_hot.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-diskann/examples/mmap_674_bench.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-diskann/src/distance.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-diskann/src/error.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-diskann/src/graph.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-diskann/src/index.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-diskann/src/lib.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-diskann/src/pq.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-diskann/src/reuse.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-diskann/tests/search_allocations.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/Cargo.toml +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/README.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/examples/diskann_real_trajectory.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/examples/loss_demo.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/examples/triggered_rebuild.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/src/cold_tier.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/src/compress.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/src/error.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/src/ewc.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/src/graphmae.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/src/layer.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/src/lib.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/src/mmap.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/src/mmap_fixed.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/src/query.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/src/replay.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/src/scheduler.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/src/search.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/src/tensor.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/src/training.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-gnn/tests/loss_verification.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/ARCHITECTURE.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/Cargo.toml +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/README.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/benches/cypher_parser.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/benches/distributed_query.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/benches/graph_bench.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/benches/graph_traversal.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/benches/hybrid_vector_graph.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/benches/new_capabilities_bench.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/benches/query_execution.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/benches/simd_operations.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/benches/typed_graph_bench.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/examples/test_cypher_parser.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/bm25.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/codegen.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/cypher/README.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/cypher/ast.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/cypher/lexer.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/cypher/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/cypher/optimizer.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/cypher/parser.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/cypher/semantic.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/distributed/coordinator.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/distributed/federation.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/distributed/gossip.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/distributed/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/distributed/replication.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/distributed/rpc.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/distributed/shard.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/edge.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/embed.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/error.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/executor/cache.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/executor/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/executor/operators.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/executor/parallel.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/executor/pipeline.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/executor/plan.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/executor/stats.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/graph.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/hybrid/cypher_extensions.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/hybrid/graph_neural.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/hybrid/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/hybrid/rag_integration.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/hybrid/semantic_search.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/hybrid/vector_index.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/hyperedge.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/index.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/lib.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/node.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/optimization/adaptive_radix.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/optimization/bloom_filter.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/optimization/cache_hierarchy.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/optimization/index_compression.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/optimization/memory_pool.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/optimization/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/optimization/query_jit.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/optimization/simd_traversal.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/schema.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/storage.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/transaction.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/typed_graph.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/src/types.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/tests/compatibility_tests.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/tests/concurrent_tests.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/tests/cypher_execution_tests.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/tests/cypher_parser_integration.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/tests/cypher_parser_tests.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/tests/distributed_tests.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/tests/edge_tests.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/tests/fixtures/README.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/tests/fixtures/expected_results.json +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/tests/fixtures/movie_database.json +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/tests/fixtures/social_network.json +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/tests/hyperedge_tests.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/tests/node_tests.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/tests/performance_tests.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-graph/tests/transaction_tests.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/Cargo.toml +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/README.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/benches/information_geometry.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/benches/optimal_transport.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/benches/product_manifold.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/benches/spectral.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/benches/tropical.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/error.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/homology/distance.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/homology/filtration.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/homology/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/homology/persistence.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/homology/simplex.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/information_geometry/fisher.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/information_geometry/kfac.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/information_geometry/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/information_geometry/natural_gradient.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/lib.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/optimal_transport/config.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/optimal_transport/gromov_wasserstein.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/optimal_transport/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/optimal_transport/sinkhorn.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/optimal_transport/sliced_wasserstein.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/optimization/certificates.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/optimization/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/optimization/polynomial.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/optimization/sdp.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/optimization/sos.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/product_manifold/config.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/product_manifold/manifold.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/product_manifold/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/product_manifold/operations.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/spectral/chebyshev.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/spectral/clustering.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/spectral/graph_filter.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/spectral/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/spectral/wavelets.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/spherical/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/tensor_networks/contraction.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/tensor_networks/cp_decomposition.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/tensor_networks/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/tensor_networks/tensor_train.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/tensor_networks/tucker.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/tropical/matrix.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/tropical/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/tropical/neural_analysis.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/tropical/polynomial.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/tropical/semiring.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/utils/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/utils/numerical.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-math/src/utils/sorting.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/.gitignore +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/LICENSE +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/benchmarks/bench_compare_rabitq.py +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/benchmarks/bench_hnsw_real_embeddings.py +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/scripts/check-release-version.sh +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/scripts/sdist-add-patches.sh +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/src/cluster.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/src/error.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/src/gnn.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/src/graph/convert.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/src/graph/cypher_bridge.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/src/graph/cypher_eval.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/src/graph/cypher_exec.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/src/graph.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/src/hnsw.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/src/lib.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/src/sona.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/tests/test_cluster.py +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/tests/test_collection.py +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/tests/test_gnn.py +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/tests/test_graph.py +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/tests/test_graph_cypher.py +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/tests/test_langchain_integration.py +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/tests/test_llamaindex_integration.py +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/tests/test_salesforce_integration.py +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/tests/test_salesforce_routes.py +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-py/tests/test_sona.py +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-rabitq/BENCHMARK.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-rabitq/Cargo.toml +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-rabitq/benches/rabitq_bench.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-rabitq/src/error.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-rabitq/src/index.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-rabitq/src/kernel.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-rabitq/src/lib.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-rabitq/src/main.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-rabitq/src/persist.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-rabitq/src/quantize.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-rabitq/src/rotation.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-rabitq/src/scan.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-raft/Cargo.toml +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-raft/README.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-raft/src/election.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-raft/src/lib.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-raft/src/log.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-raft/src/node.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-raft/src/rpc.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-raft/src/state.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-raft/tests/integration_tests.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-replication/Cargo.toml +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-replication/README.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-replication/src/conflict.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-replication/src/failover.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-replication/src/lib.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-replication/src/replica.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-replication/src/stream.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-replication/src/sync.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-turboquant/Cargo.toml +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-turboquant/benches/kernels.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-turboquant/src/bits1.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-turboquant/src/codec.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-turboquant/src/lib.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-turboquant/src/rotation.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-turboquant/src/score.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-turboquant/src/simd.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/ruvector-turboquant/src/tables.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/Cargo.toml +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/LICENSE-APACHE +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/LICENSE-MIT +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/README.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/auto_tuner.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/darwin_guard.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/engine.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/ewc.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/export/dataset.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/export/huggingface_hub.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/export/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/export/pretrain.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/export/safetensors.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/lib.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/loops/background.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/loops/coordinator.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/loops/instant.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/loops/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/lora.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/napi.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/napi_simple.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/reasoning_bank.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/time_compat.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/training/factory.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/training/federated.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/training/metrics.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/training/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/training/pipeline.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/training/templates.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/trajectory.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/types.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/src/wasm.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/crates/sona/wasm-example/README.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/.gitignore +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/Cargo.toml +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/Changes.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/LICENSE-APACHE +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/LICENSE-MIT +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/README.md +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/examples/ann-glove25-angular.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/examples/ann-mnist-784-euclidean.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/examples/ann-sift1m-128-euclidean.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/examples/levensthein.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/examples/random.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/examples/utils/annhdf5.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/examples/utils/mod.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/src/api.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/src/datamap.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/src/filter.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/src/flatten.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/src/hnsw.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/src/hnswio.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/src/lib.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/src/libext.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/src/prelude.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/tests/deallocation_test.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/tests/filtertest.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/patches/hnsw_rs/tests/serpar.rs +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/python/ruvector/__init__.py +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/python/ruvector/__init__.pyi +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/python/ruvector/collection.py +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/python/ruvector/integrations/__init__.py +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/python/ruvector/integrations/langchain.py +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/python/ruvector/integrations/llamaindex.py +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/python/ruvector/integrations/salesforce.py +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/python/ruvector/py.typed +0 -0
- {ruvector-0.1.0 → ruvector-0.1.2}/python/ruvector/salesforce_routes.py +0 -0
|
@@ -10759,7 +10759,7 @@ dependencies = [
|
|
|
10759
10759
|
|
|
10760
10760
|
[[package]]
|
|
10761
10761
|
name = "ruvector-py"
|
|
10762
|
-
version = "0.1.
|
|
10762
|
+
version = "0.1.2"
|
|
10763
10763
|
dependencies = [
|
|
10764
10764
|
"numpy",
|
|
10765
10765
|
"pyo3",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ruvector
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Classifier: Development Status :: 3 - Alpha
|
|
5
5
|
Classifier: Programming Language :: Rust
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -9,6 +9,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.11
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.12
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
12
13
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
13
14
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
14
15
|
Classifier: Topic :: Database :: Database Engines/Servers
|
|
@@ -136,6 +137,7 @@ ruvector benchmark -n 100000 --dim 128 # in-process latency/QPS, no external
|
|
|
136
137
|
ruvector serve # MCP server over stdio
|
|
137
138
|
ruvector serve --http --port 8420 # MCP server over streamable-HTTP (loopback)
|
|
138
139
|
ruvector serve --read-only # no create/insert/delete tools
|
|
140
|
+
ruvector serve --max-vectors 50000 # cap vectors per collection (default 1,000,000)
|
|
139
141
|
```
|
|
140
142
|
|
|
141
143
|
`serve --http` on a non-loopback `--host` refuses to start unless
|
|
@@ -161,6 +163,16 @@ directory-traversal surface regardless of what a remote MCP client sends.
|
|
|
161
163
|
See `ruvector/mcp_server.py`'s module docstring for the full security
|
|
162
164
|
model.
|
|
163
165
|
|
|
166
|
+
Write size is capped. Per call: 10,000 rows, 2,000,000 floats in total, and
|
|
167
|
+
64 KiB of serialized metadata per row. Per collection: 1,000,000 vectors by
|
|
168
|
+
default, counting deleted-but-not-vacuumed rows; `vector_insert` and
|
|
169
|
+
`vector_insert_batch` fail with a `ToolError` that names the limit once it
|
|
170
|
+
would be exceeded. Change it with `ruvector serve --max-vectors N` or
|
|
171
|
+
`RUVECTOR_MCP_MAX_VECTORS=N` (the option wins; a non-positive or non-integer
|
|
172
|
+
value stops the server at startup). The server re-saves the whole collection
|
|
173
|
+
on every write, so keep this cap well below what your disk and latency budget
|
|
174
|
+
can take.
|
|
175
|
+
|
|
164
176
|
```sh
|
|
165
177
|
# point an MCP client at: ruvector serve (stdio)
|
|
166
178
|
# or: ruvector serve --http --port 8420
|
|
@@ -88,6 +88,7 @@ ruvector benchmark -n 100000 --dim 128 # in-process latency/QPS, no external
|
|
|
88
88
|
ruvector serve # MCP server over stdio
|
|
89
89
|
ruvector serve --http --port 8420 # MCP server over streamable-HTTP (loopback)
|
|
90
90
|
ruvector serve --read-only # no create/insert/delete tools
|
|
91
|
+
ruvector serve --max-vectors 50000 # cap vectors per collection (default 1,000,000)
|
|
91
92
|
```
|
|
92
93
|
|
|
93
94
|
`serve --http` on a non-loopback `--host` refuses to start unless
|
|
@@ -113,6 +114,16 @@ directory-traversal surface regardless of what a remote MCP client sends.
|
|
|
113
114
|
See `ruvector/mcp_server.py`'s module docstring for the full security
|
|
114
115
|
model.
|
|
115
116
|
|
|
117
|
+
Write size is capped. Per call: 10,000 rows, 2,000,000 floats in total, and
|
|
118
|
+
64 KiB of serialized metadata per row. Per collection: 1,000,000 vectors by
|
|
119
|
+
default, counting deleted-but-not-vacuumed rows; `vector_insert` and
|
|
120
|
+
`vector_insert_batch` fail with a `ToolError` that names the limit once it
|
|
121
|
+
would be exceeded. Change it with `ruvector serve --max-vectors N` or
|
|
122
|
+
`RUVECTOR_MCP_MAX_VECTORS=N` (the option wins; a non-positive or non-integer
|
|
123
|
+
value stops the server at startup). The server re-saves the whole collection
|
|
124
|
+
on every write, so keep this cap well below what your disk and latency budget
|
|
125
|
+
can take.
|
|
126
|
+
|
|
116
127
|
```sh
|
|
117
128
|
# point an MCP client at: ruvector serve (stdio)
|
|
118
129
|
# or: ruvector serve --http --port 8420
|
|
@@ -88,6 +88,7 @@ ruvector benchmark -n 100000 --dim 128 # in-process latency/QPS, no external
|
|
|
88
88
|
ruvector serve # MCP server over stdio
|
|
89
89
|
ruvector serve --http --port 8420 # MCP server over streamable-HTTP (loopback)
|
|
90
90
|
ruvector serve --read-only # no create/insert/delete tools
|
|
91
|
+
ruvector serve --max-vectors 50000 # cap vectors per collection (default 1,000,000)
|
|
91
92
|
```
|
|
92
93
|
|
|
93
94
|
`serve --http` on a non-loopback `--host` refuses to start unless
|
|
@@ -113,6 +114,16 @@ directory-traversal surface regardless of what a remote MCP client sends.
|
|
|
113
114
|
See `ruvector/mcp_server.py`'s module docstring for the full security
|
|
114
115
|
model.
|
|
115
116
|
|
|
117
|
+
Write size is capped. Per call: 10,000 rows, 2,000,000 floats in total, and
|
|
118
|
+
64 KiB of serialized metadata per row. Per collection: 1,000,000 vectors by
|
|
119
|
+
default, counting deleted-but-not-vacuumed rows; `vector_insert` and
|
|
120
|
+
`vector_insert_batch` fail with a `ToolError` that names the limit once it
|
|
121
|
+
would be exceeded. Change it with `ruvector serve --max-vectors N` or
|
|
122
|
+
`RUVECTOR_MCP_MAX_VECTORS=N` (the option wins; a non-positive or non-integer
|
|
123
|
+
value stops the server at startup). The server re-saves the whole collection
|
|
124
|
+
on every write, so keep this cap well below what your disk and latency budget
|
|
125
|
+
can take.
|
|
126
|
+
|
|
116
127
|
```sh
|
|
117
128
|
# point an MCP client at: ruvector serve (stdio)
|
|
118
129
|
# or: ruvector serve --http --port 8420
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
//! and `RabitqAsymIndex` as separate Python classes per the surface sketch in
|
|
13
13
|
//! `docs/sdk/03-api-surface.md`. M1 ships exactly one class.
|
|
14
14
|
|
|
15
|
+
use std::collections::HashSet;
|
|
15
16
|
use std::fs::File;
|
|
16
17
|
use std::io::{BufReader, BufWriter};
|
|
17
18
|
|
|
@@ -50,6 +51,53 @@ pub struct RabitqIndex {
|
|
|
50
51
|
// to keep a redundant copy here. The seed lives separately because
|
|
51
52
|
// `RabitqPlusIndex` doesn't expose its own seed field.
|
|
52
53
|
seed: u64,
|
|
54
|
+
// Ids currently in the index, so `add`/`add_batch` can reject a duplicate in O(1).
|
|
55
|
+
ids: HashSet<u32>,
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// Describe a Python object for an error message (dtype and ndim when it is an array).
|
|
59
|
+
fn describe(obj: &Bound<'_, PyAny>) -> String {
|
|
60
|
+
match (obj.getattr("dtype"), obj.getattr("ndim")) {
|
|
61
|
+
(Ok(d), Ok(n)) => format!("dtype={d}, ndim={n}"),
|
|
62
|
+
_ => obj
|
|
63
|
+
.get_type()
|
|
64
|
+
.name()
|
|
65
|
+
.map(|n| n.to_string())
|
|
66
|
+
.unwrap_or_else(|_| "an unknown object".into()),
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
fn arr1<'py>(obj: &Bound<'py, PyAny>, name: &str) -> PyResult<PyReadonlyArray1<'py, f32>> {
|
|
71
|
+
obj.extract().map_err(|_| {
|
|
72
|
+
PyTypeError::new_err(format!(
|
|
73
|
+
"{name} must be a 1D float32 NumPy array, got {}; convert with np.ascontiguousarray(x, dtype=np.float32)",
|
|
74
|
+
describe(obj)
|
|
75
|
+
))
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
fn arr2<'py>(obj: &Bound<'py, PyAny>, name: &str) -> PyResult<PyReadonlyArray2<'py, f32>> {
|
|
80
|
+
obj.extract().map_err(|_| {
|
|
81
|
+
PyTypeError::new_err(format!(
|
|
82
|
+
"{name} must be a 2D float32 NumPy array, got {}; convert with np.ascontiguousarray(x, dtype=np.float32)",
|
|
83
|
+
describe(obj)
|
|
84
|
+
))
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/// Reject NaN and infinity, which would otherwise be indexed or searched and yield NaN scores.
|
|
89
|
+
fn check_finite(data: &[f32], dim: usize, name: &str) -> PyResult<()> {
|
|
90
|
+
match data.iter().position(|x| !x.is_finite()) {
|
|
91
|
+
None => Ok(()),
|
|
92
|
+
Some(i) if dim > 0 && data.len() > dim => Err(PyValueError::new_err(format!(
|
|
93
|
+
"{name} contains a non-finite value (NaN or inf) at row {}, column {}",
|
|
94
|
+
i / dim,
|
|
95
|
+
i % dim
|
|
96
|
+
))),
|
|
97
|
+
Some(i) => Err(PyValueError::new_err(format!(
|
|
98
|
+
"{name} contains a non-finite value (NaN or inf) at position {i}"
|
|
99
|
+
))),
|
|
100
|
+
}
|
|
53
101
|
}
|
|
54
102
|
|
|
55
103
|
#[pymethods]
|
|
@@ -61,8 +109,15 @@ impl RabitqIndex {
|
|
|
61
109
|
/// silently copying — silent copies would be an O(n·dim) surprise on a
|
|
62
110
|
/// "fast" build call.
|
|
63
111
|
///
|
|
64
|
-
/// `rerank_factor` defaults to 20
|
|
65
|
-
///
|
|
112
|
+
/// `rerank_factor` defaults to 20. Recall depends on the data: ADR-154
|
|
113
|
+
/// reports 100% recall@10 at D=128 on clustered, embedding-like data, but
|
|
114
|
+
/// on isotropic Gaussian vectors (D=128, n=10k) a rerank_factor of 20 gives
|
|
115
|
+
/// about 0.63 recall@10 and 500 is needed for 1.0. Raise `rerank_factor`
|
|
116
|
+
/// (here or per `search` call) for hard distributions and measure recall
|
|
117
|
+
/// against brute force on your own data.
|
|
118
|
+
///
|
|
119
|
+
/// Raises `ValueError` if `vectors` contains NaN or infinity, or if `ids`
|
|
120
|
+
/// contains a duplicate.
|
|
66
121
|
///
|
|
67
122
|
/// `seed` defaults to 42 to keep the build deterministic out-of-the-box —
|
|
68
123
|
/// the doc-comment guarantee on `ruvector_rabitq` is that
|
|
@@ -81,11 +136,12 @@ impl RabitqIndex {
|
|
|
81
136
|
#[pyo3(signature = (vectors, *, ids = None, rerank_factor = 20, seed = 42))]
|
|
82
137
|
fn build(
|
|
83
138
|
py: Python<'_>,
|
|
84
|
-
vectors:
|
|
139
|
+
vectors: &Bound<'_, PyAny>,
|
|
85
140
|
ids: Option<PyReadonlyArray1<'_, u64>>,
|
|
86
141
|
rerank_factor: u32,
|
|
87
142
|
seed: u64,
|
|
88
143
|
) -> PyResult<Self> {
|
|
144
|
+
let vectors = arr2(vectors, "vectors")?;
|
|
89
145
|
// Validate the dtype/contig invariants up front. `PyReadonlyArray2`
|
|
90
146
|
// already guarantees the dtype is f32 (otherwise the conversion at
|
|
91
147
|
// the call site fails with `TypeError`). What it does NOT guarantee
|
|
@@ -122,6 +178,7 @@ impl RabitqIndex {
|
|
|
122
178
|
// across rayon workers. PyO3 cannot give us mutable owned access
|
|
123
179
|
// to NumPy storage without breaking the readonly contract.
|
|
124
180
|
let slice = vectors.as_slice()?; // contiguous view, len = n*dim
|
|
181
|
+
check_finite(slice, dim, "vectors")?;
|
|
125
182
|
let mut items: Vec<(usize, Vec<f32>)> = Vec::with_capacity(n);
|
|
126
183
|
match ids {
|
|
127
184
|
Some(ids_arr) => {
|
|
@@ -145,6 +202,12 @@ impl RabitqIndex {
|
|
|
145
202
|
)));
|
|
146
203
|
}
|
|
147
204
|
}
|
|
205
|
+
let mut seen = HashSet::with_capacity(ids_slice.len());
|
|
206
|
+
for &id in ids_slice {
|
|
207
|
+
if !seen.insert(id) {
|
|
208
|
+
return Err(PyValueError::new_err(format!("duplicate id {id} in ids")));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
148
211
|
for (i, &id) in ids_slice.iter().enumerate() {
|
|
149
212
|
let row = &slice[i * dim..(i + 1) * dim];
|
|
150
213
|
items.push((id as usize, row.to_vec()));
|
|
@@ -168,7 +231,8 @@ impl RabitqIndex {
|
|
|
168
231
|
})
|
|
169
232
|
.map_err(to_pyerr)?;
|
|
170
233
|
|
|
171
|
-
|
|
234
|
+
let ids = inner.ids_u64().into_iter().map(|i| i as u32).collect();
|
|
235
|
+
Ok(Self { inner, seed, ids })
|
|
172
236
|
}
|
|
173
237
|
|
|
174
238
|
/// Search for the `k` nearest neighbours of a single `query` vector.
|
|
@@ -185,10 +249,11 @@ impl RabitqIndex {
|
|
|
185
249
|
fn search(
|
|
186
250
|
&self,
|
|
187
251
|
py: Python<'_>,
|
|
188
|
-
query:
|
|
252
|
+
query: &Bound<'_, PyAny>,
|
|
189
253
|
k: usize,
|
|
190
254
|
rerank_factor: Option<u32>,
|
|
191
255
|
) -> PyResult<Vec<(u32, f32)>> {
|
|
256
|
+
let query = arr1(query, "query")?;
|
|
192
257
|
if !query.is_c_contiguous() {
|
|
193
258
|
return Err(PyTypeError::new_err(
|
|
194
259
|
"query must be C-contiguous; pass np.ascontiguousarray(...) first",
|
|
@@ -198,6 +263,7 @@ impl RabitqIndex {
|
|
|
198
263
|
return Err(PyValueError::new_err("k must be > 0"));
|
|
199
264
|
}
|
|
200
265
|
let q = query.as_slice()?;
|
|
266
|
+
check_finite(q, 0, "query")?;
|
|
201
267
|
|
|
202
268
|
// `search_with_rerank` is the right entry point even when no
|
|
203
269
|
// override is requested, because it is the common path the
|
|
@@ -263,7 +329,8 @@ impl RabitqIndex {
|
|
|
263
329
|
let seed = u64::from_le_bytes(header[16..24].try_into().unwrap());
|
|
264
330
|
|
|
265
331
|
let inner = persist::load_index(&mut r).map_err(to_pyerr)?;
|
|
266
|
-
|
|
332
|
+
let ids = inner.ids_u64().into_iter().map(|i| i as u32).collect();
|
|
333
|
+
Ok(Self { inner, seed, ids })
|
|
267
334
|
}
|
|
268
335
|
|
|
269
336
|
/// Number of indexed vectors (matches `AnnIndex::len`).
|
|
@@ -303,7 +370,8 @@ impl RabitqIndex {
|
|
|
303
370
|
/// release/reacquire cost itself (same call made for `RabitqPlusIndex.add`
|
|
304
371
|
/// in `docs/sdk/02-strategy.md`'s GIL table). Use `add_batch` for bulk
|
|
305
372
|
/// inserts, which does release the GIL.
|
|
306
|
-
fn add(&mut self, id: u32, vector:
|
|
373
|
+
fn add(&mut self, id: u32, vector: &Bound<'_, PyAny>) -> PyResult<()> {
|
|
374
|
+
let vector = arr1(vector, "vector")?;
|
|
307
375
|
if !vector.is_c_contiguous() {
|
|
308
376
|
return Err(PyTypeError::new_err(
|
|
309
377
|
"vector must be C-contiguous; pass np.ascontiguousarray(...) first",
|
|
@@ -317,7 +385,14 @@ impl RabitqIndex {
|
|
|
317
385
|
v.len()
|
|
318
386
|
)));
|
|
319
387
|
}
|
|
388
|
+
check_finite(v, 0, "vector")?;
|
|
389
|
+
if self.ids.contains(&id) {
|
|
390
|
+
return Err(PyValueError::new_err(format!(
|
|
391
|
+
"id {id} is already in the index; ids must be unique"
|
|
392
|
+
)));
|
|
393
|
+
}
|
|
320
394
|
self.inner.add(id as usize, v.to_vec()).map_err(to_pyerr)?;
|
|
395
|
+
self.ids.insert(id);
|
|
321
396
|
Ok(())
|
|
322
397
|
}
|
|
323
398
|
|
|
@@ -328,8 +403,9 @@ impl RabitqIndex {
|
|
|
328
403
|
&mut self,
|
|
329
404
|
py: Python<'_>,
|
|
330
405
|
ids: PyReadonlyArray1<'_, u64>,
|
|
331
|
-
vectors:
|
|
406
|
+
vectors: &Bound<'_, PyAny>,
|
|
332
407
|
) -> PyResult<()> {
|
|
408
|
+
let vectors = arr2(vectors, "vectors")?;
|
|
333
409
|
if !vectors.is_c_contiguous() {
|
|
334
410
|
return Err(PyTypeError::new_err(
|
|
335
411
|
"vectors must be C-contiguous; pass np.ascontiguousarray(...) first",
|
|
@@ -371,6 +447,15 @@ impl RabitqIndex {
|
|
|
371
447
|
}
|
|
372
448
|
}
|
|
373
449
|
let vecs_slice = vectors.as_slice()?;
|
|
450
|
+
check_finite(vecs_slice, dim, "vectors")?;
|
|
451
|
+
let mut batch_ids = HashSet::with_capacity(ids_slice.len());
|
|
452
|
+
for &id in &ids_slice {
|
|
453
|
+
if self.ids.contains(&(id as u32)) || !batch_ids.insert(id) {
|
|
454
|
+
return Err(PyValueError::new_err(format!(
|
|
455
|
+
"id {id} is already in the index or repeated in the batch; ids must be unique"
|
|
456
|
+
)));
|
|
457
|
+
}
|
|
458
|
+
}
|
|
374
459
|
let rows: Vec<(usize, Vec<f32>)> = (0..n)
|
|
375
460
|
.map(|i| {
|
|
376
461
|
(
|
|
@@ -387,6 +472,7 @@ impl RabitqIndex {
|
|
|
387
472
|
Ok(())
|
|
388
473
|
})
|
|
389
474
|
.map_err(to_pyerr)?;
|
|
475
|
+
self.ids.extend(batch_ids.into_iter().map(|i| i as u32));
|
|
390
476
|
Ok(())
|
|
391
477
|
}
|
|
392
478
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Micro-benchmark for Collection insert / insert_batch / search / save / load.
|
|
2
|
+
|
|
3
|
+
Not collected by pytest (no ``test_`` prefix). Run on a quiet machine:
|
|
4
|
+
|
|
5
|
+
python tests/perf/bench_collection.py --n 50000 --dim 256 --repeat 5
|
|
6
|
+
|
|
7
|
+
Each figure is the median of ``--repeat`` runs; the spread (min..max) is printed
|
|
8
|
+
beside it. Data is seeded, so runs are comparable across commits on one machine.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import argparse
|
|
14
|
+
import json
|
|
15
|
+
import statistics
|
|
16
|
+
import tempfile
|
|
17
|
+
import time
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Callable, Dict, List
|
|
20
|
+
|
|
21
|
+
import numpy as np
|
|
22
|
+
|
|
23
|
+
from ruvector.collection import Collection
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def timed(fn: Callable[[], object]) -> float:
|
|
27
|
+
t0 = time.perf_counter()
|
|
28
|
+
fn()
|
|
29
|
+
return time.perf_counter() - t0
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def summarize(samples: List[float]) -> str:
|
|
33
|
+
return f"{statistics.median(samples) * 1000:9.2f} ms [{min(samples) * 1000:.2f}..{max(samples) * 1000:.2f}]"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def bench_backend(backend: str, n: int, dim: int, repeat: int, with_meta: bool) -> Dict[str, List[float]]:
|
|
37
|
+
rng = np.random.default_rng(0)
|
|
38
|
+
vecs = rng.standard_normal((n, dim)).astype(np.float32)
|
|
39
|
+
queries = rng.standard_normal((200, dim)).astype(np.float32)
|
|
40
|
+
metas = [{"i": i, "tag": f"t{i % 50}", "txt": "x" * 40} for i in range(n)] if with_meta else None
|
|
41
|
+
n_single = min(2000, n)
|
|
42
|
+
out: Dict[str, List[float]] = {k: [] for k in ("insert_x2000", "insert_batch", "from_vectors", "search_x200", "save", "load")}
|
|
43
|
+
for _ in range(repeat):
|
|
44
|
+
c = Collection.create(dim=dim, backend=backend)
|
|
45
|
+
if backend == "rabitq": # first row builds; time the add() path after it
|
|
46
|
+
c.insert(vecs[0])
|
|
47
|
+
out["insert_x2000"].append(timed(lambda: [c.insert(vecs[i]) for i in range(1, n_single)]))
|
|
48
|
+
c = Collection.create(dim=dim, backend=backend)
|
|
49
|
+
out["insert_batch"].append(timed(lambda: c.insert_batch(vecs, metadatas=metas)))
|
|
50
|
+
out["from_vectors"].append(timed(lambda: Collection.from_vectors(vecs, backend=backend, metadatas=metas)))
|
|
51
|
+
if backend == "rabitq":
|
|
52
|
+
for i in range(0, n, 10): # 10% tombstones, so search exercises the filter path
|
|
53
|
+
c.delete(i)
|
|
54
|
+
out["search_x200"].append(timed(lambda: [c.search(q, 10) for q in queries]))
|
|
55
|
+
with tempfile.TemporaryDirectory() as d:
|
|
56
|
+
p = Path(d) / "c.idx"
|
|
57
|
+
out["save"].append(timed(lambda: c.save(p)))
|
|
58
|
+
out["load"].append(timed(lambda: Collection.load(p)))
|
|
59
|
+
return out
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def main() -> None:
|
|
63
|
+
ap = argparse.ArgumentParser()
|
|
64
|
+
ap.add_argument("--n", type=int, default=50_000)
|
|
65
|
+
ap.add_argument("--dim", type=int, default=256)
|
|
66
|
+
ap.add_argument("--repeat", type=int, default=5)
|
|
67
|
+
ap.add_argument("--backends", default="hnsw,rabitq")
|
|
68
|
+
ap.add_argument("--no-metadata", action="store_true")
|
|
69
|
+
ap.add_argument("--json", action="store_true")
|
|
70
|
+
a = ap.parse_args()
|
|
71
|
+
results = {}
|
|
72
|
+
for backend in a.backends.split(","):
|
|
73
|
+
results[backend] = bench_backend(backend, a.n, a.dim, a.repeat, not a.no_metadata)
|
|
74
|
+
if a.json:
|
|
75
|
+
print(json.dumps({b: {k: statistics.median(v) for k, v in r.items()} for b, r in results.items()}))
|
|
76
|
+
return
|
|
77
|
+
print(f"n={a.n} dim={a.dim} repeat={a.repeat} metadata={'no' if a.no_metadata else 'yes'}")
|
|
78
|
+
for backend, r in results.items():
|
|
79
|
+
for name, samples in r.items():
|
|
80
|
+
print(f"{backend:7s} {name:14s} {summarize(samples)}")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
if __name__ == "__main__":
|
|
84
|
+
main()
|
|
@@ -6,6 +6,7 @@ from __future__ import annotations
|
|
|
6
6
|
|
|
7
7
|
import json
|
|
8
8
|
from pathlib import Path
|
|
9
|
+
from typing import Any, List, Optional
|
|
9
10
|
|
|
10
11
|
import numpy as np
|
|
11
12
|
import pytest
|
|
@@ -165,6 +166,41 @@ def test_benchmark_human_readable_has_data(runner: CliRunner) -> None:
|
|
|
165
166
|
assert "dim=16" in r.output
|
|
166
167
|
|
|
167
168
|
|
|
169
|
+
@pytest.mark.parametrize("backend", ["hnsw", "rabitq"])
|
|
170
|
+
def test_benchmark_reports_recall(runner: CliRunner, backend: str) -> None:
|
|
171
|
+
r = runner.invoke(
|
|
172
|
+
main, ["benchmark", "-n", "400", "--dim", "16", "--queries", "15", "--backend", backend, "--json"]
|
|
173
|
+
)
|
|
174
|
+
assert r.exit_code == 0, r.output
|
|
175
|
+
result = json.loads(r.output)
|
|
176
|
+
assert result["backend"] == backend
|
|
177
|
+
assert result["recall_k"] == 10
|
|
178
|
+
assert 0.5 <= result["recall_at_10"] <= 1.0
|
|
179
|
+
# the existing latency fields are unchanged
|
|
180
|
+
for key in ("n", "dim", "k", "queries", "build_seconds", "p50_ms", "p99_ms", "qps"):
|
|
181
|
+
assert key in result
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def test_benchmark_recall_k_is_configurable_and_in_human_output(runner: CliRunner) -> None:
|
|
185
|
+
r = runner.invoke(main, ["benchmark", "-n", "300", "--dim", "8", "--queries", "10", "--recall-k", "5"])
|
|
186
|
+
assert r.exit_code == 0, r.output
|
|
187
|
+
assert "recall@5=" in r.output
|
|
188
|
+
j = json.loads(runner.invoke(main, ["benchmark", "-n", "300", "--dim", "8", "--queries", "10", "--recall-k", "5", "--json"]).output)
|
|
189
|
+
assert "recall_at_5" in j and "recall_at_10" not in j
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def test_benchmark_recall_is_exact_for_tiny_corpus(runner: CliRunner) -> None:
|
|
193
|
+
# n <= recall-k: every vector is in the top-k, so recall must be exactly 1.0
|
|
194
|
+
r = runner.invoke(main, ["benchmark", "-n", "6", "--dim", "8", "--queries", "5", "--recall-k", "10", "--json"])
|
|
195
|
+
assert r.exit_code == 0, r.output
|
|
196
|
+
assert json.loads(r.output)["recall_at_10"] == 1.0
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def test_benchmark_rejects_nonpositive_recall_k(runner: CliRunner) -> None:
|
|
200
|
+
r = runner.invoke(main, ["benchmark", "-n", "50", "--dim", "8", "--recall-k", "0"])
|
|
201
|
+
assert r.exit_code != 0
|
|
202
|
+
|
|
203
|
+
|
|
168
204
|
def test_search_no_color_flag_forces_plain(runner: CliRunner, tmp_path: Path) -> None:
|
|
169
205
|
"""--no-color is a no-op in terms of data under CliRunner (already
|
|
170
206
|
non-TTY => already plain), but exercise the flag itself end to end so
|
|
@@ -263,3 +299,39 @@ def test_serve_without_mcp_sdk_gives_install_hint(runner: CliRunner, monkeypatch
|
|
|
263
299
|
assert result.exit_code != 0
|
|
264
300
|
assert "ruvector[mcp]" in result.output
|
|
265
301
|
assert "Traceback" not in result.output
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
# ── serve --max-vectors ─────────────────────────────────────────────────────
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def test_serve_max_vectors_option_sets_cap(runner: CliRunner, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
308
|
+
pytest.importorskip("mcp")
|
|
309
|
+
import ruvector.mcp_server as m
|
|
310
|
+
|
|
311
|
+
monkeypatch.delenv("RUVECTOR_MCP_MAX_VECTORS", raising=False)
|
|
312
|
+
monkeypatch.setattr(m.server, "run", lambda *a, **kw: None)
|
|
313
|
+
try:
|
|
314
|
+
result = runner.invoke(main, ["serve", "--max-vectors", "123"])
|
|
315
|
+
assert result.exit_code == 0, result.output
|
|
316
|
+
assert m.max_vectors() == 123
|
|
317
|
+
finally:
|
|
318
|
+
m.set_max_vectors(None)
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
@pytest.mark.parametrize("args,env", [(["--max-vectors", "0"], None), ([], "nope")])
|
|
322
|
+
def test_serve_rejects_bad_max_vectors(
|
|
323
|
+
runner: CliRunner, monkeypatch: pytest.MonkeyPatch, args: List[str], env: Optional[str]
|
|
324
|
+
) -> None:
|
|
325
|
+
pytest.importorskip("mcp")
|
|
326
|
+
import ruvector.mcp_server as m
|
|
327
|
+
|
|
328
|
+
ran: List[Any] = []
|
|
329
|
+
monkeypatch.setattr(m.server, "run", lambda *a, **kw: ran.append(1))
|
|
330
|
+
if env is None:
|
|
331
|
+
monkeypatch.delenv("RUVECTOR_MCP_MAX_VECTORS", raising=False)
|
|
332
|
+
else:
|
|
333
|
+
monkeypatch.setenv("RUVECTOR_MCP_MAX_VECTORS", env)
|
|
334
|
+
result = runner.invoke(main, ["serve", *args])
|
|
335
|
+
assert result.exit_code != 0
|
|
336
|
+
assert "positive integer" in result.output
|
|
337
|
+
assert not ran
|
|
@@ -499,3 +499,107 @@ def test_apply_read_only_removes_mutating_tools(tmp_path: Path, monkeypatch: pyt
|
|
|
499
499
|
_call(m, gone, name="x")
|
|
500
500
|
finally:
|
|
501
501
|
importlib.reload(m)
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
def test_validation_errors_reach_the_client():
|
|
505
|
+
"""mcp 2.x masks non-ToolError exceptions; our validation messages must get through (issue #1134)."""
|
|
506
|
+
import asyncio
|
|
507
|
+
|
|
508
|
+
from mcp.server.mcpserver.exceptions import ToolError
|
|
509
|
+
|
|
510
|
+
from ruvector import mcp_server as m
|
|
511
|
+
|
|
512
|
+
async def call(name, args):
|
|
513
|
+
return await m.server.call_tool(name, args)
|
|
514
|
+
|
|
515
|
+
try:
|
|
516
|
+
asyncio.run(call("vector_create_collection", {"name": "../escape", "dim": 4}))
|
|
517
|
+
except ToolError as e:
|
|
518
|
+
assert "invalid collection name" in str(e)
|
|
519
|
+
else:
|
|
520
|
+
raise AssertionError("expected ToolError")
|
|
521
|
+
try:
|
|
522
|
+
asyncio.run(call("vector_search", {"name": "no-such-collection", "query": [1.0, 2.0, 3.0, 4.0], "k": 1}))
|
|
523
|
+
except ToolError as e:
|
|
524
|
+
assert "no such collection" in str(e)
|
|
525
|
+
else:
|
|
526
|
+
raise AssertionError("expected ToolError")
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
# ── per-collection vector cap ────────────────────────────────────────────
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
@pytest.fixture
|
|
533
|
+
def capped(server_module: ModuleType, monkeypatch: pytest.MonkeyPatch) -> ModuleType:
|
|
534
|
+
monkeypatch.delenv("RUVECTOR_MCP_MAX_VECTORS", raising=False)
|
|
535
|
+
server_module.set_max_vectors(None)
|
|
536
|
+
yield server_module
|
|
537
|
+
server_module.set_max_vectors(None)
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
def test_default_vector_cap_is_one_million(capped: ModuleType) -> None:
|
|
541
|
+
assert capped.max_vectors() == 1_000_000
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
def test_env_var_sets_vector_cap_and_option_wins(capped: ModuleType, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
545
|
+
monkeypatch.setenv("RUVECTOR_MCP_MAX_VECTORS", "7")
|
|
546
|
+
assert capped.max_vectors() == 7
|
|
547
|
+
capped.set_max_vectors(3)
|
|
548
|
+
assert capped.max_vectors() == 3
|
|
549
|
+
capped.set_max_vectors(None)
|
|
550
|
+
monkeypatch.setenv("RUVECTOR_MCP_MAX_VECTORS", " ")
|
|
551
|
+
assert capped.max_vectors() == 1_000_000 # blank counts as unset
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
@pytest.mark.parametrize("bad", ["0", "-5", "abc", "1.5"])
|
|
555
|
+
def test_invalid_vector_cap_is_rejected(capped: ModuleType, monkeypatch: pytest.MonkeyPatch, bad: str) -> None:
|
|
556
|
+
monkeypatch.setenv("RUVECTOR_MCP_MAX_VECTORS", bad)
|
|
557
|
+
with pytest.raises(ValueError, match="RUVECTOR_MCP_MAX_VECTORS"):
|
|
558
|
+
capped.max_vectors()
|
|
559
|
+
with pytest.raises(ValueError):
|
|
560
|
+
capped.set_max_vectors(int(bad) if bad.lstrip("-").isdigit() else 0)
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
def test_insert_stops_at_vector_cap(capped: ModuleType) -> None:
|
|
564
|
+
m = capped
|
|
565
|
+
m.set_max_vectors(2)
|
|
566
|
+
_call(m, "vector_create_collection", name="cap1", dim=2)
|
|
567
|
+
_call(m, "vector_insert", name="cap1", vector=[1.0, 0.0])
|
|
568
|
+
_call(m, "vector_insert", name="cap1", vector=[0.0, 1.0])
|
|
569
|
+
with _raises_chain(r"vector limit.*maximum of 2"):
|
|
570
|
+
_call(m, "vector_insert", name="cap1", vector=[1.0, 1.0])
|
|
571
|
+
assert _call(m, "vector_stats", name="cap1")["count"] == 2
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
def test_batch_insert_is_all_or_nothing_at_cap(capped: ModuleType) -> None:
|
|
575
|
+
m = capped
|
|
576
|
+
m.set_max_vectors(3)
|
|
577
|
+
_call(m, "vector_create_collection", name="cap2", dim=2)
|
|
578
|
+
_call(m, "vector_insert_batch", name="cap2", vectors=[[1.0, 0.0], [0.0, 1.0]])
|
|
579
|
+
with _raises_chain("maximum of 3"):
|
|
580
|
+
_call(m, "vector_insert_batch", name="cap2", vectors=[[1.0, 1.0], [2.0, 2.0]])
|
|
581
|
+
assert _call(m, "vector_stats", name="cap2")["count"] == 2 # nothing partially written
|
|
582
|
+
_call(m, "vector_insert_batch", name="cap2", vectors=[[1.0, 1.0]]) # exactly reaches the cap
|
|
583
|
+
assert _call(m, "vector_stats", name="cap2")["count"] == 3
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
def test_cap_message_is_a_tool_error(capped: ModuleType) -> None:
|
|
587
|
+
"""mcp 2.x hides non-ToolError messages from the client; the cap text must survive."""
|
|
588
|
+
from mcp.server.mcpserver.exceptions import ToolError
|
|
589
|
+
|
|
590
|
+
m = capped
|
|
591
|
+
m.set_max_vectors(1)
|
|
592
|
+
_call(m, "vector_create_collection", name="cap3", dim=2)
|
|
593
|
+
_call(m, "vector_insert", name="cap3", vector=[1.0, 0.0])
|
|
594
|
+
with pytest.raises(ToolError, match="vector limit"):
|
|
595
|
+
asyncio.run(m.server.call_tool("vector_insert", {"name": "cap3", "vector": [0.0, 1.0]}))
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
@pytest.mark.parametrize("backend", ["hnsw", "rabitq"])
|
|
599
|
+
def test_deleted_rows_count_until_vacuumed(capped: ModuleType, backend: str) -> None:
|
|
600
|
+
m = capped
|
|
601
|
+
m.set_max_vectors(2)
|
|
602
|
+
_call(m, "vector_create_collection", name=f"cap4{backend}", dim=2, backend=backend)
|
|
603
|
+
ids = _call(m, "vector_insert_batch", name=f"cap4{backend}", vectors=[[1.0, 0.0], [0.0, 1.0]])["ids"]
|
|
604
|
+
_call(m, "vector_delete", name=f"cap4{backend}", id=ids[0], vacuum=True)
|
|
605
|
+
_call(m, "vector_insert", name=f"cap4{backend}", vector=[1.0, 1.0]) # vacuumed -> room again
|