mem-os-python 1.6.27__py3-none-any.whl
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.
- mem_os_python-1.6.27.dist-info/METADATA +1032 -0
- mem_os_python-1.6.27.dist-info/RECORD +253 -0
- mem_os_python-1.6.27.dist-info/WHEEL +4 -0
- mem_os_python-1.6.27.dist-info/entry_points.txt +2 -0
- mem_os_python-1.6.27.dist-info/licenses/LICENSE +21 -0
- memos/__init__.py +16 -0
- memos/_js/adapters/anthropic.d.ts +279 -0
- memos/_js/adapters/anthropic.d.ts.map +1 -0
- memos/_js/adapters/anthropic.js +348 -0
- memos/_js/adapters/anthropic.js.map +1 -0
- memos/_js/adapters/base.d.ts +10 -0
- memos/_js/adapters/base.d.ts.map +1 -0
- memos/_js/adapters/base.js +2 -0
- memos/_js/adapters/base.js.map +1 -0
- memos/_js/adapters/openai.d.ts +264 -0
- memos/_js/adapters/openai.d.ts.map +1 -0
- memos/_js/adapters/openai.js +342 -0
- memos/_js/adapters/openai.js.map +1 -0
- memos/_js/apps/explorer.d.ts +244 -0
- memos/_js/apps/explorer.d.ts.map +1 -0
- memos/_js/apps/explorer.js +738 -0
- memos/_js/apps/explorer.js.map +1 -0
- memos/_js/citations.d.ts +65 -0
- memos/_js/citations.d.ts.map +1 -0
- memos/_js/citations.js +143 -0
- memos/_js/citations.js.map +1 -0
- memos/_js/cli-browse.d.ts +3 -0
- memos/_js/cli-browse.d.ts.map +1 -0
- memos/_js/cli-browse.js +129 -0
- memos/_js/cli-browse.js.map +1 -0
- memos/_js/cli-completion.d.ts +31 -0
- memos/_js/cli-completion.d.ts.map +1 -0
- memos/_js/cli-completion.js +340 -0
- memos/_js/cli-completion.js.map +1 -0
- memos/_js/cli-help.d.ts +18 -0
- memos/_js/cli-help.d.ts.map +1 -0
- memos/_js/cli-help.js +357 -0
- memos/_js/cli-help.js.map +1 -0
- memos/_js/cli.d.ts +28 -0
- memos/_js/cli.d.ts.map +1 -0
- memos/_js/cli.js +2880 -0
- memos/_js/cli.js.map +1 -0
- memos/_js/compression.d.ts +25 -0
- memos/_js/compression.d.ts.map +1 -0
- memos/_js/compression.js +319 -0
- memos/_js/compression.js.map +1 -0
- memos/_js/confidence-machine.d.ts +99 -0
- memos/_js/confidence-machine.d.ts.map +1 -0
- memos/_js/confidence-machine.js +222 -0
- memos/_js/confidence-machine.js.map +1 -0
- memos/_js/context-pack.d.ts +506 -0
- memos/_js/context-pack.d.ts.map +1 -0
- memos/_js/context-pack.js +1435 -0
- memos/_js/context-pack.js.map +1 -0
- memos/_js/contradictions.d.ts +160 -0
- memos/_js/contradictions.d.ts.map +1 -0
- memos/_js/contradictions.js +255 -0
- memos/_js/contradictions.js.map +1 -0
- memos/_js/dashboard.d.ts +30 -0
- memos/_js/dashboard.d.ts.map +1 -0
- memos/_js/dashboard.js +302 -0
- memos/_js/dashboard.js.map +1 -0
- memos/_js/ebbinghaus.d.ts +29 -0
- memos/_js/ebbinghaus.d.ts.map +1 -0
- memos/_js/ebbinghaus.js +32 -0
- memos/_js/ebbinghaus.js.map +1 -0
- memos/_js/embedding-queue.d.ts +190 -0
- memos/_js/embedding-queue.d.ts.map +1 -0
- memos/_js/embedding-queue.js +316 -0
- memos/_js/embedding-queue.js.map +1 -0
- memos/_js/embeddings.d.ts +187 -0
- memos/_js/embeddings.d.ts.map +1 -0
- memos/_js/embeddings.js +633 -0
- memos/_js/embeddings.js.map +1 -0
- memos/_js/entity-extraction.d.ts +54 -0
- memos/_js/entity-extraction.d.ts.map +1 -0
- memos/_js/entity-extraction.js +325 -0
- memos/_js/entity-extraction.js.map +1 -0
- memos/_js/entity-index.d.ts +93 -0
- memos/_js/entity-index.d.ts.map +1 -0
- memos/_js/entity-index.js +165 -0
- memos/_js/entity-index.js.map +1 -0
- memos/_js/event-memory.d.ts +147 -0
- memos/_js/event-memory.d.ts.map +1 -0
- memos/_js/event-memory.js +290 -0
- memos/_js/event-memory.js.map +1 -0
- memos/_js/external-import.d.ts +98 -0
- memos/_js/external-import.d.ts.map +1 -0
- memos/_js/external-import.js +669 -0
- memos/_js/external-import.js.map +1 -0
- memos/_js/fidelity.d.ts +367 -0
- memos/_js/fidelity.d.ts.map +1 -0
- memos/_js/fidelity.js +911 -0
- memos/_js/fidelity.js.map +1 -0
- memos/_js/graph-expansion.d.ts +119 -0
- memos/_js/graph-expansion.d.ts.map +1 -0
- memos/_js/graph-expansion.js +213 -0
- memos/_js/graph-expansion.js.map +1 -0
- memos/_js/graph-mermaid.d.ts +13 -0
- memos/_js/graph-mermaid.d.ts.map +1 -0
- memos/_js/graph-mermaid.js +32 -0
- memos/_js/graph-mermaid.js.map +1 -0
- memos/_js/graph.d.ts +170 -0
- memos/_js/graph.d.ts.map +1 -0
- memos/_js/graph.js +482 -0
- memos/_js/graph.js.map +1 -0
- memos/_js/harness.d.ts +63 -0
- memos/_js/harness.d.ts.map +1 -0
- memos/_js/harness.js +93 -0
- memos/_js/harness.js.map +1 -0
- memos/_js/importance.d.ts +118 -0
- memos/_js/importance.d.ts.map +1 -0
- memos/_js/importance.js +144 -0
- memos/_js/importance.js.map +1 -0
- memos/_js/index.d.ts +51 -0
- memos/_js/index.d.ts.map +1 -0
- memos/_js/index.js +53 -0
- memos/_js/index.js.map +1 -0
- memos/_js/mcp.d.ts +58 -0
- memos/_js/mcp.d.ts.map +1 -0
- memos/_js/mcp.js +1853 -0
- memos/_js/mcp.js.map +1 -0
- memos/_js/memory.d.ts +1762 -0
- memos/_js/memory.d.ts.map +1 -0
- memos/_js/memory.js +6283 -0
- memos/_js/memory.js.map +1 -0
- memos/_js/procedural.d.ts +74 -0
- memos/_js/procedural.d.ts.map +1 -0
- memos/_js/procedural.js +125 -0
- memos/_js/procedural.js.map +1 -0
- memos/_js/project-config.d.ts +68 -0
- memos/_js/project-config.d.ts.map +1 -0
- memos/_js/project-config.js +59 -0
- memos/_js/project-config.js.map +1 -0
- memos/_js/proof-of-forgetting.d.ts +57 -0
- memos/_js/proof-of-forgetting.d.ts.map +1 -0
- memos/_js/proof-of-forgetting.js +80 -0
- memos/_js/proof-of-forgetting.js.map +1 -0
- memos/_js/provenance.d.ts +122 -0
- memos/_js/provenance.d.ts.map +1 -0
- memos/_js/provenance.js +182 -0
- memos/_js/provenance.js.map +1 -0
- memos/_js/quarantine-commands.d.ts +23 -0
- memos/_js/quarantine-commands.d.ts.map +1 -0
- memos/_js/quarantine-commands.js +42 -0
- memos/_js/quarantine-commands.js.map +1 -0
- memos/_js/quarantine.d.ts +120 -0
- memos/_js/quarantine.d.ts.map +1 -0
- memos/_js/quarantine.js +873 -0
- memos/_js/quarantine.js.map +1 -0
- memos/_js/redact.d.ts +12 -0
- memos/_js/redact.d.ts.map +1 -0
- memos/_js/redact.js +26 -0
- memos/_js/redact.js.map +1 -0
- memos/_js/repl.d.ts +57 -0
- memos/_js/repl.d.ts.map +1 -0
- memos/_js/repl.js +295 -0
- memos/_js/repl.js.map +1 -0
- memos/_js/rerank-local.d.ts +61 -0
- memos/_js/rerank-local.d.ts.map +1 -0
- memos/_js/rerank-local.js +210 -0
- memos/_js/rerank-local.js.map +1 -0
- memos/_js/retain-filter.d.ts +98 -0
- memos/_js/retain-filter.d.ts.map +1 -0
- memos/_js/retain-filter.js +232 -0
- memos/_js/retain-filter.js.map +1 -0
- memos/_js/retrieval.d.ts +265 -0
- memos/_js/retrieval.d.ts.map +1 -0
- memos/_js/retrieval.js +1018 -0
- memos/_js/retrieval.js.map +1 -0
- memos/_js/revert.d.ts +77 -0
- memos/_js/revert.d.ts.map +1 -0
- memos/_js/revert.js +252 -0
- memos/_js/revert.js.map +1 -0
- memos/_js/scope.d.ts +30 -0
- memos/_js/scope.d.ts.map +1 -0
- memos/_js/scope.js +71 -0
- memos/_js/scope.js.map +1 -0
- memos/_js/semantic-screen.d.ts +152 -0
- memos/_js/semantic-screen.d.ts.map +1 -0
- memos/_js/semantic-screen.js +290 -0
- memos/_js/semantic-screen.js.map +1 -0
- memos/_js/session-hooks.d.ts +127 -0
- memos/_js/session-hooks.d.ts.map +1 -0
- memos/_js/session-hooks.js +482 -0
- memos/_js/session-hooks.js.map +1 -0
- memos/_js/storage/sqlite.d.ts +427 -0
- memos/_js/storage/sqlite.d.ts.map +1 -0
- memos/_js/storage/sqlite.js +2428 -0
- memos/_js/storage/sqlite.js.map +1 -0
- memos/_js/sync.d.ts +213 -0
- memos/_js/sync.d.ts.map +1 -0
- memos/_js/sync.js +389 -0
- memos/_js/sync.js.map +1 -0
- memos/_js/tamper-log.d.ts +98 -0
- memos/_js/tamper-log.d.ts.map +1 -0
- memos/_js/tamper-log.js +327 -0
- memos/_js/tamper-log.js.map +1 -0
- memos/_js/temporal.d.ts +92 -0
- memos/_js/temporal.d.ts.map +1 -0
- memos/_js/temporal.js +536 -0
- memos/_js/temporal.js.map +1 -0
- memos/_js/time-travel.d.ts +38 -0
- memos/_js/time-travel.d.ts.map +1 -0
- memos/_js/time-travel.js +46 -0
- memos/_js/time-travel.js.map +1 -0
- memos/_js/timestamp-format.d.ts +18 -0
- memos/_js/timestamp-format.d.ts.map +1 -0
- memos/_js/timestamp-format.js +52 -0
- memos/_js/timestamp-format.js.map +1 -0
- memos/_js/triple-extraction.d.ts +31 -0
- memos/_js/triple-extraction.d.ts.map +1 -0
- memos/_js/triple-extraction.js +116 -0
- memos/_js/triple-extraction.js.map +1 -0
- memos/_js/types.d.ts +2474 -0
- memos/_js/types.d.ts.map +1 -0
- memos/_js/types.js +20 -0
- memos/_js/types.js.map +1 -0
- memos/_js/updater.d.ts +95 -0
- memos/_js/updater.d.ts.map +1 -0
- memos/_js/updater.js +268 -0
- memos/_js/updater.js.map +1 -0
- memos/_js/version.d.ts +17 -0
- memos/_js/version.d.ts.map +1 -0
- memos/_js/version.js +34 -0
- memos/_js/version.js.map +1 -0
- memos/_js/vision/clip-query-cache.d.ts +58 -0
- memos/_js/vision/clip-query-cache.d.ts.map +1 -0
- memos/_js/vision/clip-query-cache.js +79 -0
- memos/_js/vision/clip-query-cache.js.map +1 -0
- memos/_js/vision/clip.d.ts +113 -0
- memos/_js/vision/clip.d.ts.map +1 -0
- memos/_js/vision/clip.js +224 -0
- memos/_js/vision/clip.js.map +1 -0
- memos/_js/vision/fake-clip.d.ts +55 -0
- memos/_js/vision/fake-clip.d.ts.map +1 -0
- memos/_js/vision/fake-clip.js +122 -0
- memos/_js/vision/fake-clip.js.map +1 -0
- memos/_js/vision/index.d.ts +15 -0
- memos/_js/vision/index.d.ts.map +1 -0
- memos/_js/vision/index.js +13 -0
- memos/_js/vision/index.js.map +1 -0
- memos/_js/vision/store.d.ts +137 -0
- memos/_js/vision/store.d.ts.map +1 -0
- memos/_js/vision/store.js +383 -0
- memos/_js/vision/store.js.map +1 -0
- memos/adapters/__init__.py +0 -0
- memos/adapters/crewai.py +385 -0
- memos/adapters/langchain.py +301 -0
- memos/adapters/ollama.py +396 -0
- memos/server/__init__.py +0 -0
- memos/server/main.py +547 -0
- memos/server/routes.py +360 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded LRU cache for CLIP query vectors.
|
|
3
|
+
*
|
|
4
|
+
* CLIP text-encoding is cheap (~10–30 ms on CPU for a 20-token query)
|
|
5
|
+
* but not free, and conversations repeat queries (the same query fans
|
|
6
|
+
* out across multiple retrieval legs). This mirrors the text path's
|
|
7
|
+
* `queryEmbeddingCache` LRU, but it is a SEPARATE cache by design:
|
|
8
|
+
*
|
|
9
|
+
* - `embedQueryCached` is keyed `provider.id:model:query` for the TEXT
|
|
10
|
+
* provider. CLIP text encoding is a different model in a different
|
|
11
|
+
* vector space and must not share that LRU — a shared LRU would let a
|
|
12
|
+
* CLIP query vector be served to a text-semantic query (or vice
|
|
13
|
+
* versa), which is the same silent-corruption class as the
|
|
14
|
+
* vectorCache namespace bug.
|
|
15
|
+
* - The key here is `clip:<model>:<query>`, namespaced away from every
|
|
16
|
+
* text cache key.
|
|
17
|
+
*
|
|
18
|
+
* The cache is bounded (default 512 entries ≈ 512 × 512 floats ≈ 1 MB)
|
|
19
|
+
* with FIFO eviction on insert and LRU touch on hit, matching the text
|
|
20
|
+
* cache's semantics.
|
|
21
|
+
*
|
|
22
|
+
* @module @memos/vision/clip-query-cache
|
|
23
|
+
*/
|
|
24
|
+
/** Default bound on cached CLIP query vectors. */
|
|
25
|
+
export const DEFAULT_CLIP_QUERY_CACHE_MAX = 512;
|
|
26
|
+
/**
|
|
27
|
+
* A bounded LRU cache for CLIP query vectors.
|
|
28
|
+
*
|
|
29
|
+
* Usage:
|
|
30
|
+
* ```ts
|
|
31
|
+
* const cache = new ClipQueryCache();
|
|
32
|
+
* const v = await cache.get("a red error banner", clipProvider);
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export class ClipQueryCache {
|
|
36
|
+
entries = new Map();
|
|
37
|
+
max;
|
|
38
|
+
constructor(max = DEFAULT_CLIP_QUERY_CACHE_MAX) {
|
|
39
|
+
this.max = Math.max(1, max);
|
|
40
|
+
}
|
|
41
|
+
/** Number of cached vectors. */
|
|
42
|
+
get size() {
|
|
43
|
+
return this.entries.size;
|
|
44
|
+
}
|
|
45
|
+
/** Drop every cached vector. */
|
|
46
|
+
clear() {
|
|
47
|
+
this.entries.clear();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Encode `query` with `provider.embedImageText`, memoized under
|
|
51
|
+
* `clip:<model>:<query>`.
|
|
52
|
+
*
|
|
53
|
+
* Returns null when the provider cannot encode text (no
|
|
54
|
+
* `embedImageText`) — the caller degrades to the caption leg. A
|
|
55
|
+
* provider that THROWS propagates the error: caching a failure would
|
|
56
|
+
* pin it, and a failed encode is a real signal the caller must see.
|
|
57
|
+
*/
|
|
58
|
+
async get(query, provider) {
|
|
59
|
+
if (!provider.embedImageText)
|
|
60
|
+
return null;
|
|
61
|
+
const key = `clip:${provider.model}:${query}`;
|
|
62
|
+
const hit = this.entries.get(key);
|
|
63
|
+
if (hit) {
|
|
64
|
+
// LRU touch: re-insert to mark most-recently-used.
|
|
65
|
+
this.entries.delete(key);
|
|
66
|
+
this.entries.set(key, hit);
|
|
67
|
+
return hit;
|
|
68
|
+
}
|
|
69
|
+
const vector = await provider.embedImageText(query);
|
|
70
|
+
this.entries.set(key, vector);
|
|
71
|
+
if (this.entries.size > this.max) {
|
|
72
|
+
const oldest = this.entries.keys().next();
|
|
73
|
+
if (!oldest.done)
|
|
74
|
+
this.entries.delete(oldest.value);
|
|
75
|
+
}
|
|
76
|
+
return vector;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=clip-query-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clip-query-cache.js","sourceRoot":"","sources":["../../src/vision/clip-query-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,kDAAkD;AAClD,MAAM,CAAC,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAEhD;;;;;;;;GAQG;AACH,MAAM,OAAO,cAAc;IACR,OAAO,GAAG,IAAI,GAAG,EAA2B,CAAC;IAC7C,GAAG,CAAS;IAE7B,YAAY,GAAG,GAAG,4BAA4B;QAC5C,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,gCAAgC;IAChC,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED,gCAAgC;IAChC,KAAK;QACH,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,GAAG,CACP,KAAa,EACb,QAGC;QAED,IAAI,CAAC,QAAQ,CAAC,cAAc;YAAE,OAAO,IAAI,CAAC;QAC1C,MAAM,GAAG,GAAG,QAAQ,QAAQ,CAAC,KAAK,IAAI,KAAK,EAAE,CAAC;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,GAAG,EAAE,CAAC;YACR,mDAAmD;YACnD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAC3B,OAAO,GAAG,CAAC;QACb,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QACpD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC9B,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YAC1C,IAAI,CAAC,MAAM,CAAC,IAAI;gBAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLIP image-embedding provider (Track B of image memory).
|
|
3
|
+
*
|
|
4
|
+
* Encodes images with `Xenova/clip-vit-base-patch32` via
|
|
5
|
+
* `@huggingface/transformers` (the same optional peer dependency the text
|
|
6
|
+
* FastEmbed provider uses), entirely in-process — no API key, no network
|
|
7
|
+
* beyond the first model download (~350 MB, cached on disk like the text
|
|
8
|
+
* model).
|
|
9
|
+
*
|
|
10
|
+
* Design constraints, all deliberate:
|
|
11
|
+
*
|
|
12
|
+
* 1. **Lazy load.** The pipeline is constructed on the FIRST embed call,
|
|
13
|
+
* not in the constructor — constructing a MemOS instance must never
|
|
14
|
+
* pay a model download. Mirrors `FastEmbedEmbeddingProvider.resolve()`.
|
|
15
|
+
* 2. **Fail soft.** If the transformers package is missing (or the model
|
|
16
|
+
* can't be built), `embedImage` throws a typed {@link ClipUnavailableError}
|
|
17
|
+
* so the write path can record `clipStatus: "failed"` — but the
|
|
18
|
+
* provider NEVER silently substitutes a text vector for an image
|
|
19
|
+
* vector. That substitution is the one failure mode that corrupts
|
|
20
|
+
* retrieval invisibly.
|
|
21
|
+
* 3. **Separate contract from EmbeddingProvider.** CLIP's 512-d space is
|
|
22
|
+
* not comparable with bge's 384-d text space; the two vector tables
|
|
23
|
+
* exist precisely so they can never be mixed. The class satisfies
|
|
24
|
+
* {@link EmbedImageProvider} so it can also be dropped into
|
|
25
|
+
* `vision.clip.embedImage` directly.
|
|
26
|
+
* 4. **Text side.** `embedImageText` encodes a query through CLIP's text
|
|
27
|
+
* encoder. Note CLIP's documented limitation: its text encoder is
|
|
28
|
+
* trained on short captions (<77 tokens) and is a weak text retriever
|
|
29
|
+
* — it is excellent at cross-modal matching ("a cat on a couch" →
|
|
30
|
+
* that photo), which is exactly what the image leg uses it for.
|
|
31
|
+
*
|
|
32
|
+
* @module @memos/vision/clip
|
|
33
|
+
*/
|
|
34
|
+
import type { EmbedImageProvider, EmbeddingVector } from "../types.js";
|
|
35
|
+
/** Default CLIP model — ViT-B/32, 512-d image space. */
|
|
36
|
+
export declare const DEFAULT_CLIP_MODEL = "Xenova/clip-vit-base-patch32";
|
|
37
|
+
/** Default CLIP dimensionality. */
|
|
38
|
+
export declare const DEFAULT_CLIP_DIMENSIONS = 512;
|
|
39
|
+
/**
|
|
40
|
+
* Thrown when the CLIP pipeline could not be constructed (missing
|
|
41
|
+
* optional dependency, model load failure, or no callable interface).
|
|
42
|
+
* The write path catches this and records `clipStatus: "failed"`;
|
|
43
|
+
* nothing ever falls back to a text vector.
|
|
44
|
+
*/
|
|
45
|
+
export declare class ClipUnavailableError extends Error {
|
|
46
|
+
readonly cause?: unknown;
|
|
47
|
+
constructor(message: string, cause?: unknown);
|
|
48
|
+
}
|
|
49
|
+
export interface ClipEmbeddingProviderOptions {
|
|
50
|
+
model?: string;
|
|
51
|
+
dimensions?: number;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* CLIP image encoder. Lazy, optional-dependency-tolerant, and separate
|
|
55
|
+
* from the text embedding pipeline by construction.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* const clip = new ClipEmbeddingProvider();
|
|
60
|
+
* const vector = await clip.embedImage(fs.readFileSync("cat.png")); // 512-d
|
|
61
|
+
* const query = await clip.embedImageText("a cat on a couch"); // 512-d
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export declare class ClipEmbeddingProvider implements EmbedImageProvider {
|
|
65
|
+
readonly id = "clip";
|
|
66
|
+
readonly model: string;
|
|
67
|
+
readonly dimensions: number;
|
|
68
|
+
private extractor;
|
|
69
|
+
private resolveAttempted;
|
|
70
|
+
/** Why the pipeline could not be built, or null when it loaded fine. */
|
|
71
|
+
private failureReason;
|
|
72
|
+
constructor(options?: ClipEmbeddingProviderOptions);
|
|
73
|
+
/**
|
|
74
|
+
* Why the CLIP pipeline is unavailable, or null when it loaded (or has
|
|
75
|
+
* not been probed yet). The write path records this in
|
|
76
|
+
* `metadata.clip.error` so a degraded install is diagnosable.
|
|
77
|
+
*/
|
|
78
|
+
get fallbackReason(): string | null;
|
|
79
|
+
/** True once the pipeline has been successfully constructed. */
|
|
80
|
+
get available(): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Lazily resolve the transformers pipeline. Tries
|
|
83
|
+
* `@huggingface/transformers` first, then the legacy
|
|
84
|
+
* `@xenova/transformers`, exactly like the text provider's fallback
|
|
85
|
+
* chain. Resolved at most once — a failure is sticky so repeated
|
|
86
|
+
* embed calls fail fast instead of retrying a doomed model load.
|
|
87
|
+
*/
|
|
88
|
+
private resolve;
|
|
89
|
+
/** Reference to the lazily-resolved `RawImage`, or null. */
|
|
90
|
+
private resolveRawImage;
|
|
91
|
+
/**
|
|
92
|
+
* Encode image bytes (or a path/URL) into the CLIP image space.
|
|
93
|
+
*
|
|
94
|
+
* A `Buffer` is wrapped in a `Blob` because `RawImage.read` accepts
|
|
95
|
+
* `RawImage | string | URL | Blob | canvas` natively — a raw Node
|
|
96
|
+
* Buffer is not one of those.
|
|
97
|
+
*
|
|
98
|
+
* @throws {@link ClipUnavailableError} when the pipeline is missing.
|
|
99
|
+
*/
|
|
100
|
+
embedImage(image: Buffer | string): Promise<EmbeddingVector>;
|
|
101
|
+
/**
|
|
102
|
+
* Encode a text query into the CLIP image space, so a text→image
|
|
103
|
+
* cosine query works. Uses the `feature-extraction` pipeline (CLIP's
|
|
104
|
+
* text encoder).
|
|
105
|
+
*
|
|
106
|
+
* When unavailable, the caller should degrade to the caption leg
|
|
107
|
+
* (Track A) rather than fail the query.
|
|
108
|
+
*
|
|
109
|
+
* @throws {@link ClipUnavailableError} when the text pipeline is missing.
|
|
110
|
+
*/
|
|
111
|
+
embedImageText(query: string): Promise<EmbeddingVector>;
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=clip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clip.d.ts","sourceRoot":"","sources":["../../src/vision/clip.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEvE,wDAAwD;AACxD,eAAO,MAAM,kBAAkB,iCAAiC,CAAC;AAEjE,mCAAmC;AACnC,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAE3C;;;;;GAKG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAG3C,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO;IAF1B,YACE,OAAO,EAAE,MAAM,EACN,KAAK,CAAC,EAAE,OAAO,EAIzB;CACF;AAoBD,MAAM,WAAW,4BAA4B;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,qBAAsB,YAAW,kBAAkB;IAC9D,QAAQ,CAAC,EAAE,UAAU;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,OAAO,CAAC,SAAS,CAAwC;IACzD,OAAO,CAAC,gBAAgB,CAAS;IACjC,wEAAwE;IACxE,OAAO,CAAC,aAAa,CAAuB;IAE5C,YAAY,OAAO,GAAE,4BAAiC,EAGrD;IAED;;;;OAIG;IACH,IAAI,cAAc,IAAI,MAAM,GAAG,IAAI,CAElC;IAED,gEAAgE;IAChE,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED;;;;;;OAMG;YACW,OAAO;IA2DrB,4DAA4D;YAC9C,eAAe;IAa7B;;;;;;;;OAQG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CA2DjE;IAED;;;;;;;;;OASG;IACG,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CA6B5D;CACF"}
|
memos/_js/vision/clip.js
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLIP image-embedding provider (Track B of image memory).
|
|
3
|
+
*
|
|
4
|
+
* Encodes images with `Xenova/clip-vit-base-patch32` via
|
|
5
|
+
* `@huggingface/transformers` (the same optional peer dependency the text
|
|
6
|
+
* FastEmbed provider uses), entirely in-process — no API key, no network
|
|
7
|
+
* beyond the first model download (~350 MB, cached on disk like the text
|
|
8
|
+
* model).
|
|
9
|
+
*
|
|
10
|
+
* Design constraints, all deliberate:
|
|
11
|
+
*
|
|
12
|
+
* 1. **Lazy load.** The pipeline is constructed on the FIRST embed call,
|
|
13
|
+
* not in the constructor — constructing a MemOS instance must never
|
|
14
|
+
* pay a model download. Mirrors `FastEmbedEmbeddingProvider.resolve()`.
|
|
15
|
+
* 2. **Fail soft.** If the transformers package is missing (or the model
|
|
16
|
+
* can't be built), `embedImage` throws a typed {@link ClipUnavailableError}
|
|
17
|
+
* so the write path can record `clipStatus: "failed"` — but the
|
|
18
|
+
* provider NEVER silently substitutes a text vector for an image
|
|
19
|
+
* vector. That substitution is the one failure mode that corrupts
|
|
20
|
+
* retrieval invisibly.
|
|
21
|
+
* 3. **Separate contract from EmbeddingProvider.** CLIP's 512-d space is
|
|
22
|
+
* not comparable with bge's 384-d text space; the two vector tables
|
|
23
|
+
* exist precisely so they can never be mixed. The class satisfies
|
|
24
|
+
* {@link EmbedImageProvider} so it can also be dropped into
|
|
25
|
+
* `vision.clip.embedImage` directly.
|
|
26
|
+
* 4. **Text side.** `embedImageText` encodes a query through CLIP's text
|
|
27
|
+
* encoder. Note CLIP's documented limitation: its text encoder is
|
|
28
|
+
* trained on short captions (<77 tokens) and is a weak text retriever
|
|
29
|
+
* — it is excellent at cross-modal matching ("a cat on a couch" →
|
|
30
|
+
* that photo), which is exactly what the image leg uses it for.
|
|
31
|
+
*
|
|
32
|
+
* @module @memos/vision/clip
|
|
33
|
+
*/
|
|
34
|
+
import { normalizeVector } from "../embeddings.js";
|
|
35
|
+
/** Default CLIP model — ViT-B/32, 512-d image space. */
|
|
36
|
+
export const DEFAULT_CLIP_MODEL = "Xenova/clip-vit-base-patch32";
|
|
37
|
+
/** Default CLIP dimensionality. */
|
|
38
|
+
export const DEFAULT_CLIP_DIMENSIONS = 512;
|
|
39
|
+
/**
|
|
40
|
+
* Thrown when the CLIP pipeline could not be constructed (missing
|
|
41
|
+
* optional dependency, model load failure, or no callable interface).
|
|
42
|
+
* The write path catches this and records `clipStatus: "failed"`;
|
|
43
|
+
* nothing ever falls back to a text vector.
|
|
44
|
+
*/
|
|
45
|
+
export class ClipUnavailableError extends Error {
|
|
46
|
+
cause;
|
|
47
|
+
constructor(message, cause) {
|
|
48
|
+
super(message);
|
|
49
|
+
this.cause = cause;
|
|
50
|
+
this.name = "ClipUnavailableError";
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* CLIP image encoder. Lazy, optional-dependency-tolerant, and separate
|
|
55
|
+
* from the text embedding pipeline by construction.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* const clip = new ClipEmbeddingProvider();
|
|
60
|
+
* const vector = await clip.embedImage(fs.readFileSync("cat.png")); // 512-d
|
|
61
|
+
* const query = await clip.embedImageText("a cat on a couch"); // 512-d
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export class ClipEmbeddingProvider {
|
|
65
|
+
id = "clip";
|
|
66
|
+
model;
|
|
67
|
+
dimensions;
|
|
68
|
+
extractor = null;
|
|
69
|
+
resolveAttempted = false;
|
|
70
|
+
/** Why the pipeline could not be built, or null when it loaded fine. */
|
|
71
|
+
failureReason = null;
|
|
72
|
+
constructor(options = {}) {
|
|
73
|
+
this.model = options.model ?? DEFAULT_CLIP_MODEL;
|
|
74
|
+
this.dimensions = options.dimensions ?? DEFAULT_CLIP_DIMENSIONS;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Why the CLIP pipeline is unavailable, or null when it loaded (or has
|
|
78
|
+
* not been probed yet). The write path records this in
|
|
79
|
+
* `metadata.clip.error` so a degraded install is diagnosable.
|
|
80
|
+
*/
|
|
81
|
+
get fallbackReason() {
|
|
82
|
+
return this.failureReason;
|
|
83
|
+
}
|
|
84
|
+
/** True once the pipeline has been successfully constructed. */
|
|
85
|
+
get available() {
|
|
86
|
+
return this.extractor !== null;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Lazily resolve the transformers pipeline. Tries
|
|
90
|
+
* `@huggingface/transformers` first, then the legacy
|
|
91
|
+
* `@xenova/transformers`, exactly like the text provider's fallback
|
|
92
|
+
* chain. Resolved at most once — a failure is sticky so repeated
|
|
93
|
+
* embed calls fail fast instead of retrying a doomed model load.
|
|
94
|
+
*/
|
|
95
|
+
async resolve() {
|
|
96
|
+
if (this.resolveAttempted)
|
|
97
|
+
return;
|
|
98
|
+
this.resolveAttempted = true;
|
|
99
|
+
try {
|
|
100
|
+
const mod = (await import("@huggingface/transformers").catch(() => null));
|
|
101
|
+
const legacyMod = mod
|
|
102
|
+
? null
|
|
103
|
+
: (await import("@xenova/transformers").catch(() => null));
|
|
104
|
+
const resolved = mod ?? legacyMod;
|
|
105
|
+
if (!resolved || typeof resolved.pipeline !== "function") {
|
|
106
|
+
this.failureReason =
|
|
107
|
+
"neither @huggingface/transformers nor @xenova/transformers is installed";
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const pipeline = await resolved.pipeline("image-feature-extraction", this.model);
|
|
111
|
+
// transformers.js v3+/v4 pipelines are Callable instances (the
|
|
112
|
+
// class is wrapped in a function closure); older shapes exposed
|
|
113
|
+
// `._call`. Normalize both behind one callable.
|
|
114
|
+
const callable = typeof pipeline === "function"
|
|
115
|
+
? pipeline
|
|
116
|
+
: (pipeline._call ??
|
|
117
|
+
pipeline.feature ??
|
|
118
|
+
null);
|
|
119
|
+
if (!callable) {
|
|
120
|
+
this.failureReason = `pipeline for model "${this.model}" exposed no callable image-feature-extraction interface`;
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
this.extractor = callable;
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
this.failureReason = `CLIP pipeline construction failed for model "${this.model}": ${String(err).substring(0, 200)}`;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/** Reference to the lazily-resolved `RawImage`, or null. */
|
|
130
|
+
async resolveRawImage() {
|
|
131
|
+
const mod = (await import("@huggingface/transformers").catch(() => null));
|
|
132
|
+
if (mod?.RawImage)
|
|
133
|
+
return mod.RawImage;
|
|
134
|
+
const legacy = (await import("@xenova/transformers").catch(() => null));
|
|
135
|
+
return legacy?.RawImage ?? null;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Encode image bytes (or a path/URL) into the CLIP image space.
|
|
139
|
+
*
|
|
140
|
+
* A `Buffer` is wrapped in a `Blob` because `RawImage.read` accepts
|
|
141
|
+
* `RawImage | string | URL | Blob | canvas` natively — a raw Node
|
|
142
|
+
* Buffer is not one of those.
|
|
143
|
+
*
|
|
144
|
+
* @throws {@link ClipUnavailableError} when the pipeline is missing.
|
|
145
|
+
*/
|
|
146
|
+
async embedImage(image) {
|
|
147
|
+
await this.resolve();
|
|
148
|
+
if (!this.extractor) {
|
|
149
|
+
throw new ClipUnavailableError(`CLIP image encoding unavailable: ${this.failureReason ?? "pipeline not resolved"}`);
|
|
150
|
+
}
|
|
151
|
+
let decoded = image;
|
|
152
|
+
if (typeof image !== "string") {
|
|
153
|
+
// Node Buffer → Blob. No mime known at this layer; the decoder
|
|
154
|
+
// sniffs the format from the header, same as a file path would be.
|
|
155
|
+
const blob = new Blob([new Uint8Array(image)]);
|
|
156
|
+
const RawImage = await this.resolveRawImage();
|
|
157
|
+
if (RawImage) {
|
|
158
|
+
try {
|
|
159
|
+
decoded = await RawImage.read(blob);
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
throw new ClipUnavailableError(`CLIP image decode failed for model "${this.model}": ${String(err).substring(0, 200)}`, err);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
decoded = blob;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
let out;
|
|
170
|
+
try {
|
|
171
|
+
out = await this.extractor(decoded);
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
// An encode failure (unsupported/corrupt image bytes, ONNX
|
|
175
|
+
// runtime error) is a REAL failure the write path must see —
|
|
176
|
+
// wrap it so callers catch one typed error, never a bare Error
|
|
177
|
+
// they might mistake for something else. The provider still
|
|
178
|
+
// never substitutes a text vector.
|
|
179
|
+
throw new ClipUnavailableError(`CLIP image encoding failed for model "${this.model}": ${String(err).substring(0, 200)}`, err);
|
|
180
|
+
}
|
|
181
|
+
if (!out || !out.data || out.data.length === 0) {
|
|
182
|
+
throw new ClipUnavailableError(`CLIP image encoding produced an empty tensor for model "${this.model}"`);
|
|
183
|
+
}
|
|
184
|
+
if (out.data.length !== this.dimensions) {
|
|
185
|
+
// A projection mismatch means the configured dimensions no longer
|
|
186
|
+
// describe the model's output space — refuse rather than persist
|
|
187
|
+
// vectors that querySimilarImages would filter out or, worse,
|
|
188
|
+
// score against the wrong space.
|
|
189
|
+
throw new ClipUnavailableError(`CLIP model "${this.model}" produced ${out.data.length} dims, expected ${this.dimensions}`);
|
|
190
|
+
}
|
|
191
|
+
return normalizeVector(Array.from(out.data));
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Encode a text query into the CLIP image space, so a text→image
|
|
195
|
+
* cosine query works. Uses the `feature-extraction` pipeline (CLIP's
|
|
196
|
+
* text encoder).
|
|
197
|
+
*
|
|
198
|
+
* When unavailable, the caller should degrade to the caption leg
|
|
199
|
+
* (Track A) rather than fail the query.
|
|
200
|
+
*
|
|
201
|
+
* @throws {@link ClipUnavailableError} when the text pipeline is missing.
|
|
202
|
+
*/
|
|
203
|
+
async embedImageText(query) {
|
|
204
|
+
await this.resolve();
|
|
205
|
+
if (!this.extractor) {
|
|
206
|
+
throw new ClipUnavailableError(`CLIP text encoding unavailable: ${this.failureReason ?? "pipeline not resolved"}`);
|
|
207
|
+
}
|
|
208
|
+
let out;
|
|
209
|
+
try {
|
|
210
|
+
out = await this.extractor(query);
|
|
211
|
+
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
throw new ClipUnavailableError(`CLIP text encoding failed for model "${this.model}": ${String(err).substring(0, 200)}`, err);
|
|
214
|
+
}
|
|
215
|
+
if (!out || !out.data || out.data.length === 0) {
|
|
216
|
+
throw new ClipUnavailableError(`CLIP text encoding produced an empty tensor for model "${this.model}"`);
|
|
217
|
+
}
|
|
218
|
+
if (out.data.length !== this.dimensions) {
|
|
219
|
+
throw new ClipUnavailableError(`CLIP text model "${this.model}" produced ${out.data.length} dims, expected ${this.dimensions}`);
|
|
220
|
+
}
|
|
221
|
+
return normalizeVector(Array.from(out.data));
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=clip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clip.js","sourceRoot":"","sources":["../../src/vision/clip.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fake CLIP provider — the offline test seam for the image-embedding
|
|
3
|
+
* foundation.
|
|
4
|
+
*
|
|
5
|
+
* Produces a DETERMINISTIC 512-d normalized vector from the pixel bytes
|
|
6
|
+
* (a feature hash over the buffer), with no model download, no network,
|
|
7
|
+
* and no `@huggingface/transformers` dependency. It exists so the rest
|
|
8
|
+
* of the image-memory suite (storage isolation, querySimilarImages,
|
|
9
|
+
* the vectorCache namespace guarantee) can run offline and
|
|
10
|
+
* deterministically — exactly the role the FastEmbed local-hash
|
|
11
|
+
* fallback plays for text.
|
|
12
|
+
*
|
|
13
|
+
* It is deliberately NOT wired into production code: it is exported for
|
|
14
|
+
* tests and for callers who want a deterministic stand-in. Real installs
|
|
15
|
+
* use {@link ClipEmbeddingProvider} via `vision.clip.embedImage` or the
|
|
16
|
+
* lazy default.
|
|
17
|
+
*
|
|
18
|
+
* Semantics:
|
|
19
|
+
* - `embedImage(bytes)` hashes the raw bytes → 512-d, normalized.
|
|
20
|
+
* - `embedImageText(query)` hashes the query STRING → 512-d, normalized.
|
|
21
|
+
* - Same input always gives the same vector (assert-able in tests).
|
|
22
|
+
* - `embedImageText` with a query whose text matches a previously
|
|
23
|
+
* embedded image's content produces a related-but-distinct vector —
|
|
24
|
+
* the fake is a hash, not a similarity model, so cross-modal
|
|
25
|
+
* "similarity" is only what tests choose to construct.
|
|
26
|
+
*
|
|
27
|
+
* @module @memos/vision/fake-clip
|
|
28
|
+
*/
|
|
29
|
+
import type { EmbedImageProvider, EmbeddingVector } from "../types.js";
|
|
30
|
+
export interface FakeClipProviderOptions {
|
|
31
|
+
model?: string;
|
|
32
|
+
dimensions?: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Deterministic offline stand-in for {@link ClipEmbeddingProvider}.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* const clip = new FakeClipProvider();
|
|
40
|
+
* const v = await clip.embedImage(Buffer.from([0xff, 0xd8, 0xff])); // 512-d
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare class FakeClipProvider implements EmbedImageProvider {
|
|
44
|
+
readonly id = "fake-clip";
|
|
45
|
+
readonly model: string;
|
|
46
|
+
readonly dimensions: number;
|
|
47
|
+
/** Counts embedImage calls — useful for asserting cache behavior. */
|
|
48
|
+
imageCalls: number;
|
|
49
|
+
/** Counts embedImageText calls. */
|
|
50
|
+
textCalls: number;
|
|
51
|
+
constructor(options?: FakeClipProviderOptions);
|
|
52
|
+
embedImage(image: Buffer | string): Promise<EmbeddingVector>;
|
|
53
|
+
embedImageText(query: string): Promise<EmbeddingVector>;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=fake-clip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake-clip.d.ts","sourceRoot":"","sources":["../../src/vision/fake-clip.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AA4DvE,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,qBAAa,gBAAiB,YAAW,kBAAkB;IACzD,QAAQ,CAAC,EAAE,eAAe;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,qEAAqE;IACrE,UAAU,SAAK;IACf,mCAAmC;IACnC,SAAS,SAAK;IAEd,YAAY,OAAO,GAAE,uBAA4B,EAGhD;IAEK,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAOjE;IAEK,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAO5D;CACF"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fake CLIP provider — the offline test seam for the image-embedding
|
|
3
|
+
* foundation.
|
|
4
|
+
*
|
|
5
|
+
* Produces a DETERMINISTIC 512-d normalized vector from the pixel bytes
|
|
6
|
+
* (a feature hash over the buffer), with no model download, no network,
|
|
7
|
+
* and no `@huggingface/transformers` dependency. It exists so the rest
|
|
8
|
+
* of the image-memory suite (storage isolation, querySimilarImages,
|
|
9
|
+
* the vectorCache namespace guarantee) can run offline and
|
|
10
|
+
* deterministically — exactly the role the FastEmbed local-hash
|
|
11
|
+
* fallback plays for text.
|
|
12
|
+
*
|
|
13
|
+
* It is deliberately NOT wired into production code: it is exported for
|
|
14
|
+
* tests and for callers who want a deterministic stand-in. Real installs
|
|
15
|
+
* use {@link ClipEmbeddingProvider} via `vision.clip.embedImage` or the
|
|
16
|
+
* lazy default.
|
|
17
|
+
*
|
|
18
|
+
* Semantics:
|
|
19
|
+
* - `embedImage(bytes)` hashes the raw bytes → 512-d, normalized.
|
|
20
|
+
* - `embedImageText(query)` hashes the query STRING → 512-d, normalized.
|
|
21
|
+
* - Same input always gives the same vector (assert-able in tests).
|
|
22
|
+
* - `embedImageText` with a query whose text matches a previously
|
|
23
|
+
* embedded image's content produces a related-but-distinct vector —
|
|
24
|
+
* the fake is a hash, not a similarity model, so cross-modal
|
|
25
|
+
* "similarity" is only what tests choose to construct.
|
|
26
|
+
*
|
|
27
|
+
* @module @memos/vision/fake-clip
|
|
28
|
+
*/
|
|
29
|
+
import { normalizeVector } from "../embeddings.js";
|
|
30
|
+
/** Feature-hash weight table shared by image and text sides. */
|
|
31
|
+
const FEATURE_WEIGHT = 1;
|
|
32
|
+
const NGRAM_WEIGHT = 0.12;
|
|
33
|
+
const BIGRAM_WEIGHT = 0.35;
|
|
34
|
+
/**
|
|
35
|
+
* Deterministic feature-hash vector, mirroring the text local-hash
|
|
36
|
+
* fallback's construction so the two spaces behave the same way under
|
|
37
|
+
* test (same norm, same shape, same determinism).
|
|
38
|
+
*/
|
|
39
|
+
function hashVector(source, dims) {
|
|
40
|
+
const vector = new Array(dims).fill(0);
|
|
41
|
+
const add = (feature, weight) => {
|
|
42
|
+
// FNV-1a 32-bit over the feature string, folded into the dims range.
|
|
43
|
+
let hash = 0x811c9dc5;
|
|
44
|
+
for (let i = 0; i < feature.length; i += 1) {
|
|
45
|
+
hash ^= feature.charCodeAt(i);
|
|
46
|
+
hash = Math.imul(hash, 0x01000193) >>> 0;
|
|
47
|
+
}
|
|
48
|
+
const slot = hash % dims;
|
|
49
|
+
const sign = (hash >>> 16) % 2 === 0 ? 1 : -1;
|
|
50
|
+
vector[slot] += sign * weight;
|
|
51
|
+
};
|
|
52
|
+
// Byte-level bigrams over the raw buffer: stable, cheap, and sensitive
|
|
53
|
+
// to both ordering and content (so two different images hash
|
|
54
|
+
// differently, and the same bytes always hash identically).
|
|
55
|
+
for (let i = 0; i + 1 < source.length; i += 2) {
|
|
56
|
+
add(`b${source[i]}:${source[i + 1]}`, FEATURE_WEIGHT);
|
|
57
|
+
}
|
|
58
|
+
// Structural n-grams of the first 4 bytes (header signature) — a
|
|
59
|
+
// coarse, real-ish signal that two JPEGs share more than two random
|
|
60
|
+
// PNGs do, without pretending to be a vision model.
|
|
61
|
+
if (source.length >= 4) {
|
|
62
|
+
add(`h${source[0]}:${source[1]}:${source[2]}:${source[3]}`, NGRAM_WEIGHT);
|
|
63
|
+
add(`h${source[0]}:${source[1]}`, BIGRAM_WEIGHT);
|
|
64
|
+
}
|
|
65
|
+
// Length signature: guards against short inputs hashing to the
|
|
66
|
+
// all-zero vector (an empty normalized vector scores 0 against
|
|
67
|
+
// everything and would make two distinct short inputs look equal).
|
|
68
|
+
add(`len:${source.length}`, FEATURE_WEIGHT);
|
|
69
|
+
if (source.length === 0) {
|
|
70
|
+
// A truly empty input still gets a deterministic non-zero vector so
|
|
71
|
+
// it never collides with another short input's zero vector.
|
|
72
|
+
vector[0] += FEATURE_WEIGHT;
|
|
73
|
+
}
|
|
74
|
+
return normalizeVector(vector);
|
|
75
|
+
}
|
|
76
|
+
/** Hash a string into the same feature space. */
|
|
77
|
+
function hashText(text, dims) {
|
|
78
|
+
const bytes = new Uint8Array(text.length * 2);
|
|
79
|
+
for (let i = 0; i < text.length; i += 1) {
|
|
80
|
+
bytes[i * 2] = text.charCodeAt(i) & 0xff;
|
|
81
|
+
bytes[i * 2 + 1] = (text.charCodeAt(i) >> 8) & 0xff;
|
|
82
|
+
}
|
|
83
|
+
return hashVector(bytes, dims);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Deterministic offline stand-in for {@link ClipEmbeddingProvider}.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* const clip = new FakeClipProvider();
|
|
91
|
+
* const v = await clip.embedImage(Buffer.from([0xff, 0xd8, 0xff])); // 512-d
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export class FakeClipProvider {
|
|
95
|
+
id = "fake-clip";
|
|
96
|
+
model;
|
|
97
|
+
dimensions;
|
|
98
|
+
/** Counts embedImage calls — useful for asserting cache behavior. */
|
|
99
|
+
imageCalls = 0;
|
|
100
|
+
/** Counts embedImageText calls. */
|
|
101
|
+
textCalls = 0;
|
|
102
|
+
constructor(options = {}) {
|
|
103
|
+
this.model = options.model ?? "fake-clip-vit-base-patch32";
|
|
104
|
+
this.dimensions = options.dimensions ?? 512;
|
|
105
|
+
}
|
|
106
|
+
async embedImage(image) {
|
|
107
|
+
this.imageCalls += 1;
|
|
108
|
+
const bytes = typeof image === "string"
|
|
109
|
+
? new TextEncoder().encode(image)
|
|
110
|
+
: new Uint8Array(image);
|
|
111
|
+
return hashVector(bytes, this.dimensions);
|
|
112
|
+
}
|
|
113
|
+
async embedImageText(query) {
|
|
114
|
+
this.textCalls += 1;
|
|
115
|
+
// The model id is mixed into the hash so two fake providers with
|
|
116
|
+
// different model names (but identical query text) produce
|
|
117
|
+
// DIFFERENT vectors — that's what proves the cache is keyed by
|
|
118
|
+
// model, not by query alone.
|
|
119
|
+
return hashText(`${this.model}\u0000${query}`, this.dimensions);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=fake-clip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake-clip.js","sourceRoot":"","sources":["../../src/vision/fake-clip.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGnD,gEAAgE;AAChE,MAAM,cAAc,GAAG,CAAC,CAAC;AACzB,MAAM,YAAY,GAAG,IAAI,CAAC;AAC1B,MAAM,aAAa,GAAG,IAAI,CAAC;AAE3B;;;;GAIG;AACH,SAAS,UAAU,CAAC,MAAkB,EAAE,IAAY;IAClD,MAAM,MAAM,GAAG,IAAI,KAAK,CAAS,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,CAAC,OAAe,EAAE,MAAc,EAAQ,EAAE;QACpD,qEAAqE;QACrE,IAAI,IAAI,GAAG,UAAU,CAAC;QACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3C,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;QAC3C,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;QACzB,MAAM,IAAI,GAAG,CAAC,IAAI,KAAK,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,MAAM,CAAC;IAChC,CAAC,CAAC;IACF,uEAAuE;IACvE,6DAA6D;IAC7D,4DAA4D;IAC5D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9C,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;IACxD,CAAC;IACD,iEAAiE;IACjE,oEAAoE;IACpE,oDAAoD;IACpD,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACvB,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;QAC1E,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;IACnD,CAAC;IACD,+DAA+D;IAC/D,+DAA+D;IAC/D,mEAAmE;IACnE,GAAG,CAAC,OAAO,MAAM,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC;IAC5C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,oEAAoE;QACpE,4DAA4D;QAC5D,MAAM,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC;IAC9B,CAAC;IACD,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC;AAED,iDAAiD;AACjD,SAAS,QAAQ,CAAC,IAAY,EAAE,IAAY;IAC1C,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;QACzC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IACtD,CAAC;IACD,OAAO,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACjC,CAAC;AAOD;;;;;;;;GAQG;AACH,MAAM,OAAO,gBAAgB;IAClB,EAAE,GAAG,WAAW,CAAC;IACjB,KAAK,CAAS;IACd,UAAU,CAAS;IAE5B,qEAAqE;IACrE,UAAU,GAAG,CAAC,CAAC;IACf,mCAAmC;IACnC,SAAS,GAAG,CAAC,CAAC;IAEd,YAAY,OAAO,GAA4B,EAAE;QAC/C,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,4BAA4B,CAAC;QAC3D,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,GAAG,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,KAAsB;QACrC,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC;QACrB,MAAM,KAAK,GACT,OAAO,KAAK,KAAK,QAAQ;YACvB,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC;YACjC,CAAC,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;QAC5B,OAAO,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,KAAa;QAChC,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC;QACpB,iEAAiE;QACjE,2DAA2D;QAC3D,+DAA+D;QAC/D,6BAA6B;QAC7B,OAAO,QAAQ,CAAC,GAAG,IAAI,CAAC,KAAK,SAAS,KAAK,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAClE,CAAC;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vision (image memory) module surface.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the CLIP provider, the offline fake provider, and the CLIP
|
|
5
|
+
* query cache so callers import from `@memos/vision` rather than
|
|
6
|
+
* reaching into individual files.
|
|
7
|
+
*
|
|
8
|
+
* @module @memos/vision
|
|
9
|
+
*/
|
|
10
|
+
export { ClipEmbeddingProvider, ClipUnavailableError, DEFAULT_CLIP_MODEL, DEFAULT_CLIP_DIMENSIONS, } from "./clip.js";
|
|
11
|
+
export type { ClipEmbeddingProviderOptions } from "./clip.js";
|
|
12
|
+
export { FakeClipProvider } from "./fake-clip.js";
|
|
13
|
+
export type { FakeClipProviderOptions } from "./fake-clip.js";
|
|
14
|
+
export { ClipQueryCache, DEFAULT_CLIP_QUERY_CACHE_MAX, } from "./clip-query-cache.js";
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vision/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,4BAA4B,EAAE,MAAM,WAAW,CAAC;AAE9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,YAAY,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAE9D,OAAO,EACL,cAAc,EACd,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vision (image memory) module surface.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the CLIP provider, the offline fake provider, and the CLIP
|
|
5
|
+
* query cache so callers import from `@memos/vision` rather than
|
|
6
|
+
* reaching into individual files.
|
|
7
|
+
*
|
|
8
|
+
* @module @memos/vision
|
|
9
|
+
*/
|
|
10
|
+
export { ClipEmbeddingProvider, ClipUnavailableError, DEFAULT_CLIP_MODEL, DEFAULT_CLIP_DIMENSIONS, } from "./clip.js";
|
|
11
|
+
export { FakeClipProvider } from "./fake-clip.js";
|
|
12
|
+
export { ClipQueryCache, DEFAULT_CLIP_QUERY_CACHE_MAX, } from "./clip-query-cache.js";
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vision/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGlD,OAAO,EACL,cAAc,EACd,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC"}
|