Skip to content

Commit 3dbc02b

Browse files
committed
documentation and logo
1 parent ded59f7 commit 3dbc02b

41 files changed

Lines changed: 2031 additions & 167 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.readthedocs.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
version: 2
2+
3+
build:
4+
os: ubuntu-24.04
5+
tools:
6+
python: "3.12"
7+
8+
mkdocs:
9+
configuration: mkdocs.yml

README.md

Lines changed: 87 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,166 +1,141 @@
1-
# Jigen DB
2-
3-
**Jigen DB** is a vector database written from scratch in C#.
4-
It is a study/research project focused on vector search use cases and implementation trade-offs.
5-
6-
The goal is to iteratively explore performance strategies, indexing approaches, and practical optimizations.
1+
<p align="center">
2+
<picture>
3+
<source media="(prefers-color-scheme: dark)" srcset="assets/jigen-logo-full-dark.png">
4+
<img src="assets/jigen-logo-full.png" alt="Jigen DB" width="320"/>
5+
</picture>
6+
</p>
77

8+
# Jigen DB
89

9-
> Tech stack: **.NET (net8.0 / net10.0)**, **ASP.NET Core** (hosting), **gRPC**.
10-
11-
---
10+
**Jigen DB** is a vector database written from scratch in C# for the .NET platform.
1211

13-
## Table of contents
12+
Use it **in-process** inside your application — like SQLite, but for vector search — or run it as a **standalone server** with gRPC and REST APIs, typed .NET client, and optional built-in text embedding generation powered by ONNX Runtime.
1413

