jeevesagent.vectorstore.inmemory
================================

.. py:module:: jeevesagent.vectorstore.inmemory

.. autoapi-nested-parse::

   In-memory vector store — cosine over a Python list.

   Zero dependencies. Default for dev, tests, and small corpora (up
   to ~10K chunks before search latency starts to bite). For larger
   corpora swap to :class:`FAISSVectorStore` (in-process ANN) or
   :class:`ChromaVectorStore` / :class:`PostgresVectorStore`
   (persistent).

   Beyond the protocol contract this backend additionally supports:

   * **Diversity (MMR)** — pass ``diversity=0.3`` to :meth:`search`
     for varied top-k.
   * **Hybrid search** — :meth:`search_hybrid` combines BM25 lexical
     scores with vector similarity via Reciprocal Rank Fusion.
   * **Persistence** — :meth:`save` / :meth:`load` round-trip the
     store to JSON on disk.



Classes
-------

.. autoapisummary::

   jeevesagent.vectorstore.inmemory.InMemoryVectorStore


Module Contents
---------------

.. py:class:: InMemoryVectorStore(embedder: jeevesagent.core.protocols.Embedder)

   In-process vector store backed by a Python list.


   .. py:method:: add(chunks: list[jeevesagent.loader.base.Chunk], ids: list[str] | None = None) -> list[str]
      :async:



   .. py:method:: count() -> int
      :async:



   .. py:method:: delete(ids: list[str]) -> None
      :async:



   .. py:method:: from_chunks(chunks: list[jeevesagent.loader.base.Chunk], *, embedder: jeevesagent.core.protocols.Embedder, ids: list[str] | None = None) -> InMemoryVectorStore
      :classmethod:

      :async:


      One-shot: construct an InMemoryVectorStore + add ``chunks``.



   .. py:method:: from_texts(texts: list[str], *, embedder: jeevesagent.core.protocols.Embedder, metadatas: list[dict[str, Any]] | None = None, ids: list[str] | None = None) -> InMemoryVectorStore
      :classmethod:

      :async:


      One-shot: construct an InMemoryVectorStore from raw text
      strings (each becomes a :class:`Chunk` with the matching
      metadata dict, or empty if ``metadatas`` is None).



   .. py:method:: get_by_ids(ids: list[str]) -> list[jeevesagent.loader.base.Chunk]
      :async:



   .. py:method:: load(path: str | pathlib.Path, *, embedder: jeevesagent.core.protocols.Embedder) -> InMemoryVectorStore
      :classmethod:

      :async:


      Restore a store previously :meth:`save`-d. Pass the same
      embedder kind/dimensions or queries will produce nonsense
      scores.



   .. py:method:: save(path: str | pathlib.Path) -> None
      :async:


      Write the full store (chunks + vectors + ids) to a JSON
      file. The embedder is NOT serialized — supply the same
      embedder when calling :meth:`load`.



   .. py:method:: search(query: str, *, k: int = 4, filter: collections.abc.Mapping[str, Any] | None = None, diversity: float | None = None) -> list[jeevesagent.vectorstore.base.SearchResult]
      :async:



   .. py:method:: search_by_vector(vector: list[float], *, k: int = 4, filter: collections.abc.Mapping[str, Any] | None = None, diversity: float | None = None) -> list[jeevesagent.vectorstore.base.SearchResult]
      :async:



   .. py:method:: search_hybrid(query: str, *, k: int = 4, filter: collections.abc.Mapping[str, Any] | None = None, alpha: float = 0.5) -> list[jeevesagent.vectorstore.base.SearchResult]
      :async:


      Hybrid lexical (BM25) + vector search via RRF.

      ``alpha`` is in [0, 1]: 0 = pure BM25, 1 = pure vector,
      0.5 = even weighting (RRF default). Both rankings are
      computed independently and fused by Reciprocal Rank Fusion,
      then the top-``k`` survivors are returned.

      Embeddings catch semantic similarity ("automobile" ↔ "car"),
      BM25 catches exact-term hits (model names, error codes,
      person names) — together they outperform either alone on
      most retrieval benchmarks.



   .. py:property:: embedder
      :type: jeevesagent.core.protocols.Embedder



   .. py:attribute:: name
      :value: 'in-memory'



