Skip to content

feat(store): attach document vectors after the write, not before it - #189

Merged
senamakel merged 4 commits into
tinyhumansai:mainfrom
senamakel:deferred-embedding
Oct 2, 2026
Merged

senamakel merged 4 commits into
tinyhumansai:mainfrom
senamakel:deferred-embedding

Conversation

@senamakel

Copy link
Copy Markdown
Member

Problem

Memory::store committed a document only after its chunks had been embedded, so every write waited out one embedding round trip. An embedding failure does not fail the write, so a refused or timed-out provider cost its whole latency for nothing.

OpenHuman autosaves the user message and the assistant message after every agent turn, as two sequential store calls, and the turn does not return until both are done. With a provider that refuses (an expired or placeholder key), a traced turn spent 655 ms + 847 ms = 1.5 s there, on the end of every task, and the same two calls cost a round trip each when the provider works.

Change

UnifiedMemory::store_with_taint (the Memory::store path) now commits the row and its chunks vector-less and returns. A background task embeds the chunks and attaches the vectors afterwards.

  • New documents_deferred.rs holds the path (documents.rs is already over 1000 lines). It reuses write_document_presanitized, and embed_chunk_texts now delegates to an embedder-taking helper so the task needs no borrow of the store.
  • The same secret/PII write gate runs first (write_gate::upsert_document_deferred).
  • The attach is one guarded UPDATE per chunk: it matches the chunk id and its text, and only where embedding IS NULL. A rewrite or forget while the embedding is in flight replaces or removes the chunks, so a stale vector finds nothing to attach to.
  • A vector-less chunk is the state an embedding failure already leaves, so keyword search is unaffected. Only semantic recall of a just-stored document lags by one provider round trip.

Not changed: upsert_document, upsert_documents (the connector batch path, which wants vectors present when it returns) and put_doc.

Tests

documents_deferred_tests.rs, driven by an embedder whose requests wait on a semaphore:

  • returns while the provider is still blocked, with the chunk committed vector-less, then the vector appears;
  • a refusing provider leaves the stored document vector-less and the write still succeeds;
  • a rewrite in flight does not receive the stale vector (attached count 0, new chunk keeps its own vector);
  • the write gate still rejects a secret-looking key;
  • Memory::store does not wait on the provider (it would hang on the old code).

cargo test --workspace, cargo clippy --all-targets --all-features -- -D warnings and cargo fmt --check are clean locally.

Follow-up

OpenHuman needs a gitlink bump to pick this up. Separately, the bench harness still runs with a placeholder TinyHumans key, which is what makes those embedding calls fail; that is tracked on the OpenHuman side.

senamakel and others added 4 commits October 2, 2026 16:59
When a document is not found in the namespace store, the code now returns a clear error instead of panicking or returning an ambiguous result. This improves robustness by ensuring callers can properly handle the absence of a document.

Auto-committed-on: macbook
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Introduce a mechanism to defer document writes in the namespace store, allowing write operations to be batched and committed later. This change adds a new `documents_deferred` module and updates the memory trait and write gate to support deferred write patterns, improving performance for bulk write scenarios.

Auto-committed-on: macbook
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add a trace-level log message when a memory entry is stored without waiting for vector indexing, so that developers can observe the asynchronous write path in debug logs without changing the function's return type or behaviour.

Auto-committed-on: macbook
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The store operation now explicitly drops the vectors handle after writing, allowing the vectors to complete asynchronously without blocking the caller. This avoids unnecessary waiting while ensuring the vectors still land after the store returns.

Auto-committed-on: macbook
Co-authored-by: Medulla <medulla@tinyhumans.ai>
@tinysweeper

tinysweeper Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Tiny Sweeper review

⚠️ Review failed for 9eb901059334. the review of #189 did not finish within 900s

@coderabbitai

coderabbitai Bot commented Oct 2, 2026

Copy link
Copy Markdown

Warning

Review limit reached

  • Run on-demand review

This review includes 6 billable files and costs up to $1.50.

Or wait 48 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: ce3d9158-ee43-4176-8f3c-0c8e74c35803

📥 Commits

Reviewing files that changed from the base of the PR and between 95ddce3 and 9eb9010.

📒 Files selected for processing (6)
  • crates/tinymemory-core/src/store/memory_trait.rs
  • crates/tinymemory-core/src/store/namespace_store/documents.rs
  • crates/tinymemory-core/src/store/namespace_store/documents_deferred.rs
  • crates/tinymemory-core/src/store/namespace_store/documents_deferred_tests.rs
  • crates/tinymemory-core/src/store/namespace_store/mod.rs
  • crates/tinymemory-core/src/store/write_gate.rs
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Comment @coderabbitai help to get the list of available commands.

@senamakel
senamakel merged commit b7a1225 into tinyhumansai:main Oct 2, 2026
23 of 24 checks passed
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.

1 participant