agent-working-memory 0.13.0 → 0.13.1
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.
- package/dist/core/embeddings.d.ts.map +1 -1
- package/dist/core/embeddings.js +2 -0
- package/dist/core/embeddings.js.map +1 -1
- package/dist/core/model-cache.d.ts +28 -0
- package/dist/core/model-cache.d.ts.map +1 -0
- package/dist/core/model-cache.js +50 -0
- package/dist/core/model-cache.js.map +1 -0
- package/dist/core/query-expander.d.ts.map +1 -1
- package/dist/core/query-expander.js +2 -0
- package/dist/core/query-expander.js.map +1 -1
- package/dist/core/reranker.d.ts.map +1 -1
- package/dist/core/reranker.js +2 -0
- package/dist/core/reranker.js.map +1 -1
- package/package.json +1 -1
- package/src/core/embeddings.ts +2 -0
- package/src/core/model-cache.ts +51 -0
- package/src/core/query-expander.ts +2 -0
- package/src/core/reranker.ts +2 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../../src/core/embeddings.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAY,KAAK,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../../src/core/embeddings.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAY,KAAK,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AA8CrF;;;;;GAKG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,yBAAyB,CAAC,CAEtE;AAED;;;GAGG;AACH,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAG3D;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAGrE;AAED,qFAAqF;AACrF,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAQjE;AAED,uCAAuC;AACvC,eAAO,MAAM,oBAAoB,QAAa,CAAC"}
|
package/dist/core/embeddings.js
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
import { pipeline } from '@huggingface/transformers';
|
|
20
20
|
import { dispatchEmbed, registerInProcessHandlers } from './ml-worker.js';
|
|
21
21
|
import { noteModelLoad } from './write-telemetry.js';
|
|
22
|
+
import { ensureModelCacheDir } from './model-cache.js';
|
|
22
23
|
const MODEL_ID = process.env.AWM_EMBED_MODEL ?? 'Xenova/bge-small-en-v1.5';
|
|
23
24
|
const DIMENSIONS = parseInt(process.env.AWM_EMBED_DIMS ?? '384', 10);
|
|
24
25
|
const POOLING = (process.env.AWM_EMBED_POOLING ?? 'mean');
|
|
@@ -31,6 +32,7 @@ async function loadInProcess() {
|
|
|
31
32
|
if (inProcessInitPromise)
|
|
32
33
|
return inProcessInitPromise;
|
|
33
34
|
const tLoadStart = performance.now();
|
|
35
|
+
ensureModelCacheDir();
|
|
34
36
|
inProcessInitPromise = pipeline('feature-extraction', MODEL_ID, { dtype: 'fp32' }).then(pipe => {
|
|
35
37
|
inProcessInstance = pipe;
|
|
36
38
|
noteModelLoad(performance.now() - tLoadStart);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../../src/core/embeddings.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,sCAAsC;AACtC;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,QAAQ,EAAkC,MAAM,2BAA2B,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../../src/core/embeddings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model cache directory — makes `HF_HOME` (and `AWM_CACHE_DIR`) actually work.
|
|
3
|
+
*
|
|
4
|
+
* ROOT CAUSE (found 2026-08-22 investigating flaky model loads in ephemeral Docker
|
|
5
|
+
* containers): @huggingface/transformers has NO built-in environment-variable support
|
|
6
|
+
* for its cache location — it reads only `env.cacheDir`, set in code, and nothing else.
|
|
7
|
+
* Left unset, it defaults to `<install-dir-of-@huggingface/transformers>/.cache/` —
|
|
8
|
+
* inside node_modules, wiped on every `npm install`/`npm ci`, i.e. every Docker build
|
|
9
|
+
* and every global upgrade re-downloads all three models from scratch.
|
|
10
|
+
*
|
|
11
|
+
* `docs/deployment.md` has instructed `HF_HOME=/data/models` for Railway/Fly/Render
|
|
12
|
+
* persistence since it was written — that variable was a silent no-op the whole time;
|
|
13
|
+
* nothing in AWM ever read it. This module makes it real, so existing deployments start
|
|
14
|
+
* working with ZERO config changes on the user's end. `AWM_CACHE_DIR` (referenced in
|
|
15
|
+
* docs/architecture.md, also previously fictional) is honored as an AWM-specific
|
|
16
|
+
* override, and the default is now genuinely persistent for a bare npm install too
|
|
17
|
+
* (previously it was ephemeral there as well, just less obviously so).
|
|
18
|
+
*
|
|
19
|
+
* Precedence: AWM_CACHE_DIR > HF_HOME > <packageRoot>/data/models.
|
|
20
|
+
*
|
|
21
|
+
* MUST run before the first `pipeline()` / `AutoTokenizer.from_pretrained()` /
|
|
22
|
+
* `AutoModel*.from_pretrained()` call in the process — `env.cacheDir` is read at
|
|
23
|
+
* download/load time, not import time, but there's no reason to risk a race, so every
|
|
24
|
+
* model-loading module in src/core/ calls `ensureModelCacheDir()` before its first
|
|
25
|
+
* library call. Idempotent — safe to call from all three.
|
|
26
|
+
*/
|
|
27
|
+
export declare function ensureModelCacheDir(): string;
|
|
28
|
+
//# sourceMappingURL=model-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-cache.d.ts","sourceRoot":"","sources":["../../src/core/model-cache.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAgBH,wBAAgB,mBAAmB,IAAI,MAAM,CAO5C"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Copyright 2026 Robert Winter / Complete Ideas
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Model cache directory — makes `HF_HOME` (and `AWM_CACHE_DIR`) actually work.
|
|
5
|
+
*
|
|
6
|
+
* ROOT CAUSE (found 2026-08-22 investigating flaky model loads in ephemeral Docker
|
|
7
|
+
* containers): @huggingface/transformers has NO built-in environment-variable support
|
|
8
|
+
* for its cache location — it reads only `env.cacheDir`, set in code, and nothing else.
|
|
9
|
+
* Left unset, it defaults to `<install-dir-of-@huggingface/transformers>/.cache/` —
|
|
10
|
+
* inside node_modules, wiped on every `npm install`/`npm ci`, i.e. every Docker build
|
|
11
|
+
* and every global upgrade re-downloads all three models from scratch.
|
|
12
|
+
*
|
|
13
|
+
* `docs/deployment.md` has instructed `HF_HOME=/data/models` for Railway/Fly/Render
|
|
14
|
+
* persistence since it was written — that variable was a silent no-op the whole time;
|
|
15
|
+
* nothing in AWM ever read it. This module makes it real, so existing deployments start
|
|
16
|
+
* working with ZERO config changes on the user's end. `AWM_CACHE_DIR` (referenced in
|
|
17
|
+
* docs/architecture.md, also previously fictional) is honored as an AWM-specific
|
|
18
|
+
* override, and the default is now genuinely persistent for a bare npm install too
|
|
19
|
+
* (previously it was ephemeral there as well, just less obviously so).
|
|
20
|
+
*
|
|
21
|
+
* Precedence: AWM_CACHE_DIR > HF_HOME > <packageRoot>/data/models.
|
|
22
|
+
*
|
|
23
|
+
* MUST run before the first `pipeline()` / `AutoTokenizer.from_pretrained()` /
|
|
24
|
+
* `AutoModel*.from_pretrained()` call in the process — `env.cacheDir` is read at
|
|
25
|
+
* download/load time, not import time, but there's no reason to risk a race, so every
|
|
26
|
+
* model-loading module in src/core/ calls `ensureModelCacheDir()` before its first
|
|
27
|
+
* library call. Idempotent — safe to call from all three.
|
|
28
|
+
*/
|
|
29
|
+
import { env } from '@huggingface/transformers';
|
|
30
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
31
|
+
import { dirname, join } from 'node:path';
|
|
32
|
+
import { fileURLToPath } from 'node:url';
|
|
33
|
+
let configured = false;
|
|
34
|
+
function resolvePackageRoot() {
|
|
35
|
+
// This file lives at src/core/model-cache.ts (dev, via tsx) or
|
|
36
|
+
// dist/core/model-cache.js (built) — either way, two levels up is the package root.
|
|
37
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
38
|
+
return dirname(dirname(here));
|
|
39
|
+
}
|
|
40
|
+
export function ensureModelCacheDir() {
|
|
41
|
+
if (configured)
|
|
42
|
+
return env.cacheDir;
|
|
43
|
+
const dir = process.env.AWM_CACHE_DIR || process.env.HF_HOME || join(resolvePackageRoot(), 'data', 'models');
|
|
44
|
+
if (!existsSync(dir))
|
|
45
|
+
mkdirSync(dir, { recursive: true });
|
|
46
|
+
env.cacheDir = dir;
|
|
47
|
+
configured = true;
|
|
48
|
+
return dir;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=model-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-cache.js","sourceRoot":"","sources":["../../src/core/model-cache.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,sCAAsC;AACtC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,IAAI,UAAU,GAAG,KAAK,CAAC;AAEvB,SAAS,kBAAkB;IACzB,+DAA+D;IAC/D,oFAAoF;IACpF,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,IAAI,UAAU;QAAE,OAAO,GAAG,CAAC,QAAS,CAAC;IACrC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,kBAAkB,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC7G,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC;IACnB,UAAU,GAAG,IAAI,CAAC;IAClB,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-expander.d.ts","sourceRoot":"","sources":["../../src/core/query-expander.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAY,KAAK,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"query-expander.d.ts","sourceRoot":"","sources":["../../src/core/query-expander.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAY,KAAK,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAqCvF,iCAAiC;AACjC,wBAAsB,WAAW,IAAI,OAAO,CAAC,2BAA2B,CAAC,CAExE;AAmBD;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkCxE;AAED,sEAAsE;AACtE,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C"}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { pipeline } from '@huggingface/transformers';
|
|
18
18
|
import { dispatchExpand, registerInProcessHandlers } from './ml-worker.js';
|
|
19
|
+
import { ensureModelCacheDir } from './model-cache.js';
|
|
19
20
|
const MODEL_ID = 'Xenova/flan-t5-small';
|
|
20
21
|
// --- In-process fallback ---
|
|
21
22
|
let inProcessInstance = null;
|
|
@@ -25,6 +26,7 @@ async function loadInProcess() {
|
|
|
25
26
|
return inProcessInstance;
|
|
26
27
|
if (inProcessInitPromise)
|
|
27
28
|
return inProcessInitPromise;
|
|
29
|
+
ensureModelCacheDir();
|
|
28
30
|
inProcessInitPromise = pipeline('text2text-generation', MODEL_ID, { dtype: 'fp32' }).then(pipe => {
|
|
29
31
|
inProcessInstance = pipe;
|
|
30
32
|
console.error(`Query expander loaded in-process: ${MODEL_ID}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-expander.js","sourceRoot":"","sources":["../../src/core/query-expander.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,sCAAsC;AACtC;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,QAAQ,EAAoC,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"query-expander.js","sourceRoot":"","sources":["../../src/core/query-expander.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reranker.d.ts","sourceRoot":"","sources":["../../src/core/reranker.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"reranker.d.ts","sourceRoot":"","sources":["../../src/core/reranker.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAyFH,iCAAiC;AACjC,wBAAsB,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,CAGhD;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAsB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAGvF"}
|
package/dist/core/reranker.js
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { AutoTokenizer, AutoModelForSequenceClassification, } from '@huggingface/transformers';
|
|
15
15
|
import { dispatchRerank, registerInProcessHandlers } from './ml-worker.js';
|
|
16
|
+
import { ensureModelCacheDir } from './model-cache.js';
|
|
16
17
|
const DEFAULT_MODEL = 'Xenova/ms-marco-MiniLM-L-6-v2';
|
|
17
18
|
const MODEL_ID = process.env.AWM_RERANKER_MODEL || DEFAULT_MODEL;
|
|
18
19
|
// --- In-process fallback ---
|
|
@@ -25,6 +26,7 @@ async function ensureLoaded() {
|
|
|
25
26
|
if (initPromise)
|
|
26
27
|
return initPromise;
|
|
27
28
|
initPromise = (async () => {
|
|
29
|
+
ensureModelCacheDir();
|
|
28
30
|
tokenizer = await AutoTokenizer.from_pretrained(MODEL_ID);
|
|
29
31
|
model = await AutoModelForSequenceClassification.from_pretrained(MODEL_ID, { dtype: 'fp32' });
|
|
30
32
|
console.error(`Re-ranker model loaded in-process: ${MODEL_ID}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reranker.js","sourceRoot":"","sources":["../../src/core/reranker.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,sCAAsC;AACtC;;;;;;;;;;GAUG;AAEH,OAAO,EACL,aAAa,EACb,kCAAkC,GAGnC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"reranker.js","sourceRoot":"","sources":["../../src/core/reranker.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/core/embeddings.ts
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
import { pipeline, type FeatureExtractionPipeline } from '@huggingface/transformers';
|
|
21
21
|
import { dispatchEmbed, registerInProcessHandlers } from './ml-worker.js';
|
|
22
22
|
import { noteModelLoad } from './write-telemetry.js';
|
|
23
|
+
import { ensureModelCacheDir } from './model-cache.js';
|
|
23
24
|
|
|
24
25
|
const MODEL_ID = process.env.AWM_EMBED_MODEL ?? 'Xenova/bge-small-en-v1.5';
|
|
25
26
|
const DIMENSIONS = parseInt(process.env.AWM_EMBED_DIMS ?? '384', 10);
|
|
@@ -34,6 +35,7 @@ async function loadInProcess(): Promise<FeatureExtractionPipeline> {
|
|
|
34
35
|
if (inProcessInstance) return inProcessInstance;
|
|
35
36
|
if (inProcessInitPromise) return inProcessInitPromise;
|
|
36
37
|
const tLoadStart = performance.now();
|
|
38
|
+
ensureModelCacheDir();
|
|
37
39
|
inProcessInitPromise = pipeline('feature-extraction', MODEL_ID, { dtype: 'fp32' }).then(pipe => {
|
|
38
40
|
inProcessInstance = pipe;
|
|
39
41
|
noteModelLoad(performance.now() - tLoadStart);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Copyright 2026 Robert Winter / Complete Ideas
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Model cache directory — makes `HF_HOME` (and `AWM_CACHE_DIR`) actually work.
|
|
5
|
+
*
|
|
6
|
+
* ROOT CAUSE (found 2026-08-22 investigating flaky model loads in ephemeral Docker
|
|
7
|
+
* containers): @huggingface/transformers has NO built-in environment-variable support
|
|
8
|
+
* for its cache location — it reads only `env.cacheDir`, set in code, and nothing else.
|
|
9
|
+
* Left unset, it defaults to `<install-dir-of-@huggingface/transformers>/.cache/` —
|
|
10
|
+
* inside node_modules, wiped on every `npm install`/`npm ci`, i.e. every Docker build
|
|
11
|
+
* and every global upgrade re-downloads all three models from scratch.
|
|
12
|
+
*
|
|
13
|
+
* `docs/deployment.md` has instructed `HF_HOME=/data/models` for Railway/Fly/Render
|
|
14
|
+
* persistence since it was written — that variable was a silent no-op the whole time;
|
|
15
|
+
* nothing in AWM ever read it. This module makes it real, so existing deployments start
|
|
16
|
+
* working with ZERO config changes on the user's end. `AWM_CACHE_DIR` (referenced in
|
|
17
|
+
* docs/architecture.md, also previously fictional) is honored as an AWM-specific
|
|
18
|
+
* override, and the default is now genuinely persistent for a bare npm install too
|
|
19
|
+
* (previously it was ephemeral there as well, just less obviously so).
|
|
20
|
+
*
|
|
21
|
+
* Precedence: AWM_CACHE_DIR > HF_HOME > <packageRoot>/data/models.
|
|
22
|
+
*
|
|
23
|
+
* MUST run before the first `pipeline()` / `AutoTokenizer.from_pretrained()` /
|
|
24
|
+
* `AutoModel*.from_pretrained()` call in the process — `env.cacheDir` is read at
|
|
25
|
+
* download/load time, not import time, but there's no reason to risk a race, so every
|
|
26
|
+
* model-loading module in src/core/ calls `ensureModelCacheDir()` before its first
|
|
27
|
+
* library call. Idempotent — safe to call from all three.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import { env } from '@huggingface/transformers';
|
|
31
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
32
|
+
import { dirname, join } from 'node:path';
|
|
33
|
+
import { fileURLToPath } from 'node:url';
|
|
34
|
+
|
|
35
|
+
let configured = false;
|
|
36
|
+
|
|
37
|
+
function resolvePackageRoot(): string {
|
|
38
|
+
// This file lives at src/core/model-cache.ts (dev, via tsx) or
|
|
39
|
+
// dist/core/model-cache.js (built) — either way, two levels up is the package root.
|
|
40
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
41
|
+
return dirname(dirname(here));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function ensureModelCacheDir(): string {
|
|
45
|
+
if (configured) return env.cacheDir!;
|
|
46
|
+
const dir = process.env.AWM_CACHE_DIR || process.env.HF_HOME || join(resolvePackageRoot(), 'data', 'models');
|
|
47
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
48
|
+
env.cacheDir = dir;
|
|
49
|
+
configured = true;
|
|
50
|
+
return dir;
|
|
51
|
+
}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
import { pipeline, type Text2TextGenerationPipeline } from '@huggingface/transformers';
|
|
19
19
|
import { dispatchExpand, registerInProcessHandlers } from './ml-worker.js';
|
|
20
|
+
import { ensureModelCacheDir } from './model-cache.js';
|
|
20
21
|
|
|
21
22
|
const MODEL_ID = 'Xenova/flan-t5-small';
|
|
22
23
|
|
|
@@ -28,6 +29,7 @@ let inProcessInitPromise: Promise<Text2TextGenerationPipeline> | null = null;
|
|
|
28
29
|
async function loadInProcess(): Promise<Text2TextGenerationPipeline> {
|
|
29
30
|
if (inProcessInstance) return inProcessInstance;
|
|
30
31
|
if (inProcessInitPromise) return inProcessInitPromise;
|
|
32
|
+
ensureModelCacheDir();
|
|
31
33
|
inProcessInitPromise = pipeline('text2text-generation', MODEL_ID, { dtype: 'fp32' }).then(pipe => {
|
|
32
34
|
inProcessInstance = pipe as Text2TextGenerationPipeline;
|
|
33
35
|
console.error(`Query expander loaded in-process: ${MODEL_ID}`);
|
package/src/core/reranker.ts
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
type PreTrainedModel,
|
|
20
20
|
} from '@huggingface/transformers';
|
|
21
21
|
import { dispatchRerank, registerInProcessHandlers } from './ml-worker.js';
|
|
22
|
+
import { ensureModelCacheDir } from './model-cache.js';
|
|
22
23
|
|
|
23
24
|
const DEFAULT_MODEL = 'Xenova/ms-marco-MiniLM-L-6-v2';
|
|
24
25
|
const MODEL_ID = process.env.AWM_RERANKER_MODEL || DEFAULT_MODEL;
|
|
@@ -33,6 +34,7 @@ async function ensureLoaded(): Promise<void> {
|
|
|
33
34
|
if (tokenizer && model) return;
|
|
34
35
|
if (initPromise) return initPromise;
|
|
35
36
|
initPromise = (async () => {
|
|
37
|
+
ensureModelCacheDir();
|
|
36
38
|
tokenizer = await AutoTokenizer.from_pretrained(MODEL_ID);
|
|
37
39
|
model = await AutoModelForSequenceClassification.from_pretrained(MODEL_ID, { dtype: 'fp32' });
|
|
38
40
|
console.error(`Re-ranker model loaded in-process: ${MODEL_ID}`);
|