cozo-memory 1.0.7 β 1.0.8
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.
- package/README.md +38 -10
- package/dist/eval-suite.js +136 -0
- package/dist/hybrid-search.js +99 -0
- package/dist/index.js +267 -43
- package/dist/inference-engine.js +7 -0
- package/dist/make-old.js +58 -0
- package/dist/test-agentic-retrieval.js +28 -0
- package/dist/test-discovery.js +53 -0
- package/dist/test-graphrag.js +35 -0
- package/dist/verify-agentic-logic.js +64 -0
- package/package.json +2 -1
- package/dist/test-mcp-search.js +0 -47
- package/dist/tui-blessed.js +0 -789
- package/dist/tui.py +0 -481
package/README.md
CHANGED
|
@@ -59,7 +59,9 @@ Now you can add the server to your MCP client (e.g. Claude Desktop).
|
|
|
59
59
|
|
|
60
60
|
π **Hybrid Search (since v0.7)** - Combines semantic search (HNSW), full-text search (FTS), and graph signals via Reciprocal Rank Fusion (RRF)
|
|
61
61
|
|
|
62
|
-
πΈοΈ **Graph-RAG & Graph-Walking (
|
|
62
|
+
πΈοΈ **Graph-RAG & Graph-Walking (v1.7/v2.0)** - Hierarchical retrieval with community detection and summarization; recursive traversals using optimized Datalog algorithms
|
|
63
|
+
|
|
64
|
+
π§ **Agentic Retrieval Layer (v2.0)** - Auto-routing engine that analyzes query intent via local LLM to select the optimal search strategy (Vector, Graph, or Community)
|
|
63
65
|
|
|
64
66
|
π― **Multi-Vector Support (since v1.7)** - Dual embeddings per entity: content-embedding for context, name-embedding for identification
|
|
65
67
|
|
|
@@ -71,7 +73,9 @@ Now you can add the server to your MCP client (e.g. Claude Desktop).
|
|
|
71
73
|
|
|
72
74
|
π **Graph Algorithms (since v1.3/v1.6)** - PageRank, Betweenness Centrality, HITS, Community Detection, Shortest Path
|
|
73
75
|
|
|
74
|
-
|
|
76
|
+
ποΈ **Hierarchical GraphRAG (v2.0)** - Automatic generation of thematic "Community Summaries" using local LLMs to enable global "Big Picture" reasoning
|
|
77
|
+
|
|
78
|
+
π§Ή **Janitor Service** - LLM-backed automatic cleanup with hierarchical summarization and observation pruning
|
|
75
79
|
|
|
76
80
|
π€ **User Preference Profiling** - Persistent user preferences with automatic 50% search boost
|
|
77
81
|
|
|
@@ -136,13 +140,14 @@ This server fills the gap in between ("Sweet Spot"): A **local, database-backed
|
|
|
136
140
|
| Feature | **CozoDB Memory (This Project)** | **Official Reference (`@modelcontextprotocol/server-memory`)** | **mcp-memory-service (Community)** | **Database Adapters (Qdrant/Neo4j)** |
|
|
137
141
|
| :--- | :--- | :--- | :--- | :--- |
|
|
138
142
|
| **Backend** | **CozoDB** (Graph + Vector + Relational) | JSON file (`memory.jsonl`) | SQLite / Cloudflare | Specialized DB (only Vector or Graph) |
|
|
139
|
-
| **Search Logic** | **
|
|
143
|
+
| **Search Logic** | **Agentic (Auto-Route)**: Hybrid + Graph + Summaries | Keyword only / Exact Graph Match | Vector + Keyword | Mostly only one dimension |
|
|
140
144
|
| **Inference** | **Yes**: Built-in engine for implicit knowledge | No | No ("Dreaming" is consolidation) | No (Retrieval only) |
|
|
145
|
+
| **Community** | **Yes**: Hierarchical Community Summaries | No | No | Only clustering (no summary) |
|
|
141
146
|
| **Time-Travel** | **Yes**: Queries at any point in time (`Validity`) | No (current state only) | History available, no native DB feature | No |
|
|
142
147
|
| **Maintenance** | **Janitor**: LLM-backed cleanup | Manual | Automatic consolidation | Mostly manual |
|
|
143
148
|
| **Deployment** | **Local** (Node.js + Embedded DB) | Local (Docker/NPX) | Local or Cloud | Often requires external DB server |
|
|
144
149
|
|
|
145
|
-
The core advantage is **
|
|
150
|
+
The core advantage is **Intelligence and Traceability**: By combining an **Agentic Retrieval Layer** with **Hierarchical GraphRAG**, the system can answer both specific factual questions and broad thematic queries with much higher accuracy than pure vector stores.
|
|
146
151
|
|
|
147
152
|
## Performance & Benchmarks
|
|
148
153
|
|
|
@@ -173,6 +178,22 @@ This tool (`src/benchmark.ts`) performs the following tests:
|
|
|
173
178
|
3. **Search Performance**: Latency measurement for Hybrid Search vs. Raw Vector Search.
|
|
174
179
|
4. **RRF Overhead**: Determination of additional computation time for fusion logic.
|
|
175
180
|
|
|
181
|
+
### Running Evaluation Suite (RAG Quality)
|
|
182
|
+
|
|
183
|
+
To evaluate the quality and recall of different retrieval strategies (Search vs. Graph-RAG vs. Graph-Walking), use the evaluation suite:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
npm run eval
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
This tool compares strategies using a synthetic dataset and measures **Recall@K**, **MRR**, and **Latency**.
|
|
190
|
+
|
|
191
|
+
| Method | Recall@10 | Avg Latency | Best For |
|
|
192
|
+
| :--- | :--- | :--- | :--- |
|
|
193
|
+
| **Graph-RAG** | **1.00** | **~32 ms** | Deep relational reasoning |
|
|
194
|
+
| **Graph-Walking** | 1.00 | ~50 ms | Associative path exploration |
|
|
195
|
+
| **Hybrid Search** | 1.00 | ~89 ms | Broad factual retrieval |
|
|
196
|
+
|
|
176
197
|
## Architecture
|
|
177
198
|
|
|
178
199
|
```mermaid
|
|
@@ -488,9 +509,9 @@ The interface is reduced to **4 consolidated tools**. The concrete operation is
|
|
|
488
509
|
| Tool | Purpose | Key Actions |
|
|
489
510
|
|------|---------|-------------|
|
|
490
511
|
| `mutate_memory` | Write operations | create_entity, update_entity, delete_entity, add_observation, create_relation, run_transaction, add_inference_rule, ingest_file |
|
|
491
|
-
| `query_memory` | Read operations | search, advancedSearch, context, entity_details, history, graph_rag, graph_walking |
|
|
512
|
+
| `query_memory` | Read operations | search, advancedSearch, context, entity_details, history, graph_rag, graph_walking, agentic_search |
|
|
492
513
|
| `analyze_graph` | Graph analysis | explore, communities, pagerank, betweenness, hits, shortest_path, bridge_discovery, semantic_walk, infer_relations |
|
|
493
|
-
| `manage_system` | Maintenance | health, metrics, export_memory, import_memory, snapshot_create, snapshot_list, snapshot_diff, cleanup, reflect, clear_memory |
|
|
514
|
+
| `manage_system` | Maintenance | health, metrics, export_memory, import_memory, snapshot_create, snapshot_list, snapshot_diff, cleanup, reflect, summarize_communities, clear_memory |
|
|
494
515
|
|
|
495
516
|
### mutate_memory (Write)
|
|
496
517
|
|
|
@@ -594,6 +615,7 @@ Actions:
|
|
|
594
615
|
- `history`: `{ entity_id }`
|
|
595
616
|
- `graph_rag`: `{ query, max_depth?, limit?, filters? }` Graph-based reasoning. Finds vector seeds (with inline filtering) first and then expands transitive relationships. Uses recursive Datalog for efficient BFS expansion.
|
|
596
617
|
- `graph_walking`: `{ query, start_entity_id?, max_depth?, limit? }` (v1.7) Recursive semantic graph search. Starts at vector seeds or a specific entity and follows relationships to other semantically relevant entities. Ideal for deeper path exploration.
|
|
618
|
+
- `agentic_search`: `{ query, limit? }` **(New v2.0)**: **Auto-Routing Search**. Uses a local LLM (Ollama) to analyze query intent and automatically routes it to the most appropriate strategy (`vector_search`, `graph_walk`, or `community_summary`).
|
|
597
619
|
- `get_relation_evolution`: `{ from_id, to_id?, since?, until? }` (in `analyze_graph`) Shows temporal development of relationships including time range filter and diff summary.
|
|
598
620
|
|
|
599
621
|
Important Details:
|
|
@@ -687,7 +709,8 @@ Actions:
|
|
|
687
709
|
- `snapshot_list`: `{}`
|
|
688
710
|
- `snapshot_diff`: `{ snapshot_id_a, snapshot_id_b }`
|
|
689
711
|
- `cleanup`: `{ confirm, older_than_days?, max_observations?, min_entity_degree?, model? }`
|
|
690
|
-
- `
|
|
712
|
+
- `summarize_communities`: `{ model?, min_community_size? }` **(New v2.0)**: Triggers the **Hierarchical GraphRAG** pipeline. Recomputes communities, generates thematic summaries via LLM, and stores them as `CommunitySummary` entities.
|
|
713
|
+
- `reflect`: `{ entity_id?, mode?, model? }` Analyzes memory for contradictions and new insights. Supports `summary` (default) and `discovery` (autonomous link refinement) modes.
|
|
691
714
|
- `clear_memory`: `{ confirm }`
|
|
692
715
|
|
|
693
716
|
Janitor Cleanup Details:
|
|
@@ -711,9 +734,14 @@ Entity: Project X
|
|
|
711
734
|
with a team of 5 developers, currently deployed to staging environment."
|
|
712
735
|
```
|
|
713
736
|
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
-
|
|
737
|
+
### Self-Improving Memory Loop (`reflect`)
|
|
738
|
+
The `reflect` service analyzes observations of an entity (or top 5 active entities) to find contradictions, patterns, or temporal developments.
|
|
739
|
+
- **Modes**:
|
|
740
|
+
- `summary` (default): Generates a textual "Reflective Insight" observation.
|
|
741
|
+
- `discovery`: Autonomously finds potential relationships using the Inference Engine and validates them via LLM.
|
|
742
|
+
- High-confidence links (>0.8) are created automatically.
|
|
743
|
+
- Medium-confidence links (>0.5) are returned as suggestions.
|
|
744
|
+
- Results are persisted as new observations (for `summary`) or relationships (for `discovery`) with metadata field `{ "kind": "reflection" }` or `{ "source": "reflection" }`.
|
|
717
745
|
- Text is stored with prefix `Reflective Insight: `.
|
|
718
746
|
|
|
719
747
|
Defaults: `older_than_days=30`, `max_observations=20`, `min_entity_degree=2`, `model="demyagent-4b-i1:Q6_K"`.
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const index_1 = require("./index");
|
|
7
|
+
const perf_hooks_1 = require("perf_hooks");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const EVAL_DB_PATH = path_1.default.join(process.cwd(), "eval_db");
|
|
11
|
+
const EVAL_DATASET = [
|
|
12
|
+
{
|
|
13
|
+
query: "Where does Alice live?",
|
|
14
|
+
expectedEntityNames: ["Alice"],
|
|
15
|
+
type: "factual"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
query: "Which technology does CozoDB use?",
|
|
19
|
+
expectedEntityNames: ["Datalog"],
|
|
20
|
+
type: "factual"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
query: "Which technology is used by the project Alice works on?",
|
|
24
|
+
expectedEntityNames: ["Datalog"],
|
|
25
|
+
type: "multi-hop"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
query: "What language is used by the project Bob works on?",
|
|
29
|
+
expectedEntityNames: ["Datalog"],
|
|
30
|
+
type: "multi-hop"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
query: "Who is Bob's colleague?",
|
|
34
|
+
expectedEntityNames: ["Alice"],
|
|
35
|
+
type: "relational"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
query: "What is the background of Bob's coworkers?",
|
|
39
|
+
expectedEntityNames: ["Alice"],
|
|
40
|
+
type: "relational"
|
|
41
|
+
}
|
|
42
|
+
];
|
|
43
|
+
async function setupEvalData(server) {
|
|
44
|
+
console.log("β’ Setting up Evaluation Knowledge Graph...");
|
|
45
|
+
// Create Entities
|
|
46
|
+
const alice = await server.createEntity({ name: "Alice", type: "Person", metadata: { location: "Berlin" } });
|
|
47
|
+
const bob = await server.createEntity({ name: "Bob", type: "Person", metadata: { role: "Developer" } });
|
|
48
|
+
const cozodb = await server.createEntity({ name: "CozoDB", type: "Project", metadata: { category: "Database" } });
|
|
49
|
+
const datalog = await server.createEntity({ name: "Datalog", type: "Technology", metadata: { type: "Logic Language" } });
|
|
50
|
+
const aid = alice.id;
|
|
51
|
+
const bid = bob.id;
|
|
52
|
+
const cid = cozodb.id;
|
|
53
|
+
const did = datalog.id;
|
|
54
|
+
// Add Observations
|
|
55
|
+
await server.addObservation({ entity_id: aid, text: "Alice lives in Berlin and works as a Senior Engineer." });
|
|
56
|
+
await server.addObservation({ entity_id: aid, text: "Alice is a leading expert in CozoDB and recursive queries." });
|
|
57
|
+
await server.addObservation({ entity_id: cid, text: "CozoDB is a powerful graph-vector relational database." });
|
|
58
|
+
await server.addObservation({ entity_id: cid, text: "CozoDB uses Datalog as its primary query language." });
|
|
59
|
+
await server.addObservation({ entity_id: bid, text: "Bob is a software developer focused on backend systems." });
|
|
60
|
+
await server.addObservation({ entity_id: did, text: "Datalog is a declarative logic programming language used for deductive databases." });
|
|
61
|
+
// Create Relations
|
|
62
|
+
await server.createRelation({ from_id: aid, to_id: cid, relation_type: "works_on", strength: 1.0 });
|
|
63
|
+
await server.createRelation({ from_id: bid, to_id: cid, relation_type: "works_on", strength: 1.0 });
|
|
64
|
+
await server.createRelation({ from_id: bid, to_id: aid, relation_type: "colleague_of", strength: 0.9 });
|
|
65
|
+
await server.createRelation({ from_id: cid, to_id: did, relation_type: "uses_tech", strength: 1.0 });
|
|
66
|
+
console.log(" -> Knowledge Graph populated.");
|
|
67
|
+
}
|
|
68
|
+
function calculateRecall(results, expected, k) {
|
|
69
|
+
const topK = results.slice(0, k);
|
|
70
|
+
const found = expected.filter(name => topK.some(r => (r.name || "").toLowerCase() === name.toLowerCase()));
|
|
71
|
+
return found.length / expected.length;
|
|
72
|
+
}
|
|
73
|
+
function calculateMRR(results, expected) {
|
|
74
|
+
for (let i = 0; i < results.length; i++) {
|
|
75
|
+
const r = results[i];
|
|
76
|
+
if (expected.some(name => (r.name || "").toLowerCase() === name.toLowerCase())) {
|
|
77
|
+
return 1 / (i + 1);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
async function runEvaluation() {
|
|
83
|
+
console.log("==================================================");
|
|
84
|
+
console.log("π Cozo Memory Evaluation Suite");
|
|
85
|
+
console.log("==================================================");
|
|
86
|
+
if (fs_1.default.existsSync(EVAL_DB_PATH + ".db")) {
|
|
87
|
+
fs_1.default.unlinkSync(EVAL_DB_PATH + ".db");
|
|
88
|
+
}
|
|
89
|
+
const server = new index_1.MemoryServer(EVAL_DB_PATH);
|
|
90
|
+
await server.embeddingService.embed("warmup");
|
|
91
|
+
await setupEvalData(server);
|
|
92
|
+
const methods = [
|
|
93
|
+
{ name: "Hybrid Search", func: (q) => server.hybridSearch.search({ query: q, limit: 10 }) },
|
|
94
|
+
{ name: "Graph-RAG", func: (q) => server.hybridSearch.graphRag({ query: q, limit: 10, graphConstraints: { maxDepth: 2 } }) },
|
|
95
|
+
{ name: "Graph-Walking", func: (q) => server.graph_walking({ query: q, limit: 10, max_depth: 3 }) }
|
|
96
|
+
];
|
|
97
|
+
const summary = [];
|
|
98
|
+
for (const method of methods) {
|
|
99
|
+
console.log(`\nβ’ Evaluating ${method.name}...`);
|
|
100
|
+
let totalRecall3 = 0;
|
|
101
|
+
let totalRecall10 = 0;
|
|
102
|
+
let totalMRR = 0;
|
|
103
|
+
let totalLatency = 0;
|
|
104
|
+
for (const task of EVAL_DATASET) {
|
|
105
|
+
const t0 = perf_hooks_1.performance.now();
|
|
106
|
+
const results = await method.func(task.query);
|
|
107
|
+
const t1 = perf_hooks_1.performance.now();
|
|
108
|
+
const r3 = calculateRecall(results, task.expectedEntityNames, 3);
|
|
109
|
+
const r10 = calculateRecall(results, task.expectedEntityNames, 10);
|
|
110
|
+
const mrr = calculateMRR(results, task.expectedEntityNames);
|
|
111
|
+
totalRecall3 += r3;
|
|
112
|
+
totalRecall10 += r10;
|
|
113
|
+
totalMRR += mrr;
|
|
114
|
+
totalLatency += (t1 - t0);
|
|
115
|
+
}
|
|
116
|
+
const n = EVAL_DATASET.length;
|
|
117
|
+
summary.push({
|
|
118
|
+
Method: method.name,
|
|
119
|
+
"Recall@3": (totalRecall3 / n).toFixed(3),
|
|
120
|
+
"Recall@10": (totalRecall10 / n).toFixed(3),
|
|
121
|
+
MRR: (totalMRR / n).toFixed(3),
|
|
122
|
+
"Avg Latency": (totalLatency / n).toFixed(2) + "ms"
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
console.log("\n==================================================");
|
|
126
|
+
console.log("Final Evaluation Results:");
|
|
127
|
+
console.table(summary);
|
|
128
|
+
console.log("==================================================");
|
|
129
|
+
// Cleanup
|
|
130
|
+
// @ts-ignore
|
|
131
|
+
server.db.close();
|
|
132
|
+
if (fs_1.default.existsSync(EVAL_DB_PATH + ".db")) {
|
|
133
|
+
fs_1.default.unlinkSync(EVAL_DB_PATH + ".db");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
runEvaluation().catch(console.error);
|
package/dist/hybrid-search.js
CHANGED
|
@@ -338,5 +338,104 @@ class HybridSearch {
|
|
|
338
338
|
return this.search(options);
|
|
339
339
|
}
|
|
340
340
|
}
|
|
341
|
+
async agenticRetrieve(options) {
|
|
342
|
+
console.error("[HybridSearch] Starting agenticRetrieve with query:", options.query);
|
|
343
|
+
const { query, routingModel = "demyagent-4b-i1:Q6_K" } = options;
|
|
344
|
+
const systemPrompt = `You are a Routing Agent for an advanced Memory/RAG system.
|
|
345
|
+
Your job is to analyze the user's query and decide which search strategy is the most appropriate.
|
|
346
|
+
Available strategies:
|
|
347
|
+
- "vector_search": Best for finding specific facts or general semantic queries (e.g., "What ORM is used?", "How does feature X work?", "Welches System nutzt B?").
|
|
348
|
+
- "graph_walk": Best for queries about relations, links, or paths between entities (e.g., "Who works with Bob?", "What depends on Project A?", "Wer arbeitet mit ReactJS?").
|
|
349
|
+
- "community_summary": Best for high-level, overarching questions about the big picture, status, or general themes of entire clusters (e.g., "What is the general tech stack?", "Give me an overview of the legacy project", "Wie ist der generelle Status aller Frontend-Projekte?").
|
|
350
|
+
- "hybrid": Best for complex queries that require both factual retrieval and deep relational context.
|
|
351
|
+
|
|
352
|
+
You MUST respond with a JSON object in this format: {"strategy": "one_of_the_above"}.
|
|
353
|
+
No markdown, no explanation. Just the JSON.`;
|
|
354
|
+
let strategy = "vector_search"; // Fallback
|
|
355
|
+
try {
|
|
356
|
+
const ollamaMod = await import("ollama");
|
|
357
|
+
const ollamaClient = ollamaMod?.default ?? ollamaMod;
|
|
358
|
+
const response = await ollamaClient.chat({
|
|
359
|
+
model: routingModel,
|
|
360
|
+
messages: [
|
|
361
|
+
{ role: "system", content: systemPrompt },
|
|
362
|
+
{ role: "user", content: query },
|
|
363
|
+
],
|
|
364
|
+
format: "json",
|
|
365
|
+
});
|
|
366
|
+
let responseText = response?.message?.content?.trim?.() ?? "";
|
|
367
|
+
// Clean markdown formatting if Ollama returned it
|
|
368
|
+
if (responseText.startsWith("```json")) {
|
|
369
|
+
responseText = responseText.replace(/```json/g, "").replace(/```/g, "").trim();
|
|
370
|
+
}
|
|
371
|
+
else if (responseText.startsWith("```")) {
|
|
372
|
+
responseText = responseText.replace(/```/g, "").trim();
|
|
373
|
+
}
|
|
374
|
+
console.error(`[AgenticRetrieve] DEBUG: Raw LLM Output: ${responseText}`);
|
|
375
|
+
try {
|
|
376
|
+
const parsed = JSON.parse(responseText);
|
|
377
|
+
let selected = "";
|
|
378
|
+
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
379
|
+
selected = parsed[0];
|
|
380
|
+
}
|
|
381
|
+
else if (typeof parsed === "object" && parsed.strategy) {
|
|
382
|
+
selected = parsed.strategy;
|
|
383
|
+
}
|
|
384
|
+
else if (typeof parsed === "string") {
|
|
385
|
+
selected = parsed;
|
|
386
|
+
}
|
|
387
|
+
if (selected) {
|
|
388
|
+
const s = selected.toLowerCase();
|
|
389
|
+
if (["vector_search", "graph_walk", "community_summary", "hybrid"].includes(s)) {
|
|
390
|
+
strategy = s;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
catch (e) {
|
|
395
|
+
console.warn(`[AgenticRetrieve] Failed to parse JSON from LLM: ${responseText}`);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
catch (e) {
|
|
399
|
+
console.warn(`[AgenticRetrieve] Ollama routing failed: ${e.message}. Using fallback.`);
|
|
400
|
+
}
|
|
401
|
+
console.error(`[AgenticRetrieve] Selected Strategy: ${strategy}`);
|
|
402
|
+
let results = [];
|
|
403
|
+
// Map strategy to existing search methods
|
|
404
|
+
switch (strategy) {
|
|
405
|
+
case "graph_walk":
|
|
406
|
+
case "hybrid":
|
|
407
|
+
// Use our advanced Datalog graph-rag for deep relational context
|
|
408
|
+
results = await this.graphRag(options);
|
|
409
|
+
break;
|
|
410
|
+
case "community_summary":
|
|
411
|
+
// Prioritize CommunitySummary entities
|
|
412
|
+
results = await this.advancedSearch({
|
|
413
|
+
...options,
|
|
414
|
+
filters: {
|
|
415
|
+
...options.filters,
|
|
416
|
+
entityTypes: ["CommunitySummary"]
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
// If no community summaries found, fallback to standard search
|
|
420
|
+
if (results.length === 0) {
|
|
421
|
+
console.error(`[AgenticRetrieve] No Community Summaries found, falling back to hybrid search.`);
|
|
422
|
+
results = await this.advancedSearch(options);
|
|
423
|
+
}
|
|
424
|
+
break;
|
|
425
|
+
case "vector_search":
|
|
426
|
+
default:
|
|
427
|
+
// Standard vector search (which is advancedSearch in v1.7)
|
|
428
|
+
results = await this.advancedSearch(options);
|
|
429
|
+
break;
|
|
430
|
+
}
|
|
431
|
+
// Annotate results with the routing decision for testing/transparency
|
|
432
|
+
return results.map(r => ({
|
|
433
|
+
...r,
|
|
434
|
+
metadata: {
|
|
435
|
+
...(r.metadata || {}),
|
|
436
|
+
agentic_routing: strategy
|
|
437
|
+
}
|
|
438
|
+
}));
|
|
439
|
+
}
|
|
341
440
|
}
|
|
342
441
|
exports.HybridSearch = HybridSearch;
|