|
| 1 | +# Milvus Vector Index |
| 2 | + |
| 3 | +memU can route in-memory metadata-store similarity search to [Milvus](https://milvus.io/) as an external vector index. This is useful when: |
| 4 | + |
| 5 | +- **Scale**: you have more vectors than the brute-force fallback can handle at latency budget. |
| 6 | +- **Managed deployments**: you want to offload vector infrastructure to Zilliz Cloud or a self-hosted Milvus cluster. |
| 7 | +- **Zero-setup local dev**: Milvus Lite runs as a local file (`./milvus.db`) with no external service. |
| 8 | + |
| 9 | +## Install |
| 10 | + |
| 11 | +```bash |
| 12 | +uv sync --extra milvus |
| 13 | +``` |
| 14 | + |
| 15 | +> The `milvus` extra pulls `pymilvus`, `milvus-lite` and — on Python 3.13 — a `setuptools<81` compatibility pin because Milvus Lite 3.0 still imports `pkg_resources`. New local Milvus Lite files should use the 3.x storage format; older 2.x `.db` files are not expected to be reusable after upgrading to Milvus Lite 3.x. |
| 16 | +
|
| 17 | +## Quick Start (Milvus Lite) |
| 18 | + |
| 19 | +```python |
| 20 | +from memu.app import MemoryService |
| 21 | + |
| 22 | +service = MemoryService( |
| 23 | + llm_profiles={"default": {"api_key": "your-api-key"}}, |
| 24 | + database_config={ |
| 25 | + "metadata_store": {"provider": "inmemory"}, |
| 26 | + "vector_index": {"provider": "milvus"}, |
| 27 | + }, |
| 28 | +) |
| 29 | +``` |
| 30 | + |
| 31 | +With the default configuration the index is persisted to `./milvus.db` using Milvus Lite — no Docker, no separate process. |
| 32 | + |
| 33 | +## Targeting a Milvus Server |
| 34 | + |
| 35 | +```python |
| 36 | +database_config = { |
| 37 | + "metadata_store": {"provider": "inmemory"}, |
| 38 | + "vector_index": { |
| 39 | + "provider": "milvus", |
| 40 | + "uri": "http://localhost:19530", |
| 41 | + "collection_name": "memu_prod", |
| 42 | + }, |
| 43 | +} |
| 44 | +``` |
| 45 | + |
| 46 | +## Targeting Zilliz Cloud |
| 47 | + |
| 48 | +```python |
| 49 | +import os |
| 50 | + |
| 51 | +database_config = { |
| 52 | + "metadata_store": {"provider": "inmemory"}, |
| 53 | + "vector_index": { |
| 54 | + "provider": "milvus", |
| 55 | + "uri": os.environ["ZILLIZ_URI"], |
| 56 | + "token": os.environ["ZILLIZ_TOKEN"], |
| 57 | + "collection_name": "memu_prod", |
| 58 | + }, |
| 59 | +} |
| 60 | +``` |
| 61 | + |
| 62 | +## Configuration |
| 63 | + |
| 64 | +| Field | Default | Notes | |
| 65 | +| --- | --- | --- | |
| 66 | +| `provider` | — | Must be `"milvus"` to enable this index. | |
| 67 | +| `uri` | `"./milvus.db"` | File path runs Milvus Lite; `http(s)://host:port` targets a Milvus server; a Zilliz Cloud endpoint targets the managed service. | |
| 68 | +| `token` | `None` | Auth token for Zilliz Cloud or a secured Milvus server. | |
| 69 | +| `db_name` | `None` | Optional Milvus database name. | |
| 70 | +| `collection_name` | `"memu_memory_items"` | Name of the Milvus collection that holds memory vectors. | |
| 71 | +| `dim` | `None` | Embedding dimension. Inferred from the first upsert when omitted. | |
| 72 | +| `consistency_level` | `None` | Optional Milvus collection consistency level (`"Strong"`, `"Session"`, `"Bounded"`, or `"Eventually"`). Uses the server default when omitted. | |
| 73 | + |
| 74 | +## Supported Combinations |
| 75 | + |
| 76 | +memU keeps metadata records (summary, categories, scope, reinforcement stats, ...) in the metadata store and mirrors embeddings into Milvus on create / update / delete. |
| 77 | + |
| 78 | +- **Available now**: `inmemory` metadata store + Milvus vector index (feature-complete). |
| 79 | +- **Not wired yet**: `sqlite` and `postgres` metadata stores reject `vector_index.provider="milvus"` rather than silently ignoring it. See `docs/adr/0008-external-vector-index.md` for the rollout plan. |
| 80 | + |
| 81 | +## How Search Works |
| 82 | + |
| 83 | +1. `create_item` / `update_item` mirror the embedding (and scope fields such as `user_id`, `agent_id`) into the configured Milvus collection. |
| 84 | +2. `vector_search_items` forwards the query vector to Milvus using a COSINE AUTOINDEX. Scope filters (e.g. `where={"user_id": "u1"}`) are translated into Milvus boolean expressions on dynamic fields. |
| 85 | +3. Milvus returns `(id, score)` pairs; the metadata store resolves them back to full memory records. |
| 86 | +4. Salience ranking (`ranking="salience"`) still runs locally because it needs per-item reinforcement and recency factors that the vector index does not store. |
0 commit comments