mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 21:07:01 -06:00
fix(ollama): honor memory embedding output dimensionality (#94811)
This commit is contained in:
@@ -147,6 +147,25 @@ describe("ollama embedding provider", () => {
|
||||
expect(vector[1]).toBeCloseTo(0.8, 5);
|
||||
});
|
||||
|
||||
it("applies outputDimensionality before normalizing vectors", async () => {
|
||||
mockEmbeddingFetch([3, 4, 12]);
|
||||
|
||||
const { provider } = await createOllamaEmbeddingProvider({
|
||||
config: {} as OpenClawConfig,
|
||||
provider: "ollama",
|
||||
model: "unknown-embedder",
|
||||
fallback: "none",
|
||||
remote: { baseUrl: "http://127.0.0.1:11434" },
|
||||
outputDimensionality: 2,
|
||||
});
|
||||
|
||||
const vector = await provider.embedQuery("hi");
|
||||
|
||||
expect(vector).toHaveLength(2);
|
||||
expect(vector[0]).toBeCloseTo(0.6, 5);
|
||||
expect(vector[1]).toBeCloseTo(0.8, 5);
|
||||
});
|
||||
|
||||
it("marks the configured Ollama origin for managed-proxy direct routing", async () => {
|
||||
const fetchMock = mockEmbeddingFetch([1, 0]);
|
||||
|
||||
@@ -664,6 +683,23 @@ describe("ollama embedding provider", () => {
|
||||
expect(headers?.Authorization).toBeUndefined();
|
||||
});
|
||||
|
||||
it("includes outputDimensionality in the memory embedding cache identity", async () => {
|
||||
const result = await ollamaMemoryEmbeddingProviderAdapter.create({
|
||||
config: {} as OpenClawConfig,
|
||||
provider: "ollama",
|
||||
model: "nomic-embed-text",
|
||||
fallback: "none",
|
||||
remote: { baseUrl: "http://127.0.0.1:11434" },
|
||||
outputDimensionality: 2,
|
||||
});
|
||||
|
||||
expect(result.runtime?.cacheKeyData).toMatchObject({
|
||||
provider: "ollama",
|
||||
model: "nomic-embed-text",
|
||||
outputDimensionality: 2,
|
||||
});
|
||||
});
|
||||
|
||||
it("marks inline memory batches as local-server timeout work", async () => {
|
||||
const result = await ollamaMemoryEmbeddingProviderAdapter.create({
|
||||
config: {} as OpenClawConfig,
|
||||
|
||||
@@ -52,6 +52,7 @@ export type OllamaEmbeddingClient = {
|
||||
headers: Record<string, string>;
|
||||
ssrfPolicy?: SsrFPolicy;
|
||||
model: string;
|
||||
outputDimensionality?: number;
|
||||
embedBatch: (texts: string[]) => Promise<number[][]>;
|
||||
};
|
||||
|
||||
@@ -76,8 +77,10 @@ const QUERY_INSTRUCTION_TEMPLATES = [
|
||||
},
|
||||
] as const;
|
||||
|
||||
function sanitizeAndNormalizeEmbedding(vec: unknown[]): number[] {
|
||||
const sanitized = vec.map((value) => {
|
||||
function sanitizeAndNormalizeEmbedding(vec: unknown[], outputDimensionality?: number): number[] {
|
||||
const selected =
|
||||
typeof outputDimensionality === "number" ? vec.slice(0, outputDimensionality) : vec;
|
||||
const sanitized = selected.map((value) => {
|
||||
if (typeof value !== "number") {
|
||||
throw new Error("Ollama embed response contains a non-number embedding value");
|
||||
}
|
||||
@@ -320,6 +323,7 @@ function resolveOllamaEmbeddingClient(
|
||||
headers,
|
||||
ssrfPolicy: ssrfPolicyFromHttpBaseUrlAllowedOrigin(baseUrl),
|
||||
model,
|
||||
outputDimensionality: options.outputDimensionality,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -364,7 +368,7 @@ export async function createOllamaEmbeddingProvider(
|
||||
if (!Array.isArray(embedding)) {
|
||||
throw new Error("Ollama embed response contains a non-array embedding");
|
||||
}
|
||||
return sanitizeAndNormalizeEmbedding(embedding);
|
||||
return sanitizeAndNormalizeEmbedding(embedding, client.outputDimensionality);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ export const ollamaMemoryEmbeddingProviderAdapter: MemoryEmbeddingProviderAdapte
|
||||
cacheKeyData: {
|
||||
provider: "ollama",
|
||||
model: client.model,
|
||||
outputDimensionality: client.outputDimensionality,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user