knowledge-rag 3.3.2__tar.gz → 3.4.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.
- {knowledge_rag-3.3.2 → knowledge_rag-3.4.0}/.gitignore +1 -0
- {knowledge_rag-3.3.2 → knowledge_rag-3.4.0}/PKG-INFO +54 -5
- {knowledge_rag-3.3.2 → knowledge_rag-3.4.0}/README.md +53 -4
- {knowledge_rag-3.3.2 → knowledge_rag-3.4.0}/config.example.yaml +24 -0
- {knowledge_rag-3.3.2 → knowledge_rag-3.4.0}/mcp_server/__init__.py +1 -1
- {knowledge_rag-3.3.2 → knowledge_rag-3.4.0}/mcp_server/config.py +19 -3
- {knowledge_rag-3.3.2 → knowledge_rag-3.4.0}/mcp_server/ingestion.py +93 -1
- {knowledge_rag-3.3.2 → knowledge_rag-3.4.0}/mcp_server/server.py +18 -9
- {knowledge_rag-3.3.2 → knowledge_rag-3.4.0}/presets/cybersecurity.yaml +4 -0
- {knowledge_rag-3.3.2 → knowledge_rag-3.4.0}/presets/developer.yaml +11 -0
- {knowledge_rag-3.3.2 → knowledge_rag-3.4.0}/presets/general.yaml +3 -0
- {knowledge_rag-3.3.2 → knowledge_rag-3.4.0}/presets/research.yaml +4 -0
- {knowledge_rag-3.3.2 → knowledge_rag-3.4.0}/pyproject.toml +1 -1
- {knowledge_rag-3.3.2 → knowledge_rag-3.4.0}/LICENSE +0 -0
- {knowledge_rag-3.3.2 → knowledge_rag-3.4.0}/documents/examples/sample-document.md +0 -0
- {knowledge_rag-3.3.2 → knowledge_rag-3.4.0}/requirements.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: knowledge-rag
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.4.0
|
|
4
4
|
Summary: Local RAG System for Claude Code — Hybrid search + Cross-encoder Reranking + 12 MCP Tools. Zero external servers.
|
|
5
5
|
Project-URL: Homepage, https://github.com/lyonzin/knowledge-rag
|
|
6
6
|
Project-URL: Repository, https://github.com/lyonzin/knowledge-rag
|
|
@@ -38,7 +38,7 @@ Description-Content-Type: text/markdown
|
|
|
38
38
|
|
|
39
39
|
<div align="center">
|
|
40
40
|
|
|
41
|
-

|
|
42
42
|

|
|
43
43
|

|
|
44
44
|

