mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-12 09:41:11 +00:00
perf: extract memory search preflight helpers
This commit is contained in:
@@ -485,48 +485,6 @@ describe("memory index", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("passes Gemini outputDimensionality from config into the provider", async () => {
|
||||
const cfg = createCfg({
|
||||
storePath: indexMainPath,
|
||||
provider: "gemini",
|
||||
model: "gemini-embedding-2-preview",
|
||||
outputDimensionality: 1536,
|
||||
});
|
||||
|
||||
const result = await getMemorySearchManager({ cfg, agentId: "main" });
|
||||
const manager = requireManager(result);
|
||||
await manager.probeEmbeddingAvailability();
|
||||
|
||||
expect(
|
||||
providerCalls.some(
|
||||
(call) =>
|
||||
call.provider === "gemini" &&
|
||||
call.model === "gemini-embedding-2-preview" &&
|
||||
call.outputDimensionality === 1536,
|
||||
),
|
||||
).toBe(true);
|
||||
await manager.close?.();
|
||||
});
|
||||
|
||||
it("does not initialize the provider when searching an empty index", async () => {
|
||||
const cfg = createCfg({
|
||||
storePath: path.join(workspaceDir, `index-empty-${randomUUID()}.sqlite`),
|
||||
provider: "gemini",
|
||||
model: "gemini-embedding-2-preview",
|
||||
outputDimensionality: 1536,
|
||||
onSearch: false,
|
||||
});
|
||||
|
||||
const result = await getMemorySearchManager({ cfg, agentId: "main" });
|
||||
const manager = requireManager(result);
|
||||
|
||||
const results = await manager.search("hello");
|
||||
|
||||
expect(results).toEqual([]);
|
||||
expect(providerCalls).toEqual([]);
|
||||
await manager.close?.();
|
||||
});
|
||||
|
||||
it("reuses cached embeddings on forced reindex", async () => {
|
||||
const cfg = createCfg({ storePath: indexMainPath, cacheEnabled: true });
|
||||
const manager = await getPersistentManager(cfg);
|
||||
|
||||
@@ -17,6 +17,26 @@ export type MemoryResolvedProviderState = {
|
||||
providerRuntime?: EmbeddingProviderRuntime;
|
||||
};
|
||||
|
||||
export function resolveMemoryPrimaryProviderRequest(params: {
|
||||
settings: ResolvedMemorySearchConfig;
|
||||
}): {
|
||||
provider: string;
|
||||
model: string;
|
||||
remote: ResolvedMemorySearchConfig["remote"];
|
||||
outputDimensionality: ResolvedMemorySearchConfig["outputDimensionality"];
|
||||
fallback: ResolvedMemorySearchConfig["fallback"];
|
||||
local: ResolvedMemorySearchConfig["local"];
|
||||
} {
|
||||
return {
|
||||
provider: params.settings.provider,
|
||||
model: params.settings.model,
|
||||
remote: params.settings.remote,
|
||||
outputDimensionality: params.settings.outputDimensionality,
|
||||
fallback: params.settings.fallback,
|
||||
local: params.settings.local,
|
||||
};
|
||||
}
|
||||
|
||||
export function resolveMemoryProviderState(
|
||||
result: Pick<
|
||||
EmbeddingProviderResult,
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveMemorySearchPreflight } from "./manager-search-preflight.js";
|
||||
|
||||
describe("memory manager search preflight", () => {
|
||||
it("skips search and provider init for blank queries", () => {
|
||||
expect(
|
||||
resolveMemorySearchPreflight({
|
||||
query: " ",
|
||||
hasIndexedContent: true,
|
||||
}),
|
||||
).toEqual({
|
||||
normalizedQuery: "",
|
||||
shouldInitializeProvider: false,
|
||||
shouldSearch: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("skips provider init when the index is empty", () => {
|
||||
expect(
|
||||
resolveMemorySearchPreflight({
|
||||
query: "hello",
|
||||
hasIndexedContent: false,
|
||||
}),
|
||||
).toEqual({
|
||||
normalizedQuery: "hello",
|
||||
shouldInitializeProvider: false,
|
||||
shouldSearch: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("allows provider init when query and indexed content are present", () => {
|
||||
expect(
|
||||
resolveMemorySearchPreflight({
|
||||
query: " hello ",
|
||||
hasIndexedContent: true,
|
||||
}),
|
||||
).toEqual({
|
||||
normalizedQuery: "hello",
|
||||
shouldInitializeProvider: true,
|
||||
shouldSearch: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
export function resolveMemorySearchPreflight(params: { query: string; hasIndexedContent: boolean }):
|
||||
| {
|
||||
normalizedQuery: string;
|
||||
shouldInitializeProvider: boolean;
|
||||
shouldSearch: true;
|
||||
}
|
||||
| {
|
||||
normalizedQuery: string;
|
||||
shouldInitializeProvider: false;
|
||||
shouldSearch: false;
|
||||
} {
|
||||
const normalizedQuery = params.query.trim();
|
||||
if (!normalizedQuery) {
|
||||
return {
|
||||
normalizedQuery,
|
||||
shouldInitializeProvider: false,
|
||||
shouldSearch: false,
|
||||
};
|
||||
}
|
||||
if (!params.hasIndexedContent) {
|
||||
return {
|
||||
normalizedQuery,
|
||||
shouldInitializeProvider: false,
|
||||
shouldSearch: false,
|
||||
};
|
||||
}
|
||||
return {
|
||||
normalizedQuery,
|
||||
shouldInitializeProvider: true,
|
||||
shouldSearch: true,
|
||||
};
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import { describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
applyMemoryFallbackProviderState,
|
||||
resolveMemoryFallbackProviderRequest,
|
||||
resolveMemoryPrimaryProviderRequest,
|
||||
resolveMemoryProviderState,
|
||||
} from "./manager-provider-state.js";
|
||||
|
||||
@@ -114,4 +115,19 @@ describe("memory manager mistral provider wiring", () => {
|
||||
expect(request?.model).toBe(DEFAULT_OLLAMA_EMBEDDING_MODEL);
|
||||
expect(request?.fallback).toBe("none");
|
||||
});
|
||||
|
||||
it("includes outputDimensionality in the primary provider request", () => {
|
||||
const request = resolveMemoryPrimaryProviderRequest({
|
||||
settings: {
|
||||
...createSettings({ provider: "mistral" }),
|
||||
provider: "gemini",
|
||||
model: "gemini-embedding-2-preview",
|
||||
outputDimensionality: 1536,
|
||||
} as ResolvedMemorySearchConfig,
|
||||
});
|
||||
|
||||
expect(request.provider).toBe("gemini");
|
||||
expect(request.model).toBe("gemini-embedding-2-preview");
|
||||
expect(request.outputDimensionality).toBe(1536);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -34,7 +34,11 @@ import {
|
||||
resolveSingletonManagedCache,
|
||||
} from "./manager-cache.js";
|
||||
import { MemoryManagerEmbeddingOps } from "./manager-embedding-ops.js";
|
||||
import { resolveMemoryProviderState } from "./manager-provider-state.js";
|
||||
import {
|
||||
resolveMemoryPrimaryProviderRequest,
|
||||
resolveMemoryProviderState,
|
||||
} from "./manager-provider-state.js";
|
||||
import { resolveMemorySearchPreflight } from "./manager-search-preflight.js";
|
||||
import { searchKeyword, searchVector } from "./manager-search.js";
|
||||
import {
|
||||
collectMemoryStatusAggregate,
|
||||
@@ -142,12 +146,7 @@ export class MemoryIndexManager extends MemoryManagerEmbeddingOps implements Mem
|
||||
return await createEmbeddingProvider({
|
||||
config: params.cfg,
|
||||
agentDir: resolveAgentDir(params.cfg, params.agentId),
|
||||
provider: params.settings.provider,
|
||||
remote: params.settings.remote,
|
||||
model: params.settings.model,
|
||||
outputDimensionality: params.settings.outputDimensionality,
|
||||
fallback: params.settings.fallback,
|
||||
local: params.settings.local,
|
||||
...resolveMemoryPrimaryProviderRequest({ settings: params.settings }),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -293,10 +292,14 @@ export class MemoryIndexManager extends MemoryManagerEmbeddingOps implements Mem
|
||||
sessionKey?: string;
|
||||
},
|
||||
): Promise<MemorySearchResult[]> {
|
||||
const cleaned = query.trim();
|
||||
if (!cleaned) {
|
||||
const preflight = resolveMemorySearchPreflight({
|
||||
query,
|
||||
hasIndexedContent: this.hasIndexedContent(),
|
||||
});
|
||||
if (!preflight.shouldSearch) {
|
||||
return [];
|
||||
}
|
||||
const cleaned = preflight.normalizedQuery;
|
||||
void this.warmSession(opts?.sessionKey);
|
||||
startAsyncSearchSync({
|
||||
enabled: this.settings.sync.onSearch,
|
||||
@@ -307,11 +310,9 @@ export class MemoryIndexManager extends MemoryManagerEmbeddingOps implements Mem
|
||||
log.warn(`memory sync failed (search): ${String(err)}`);
|
||||
},
|
||||
});
|
||||
const hasIndexedContent = this.hasIndexedContent();
|
||||
if (!hasIndexedContent) {
|
||||
return [];
|
||||
if (preflight.shouldInitializeProvider) {
|
||||
await this.ensureProviderInitialized();
|
||||
}
|
||||
await this.ensureProviderInitialized();
|
||||
const minScore = opts?.minScore ?? this.settings.query.minScore;
|
||||
const maxResults = opts?.maxResults ?? this.settings.query.maxResults;
|
||||
const hybrid = this.settings.query.hybrid;
|
||||
|
||||
Reference in New Issue
Block a user