feat(memory): add experimental qmd search backend

This commit is contained in:
William Valentin
2026-02-15 19:33:43 -08:00
parent c6e3d09ecc
commit 81c97a9df1
14 changed files with 340 additions and 29 deletions
+16 -6
View File
@@ -1,8 +1,9 @@
import type { Config } from '../config/index.js';
import type { Lifecycle } from './lifecycle.js';
import { MemoryStore } from '../memory/index.js';
import { VectorStore, HybridSearch, createEmbeddingProvider, chunkText, contentHash } from '../memory/index.js';
import { VectorStore, HybridSearch, QmdSearch, createEmbeddingProvider, chunkText, contentHash } from '../memory/index.js';
import type { EmbeddingProvider as EmbeddingProviderInterface } from '../memory/index.js';
import type { MemorySearchBackend } from '../tools/builtin/memory-search.js';
import { createMemoryTools } from '../tools/builtin/index.js';
import type { ToolRegistry } from '../tools/index.js';
import { resolve } from 'path';
@@ -17,7 +18,7 @@ export interface MemoryDeps {
export interface MemoryResult {
memoryStore?: MemoryStore;
hybridSearch?: HybridSearch;
searchBackend?: MemorySearchBackend;
memoryDir: string;
}
@@ -32,18 +33,19 @@ export async function initMemory(deps: MemoryDeps): Promise<MemoryResult> {
: undefined;
// Register memory tools if memory is enabled
let hybridSearch: HybridSearch | undefined;
let searchBackend: MemorySearchBackend | undefined;
if (memoryStore && config.memory.embedding.enabled) {
try {
const embeddingProvider: EmbeddingProviderInterface = createEmbeddingProvider(config.memory.embedding);
const vectorStore = new VectorStore(resolve(dataDir, 'vectors.db'));
hybridSearch = new HybridSearch(
const hybridSearch = new HybridSearch(
memoryStore,
vectorStore,
embeddingProvider,
config.memory.embedding.hybrid_weight,
);
searchBackend = hybridSearch;
// Background indexer: re-embed dirty namespaces every 30 seconds
const indexerInterval = setInterval(async () => {
@@ -89,11 +91,19 @@ export async function initMemory(deps: MemoryDeps): Promise<MemoryResult> {
}
}
if (!searchBackend && memoryStore && config.memory.qmd.enabled) {
searchBackend = new QmdSearch(memoryStore, {
topK: config.memory.qmd.top_k,
minScore: config.memory.qmd.min_score,
});
console.log(`QMD memory search enabled (top_k=${config.memory.qmd.top_k}, min_score=${config.memory.qmd.min_score})`);
}
if (memoryStore) {
for (const tool of createMemoryTools(memoryStore, hybridSearch)) {
for (const tool of createMemoryTools(memoryStore, searchBackend)) {
toolRegistry.register(tool);
}
}
return { memoryStore, hybridSearch, memoryDir };
return { memoryStore, searchBackend, memoryDir };
}