perf(memory): copy only requested embedding dimensions (#96952) · openclaw/openclaw@4c4396c
ly-wang19
·
2026-06-27
·
via Recent Commits to openclaw:main
File tree
packages/memory-host-sdk/src/host
| Original file line number | Diff line number | Diff line change |
|---|
@@ -36,7 +36,9 @@ function createDeferred<T>() {
|
36 | 36 | return { promise, resolve, reject }; |
37 | 37 | } |
38 | 38 | |
39 | | -function mockLocalEmbeddingRuntime(vector = new Float32Array([2.35, 3.45, 0.63, 4.3])) { |
| 39 | +function mockLocalEmbeddingRuntime( |
| 40 | +vector: ArrayLike<number> = new Float32Array([2.35, 3.45, 0.63, 4.3]), |
| 41 | +) { |
40 | 42 | const disposeContext = vi.fn(); |
41 | 43 | const disposeModel = vi.fn(); |
42 | 44 | const disposeLlama = vi.fn(); |
@@ -111,6 +113,26 @@ describe("local embedding provider", () => {
|
111 | 113 | await expect(provider.embedBatch(["test document"])).resolves.toEqual([[0.6, 0.8]]); |
112 | 114 | }); |
113 | 115 | |
| 116 | +it("does not read local embedding coordinates past outputDimensionality", async () => { |
| 117 | +mockLocalEmbeddingRuntime({ |
| 118 | +length: 3, |
| 119 | +0: 3, |
| 120 | +1: 4, |
| 121 | +get 2(): number { |
| 122 | +throw new Error("tail coordinate should not be read"); |
| 123 | +}, |
| 124 | +}); |
| 125 | +const provider = await createLocalEmbeddingProviderInProcess({ |
| 126 | +config: {} as never, |
| 127 | +provider: "local", |
| 128 | +model: "", |
| 129 | +fallback: "none", |
| 130 | +outputDimensionality: 2, |
| 131 | +}); |
| 132 | + |
| 133 | +await expect(provider.embedQuery("test query")).resolves.toEqual([0.6, 0.8]); |
| 134 | +}); |
| 135 | + |
114 | 136 | it("passes default contextSize (4096) to createEmbeddingContext when not configured", async () => { |
115 | 137 | const runtime = mockLocalEmbeddingRuntime(); |
116 | 138 | |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -31,6 +31,15 @@ export type LocalEmbeddingProviderRuntimeOptions = {
|
31 | 31 | nodeLlamaCppImportUrl?: string; |
32 | 32 | }; |
33 | 33 | |
| 34 | +function copyEmbeddingVector(vector: ArrayLike<number>, maxLength?: number): number[] { |
| 35 | +const length = Math.min(maxLength ?? vector.length, vector.length); |
| 36 | +const values: number[] = []; |
| 37 | +for (let index = 0; index < length; index += 1) { |
| 38 | +values.push(vector[index]); |
| 39 | +} |
| 40 | +return values; |
| 41 | +} |
| 42 | + |
34 | 43 | async function disposeResources( |
35 | 44 | resources: Array<DisposableResource | null | undefined>, |
36 | 45 | ): Promise<void> { |
@@ -144,9 +153,7 @@ export async function createLocalEmbeddingProviderInProcess(
|
144 | 153 | const outputDimensionality = |
145 | 154 | typeof options.outputDimensionality === "number" ? options.outputDimensionality : undefined; |
146 | 155 | const normalize = (vector: ArrayLike<number>): number[] => |
147 | | -sanitizeAndNormalizeEmbedding( |
148 | | -outputDimensionality ? Array.from(vector).slice(0, outputDimensionality) : Array.from(vector), |
149 | | -); |
| 156 | +sanitizeAndNormalizeEmbedding(copyEmbeddingVector(vector, outputDimensionality)); |
150 | 157 | |
151 | 158 | return { |
152 | 159 | id: "local", |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。