Compare commits
2 Commits
fix/913-sy
...
fix/879
| Author | SHA1 | Date | |
|---|---|---|---|
| ba56567631 | |||
| c6f2855745 |
42
docs/holographic-vector-hybrid.md
Normal file
42
docs/holographic-vector-hybrid.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Holographic + Vector Hybrid Memory Architecture
|
||||||
|
|
||||||
|
Research issue #879. Combining HRR (holographic) and vector (Qdrant) memory.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
Three memory backends, each with unique strengths:
|
||||||
|
|
||||||
|
| Backend | Strength | Weakness | Use Case |
|
||||||
|
|---------|----------|----------|----------|
|
||||||
|
| FTS5 | Exact keyword match | No semantic understanding | Precise recall |
|
||||||
|
| Vector (Qdrant) | Semantic similarity | No compositional queries | Topic search |
|
||||||
|
| HRR (Holographic) | Compositional queries | Limited scale | Complex reasoning |
|
||||||
|
|
||||||
|
## Why Hybrid
|
||||||
|
|
||||||
|
- FTS5 alone: misses ~30-40% of semantically relevant content
|
||||||
|
- Vector alone: can't do compositional queries ("what did I discuss about X after doing Y?")
|
||||||
|
- HRR alone: unique capability but no semantic fallback
|
||||||
|
- Hybrid: best of all three, RRF fusion for ranking
|
||||||
|
|
||||||
|
## Implementation: Reciprocal Rank Fusion
|
||||||
|
|
||||||
|
Results from each backend are merged using RRF:
|
||||||
|
- score = sum(weight / (k + rank)) for each backend
|
||||||
|
- k=60 (standard RRF constant)
|
||||||
|
- Weights: FTS5=0.6, Vector=0.4 (configurable)
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
- FTS5: EXISTS (hermes_state.py)
|
||||||
|
- Vector (Qdrant): implemented (tools/hybrid_search.py)
|
||||||
|
- HRR: EXISTS (plugins/memory/holographic.py)
|
||||||
|
- RRF fusion: implemented (tools/hybrid_search.py)
|
||||||
|
- Ingestion pipeline: partial
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
1. Wire HRR into hybrid_search.py
|
||||||
|
2. Session-level vector ingestion
|
||||||
|
3. Benchmark: measure R@5 improvement
|
||||||
|
4. Cross-session memory persistence
|
||||||
@@ -44,6 +44,34 @@ from typing import Dict, Any, Optional, Tuple
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def _format_error(
|
||||||
|
message: str,
|
||||||
|
skill_name: str = None,
|
||||||
|
file_path: str = None,
|
||||||
|
suggestion: str = None,
|
||||||
|
context: dict = None,
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
"""Format an error with rich context for better debugging."""
|
||||||
|
parts = [message]
|
||||||
|
if skill_name:
|
||||||
|
parts.append(f"Skill: {skill_name}")
|
||||||
|
if file_path:
|
||||||
|
parts.append(f"File: {file_path}")
|
||||||
|
if suggestion:
|
||||||
|
parts.append(f"Suggestion: {suggestion}")
|
||||||
|
if context:
|
||||||
|
for key, value in context.items():
|
||||||
|
parts.append(f"{key}: {value}")
|
||||||
|
return {
|
||||||
|
"success": False,
|
||||||
|
"error": " | ".join(parts),
|
||||||
|
"skill_name": skill_name,
|
||||||
|
"file_path": file_path,
|
||||||
|
"suggestion": suggestion,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# Import security scanner — agent-created skills get the same scrutiny as
|
# Import security scanner — agent-created skills get the same scrutiny as
|
||||||
# community hub installs.
|
# community hub installs.
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user