Skip to content

fix(vector_io): align FAISS to upsert semantics for repeated chunk IDs - #6336

Open
yashanil98 wants to merge 1 commit into
ogx-ai:mainfrom
yashanil98:fix/issue-6256-faiss-upsert
Open

fix(vector_io): align FAISS to upsert semantics for repeated chunk IDs#6336
yashanil98 wants to merge 1 commit into
ogx-ai:mainfrom
yashanil98:fix/issue-6256-faiss-upsert

Conversation

@yashanil98

Copy link
Copy Markdown
Contributor

What does this PR do?

Finishes the FAISS part of #6256. PR #6260 aligned Milvus, ChromaDB, and SQLite-vec to upsert semantics and documented the contract on VectorIO.insert_chunks and EmbeddingIndex.add_chunks, but left FAISS on pure-append semantics.

The FAISS index called self.index.add(embeddings) unconditionally, so re-ingesting a chunk with an existing chunk_id silently created a duplicate. add_chunks now deduplicates within a batch and removes any existing entry that shares an incoming chunk_id before appending. The removal reuses the position-shift logic already used by delete_chunks, which is extracted into a _remove_chunk helper.

Closes #6256

Test Plan

Added two unit tests: one for replacing a chunk across separate add_chunks calls, one for deduplicating repeated chunk_ids within a single batch. Both fail on the current code (index count grows to 3) and pass with this change.

uv run --group unit --group test pytest tests/unit/providers/vector_io/test_faiss.py -q

Output:

11 passed in 0.19s

Full vector_io unit suite also passes:

uv run --group unit --group test pytest tests/unit/providers/vector_io/ -q
277 passed, 19 warnings in 15.18s

The FAISS index appended embeddings unconditionally, so re-ingesting a chunk
with an existing chunk_id silently duplicated it, violating the upsert contract
documented on VectorIO.insert_chunks and EmbeddingIndex.add_chunks. add_chunks
now deduplicates within a batch and removes any existing entry that shares an
incoming chunk_id before appending, reusing the position-shift logic already
used by delete_chunks.

Fixes ogx-ai#6256

Signed-off-by: Yash Anil <yashanil98@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the inline FAISS EmbeddingIndex implementation to match the VectorIO.insert_chunks / EmbeddingIndex.add_chunks upsert contract by removing existing entries for repeated chunk_ids before appending new vectors, and adds unit tests to lock in the behavior.

Changes:

  • Implement upsert-like behavior in FaissIndex.add_chunks by de-duplicating within a batch and removing existing entries for incoming chunk_ids.
  • Extract deletion/position-shift logic into a shared _remove_chunk helper reused by both add_chunks and delete_chunks.
  • Add unit tests covering cross-call replacement and within-batch de-duplication for repeated chunk_ids.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/ogx/providers/inline/vector_io/faiss/faiss.py Adds upsert semantics to FAISS add_chunks and factors out shared removal logic.
tests/unit/providers/vector_io/test_faiss.py Adds unit tests verifying replacement across calls and de-duplication within a batch.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +198 to +201
deduped: dict[str, EmbeddedChunk] = {}
for embedded_chunk in embedded_chunks:
deduped[embedded_chunk.chunk_id] = embedded_chunk
embedded_chunks = list(deduped.values())
Comment on lines 210 to +213
async with self.chunk_id_lock:
for chunk_id in [ec.chunk_id for ec in embedded_chunks if ec.chunk_id in self.chunk_ids]:
self._remove_chunk(chunk_id)

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.

insert_chunks should use upsert semantics — providers silently duplicate or error on repeated chunk IDs

2 participants