Skip to content

Conversation

@xav-db
Copy link
Member

@xav-db xav-db commented Oct 8, 2025

Description

Related Issues

Closes #650

Checklist when merging to main

  • No compiler warnings (if applicable)
  • Code is formatted with rustfmt
  • No useless or dead code (if applicable)
  • Code is easy to understand
  • Doc comments are used for all functions, enums, structs, and fields (where appropriate)
  • All tests pass
  • Performance has not regressed (assuming change was not to fix a bug)
  • Version number has been updated in helix-cli/Cargo.toml and helixdb/Cargo.toml

Additional Notes

Greptile Overview

Updated On: 2025-10-08 17:38:49 UTC

Summary

This PR implements comprehensive support for multiple floating-point precisions (f16, f32, f64) in HelixDB's vector operations, addressing issue #650. The changes introduce a new `VectorData` enum that wraps different precision types, enabling more memory-efficient vector storage and operations while maintaining backward compatibility with existing f64 vectors.

Key architectural changes include:

  • New VectorData enum: Provides type-safe abstraction over f64, f32, and f16 vectors with proper serialization support
  • Grammar extensions: HQL now supports precision specifications like V::MyVector<F32> for vector definitions
  • Vector core updates: HNSW search, distance calculations, and storage operations now handle multiple precisions natively
  • Compiler enhancements: Parser, analyzer, and code generator updated to support precision-aware vector operations
  • Test coverage: Comprehensive test suite validates functionality across all precision types

The implementation follows a systematic approach, updating every layer from the grammar parser through to the storage engine. The VectorData enum serves as the central abstraction, allowing the same APIs to work with different precision types while enabling precision-specific optimizations for distance calculations.

PR Description Notes:

  • The PR description is quite minimal and lacks detail about the significant architectural changes being made
  • No mention of the new VectorData enum or the comprehensive nature of the changes across multiple system layers

Important Files Changed