|
|
@@ -61,7 +61,7 @@ Your documents become instantly searchable inside Claude Code — with reranking
|
|
|
61
61
|
|
|
62
62
|
**12 MCP Tools** | **Hybrid Search + Cross-Encoder Reranking** | **Markdown-Aware Chunking** | **100% Local, Zero Cloud**
|
|
63
63
|
|
|
64
|
-
[What's New](#whats-new-in-
|
|
64
|
+
[What's New](#whats-new-in-v340) | [Installation](#installation) | [Configuration](#configuration) | [API Reference](#api-reference) | [Architecture](#architecture)
|
|
65
65
|
|
|
66
66
|
</div>
|
|
67
67
|
|
|
@@ -108,6 +108,40 @@ After the initial rebuild, startup and queries are faster than v2.x because ther
|
|
|
108
108
|
|
|
109
109
|
---
|
|
110
110
|
|
|
111
|
+
## What's New in v3.4.0
|
|
112
|
+
|
|
113
|
+
### Persistent Model Cache
|
|
114
|
+
Embedding models (~250MB) are now stored in `models_cache/` instead of `/tmp`. No more re-downloading after system reboots on Linux. Configurable via `paths.models_cache_dir` in config.yaml.
|
|
115
|
+
|
|
116
|
+
### Exclude Patterns
|
|
117
|
+
Skip files and directories during indexing with glob patterns. Configure under `documents.exclude_patterns` in config.yaml:
|
|
118
|
+
```yaml
|
|
119
|
+
documents:
|
|
120
|
+
exclude_patterns:
|
|
121
|
+
- "node_modules"
|
|
122
|
+
- ".venv"
|
|
123
|
+
- "__pycache__"
|
|
124
|
+
- ".git"
|
|
125
|
+
- "*.tmp"
|
|
126
|
+
```
|
|
127
|
+
Patterns match against both full relative paths and individual path components — `"node_modules"` excludes it at any depth.
|
|
128
|
+
|
|
129
|
+
### Jupyter Notebook Support (.ipynb)
|
|
130
|
+
Native parser extracts only markdown and code cell sources — no outputs, no execution counts, no base64-encoded images. Clean content for high-quality retrieval. Added to default supported formats.
|
|
131
|
+
|
|
132
|
+
### MCP Protocol Stability
|
|
133
|
+
`stdout` is redirected to `stderr` before the MCP server starts. Prevents random library `print()` calls from corrupting the JSON-RPC stream — fixes "Failed to connect" errors in VS Code and IDE integrations.
|
|
134
|
+
|
|
135
|
+
### File Watcher Resilience (Linux)
|
|
136
|
+
Server no longer crashes when system inotify limits are reached. Falls back gracefully to manual indexing with a clear warning message.
|
|
137
|
+
|
|
138
|
+
### MetaTrader Support (.mq4, .mqh)
|
|
139
|
+
MQL4/MQL5 source files can now be indexed as code. Not enabled by default — add `.mq4` and `.mqh` to your `supported_formats` list to activate.
|
|
140
|
+
|
|
141
|
+
*Community credit: Features inspired by ideas from [@Hohlas](https://github.com/Hohlas) in [PR #18](https://github.com/lyonzin/knowledge-rag/pull/18).*
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
111
145
|
## What's New in v3.3.0
|
|
112
146
|
|
|
113
147
|
### YAML Configuration System
|
|
@@ -966,6 +1000,7 @@ Pre-built configurations for common use cases. Each preset is a complete `config
|
|
|
966
1000
|
|-------|---------|-------------|
|
|
967
1001
|
| `paths.documents_dir` | `./documents` | Root folder scanned recursively for documents |
|
|
968
1002
|
| `paths.data_dir` | `./data` | Internal storage for ChromaDB and index metadata |
|
|
1003
|
+
| `paths.models_cache_dir` | `./models_cache` | Persistent cache for embedding models (~250MB). Prevents re-download after reboots |
|
|
969
1004
|
|
|
970
1005
|
Relative paths resolve from the project root. Absolute paths work too. The `KNOWLEDGE_RAG_DIR` environment variable overrides the project root.
|
|
971
1006
|
|
|
@@ -973,7 +1008,8 @@ Relative paths resolve from the project root. Absolute paths work too. The `KNOW
|
|
|
973
1008
|
|
|
974
1009
|
| Field | Default | Description |
|
|
975
1010
|
|-------|---------|-------------|
|
|
976
|
-
| `documents.supported_formats` | .md .txt .pdf .py .json .docx .xlsx .pptx .csv | File extensions to index |
|
|
1011
|
+
| `documents.supported_formats` | .md .txt .pdf .py .json .docx .xlsx .pptx .csv .ipynb | File extensions to index |
|
|
1012
|
+
| `documents.exclude_patterns` | `[]` (empty) | Glob patterns for files/dirs to skip during indexing |
|
|
977
1013
|
| `documents.chunking.chunk_size` | 1000 | Max characters per chunk |
|
|
978
1014
|
| `documents.chunking.chunk_overlap` | 200 | Characters shared between consecutive chunks |
|
|
979
1015
|
|
|
@@ -1090,7 +1126,8 @@ knowledge-rag/
|
|
|
1090
1126
|
├── data/
|
|
1091
1127
|
│ ├── chroma_db/ # ChromaDB vector database
|
|
1092
1128
|
│ └── index_metadata.json # Incremental indexing state
|
|
1093
|
-
├──
|
|
1129
|
+
├── models_cache/ # Persistent embedding model cache
|
|
1130
|
+
├── tests/ # Test suite (70+ tests)
|
|
1094
1131
|
├── venv/ # Python virtual environment
|
|
1095
1132
|
├── requirements.txt # Python dependencies
|
|
1096
1133
|
├── LICENSE # MIT License
|
|
@@ -1195,6 +1232,18 @@ With ~200 documents, expect ~300-500MB RAM. The embedding model (~50MB) and rera
|
|
|
1195
1232
|
|
|
1196
1233
|
## Changelog
|
|
1197
1234
|
|
|
1235
|
+
### v3.4.0 (2026-04-16)
|
|
1236
|
+
|
|
1237
|
+
- **NEW**: `models_cache_dir` — persistent embedding model cache, prevents re-download after reboots
|
|
1238
|
+
- **NEW**: `exclude_patterns` — glob-based file/directory exclusion during indexing (under `documents:` section)
|
|
1239
|
+
- **NEW**: Jupyter Notebook (.ipynb) parser — extracts markdown and code cell sources only, ignores outputs and base64
|
|
1240
|
+
- **NEW**: MCP stdout protection — redirects stdout to stderr before server start, fixes "Failed to connect" errors
|
|
1241
|
+
- **NEW**: File watcher resilience — graceful fallback when Linux inotify limits are reached
|
|
1242
|
+
- **NEW**: MetaTrader (.mq4, .mqh) support — opt-in code parsing for MQL4/MQL5 files
|
|
1243
|
+
- **NEW**: 23 new tests (exclude patterns, ipynb parser, stdout protection)
|
|
1244
|
+
- **IMPROVED**: All 4 presets updated with new config fields
|
|
1245
|
+
- Community credit: [@Hohlas](https://github.com/Hohlas) ([PR #18](https://github.com/lyonzin/knowledge-rag/pull/18))
|
|
1246
|
+
|
|
1198
1247
|
### v3.3.2 (2026-04-06)
|
|
1199
1248
|
|
|
1200
1249
|
- **FIX**: Full type validation on all YAML config values — wrong types warn and fall back to defaults
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
4
|
|
|
5
|
-

|
|
6
6
|

|
|
7
7
|

|
|
8
8
|

|
|
@@ -25,7 +25,7 @@ Your documents become instantly searchable inside Claude Code — with reranking
|
|
|
25
25
|
|
|
26
26
|
**12 MCP Tools** | **Hybrid Search + Cross-Encoder Reranking** | **Markdown-Aware Chunking** | **100% Local, Zero Cloud**
|
|
27
27
|
|
|
28
|
-
[What's New](#whats-new-in-
|
|
28
|
+
[What's New](#whats-new-in-v340) | [Installation](#installation) | [Configuration](#configuration) | [API Reference](#api-reference) | [Architecture](#architecture)
|
|
29
29
|
|
|
30
30
|
</div>
|
|
31
31
|
|
|
@@ -72,6 +72,40 @@ After the initial rebuild, startup and queries are faster than v2.x because ther
|
|
|
72
72
|
|
|
73
73
|
---
|
|
74
74
|
|
|
75
|
+
## What's New in v3.4.0
|
|
76
|
+
|
|
77
|
+
### Persistent Model Cache
|
|
78
|
+
Embedding models (~250MB) are now stored in `models_cache/` instead of `/tmp`. No more re-downloading after system reboots on Linux. Configurable via `paths.models_cache_dir` in config.yaml.
|
|
79
|
+
|
|
80
|
+
### Exclude Patterns
|
|
81
|
+
Skip files and directories during indexing with glob patterns. Configure under `documents.exclude_patterns` in config.yaml:
|
|
82
|
+
```yaml
|
|
83
|
+
documents:
|
|
84
|
+
exclude_patterns:
|
|
85
|
+
- "node_modules"
|
|
86
|
+
- ".venv"
|
|
87
|
+
- "__pycache__"
|
|
88
|
+
- ".git"
|
|
89
|
+
- "*.tmp"
|
|
90
|
+
```
|
|
91
|
+
Patterns match against both full relative paths and individual path components — `"node_modules"` excludes it at any depth.
|
|
92
|
+
|
|
93
|
+
### Jupyter Notebook Support (.ipynb)
|
|
94
|
+
Native parser extracts only markdown and code cell sources — no outputs, no execution counts, no base64-encoded images. Clean content for high-quality retrieval. Added to default supported formats.
|
|
95
|
+
|
|
96
|
+
### MCP Protocol Stability
|
|
97
|
+
`stdout` is redirected to `stderr` before the MCP server starts. Prevents random library `print()` calls from corrupting the JSON-RPC stream — fixes "Failed to connect" errors in VS Code and IDE integrations.
|
|
98
|
+
|
|
99
|
+
### File Watcher Resilience (Linux)
|
|
100
|
+
Server no longer crashes when system inotify limits are reached. Falls back gracefully to manual indexing with a clear warning message.
|
|
101
|
+
|
|
102
|
+
### MetaTrader Support (.mq4, .mqh)
|
|
103
|
+
MQL4/MQL5 source files can now be indexed as code. Not enabled by default — add `.mq4` and `.mqh` to your `supported_formats` list to activate.
|
|
104
|
+
|
|
105
|
+
*Community credit: Features inspired by ideas from [@Hohlas](https://github.com/Hohlas) in [PR #18](https://github.com/lyonzin/knowledge-rag/pull/18).*
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
75
109
|
## What's New in v3.3.0
|
|
76
110
|
|
|
77
111
|
### YAML Configuration System
|
|
@@ -930,6 +964,7 @@ Pre-built configurations for common use cases. Each preset is a complete `config
|
|
|
930
964
|
|-------|---------|-------------|
|
|
931
965
|
| `paths.documents_dir` | `./documents` | Root folder scanned recursively for documents |
|
|
932
966
|
| `paths.data_dir` | `./data` | Internal storage for ChromaDB and index metadata |
|
|
967
|
+
| `paths.models_cache_dir` | `./models_cache` | Persistent cache for embedding models (~250MB). Prevents re-download after reboots |
|
|
933
968
|
|
|
934
969
|
Relative paths resolve from the project root. Absolute paths work too. The `KNOWLEDGE_RAG_DIR` environment variable overrides the project root.
|
|
935
970
|
|
|
@@ -937,7 +972,8 @@ Relative paths resolve from the project root. Absolute paths work too. The `KNOW
|
|
|
937
972
|
|
|
938
973
|
| Field | Default | Description |
|
|
939
974
|
|-------|---------|-------------|
|
|
940
|
-
| `documents.supported_formats` | .md .txt .pdf .py .json .docx .xlsx .pptx .csv | File extensions to index |
|
|
975
|
+
| `documents.supported_formats` | .md .txt .pdf .py .json .docx .xlsx .pptx .csv .ipynb | File extensions to index |
|
|
976
|
+
| `documents.exclude_patterns` | `[]` (empty) | Glob patterns for files/dirs to skip during indexing |
|
|
941
977
|
| `documents.chunking.chunk_size` | 1000 | Max characters per chunk |
|
|
942
978
|
| `documents.chunking.chunk_overlap` | 200 | Characters shared between consecutive chunks |
|
|
943
979
|
|
|
@@ -1054,7 +1090,8 @@ knowledge-rag/
|
|
|
1054
1090
|
├── data/
|
|
1055
1091
|
│ ├── chroma_db/ # ChromaDB vector database
|
|
1056
1092
|
│ └── index_metadata.json # Incremental indexing state
|
|
1057
|
-
├──
|
|
1093
|
+
├── models_cache/ # Persistent embedding model cache
|
|
1094
|
+
├── tests/ # Test suite (70+ tests)
|
|
1058
1095
|
├── venv/ # Python virtual environment
|
|
1059
1096
|
├── requirements.txt # Python dependencies
|
|
1060
1097
|
├── LICENSE # MIT License
|
|
@@ -1159,6 +1196,18 @@ With ~200 documents, expect ~300-500MB RAM. The embedding model (~50MB) and rera
|
|
|
1159
1196
|
|
|
1160
1197
|
## Changelog
|
|
1161
1198
|
|
|
1199
|
+
### v3.4.0 (2026-04-16)
|
|
1200
|
+
|
|
1201
|
+
- **NEW**: `models_cache_dir` — persistent embedding model cache, prevents re-download after reboots
|
|
1202
|
+
- **NEW**: `exclude_patterns` — glob-based file/directory exclusion during indexing (under `documents:` section)
|
|
1203
|
+
- **NEW**: Jupyter Notebook (.ipynb) parser — extracts markdown and code cell sources only, ignores outputs and base64
|
|
1204
|
+
- **NEW**: MCP stdout protection — redirects stdout to stderr before server start, fixes "Failed to connect" errors
|
|
1205
|
+
- **NEW**: File watcher resilience — graceful fallback when Linux inotify limits are reached
|
|
1206
|
+
- **NEW**: MetaTrader (.mq4, .mqh) support — opt-in code parsing for MQL4/MQL5 files
|
|
1207
|
+
- **NEW**: 23 new tests (exclude patterns, ipynb parser, stdout protection)
|
|
1208
|
+
- **IMPROVED**: All 4 presets updated with new config fields
|
|
1209
|
+
- Community credit: [@Hohlas](https://github.com/Hohlas) ([PR #18](https://github.com/lyonzin/knowledge-rag/pull/18))
|
|
1210
|
+
|
|
1162
1211
|
### v3.3.2 (2026-04-06)
|
|
1163
1212
|
|
|
1164
1213
|
- **FIX**: Full type validation on all YAML config values — wrong types warn and fall back to defaults
|
|
@@ -39,6 +39,11 @@ paths:
|
|
|
39
39
|
# You generally don't need to touch this.
|
|
40
40
|
data_dir: "./data"
|
|
41
41
|
|
|
42
|
+
# Persistent cache for embedding models (~250MB).
|
|
43
|
+
# Prevents re-downloading after reboots (especially on Linux where /tmp is cleared).
|
|
44
|
+
# Default: ./models_cache (relative to project root)
|
|
45
|
+
models_cache_dir: "./models_cache"
|
|
46
|
+
|
|
42
47
|
|
|
43
48
|
# ============================================================================
|
|
44
49
|
# DOCUMENTS
|
|
@@ -58,6 +63,25 @@ documents:
|
|
|
58
63
|
# - .csv # CSV data files
|
|
59
64
|
# - .py # Python source code
|
|
60
65
|
# - .json # JSON files
|
|
66
|
+
# - .ipynb # Jupyter Notebooks (extracts markdown + code cells)
|
|
67
|
+
# - .mq4 # MetaTrader MQL4 source (opt-in, add to enable)
|
|
68
|
+
# - .mqh # MetaTrader MQL4/5 headers (opt-in, add to enable)
|
|
69
|
+
|
|
70
|
+
# Exclude patterns — skip files/directories matching these patterns.
|
|
71
|
+
# Uses fnmatch glob syntax. Patterns match against relative paths AND
|
|
72
|
+
# individual path components (so "node_modules" matches at any depth).
|
|
73
|
+
#
|
|
74
|
+
# Examples:
|
|
75
|
+
# exclude_patterns:
|
|
76
|
+
# - "node_modules" # Skip node_modules at any depth
|
|
77
|
+
# - ".git" # Skip .git directories
|
|
78
|
+
# - "__pycache__" # Skip Python cache
|
|
79
|
+
# - ".venv" # Skip virtual environments
|
|
80
|
+
# - "*.tmp" # Skip .tmp files anywhere
|
|
81
|
+
# - "drafts/*" # Skip everything in top-level drafts/
|
|
82
|
+
#
|
|
83
|
+
# Default: [] (nothing excluded — all supported files are indexed)
|
|
84
|
+
exclude_patterns: []
|
|
61
85
|
|
|
62
86
|
# How documents are split into searchable chunks.
|
|
63
87
|
#
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Configuration for Knowledge RAG System v3.
|
|
1
|
+
"""Configuration for Knowledge RAG System v3.4.0 — YAML-configurable"""
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
from dataclasses import dataclass, field
|
|
@@ -15,7 +15,7 @@ import yaml
|
|
|
15
15
|
_source_dir = Path(__file__).parent.parent
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
_SUPPORTED_SUFFIXES = frozenset([".md", ".txt", ".pdf", ".py", ".json", ".docx", ".xlsx", ".pptx", ".csv"])
|
|
18
|
+
_SUPPORTED_SUFFIXES = frozenset([".md", ".txt", ".pdf", ".py", ".json", ".docx", ".xlsx", ".pptx", ".csv", ".ipynb"])
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
def _has_documents(path: Path) -> bool:
|
|
@@ -357,6 +357,9 @@ class Config:
|
|
|
357
357
|
documents_dir: Path = field(
|
|
358
358
|
default_factory=lambda: _resolve_path(_get("paths", "documents_dir", None), BASE_DIR / "documents")
|
|
359
359
|
)
|
|
360
|
+
models_cache_dir: Path = field(
|
|
361
|
+
default_factory=lambda: _resolve_path(_get("paths", "models_cache_dir", None), BASE_DIR / "models_cache")
|
|
362
|
+
)
|
|
360
363
|
|
|
361
364
|
# Chunking
|
|
362
365
|
chunk_size: int = field(
|
|
@@ -419,10 +422,15 @@ class Config:
|
|
|
419
422
|
# Supported formats
|
|
420
423
|
supported_formats: List[str] = field(
|
|
421
424
|
default_factory=lambda: _get(
|
|
422
|
-
"documents",
|
|
425
|
+
"documents",
|
|
426
|
+
"supported_formats",
|
|
427
|
+
[".md", ".txt", ".pdf", ".py", ".json", ".docx", ".xlsx", ".pptx", ".csv", ".ipynb"],
|
|
423
428
|
)
|
|
424
429
|
)
|
|
425
430
|
|
|
431
|
+
# Exclude patterns for directory traversal
|
|
432
|
+
exclude_patterns: List[str] = field(default_factory=lambda: _get("documents", "exclude_patterns", []))
|
|
433
|
+
|
|
426
434
|
# Category mappings
|
|
427
435
|
category_mappings: Dict[str, str] = field(
|
|
428
436
|
default_factory=lambda: _get_top("category_mappings", _DEFAULT_CATEGORY_MAPPINGS)
|
|
@@ -471,6 +479,13 @@ class Config:
|
|
|
471
479
|
print("[WARN] supported_formats is empty or invalid, using defaults")
|
|
472
480
|
self.supported_formats = [".md", ".txt", ".pdf", ".py", ".json", ".docx", ".xlsx", ".pptx", ".csv"]
|
|
473
481
|
|
|
482
|
+
# Validate exclude_patterns is a list of strings
|
|
483
|
+
if not isinstance(self.exclude_patterns, list):
|
|
484
|
+
print(f"[WARN] exclude_patterns={self.exclude_patterns!r} invalid, using []")
|
|
485
|
+
self.exclude_patterns = []
|
|
486
|
+
else:
|
|
487
|
+
self.exclude_patterns = [p for p in self.exclude_patterns if isinstance(p, str)]
|
|
488
|
+
|
|
474
489
|
# Validate keyword_routes values are lists (not strings)
|
|
475
490
|
for cat, keywords in list(self.keyword_routes.items()):
|
|
476
491
|
if not isinstance(keywords, list):
|
|
@@ -481,6 +496,7 @@ class Config:
|
|
|
481
496
|
self.data_dir.mkdir(parents=True, exist_ok=True)
|
|
482
497
|
self.chroma_dir.mkdir(parents=True, exist_ok=True)
|
|
483
498
|
self.documents_dir.mkdir(parents=True, exist_ok=True)
|
|
499
|
+
self.models_cache_dir.mkdir(parents=True, exist_ok=True)
|
|
484
500
|
|
|
485
501
|
|
|
486
502
|
# Global config instance
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""Document Ingestion System for Knowledge RAG
|
|
2
2
|
|
|
3
3
|
Multi-format document parsing, chunking, and metadata extraction.
|
|
4
|
-
Supports: MD, PDF, TXT, PY, JSON, DOCX, XLSX, PPTX, CSV
|
|
4
|
+
Supports: MD, PDF, TXT, PY, JSON, DOCX, XLSX, PPTX, CSV, IPYNB, MQH, MQ4
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
import fnmatch
|
|
7
8
|
import hashlib
|
|
8
9
|
import json
|
|
9
10
|
import os
|
|
@@ -103,6 +104,9 @@ class DocumentParser:
|
|
|
103
104
|
".xlsx": self._parse_xlsx,
|
|
104
105
|
".pptx": self._parse_pptx,
|
|
105
106
|
".csv": self._parse_csv,
|
|
107
|
+
".ipynb": self._parse_ipynb,
|
|
108
|
+
".mqh": self._parse_code,
|
|
109
|
+
".mq4": self._parse_code,
|
|
106
110
|
}
|
|
107
111
|
|
|
108
112
|
def parse_file(self, filepath: Path) -> Optional[Document]:
|
|
@@ -151,12 +155,41 @@ class DocumentParser:
|
|
|
151
155
|
|
|
152
156
|
return doc
|
|
153
157
|
|
|
158
|
+
@staticmethod
|
|
159
|
+
def _should_exclude(path: Path, base_dir: Path, patterns: List[str]) -> bool:
|
|
160
|
+
"""Check if a path matches any exclude pattern.
|
|
161
|
+
|
|
162
|
+
Uses fnmatch on the relative path (forward-slash normalized) and
|
|
163
|
+
also checks each path component individually for simple name patterns.
|
|
164
|
+
"""
|
|
165
|
+
if not patterns:
|
|
166
|
+
return False
|
|
167
|
+
|
|
168
|
+
try:
|
|
169
|
+
rel = path.relative_to(base_dir)
|
|
170
|
+
except ValueError:
|
|
171
|
+
rel = path
|
|
172
|
+
|
|
173
|
+
rel_str = str(rel).replace("\\", "/")
|
|
174
|
+
|
|
175
|
+
for pattern in patterns:
|
|
176
|
+
# Full relative path match (e.g., "docs/drafts/*.tmp")
|
|
177
|
+
if fnmatch.fnmatch(rel_str, pattern):
|
|
178
|
+
return True
|
|
179
|
+
# Check each component (e.g., "node_modules" matches any/node_modules/deep)
|
|
180
|
+
for part in rel.parts:
|
|
181
|
+
if fnmatch.fnmatch(part, pattern):
|
|
182
|
+
return True
|
|
183
|
+
|
|
184
|
+
return False
|
|
185
|
+
|
|
154
186
|
def parse_directory(self, directory: Path = None) -> List[Document]:
|
|
155
187
|
"""Parse all supported files in a directory recursively (follows symlinks)."""
|
|
156
188
|
directory = Path(directory) if directory else config.documents_dir
|
|
157
189
|
documents = []
|
|
158
190
|
seen_dirs = set()
|
|
159
191
|
supported = set(config.supported_formats)
|
|
192
|
+
exclude = config.exclude_patterns
|
|
160
193
|
|
|
161
194
|
for root, dirs, files in os.walk(directory, followlinks=True):
|
|
162
195
|
real_root = os.path.realpath(root)
|
|
@@ -165,10 +198,16 @@ class DocumentParser:
|
|
|
165
198
|
continue
|
|
166
199
|
seen_dirs.add(real_root)
|
|
167
200
|
|
|
201
|
+
# Filter out excluded directories in-place (prevents os.walk from descending)
|
|
202
|
+
if exclude:
|
|
203
|
+
dirs[:] = [d for d in dirs if not self._should_exclude(Path(root) / d, directory, exclude)]
|
|
204
|
+
|
|
168
205
|
for fname in files:
|
|
169
206
|
filepath = Path(root) / fname
|
|
170
207
|
if filepath.suffix.lower() not in supported:
|
|
171
208
|
continue
|
|
209
|
+
if exclude and self._should_exclude(filepath, directory, exclude):
|
|
210
|
+
continue
|
|
172
211
|
try:
|
|
173
212
|
doc = self.parse_file(filepath)
|
|
174
213
|
if doc:
|
|
@@ -437,6 +476,59 @@ class DocumentParser:
|
|
|
437
476
|
content = "\n".join(parts)
|
|
438
477
|
return content, metadata
|
|
439
478
|
|
|
479
|
+
def _parse_ipynb(self, filepath: Path) -> tuple[str, Dict]:
|
|
480
|
+
"""Parse Jupyter Notebook, extracting only markdown and code cell sources.
|
|
481
|
+
|
|
482
|
+
Ignores outputs, execution counts, cell metadata, and base64 images.
|
|
483
|
+
"""
|
|
484
|
+
raw = filepath.read_text(encoding="utf-8", errors="ignore")
|
|
485
|
+
metadata = {
|
|
486
|
+
"type": "jupyter_notebook",
|
|
487
|
+
"title": filepath.stem,
|
|
488
|
+
"file_size": filepath.stat().st_size,
|
|
489
|
+
"modified": datetime.fromtimestamp(filepath.stat().st_mtime).isoformat(),
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
try:
|
|
493
|
+
nb = json.loads(raw)
|
|
494
|
+
except json.JSONDecodeError:
|
|
495
|
+
metadata["is_valid_json"] = False
|
|
496
|
+
return raw, metadata
|
|
497
|
+
|
|
498
|
+
metadata["is_valid_json"] = True
|
|
499
|
+
metadata["nbformat"] = nb.get("nbformat", 0)
|
|
500
|
+
kernel = nb.get("metadata", {}).get("kernelspec", {})
|
|
501
|
+
metadata["kernel"] = kernel.get("display_name", kernel.get("name", "unknown"))
|
|
502
|
+
|
|
503
|
+
cells = nb.get("cells", [])
|
|
504
|
+
metadata["cells"] = len(cells)
|
|
505
|
+
code_cells = 0
|
|
506
|
+
markdown_cells = 0
|
|
507
|
+
|
|
508
|
+
parts = []
|
|
509
|
+
for cell in cells:
|
|
510
|
+
cell_type = cell.get("cell_type", "")
|
|
511
|
+
source = cell.get("source", "")
|
|
512
|
+
|
|
513
|
+
if isinstance(source, list):
|
|
514
|
+
source = "".join(source)
|
|
515
|
+
|
|
516
|
+
if not source or not source.strip():
|
|
517
|
+
continue
|
|
518
|
+
|
|
519
|
+
if cell_type == "markdown":
|
|
520
|
+
parts.append(source)
|
|
521
|
+
markdown_cells += 1
|
|
522
|
+
elif cell_type == "code":
|
|
523
|
+
parts.append(f"```python\n{source}\n```")
|
|
524
|
+
code_cells += 1
|
|
525
|
+
|
|
526
|
+
metadata["code_cells"] = code_cells
|
|
527
|
+
metadata["markdown_cells"] = markdown_cells
|
|
528
|
+
|
|
529
|
+
content = "\n\n".join(parts)
|
|
530
|
+
return content, metadata
|
|
531
|
+
|
|
440
532
|
# =========================================================================
|
|
441
533
|
# Chunking
|
|
442
534
|
# =========================================================================
|
|
@@ -19,8 +19,8 @@ Features:
|
|
|
19
19
|
- CRUD operations via MCP tools (add, update, remove docs)
|
|
20
20
|
|
|
21
21
|
Autor: Lyon (Ailton Rocha)
|
|
22
|
-
Versao: 3.
|
|
23
|
-
Data: 2026-04-
|
|
22
|
+
Versao: 3.4.0
|
|
23
|
+
Data: 2026-04-16
|
|
24
24
|
"""
|
|
25
25
|
|
|
26
26
|
import hashlib
|
|
@@ -141,7 +141,7 @@ class FastEmbedEmbeddings:
|
|
|
141
141
|
self.model_name = model or config.embedding_model
|
|
142
142
|
self._dim = config.embedding_dim
|
|
143
143
|
print(f"[INFO] Loading embedding model: {self.model_name} ({self._dim}D)...")
|
|
144
|
-
self._model = TextEmbedding(model_name=self.model_name)
|
|
144
|
+
self._model = TextEmbedding(model_name=self.model_name, cache_dir=str(config.models_cache_dir))
|
|
145
145
|
print("[INFO] Embedding model loaded successfully")
|
|
146
146
|
|
|
147
147
|
def __call__(self, input: List[str]) -> List[List[float]]:
|
|
@@ -1899,12 +1899,21 @@ def main():
|
|
|
1899
1899
|
print(f"[INFO] Indexed {stats['indexed']} documents with {stats['chunks_added']} chunks")
|
|
1900
1900
|
|
|
1901
1901
|
# Start file watcher for auto-reindex on document changes
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1902
|
+
try:
|
|
1903
|
+
watcher = DocumentWatcher(get_orchestrator, debounce_seconds=5.0)
|
|
1904
|
+
observer = Observer()
|
|
1905
|
+
observer.schedule(watcher, str(config.documents_dir), recursive=True)
|
|
1906
|
+
observer.daemon = True
|
|
1907
|
+
observer.start()
|
|
1908
|
+
print(f"[WATCHER] Monitoring {config.documents_dir} for changes")
|
|
1909
|
+
except Exception as e:
|
|
1910
|
+
print(f"[WARN] Failed to start file watcher: {e}")
|
|
1911
|
+
print("[WARN] Auto-reindexing disabled. Use reindex_documents tool manually.")
|
|
1912
|
+
|
|
1913
|
+
# Redirect stdout to stderr to protect MCP stdio JSON-RPC stream.
|
|
1914
|
+
# Libraries (fastembed, chromadb, watchdog) may print() at runtime,
|
|
1915
|
+
# which would corrupt the protocol. This ONLY affects the server process.
|
|
1916
|
+
sys.stdout = sys.stderr
|
|
1908
1917
|
|
|
1909
1918
|
mcp.run()
|
|
1910
1919
|
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
paths:
|
|
23
23
|
documents_dir: "./documents"
|
|
24
24
|
data_dir: "./data"
|
|
25
|
+
models_cache_dir: "./models_cache"
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
# ============================================================================
|
|
@@ -39,6 +40,9 @@ documents:
|
|
|
39
40
|
- .xlsx
|
|
40
41
|
- .pptx
|
|
41
42
|
- .csv
|
|
43
|
+
- .ipynb # Jupyter Notebooks (exploit dev, research)
|
|
44
|
+
|
|
45
|
+
exclude_patterns: []
|
|
42
46
|
|
|
43
47
|
chunking:
|
|
44
48
|
chunk_size: 1000
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
paths:
|
|
18
18
|
documents_dir: "./documents"
|
|
19
19
|
data_dir: "./data"
|
|
20
|
+
models_cache_dir: "./models_cache"
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
# ============================================================================
|
|
@@ -32,6 +33,16 @@ documents:
|
|
|
32
33
|
- .py # Python source code
|
|
33
34
|
- .json # API schemas, configs
|
|
34
35
|
- .csv # Data files, logs
|
|
36
|
+
- .ipynb # Jupyter Notebooks
|
|
37
|
+
|
|
38
|
+
exclude_patterns:
|
|
39
|
+
- "node_modules"
|
|
40
|
+
- ".venv"
|
|
41
|
+
- "__pycache__"
|
|
42
|
+
- ".git"
|
|
43
|
+
- "dist"
|
|
44
|
+
- "build"
|
|
45
|
+
- ".next"
|
|
35
46
|
|
|
36
47
|
chunking:
|
|
37
48
|
chunk_size: 1200 # Slightly larger for code + prose docs
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
paths:
|
|
27
27
|
documents_dir: "./documents"
|
|
28
28
|
data_dir: "./data"
|
|
29
|
+
models_cache_dir: "./models_cache"
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
# ============================================================================
|
|
@@ -39,6 +40,8 @@ documents:
|
|
|
39
40
|
- .pdf
|
|
40
41
|
- .docx
|
|
41
42
|
|
|
43
|
+
exclude_patterns: []
|
|
44
|
+
|
|
42
45
|
chunking:
|
|
43
46
|
chunk_size: 1000
|
|
44
47
|
chunk_overlap: 200
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
paths:
|
|
18
18
|
documents_dir: "./documents"
|
|
19
19
|
data_dir: "./data"
|
|
20
|
+
models_cache_dir: "./models_cache"
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
# ============================================================================
|
|
@@ -32,6 +33,9 @@ documents:
|
|
|
32
33
|
- .xlsx # Data tables, survey results
|
|
33
34
|
- .pptx # Presentations, lecture slides
|
|
34
35
|
- .csv # Experiment data, datasets
|
|
36
|
+
- .ipynb # Jupyter Notebooks (analysis, experiments)
|
|
37
|
+
|
|
38
|
+
exclude_patterns: []
|
|
35
39
|
|
|
36
40
|
chunking:
|
|
37
41
|
chunk_size: 1500 # Larger chunks — academic text needs more context
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "knowledge-rag"
|
|
7
|
-
version = "3.
|
|
7
|
+
version = "3.4.0"
|
|
8
8
|
description = "Local RAG System for Claude Code — Hybrid search + Cross-encoder Reranking + 12 MCP Tools. Zero external servers."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|