@plur-ai/core 0.2.4 → 0.2.6
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/index.d.ts +4 -1
- package/dist/index.js +55 -10
- package/package.json +1 -2
package/dist/index.d.ts
CHANGED
|
@@ -769,8 +769,11 @@ declare class Plur {
|
|
|
769
769
|
private _filterEngrams;
|
|
770
770
|
/** Reactivate accessed engrams (bump retrieval strength, frequency, last_accessed) */
|
|
771
771
|
private _reactivateResults;
|
|
772
|
-
/** Scored injection within token budget. Returns formatted strings. */
|
|
772
|
+
/** Scored injection within token budget (BM25 only). Returns formatted strings. */
|
|
773
773
|
inject(task: string, options?: InjectOptions): InjectionResult;
|
|
774
|
+
/** Scored injection with embedding boost when available. Falls back to BM25 if embeddings not installed. */
|
|
775
|
+
injectHybrid(task: string, options?: InjectOptions): Promise<InjectionResult>;
|
|
776
|
+
private _formatInjection;
|
|
774
777
|
/** Update feedback_signals and adjust retrieval_strength. */
|
|
775
778
|
feedback(id: string, signal: 'positive' | 'negative' | 'neutral'): void;
|
|
776
779
|
/** Set engram status to 'retired'. */
|
package/dist/index.js
CHANGED
|
@@ -509,7 +509,7 @@ function fillTokenBudget(scored, maxTokens) {
|
|
|
509
509
|
}
|
|
510
510
|
return { selected: result, tokens_used: tokensUsed };
|
|
511
511
|
}
|
|
512
|
-
function selectAndSpread(ctx, personalEngrams, packs, config) {
|
|
512
|
+
function selectAndSpread(ctx, personalEngrams, packs, config, embeddingBoosts) {
|
|
513
513
|
const spreadCap = config?.spread_cap ?? 3;
|
|
514
514
|
const spreadBudget = config?.spread_budget ?? 480;
|
|
515
515
|
const promptLower = ctx.prompt.toLowerCase();
|
|
@@ -521,7 +521,13 @@ function selectAndSpread(ctx, personalEngrams, packs, config) {
|
|
|
521
521
|
for (const engram of personalEngrams) {
|
|
522
522
|
if (engram.status !== "active") continue;
|
|
523
523
|
engramMap.set(engram.id, engram);
|
|
524
|
-
|
|
524
|
+
let raw = scoreEngram(engram, promptLower, promptWords, [], ctx.scope, false);
|
|
525
|
+
const embBoost = embeddingBoosts?.get(engram.id) ?? 0;
|
|
526
|
+
if (raw === 0 && embBoost > 0.3) {
|
|
527
|
+
raw = embBoost * 2;
|
|
528
|
+
} else if (raw > 0 && embBoost > 0) {
|
|
529
|
+
raw += embBoost;
|
|
530
|
+
}
|
|
525
531
|
if (raw > 0) {
|
|
526
532
|
scored.push({ ...engram, keyword_match: raw, raw_score: raw, score: raw });
|
|
527
533
|
}
|
|
@@ -533,7 +539,13 @@ function selectAndSpread(ctx, personalEngrams, packs, config) {
|
|
|
533
539
|
for (const engram of pack.engrams) {
|
|
534
540
|
if (engram.status !== "active") continue;
|
|
535
541
|
engramMap.set(engram.id, engram);
|
|
536
|
-
|
|
542
|
+
let raw = scoreEngram(engram, promptLower, promptWords, matchTerms, ctx.scope, true);
|
|
543
|
+
const embBoost = embeddingBoosts?.get(engram.id) ?? 0;
|
|
544
|
+
if (raw === 0 && embBoost > 0.3) {
|
|
545
|
+
raw = embBoost * 2;
|
|
546
|
+
} else if (raw > 0 && embBoost > 0) {
|
|
547
|
+
raw += embBoost;
|
|
548
|
+
}
|
|
537
549
|
if (raw > 0) {
|
|
538
550
|
scored.push({ ...engram, keyword_match: raw, raw_score: raw, score: raw });
|
|
539
551
|
}
|
|
@@ -732,17 +744,25 @@ Rules:
|
|
|
732
744
|
import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
733
745
|
import { join as join2 } from "path";
|
|
734
746
|
var embedPipeline = null;
|
|
747
|
+
var transformersUnavailable = false;
|
|
735
748
|
async function getEmbedder() {
|
|
749
|
+
if (transformersUnavailable) return null;
|
|
736
750
|
if (!embedPipeline) {
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
751
|
+
try {
|
|
752
|
+
const { pipeline } = await import("@huggingface/transformers");
|
|
753
|
+
embedPipeline = await pipeline("feature-extraction", "Xenova/bge-small-en-v1.5", {
|
|
754
|
+
dtype: "fp32"
|
|
755
|
+
});
|
|
756
|
+
} catch {
|
|
757
|
+
transformersUnavailable = true;
|
|
758
|
+
return null;
|
|
759
|
+
}
|
|
741
760
|
}
|
|
742
761
|
return embedPipeline;
|
|
743
762
|
}
|
|
744
763
|
async function embed(text) {
|
|
745
764
|
const embedder = await getEmbedder();
|
|
765
|
+
if (!embedder) return null;
|
|
746
766
|
const result = await embedder(text, { pooling: "cls", normalize: true });
|
|
747
767
|
return new Float32Array(result.data);
|
|
748
768
|
}
|
|
@@ -776,6 +796,9 @@ async function embeddingSearch(engrams, query, limit, storagePath) {
|
|
|
776
796
|
const cachePath = storagePath ? join2(storagePath, ".embeddings-cache.json") : ".embeddings-cache.json";
|
|
777
797
|
const cache2 = loadCache(cachePath);
|
|
778
798
|
const queryEmbedding = await embed(query);
|
|
799
|
+
if (!queryEmbedding) {
|
|
800
|
+
return [];
|
|
801
|
+
}
|
|
779
802
|
const similarities = [];
|
|
780
803
|
for (const engram of engrams) {
|
|
781
804
|
const searchText = engramSearchText(engram);
|
|
@@ -784,7 +807,9 @@ async function embeddingSearch(engrams, query, limit, storagePath) {
|
|
|
784
807
|
if (cache2[engram.id]?.hash === hash) {
|
|
785
808
|
engramEmbedding = new Float32Array(cache2[engram.id].embedding);
|
|
786
809
|
} else {
|
|
787
|
-
|
|
810
|
+
const emb = await embed(searchText);
|
|
811
|
+
if (!emb) return [];
|
|
812
|
+
engramEmbedding = emb;
|
|
788
813
|
cache2[engram.id] = {
|
|
789
814
|
hash,
|
|
790
815
|
embedding: Array.from(engramEmbedding)
|
|
@@ -1331,8 +1356,27 @@ var Plur = class {
|
|
|
1331
1356
|
}
|
|
1332
1357
|
if (modified) saveEngrams(this.paths.engrams, allEngrams);
|
|
1333
1358
|
}
|
|
1334
|
-
/** Scored injection within token budget. Returns formatted strings. */
|
|
1359
|
+
/** Scored injection within token budget (BM25 only). Returns formatted strings. */
|
|
1335
1360
|
inject(task, options) {
|
|
1361
|
+
return this._formatInjection(task, options);
|
|
1362
|
+
}
|
|
1363
|
+
/** Scored injection with embedding boost when available. Falls back to BM25 if embeddings not installed. */
|
|
1364
|
+
async injectHybrid(task, options) {
|
|
1365
|
+
let embeddingBoosts;
|
|
1366
|
+
try {
|
|
1367
|
+
const engrams = loadEngrams(this.paths.engrams).filter((e) => e.status === "active");
|
|
1368
|
+
const results = await embeddingSearch(engrams, task, engrams.length, this.paths.root);
|
|
1369
|
+
if (results.length > 0) {
|
|
1370
|
+
embeddingBoosts = /* @__PURE__ */ new Map();
|
|
1371
|
+
for (let i = 0; i < results.length; i++) {
|
|
1372
|
+
embeddingBoosts.set(results[i].id, 1 / (1 + i * 0.1));
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
} catch {
|
|
1376
|
+
}
|
|
1377
|
+
return this._formatInjection(task, options, embeddingBoosts);
|
|
1378
|
+
}
|
|
1379
|
+
_formatInjection(task, options, embeddingBoosts) {
|
|
1336
1380
|
const engrams = loadEngrams(this.paths.engrams);
|
|
1337
1381
|
const packs = loadAllPacks(this.paths.packs);
|
|
1338
1382
|
const budget = options?.budget ?? this.config.injection_budget ?? 2e3;
|
|
@@ -1347,7 +1391,8 @@ var Plur = class {
|
|
|
1347
1391
|
{
|
|
1348
1392
|
spread_cap: this.config.injection?.spread_cap,
|
|
1349
1393
|
spread_budget: this.config.injection?.spread_budget
|
|
1350
|
-
}
|
|
1394
|
+
},
|
|
1395
|
+
embeddingBoosts
|
|
1351
1396
|
);
|
|
1352
1397
|
const formatEngrams = (wires) => {
|
|
1353
1398
|
if (wires.length === 0) return "";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plur-ai/core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
"dist"
|
|
9
9
|
],
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@huggingface/transformers": "^3.8.1",
|
|
12
11
|
"js-yaml": "^4.1.0",
|
|
13
12
|
"zod": "^3.23.0"
|
|
14
13
|
},
|