Changed Files
Filename Score Overview
helix-db/src/helix_engine/vector_core/vector_data.rs 4/5 New core VectorData enum implementation supporting f64/f32/f16 precision types with serialization
helix-db/src/helix_engine/vector_core/vector.rs 4/5 Major refactor replacing Vec with VectorData enum, includes backwards compatibility for existing vectors
helix-db/src/helix_engine/vector_core/vector_distance.rs 4/5 Implements native precision distance calculations and mixed-precision comparisons with SIMD optimizations
helix-db/src/grammar.pest 5/5 Extends HQL grammar to support vector precision specifications like V::MyVector
helix-db/src/helixc/parser/types.rs 4/5 Adds Precision enum and F16 field type support throughout the type system
helix-db/src/helixc/analyzer/methods/traversal_validation.rs 4/5 Updates validation logic to handle precision-aware vector operations with proper scope management
helix-db/src/helixc/generator/utils.rs 4/5 Adds code generation support for F16 type and Precision enum with TypeScript mappings
helix-db/src/helix_engine/vector_core/hnsw.rs 4/5 Updates HNSW trait signatures to accept VectorData instead of raw f64 slices
helix-db/src/helix_engine/vector_core/vector_core.rs 5/5 Core HNSW implementation updated to work with VectorData enum for multi-precision support
helix-db/src/helix_engine/traversal_core/ops/vectors/search.rs 5/5 Vector search operations updated to accept VectorData instead of f64 arrays
helix-db/src/helix_engine/traversal_core/ops/vectors/insert.rs 5/5 Vector insertion API updated to handle VectorData enum with proper type safety
helix-db/src/helixc/parser/schema_parse_methods.rs 4/5 Parser support for vector precision specifications in schema definitions
helix-db/src/helixc/analyzer/types.rs 3/5 Adds F16 type support but missing F16 in is_numeric() method - potential validation bug
helix-db/Cargo.toml 5/5 Adds half crate dependency for f16 support with appropriate features
helix-container/Cargo.toml 5/5 Consistent half crate dependency addition for container component
hql-tests/tests/vector_precision/schema.hx 2/5 Test schema file with all definitions commented out - appears incomplete
hql-tests/tests/vector_precision/queries.hx 4/5 Comprehensive test queries demonstrating F16/F32/F64 vector operations
hql-tests/tests/vector_precision/config.hx.json 5/5 Well-structured test configuration for validating vector precision features
hql-tests/tests/vector_precision/helix.toml 5/5 Standard test project configuration for vector precision validation
helix-db/src/helix_gateway/mcp/tools.rs 5/5 MCP tools updated to wrap embeddings in VectorData::F64 for compatibility
helix-db/src/helix_engine/tests/traversal_tests/util_tests.rs 5/5 Test updates to use VectorData enum while maintaining test functionality
helix-db/src/protocol/value.rs 5/5 Minor formatting improvement in type casting module
helix-db/src/helix_engine/bm25/bm25.rs 4/5 BM25 hybrid search updated to use VectorData::from_f64_slice for compatibility
helix-db/src/helixc/parser/utils.rs 4/5 New try_peek_matches utility method for parsing optional precision specifiers
helix-db/src/helix_engine/tests/traversal_tests/edge_traversal_tests.rs 5/5 Vector operations wrapped in VectorData::F64 to maintain test compatibility
helix-db/src/helix_engine/tests/traversal_tests/drop_tests.rs 5/5 Drop functionality tests updated for new VectorData enum structure
helix-db/src/helix_engine/tests/traversal_tests/vector_traversal_tests.rs 5/5 Comprehensive vector traversal test updates using VectorData wrappers
helix-db/src/helix_engine/bm25/bm25_tests.rs 5/5 BM25 test suite updated to wrap vector data in VectorData::F64 enum
helix-db/src/helix_gateway/mcp/tools_tests.rs 4/5 MCP tools tests updated to support VectorData enum with proper assertions
helix-db/src/helixc/generator/traversal_steps.rs 4/5 SearchVectorStep updated to use precision-wrapped vector data
helix-db/src/helix_engine/tests/hnsw_tests.rs 5/5 HNSW tests adapted to new VectorData API while preserving functionality
helix-db/src/helix_engine/tests/vector_tests.rs 4/5 Core vector tests updated to use VectorData enum for all operations
helix-db/src/helixc/analyzer/methods/infer_expr_type.rs 4/5 Expression type inference updated with precision-aware vector handling
helix-db/src/helixc/analyzer/methods/graph_step_validation.rs 4/5 Graph step validation enhanced with vector precision support
helix-db/benches/hnsw_benches.rs 4/5 Benchmark code updated to use VectorData while maintaining performance testing
helix-db/src/helixc/generator/source_steps.rs 5/5 Code generator updated to handle precision-wrapped vector data in operations
helix-db/src/helix_engine/vector_core/mod.rs 5/5 Module exports updated to include VectorData and related types
helix-db/src/helix_engine/traversal_core/ops/vectors/brute_force_search.rs 4/5 Brute force search updated for mixed-precision vector comparisons

Sequence Diagram

sequenceDiagram
    participant User
    participant Parser as "HQL Parser"
    participant Analyzer as "Semantic Analyzer" 
    participant Generator as "Code Generator"
    participant VectorCore as "Vector Core"
    participant Storage as "HNSW Storage"

    User->>Parser: "V::Embedding<F16> { content: String }"
    Parser->>Parser: "Parse precision specification"
    Parser->>Analyzer: "VectorSchema with Precision::F16"
    
    Analyzer->>Analyzer: "Validate precision type"
    Analyzer->>Generator: "Generate VectorData::F16 operations"
    
    User->>Parser: "AddV<Embedding>(vector, {content: content})"
    Parser->>Analyzer: "Vector creation with F16 data"
    Analyzer->>Generator: "Generate F16-specific VectorData"
    Generator->>VectorCore: "VectorData::F16(vec)"
    
    VectorCore->>VectorCore: "Create HVector with F16 precision"
    VectorCore->>Storage: "Store vector with type marker"
    Storage-->>VectorCore: "Vector stored with F16 metadata"
    
    User->>Parser: "SearchV<Embedding>(query_vector, 10)"
    Parser->>Analyzer: "Vector search operation"
    Analyzer->>Generator: "Generate F16 search operation"
    Generator->>VectorCore: "search() with VectorData::F16"
    
    VectorCore->>VectorCore: "Perform cosine similarity with F16"
    Note over VectorCore: "Uses native F16 arithmetic or converts to F32 for calculations"
    VectorCore->>Storage: "Query HNSW index"
    Storage-->>VectorCore: "Return matching F16 vectors"
    VectorCore-->>Generator: "Search results"
    Generator-->>User: "Vector search results"
