@jaex/dstsx 0.1.0 → 0.1.2
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/README.md +10 -0
- package/dist/index.cjs +265 -166
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -10
- package/dist/index.d.ts +42 -10
- package/dist/index.js +264 -166
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -99,6 +99,7 @@ __export(index_exports, {
|
|
|
99
99
|
evaluate: () => evaluate,
|
|
100
100
|
exactMatch: () => exactMatch,
|
|
101
101
|
f1: () => f1,
|
|
102
|
+
firstPrediction: () => firstPrediction,
|
|
102
103
|
majority: () => majority,
|
|
103
104
|
passAtK: () => passAtK,
|
|
104
105
|
rouge: () => rouge,
|
|
@@ -490,7 +491,7 @@ var LM = class {
|
|
|
490
491
|
#cache;
|
|
491
492
|
#diskCache;
|
|
492
493
|
#requestCount = 0;
|
|
493
|
-
#tokenUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
|
|
494
|
+
#tokenUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0, cachedPromptTokens: 0 };
|
|
494
495
|
constructor(model, cacheOptions = {}) {
|
|
495
496
|
this.model = model;
|
|
496
497
|
this.#cache = new LRUCache(cacheOptions.maxSize, cacheOptions.ttlMs);
|
|
@@ -524,6 +525,9 @@ var LM = class {
|
|
|
524
525
|
this.#tokenUsage.promptTokens += response.usage.promptTokens;
|
|
525
526
|
this.#tokenUsage.completionTokens += response.usage.completionTokens;
|
|
526
527
|
this.#tokenUsage.totalTokens += response.usage.totalTokens;
|
|
528
|
+
if (response.usage.cachedPromptTokens) {
|
|
529
|
+
this.#tokenUsage.cachedPromptTokens += response.usage.cachedPromptTokens;
|
|
530
|
+
}
|
|
527
531
|
}
|
|
528
532
|
return response;
|
|
529
533
|
}
|
|
@@ -570,21 +574,28 @@ var LM = class {
|
|
|
570
574
|
// src/lm/adapters/OpenAI.ts
|
|
571
575
|
var OpenAI = class extends LM {
|
|
572
576
|
#options;
|
|
577
|
+
#client;
|
|
573
578
|
constructor(options = {}) {
|
|
574
579
|
super(options.model ?? "gpt-4o");
|
|
575
580
|
this.#options = options;
|
|
576
581
|
}
|
|
582
|
+
async #getClient() {
|
|
583
|
+
if (!this.#client) {
|
|
584
|
+
const { default: Client } = await import("openai").catch(() => {
|
|
585
|
+
throw new Error(
|
|
586
|
+
"The `openai` package is required for the OpenAI adapter.\nInstall it with: npm install openai"
|
|
587
|
+
);
|
|
588
|
+
});
|
|
589
|
+
this.#client = new Client({
|
|
590
|
+
apiKey: this.#options.apiKey ?? process.env["OPENAI_API_KEY"],
|
|
591
|
+
baseURL: this.#options.baseURL,
|
|
592
|
+
maxRetries: this.#options.maxRetries ?? 3
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
return this.#client;
|
|
596
|
+
}
|
|
577
597
|
async _call(prompt, config) {
|
|
578
|
-
const
|
|
579
|
-
throw new Error(
|
|
580
|
-
"The `openai` package is required for the OpenAI adapter.\nInstall it with: npm install openai"
|
|
581
|
-
);
|
|
582
|
-
});
|
|
583
|
-
const client = new OpenAIClient({
|
|
584
|
-
apiKey: this.#options.apiKey ?? process.env["OPENAI_API_KEY"],
|
|
585
|
-
baseURL: this.#options.baseURL,
|
|
586
|
-
maxRetries: this.#options.maxRetries ?? 3
|
|
587
|
-
});
|
|
598
|
+
const client = await this.#getClient();
|
|
588
599
|
const messages = typeof prompt === "string" ? [{ role: "user", content: prompt }] : prompt;
|
|
589
600
|
const response = await client.chat.completions.create({
|
|
590
601
|
model: config.model ?? this.model,
|
|
@@ -598,28 +609,21 @@ var OpenAI = class extends LM {
|
|
|
598
609
|
const texts = (response.choices ?? []).map(
|
|
599
610
|
(c) => c.message?.content ?? ""
|
|
600
611
|
);
|
|
612
|
+
const usageDetails = response.usage;
|
|
601
613
|
return {
|
|
602
614
|
text: texts[0] ?? "",
|
|
603
615
|
texts,
|
|
604
|
-
usage:
|
|
605
|
-
promptTokens:
|
|
606
|
-
completionTokens:
|
|
607
|
-
totalTokens:
|
|
616
|
+
usage: usageDetails ? {
|
|
617
|
+
promptTokens: usageDetails.prompt_tokens,
|
|
618
|
+
completionTokens: usageDetails.completion_tokens,
|
|
619
|
+
totalTokens: usageDetails.total_tokens,
|
|
620
|
+
...usageDetails.prompt_tokens_details?.cached_tokens ? { cachedPromptTokens: usageDetails.prompt_tokens_details.cached_tokens } : {}
|
|
608
621
|
} : null,
|
|
609
622
|
raw: response
|
|
610
623
|
};
|
|
611
624
|
}
|
|
612
625
|
async *stream(prompt, config = {}) {
|
|
613
|
-
const
|
|
614
|
-
throw new Error(
|
|
615
|
-
"The `openai` package is required for the OpenAI adapter.\nInstall it with: npm install openai"
|
|
616
|
-
);
|
|
617
|
-
});
|
|
618
|
-
const client = new OpenAIClient({
|
|
619
|
-
apiKey: this.#options.apiKey ?? process.env["OPENAI_API_KEY"],
|
|
620
|
-
baseURL: this.#options.baseURL,
|
|
621
|
-
maxRetries: this.#options.maxRetries ?? 3
|
|
622
|
-
});
|
|
626
|
+
const client = await this.#getClient();
|
|
623
627
|
const messages = typeof prompt === "string" ? [{ role: "user", content: prompt }] : prompt;
|
|
624
628
|
const stream = await client.chat.completions.create({
|
|
625
629
|
model: config.model ?? this.model,
|
|
@@ -640,64 +644,164 @@ var OpenAI = class extends LM {
|
|
|
640
644
|
}
|
|
641
645
|
};
|
|
642
646
|
|
|
647
|
+
// src/settings/Settings.ts
|
|
648
|
+
var import_node_async_hooks = require("async_hooks");
|
|
649
|
+
var contextStore = new import_node_async_hooks.AsyncLocalStorage();
|
|
650
|
+
var Settings = class {
|
|
651
|
+
#global = {};
|
|
652
|
+
// ---------------------------------------------------------------------------
|
|
653
|
+
// Effective settings: async-context overrides take precedence over globals.
|
|
654
|
+
// ---------------------------------------------------------------------------
|
|
655
|
+
get #current() {
|
|
656
|
+
const ctx = contextStore.getStore();
|
|
657
|
+
return ctx !== void 0 ? { ...this.#global, ...ctx } : this.#global;
|
|
658
|
+
}
|
|
659
|
+
// ---------------------------------------------------------------------------
|
|
660
|
+
// Accessors
|
|
661
|
+
// ---------------------------------------------------------------------------
|
|
662
|
+
get lm() {
|
|
663
|
+
return this.#current.lm;
|
|
664
|
+
}
|
|
665
|
+
get rm() {
|
|
666
|
+
return this.#current.rm;
|
|
667
|
+
}
|
|
668
|
+
get lmConfig() {
|
|
669
|
+
return this.#current.lmConfig;
|
|
670
|
+
}
|
|
671
|
+
get logLevel() {
|
|
672
|
+
return this.#current.logLevel ?? "warn";
|
|
673
|
+
}
|
|
674
|
+
get cacheDir() {
|
|
675
|
+
return this.#current.cacheDir;
|
|
676
|
+
}
|
|
677
|
+
// ---------------------------------------------------------------------------
|
|
678
|
+
// Mutation
|
|
679
|
+
// ---------------------------------------------------------------------------
|
|
680
|
+
/**
|
|
681
|
+
* Merge `options` into the global settings. Existing keys are overwritten;
|
|
682
|
+
* omitted keys are unchanged. This does NOT affect currently running
|
|
683
|
+
* {@link Settings.context} scopes.
|
|
684
|
+
*/
|
|
685
|
+
configure(options) {
|
|
686
|
+
this.#global = { ...this.#global, ...options };
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Reset all global settings to their defaults.
|
|
690
|
+
*/
|
|
691
|
+
reset() {
|
|
692
|
+
this.#global = {};
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* Return a deep-frozen snapshot of the currently effective settings
|
|
696
|
+
* (respects any active async-context overrides).
|
|
697
|
+
*/
|
|
698
|
+
inspect() {
|
|
699
|
+
return Object.freeze({ ...this.#current });
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Run `fn` inside an async-context-local settings scope.
|
|
703
|
+
*
|
|
704
|
+
* The `overrides` are merged on top of the current global settings and
|
|
705
|
+
* stored in an `AsyncLocalStorage` context. Concurrent calls each get
|
|
706
|
+
* their own isolated snapshot — they never overwrite each other's settings.
|
|
707
|
+
*
|
|
708
|
+
* @example
|
|
709
|
+
* ```ts
|
|
710
|
+
* // In an Express/Fastify handler:
|
|
711
|
+
* await settings.context({ lm: perRequestLM }, () => program.forward(inputs));
|
|
712
|
+
* ```
|
|
713
|
+
*/
|
|
714
|
+
async context(overrides, fn) {
|
|
715
|
+
const merged = { ...this.#global, ...overrides };
|
|
716
|
+
return contextStore.run(merged, fn);
|
|
717
|
+
}
|
|
718
|
+
};
|
|
719
|
+
var settings = new Settings();
|
|
720
|
+
|
|
643
721
|
// src/lm/adapters/Anthropic.ts
|
|
644
722
|
var Anthropic = class extends LM {
|
|
645
723
|
#options;
|
|
724
|
+
#client;
|
|
646
725
|
constructor(options = {}) {
|
|
647
726
|
super(options.model ?? "claude-3-5-sonnet-20241022");
|
|
648
727
|
this.#options = options;
|
|
649
728
|
}
|
|
729
|
+
async #getClient() {
|
|
730
|
+
if (!this.#client) {
|
|
731
|
+
const { default: Client } = await import("@anthropic-ai/sdk").catch(() => {
|
|
732
|
+
throw new Error(
|
|
733
|
+
"The `@anthropic-ai/sdk` package is required for the Anthropic adapter.\nInstall it with: npm install @anthropic-ai/sdk"
|
|
734
|
+
);
|
|
735
|
+
});
|
|
736
|
+
this.#client = new Client({
|
|
737
|
+
apiKey: this.#options.apiKey ?? process.env["ANTHROPIC_API_KEY"],
|
|
738
|
+
maxRetries: this.#options.maxRetries ?? 3
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
return this.#client;
|
|
742
|
+
}
|
|
650
743
|
async _call(prompt, config) {
|
|
651
|
-
const
|
|
652
|
-
|
|
653
|
-
"The `@anthropic-ai/sdk` package is required for the Anthropic adapter.\nInstall it with: npm install @anthropic-ai/sdk"
|
|
654
|
-
);
|
|
655
|
-
});
|
|
656
|
-
const client = new Anthropic2({
|
|
657
|
-
apiKey: this.#options.apiKey ?? process.env["ANTHROPIC_API_KEY"],
|
|
658
|
-
maxRetries: this.#options.maxRetries ?? 3
|
|
659
|
-
});
|
|
744
|
+
const client = await this.#getClient();
|
|
745
|
+
const doCache = config.promptCaching ?? settings.lmConfig?.promptCaching ?? this.#options.promptCaching ?? false;
|
|
660
746
|
const msgs = typeof prompt === "string" ? [{ role: "user", content: prompt }] : prompt;
|
|
661
747
|
const systemMsg = msgs.find((m) => m.role === "system");
|
|
662
748
|
const userMsgs = msgs.filter((m) => m.role !== "system");
|
|
749
|
+
let systemPayload;
|
|
750
|
+
if (systemMsg) {
|
|
751
|
+
systemPayload = doCache ? [{ type: "text", text: systemMsg.content, cache_control: { type: "ephemeral" } }] : systemMsg.content;
|
|
752
|
+
}
|
|
753
|
+
const messagesPayload = userMsgs.map((m, idx) => {
|
|
754
|
+
const isLast = idx === userMsgs.length - 1;
|
|
755
|
+
return {
|
|
756
|
+
role: m.role,
|
|
757
|
+
content: doCache && isLast ? [{ type: "text", text: m.content, cache_control: { type: "ephemeral" } }] : m.content
|
|
758
|
+
};
|
|
759
|
+
});
|
|
663
760
|
const response = await client.messages.create({
|
|
664
761
|
model: config.model ?? this.model,
|
|
665
762
|
max_tokens: config.maxTokens ?? 1024,
|
|
666
|
-
system:
|
|
667
|
-
messages:
|
|
763
|
+
system: systemPayload,
|
|
764
|
+
messages: messagesPayload,
|
|
668
765
|
temperature: config.temperature,
|
|
669
766
|
...config.extra ?? {}
|
|
670
767
|
});
|
|
671
768
|
const text = response.content.filter((b) => b.type === "text").map((b) => b.text ?? "").join("") ?? "";
|
|
769
|
+
const usage = response.usage;
|
|
770
|
+
const cachedInput = (usage.cache_read_input_tokens ?? 0) + (usage.cache_creation_input_tokens ?? 0);
|
|
672
771
|
return {
|
|
673
772
|
text,
|
|
674
773
|
texts: [text],
|
|
675
|
-
usage:
|
|
676
|
-
promptTokens:
|
|
677
|
-
completionTokens:
|
|
678
|
-
totalTokens:
|
|
774
|
+
usage: usage ? {
|
|
775
|
+
promptTokens: usage.input_tokens,
|
|
776
|
+
completionTokens: usage.output_tokens,
|
|
777
|
+
totalTokens: usage.input_tokens + usage.output_tokens,
|
|
778
|
+
...cachedInput > 0 ? { cachedPromptTokens: cachedInput } : {}
|
|
679
779
|
} : null,
|
|
680
780
|
raw: response
|
|
681
781
|
};
|
|
682
782
|
}
|
|
683
783
|
async *stream(prompt, config = {}) {
|
|
684
|
-
const
|
|
685
|
-
|
|
686
|
-
"The `@anthropic-ai/sdk` package is required for the Anthropic adapter.\nInstall it with: npm install @anthropic-ai/sdk"
|
|
687
|
-
);
|
|
688
|
-
});
|
|
689
|
-
const client = new Anthropic2({
|
|
690
|
-
apiKey: this.#options.apiKey ?? process.env["ANTHROPIC_API_KEY"],
|
|
691
|
-
maxRetries: this.#options.maxRetries ?? 3
|
|
692
|
-
});
|
|
784
|
+
const client = await this.#getClient();
|
|
785
|
+
const doCache = config.promptCaching ?? settings.lmConfig?.promptCaching ?? this.#options.promptCaching ?? false;
|
|
693
786
|
const msgs = typeof prompt === "string" ? [{ role: "user", content: prompt }] : prompt;
|
|
694
787
|
const systemMsg = msgs.find((m) => m.role === "system");
|
|
695
788
|
const userMsgs = msgs.filter((m) => m.role !== "system");
|
|
789
|
+
let systemPayload;
|
|
790
|
+
if (systemMsg) {
|
|
791
|
+
systemPayload = doCache ? [{ type: "text", text: systemMsg.content, cache_control: { type: "ephemeral" } }] : systemMsg.content;
|
|
792
|
+
}
|
|
793
|
+
const messagesPayload = userMsgs.map((m, idx) => {
|
|
794
|
+
const isLast = idx === userMsgs.length - 1;
|
|
795
|
+
return {
|
|
796
|
+
role: m.role,
|
|
797
|
+
content: doCache && isLast ? [{ type: "text", text: m.content, cache_control: { type: "ephemeral" } }] : m.content
|
|
798
|
+
};
|
|
799
|
+
});
|
|
696
800
|
const stream = client.messages.stream({
|
|
697
801
|
model: config.model ?? this.model,
|
|
698
802
|
max_tokens: config.maxTokens ?? 1024,
|
|
699
|
-
system:
|
|
700
|
-
messages:
|
|
803
|
+
system: systemPayload,
|
|
804
|
+
messages: messagesPayload,
|
|
701
805
|
...config.extra ?? {}
|
|
702
806
|
});
|
|
703
807
|
for await (const event of stream) {
|
|
@@ -951,6 +1055,9 @@ var MockLM = class extends LM {
|
|
|
951
1055
|
};
|
|
952
1056
|
|
|
953
1057
|
// src/modules/Module.ts
|
|
1058
|
+
function firstPrediction(result) {
|
|
1059
|
+
return Array.isArray(result) ? result[0] ?? new Prediction({}) : result;
|
|
1060
|
+
}
|
|
954
1061
|
var Module = class _Module {
|
|
955
1062
|
/**
|
|
956
1063
|
* Recursively discover all {@link Predict} sub-modules by walking the own
|
|
@@ -1014,80 +1121,6 @@ var Module = class _Module {
|
|
|
1014
1121
|
}
|
|
1015
1122
|
};
|
|
1016
1123
|
|
|
1017
|
-
// src/settings/Settings.ts
|
|
1018
|
-
var import_node_async_hooks = require("async_hooks");
|
|
1019
|
-
var contextStore = new import_node_async_hooks.AsyncLocalStorage();
|
|
1020
|
-
var Settings = class {
|
|
1021
|
-
#global = {};
|
|
1022
|
-
// ---------------------------------------------------------------------------
|
|
1023
|
-
// Effective settings: async-context overrides take precedence over globals.
|
|
1024
|
-
// ---------------------------------------------------------------------------
|
|
1025
|
-
get #current() {
|
|
1026
|
-
const ctx = contextStore.getStore();
|
|
1027
|
-
return ctx !== void 0 ? { ...this.#global, ...ctx } : this.#global;
|
|
1028
|
-
}
|
|
1029
|
-
// ---------------------------------------------------------------------------
|
|
1030
|
-
// Accessors
|
|
1031
|
-
// ---------------------------------------------------------------------------
|
|
1032
|
-
get lm() {
|
|
1033
|
-
return this.#current.lm;
|
|
1034
|
-
}
|
|
1035
|
-
get rm() {
|
|
1036
|
-
return this.#current.rm;
|
|
1037
|
-
}
|
|
1038
|
-
get lmConfig() {
|
|
1039
|
-
return this.#current.lmConfig;
|
|
1040
|
-
}
|
|
1041
|
-
get logLevel() {
|
|
1042
|
-
return this.#current.logLevel ?? "warn";
|
|
1043
|
-
}
|
|
1044
|
-
get cacheDir() {
|
|
1045
|
-
return this.#current.cacheDir;
|
|
1046
|
-
}
|
|
1047
|
-
// ---------------------------------------------------------------------------
|
|
1048
|
-
// Mutation
|
|
1049
|
-
// ---------------------------------------------------------------------------
|
|
1050
|
-
/**
|
|
1051
|
-
* Merge `options` into the global settings. Existing keys are overwritten;
|
|
1052
|
-
* omitted keys are unchanged. This does NOT affect currently running
|
|
1053
|
-
* {@link Settings.context} scopes.
|
|
1054
|
-
*/
|
|
1055
|
-
configure(options) {
|
|
1056
|
-
this.#global = { ...this.#global, ...options };
|
|
1057
|
-
}
|
|
1058
|
-
/**
|
|
1059
|
-
* Reset all global settings to their defaults.
|
|
1060
|
-
*/
|
|
1061
|
-
reset() {
|
|
1062
|
-
this.#global = {};
|
|
1063
|
-
}
|
|
1064
|
-
/**
|
|
1065
|
-
* Return a deep-frozen snapshot of the currently effective settings
|
|
1066
|
-
* (respects any active async-context overrides).
|
|
1067
|
-
*/
|
|
1068
|
-
inspect() {
|
|
1069
|
-
return Object.freeze({ ...this.#current });
|
|
1070
|
-
}
|
|
1071
|
-
/**
|
|
1072
|
-
* Run `fn` inside an async-context-local settings scope.
|
|
1073
|
-
*
|
|
1074
|
-
* The `overrides` are merged on top of the current global settings and
|
|
1075
|
-
* stored in an `AsyncLocalStorage` context. Concurrent calls each get
|
|
1076
|
-
* their own isolated snapshot — they never overwrite each other's settings.
|
|
1077
|
-
*
|
|
1078
|
-
* @example
|
|
1079
|
-
* ```ts
|
|
1080
|
-
* // In an Express/Fastify handler:
|
|
1081
|
-
* await settings.context({ lm: perRequestLM }, () => program.forward(inputs));
|
|
1082
|
-
* ```
|
|
1083
|
-
*/
|
|
1084
|
-
async context(overrides, fn) {
|
|
1085
|
-
const merged = { ...this.#global, ...overrides };
|
|
1086
|
-
return contextStore.run(merged, fn);
|
|
1087
|
-
}
|
|
1088
|
-
};
|
|
1089
|
-
var settings = new Settings();
|
|
1090
|
-
|
|
1091
1124
|
// src/modules/Predict.ts
|
|
1092
1125
|
var Predict = class extends Module {
|
|
1093
1126
|
signature;
|
|
@@ -1107,9 +1140,7 @@ var Predict = class extends Module {
|
|
|
1107
1140
|
async forward(inputs) {
|
|
1108
1141
|
const lm = settings.lm;
|
|
1109
1142
|
if (!lm) {
|
|
1110
|
-
throw new Error(
|
|
1111
|
-
"No LM configured. Call settings.configure({ lm }) before using Predict."
|
|
1112
|
-
);
|
|
1143
|
+
throw new Error("No LM configured. Call settings.configure({ lm }) before using Predict.");
|
|
1113
1144
|
}
|
|
1114
1145
|
const prompt = this.#buildPrompt(inputs);
|
|
1115
1146
|
const config = settings.lmConfig ?? {};
|
|
@@ -1124,7 +1155,8 @@ var Predict = class extends Module {
|
|
|
1124
1155
|
*/
|
|
1125
1156
|
async *stream(inputs) {
|
|
1126
1157
|
const lm = settings.lm;
|
|
1127
|
-
if (!lm)
|
|
1158
|
+
if (!lm)
|
|
1159
|
+
throw new Error("No LM configured. Call settings.configure({ lm }) before using Predict.");
|
|
1128
1160
|
const prompt = this.#buildPrompt(inputs);
|
|
1129
1161
|
const config = settings.lmConfig ?? {};
|
|
1130
1162
|
yield* lm.stream(prompt, config);
|
|
@@ -1141,9 +1173,7 @@ var Predict = class extends Module {
|
|
|
1141
1173
|
}
|
|
1142
1174
|
load(state) {
|
|
1143
1175
|
if (Array.isArray(state["demos"])) {
|
|
1144
|
-
this.demos = state["demos"].map(
|
|
1145
|
-
(d) => new Example(d)
|
|
1146
|
-
);
|
|
1176
|
+
this.demos = state["demos"].map((d) => new Example(d));
|
|
1147
1177
|
}
|
|
1148
1178
|
if (typeof state["instructions"] === "string") {
|
|
1149
1179
|
this.instructions = state["instructions"];
|
|
@@ -1164,32 +1194,80 @@ var Predict = class extends Module {
|
|
|
1164
1194
|
}
|
|
1165
1195
|
}
|
|
1166
1196
|
lines.push(this.#formatInputs(inputs));
|
|
1167
|
-
for (const [name] of this.signature.outputs) {
|
|
1168
|
-
|
|
1197
|
+
for (const [name, meta] of this.signature.outputs) {
|
|
1198
|
+
const label = meta.prefix ?? `${name}:`;
|
|
1199
|
+
lines.push(label.endsWith(":") ? label : `${label}:`);
|
|
1169
1200
|
}
|
|
1170
1201
|
return lines.join("\n");
|
|
1171
1202
|
}
|
|
1172
1203
|
#formatExample(data) {
|
|
1173
|
-
|
|
1204
|
+
const formatField = (name, meta) => {
|
|
1205
|
+
const label = meta?.prefix ?? `${name}:`;
|
|
1206
|
+
const prefix = label.endsWith(":") ? label : `${label}:`;
|
|
1207
|
+
return `${prefix} ${String(data[name] ?? "")}`;
|
|
1208
|
+
};
|
|
1209
|
+
return [
|
|
1210
|
+
...[...this.signature.inputs].map(([name, meta]) => formatField(name, meta)),
|
|
1211
|
+
...[...this.signature.outputs].map(([name, meta]) => formatField(name, meta))
|
|
1212
|
+
].join("\n");
|
|
1174
1213
|
}
|
|
1175
1214
|
#formatInputs(inputs) {
|
|
1176
|
-
return [...this.signature.inputs].map(([name]) =>
|
|
1215
|
+
return [...this.signature.inputs].map(([name, meta]) => {
|
|
1216
|
+
const label = meta.prefix ?? `${name}:`;
|
|
1217
|
+
const prefix = label.endsWith(":") ? label : `${label}:`;
|
|
1218
|
+
return `${prefix} ${String(inputs[name] ?? "")}`;
|
|
1219
|
+
}).join("\n");
|
|
1177
1220
|
}
|
|
1178
1221
|
/**
|
|
1179
1222
|
* Parse a raw completion string into a map of field name → value.
|
|
1180
1223
|
*
|
|
1181
|
-
* Looks for `fieldName: <value>`
|
|
1224
|
+
* Looks for `fieldName: <value>` or `prefix: <value>` patterns in the completion.
|
|
1225
|
+
* Handles common LLM formatting like **bold**, *italic*, etc.
|
|
1226
|
+
* Supports multi-line values by extracting content between field markers.
|
|
1182
1227
|
*/
|
|
1183
1228
|
#parseCompletion(text) {
|
|
1184
1229
|
const result = {};
|
|
1185
|
-
const
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
const
|
|
1189
|
-
|
|
1190
|
-
|
|
1230
|
+
const outputs = [...this.signature.outputs.entries()];
|
|
1231
|
+
const fieldLabels = [];
|
|
1232
|
+
for (const [key, meta] of outputs) {
|
|
1233
|
+
const prefixBase = (meta.prefix ?? "").replace(/:$/, "").trim();
|
|
1234
|
+
const patterns = [key];
|
|
1235
|
+
if (prefixBase && prefixBase.toLowerCase() !== key.toLowerCase()) {
|
|
1236
|
+
patterns.push(prefixBase);
|
|
1237
|
+
}
|
|
1238
|
+
fieldLabels.push({ key, patterns });
|
|
1239
|
+
}
|
|
1240
|
+
const allPatterns = fieldLabels.flatMap((f) => f.patterns);
|
|
1241
|
+
const allPatternsEscaped = allPatterns.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
1242
|
+
const markerPattern = `(?:\\*\\*|\\*|_)?(${allPatternsEscaped.join("|")})(?:\\*\\*|\\*|_)?:`;
|
|
1243
|
+
const markerRegex = new RegExp(markerPattern, "gi");
|
|
1244
|
+
const markers = [];
|
|
1245
|
+
let markerMatch;
|
|
1246
|
+
while ((markerMatch = markerRegex.exec(text)) !== null) {
|
|
1247
|
+
const matchedLabel = markerMatch[1].toLowerCase();
|
|
1248
|
+
for (const { key, patterns } of fieldLabels) {
|
|
1249
|
+
if (patterns.some((p) => p.toLowerCase() === matchedLabel)) {
|
|
1250
|
+
markers.push({
|
|
1251
|
+
key,
|
|
1252
|
+
start: markerMatch.index,
|
|
1253
|
+
end: markerMatch.index + markerMatch[0].length
|
|
1254
|
+
});
|
|
1255
|
+
break;
|
|
1256
|
+
}
|
|
1191
1257
|
}
|
|
1192
1258
|
}
|
|
1259
|
+
for (let i = 0; i < markers.length; i++) {
|
|
1260
|
+
const marker = markers[i];
|
|
1261
|
+
const contentStart = marker.end;
|
|
1262
|
+
const contentEnd = i + 1 < markers.length ? markers[i + 1].start : text.length;
|
|
1263
|
+
let content = text.slice(contentStart, contentEnd).trim();
|
|
1264
|
+
content = content.replace(/^(\*\*|\*|_)+\s*/, "");
|
|
1265
|
+
content = content.replace(/\s*(\*\*|\*|_)+$/, "");
|
|
1266
|
+
if (!(marker.key in result)) {
|
|
1267
|
+
result[marker.key] = content;
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
const outputKeys = outputs.map(([k]) => k);
|
|
1193
1271
|
if (outputKeys.length === 1 && !(outputKeys[0] in result)) {
|
|
1194
1272
|
result[outputKeys[0]] = text.trim();
|
|
1195
1273
|
}
|
|
@@ -1235,9 +1313,6 @@ var ChainOfThoughtWithHint = class extends ChainOfThought {
|
|
|
1235
1313
|
});
|
|
1236
1314
|
Object.assign(this, { signature: extendedSig });
|
|
1237
1315
|
}
|
|
1238
|
-
async forward(inputs) {
|
|
1239
|
-
return super.forward(inputs);
|
|
1240
|
-
}
|
|
1241
1316
|
};
|
|
1242
1317
|
|
|
1243
1318
|
// src/modules/MultiChainComparison.ts
|
|
@@ -1255,14 +1330,23 @@ var MultiChainComparison = class extends Module {
|
|
|
1255
1330
|
}
|
|
1256
1331
|
async forward(inputs) {
|
|
1257
1332
|
const completions = [];
|
|
1333
|
+
const outputKey = [...this.#cot.signature.outputs.keys()].find((k) => k !== "rationale") ?? "answer";
|
|
1258
1334
|
for (let i = 0; i < this.M; i++) {
|
|
1259
1335
|
const result = await this.#cot.forward(inputs);
|
|
1260
|
-
|
|
1261
|
-
completions.push(String(result.get(outputKey ?? "answer") ?? ""));
|
|
1336
|
+
completions.push(String(result.get(outputKey) ?? ""));
|
|
1262
1337
|
}
|
|
1263
|
-
|
|
1338
|
+
const aggregated = await this.#aggregator.forward({
|
|
1264
1339
|
completions: completions.map((c, i) => `Option ${i + 1}: ${c}`).join("\n")
|
|
1265
1340
|
});
|
|
1341
|
+
const rawAnswer = String(aggregated.get("answer") ?? "");
|
|
1342
|
+
const optionMatch = /^Option\s*(\d+)/i.exec(rawAnswer);
|
|
1343
|
+
if (optionMatch) {
|
|
1344
|
+
const optionIdx = parseInt(optionMatch[1], 10) - 1;
|
|
1345
|
+
if (optionIdx >= 0 && optionIdx < completions.length) {
|
|
1346
|
+
return new Prediction({ answer: completions[optionIdx] ?? rawAnswer });
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
return new Prediction({ answer: rawAnswer });
|
|
1266
1350
|
}
|
|
1267
1351
|
};
|
|
1268
1352
|
|
|
@@ -1276,7 +1360,6 @@ var ReAct = class extends Module {
|
|
|
1276
1360
|
this.tools = new Map(tools.map((t) => [t.name, t]));
|
|
1277
1361
|
this.maxIter = maxIter;
|
|
1278
1362
|
const toolDescriptions = tools.map((t) => `${t.name}: ${t.description}`).join("\n");
|
|
1279
|
-
const base = typeof signature === "string" ? signature : signature;
|
|
1280
1363
|
const instructions = `You are an agent. Use the following tools:
|
|
1281
1364
|
${toolDescriptions}
|
|
1282
1365
|
|
|
@@ -1286,9 +1369,12 @@ Action: <tool>[<args>]
|
|
|
1286
1369
|
Observation: <result>
|
|
1287
1370
|
...
|
|
1288
1371
|
Finish[<answer>]`;
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1372
|
+
let baseSig = typeof signature === "string" ? Signature.from(signature) : signature;
|
|
1373
|
+
baseSig = baseSig.withInput("trajectory", {
|
|
1374
|
+
description: "Interleaved reasoning steps so far",
|
|
1375
|
+
optional: true
|
|
1376
|
+
});
|
|
1377
|
+
this.#predictor = new Predict(baseSig);
|
|
1292
1378
|
this.#predictor.instructions = instructions;
|
|
1293
1379
|
}
|
|
1294
1380
|
async forward(inputs) {
|
|
@@ -1371,10 +1457,11 @@ var ProgramOfThought = class extends Module {
|
|
|
1371
1457
|
for (let attempt = 0; attempt < this.maxAttempts; attempt++) {
|
|
1372
1458
|
const genInputs = attempt === 0 ? {
|
|
1373
1459
|
...inputs,
|
|
1374
|
-
instructions: "Write JavaScript code to compute the answer. Use a `return` statement for the final value."
|
|
1460
|
+
instructions: "Write JavaScript code to compute the answer. IMPORTANT: Use a `return` statement (not console.log) for the final value. Do not include markdown code fences."
|
|
1375
1461
|
} : { code, error: lastError };
|
|
1376
1462
|
const generated = attempt === 0 ? await this.#codeGenerator.forward(genInputs) : await this.#corrector.forward(genInputs);
|
|
1377
1463
|
code = String(generated.get("code") ?? generated.get("fixed_code") ?? "");
|
|
1464
|
+
code = code.replace(/^```(?:\w+)?\s*\n?/i, "").replace(/\n?```\s*$/i, "").trim();
|
|
1378
1465
|
try {
|
|
1379
1466
|
if (this.sandbox === "worker") {
|
|
1380
1467
|
result = await this.#executeInWorker(code, this.timeoutMs);
|
|
@@ -1513,7 +1600,9 @@ var Retry = class extends Module {
|
|
|
1513
1600
|
let lastError;
|
|
1514
1601
|
for (let attempt = 0; attempt < this.maxAttempts; attempt++) {
|
|
1515
1602
|
try {
|
|
1516
|
-
return
|
|
1603
|
+
return firstPrediction(
|
|
1604
|
+
await this.#inner.forward(...args)
|
|
1605
|
+
);
|
|
1517
1606
|
} catch (err) {
|
|
1518
1607
|
if (err instanceof AssertionError) {
|
|
1519
1608
|
lastError = err;
|
|
@@ -1548,7 +1637,7 @@ var BestOfN = class extends Module {
|
|
|
1548
1637
|
() => this.#inner.forward(...args)
|
|
1549
1638
|
)
|
|
1550
1639
|
);
|
|
1551
|
-
return this.#reduce(results);
|
|
1640
|
+
return this.#reduce(results.map(firstPrediction));
|
|
1552
1641
|
}
|
|
1553
1642
|
};
|
|
1554
1643
|
|
|
@@ -1567,7 +1656,7 @@ var Ensemble = class extends Module {
|
|
|
1567
1656
|
(m) => m.forward(...args)
|
|
1568
1657
|
)
|
|
1569
1658
|
);
|
|
1570
|
-
return this.#reduce(results);
|
|
1659
|
+
return this.#reduce(results.map(firstPrediction));
|
|
1571
1660
|
}
|
|
1572
1661
|
};
|
|
1573
1662
|
|
|
@@ -1676,6 +1765,7 @@ var TypedChainOfThought = class extends TypedPredictor {
|
|
|
1676
1765
|
};
|
|
1677
1766
|
|
|
1678
1767
|
// src/modules/Parallel.ts
|
|
1768
|
+
var import_node_timers = require("timers");
|
|
1679
1769
|
var Parallel = class extends Module {
|
|
1680
1770
|
#modules;
|
|
1681
1771
|
#timeoutMs;
|
|
@@ -1684,29 +1774,37 @@ var Parallel = class extends Module {
|
|
|
1684
1774
|
this.#modules = modules;
|
|
1685
1775
|
this.#timeoutMs = options.timeoutMs;
|
|
1686
1776
|
}
|
|
1687
|
-
/**
|
|
1777
|
+
/**
|
|
1778
|
+
* Run all modules in parallel and return one {@link Prediction} per module.
|
|
1779
|
+
* If a module's `forward()` returns multiple predictions, the first is used.
|
|
1780
|
+
*/
|
|
1688
1781
|
async run(...args) {
|
|
1689
1782
|
const tasks = this.#modules.map(
|
|
1690
1783
|
(m) => m.forward(...args)
|
|
1691
1784
|
);
|
|
1785
|
+
let settled;
|
|
1692
1786
|
if (this.#timeoutMs !== void 0) {
|
|
1693
1787
|
const timeoutMs = this.#timeoutMs;
|
|
1694
1788
|
const withTimeout = tasks.map(
|
|
1695
1789
|
(t) => Promise.race([
|
|
1696
1790
|
t,
|
|
1697
1791
|
new Promise(
|
|
1698
|
-
(_, reject) => setTimeout(() => reject(new Error("Parallel: timeout")), timeoutMs)
|
|
1792
|
+
(_, reject) => (0, import_node_timers.setTimeout)(() => reject(new Error("Parallel: timeout")), timeoutMs)
|
|
1699
1793
|
)
|
|
1700
1794
|
])
|
|
1701
1795
|
);
|
|
1702
|
-
|
|
1796
|
+
settled = Promise.all(withTimeout);
|
|
1797
|
+
} else {
|
|
1798
|
+
settled = Promise.all(tasks);
|
|
1703
1799
|
}
|
|
1704
|
-
return
|
|
1800
|
+
return (await settled).map(firstPrediction);
|
|
1705
1801
|
}
|
|
1706
|
-
/**
|
|
1802
|
+
/**
|
|
1803
|
+
* Execute all modules in parallel and return all predictions as an array
|
|
1804
|
+
* (one entry per module).
|
|
1805
|
+
*/
|
|
1707
1806
|
async forward(...args) {
|
|
1708
|
-
|
|
1709
|
-
return results[0];
|
|
1807
|
+
return this.run(...args);
|
|
1710
1808
|
}
|
|
1711
1809
|
};
|
|
1712
1810
|
|
|
@@ -1727,7 +1825,7 @@ var Refine = class extends Module {
|
|
|
1727
1825
|
}
|
|
1728
1826
|
async forward(...args) {
|
|
1729
1827
|
const innerForward = this.#inner.forward.bind(this.#inner);
|
|
1730
|
-
let prediction = await innerForward(...args);
|
|
1828
|
+
let prediction = firstPrediction(await innerForward(...args));
|
|
1731
1829
|
for (let i = 0; i < this.#maxRefinements; i++) {
|
|
1732
1830
|
if (this.#stopCondition?.(prediction)) break;
|
|
1733
1831
|
const outputStr = JSON.stringify(prediction.toDict());
|
|
@@ -1750,7 +1848,7 @@ var Refine = class extends Module {
|
|
|
1750
1848
|
};
|
|
1751
1849
|
}
|
|
1752
1850
|
try {
|
|
1753
|
-
prediction = await innerForward(...newArgs);
|
|
1851
|
+
prediction = firstPrediction(await innerForward(...newArgs));
|
|
1754
1852
|
} catch {
|
|
1755
1853
|
break;
|
|
1756
1854
|
}
|
|
@@ -2875,6 +2973,7 @@ var JsonFileTracker = class extends Tracker {
|
|
|
2875
2973
|
evaluate,
|
|
2876
2974
|
exactMatch,
|
|
2877
2975
|
f1,
|
|
2976
|
+
firstPrediction,
|
|
2878
2977
|
majority,
|
|
2879
2978
|
passAtK,
|
|
2880
2979
|
rouge,
|