ruvector 0.1.1__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.1 → ruvector-0.1.2}/Cargo.lock +1 -1
- {ruvector-0.1.1 → ruvector-0.1.2}/PKG-INFO +12 -1
- {ruvector-0.1.1 → ruvector-0.1.2}/README.md +11 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/Cargo.toml +1 -1
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/README.md +11 -0
- ruvector-0.1.2/crates/ruvector-py/tests/perf/bench_collection.py +84 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/tests/test_cli.py +72 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/tests/test_mcp_server.py +79 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/tests/test_smoke.py +1 -1
- {ruvector-0.1.1 → ruvector-0.1.2}/pyproject.toml +1 -1
- {ruvector-0.1.1 → ruvector-0.1.2}/python/ruvector/cli.py +81 -7
- {ruvector-0.1.1 → ruvector-0.1.2}/python/ruvector/mcp_server.py +67 -3
- {ruvector-0.1.1 → ruvector-0.1.2}/Cargo.toml +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/LICENSE +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/Cargo.toml +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/LICENSE +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/README.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/benches/attention_bench.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/benches/attention_benchmarks.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/docs/IMPLEMENTATION_SUMMARY.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/docs/SDK_GUIDE.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/examples/hyperbolic_bench.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/attention/flash.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/attention/kv_cache.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/attention/mla.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/attention/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/attention/multi_head.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/attention/scaled_dot_product.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/attention/speculative.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/attention/ssm.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/config.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/curvature/component_quantizer.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/curvature/fused_attention.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/curvature/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/curvature/tangent_space.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/error.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/graph/dual_space.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/graph/edge_featured.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/graph/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/graph/rope.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/hyperbolic/hyperbolic_attention.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/hyperbolic/lorentz_cascade.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/hyperbolic/mixed_curvature.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/hyperbolic/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/hyperbolic/poincare.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/info_bottleneck/bottleneck.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/info_bottleneck/kl_divergence.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/info_bottleneck/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/info_geometry/fisher.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/info_geometry/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/info_geometry/natural_gradient.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/lib.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/moe/expert.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/moe/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/moe/moe_attention.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/moe/router.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/pde_attention/diffusion.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/pde_attention/laplacian.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/pde_attention/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/sdk/builder.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/sdk/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/sdk/pipeline.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/sdk/presets.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/sheaf/attention.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/sheaf/early_exit.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/sheaf/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/sheaf/restriction.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/sheaf/router.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/sheaf/sparse.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/sparse/flash.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/sparse/linear.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/sparse/local_global.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/sparse/mask.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/sparse/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/topology/coherence.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/topology/gated_attention.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/topology/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/topology/policy.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/training/curriculum.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/training/loss.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/training/mining.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/training/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/training/optimizer.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/traits.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/transport/cached_projections.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/transport/centroid_ot.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/transport/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/transport/sliced_wasserstein.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/unified_report/metrics.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/unified_report/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/unified_report/report.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-attention/src/utils.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-cluster/Cargo.toml +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-cluster/README.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-cluster/package.json +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-cluster/src/consensus.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-cluster/src/discovery.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-cluster/src/lib.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-cluster/src/shard.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-cluster/tests/integration_tests.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-cluster-rag/Cargo.toml +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-cluster-rag/README.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-cluster-rag/src/bench.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-cluster-rag/src/bin/benchmark.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-cluster-rag/src/cluster.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-cluster-rag/src/dataset.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-cluster-rag/src/lib.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-cluster-rag/src/search.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-cluster-rag/src/tree.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/Cargo.toml +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/README.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/benches/batch_operations.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/benches/bench_memory.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/benches/bench_simd.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/benches/comprehensive_bench.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/benches/distance_metrics.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/benches/hnsw_search.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/benches/pdx_vs_rowmajor.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/benches/quantization_bench.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/benches/real_benchmark.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/docs/EMBEDDINGS.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/examples/embeddings_example.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/examples/lattice_embedding_example.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/examples/neon_benchmark.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/advanced/hypergraph.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/advanced/learned_index.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/advanced/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/advanced/neural_hash.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/advanced/tda.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/compaction.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/conformal_prediction.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/diskann.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/filtered_search.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/graph_rag.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/hybrid_search.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/matryoshka.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/mmr.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/multi_vector.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/opq.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/product_quantization.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features/sparse_vector.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/advanced_features.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/agenticdb.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/arena.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/cache_optimized.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/distance.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/embeddings.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/encoding/codecs.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/encoding.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/error.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/index/flat.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/index/hnsw.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/index/turbo4.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/index.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/integration.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/lib.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/lockfree.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/memory.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/pdx.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/quantization.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/simd_intrinsics.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/storage.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/storage_compat.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/storage_memory.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/types.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/src/vector_db.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/tests/README.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/tests/advanced_features_integration.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/tests/concurrent_tests.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/tests/embeddings_role_test.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/tests/embeddings_test.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/tests/hnsw_773_recall_distributions.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/tests/hnsw_integration_test.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/tests/hnsw_issue_773_regression.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/tests/hnsw_issue_773_structural.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/tests/integration_tests.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/tests/property_tests.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/tests/stress_tests.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/tests/test_memory_pool.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/tests/test_quantization.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/tests/test_simd_correctness.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-core/tests/unit_tests.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-diskann/Cargo.toml +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-diskann/examples/bench_delete_recall.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-diskann/examples/bench_search_hot.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-diskann/examples/mmap_674_bench.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-diskann/src/distance.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-diskann/src/error.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-diskann/src/graph.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-diskann/src/index.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-diskann/src/lib.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-diskann/src/pq.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-diskann/src/reuse.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-diskann/tests/search_allocations.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/Cargo.toml +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/README.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/examples/diskann_real_trajectory.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/examples/loss_demo.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/examples/triggered_rebuild.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/src/cold_tier.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/src/compress.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/src/error.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/src/ewc.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/src/graphmae.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/src/layer.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/src/lib.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/src/mmap.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/src/mmap_fixed.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/src/query.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/src/replay.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/src/scheduler.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/src/search.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/src/tensor.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/src/training.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-gnn/tests/loss_verification.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/ARCHITECTURE.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/Cargo.toml +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/README.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/benches/cypher_parser.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/benches/distributed_query.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/benches/graph_bench.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/benches/graph_traversal.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/benches/hybrid_vector_graph.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/benches/new_capabilities_bench.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/benches/query_execution.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/benches/simd_operations.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/benches/typed_graph_bench.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/examples/test_cypher_parser.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/bm25.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/codegen.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/cypher/README.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/cypher/ast.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/cypher/lexer.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/cypher/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/cypher/optimizer.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/cypher/parser.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/cypher/semantic.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/distributed/coordinator.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/distributed/federation.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/distributed/gossip.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/distributed/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/distributed/replication.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/distributed/rpc.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/distributed/shard.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/edge.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/embed.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/error.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/executor/cache.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/executor/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/executor/operators.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/executor/parallel.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/executor/pipeline.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/executor/plan.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/executor/stats.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/graph.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/hybrid/cypher_extensions.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/hybrid/graph_neural.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/hybrid/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/hybrid/rag_integration.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/hybrid/semantic_search.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/hybrid/vector_index.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/hyperedge.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/index.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/lib.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/node.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/optimization/adaptive_radix.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/optimization/bloom_filter.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/optimization/cache_hierarchy.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/optimization/index_compression.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/optimization/memory_pool.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/optimization/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/optimization/query_jit.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/optimization/simd_traversal.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/schema.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/storage.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/transaction.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/typed_graph.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/src/types.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/tests/compatibility_tests.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/tests/concurrent_tests.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/tests/cypher_execution_tests.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/tests/cypher_parser_integration.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/tests/cypher_parser_tests.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/tests/distributed_tests.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/tests/edge_tests.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/tests/fixtures/README.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/tests/fixtures/expected_results.json +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/tests/fixtures/movie_database.json +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/tests/fixtures/social_network.json +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/tests/hyperedge_tests.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/tests/node_tests.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/tests/performance_tests.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-graph/tests/transaction_tests.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/Cargo.toml +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/README.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/benches/information_geometry.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/benches/optimal_transport.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/benches/product_manifold.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/benches/spectral.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/benches/tropical.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/error.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/homology/distance.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/homology/filtration.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/homology/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/homology/persistence.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/homology/simplex.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/information_geometry/fisher.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/information_geometry/kfac.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/information_geometry/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/information_geometry/natural_gradient.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/lib.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/optimal_transport/config.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/optimal_transport/gromov_wasserstein.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/optimal_transport/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/optimal_transport/sinkhorn.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/optimal_transport/sliced_wasserstein.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/optimization/certificates.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/optimization/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/optimization/polynomial.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/optimization/sdp.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/optimization/sos.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/product_manifold/config.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/product_manifold/manifold.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/product_manifold/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/product_manifold/operations.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/spectral/chebyshev.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/spectral/clustering.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/spectral/graph_filter.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/spectral/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/spectral/wavelets.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/spherical/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/tensor_networks/contraction.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/tensor_networks/cp_decomposition.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/tensor_networks/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/tensor_networks/tensor_train.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/tensor_networks/tucker.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/tropical/matrix.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/tropical/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/tropical/neural_analysis.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/tropical/polynomial.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/tropical/semiring.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/utils/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/utils/numerical.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-math/src/utils/sorting.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/.gitignore +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/LICENSE +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/benchmarks/bench_compare_rabitq.py +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/benchmarks/bench_hnsw_real_embeddings.py +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/scripts/check-release-version.sh +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/scripts/sdist-add-patches.sh +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/src/cluster.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/src/error.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/src/gnn.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/src/graph/convert.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/src/graph/cypher_bridge.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/src/graph/cypher_eval.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/src/graph/cypher_exec.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/src/graph.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/src/hnsw.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/src/lib.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/src/rabitq.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/src/sona.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/tests/test_cluster.py +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/tests/test_collection.py +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/tests/test_gnn.py +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/tests/test_graph.py +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/tests/test_graph_cypher.py +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/tests/test_langchain_integration.py +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/tests/test_llamaindex_integration.py +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/tests/test_salesforce_integration.py +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/tests/test_salesforce_routes.py +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-py/tests/test_sona.py +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-rabitq/BENCHMARK.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-rabitq/Cargo.toml +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-rabitq/benches/rabitq_bench.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-rabitq/src/error.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-rabitq/src/index.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-rabitq/src/kernel.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-rabitq/src/lib.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-rabitq/src/main.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-rabitq/src/persist.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-rabitq/src/quantize.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-rabitq/src/rotation.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-rabitq/src/scan.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-raft/Cargo.toml +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-raft/README.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-raft/src/election.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-raft/src/lib.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-raft/src/log.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-raft/src/node.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-raft/src/rpc.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-raft/src/state.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-raft/tests/integration_tests.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-replication/Cargo.toml +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-replication/README.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-replication/src/conflict.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-replication/src/failover.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-replication/src/lib.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-replication/src/replica.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-replication/src/stream.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-replication/src/sync.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-turboquant/Cargo.toml +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-turboquant/benches/kernels.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-turboquant/src/bits1.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-turboquant/src/codec.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-turboquant/src/lib.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-turboquant/src/rotation.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-turboquant/src/score.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-turboquant/src/simd.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/ruvector-turboquant/src/tables.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/Cargo.toml +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/LICENSE-APACHE +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/LICENSE-MIT +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/README.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/auto_tuner.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/darwin_guard.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/engine.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/ewc.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/export/dataset.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/export/huggingface_hub.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/export/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/export/pretrain.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/export/safetensors.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/lib.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/loops/background.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/loops/coordinator.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/loops/instant.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/loops/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/lora.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/napi.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/napi_simple.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/reasoning_bank.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/time_compat.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/training/factory.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/training/federated.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/training/metrics.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/training/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/training/pipeline.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/training/templates.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/trajectory.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/types.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/src/wasm.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/crates/sona/wasm-example/README.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/.gitignore +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/Cargo.toml +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/Changes.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/LICENSE-APACHE +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/LICENSE-MIT +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/README.md +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/examples/ann-glove25-angular.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/examples/ann-mnist-784-euclidean.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/examples/ann-sift1m-128-euclidean.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/examples/levensthein.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/examples/random.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/examples/utils/annhdf5.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/examples/utils/mod.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/src/api.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/src/datamap.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/src/filter.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/src/flatten.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/src/hnsw.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/src/hnswio.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/src/lib.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/src/libext.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/src/prelude.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/tests/deallocation_test.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/tests/filtertest.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/patches/hnsw_rs/tests/serpar.rs +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/python/ruvector/__init__.py +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/python/ruvector/__init__.pyi +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/python/ruvector/_native.pyi +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/python/ruvector/collection.py +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/python/ruvector/integrations/__init__.py +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/python/ruvector/integrations/langchain.py +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/python/ruvector/integrations/llamaindex.py +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/python/ruvector/integrations/salesforce.py +0 -0
- {ruvector-0.1.1 → ruvector-0.1.2}/python/ruvector/py.typed +0 -0
- {ruvector-0.1.1 → 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
|
|
@@ -137,6 +137,7 @@ ruvector benchmark -n 100000 --dim 128 # in-process latency/QPS, no external
|
|
|
137
137
|
ruvector serve # MCP server over stdio
|
|
138
138
|
ruvector serve --http --port 8420 # MCP server over streamable-HTTP (loopback)
|
|
139
139
|
ruvector serve --read-only # no create/insert/delete tools
|
|
140
|
+
ruvector serve --max-vectors 50000 # cap vectors per collection (default 1,000,000)
|
|
140
141
|
```
|
|
141
142
|
|
|
142
143
|
`serve --http` on a non-loopback `--host` refuses to start unless
|
|
@@ -162,6 +163,16 @@ directory-traversal surface regardless of what a remote MCP client sends.
|
|
|
162
163
|
See `ruvector/mcp_server.py`'s module docstring for the full security
|
|
163
164
|
model.
|
|
164
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
|
+
|
|
165
176
|
```sh
|
|
166
177
|
# point an MCP client at: ruvector serve (stdio)
|
|
167
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
|
|
@@ -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
|
|
@@ -524,3 +524,82 @@ def test_validation_errors_reach_the_client():
|
|
|
524
524
|
assert "no such collection" in str(e)
|
|
525
525
|
else:
|
|
526
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
|
|
@@ -26,7 +26,7 @@ import ruvector
|
|
|
26
26
|
def test_version() -> None:
|
|
27
27
|
assert ruvector.__version__
|
|
28
28
|
# Cargo.toml ships 0.1.0; if you bump there, bump here.
|
|
29
|
-
assert ruvector.__version__ == "0.1.
|
|
29
|
+
assert ruvector.__version__ == "0.1.2"
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def test_build_and_search() -> None:
|
|
@@ -335,18 +335,67 @@ def info(path: str, as_json: bool, no_color: bool) -> None:
|
|
|
335
335
|
console.print(Panel(table, title=f"[bold]{p.name}[/bold]", expand=False))
|
|
336
336
|
|
|
337
337
|
|
|
338
|
+
def _recall_at_k(coll: "Collection", vecs: "NDArray[np.float32]", qs: "NDArray[np.float32]", k: int) -> float:
|
|
339
|
+
"""Mean recall@k of ``coll.search`` against exact brute-force top-k.
|
|
340
|
+
|
|
341
|
+
Ground truth uses the collection's own metric (cosine, or squared L2 for
|
|
342
|
+
rabitq). Ids are row indices because the benchmark builds with the
|
|
343
|
+
default ``ids=range(n)``. Ties at the k-th distance are resolved by the
|
|
344
|
+
stable sort, so recall can differ from 1.0 only through the index.
|
|
345
|
+
"""
|
|
346
|
+
import numpy as np
|
|
347
|
+
|
|
348
|
+
k = min(k, vecs.shape[0])
|
|
349
|
+
if coll.metric == "squared_l2":
|
|
350
|
+
# |v|^2 - 2 v.q (|q|^2 is constant per query and does not change the order)
|
|
351
|
+
scores = (vecs * vecs).sum(axis=1)[None, :] - 2.0 * (qs @ vecs.T)
|
|
352
|
+
else:
|
|
353
|
+
vn = vecs / np.maximum(np.linalg.norm(vecs, axis=1, keepdims=True), 1e-30)
|
|
354
|
+
scores = -(qs @ vn.T) # cosine order = order of v.q / |v|, |q| is per-query constant
|
|
355
|
+
truth = np.argsort(scores, axis=1, kind="stable")[:, :k]
|
|
356
|
+
total = 0.0
|
|
357
|
+
for i in range(qs.shape[0]):
|
|
358
|
+
got = {hit.id for hit in coll.search(qs[i], k)}
|
|
359
|
+
total += len(got.intersection(truth[i].tolist())) / k
|
|
360
|
+
return total / qs.shape[0]
|
|
361
|
+
|
|
362
|
+
|
|
338
363
|
@main.command()
|
|
339
364
|
@click.option("-n", default=10_000, show_default=True, type=int, help="Number of vectors.")
|
|
340
365
|
@click.option("--dim", default=128, show_default=True, type=int)
|
|
341
366
|
@click.option("--k", default=10, show_default=True, type=int)
|
|
342
367
|
@click.option("--queries", default=100, show_default=True, type=int)
|
|
343
|
-
@click.option("--rerank-factor", default=20, show_default=True, type=int)
|
|
368
|
+
@click.option("--rerank-factor", default=20, show_default=True, type=int, help="Only used by --backend rabitq.")
|
|
369
|
+
@click.option(
|
|
370
|
+
"--backend",
|
|
371
|
+
default="hnsw",
|
|
372
|
+
show_default=True,
|
|
373
|
+
type=click.Choice(["hnsw", "rabitq"]),
|
|
374
|
+
help="Index backend to benchmark.",
|
|
375
|
+
)
|
|
376
|
+
@click.option(
|
|
377
|
+
"--recall-k",
|
|
378
|
+
default=10,
|
|
379
|
+
show_default=True,
|
|
380
|
+
type=int,
|
|
381
|
+
help="k for recall@k, measured against exact brute-force search over the same vectors.",
|
|
382
|
+
)
|
|
344
383
|
@click.option("--json", "as_json", is_flag=True, default=False)
|
|
345
|
-
def benchmark(
|
|
346
|
-
|
|
347
|
-
|
|
384
|
+
def benchmark(
|
|
385
|
+
n: int, dim: int, k: int, queries: int, rerank_factor: int, backend: str, recall_k: int, as_json: bool
|
|
386
|
+
) -> None:
|
|
387
|
+
"""Run an in-memory build+search benchmark: latency, QPS and recall@k
|
|
388
|
+
against exact brute-force search (no comparator — see the ADR-352
|
|
389
|
+
benchmark methodology for a real side-by-side).
|
|
390
|
+
|
|
391
|
+
Recall is computed on the same queries as the latency loop, using the
|
|
392
|
+
index's own distance (cosine for hnsw, squared L2 for rabitq), and is
|
|
393
|
+
not included in the timings."""
|
|
348
394
|
import time
|
|
349
395
|
|
|
396
|
+
if n < 1 or dim < 1 or k < 1 or queries < 1 or recall_k < 1:
|
|
397
|
+
raise click.ClickException("-n, --dim, --k, --queries and --recall-k must all be >= 1")
|
|
398
|
+
|
|
350
399
|
import numpy as np
|
|
351
400
|
|
|
352
401
|
from ruvector.collection import Collection
|
|
@@ -355,7 +404,7 @@ def benchmark(n: int, dim: int, k: int, queries: int, rerank_factor: int, as_jso
|
|
|
355
404
|
vecs = rng.standard_normal((n, dim)).astype(np.float32)
|
|
356
405
|
|
|
357
406
|
t0 = time.perf_counter()
|
|
358
|
-
coll = Collection.from_vectors(vecs, rerank_factor=rerank_factor)
|
|
407
|
+
coll = Collection.from_vectors(vecs, backend=backend, rerank_factor=rerank_factor)
|
|
359
408
|
build_s = time.perf_counter() - t0
|
|
360
409
|
|
|
361
410
|
qs = rng.standard_normal((queries, dim)).astype(np.float32)
|
|
@@ -368,8 +417,13 @@ def benchmark(n: int, dim: int, k: int, queries: int, rerank_factor: int, as_jso
|
|
|
368
417
|
p50 = latencies[len(latencies) // 2]
|
|
369
418
|
p99 = latencies[int(len(latencies) * 0.99) - 1]
|
|
370
419
|
|
|
420
|
+
recall = _recall_at_k(coll, vecs, qs, recall_k)
|
|
421
|
+
|
|
371
422
|
result = {
|
|
372
423
|
"n": n, "dim": dim, "k": k, "queries": queries, "rerank_factor": rerank_factor,
|
|
424
|
+
"backend": backend,
|
|
425
|
+
f"recall_at_{recall_k}": recall,
|
|
426
|
+
"recall_k": recall_k,
|
|
373
427
|
"build_seconds": build_s,
|
|
374
428
|
"p50_ms": p50 * 1000,
|
|
375
429
|
"p99_ms": p99 * 1000,
|
|
@@ -381,7 +435,8 @@ def benchmark(n: int, dim: int, k: int, queries: int, rerank_factor: int, as_jso
|
|
|
381
435
|
else:
|
|
382
436
|
_secho(
|
|
383
437
|
f"n={n} dim={dim} build={build_s:.3f}s p50={result['p50_ms']:.3f}ms "
|
|
384
|
-
f"p99={result['p99_ms']:.3f}ms qps={result['qps']:.0f}"
|
|
438
|
+
f"p99={result['p99_ms']:.3f}ms qps={result['qps']:.0f} "
|
|
439
|
+
f"recall@{recall_k}={recall:.4f}",
|
|
385
440
|
fg="cyan",
|
|
386
441
|
)
|
|
387
442
|
|
|
@@ -396,7 +451,14 @@ def benchmark(n: int, dim: int, k: int, queries: int, rerank_factor: int, as_jso
|
|
|
396
451
|
default=False,
|
|
397
452
|
help="Do not register mutating tools (create/insert/insert_batch/delete) or the Salesforce upsert route.",
|
|
398
453
|
)
|
|
399
|
-
|
|
454
|
+
@click.option(
|
|
455
|
+
"--max-vectors",
|
|
456
|
+
default=None,
|
|
457
|
+
type=int,
|
|
458
|
+
help="Maximum vectors per collection a client may write "
|
|
459
|
+
"(default 1000000; also settable with RUVECTOR_MCP_MAX_VECTORS; this option wins).",
|
|
460
|
+
)
|
|
461
|
+
def serve(use_http: bool, host: str, port: int, read_only: bool, max_vectors: Optional[int]) -> None:
|
|
400
462
|
"""Launch the ruvector MCP server (stdio by default).
|
|
401
463
|
|
|
402
464
|
If ``RUVECTOR_ENABLE_SALESFORCE_ACTIONS`` is set, also mounts the
|
|
@@ -423,6 +485,18 @@ def serve(use_http: bool, host: str, port: int, read_only: bool) -> None:
|
|
|
423
485
|
if read_only:
|
|
424
486
|
apply_read_only()
|
|
425
487
|
|
|
488
|
+
try:
|
|
489
|
+
if max_vectors is not None:
|
|
490
|
+
from ruvector.mcp_server import set_max_vectors
|
|
491
|
+
|
|
492
|
+
set_max_vectors(max_vectors)
|
|
493
|
+
else:
|
|
494
|
+
from ruvector.mcp_server import max_vectors as _effective_max_vectors
|
|
495
|
+
|
|
496
|
+
_effective_max_vectors() # fail at startup, not on the first insert, if the env var is malformed
|
|
497
|
+
except ValueError as exc:
|
|
498
|
+
raise click.ClickException(str(exc)) from exc
|
|
499
|
+
|
|
426
500
|
if use_http and os.environ.get("RUVECTOR_ENABLE_SALESFORCE_ACTIONS"):
|
|
427
501
|
from ruvector.salesforce_routes import SalesforceAuthNotConfiguredError, maybe_register
|
|
428
502
|
|
|
@@ -78,7 +78,7 @@ import re
|
|
|
78
78
|
import sys
|
|
79
79
|
import threading
|
|
80
80
|
from pathlib import Path
|
|
81
|
-
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
|
81
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
|
|
82
82
|
|
|
83
83
|
from mcp.server.auth.middleware.auth_context import get_access_token
|
|
84
84
|
from mcp.server.auth.provider import AccessToken, TokenVerifier
|
|
@@ -105,6 +105,13 @@ _NAME_RE = re.compile(r"^[A-Za-z0-9_-]{1,128}$")
|
|
|
105
105
|
MAX_BATCH_ROWS = 10_000
|
|
106
106
|
MAX_BATCH_ELEMENTS = 2_000_000 # rows * dim floats per insert_batch call (~8 MB as float32)
|
|
107
107
|
MAX_METADATA_BYTES = 65_536 # serialized JSON, per row
|
|
108
|
+
# Total vectors a client may write into ONE collection (a cumulative cap, unlike
|
|
109
|
+
# the per-call caps above). Every write re-saves the whole collection, so an
|
|
110
|
+
# unbounded collection also makes each later write slower. Override with the
|
|
111
|
+
# RUVECTOR_MCP_MAX_VECTORS environment variable or `ruvector serve --max-vectors`.
|
|
112
|
+
DEFAULT_MAX_VECTORS = 1_000_000
|
|
113
|
+
_MAX_VECTORS_ENV_VAR = "RUVECTOR_MCP_MAX_VECTORS"
|
|
114
|
+
_max_vectors_override: Optional[int] = None
|
|
108
115
|
|
|
109
116
|
_TOKEN_ENV_VAR = "RUVECTOR_MCP_TOKEN"
|
|
110
117
|
# Self-referential placeholder — this design does not do real OAuth
|
|
@@ -263,6 +270,52 @@ def _save(name: str, coll: "Collection") -> None:
|
|
|
263
270
|
_cache[name] = coll
|
|
264
271
|
|
|
265
272
|
|
|
273
|
+
def parse_max_vectors(raw: Union[str, int], source: str) -> int:
|
|
274
|
+
"""Validate a vectors-per-collection cap; raises ``ValueError`` if not a positive int."""
|
|
275
|
+
try:
|
|
276
|
+
value = int(str(raw).strip())
|
|
277
|
+
except ValueError:
|
|
278
|
+
raise ValueError(f"{source} must be a positive integer, got {raw!r}") from None
|
|
279
|
+
if value < 1:
|
|
280
|
+
raise ValueError(f"{source} must be a positive integer, got {raw!r}")
|
|
281
|
+
return value
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def set_max_vectors(value: Optional[int]) -> None:
|
|
285
|
+
"""Set (or with ``None`` clear) the cap given on the command line; it wins over the environment."""
|
|
286
|
+
global _max_vectors_override
|
|
287
|
+
_max_vectors_override = None if value is None else parse_max_vectors(value, "max vectors")
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def max_vectors() -> int:
|
|
291
|
+
"""Effective per-collection cap: ``--max-vectors``, else the env var, else the default.
|
|
292
|
+
|
|
293
|
+
An empty env var counts as unset.
|
|
294
|
+
"""
|
|
295
|
+
if _max_vectors_override is not None:
|
|
296
|
+
return _max_vectors_override
|
|
297
|
+
raw = os.environ.get(_MAX_VECTORS_ENV_VAR, "").strip()
|
|
298
|
+
return parse_max_vectors(raw, _MAX_VECTORS_ENV_VAR) if raw else DEFAULT_MAX_VECTORS
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def _check_capacity(coll: "Collection", incoming: int) -> None:
|
|
302
|
+
"""Reject a write that would take the collection past the cap.
|
|
303
|
+
|
|
304
|
+
Counts tombstoned rows too: they still occupy the index and the saved
|
|
305
|
+
files until ``vector_delete(..., vacuum=True)`` runs.
|
|
306
|
+
"""
|
|
307
|
+
cap = max_vectors()
|
|
308
|
+
stats = coll.stats()
|
|
309
|
+
used = stats.count + stats.tombstoned
|
|
310
|
+
if used + incoming > cap:
|
|
311
|
+
raise ValueError(
|
|
312
|
+
f"collection is at its vector limit: it holds {used} vectors"
|
|
313
|
+
f"{f' ({stats.tombstoned} deleted, not yet vacuumed)' if stats.tombstoned else ''}, "
|
|
314
|
+
f"adding {incoming} would exceed the maximum of {cap} per collection "
|
|
315
|
+
f"(set {_MAX_VECTORS_ENV_VAR} or `ruvector serve --max-vectors` to change it)"
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
|
|
266
319
|
def _check_vector_len(vec: "List[float]", what: str) -> None:
|
|
267
320
|
if len(vec) > MAX_DIM:
|
|
268
321
|
raise ValueError(f"{what} has {len(vec)} elements; the maximum dimension is {MAX_DIM}")
|
|
@@ -297,7 +350,7 @@ _token_verifier, _auth_settings = _build_auth()
|
|
|
297
350
|
server = MCPServer(
|
|
298
351
|
name="ruvector",
|
|
299
352
|
title="RuVector",
|
|
300
|
-
version="0.1.
|
|
353
|
+
version="0.1.2",
|
|
301
354
|
instructions=(
|
|
302
355
|
"ultra-low-latency vector search backed by a Rust RaBitQ core. "
|
|
303
356
|
"Create a collection, insert vectors with optional metadata, search "
|
|
@@ -369,6 +422,7 @@ def vector_insert(name: str, vector: List[float], metadata: Optional[Dict[str, A
|
|
|
369
422
|
_check_metadata(metadata)
|
|
370
423
|
with _lock:
|
|
371
424
|
coll = _load(name)
|
|
425
|
+
_check_capacity(coll, 1)
|
|
372
426
|
new_id = coll.insert(np.asarray(vector, dtype=np.float32), metadata=metadata)
|
|
373
427
|
_save(name, coll)
|
|
374
428
|
return {"id": new_id, "count": len(coll)}
|
|
@@ -388,6 +442,7 @@ def vector_insert_batch(
|
|
|
388
442
|
_check_batch(vectors, metadatas)
|
|
389
443
|
with _lock:
|
|
390
444
|
coll = _load(name)
|
|
445
|
+
_check_capacity(coll, len(vectors))
|
|
391
446
|
ids = coll.insert_batch(np.asarray(vectors, dtype=np.float32), metadatas=metadatas)
|
|
392
447
|
_save(name, coll)
|
|
393
448
|
return {"ids": ids, "count": len(coll)}
|
|
@@ -619,4 +674,13 @@ def run_http(host: str = "127.0.0.1", port: int = 8420) -> None:
|
|
|
619
674
|
server.run(transport="streamable-http", host=host, port=port)
|
|
620
675
|
|
|
621
676
|
|
|
622
|
-
__all__ = [
|
|
677
|
+
__all__ = [
|
|
678
|
+
"server",
|
|
679
|
+
"run_stdio",
|
|
680
|
+
"run_http",
|
|
681
|
+
"StaticTokenVerifier",
|
|
682
|
+
"apply_read_only",
|
|
683
|
+
"UnsafeBindError",
|
|
684
|
+
"set_max_vectors",
|
|
685
|
+
"max_vectors",
|
|
686
|
+
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|