Loading

@xav-db xav-db changed the base branch from main to dev October 8, 2025 15:20
@xav-db xav-db marked this pull request as ready for review October 8, 2025 17:36
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (5)

  1. helix-db/src/helixc/parser/utils.rs, line 46 (link)

    style: Remove debug println statement before merging

  2. helix-db/src/helix_engine/tests/traversal_tests/vector_traversal_tests.rs, line 162 (link)

    logic: This brute_force_search_v call still uses raw array - should be updated to use VectorData for consistency

  3. helix-db/src/helix_engine/vector_core/vector_distance.rs, line 184 (link)

    style: Debug println statement should be removed or wrapped in debug_assert! for production code

  4. helix-db/src/helixc/parser/schema_parse_methods.rs, line 241-260 (link)

    logic: Missing F16 case in default value parsing for float literals

  5. helix-db/src/helixc/analyzer/types.rs, line 312-329 (link)

    logic: The is_numeric() method is missing F16 in its pattern matching. This could cause type validation issues when F16 values are used in numeric contexts.

38 files reviewed, 10 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +46 to 49
let original = HVector::new(VectorData::F64(vec![1.0, 2.0, 3.0]));
let bytes = original.to_bytes();
let reconstructed = HVector::from_bytes(original.get_id(), 0, &bytes).unwrap();
assert_eq!(original.get_data(), reconstructed.get_data());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: This test validates the new serialization format with type markers but only tests f64. Consider adding tests for f16/f32 precision roundtrip to ensure the new functionality works correctly.

Prompt To Fix With AI
This is a comment left during a code review.
Path: helix-db/src/helix_engine/tests/vector_tests.rs
Line: 46:49

Comment:
**style:** This test validates the new serialization format with type markers but only tests f64. Consider adding tests for f16/f32 precision roundtrip to ensure the new functionality works correctly.