15-
- [Jigen DB](#jigen-db)
16-
- [Table of contents](#table-of-contents)
17-
- [Prerequisites](#prerequisites)
18-
- [High-level structure](#high-level-structure)
19-
- [Running the gRPC server](#running-the-grpc-server)
20-
- [Using the client](#using-the-client)
21-
- [CORS / gRPC-Web](#cors--grpc-web)
22-
- [Tests](#tests)
23-
- [Troubleshooting](#troubleshooting)
24-
- [HNSW index file (`*.hnsw.index`) is empty](#hnsw-index-file-hnswindex-is-empty)
25-
- [HNSW returns fewer results than brute-force](#hnsw-returns-fewer-results-than-brute-force)
26-
- [gRPC client cannot connect](#grpc-client-cannot-connect)
27-
- [License](#license)
14+
> Tech stack: **.NET (net8.0 / net10.0)**, **ASP.NET Core**, **gRPC**, **ONNX Runtime**. License: **Apache-2.0**.
2815
29-
---
16+
## Project Overview and Genesis
3017

31-
## Prerequisites
18+
This project was born as a research initiative to understand the inner workings of vector databases and to explore how performant a database written in pure C# can be. It also provided a great opportunity to dive deeper into specific C# and .NET runtime internals.
3219

33-
- A .NET SDK compatible with the project targets (net8.0 and/or net10.0)
34-
- Read/write access to the local database folder used by the server
35-
- Optional ONNX model files if you want to use server-side embedding generation
20+
**Architecture & Development**
3621

37-
Check your installation:
22+
- Core Storage & Persistence: Written entirely from scratch by human developer.
23+
- HNSW Indexing: Forked from a Microsoft library and heavily optimized/modified to support disk persistence.
24+
- Server Architecture: Built using a well-known CQRS pattern, written by human.
25+
- This software has been optimized using Fable.
26+
- AI-Generated UI: The frontend was written completely by AI. Since UI code isn't the focus of this project, a functional, AI-built interface was more than enough.
27+
- Testing & Debugging: Handled entirely by a human.
28+
- Messaging & IPC (Hikyaku): The communication layer uses Hikyaku, a custom fork of MediatR (v12) developed over several years. It introduces out-of-process capabilities via Kafka and RabbitMQ. (Note: The library was previously named Arbitrer, then Axonflow, and finally rebranded to Hikyaku to avoid naming conflicts on NuGet).
3829

39-
```bash
40-
dotnet --info
41-
```
4230

43-
## High-level structure
4431

45-
- **Server**: [src/Server/Jigen](src/Server/Jigen) hosts the app and loads modules.
46-
- **gRPC module**: [src/Server/Jigen.Grpc](src/Server/Jigen.Grpc) exposes `StoreCollectionService`.
47-
- **Store engine**: [src/Jigen/Jigen.Store](src/Jigen/Jigen.Store) handles storage, indexing and search.
48-
- **HNSW indexer**: [src/Jigen/Jigen.Indexer.HNSW](src/Jigen/Jigen.Indexer.HNSW).
49-
- **Client library**: [src/Client/Jigen.Client](src/Client/Jigen.Client).
50-
- **Tests**: [tests](tests) with integration/unit suites for store, client and HNSW.
32+
## Highlights
5133

34+
- **In-process engine** (`Jigen.Store`): append-only memory-mapped storage, asynchronous ingestion, crash recovery, exact (brute-force) search out of the box.
35+
- **HNSW index** (`Jigen.Indexer.HNSW`): disk-backed approximate nearest neighbor graph with concurrent inserts, deletes, optional SQ8 quantization and exact reranking.
36+
- **Server**: multi-database host with gRPC (port 3223) and REST (port 13223) APIs, per-collection search with content filters, periodic durability checkpoints.
37+
- **Embeddings**: server-side text embedding generation (ONNX), in-process or scaled out to dedicated worker containers over RabbitMQ; CPU by default, GPU execution providers available.
38+
- **Typed .NET client** (`Jigen.Client`): dictionary-like collections, LINQ predicates translated to server-side filters.
5239

53-
## Running the gRPC server
40+
## Installation
5441

55-
Run the host project:
42+
**NuGet** (in-process):
5643

5744
```bash
58-
dotnet run --project src/Server/Jigen/Jigen.csproj
45+
dotnet add package Jigen.Store # embedded engine (net10.0)
46+
dotnet add package Jigen.Indexer.HNSW # ANN index for the engine
5947
```
6048

61-
Default endpoints are configured in `src/Server/Jigen/Program.cs`:
49+
**NuGet** (client):
6250

63-
- `http://localhost:13223` (`Http1AndHttp2`)
64-
- `http://localhost:3223` (`Http2`, gRPC)
51+
```bash
52+
dotnet add package Jigen.Client # client for the server (net8.0+)
53+
```
6554

66-
The gRPC service is mapped by the module in [src/Server/Jigen.Grpc/Module.cs](src/Server/Jigen.Grpc/Module.cs).
55+
**Docker** (server):
6756

57+
```bash
58+
# all-in-one: database + embedding generation in a single container
59+
docker run -d -p 3223:3223 -p 13223:13223 \
60+
-v jigen-data:/data/jigendb -v ./models:/data/onnx \
61+
ppossanzini/jigendb-all-in-one
62+
```
6863

69-
## Using the client
64+
Three images are published: `ppossanzini/jigendb` (server only), `ppossanzini/jigendb-all-in-one` (server + embeddings) and `ppossanzini/jigen-embeddings` (embedding worker). See [Docker deployment](docs/server/docker.md).
7065

71-
The client package is in [src/Client/Jigen.Client](src/Client/Jigen.Client).
66+
## Quick taste
7267

73-
Minimal usage pattern:
68+
In-process:
7469

7570
```csharp
76-
using Jigen.Client;
77-
using Jigen.Client.BaseTypes;
71+
using Jigen;
72+
using Jigen.DataStructures;
73+
using Jigen.Extensions;
74+
using Jigen.Indexer;
7875

79-
var ctx = new Context(new ConnectionOptions
76+
using var store = new Store(new StoreOptions
8077
{
81-
HostName = "localhost",
82-
Port = 3223,
83-
TLS = false,
84-
DatabaseName = "Test"
78+
DataBasePath = "/data/jigendb",
79+
DataBaseName = "demo",
80+
Indexer = new SmallWorldIndexer(new SmallWorldOptions(
81+
m: 16, efConstruction: 200, efSearch: 64, storagePath: "/data/jigendb/hnsw"))
8582
});
8683

87-
var collection = new VectorCollection<MyDocument>(ctx);
88-
89-
collection.Add(1, new VectorEntry<MyDocument>
84+
await store.AppendContent(new VectorEntry
9085
{
91-
Key = 1,
92-
Content = new MyDocument { Id = Guid.NewGuid(), Text = "hello" },
93-
Embedding = Array.Empty<float>()
86+
Id = Guid.NewGuid().ToByteArray(),
87+
CollectionName = "articles",
88+
Content = MessagePackDocumentSerializer.Instance.Serialize("hello vectors"),
89+
Embedding = embedding // float[] from your embedding model
9490
});
95-
```
9691

97-
For a concrete wrapper pattern, see [tests/JigenClientTest/Model/DB.cs](tests/JigenClientTest/Model/DB.cs) and [tests/JigenClientTest/UnitTest1.cs](tests/JigenClientTest/UnitTest1.cs).
92+
var results = store.Search("articles", queryEmbedding, top: 10);
93+
await store.SaveChangesAsync();
94+
```
9895

96+
Client against a server:
9997

100-
## CORS / gRPC-Web
98+
```csharp
99+
using Jigen.Client;
101100

102-
- General server CORS is configured in [src/Server/Jigen/Program.cs](src/Server/Jigen/Program.cs).
103-
- gRPC-specific CORS policy is configured in [src/Server/Jigen.Grpc/Module.cs](src/Server/Jigen.Grpc/Module.cs).
101+
var ctx = new Context(new ConnectionOptions { HostName = "localhost", Port = 3223, DatabaseName = "demo" });
102+
var articles = new VectorCollection<Article>(ctx);
104103

105-
Current status:
104+
articles.Add(Guid.NewGuid(), new Article { Title = "..." }, sentence: "text embedded by the server");
105+
var hits = articles.Search("query text", x => x.Category == "news", top: 5);
106+
```
106107

107-
- Native gRPC is enabled (`MapGrpcService<Server>()`).
108-
- gRPC-Web mapping is currently commented out in the module:
109-
- `.EnableGrpcWeb()`
110-
- `.RequireCors(JigenGrpcCorsDefaultPolicy)`
108+
## Documentation
111109

112-
If you need browser gRPC-Web clients, enable those lines and verify CORS policy for your frontend origin.
110+
Full documentation lives in [`docs/`](docs/index.md) (also buildable with MkDocs / Read the Docs).
113111

112+
| Section | Contents |
113+
|---|---|
114+
| [In-process engine](docs/in-process/overview.md) | [Getting started](docs/in-process/getting-started.md) · [Store options](docs/in-process/store-options.md) · [Collections](docs/in-process/collections.md) |
115+
| [Indexes](docs/indexes/hnsw.md) | [Brute force](docs/indexes/brute-force.md) · [HNSW](docs/indexes/hnsw.md) |
116+
| [Embeddings](docs/embeddings/overview.md) | [Configuration](docs/embeddings/configuration.md) · [Execution providers (CPU/GPU)](docs/embeddings/execution-providers.md) |
117+
| [Server](docs/server/overview.md) | [Configuration](docs/server/configuration.md) · [Docker](docs/server/docker.md) · [REST API](docs/server/rest-api.md) · [gRPC API](docs/server/grpc-api.md) |
118+
| [Client](docs/client/getting-started.md) | [Usage](docs/client/usage.md) |
119+
| [Benchmarks & hardware](docs/benchmarks.md) | Current numbers, supported and upcoming CPU/GPU technologies |
114120

115-
## Tests
121+
The server also ships a web administration UI (Jigen Insight) served on port 13223; it is not covered by this documentation yet.
116122

117-
Run all tests:
123+
## Building from source
118124

119125
```bash
120-
dotnet test Jigen.sln
126+
dotnet build Jigen.sln -m:1 # -m:1 required (StaticWebAssets breaks parallel builds)
127+
dotnet run --project src/Server/Jigen/Jigen.csproj
121128
```
122129

123-
Run focused suites:
130+
Tests:
124131

125132
```bash
126-
dotnet test tests/HnswTest/HnswTest.csproj
127133
dotnet test tests/JigenStoreTests/JigenStoreTests.csproj
128-
dotnet test tests/JigenClientTest/JigenClientTest.csproj
134+
dotnet test tests/HnswTest/HnswTest.csproj
129135
dotnet test tests/PrimitiveTests/PrimitiveTests.csproj
136+
# tests/JigenClientTest requires a running server on localhost:3223
130137
```
131138

132-
133-
## Troubleshooting
134-
135-
### HNSW index file (`*.hnsw.index`) is empty
136-
137-
If the `*.hnsw.index` file appears empty and HNSW returns no results after restart, ensure your app calls:
138-
139-
1. `SaveChangesAsync()`
140-
2. `Close()`
141-
142-
Recent fixes added an explicit indexer flush during store close, so `StoredList` header/index are persisted before process exit.
143-
144-
### HNSW returns fewer results than brute-force
145-
146-
This is expected in principle because HNSW is ANN (approximate nearest neighbors), but large gaps usually indicate:
147-
148-
- too-low `EfSearch`
149-
- insufficient `EfConstruction`
150-
- graph quality issues (construction/traversal bugs)
151-
152-
Tune `EfSearch` and `EfConstruction` in `SmallWorldOptions` first.
153-
154-
### gRPC client cannot connect
155-
156-
Check:
157-
158-
1. server is running
159-
2. client uses `http://localhost:5001` for HTTP/2 gRPC
160-
3. firewall/port blocks are not present
161-
162-
163139
## License
164140

165-
See [LICENSE.txt](LICENSE.txt).
166-
141+
Apache-2.0 — see [LICENSE.txt](LICENSE.txt).

assets/Jigen-128.png

-23.4 KB
Binary file not shown.
163 KB
Binary file not shown.

assets/files/jigen-icona-1024.png

31 KB
Loading

assets/files/jigen-icona-dark.svg

Lines changed: 10 additions & 0 deletions
Loading

assets/files/jigen-icona.svg

Lines changed: 10 additions & 0 deletions
Loading
34.8 KB
Loading
27.3 KB
Loading
Lines changed: 11 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)