fragmented-memory 1.0.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.
- fragmented_memory-1.0.0/LICENSE +21 -0
- fragmented_memory-1.0.0/PKG-INFO +247 -0
- fragmented_memory-1.0.0/README.md +224 -0
- fragmented_memory-1.0.0/pyproject.toml +34 -0
- fragmented_memory-1.0.0/setup.cfg +4 -0
- fragmented_memory-1.0.0/src/fragmented_memory/__init__.py +495 -0
- fragmented_memory-1.0.0/src/fragmented_memory/attention.py +146 -0
- fragmented_memory-1.0.0/src/fragmented_memory/consolidator.py +384 -0
- fragmented_memory-1.0.0/src/fragmented_memory/embedder.py +155 -0
- fragmented_memory-1.0.0/src/fragmented_memory/emotion.py +136 -0
- fragmented_memory-1.0.0/src/fragmented_memory/forgetter.py +229 -0
- fragmented_memory-1.0.0/src/fragmented_memory/splitter.py +304 -0
- fragmented_memory-1.0.0/src/fragmented_memory/storage.py +890 -0
- fragmented_memory-1.0.0/src/fragmented_memory.egg-info/PKG-INFO +247 -0
- fragmented_memory-1.0.0/src/fragmented_memory.egg-info/SOURCES.txt +16 -0
- fragmented_memory-1.0.0/src/fragmented_memory.egg-info/dependency_links.txt +1 -0
- fragmented_memory-1.0.0/src/fragmented_memory.egg-info/requires.txt +2 -0
- fragmented_memory-1.0.0/src/fragmented_memory.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 j-zly
|
|
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,247 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fragmented-memory
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Fragmented memory system for Hermes Agent — automatically retrieve relevant memory fragments and inject them into conversation context
|
|
5
|
+
Author: j-zly
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: hermes-agent,memory,rag,redisearch,llm
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: redis>=5.0
|
|
21
|
+
Requires-Dist: jieba>=0.42
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
# Fragmented Memory Plugin for Hermes Agent
|
|
25
|
+
|
|
26
|
+
The Fragmented Memory system automatically retrieves relevant memory fragments and injects them into the conversation context for each dialogue.
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
User: "How did we set up that React project structure last time?"
|
|
30
|
+
↓
|
|
31
|
+
Fragmented Memory System ← Redis + RediSearch
|
|
32
|
+
↓
|
|
33
|
+
┌─────────────────────────────────────┐
|
|
34
|
+
│ [1] User prefers TypeScript + Vite │
|
|
35
|
+
│ [2] Previous projects used pinia state management │
|
|
36
|
+
│ [3] Backend suggested using .NET 10 implementation │
|
|
37
|
+
└─────────────────────────────────────┘
|
|
38
|
+
↓
|
|
39
|
+
Model directly uses fragments to answer
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Features
|
|
43
|
+
|
|
44
|
+
- **Semantic Splitting** — auto-split conversations into standalone fragments
|
|
45
|
+
- **BM25 Full-Text Search** — works out of the box with no external API
|
|
46
|
+
- **Optional Vector Search** — KNN via RediSearch (OpenAI / DashScope embedder)
|
|
47
|
+
- **Time Decay** — newer fragments rank higher (60-day half-life configurable)
|
|
48
|
+
- **Sentiment Weighting** — emotional fragments get priority
|
|
49
|
+
- **User Feedback** — mark fragments useful/useless to improve ranking
|
|
50
|
+
- **Hot Topic Boost** — frequently discussed topics rank higher
|
|
51
|
+
- **Auto Sync** — every turn is archived automatically, memory tool writes are synced
|
|
52
|
+
- **Auto Maintenance** — consolidation + selective forgetting to keep storage tidy
|
|
53
|
+
|
|
54
|
+
## Requirements
|
|
55
|
+
|
|
56
|
+
- **Python 3.10+**
|
|
57
|
+
- **Hermes Agent 0.12+** — provides `MemoryProvider` interface
|
|
58
|
+
- **Redis 7+** — with RediSearch module (v2.6+)
|
|
59
|
+
- **jieba** — Chinese tokenization (auto-installed)
|
|
60
|
+
- **Embedding API** (optional) — OpenAI / DashScope / any compatible `/v1/embeddings` service
|
|
61
|
+
|
|
62
|
+
## Installation
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install fragmented-memory
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Or install directly from GitHub:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install git+https://github.com/j-zly/fragmented-memory.git
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Configuration
|
|
75
|
+
|
|
76
|
+
Configuration precedence (high to low): **Environment variables > JSON config file > config.yaml inline > defaults**
|
|
77
|
+
|
|
78
|
+
### 1. Create Redis Index (first-time usage)
|
|
79
|
+
|
|
80
|
+
The code will auto-create (`ensure_index()`), or execute manually:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
redis-cli FT.CREATE idx:memories ON HASH PREFIX 1 "memory:frag:" SCHEMA \
|
|
84
|
+
content TEXT WEIGHT 1 \
|
|
85
|
+
tags TAG SEPARATOR "," \
|
|
86
|
+
category TAG SEPARATOR "," \
|
|
87
|
+
source TEXT WEIGHT 1 \
|
|
88
|
+
created TEXT WEIGHT 0 \
|
|
89
|
+
fragment_type TAG SEPARATOR "," \
|
|
90
|
+
embed_bin VECTOR FLAT 6 TYPE FLOAT32 DIM 1536 DISTANCE_METRIC COSINE
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
> Dimension (DIM) is dynamically adjusted based on the embedding model used, default 1536.
|
|
94
|
+
> For Docker: `docker run -d --name redis-stack -p 6379:6379 redis/redis-stack:latest`
|
|
95
|
+
|
|
96
|
+
### 2. Hermes Configuration
|
|
97
|
+
|
|
98
|
+
Enable in `~/.hermes/config.yaml`:
|
|
99
|
+
|
|
100
|
+
```yaml
|
|
101
|
+
memory:
|
|
102
|
+
provider: fragmented
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Detailed configuration is recommended in a JSON config file (not embedded in config.yaml):
|
|
106
|
+
|
|
107
|
+
`~/.config/fragmented-memory/config.json`:
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"redis_host": "127.0.0.1",
|
|
112
|
+
"redis_port": 6379,
|
|
113
|
+
"top_k": 5,
|
|
114
|
+
"candidate_k": 10,
|
|
115
|
+
"embedder": {
|
|
116
|
+
"provider": "dashscope",
|
|
117
|
+
"api_key": "sk-xxx",
|
|
118
|
+
"model": "text-embedding-v2"
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
If `embedder` is not configured, only BM25 full-text search mode will be used.
|
|
124
|
+
|
|
125
|
+
Also supports environment variable configuration (highest precedence):
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
export FRAGMENTED_REDIS_HOST=127.0.0.1
|
|
129
|
+
export FRAGMENTED_REDIS_PORT=6379
|
|
130
|
+
export FRAGMENTED_TOP_K=5
|
|
131
|
+
export FRAGMENTED_EMBEDDER=dashscope
|
|
132
|
+
export FRAGMENTED_EMBEDDER_MODEL=text-embedding-v2
|
|
133
|
+
export OPENAI_API_KEY=sk-xxx # embedder API key
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### 3. Restart Gateway
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# For CLI mode, restart session is sufficient
|
|
140
|
+
# For Gateway mode, restart the process
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Configuration Reference
|
|
144
|
+
|
|
145
|
+
| Config Item | Environment Variable | Default Value | Description |
|
|
146
|
+
|-------------|---------------------|---------------|-------------|
|
|
147
|
+
| `redis_host` | `FRAGMENTED_REDIS_HOST` | `127.0.0.1` | Redis address |
|
|
148
|
+
| `redis_port` | `FRAGMENTED_REDIS_PORT` | `6379` | Redis port |
|
|
149
|
+
| `top_k` | `FRAGMENTED_TOP_K` | `5` | Number of final fragments returned |
|
|
150
|
+
| `candidate_k` | `FRAGMENTED_CANDIDATE_K` | `10` | Candidate fragments count (for KNN) |
|
|
151
|
+
| `tag_filter` | `FRAGMENTED_TAG_FILTER` | `""` | Tag filtering (comma-separated) |
|
|
152
|
+
| `bm25_limit` | `FRAGMENTED_BM25_LIMIT` | `10` | BM25 search candidate count |
|
|
153
|
+
| `decay_half_days` | `FRAGMENTED_DECAY_HALF_DAYS` | `60` | Time decay half-life (days) |
|
|
154
|
+
| `embed_cache_ttl` | `FRAGMENTED_EMBED_CACHE_TTL` | `3600` | Embedding cache TTL (seconds) |
|
|
155
|
+
| `sentiment_boost_positive` | — | `1.5` | Positive fragment weight multiplier |
|
|
156
|
+
| `sentiment_boost_negative` | — | `1.3` | Negative fragment weight multiplier |
|
|
157
|
+
| `feedback_positive_boost` | — | `1.3` | Positive feedback bonus weight |
|
|
158
|
+
| `feedback_negative_penalty` | — | `0.5` | Negative feedback penalty coefficient |
|
|
159
|
+
| `hot_topic_boost` | — | `1.2` | Hot topic weighting multiplier |
|
|
160
|
+
| `embedder.provider` | `FRAGMENTED_EMBEDDER` | `openai` | `openai` / `dashscope` |
|
|
161
|
+
| `embedder.api_key` | `OPENAI_API_KEY` | — | Embedding API key |
|
|
162
|
+
| `embedder.base_url` | `FRAGMENTED_EMBEDDER_URL` | `https://api.openai.com/v1` | API endpoint |
|
|
163
|
+
| `embedder.model` | `FRAGMENTED_EMBEDDER_MODEL` | `text-embedding-3-small` | Embedding model name |
|
|
164
|
+
| `consolidate_min_group` | — | `2` | Minimum fragments to trigger consolidation |
|
|
165
|
+
| `consolidate_max_age_hours` | — | `72` | Minimum age (hours) before fragments can be consolidated |
|
|
166
|
+
| `forget_max_age_days` | — | `30` | Number of days before fragments might be forgotten |
|
|
167
|
+
| `forget_dry_run` | — | `true` | Safe mode for forgetting: only count, don't delete |
|
|
168
|
+
| `hot_topic_decay_half_days` | — | `30` | Hot topic time decay half-life (days) |
|
|
169
|
+
| `emotion_intensity_factor` | — | `0.4` | Emotion intensity → weight coefficient (0=disabled, 1=max) |
|
|
170
|
+
| `attention_boost_max` | — | `1.5` | Maximum attention weighting value |
|
|
171
|
+
| `attention_base_increment` | — | `2.0` | Base attention increment per mention |
|
|
172
|
+
| `attention_emotion_factor` | — | `1.5` | Emotion intensity amplification factor for attention |
|
|
173
|
+
|
|
174
|
+
> `sentiment_*`, `feedback_*`, `hot_topic_*` and other ranking weight parameters currently only support configuration through JSON config file, not environment variables. Set to `1.0` to disable the effect of that dimension.
|
|
175
|
+
|
|
176
|
+
### Embedding Models and Dimensions
|
|
177
|
+
|
|
178
|
+
| Model | Dimensions |
|
|
179
|
+
|-------|------------|
|
|
180
|
+
| OpenAI text-embedding-3-small | 1536 |
|
|
181
|
+
| OpenAI text-embedding-3-large | 3072 |
|
|
182
|
+
| OpenAI text-embedding-ada-002 | 1536 |
|
|
183
|
+
| DashScope text-embedding-v2 | 1536 |
|
|
184
|
+
| DashScope text-embedding-v3 | 1024 |
|
|
185
|
+
|
|
186
|
+
Dimensions are automatically detected, switching models doesn't require reconfiguration.
|
|
187
|
+
|
|
188
|
+
### Synonym Table
|
|
189
|
+
|
|
190
|
+
Stored in Redis Hash `fragmented:synonyms`, expanded at search time to improve recall:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
redis-cli HSET fragmented:synonyms setup '["install","configure","deploy","setup"]'
|
|
194
|
+
redis-cli HSET fragmented:synonyms fix '["fix","modify","correct","repair","solve"]'
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Verification
|
|
198
|
+
|
|
199
|
+
Check logs after startup:
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
Memory provider 'fragmented' registered (0 tools)
|
|
203
|
+
fragmented: connected (session=xxx, top_k=5, tag_filter=(none))
|
|
204
|
+
fragmented: BM25-only mode (no embedder configured)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Architecture
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
┌────────────────────────────────────────────────────────┐
|
|
211
|
+
│ User sends message │
|
|
212
|
+
└──────────────────┬─────────────────────────────────────┘
|
|
213
|
+
│
|
|
214
|
+
┌─────────▼─────────┐
|
|
215
|
+
│ prefetch() │ ← Automatically triggered
|
|
216
|
+
│ ↓ │
|
|
217
|
+
│ BM25 Full-Text Search │ ← Default, zero cost
|
|
218
|
+
│ (KNN Vector search) │ ← Optional (needs embedder)
|
|
219
|
+
│ ↓ │
|
|
220
|
+
│ Six-dimensional Re-ranking │ ← Similarity × Time decay
|
|
221
|
+
│ │ × Emotion × Feedback × Hot Topic × Attention
|
|
222
|
+
│ ↓ │
|
|
223
|
+
│ Top N Injected into Context │
|
|
224
|
+
└─────────┬─────────┘
|
|
225
|
+
│
|
|
226
|
+
┌─────────▼─────────┐
|
|
227
|
+
│ Model Response │ ← Fragments can be used as reference
|
|
228
|
+
└───────────────────┘
|
|
229
|
+
│
|
|
230
|
+
┌─────────▼─────────┐
|
|
231
|
+
│ sync_turn() │ ← Automatically archive at end of conversation
|
|
232
|
+
│ Smart Sentence Splitting │ ← Protect abbreviations/numbers/quotes
|
|
233
|
+
│ Attention Tracking │ ← Extract keywords and increase attention score
|
|
234
|
+
│ ↓ │
|
|
235
|
+
│ Stored in Redis │ ← Available for next retrieval
|
|
236
|
+
└───────────────────┘
|
|
237
|
+
│
|
|
238
|
+
┌─────────▼─────────┐
|
|
239
|
+
│ [cron] Every 2h │ ← Background maintenance
|
|
240
|
+
│ ① Multi-level Consolidation │ ← Same topic→LLM summarization→level+1
|
|
241
|
+
│ ② Selective Forgetting │ ← Cleanup low-value fragments
|
|
242
|
+
└───────────────────┘
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## License
|
|
246
|
+
|
|
247
|
+
MIT
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Fragmented Memory Plugin for Hermes Agent
|
|
2
|
+
|
|
3
|
+
The Fragmented Memory system automatically retrieves relevant memory fragments and injects them into the conversation context for each dialogue.
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
User: "How did we set up that React project structure last time?"
|
|
7
|
+
↓
|
|
8
|
+
Fragmented Memory System ← Redis + RediSearch
|
|
9
|
+
↓
|
|
10
|
+
┌─────────────────────────────────────┐
|
|
11
|
+
│ [1] User prefers TypeScript + Vite │
|
|
12
|
+
│ [2] Previous projects used pinia state management │
|
|
13
|
+
│ [3] Backend suggested using .NET 10 implementation │
|
|
14
|
+
└─────────────────────────────────────┘
|
|
15
|
+
↓
|
|
16
|
+
Model directly uses fragments to answer
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
- **Semantic Splitting** — auto-split conversations into standalone fragments
|
|
22
|
+
- **BM25 Full-Text Search** — works out of the box with no external API
|
|
23
|
+
- **Optional Vector Search** — KNN via RediSearch (OpenAI / DashScope embedder)
|
|
24
|
+
- **Time Decay** — newer fragments rank higher (60-day half-life configurable)
|
|
25
|
+
- **Sentiment Weighting** — emotional fragments get priority
|
|
26
|
+
- **User Feedback** — mark fragments useful/useless to improve ranking
|
|
27
|
+
- **Hot Topic Boost** — frequently discussed topics rank higher
|
|
28
|
+
- **Auto Sync** — every turn is archived automatically, memory tool writes are synced
|
|
29
|
+
- **Auto Maintenance** — consolidation + selective forgetting to keep storage tidy
|
|
30
|
+
|
|
31
|
+
## Requirements
|
|
32
|
+
|
|
33
|
+
- **Python 3.10+**
|
|
34
|
+
- **Hermes Agent 0.12+** — provides `MemoryProvider` interface
|
|
35
|
+
- **Redis 7+** — with RediSearch module (v2.6+)
|
|
36
|
+
- **jieba** — Chinese tokenization (auto-installed)
|
|
37
|
+
- **Embedding API** (optional) — OpenAI / DashScope / any compatible `/v1/embeddings` service
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install fragmented-memory
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Or install directly from GitHub:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install git+https://github.com/j-zly/fragmented-memory.git
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Configuration
|
|
52
|
+
|
|
53
|
+
Configuration precedence (high to low): **Environment variables > JSON config file > config.yaml inline > defaults**
|
|
54
|
+
|
|
55
|
+
### 1. Create Redis Index (first-time usage)
|
|
56
|
+
|
|
57
|
+
The code will auto-create (`ensure_index()`), or execute manually:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
redis-cli FT.CREATE idx:memories ON HASH PREFIX 1 "memory:frag:" SCHEMA \
|
|
61
|
+
content TEXT WEIGHT 1 \
|
|
62
|
+
tags TAG SEPARATOR "," \
|
|
63
|
+
category TAG SEPARATOR "," \
|
|
64
|
+
source TEXT WEIGHT 1 \
|
|
65
|
+
created TEXT WEIGHT 0 \
|
|
66
|
+
fragment_type TAG SEPARATOR "," \
|
|
67
|
+
embed_bin VECTOR FLAT 6 TYPE FLOAT32 DIM 1536 DISTANCE_METRIC COSINE
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
> Dimension (DIM) is dynamically adjusted based on the embedding model used, default 1536.
|
|
71
|
+
> For Docker: `docker run -d --name redis-stack -p 6379:6379 redis/redis-stack:latest`
|
|
72
|
+
|
|
73
|
+
### 2. Hermes Configuration
|
|
74
|
+
|
|
75
|
+
Enable in `~/.hermes/config.yaml`:
|
|
76
|
+
|
|
77
|
+
```yaml
|
|
78
|
+
memory:
|
|
79
|
+
provider: fragmented
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Detailed configuration is recommended in a JSON config file (not embedded in config.yaml):
|
|
83
|
+
|
|
84
|
+
`~/.config/fragmented-memory/config.json`:
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"redis_host": "127.0.0.1",
|
|
89
|
+
"redis_port": 6379,
|
|
90
|
+
"top_k": 5,
|
|
91
|
+
"candidate_k": 10,
|
|
92
|
+
"embedder": {
|
|
93
|
+
"provider": "dashscope",
|
|
94
|
+
"api_key": "sk-xxx",
|
|
95
|
+
"model": "text-embedding-v2"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
If `embedder` is not configured, only BM25 full-text search mode will be used.
|
|
101
|
+
|
|
102
|
+
Also supports environment variable configuration (highest precedence):
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
export FRAGMENTED_REDIS_HOST=127.0.0.1
|
|
106
|
+
export FRAGMENTED_REDIS_PORT=6379
|
|
107
|
+
export FRAGMENTED_TOP_K=5
|
|
108
|
+
export FRAGMENTED_EMBEDDER=dashscope
|
|
109
|
+
export FRAGMENTED_EMBEDDER_MODEL=text-embedding-v2
|
|
110
|
+
export OPENAI_API_KEY=sk-xxx # embedder API key
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 3. Restart Gateway
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# For CLI mode, restart session is sufficient
|
|
117
|
+
# For Gateway mode, restart the process
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Configuration Reference
|
|
121
|
+
|
|
122
|
+
| Config Item | Environment Variable | Default Value | Description |
|
|
123
|
+
|-------------|---------------------|---------------|-------------|
|
|
124
|
+
| `redis_host` | `FRAGMENTED_REDIS_HOST` | `127.0.0.1` | Redis address |
|
|
125
|
+
| `redis_port` | `FRAGMENTED_REDIS_PORT` | `6379` | Redis port |
|
|
126
|
+
| `top_k` | `FRAGMENTED_TOP_K` | `5` | Number of final fragments returned |
|
|
127
|
+
| `candidate_k` | `FRAGMENTED_CANDIDATE_K` | `10` | Candidate fragments count (for KNN) |
|
|
128
|
+
| `tag_filter` | `FRAGMENTED_TAG_FILTER` | `""` | Tag filtering (comma-separated) |
|
|
129
|
+
| `bm25_limit` | `FRAGMENTED_BM25_LIMIT` | `10` | BM25 search candidate count |
|
|
130
|
+
| `decay_half_days` | `FRAGMENTED_DECAY_HALF_DAYS` | `60` | Time decay half-life (days) |
|
|
131
|
+
| `embed_cache_ttl` | `FRAGMENTED_EMBED_CACHE_TTL` | `3600` | Embedding cache TTL (seconds) |
|
|
132
|
+
| `sentiment_boost_positive` | — | `1.5` | Positive fragment weight multiplier |
|
|
133
|
+
| `sentiment_boost_negative` | — | `1.3` | Negative fragment weight multiplier |
|
|
134
|
+
| `feedback_positive_boost` | — | `1.3` | Positive feedback bonus weight |
|
|
135
|
+
| `feedback_negative_penalty` | — | `0.5` | Negative feedback penalty coefficient |
|
|
136
|
+
| `hot_topic_boost` | — | `1.2` | Hot topic weighting multiplier |
|
|
137
|
+
| `embedder.provider` | `FRAGMENTED_EMBEDDER` | `openai` | `openai` / `dashscope` |
|
|
138
|
+
| `embedder.api_key` | `OPENAI_API_KEY` | — | Embedding API key |
|
|
139
|
+
| `embedder.base_url` | `FRAGMENTED_EMBEDDER_URL` | `https://api.openai.com/v1` | API endpoint |
|
|
140
|
+
| `embedder.model` | `FRAGMENTED_EMBEDDER_MODEL` | `text-embedding-3-small` | Embedding model name |
|
|
141
|
+
| `consolidate_min_group` | — | `2` | Minimum fragments to trigger consolidation |
|
|
142
|
+
| `consolidate_max_age_hours` | — | `72` | Minimum age (hours) before fragments can be consolidated |
|
|
143
|
+
| `forget_max_age_days` | — | `30` | Number of days before fragments might be forgotten |
|
|
144
|
+
| `forget_dry_run` | — | `true` | Safe mode for forgetting: only count, don't delete |
|
|
145
|
+
| `hot_topic_decay_half_days` | — | `30` | Hot topic time decay half-life (days) |
|
|
146
|
+
| `emotion_intensity_factor` | — | `0.4` | Emotion intensity → weight coefficient (0=disabled, 1=max) |
|
|
147
|
+
| `attention_boost_max` | — | `1.5` | Maximum attention weighting value |
|
|
148
|
+
| `attention_base_increment` | — | `2.0` | Base attention increment per mention |
|
|
149
|
+
| `attention_emotion_factor` | — | `1.5` | Emotion intensity amplification factor for attention |
|
|
150
|
+
|
|
151
|
+
> `sentiment_*`, `feedback_*`, `hot_topic_*` and other ranking weight parameters currently only support configuration through JSON config file, not environment variables. Set to `1.0` to disable the effect of that dimension.
|
|
152
|
+
|
|
153
|
+
### Embedding Models and Dimensions
|
|
154
|
+
|
|
155
|
+
| Model | Dimensions |
|
|
156
|
+
|-------|------------|
|
|
157
|
+
| OpenAI text-embedding-3-small | 1536 |
|
|
158
|
+
| OpenAI text-embedding-3-large | 3072 |
|
|
159
|
+
| OpenAI text-embedding-ada-002 | 1536 |
|
|
160
|
+
| DashScope text-embedding-v2 | 1536 |
|
|
161
|
+
| DashScope text-embedding-v3 | 1024 |
|
|
162
|
+
|
|
163
|
+
Dimensions are automatically detected, switching models doesn't require reconfiguration.
|
|
164
|
+
|
|
165
|
+
### Synonym Table
|
|
166
|
+
|
|
167
|
+
Stored in Redis Hash `fragmented:synonyms`, expanded at search time to improve recall:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
redis-cli HSET fragmented:synonyms setup '["install","configure","deploy","setup"]'
|
|
171
|
+
redis-cli HSET fragmented:synonyms fix '["fix","modify","correct","repair","solve"]'
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Verification
|
|
175
|
+
|
|
176
|
+
Check logs after startup:
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
Memory provider 'fragmented' registered (0 tools)
|
|
180
|
+
fragmented: connected (session=xxx, top_k=5, tag_filter=(none))
|
|
181
|
+
fragmented: BM25-only mode (no embedder configured)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Architecture
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
┌────────────────────────────────────────────────────────┐
|
|
188
|
+
│ User sends message │
|
|
189
|
+
└──────────────────┬─────────────────────────────────────┘
|
|
190
|
+
│
|
|
191
|
+
┌─────────▼─────────┐
|
|
192
|
+
│ prefetch() │ ← Automatically triggered
|
|
193
|
+
│ ↓ │
|
|
194
|
+
│ BM25 Full-Text Search │ ← Default, zero cost
|
|
195
|
+
│ (KNN Vector search) │ ← Optional (needs embedder)
|
|
196
|
+
│ ↓ │
|
|
197
|
+
│ Six-dimensional Re-ranking │ ← Similarity × Time decay
|
|
198
|
+
│ │ × Emotion × Feedback × Hot Topic × Attention
|
|
199
|
+
│ ↓ │
|
|
200
|
+
│ Top N Injected into Context │
|
|
201
|
+
└─────────┬─────────┘
|
|
202
|
+
│
|
|
203
|
+
┌─────────▼─────────┐
|
|
204
|
+
│ Model Response │ ← Fragments can be used as reference
|
|
205
|
+
└───────────────────┘
|
|
206
|
+
│
|
|
207
|
+
┌─────────▼─────────┐
|
|
208
|
+
│ sync_turn() │ ← Automatically archive at end of conversation
|
|
209
|
+
│ Smart Sentence Splitting │ ← Protect abbreviations/numbers/quotes
|
|
210
|
+
│ Attention Tracking │ ← Extract keywords and increase attention score
|
|
211
|
+
│ ↓ │
|
|
212
|
+
│ Stored in Redis │ ← Available for next retrieval
|
|
213
|
+
└───────────────────┘
|
|
214
|
+
│
|
|
215
|
+
┌─────────▼─────────┐
|
|
216
|
+
│ [cron] Every 2h │ ← Background maintenance
|
|
217
|
+
│ ① Multi-level Consolidation │ ← Same topic→LLM summarization→level+1
|
|
218
|
+
│ ② Selective Forgetting │ ← Cleanup low-value fragments
|
|
219
|
+
└───────────────────┘
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## License
|
|
223
|
+
|
|
224
|
+
MIT
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "fragmented-memory"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Fragmented memory system for Hermes Agent — automatically retrieve relevant memory fragments and inject them into conversation context"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "j-zly"},
|
|
14
|
+
]
|
|
15
|
+
keywords = ["hermes-agent", "memory", "rag", "redisearch", "llm"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
dependencies = [
|
|
29
|
+
"redis>=5.0",
|
|
30
|
+
"jieba>=0.42",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[tool.setuptools.packages.find]
|
|
34
|
+
where = ["src"]
|