cli-memory-os 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cli_memory_os-0.1.0/LICENSE +21 -0
- cli_memory_os-0.1.0/MANIFEST.in +20 -0
- cli_memory_os-0.1.0/PKG-INFO +231 -0
- cli_memory_os-0.1.0/README.md +205 -0
- cli_memory_os-0.1.0/cli/__init__.py +1 -0
- cli_memory_os-0.1.0/cli/commands/__init__.py +1 -0
- cli_memory_os-0.1.0/cli/commands/benchmark.py +151 -0
- cli_memory_os-0.1.0/cli/commands/config_cmd.py +57 -0
- cli_memory_os-0.1.0/cli/commands/doctor.py +61 -0
- cli_memory_os-0.1.0/cli/commands/export.py +106 -0
- cli_memory_os-0.1.0/cli/commands/import_cmd.py +143 -0
- cli_memory_os-0.1.0/cli/commands/init.py +205 -0
- cli_memory_os-0.1.0/cli/commands/logs.py +38 -0
- cli_memory_os-0.1.0/cli/commands/monitor.py +63 -0
- cli_memory_os-0.1.0/cli/commands/plugins.py +37 -0
- cli_memory_os-0.1.0/cli/commands/start.py +24 -0
- cli_memory_os-0.1.0/cli/commands/status.py +92 -0
- cli_memory_os-0.1.0/cli/commands/stop.py +19 -0
- cli_memory_os-0.1.0/cli/commands/version.py +25 -0
- cli_memory_os-0.1.0/cli/commands/workspace.py +154 -0
- cli_memory_os-0.1.0/cli/main.py +496 -0
- cli_memory_os-0.1.0/cli/parser.py +188 -0
- cli_memory_os-0.1.0/cli_memory_os.egg-info/PKG-INFO +231 -0
- cli_memory_os-0.1.0/cli_memory_os.egg-info/SOURCES.txt +58 -0
- cli_memory_os-0.1.0/cli_memory_os.egg-info/dependency_links.txt +1 -0
- cli_memory_os-0.1.0/cli_memory_os.egg-info/entry_points.txt +2 -0
- cli_memory_os-0.1.0/cli_memory_os.egg-info/requires.txt +11 -0
- cli_memory_os-0.1.0/cli_memory_os.egg-info/top_level.txt +8 -0
- cli_memory_os-0.1.0/connectors/__init__.py +1 -0
- cli_memory_os-0.1.0/connectors/base.py +39 -0
- cli_memory_os-0.1.0/connectors/github.py +273 -0
- cli_memory_os-0.1.0/connectors/gmail.py +116 -0
- cli_memory_os-0.1.0/connectors/notion.py +156 -0
- cli_memory_os-0.1.0/connectors/registry.py +60 -0
- cli_memory_os-0.1.0/core/__init__.py +1 -0
- cli_memory_os-0.1.0/core/chunker.py +136 -0
- cli_memory_os-0.1.0/core/context_builder.py +407 -0
- cli_memory_os-0.1.0/core/embedder.py +42 -0
- cli_memory_os-0.1.0/core/llm.py +301 -0
- cli_memory_os-0.1.0/core/vector_store.py +629 -0
- cli_memory_os-0.1.0/infrastructure/__init__.py +1 -0
- cli_memory_os-0.1.0/infrastructure/compose.py +136 -0
- cli_memory_os-0.1.0/infrastructure/config.py +280 -0
- cli_memory_os-0.1.0/infrastructure/docker.py +61 -0
- cli_memory_os-0.1.0/infrastructure/health.py +338 -0
- cli_memory_os-0.1.0/infrastructure/observability.py +160 -0
- cli_memory_os-0.1.0/infrastructure/workspace.py +152 -0
- cli_memory_os-0.1.0/models/__init__.py +1 -0
- cli_memory_os-0.1.0/models/memory.py +28 -0
- cli_memory_os-0.1.0/pyproject.toml +45 -0
- cli_memory_os-0.1.0/setup.cfg +4 -0
- cli_memory_os-0.1.0/storage/__init__.py +1 -0
- cli_memory_os-0.1.0/storage/db.py +528 -0
- cli_memory_os-0.1.0/storage/graph.py +324 -0
- cli_memory_os-0.1.0/storage/schema.sql +57 -0
- cli_memory_os-0.1.0/storage/tech_detector.py +117 -0
- cli_memory_os-0.1.0/tests/test_cli_integration.py +274 -0
- cli_memory_os-0.1.0/tests/test_commands_phase2.py +99 -0
- cli_memory_os-0.1.0/tests/test_first_time_user_experience.py +105 -0
- cli_memory_os-0.1.0/tests/test_v1_features.py +353 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Memory-OS Authors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
include README.md
|
|
2
|
+
include LICENSE
|
|
3
|
+
include storage/schema.sql
|
|
4
|
+
recursive-include cli/ *.py
|
|
5
|
+
recursive-include infrastructure/ *.py
|
|
6
|
+
recursive-include connectors/ *.py
|
|
7
|
+
recursive-include core/ *.py
|
|
8
|
+
recursive-include storage/ *.py
|
|
9
|
+
recursive-include models/ *.py
|
|
10
|
+
global-exclude *.pyc
|
|
11
|
+
global-exclude __pycache__
|
|
12
|
+
global-exclude *.db
|
|
13
|
+
global-exclude qdrant_storage/
|
|
14
|
+
global-exclude .env
|
|
15
|
+
global-exclude logs/
|
|
16
|
+
prune clean_env
|
|
17
|
+
prune .venv
|
|
18
|
+
global-exclude clean_env/*
|
|
19
|
+
global-exclude .venv/*
|
|
20
|
+
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cli-memory-os
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: CLI-based Personal Knowledge Operating System
|
|
5
|
+
Author-email: Anirudh T <anirudh200584@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: RAG,Knowledge-Graph,Vector-Search,Personal-Assistant,LLM,Composio
|
|
8
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
12
|
+
Requires-Python: >=3.12
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: composio==0.13.1
|
|
16
|
+
Requires-Dist: composio-langchain==0.13.1
|
|
17
|
+
Requires-Dist: langchain==1.3.9
|
|
18
|
+
Requires-Dist: langchain-groq==1.1.3
|
|
19
|
+
Requires-Dist: python-dotenv==1.2.2
|
|
20
|
+
Requires-Dist: qdrant-client==1.18.0
|
|
21
|
+
Requires-Dist: neo4j==6.2.0
|
|
22
|
+
Requires-Dist: sentence-transformers==5.6.0
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
25
|
+
Dynamic: license-file
|
|
26
|
+
|
|
27
|
+
# Memory‑OS 🧠
|
|
28
|
+
|
|
29
|
+
[](https://pypi.org/project/memory-os/)
|
|
30
|
+
[](https://opensource.org/licenses/MIT)
|
|
31
|
+
|
|
32
|
+
**Memory‑OS** is a local Personal Knowledge Operating System that syncs, indexes, and retrieves information across your GitHub repositories, emails, and Notion workspaces. It runs a unified interactive CLI, exposing hybrid keyword + semantic search and natural language QA powered by RAG, local embeddings, and a knowledge graph.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 🏗️ Architecture
|
|
37
|
+
|
|
38
|
+
Memory-OS is built as a modular architecture consisting of ingestion, databases, scoring ranking engines, and a terminal user loop:
|
|
39
|
+
|
|
40
|
+
```mermaid
|
|
41
|
+
graph TD
|
|
42
|
+
%% Ingestion
|
|
43
|
+
subgraph Ingestion [1. Ingestion Layer]
|
|
44
|
+
GH[GitHub Repos & Docs]
|
|
45
|
+
GM[Gmail Inbox Messages]
|
|
46
|
+
NT[Notion Page Contents]
|
|
47
|
+
CP[Composio Integration Platform]
|
|
48
|
+
GH --> CP
|
|
49
|
+
GM --> CP
|
|
50
|
+
NT --> CP
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
%% Storage & Indexing
|
|
54
|
+
subgraph Storage [2. Storage & Indexing Layer]
|
|
55
|
+
DB[(SQLite: workspace.db)]
|
|
56
|
+
QD[(Qdrant: Qdrant Server)]
|
|
57
|
+
N4J[(Neo4j Graph Database)]
|
|
58
|
+
SQL_G[(SQLite Graph Fallback)]
|
|
59
|
+
|
|
60
|
+
CP -->|Insert Metadata & Docs| DB
|
|
61
|
+
DB -->|Text Chunks| CH[Chunking Core]
|
|
62
|
+
CH -->|Local Embeddings| EM[SentenceTransformer]
|
|
63
|
+
EM -->|Vectors| QD
|
|
64
|
+
|
|
65
|
+
DB -->|Graph Construction| N4J
|
|
66
|
+
DB -->|Graph Construction| SQL_G
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
%% Retrieval & RAG
|
|
70
|
+
subgraph Retrieval [3. Retrieval & RAG Layer]
|
|
71
|
+
HS[Hybrid Search Router]
|
|
72
|
+
QD -->|Cosine Similarity| HS
|
|
73
|
+
DB -->|Keyword Matching| HS
|
|
74
|
+
N4J -->|Graph Lookups| HS
|
|
75
|
+
SQL_G -->|Graph Fallback Lookups| HS
|
|
76
|
+
|
|
77
|
+
HR[Hybrid Ranking Scoring]
|
|
78
|
+
HS --> HR
|
|
79
|
+
|
|
80
|
+
RAG[RAG Context Builder]
|
|
81
|
+
HR -->|Merged Context| RAG
|
|
82
|
+
|
|
83
|
+
LLM[Groq LLM Pipeline]
|
|
84
|
+
RAG -->|Prompt Assembly| LLM
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
%% User Interaction
|
|
88
|
+
subgraph User [4. Interface Layer]
|
|
89
|
+
CLI[main.py: CLI Command Loop]
|
|
90
|
+
CLI -->|Sync/Rebuild| Ingestion
|
|
91
|
+
CLI -->|Search/Ask Queries| Retrieval
|
|
92
|
+
LLM -->|Formatted Answer| CLI
|
|
93
|
+
end
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## 🗄️ Database Technology Rationale
|
|
99
|
+
|
|
100
|
+
Memory-OS adopts a **multi-model storage engine strategy**, selecting each technology to excel at its designated retrieve-and-rank role:
|
|
101
|
+
|
|
102
|
+
| Database | Selection Rationale |
|
|
103
|
+
| :--- | :--- |
|
|
104
|
+
| **SQLite (`workspace.db`)** | Chosen for lightweight structured storage. It holds raw documents, chunk segments, email metadata, and repository statistics, providing ACID compliance and ultra-fast exact keyword searches. |
|
|
105
|
+
| **Qdrant** | Chosen as a high-performance vector database optimized for storing and executing cosine similarity search queries on $384$-dimensional dense vector embeddings generated by Sentence-Transformers. |
|
|
106
|
+
| **Neo4j / Fallback SQLite** | Neo4j is utilized as a native graph database to map complex developer relationships (e.g. `Repository-[USES]->Technology` or `Email-[SENT_BY]->User`). If Neo4j is unreachable, it seamlessly falls back to a relational SQLite graph schema, preserving search functionality offline. |
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 🗄️ Workspace Structure
|
|
111
|
+
|
|
112
|
+
Memory-OS manages directories and configuration under the user's home folder (`~/.memory-os/`):
|
|
113
|
+
```
|
|
114
|
+
~/.memory-os/
|
|
115
|
+
├── config.toml # Global TOML settings configuration
|
|
116
|
+
├── active_profile # Stores name of the currently active profile
|
|
117
|
+
└── workspaces/
|
|
118
|
+
├── default/ # Default workspace profile directory
|
|
119
|
+
│ ├── workspace.db # SQLite relational database
|
|
120
|
+
│ ├── qdrant/ # Qdrant local bind-mounted storage folder
|
|
121
|
+
│ ├── neo4j/ # Neo4j local bind-mounted storage folder
|
|
122
|
+
│ ├── logs/ # Log folder containing memory_os.log
|
|
123
|
+
│ └── cache/ # Chunker cache folder
|
|
124
|
+
└── personal/ # Personal workspace profile directory
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 📦 Setup & Installation
|
|
130
|
+
|
|
131
|
+
Ensure you have **Python >= 3.12** and **Docker + Docker Compose** installed.
|
|
132
|
+
|
|
133
|
+
### 1. Install via pip
|
|
134
|
+
You can install Memory-OS directly as a package:
|
|
135
|
+
```bash
|
|
136
|
+
pip install .
|
|
137
|
+
```
|
|
138
|
+
This registers the CLI entry point executable `memory-os` on your path.
|
|
139
|
+
|
|
140
|
+
### 2. Run the Initialization Wizard
|
|
141
|
+
Kick off the interactive wizard to verify system dependencies, configure API keys, spin up containers, and pre-warm model weights:
|
|
142
|
+
```bash
|
|
143
|
+
memory-os init
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## 🚀 CLI Commands Reference
|
|
149
|
+
|
|
150
|
+
Memory-OS exposes a comprehensive CLI for administration:
|
|
151
|
+
|
|
152
|
+
### Core Daemon Lifecycle
|
|
153
|
+
- **`memory-os start`**: Spins up Neo4j and Qdrant database services in the background using Docker Compose.
|
|
154
|
+
- **`memory-os stop`**: Stops the database services while retaining data directories intact.
|
|
155
|
+
|
|
156
|
+
### Operations & Ingestion
|
|
157
|
+
- **`memory-os sync [--source SOURCE] [--rebuild]`**: Triggers incremental data imports from registered sources (GitHub, Gmail, Notion). Add `--rebuild` for full vector/graph resets.
|
|
158
|
+
- **`memory-os ask <question>`**: Runs natural language queries against the RAG retrieval pipeline.
|
|
159
|
+
- **`memory-os graph <repo>`**: Visualizes the relationships of an indexed repository in the terminal knowledge graph.
|
|
160
|
+
|
|
161
|
+
### Diagnostics & Monitoring
|
|
162
|
+
- **`memory-os doctor`**: Analyzes connection validation health across all endpoints and prints actionable troubleshooting tips on failure.
|
|
163
|
+
- **`memory-os monitor`**: Displays aggregated data latencies (indexing speed, search rates, LLM times) by parsing system log traces.
|
|
164
|
+
- **`memory-os benchmark`**: Performs query speed runs on keyword, semantic, hybrid searches, and RAG pipelines.
|
|
165
|
+
- **`memory-os logs [--tail N]`**: Tails the running logs of Memory-OS (rotates at 5MB, up to 3 backups).
|
|
166
|
+
|
|
167
|
+
### Configuration Management
|
|
168
|
+
- **`memory-os config show`**: Displays the active key-value configuration block.
|
|
169
|
+
- **`memory-os config get <key>`**: Fetches a nested key value (e.g. `groq.model`).
|
|
170
|
+
- **`memory-os config set <key> <value>`**: Sets a nested key value with type validation checks.
|
|
171
|
+
- **`memory-os config reset`**: Prompts and reverts all configurations to factory defaults.
|
|
172
|
+
|
|
173
|
+
### Workspace Profile Profiles
|
|
174
|
+
- **`memory-os workspace list`**: Lists all profiles (* marks active).
|
|
175
|
+
- **`memory-os workspace create <name>`**: Allocates a new workspace folder tree.
|
|
176
|
+
- **`memory-os workspace switch <name>`**: Switches the active profile context.
|
|
177
|
+
- **`memory-os workspace delete <name>`**: Wipes profile folder directories.
|
|
178
|
+
- **`memory-os workspace info`**: Displays detailed record metrics (nodes, vectors, sizes) for the active profile.
|
|
179
|
+
|
|
180
|
+
### Portability (Export / Import)
|
|
181
|
+
- **`memory-os export <backup-zip>`**: Compresses database schemas, configurations, and vector indices into a versioned zip package.
|
|
182
|
+
- **`memory-os import <backup-zip>`**: Overwrites the active workspace profile using files from an export package after validating versions and model compatibility.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## 🔌 Plugin System Architecture
|
|
187
|
+
|
|
188
|
+
Memory-OS features a structured connector registry. Every connector implements `BaseConnector` (`connectors/base.py`) and is registered using the `@register` decorator (`connectors/registry.py`):
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
from connectors.base import BaseConnector
|
|
192
|
+
from connectors.registry import register
|
|
193
|
+
|
|
194
|
+
@register
|
|
195
|
+
class SlackConnector(BaseConnector):
|
|
196
|
+
name = "Slack"
|
|
197
|
+
slug = "slack"
|
|
198
|
+
|
|
199
|
+
def authenticate(self) -> bool:
|
|
200
|
+
# Check OAuth or API status
|
|
201
|
+
return True
|
|
202
|
+
|
|
203
|
+
def sync(self) -> dict:
|
|
204
|
+
# Fetch channels and messages
|
|
205
|
+
return {"synced": 42}
|
|
206
|
+
|
|
207
|
+
def health(self) -> tuple[bool, str]:
|
|
208
|
+
return True, "Connected"
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
To list registered plugins:
|
|
212
|
+
```bash
|
|
213
|
+
memory-os plugins
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## 🛠️ Troubleshooting
|
|
219
|
+
|
|
220
|
+
- **Database Offline / Port conflicts**: If Neo4j (ports 7474/7687) or Qdrant (port 6333) fails to start, modify port configurations:
|
|
221
|
+
```bash
|
|
222
|
+
memory-os config set neo4j.port_http 7475
|
|
223
|
+
memory-os config set qdrant.port 6334
|
|
224
|
+
memory-os start
|
|
225
|
+
```
|
|
226
|
+
- **Failing Diagnostics**: Run `memory-os doctor` to inspect status. It provides detailed actionable tips to address common environment issues.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## 📜 License
|
|
231
|
+
This project is licensed under the **MIT License**.
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# Memory‑OS 🧠
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/memory-os/)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
**Memory‑OS** is a local Personal Knowledge Operating System that syncs, indexes, and retrieves information across your GitHub repositories, emails, and Notion workspaces. It runs a unified interactive CLI, exposing hybrid keyword + semantic search and natural language QA powered by RAG, local embeddings, and a knowledge graph.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 🏗️ Architecture
|
|
11
|
+
|
|
12
|
+
Memory-OS is built as a modular architecture consisting of ingestion, databases, scoring ranking engines, and a terminal user loop:
|
|
13
|
+
|
|
14
|
+
```mermaid
|
|
15
|
+
graph TD
|
|
16
|
+
%% Ingestion
|
|
17
|
+
subgraph Ingestion [1. Ingestion Layer]
|
|
18
|
+
GH[GitHub Repos & Docs]
|
|
19
|
+
GM[Gmail Inbox Messages]
|
|
20
|
+
NT[Notion Page Contents]
|
|
21
|
+
CP[Composio Integration Platform]
|
|
22
|
+
GH --> CP
|
|
23
|
+
GM --> CP
|
|
24
|
+
NT --> CP
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
%% Storage & Indexing
|
|
28
|
+
subgraph Storage [2. Storage & Indexing Layer]
|
|
29
|
+
DB[(SQLite: workspace.db)]
|
|
30
|
+
QD[(Qdrant: Qdrant Server)]
|
|
31
|
+
N4J[(Neo4j Graph Database)]
|
|
32
|
+
SQL_G[(SQLite Graph Fallback)]
|
|
33
|
+
|
|
34
|
+
CP -->|Insert Metadata & Docs| DB
|
|
35
|
+
DB -->|Text Chunks| CH[Chunking Core]
|
|
36
|
+
CH -->|Local Embeddings| EM[SentenceTransformer]
|
|
37
|
+
EM -->|Vectors| QD
|
|
38
|
+
|
|
39
|
+
DB -->|Graph Construction| N4J
|
|
40
|
+
DB -->|Graph Construction| SQL_G
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
%% Retrieval & RAG
|
|
44
|
+
subgraph Retrieval [3. Retrieval & RAG Layer]
|
|
45
|
+
HS[Hybrid Search Router]
|
|
46
|
+
QD -->|Cosine Similarity| HS
|
|
47
|
+
DB -->|Keyword Matching| HS
|
|
48
|
+
N4J -->|Graph Lookups| HS
|
|
49
|
+
SQL_G -->|Graph Fallback Lookups| HS
|
|
50
|
+
|
|
51
|
+
HR[Hybrid Ranking Scoring]
|
|
52
|
+
HS --> HR
|
|
53
|
+
|
|
54
|
+
RAG[RAG Context Builder]
|
|
55
|
+
HR -->|Merged Context| RAG
|
|
56
|
+
|
|
57
|
+
LLM[Groq LLM Pipeline]
|
|
58
|
+
RAG -->|Prompt Assembly| LLM
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
%% User Interaction
|
|
62
|
+
subgraph User [4. Interface Layer]
|
|
63
|
+
CLI[main.py: CLI Command Loop]
|
|
64
|
+
CLI -->|Sync/Rebuild| Ingestion
|
|
65
|
+
CLI -->|Search/Ask Queries| Retrieval
|
|
66
|
+
LLM -->|Formatted Answer| CLI
|
|
67
|
+
end
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 🗄️ Database Technology Rationale
|
|
73
|
+
|
|
74
|
+
Memory-OS adopts a **multi-model storage engine strategy**, selecting each technology to excel at its designated retrieve-and-rank role:
|
|
75
|
+
|
|
76
|
+
| Database | Selection Rationale |
|
|
77
|
+
| :--- | :--- |
|
|
78
|
+
| **SQLite (`workspace.db`)** | Chosen for lightweight structured storage. It holds raw documents, chunk segments, email metadata, and repository statistics, providing ACID compliance and ultra-fast exact keyword searches. |
|
|
79
|
+
| **Qdrant** | Chosen as a high-performance vector database optimized for storing and executing cosine similarity search queries on $384$-dimensional dense vector embeddings generated by Sentence-Transformers. |
|
|
80
|
+
| **Neo4j / Fallback SQLite** | Neo4j is utilized as a native graph database to map complex developer relationships (e.g. `Repository-[USES]->Technology` or `Email-[SENT_BY]->User`). If Neo4j is unreachable, it seamlessly falls back to a relational SQLite graph schema, preserving search functionality offline. |
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 🗄️ Workspace Structure
|
|
85
|
+
|
|
86
|
+
Memory-OS manages directories and configuration under the user's home folder (`~/.memory-os/`):
|
|
87
|
+
```
|
|
88
|
+
~/.memory-os/
|
|
89
|
+
├── config.toml # Global TOML settings configuration
|
|
90
|
+
├── active_profile # Stores name of the currently active profile
|
|
91
|
+
└── workspaces/
|
|
92
|
+
├── default/ # Default workspace profile directory
|
|
93
|
+
│ ├── workspace.db # SQLite relational database
|
|
94
|
+
│ ├── qdrant/ # Qdrant local bind-mounted storage folder
|
|
95
|
+
│ ├── neo4j/ # Neo4j local bind-mounted storage folder
|
|
96
|
+
│ ├── logs/ # Log folder containing memory_os.log
|
|
97
|
+
│ └── cache/ # Chunker cache folder
|
|
98
|
+
└── personal/ # Personal workspace profile directory
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 📦 Setup & Installation
|
|
104
|
+
|
|
105
|
+
Ensure you have **Python >= 3.12** and **Docker + Docker Compose** installed.
|
|
106
|
+
|
|
107
|
+
### 1. Install via pip
|
|
108
|
+
You can install Memory-OS directly as a package:
|
|
109
|
+
```bash
|
|
110
|
+
pip install .
|
|
111
|
+
```
|
|
112
|
+
This registers the CLI entry point executable `memory-os` on your path.
|
|
113
|
+
|
|
114
|
+
### 2. Run the Initialization Wizard
|
|
115
|
+
Kick off the interactive wizard to verify system dependencies, configure API keys, spin up containers, and pre-warm model weights:
|
|
116
|
+
```bash
|
|
117
|
+
memory-os init
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 🚀 CLI Commands Reference
|
|
123
|
+
|
|
124
|
+
Memory-OS exposes a comprehensive CLI for administration:
|
|
125
|
+
|
|
126
|
+
### Core Daemon Lifecycle
|
|
127
|
+
- **`memory-os start`**: Spins up Neo4j and Qdrant database services in the background using Docker Compose.
|
|
128
|
+
- **`memory-os stop`**: Stops the database services while retaining data directories intact.
|
|
129
|
+
|
|
130
|
+
### Operations & Ingestion
|
|
131
|
+
- **`memory-os sync [--source SOURCE] [--rebuild]`**: Triggers incremental data imports from registered sources (GitHub, Gmail, Notion). Add `--rebuild` for full vector/graph resets.
|
|
132
|
+
- **`memory-os ask <question>`**: Runs natural language queries against the RAG retrieval pipeline.
|
|
133
|
+
- **`memory-os graph <repo>`**: Visualizes the relationships of an indexed repository in the terminal knowledge graph.
|
|
134
|
+
|
|
135
|
+
### Diagnostics & Monitoring
|
|
136
|
+
- **`memory-os doctor`**: Analyzes connection validation health across all endpoints and prints actionable troubleshooting tips on failure.
|
|
137
|
+
- **`memory-os monitor`**: Displays aggregated data latencies (indexing speed, search rates, LLM times) by parsing system log traces.
|
|
138
|
+
- **`memory-os benchmark`**: Performs query speed runs on keyword, semantic, hybrid searches, and RAG pipelines.
|
|
139
|
+
- **`memory-os logs [--tail N]`**: Tails the running logs of Memory-OS (rotates at 5MB, up to 3 backups).
|
|
140
|
+
|
|
141
|
+
### Configuration Management
|
|
142
|
+
- **`memory-os config show`**: Displays the active key-value configuration block.
|
|
143
|
+
- **`memory-os config get <key>`**: Fetches a nested key value (e.g. `groq.model`).
|
|
144
|
+
- **`memory-os config set <key> <value>`**: Sets a nested key value with type validation checks.
|
|
145
|
+
- **`memory-os config reset`**: Prompts and reverts all configurations to factory defaults.
|
|
146
|
+
|
|
147
|
+
### Workspace Profile Profiles
|
|
148
|
+
- **`memory-os workspace list`**: Lists all profiles (* marks active).
|
|
149
|
+
- **`memory-os workspace create <name>`**: Allocates a new workspace folder tree.
|
|
150
|
+
- **`memory-os workspace switch <name>`**: Switches the active profile context.
|
|
151
|
+
- **`memory-os workspace delete <name>`**: Wipes profile folder directories.
|
|
152
|
+
- **`memory-os workspace info`**: Displays detailed record metrics (nodes, vectors, sizes) for the active profile.
|
|
153
|
+
|
|
154
|
+
### Portability (Export / Import)
|
|
155
|
+
- **`memory-os export <backup-zip>`**: Compresses database schemas, configurations, and vector indices into a versioned zip package.
|
|
156
|
+
- **`memory-os import <backup-zip>`**: Overwrites the active workspace profile using files from an export package after validating versions and model compatibility.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 🔌 Plugin System Architecture
|
|
161
|
+
|
|
162
|
+
Memory-OS features a structured connector registry. Every connector implements `BaseConnector` (`connectors/base.py`) and is registered using the `@register` decorator (`connectors/registry.py`):
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
from connectors.base import BaseConnector
|
|
166
|
+
from connectors.registry import register
|
|
167
|
+
|
|
168
|
+
@register
|
|
169
|
+
class SlackConnector(BaseConnector):
|
|
170
|
+
name = "Slack"
|
|
171
|
+
slug = "slack"
|
|
172
|
+
|
|
173
|
+
def authenticate(self) -> bool:
|
|
174
|
+
# Check OAuth or API status
|
|
175
|
+
return True
|
|
176
|
+
|
|
177
|
+
def sync(self) -> dict:
|
|
178
|
+
# Fetch channels and messages
|
|
179
|
+
return {"synced": 42}
|
|
180
|
+
|
|
181
|
+
def health(self) -> tuple[bool, str]:
|
|
182
|
+
return True, "Connected"
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
To list registered plugins:
|
|
186
|
+
```bash
|
|
187
|
+
memory-os plugins
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## 🛠️ Troubleshooting
|
|
193
|
+
|
|
194
|
+
- **Database Offline / Port conflicts**: If Neo4j (ports 7474/7687) or Qdrant (port 6333) fails to start, modify port configurations:
|
|
195
|
+
```bash
|
|
196
|
+
memory-os config set neo4j.port_http 7475
|
|
197
|
+
memory-os config set qdrant.port 6334
|
|
198
|
+
memory-os start
|
|
199
|
+
```
|
|
200
|
+
- **Failing Diagnostics**: Run `memory-os doctor` to inspect status. It provides detailed actionable tips to address common environment issues.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## 📜 License
|
|
205
|
+
This project is licensed under the **MIT License**.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# cli package
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# cli.commands package
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Command: memory-os benchmark
|
|
3
|
+
|
|
4
|
+
Runs performance latency diagnostics across search indexes, embedding model,
|
|
5
|
+
graph lookups, LLM invocation, and RAG pipelines.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import time
|
|
9
|
+
import sys
|
|
10
|
+
from infrastructure.health import check_neo4j, check_qdrant, check_groq_api, check_memory_usage
|
|
11
|
+
from core.embedder import Embedder
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def execute(args):
|
|
15
|
+
"""Run the benchmark command."""
|
|
16
|
+
from storage.db import init_db
|
|
17
|
+
try:
|
|
18
|
+
init_db()
|
|
19
|
+
except Exception:
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
print("──────────────────────────────────────────────────")
|
|
23
|
+
print(" Memory-OS Performance Benchmark")
|
|
24
|
+
print("──────────────────────────────────────────────────")
|
|
25
|
+
print(" Running latency measurements (please wait)...")
|
|
26
|
+
|
|
27
|
+
# Metrics dictionary
|
|
28
|
+
latencies = {
|
|
29
|
+
"Keyword Search": "N/A",
|
|
30
|
+
"Semantic Search": "N/A",
|
|
31
|
+
"Hybrid Search": "N/A",
|
|
32
|
+
"Graph Lookup": "N/A",
|
|
33
|
+
"Embedding Time": "N/A",
|
|
34
|
+
"LLM Time": "N/A",
|
|
35
|
+
"Average RAG Pipeline": "N/A",
|
|
36
|
+
"Memory Usage": "N/A",
|
|
37
|
+
"Vector Count": "0",
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# 1. Memory Usage
|
|
41
|
+
_, mem_detail = check_memory_usage()
|
|
42
|
+
latencies["Memory Usage"] = mem_detail
|
|
43
|
+
|
|
44
|
+
# 2. Embedding Time
|
|
45
|
+
try:
|
|
46
|
+
start = time.perf_counter()
|
|
47
|
+
embedder = Embedder()
|
|
48
|
+
embedder.embed_documents(["This is a test snippet to benchmark the local embedding model latency."])
|
|
49
|
+
duration = time.perf_counter() - start
|
|
50
|
+
latencies["Embedding Time"] = f"{duration*1000:.1f} ms"
|
|
51
|
+
except Exception as e:
|
|
52
|
+
latencies["Embedding Time"] = f"Error: {e}"
|
|
53
|
+
|
|
54
|
+
# 3. SQLite Keyword Search
|
|
55
|
+
try:
|
|
56
|
+
from storage.db import get_connection
|
|
57
|
+
conn = get_connection()
|
|
58
|
+
cursor = conn.cursor()
|
|
59
|
+
|
|
60
|
+
# Test full text search query on SQLite
|
|
61
|
+
start = time.perf_counter()
|
|
62
|
+
cursor.execute("SELECT id FROM document_chunks WHERE chunk_text LIKE '%python%' LIMIT 5")
|
|
63
|
+
cursor.fetchall()
|
|
64
|
+
duration = time.perf_counter() - start
|
|
65
|
+
latencies["Keyword Search"] = f"{duration*1000:.2f} ms"
|
|
66
|
+
conn.close()
|
|
67
|
+
except Exception as e:
|
|
68
|
+
latencies["Keyword Search"] = f"Error: {e}"
|
|
69
|
+
|
|
70
|
+
# 4. Qdrant Semantic Search
|
|
71
|
+
qdrant_ok, _ = check_qdrant()
|
|
72
|
+
if qdrant_ok:
|
|
73
|
+
try:
|
|
74
|
+
from core.vector_store import run_semantic_search, get_vector_index_stats
|
|
75
|
+
# Vector count
|
|
76
|
+
stats = get_vector_index_stats()
|
|
77
|
+
latencies["Vector Count"] = f"{stats.get('vectors', 0):,}"
|
|
78
|
+
|
|
79
|
+
# Semantic Query
|
|
80
|
+
start = time.perf_counter()
|
|
81
|
+
run_semantic_search("python", limit=5)
|
|
82
|
+
duration = time.perf_counter() - start
|
|
83
|
+
latencies["Semantic Search"] = f"{duration*1000:.2f} ms"
|
|
84
|
+
except Exception as e:
|
|
85
|
+
latencies["Semantic Search"] = f"Error: {e}"
|
|
86
|
+
else:
|
|
87
|
+
latencies["Semantic Search"] = "Offline (Qdrant down)"
|
|
88
|
+
|
|
89
|
+
# 5. Hybrid Search
|
|
90
|
+
if qdrant_ok:
|
|
91
|
+
try:
|
|
92
|
+
from core.vector_store import hybrid_search
|
|
93
|
+
start = time.perf_counter()
|
|
94
|
+
hybrid_search("python")
|
|
95
|
+
duration = time.perf_counter() - start
|
|
96
|
+
latencies["Hybrid Search"] = f"{duration*1000:.2f} ms"
|
|
97
|
+
except Exception as e:
|
|
98
|
+
latencies["Hybrid Search"] = f"Error: {e}"
|
|
99
|
+
else:
|
|
100
|
+
latencies["Hybrid Search"] = "Offline (Qdrant down)"
|
|
101
|
+
|
|
102
|
+
# 6. Graph Lookup
|
|
103
|
+
try:
|
|
104
|
+
from storage.graph import GraphStore
|
|
105
|
+
graph = GraphStore()
|
|
106
|
+
|
|
107
|
+
# Get arbitrary repo to query
|
|
108
|
+
from storage.db import get_connection
|
|
109
|
+
conn = get_connection()
|
|
110
|
+
cursor = conn.cursor()
|
|
111
|
+
cursor.execute("SELECT repo_name FROM repositories LIMIT 1")
|
|
112
|
+
row = cursor.fetchone()
|
|
113
|
+
conn.close()
|
|
114
|
+
|
|
115
|
+
repo_to_query = row[0] if row else "unknown-repo"
|
|
116
|
+
|
|
117
|
+
start = time.perf_counter()
|
|
118
|
+
graph.get_node_relationships("Repository", repo_to_query)
|
|
119
|
+
duration = time.perf_counter() - start
|
|
120
|
+
latencies["Graph Lookup"] = f"{duration*1000:.2f} ms"
|
|
121
|
+
except Exception as e:
|
|
122
|
+
latencies["Graph Lookup"] = f"Error: {e}"
|
|
123
|
+
|
|
124
|
+
# 7. LLM time & RAG Pipeline
|
|
125
|
+
groq_ok, _ = check_groq_api()
|
|
126
|
+
if groq_ok:
|
|
127
|
+
try:
|
|
128
|
+
from core.llm import run_hybrid_rag
|
|
129
|
+
start = time.perf_counter()
|
|
130
|
+
res = run_hybrid_rag("List repositories using Python")
|
|
131
|
+
duration = time.perf_counter() - start
|
|
132
|
+
latencies["Average RAG Pipeline"] = f"{duration:.2f} s"
|
|
133
|
+
|
|
134
|
+
# Estimate LLM time
|
|
135
|
+
# Assuming LLM call took most of RAG duration (minus search overhead)
|
|
136
|
+
latencies["LLM Time"] = f"{duration * 0.85:.2f} s"
|
|
137
|
+
except Exception as e:
|
|
138
|
+
latencies["Average RAG Pipeline"] = f"Error: {e}"
|
|
139
|
+
latencies["LLM Time"] = "Error"
|
|
140
|
+
else:
|
|
141
|
+
latencies["Average RAG Pipeline"] = "Offline (Groq key missing)"
|
|
142
|
+
latencies["LLM Time"] = "Offline"
|
|
143
|
+
|
|
144
|
+
# Display results
|
|
145
|
+
print("──────────────────────────────────────────────────")
|
|
146
|
+
print(" Benchmark Metrics")
|
|
147
|
+
print("──────────────────────────────────────────────────")
|
|
148
|
+
for name, score in latencies.items():
|
|
149
|
+
padding = " " * (25 - len(name))
|
|
150
|
+
print(f" {name}{padding}: {score}")
|
|
151
|
+
print("──────────────────────────────────────────────────")
|