I was building an AI chat assistant in Blazor. It worked fine. But every new conversation started from scratch. The user would say "I'm a software engineer who loves C#" and the assistant would respond warmly , then forget it completely the next time they opened the app.
That's not a memory problem. That's just a chat window.
I wanted something better. Something that actually remembers the user across sessions, extracts facts from conversations, and uses them to give better responses over time. I looked around for a .NET library that did this. Nothing existed. So I built it.
What I built
BlazorMemory is an open-source AI memory layer for .NET. It sits between your chat logic and your LLM and does three things:
- Extracts facts from conversations using an LLM
- Stores them as vector embeddings
- Injects relevant memories into future prompts
The flow looks like this:
User message → extract facts → embed → store
↓
Next message → embed query → vector search → inject memories → LLM
It works in Blazor WASM with zero backend , everything stays in the browser using IndexedDB. It also works server-side with EF Core if you need SQL storage.
The hard part wasn't storage
Storing memories is easy. The hard part is making them useful.
Early versions just stored everything. After a few conversations, the memory panel was full of duplicates. "User likes C#." "User works with C#." "User is a C# developer." Three separate entries saying the same thing.
I solved this with a two-step pipeline:
Step 1 , Extract: The LLM reads the conversation and pulls out discrete facts. One sentence per fact, starting with "User". If the conversation already produced "User is a C# engineer", it won't also extract "User loves C#" , the preference is already implied.
Step 2 , Consolidate: For each new fact, the system finds similar existing memories using vector search. Then it asks the LLM: should I ADD this, UPDATE an existing memory, DELETE a contradiction, or do NOTHING?
The consolidation prompt has a clear priority order: NONE > UPDATE > DELETE > ADD. It prefers doing less. That keeps the memory clean.
Getting started
dotnet add package BlazorMemory
dotnet add package BlazorMemory.Storage.IndexedDb
dotnet add package BlazorMemory.Embeddings.OpenAi
dotnet add package BlazorMemory.Extractor.OpenAi
Wire it up in Program.cs:
builder.Services
.AddBlazorMemory()
.UseIndexedDbStorage()
.UseOpenAiEmbeddings(apiKey)
.UseOpenAiExtractor(apiKey);
Use it in your chat service:
public class ChatService(IMemoryService memory)
{
public async Task<string> ChatAsync(string message, string userId)
{
// Pull relevant memories
var memories = await memory.QueryAsync(message, userId,
new QueryOptions { Limit = 5, Threshold = 0.65f });
// Build system prompt
var context = string.Join("\n", memories.Select(m => $"- {m.Content}"));
var prompt = $"You are a helpful assistant.\n\nWhat you know:\n{context}";
// Call your LLM
var reply = await CallLlm(prompt, message);
// Extract and store new facts
await memory.ExtractAsync($"User: {message}\nAssistant: {reply}", userId);
return reply;
}
}
That's it. The assistant now remembers things.
Namespaces
v0.2.0 added namespace support. You can scope memories by topic:
// Store work memories separately from personal ones
await memory.ExtractAsync(conversation, userId, namespace: "work");
// Query only work memories
var results = await memory.QueryAsync(query, userId, new QueryOptions
{
Namespace = "work"
});
Useful if you're building an assistant that handles multiple contexts.
What's available
Seven NuGet packages, all at v0.2.0:
| Package | What it does |
|---|---|
BlazorMemory |
Core library |
BlazorMemory.Storage.IndexedDb |
Browser storage, zero backend |
BlazorMemory.Storage.InMemory |
For testing |
BlazorMemory.Storage.EfCore |
SQL Server, PostgreSQL, SQLite |
BlazorMemory.Embeddings.OpenAi |
OpenAI embeddings |
BlazorMemory.Extractor.OpenAi |
OpenAI fact extraction |
BlazorMemory.Extractor.Anthropic |
Claude fact extraction |
The repo is at github.com/aftabkh4n/BlazorMemory. Issues and PRs welcome.
If you're building AI assistants in .NET and want them to actually remember users, give it a try.
Top comments (0)