Mythosia.VectorDb.InMemory
4.3.0
dotnet add package Mythosia.VectorDb.InMemory --version 4.3.0
NuGet\Install-Package Mythosia.VectorDb.InMemory -Version 4.3.0
<PackageReference Include="Mythosia.VectorDb.InMemory" Version="4.3.0" />
<PackageVersion Include="Mythosia.VectorDb.InMemory" Version="4.3.0" />
<PackageReference Include="Mythosia.VectorDb.InMemory" />
paket add Mythosia.VectorDb.InMemory --version 4.3.0
#r "nuget: Mythosia.VectorDb.InMemory, 4.3.0"
#:package Mythosia.VectorDb.InMemory@4.3.0
#addin nuget:?package=Mythosia.VectorDb.InMemory&version=4.3.0
#tool nuget:?package=Mythosia.VectorDb.InMemory&version=4.3.0
Mythosia.VectorDb.InMemory
v4.3.0: Implements
IVectorStoreDiagnosticsfromMythosia.VectorDb.Abstractions4.2.0 and removes the RAG abstractions dependency. This minor release intentionally includes a breaking interface migration as a one-time versioning-policy exception: upgrade RAG together and migrateIRagDiagnosticsStorecasts. See the release notes.
Package Summary
Provides InMemoryVectorStore, a thread-safe in-memory implementation of IVectorStore using cosine similarity search.
Suitable for development, testing, and small-scale workloads.
Usage
Automatically used as the default vector store in Mythosia.AI.Rag:
// Explicit selection (same as default)
.WithRag(rag => rag
.AddDocument("docs.txt")
.UseInMemoryStore()
)
Features
- Consistent concurrent access — Synchronizes record storage and the BM25 index across writes, deletes and reads; both hybrid search legs use the same state
- Independent records — Copies input and returned records, including vector arrays and metadata
- Cosine similarity — TopK search with configurable result count
- Hybrid search — BM25 + dense vector fusion via weighted RRF, scores normalized to
[0, 1] - Metadata filtering — Full
VectorFilteroperator set (Eq/Ne/In/NotIn/Gt/Gte/Lt/Lte/Like/Exists/NotExists, And/Or groups) - Minimum score — Discard results below a similarity threshold
- Upsert — Single and batch upsert operations
- CountAsync — Count records, optionally narrowed by filter criteria
- Store diagnostics — Optional
IVectorStoreDiagnostics:ListAllRecordsAsync,ScoredListAsync;GetTotalRecordCount()remains a concrete convenience method
Diagnostics and migration from 4.2.x and earlier
InMemory depends on Mythosia.VectorDb.Abstractions and has no Mythosia.AI.Rag.Abstractions package reference. Use it independently for store-wide record inspection and raw cosine scores:
using Mythosia.VectorDb;
using Mythosia.VectorDb.InMemory;
IVectorStoreDiagnostics diagnostics = new InMemoryVectorStore();
var records = await diagnostics.ListAllRecordsAsync(cancellationToken);
var scores = await diagnostics.ScoredListAsync(queryVector, cancellationToken);
These methods inspect all records and accept no metadata filter. They do not apply a RAG pipeline's StoreFilter. RAG-specific analysis, including chunk previews, missing-result explanations, health checks and reports, remains in Mythosia.AI.Rag 8.3.0.
InMemoryVectorStore no longer implements IRagDiagnosticsStore. Replace assignments, casts and capability checks against that old interface with IVectorStoreDiagnostics and import Mythosia.VectorDb. This affects already compiled callers that use the old interface as well as source callers; the legacy shim does not restore that relationship. Upgrade Mythosia.AI.Rag to 8.3.0 together with InMemory 4.3.0. Pairing older RAG packages with the new InMemory package is unsupported.
Custom stores that still implement the obsolete IRagDiagnosticsStore use the compatibility contract in RAG Abstractions 6.5.0 and the legacy adapter in RAG 8.3.0; see the migration notes.
If your application previously obtained RAG types through InMemory's transitive dependency, add an explicit reference to the appropriate RAG package and rebuild. Standalone vector-store consumers need no RAG reference. This interface migration does not change stored records or require reindexing.
Standalone Usage
Recommended — Metadata-based isolation
using Mythosia.VectorDb;
using Mythosia.VectorDb.InMemory;
var store = new InMemoryVectorStore();
await store.UpsertAsync(new VectorRecord
{
Id = "doc-1",
Content = "Some text content",
Vector = new float[] { 0.1f, 0.2f, 0.3f },
Metadata =
{
["source"] = "manual.txt",
["namespace"] = "my-namespace",
["scope"] = "tenant-1"
}
});
var filter = new VectorFilter()
.Where("namespace", "my-namespace")
.Where("scope", "tenant-1");
var results = await store.SearchAsync(queryVector, topK: 5, filter: filter);
Concurrent Updates and Record Ownership
A query must not return a new document body with keyword matches from its old contents. The store synchronizes writes, deletes and reads so every vector, text or hybrid query sees a consistent state. Both legs of a hybrid query run against that same state. Separate API calls may see later writes.
The store copies incoming records, including vector arrays and metadata. Lookups, search results and diagnostic methods return independent copies. Keep input records, vectors and metadata unchanged while a call copies or reads them. Editing an input object or a returned record after the call does not change stored data; save edits explicitly:
var record = await store.GetAsync("doc-1");
if (record is not null)
{
record.Content = "Updated text content";
record.Vector = await embeddingService.GetEmbeddingAsync(record.Content);
await store.UpsertAsync(record);
}
A supplied CancellationToken can cancel a call while it waits for another operation to release the store lock. Canceling that wait does not itself abort the operation currently using the store. Once a record update has begun, cancellation does not interrupt it between updating the body and keyword index.
Cancellation is also checked before writes and between records in batch writes. A canceled batch can retain records already written; their bodies and keyword index entries remain consistent. This is not a transaction or a rollback guarantee for the whole batch.
BM25 Index
Bm25Index provides in-memory BM25 keyword search for hybrid retrieval. InMemoryVectorStore maintains its BM25 index alongside stored vectors. TextSearchAsync uses it without a dense query vector; configurable HybridSearchAsync combines it with dense results through normalized weighted RRF. Selecting a query mode does not change document ingestion.
// Automatic — just enable hybrid search in the builder
var store = await RagStore.BuildAsync(config => config
.AddText("환불은 14일 이내 가능합니다.", id: "refund")
.UseLocalEmbedding(512)
.UseInMemoryStore()
.UseHybridSearch() // BM25 index is built automatically
);
Standalone usage:
using Mythosia.VectorDb.InMemory;
var bm25 = new Bm25Index();
bm25.Index("doc1", "machine learning neural network");
bm25.Index("doc2", "cooking recipe pasta");
var results = bm25.Search("machine learning", topK: 5);
// results[0].Id == "doc1", results[0].Score > 0
When hybrid search is used, fused RRF scores are normalized to [0, 1], including a single active leg or no keyword matches. VectorFilter.MinScore applies after fusion, while metadata filters restrict candidates before top-K. HybridSearchOptions controls vector weight, candidate multiplier and RRF smoothing. Pure TextSearchAsync returns native BM25 scores, which are not interchangeable with vector or fusion scores.
VectorFilter
For the full operator reference and fluent API examples (Where, WhereNot, WhereIn, WhereLike, WhereExists, Or, And, WithMinScore, etc.), see the Mythosia.VectorDb.Abstractions README.
InMemory-specific note: Range operators (
WhereGreaterThan,WhereLessThan, etc.) usestring.Compare(ordinal). Store numeric values zero-padded (e.g."0042") for correct ordering.
Batch Get & Count
// Fetch multiple records by ID in one call
var filter = new VectorFilter().Where("namespace", "docs");
var records = await store.GetBatchAsync(new[] { "id-1", "id-2", "id-3" }, filter);
// Count all records matching a filter
long count = await store.CountAsync(new VectorFilter().Where("namespace", "docs"));
// Count with additional metadata filter
long filtered = await store.CountAsync(
new VectorFilter().Where("namespace", "docs").Where("storage_id", storageId));
GetBatchAsync performs O(1)-per-ID lookups via ConcurrentDictionary.TryGetValue — no vector scoring, just direct key access. Records not found or not matching the filter are omitted.
Resource Disposal
InMemoryVectorStore implements IDisposable. A Bm25Index (Lucene writer, analyzer, RAMDirectory) is maintained alongside the vector store. Dispose the store when it is no longer needed to release these resources:
using var store = new InMemoryVectorStore();
// ... use store
// Lucene resources released on Dispose
Vector Replacement
ReplaceByFilterAsync is available via the IVectorStore default interface method. It performs sequential DeleteByFilterAsync → UpsertBatchAsync (non-transactional):
IVectorStore store = new InMemoryVectorStore();
var filter = new VectorFilter()
.Where("full_path", "/docs/file.md");
await store.ReplaceByFilterAsync(filter, newRecords);
A query can observe the gap between deletion and insertion. Failure or cancellation can leave a partial replacement; completed writes are not rolled back. Synchronizing each operation keeps records and the BM25 index consistent, but does not make the whole replacement transactional. For transactional replacement, use PostgresStore, which wraps both operations in a single database transaction.
Limitations
- Data is not persisted — lost when the process exits
- Not suitable for large-scale production workloads (millions of vectors)
- For persistence or scale, implement a custom
IVectorStore(e.g., Qdrant, Chroma, Pinecone)
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- Lucene.Net (>= 4.8.0-beta00016)
- Lucene.Net.Analysis.Common (>= 4.8.0-beta00016)
- Mythosia.VectorDb.Abstractions (>= 4.2.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Mythosia.VectorDb.InMemory:
| Package | Downloads |
|---|---|
|
Mythosia.AI.Rag
Ground AI answers in application-managed documents with loading, splitting, embeddings, vector/text/hybrid retrieval, reranking and metadata filters. Provides standard and Agentic RAG, streaming runs, cancellation and optional PIXIE search. Supports Voyage Context 4, Gemini Embedding 2, OpenAI, Ollama and Perplexity embeddings. Retrieval-aware providers distinguish documents from queries and receive complete ordered document inputs; existing IEmbeddingProvider implementations remain compatible. Validates embedding results before document replacement and isolates query rewriting and reranking. Depends on Mythosia.AI.Abstractions and Mythosia.AI.Rag.Abstractions without referencing the full Mythosia.AI implementation. What's New in v8.3.0: Diagnostics use optional IVectorStoreDiagnostics and InMemory 4.3.0; migrate old InMemory diagnostic interface casts. This minor release intentionally includes a breaking interface migration. |
GitHub repositories
This package is not used by any popular GitHub repositories.
v4.3.0: Minor-version policy exception: includes a breaking diagnostics-interface migration. Removes the RAG.Abstractions dependency and implements optional IVectorStoreDiagnostics from VectorDb.Abstractions 4.2.0. Breaking: InMemoryVectorStore no longer implements IRagDiagnosticsStore; update interface assignments/casts and use RAG 8.3.0 for full diagnostics. Existing concrete diagnostic methods and ordinary vector/text/hybrid operations remain available. Full notes: https://github.com/AJ-comp/Mythosia.AI/blob/main/src/vectordb/Mythosia.VectorDb.InMemory/RELEASE_NOTES.md#v430