How can I resolve this? If you propose a fix, please make it concise.

}
let mut vec = Vec::with_capacity(data_bytes.len() / std::mem::size_of::<f64>());
for chunk in data_bytes.chunks_exact(std::mem::size_of::<f64>()) {
let value = f64::from_be_bytes(chunk.try_into().expect("Invalid chunk"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Using expect() here could cause panics on corrupted data. Consider returning VectorError instead for better error handling.

Prompt To Fix With AI
This is a comment left during a code review.
Path: helix-db/src/helix_engine/vector_core/vector.rs
Line: 218:218

Comment:
**style:** Using expect() here could cause panics on corrupted data. Consider returning VectorError instead for better error handling.

How can I resolve this? If you propose a fix, please make it concise.

let d = cosine_similarity(v.get_data(), query).unwrap();
let v_data = v.get_data();
let d =
cosine_similarity_mixed(v_data, &VectorData::F64(query.to_vec())).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Converting query to VectorData::F64 creates unnecessary allocations for each vector comparison. Consider passing the query slice directly or caching the VectorData wrapper.

Prompt To Fix With AI
This is a comment left during a code review.
Path: helix-db/src/helix_engine/traversal_core/ops/vectors/brute_force_search.rs
Line: 64:64

Comment:
**style:** Converting query to VectorData::F64 creates unnecessary allocations for each vector comparison. Consider passing the query slice directly or caching the VectorData wrapper.

How can I resolve this? If you propose a fix, please make it concise.

@xav-db xav-db mentioned this pull request Oct 29, 2025
8 tasks
@xav-db xav-db changed the base branch from dev to arena-implementation October 29, 2025 14:26
xav-db added a commit that referenced this pull request Nov 7, 2025
## Description
<!-- Provide a brief description of the changes in this PR -->

## Related Issues
<!-- Link to any related issues using #issue_number -->

Closes #670 #666 #667 #672  #668 #661 #655 #654 #652 #436 

## Checklist when merging to main
<!-- Mark items with "x" when completed -->

- [ ] No compiler warnings (if applicable)
- [ ] Code is formatted with `rustfmt`
- [ ] No useless or dead code (if applicable)
- [ ] Code is easy to understand
- [ ] Doc comments are used for all functions, enums, structs, and
fields (where appropriate)
- [ ] All tests pass
- [ ] Performance has not regressed (assuming change was not to fix a
bug)
- [ ] Version number has been updated in `helix-cli/Cargo.toml` and
`helixdb/Cargo.toml`

## Additional Notes
<!-- Add any additional information that would be helpful for reviewers
-->

<!-- greptile_comment -->

<h2>Greptile Overview</h2>

Updated On: 2025-11-07 00:19:04 UTC

<h3>Greptile Summary</h3>


This PR implements arena-based memory allocation for graph traversals
and refactors the worker pool's channel selection mechanism.

**Key Changes:**
- **Arena Implementation**: Introduced `'arena` lifetime parameter
throughout traversal operations (`in_e.rs`), replacing owned data with
arena-allocated references for improved memory efficiency
- **Worker Pool Refactor**: Replaced `flume::Selector` with a
parity-based `try_recv()`/`recv()` pattern to handle two channels
(`cont_rx` and `rx`) across multiple worker threads
- **Badge Addition**: Added Manta Graph badge to README

**Issues Found:**
- **Worker Pool Channel Handling**: The new parity-based approach
requires an even number of workers (≥2) and uses non-blocking
`try_recv()` followed by blocking `recv()` on alternating channels.
While this avoids a true busy-wait (since one `recv()` always blocks),
the asymmetry means channels are polled at different frequencies,
potentially causing channel starvation or unfair scheduling compared to
the previous `Selector::wait()` approach.

The arena implementation appears solid and follows Rust lifetime best
practices. The worker pool change seems to be addressing a specific
issue with core affinity (per commit `7437cf0f`), but the trade-off in
channel fairness should be monitored.

<details><summary><h3>Important Files Changed</h3></summary>



File Analysis



| Filename | Score | Overview |
|----------|-------|----------|
| README.md | 5/5 | Added Manta Graph badge to README - cosmetic
documentation change with no functional impact |
| helix-db/src/helix_engine/traversal_core/ops/in_/in_e.rs | 5/5 |
Refactored to use arena-based lifetimes ('arena) instead of owned data,
replacing separate InEdgesIterator struct with inline closures for
better memory management |
| helix-db/src/helix_gateway/worker_pool/mod.rs | 3/5 | Replaced flume
Selector with parity-based try_recv/recv pattern requiring even worker
count, but implementation has potential busy-wait issues that could
cause high CPU usage |

</details>


</details>


<details><summary><h3>Sequence Diagram</h3></summary>

```mermaid
sequenceDiagram
    participant Client
    participant WorkerPool
    participant Worker1 as Worker (parity=true)
    participant Worker2 as Worker (parity=false)
    participant Router
    participant Storage

    Client->>WorkerPool: process(request)
    WorkerPool->>WorkerPool: Send request to req_rx channel
    
    par Worker1 Loop (parity=true)
        loop Every iteration
            Worker1->>Worker1: try_recv(cont_rx) - non-blocking
            alt Continuation available
                Worker1->>Worker1: Execute continuation function
            else Empty
                Worker1->>Worker1: Skip (no busy wait here)
            end
            Worker1->>Worker1: recv(rx) - BLOCKS until request
            alt Request received
                Worker1->>Router: Route request to handler
                Router->>Storage: Execute graph operation
                Storage-->>Router: Return result
                Router-->>Worker1: Response
                Worker1->>WorkerPool: Send response via ret_chan
            end
        end
    end
    
    par Worker2 Loop (parity=false)
        loop Every iteration
            Worker2->>Worker2: try_recv(rx) - non-blocking
            alt Request available
                Worker2->>Router: Route request to handler
                Router->>Storage: Execute graph operation
                Storage-->>Router: Return result
                Router-->>Worker2: Response
                Worker2->>WorkerPool: Send response via ret_chan
            else Empty
                Worker2->>Worker2: Skip (no busy wait here)
            end
            Worker2->>Worker2: recv(cont_rx) - BLOCKS until continuation
            alt Continuation received
                Worker2->>Worker2: Execute continuation function
            end
        end
    end

    WorkerPool-->>Client: Response
```
</details>


<!-- greptile_other_comments_section -->

<!-- /greptile_comment -->
Base automatically changed from arena-implementation to dev November 7, 2025 00:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: support f16/f32 embeddings

2 participants