adaptive-memory-multi-model-router 2.16.2 → 2.16.4
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/.github/CODEOWNERS +2 -0
- package/.github/FUNDING.yml +7 -1
- package/.github/ISSUE_TEMPLATE/bug_report.md +56 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +41 -0
- package/.github/workflows/pages.yml +1 -1
- package/CHANGELOG.md +15 -8
- package/CONTRIBUTING.md +109 -25
- package/README.md +131 -219
- package/data/jev-distill.jsonl +320 -0
- package/dist/routing/jev/jevRouter.d.ts +49 -0
- package/dist/routing/jev/jevRouter.js +231 -0
- package/dist/routing/jev/jevRouter.js.map +1 -0
- package/dist/routing/jev/optionAttention.d.ts +63 -0
- package/dist/routing/jev/optionAttention.js +158 -0
- package/dist/routing/jev/optionAttention.js.map +1 -0
- package/dist/routing/jev/remote.d.ts +14 -0
- package/dist/routing/jev/remote.js +55 -0
- package/dist/routing/jev/remote.js.map +1 -0
- package/dist/routing/jev/types.d.ts +71 -0
- package/dist/routing/jev/types.js +19 -0
- package/dist/routing/jev/types.js.map +1 -0
- package/dist/routing/jev/weights/jev-router-weights.json +1 -0
- package/dist/server/modelMapper.js +18 -0
- package/dist/server/modelMapper.js.map +1 -1
- package/docs/assets/og-banner.svg +193 -0
- package/docs/index.html +1523 -465
- package/docs-site/index.html +1427 -563
- package/package.json +29 -20
- package/python/pyproject.toml +1 -1
- package/src/cli/setupWizard.ts +4 -2
- package/src/routing/jev/jevRouter.ts +251 -0
- package/src/routing/jev/optionAttention.ts +186 -0
- package/src/routing/jev/remote.ts +50 -0
- package/src/routing/jev/types.ts +79 -0
- package/src/routing/jev/weights/jev-router-weights.json +1 -0
- package/src/server/modelMapper.ts +17 -0
- package/tests/routing/jev.test.ts +110 -0
- package/tools/calibrate_temp.py +81 -0
- package/tools/distill.mjs +143 -0
- package/tools/train_jev.py +213 -0
- package/dist/cli/tui.d.ts +0 -6
- package/dist/cli/tui.js.map +0 -1
- package/dist/routing/shadowSampler.d.ts.map +0 -1
- /package/{ARCHITECTURE.md → archive/ARCHITECTURE.md} +0 -0
- /package/{ENTERPRISE_INTEGRATIONS.md → archive/ENTERPRISE_INTEGRATIONS.md} +0 -0
- /package/{MANIFESTO.md → archive/MANIFESTO.md} +0 -0
- /package/{README_ja.md → archive/README_ja.md} +0 -0
- /package/{README_zh.md → archive/README_zh.md} +0 -0
- /package/{SECURITY.md → archive/SECURITY.md} +0 -0
- /package/{TECHNICAL_README.md → archive/TECHNICAL_README.md} +0 -0
- /package/{TODO_BROWSER_AUTOMATION.md → archive/TODO_BROWSER_AUTOMATION.md} +0 -0
- /package/{AGENT_COUNCIL_FINDINGS.md → archive/campaign/AGENT_COUNCIL_FINDINGS.md} +0 -0
- /package/{AUDIT_REPORT.md → archive/campaign/AUDIT_REPORT.md} +0 -0
- /package/{CONTRIBUTORS.md → archive/campaign/CONTRIBUTORS.md} +0 -0
- /package/{IMPROVEMENT_PLAN.md → archive/campaign/IMPROVEMENT_PLAN.md} +0 -0
- /package/{INTEGRATION_PROGRESS.md → archive/campaign/INTEGRATION_PROGRESS.md} +0 -0
- /package/{CAMPAIGN_SUMMARY.md → archive/launch/CAMPAIGN_SUMMARY.md} +0 -0
- /package/{LANDING.md → archive/launch/LANDING.md} +0 -0
- /package/{LAUNCH-PAIN-DRIVEN.md → archive/launch/LAUNCH-PAIN-DRIVEN.md} +0 -0
- /package/{LAUNCH.md → archive/launch/LAUNCH.md} +0 -0
- /package/{LAUNCH_CHECKLIST.md → archive/launch/LAUNCH_CHECKLIST.md} +0 -0
- /package/{LAUNCH_SNAPSHOT.md → archive/launch/LAUNCH_SNAPSHOT.md} +0 -0
- /package/{REDESIGN.md → archive/launch/REDESIGN.md} +0 -0
- /package/{HEALTH_REPORT.md → archive/research/HEALTH_REPORT.md} +0 -0
- /package/{OPPORTUNITIES_100.md → archive/research/OPPORTUNITIES_100.md} +0 -0
- /package/{POPULARITY_BOOSTERS.md → archive/research/POPULARITY_BOOSTERS.md} +0 -0
- /package/{PR_STATUS_REPORT.md → archive/research/PR_STATUS_REPORT.md} +0 -0
- /package/{research-log.md → archive/research/research-log.md} +0 -0
- /package/{RELEASE_v2.16.0.md → archive/submissions/RELEASE_v2.16.0.md} +0 -0
- /package/{RUNKIT.md → archive/submissions/RUNKIT.md} +0 -0
- /package/{SUBMISSIONS.md → archive/submissions/SUBMISSIONS.md} +0 -0
- /package/{a3m-integrations-summary.md → archive/submissions/a3m-integrations-summary.md} +0 -0
- /package/{discoverability-diagnosis.md → archive/submissions/discoverability-diagnosis.md} +0 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JevRouter — System One routing for A3M.
|
|
3
|
+
*
|
|
4
|
+
* Replaces the autoregressive/heuristic routing loop with a single-pass
|
|
5
|
+
* calibrated decision (Jev interface pattern):
|
|
6
|
+
*
|
|
7
|
+
* prompt ──► OptionAttention engine ──► { provider choice, complexity score,
|
|
8
|
+
* capability noul flags }
|
|
9
|
+
*
|
|
10
|
+
* The engine is distilled from A3M's own System 2 router (advancedRouter.ts):
|
|
11
|
+
* tools/distill.mjs runs routeQuery over a synthetic prompt corpus and
|
|
12
|
+
* tools/train_jev.py trains the ~25k-parameter option-attention weights.
|
|
13
|
+
*
|
|
14
|
+
* Confidence guard: if the top provider probability is below MIN_CONFIDENCE,
|
|
15
|
+
* we fall back to the full heuristic router (System 2) — Jev decides the easy
|
|
16
|
+
* 90%, the heavy router handles the hard 10%.
|
|
17
|
+
*/
|
|
18
|
+
import { type RouteDecision } from "../advancedRouter";
|
|
19
|
+
import { type OptionAttentionWeights } from "./optionAttention";
|
|
20
|
+
import type { JevResponse } from "./types";
|
|
21
|
+
/** Below this top-probability, defer to the System 2 heuristic router. */
|
|
22
|
+
export declare const MIN_CONFIDENCE = 0.22;
|
|
23
|
+
export declare function loadWeights(): OptionAttentionWeights | null;
|
|
24
|
+
/** For tests / hot-reload of retrained weights. */
|
|
25
|
+
export declare function resetWeightsCache(): void;
|
|
26
|
+
/**
|
|
27
|
+
* Build the option text for a model profile. Option text is what the engine
|
|
28
|
+
* embeds — providers unseen at training time are still scored through their
|
|
29
|
+
* strengths/tier description.
|
|
30
|
+
*/
|
|
31
|
+
export declare function optionTextForModel(model: string, profile: {
|
|
32
|
+
providerName?: string;
|
|
33
|
+
strengths?: string[];
|
|
34
|
+
quality_score?: number;
|
|
35
|
+
cost_per_1k_input?: number;
|
|
36
|
+
cost_per_1k_output?: number;
|
|
37
|
+
type?: string;
|
|
38
|
+
}): string;
|
|
39
|
+
/**
|
|
40
|
+
* Single-pass Jev routing decision. Returns a RouteDecision shaped exactly
|
|
41
|
+
* like advancedRouter.routeQuery so it is a drop-in replacement.
|
|
42
|
+
*/
|
|
43
|
+
export declare function jevRoute(prompt: string, available_models?: string[], budget_multiplier?: number): RouteDecision & {
|
|
44
|
+
jev?: JevResponse;
|
|
45
|
+
};
|
|
46
|
+
/** Async variant with remote backend support. */
|
|
47
|
+
export declare function jevRouteAsync(prompt: string, available_models?: string[], budget_multiplier?: number): Promise<RouteDecision & {
|
|
48
|
+
jev?: JevResponse;
|
|
49
|
+
}>;
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* JevRouter — System One routing for A3M.
|
|
4
|
+
*
|
|
5
|
+
* Replaces the autoregressive/heuristic routing loop with a single-pass
|
|
6
|
+
* calibrated decision (Jev interface pattern):
|
|
7
|
+
*
|
|
8
|
+
* prompt ──► OptionAttention engine ──► { provider choice, complexity score,
|
|
9
|
+
* capability noul flags }
|
|
10
|
+
*
|
|
11
|
+
* The engine is distilled from A3M's own System 2 router (advancedRouter.ts):
|
|
12
|
+
* tools/distill.mjs runs routeQuery over a synthetic prompt corpus and
|
|
13
|
+
* tools/train_jev.py trains the ~25k-parameter option-attention weights.
|
|
14
|
+
*
|
|
15
|
+
* Confidence guard: if the top provider probability is below MIN_CONFIDENCE,
|
|
16
|
+
* we fall back to the full heuristic router (System 2) — Jev decides the easy
|
|
17
|
+
* 90%, the heavy router handles the hard 10%.
|
|
18
|
+
*/
|
|
19
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
22
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
23
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
24
|
+
}
|
|
25
|
+
Object.defineProperty(o, k2, desc);
|
|
26
|
+
}) : (function(o, m, k, k2) {
|
|
27
|
+
if (k2 === undefined) k2 = k;
|
|
28
|
+
o[k2] = m[k];
|
|
29
|
+
}));
|
|
30
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
31
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
32
|
+
}) : function(o, v) {
|
|
33
|
+
o["default"] = v;
|
|
34
|
+
});
|
|
35
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
36
|
+
var ownKeys = function(o) {
|
|
37
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
38
|
+
var ar = [];
|
|
39
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
40
|
+
return ar;
|
|
41
|
+
};
|
|
42
|
+
return ownKeys(o);
|
|
43
|
+
};
|
|
44
|
+
return function (mod) {
|
|
45
|
+
if (mod && mod.__esModule) return mod;
|
|
46
|
+
var result = {};
|
|
47
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
48
|
+
__setModuleDefault(result, mod);
|
|
49
|
+
return result;
|
|
50
|
+
};
|
|
51
|
+
})();
|
|
52
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
+
exports.MIN_CONFIDENCE = void 0;
|
|
54
|
+
exports.loadWeights = loadWeights;
|
|
55
|
+
exports.resetWeightsCache = resetWeightsCache;
|
|
56
|
+
exports.optionTextForModel = optionTextForModel;
|
|
57
|
+
exports.jevRoute = jevRoute;
|
|
58
|
+
exports.jevRouteAsync = jevRouteAsync;
|
|
59
|
+
const fs = __importStar(require("fs"));
|
|
60
|
+
const path = __importStar(require("path"));
|
|
61
|
+
const advancedRouter_1 = require("../advancedRouter");
|
|
62
|
+
const optionAttention_1 = require("./optionAttention");
|
|
63
|
+
const remote_1 = require("./remote");
|
|
64
|
+
const WEIGHTS_PATHS = [
|
|
65
|
+
path.join(__dirname, "weights", "jev-router-weights.json"), // dist copy
|
|
66
|
+
path.join(__dirname, "..", "..", "..", "src", "routing", "jev", "weights", "jev-router-weights.json"), // repo fallback
|
|
67
|
+
];
|
|
68
|
+
/** Below this top-probability, defer to the System 2 heuristic router. */
|
|
69
|
+
exports.MIN_CONFIDENCE = 0.22;
|
|
70
|
+
let cachedWeights;
|
|
71
|
+
function loadWeights() {
|
|
72
|
+
if (cachedWeights !== undefined)
|
|
73
|
+
return cachedWeights;
|
|
74
|
+
try {
|
|
75
|
+
for (const p of WEIGHTS_PATHS) {
|
|
76
|
+
if (fs.existsSync(p)) {
|
|
77
|
+
cachedWeights = JSON.parse(fs.readFileSync(p, "utf8"));
|
|
78
|
+
return cachedWeights;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
cachedWeights = null;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
cachedWeights = null;
|
|
85
|
+
}
|
|
86
|
+
return cachedWeights;
|
|
87
|
+
}
|
|
88
|
+
/** For tests / hot-reload of retrained weights. */
|
|
89
|
+
function resetWeightsCache() {
|
|
90
|
+
cachedWeights = undefined;
|
|
91
|
+
(0, optionAttention_1.resetQueryCache)();
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Build the option text for a model profile. Option text is what the engine
|
|
95
|
+
* embeds — providers unseen at training time are still scored through their
|
|
96
|
+
* strengths/tier description.
|
|
97
|
+
*/
|
|
98
|
+
function optionTextForModel(model, profile) {
|
|
99
|
+
const strengths = (profile.strengths || []).slice(0, 6).join(",");
|
|
100
|
+
const cost = profile.cost_per_1k_input != null
|
|
101
|
+
? ((profile.cost_per_1k_input + (profile.cost_per_1k_output || 0)) / 2).toFixed(4)
|
|
102
|
+
: "?";
|
|
103
|
+
return `${model} provider:${profile.providerName || "?"} type:${profile.type || "api"} strengths:${strengths} quality:${profile.quality_score ?? "?"} cost:${cost}`;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Single-pass Jev routing decision. Returns a RouteDecision shaped exactly
|
|
107
|
+
* like advancedRouter.routeQuery so it is a drop-in replacement.
|
|
108
|
+
*/
|
|
109
|
+
function jevRoute(prompt, available_models, budget_multiplier = 1.0) {
|
|
110
|
+
// 1. Remote backend (openjev-sglang / typesafe) takes precedence if configured
|
|
111
|
+
if ((0, remote_1.remoteConfigured)()) {
|
|
112
|
+
// remoteDecide is async; jevRoute is sync to match routeQuery's contract.
|
|
113
|
+
// Remote mode is exposed via jevRouteAsync below.
|
|
114
|
+
}
|
|
115
|
+
const weights = loadWeights();
|
|
116
|
+
if (!weights)
|
|
117
|
+
return fallbackRoute(prompt, available_models, budget_multiplier, "no weights");
|
|
118
|
+
// 2. Candidate pool — mirror routeQuery's candidate selection
|
|
119
|
+
const profiles = getModelProfilesSafe();
|
|
120
|
+
const candidateNames = (available_models && available_models.length
|
|
121
|
+
? available_models
|
|
122
|
+
: Object.keys(profiles)).filter((n) => profiles[n]);
|
|
123
|
+
if (candidateNames.length === 0)
|
|
124
|
+
return fallbackRoute(prompt, available_models, budget_multiplier, "no candidates");
|
|
125
|
+
const t0 = Date.now();
|
|
126
|
+
const options = candidateNames.map((m) => optionTextForModel(m, profiles[m]));
|
|
127
|
+
const { probs, top } = (0, optionAttention_1.scoreOptions)(prompt, options, weights);
|
|
128
|
+
const complexity = (0, optionAttention_1.scoreScalar)(prompt, weights);
|
|
129
|
+
const { value: needsCode, prob: codeProb } = (0, optionAttention_1.scoreNoul)(prompt, "requires code generation", weights);
|
|
130
|
+
const elapsed = Date.now() - t0;
|
|
131
|
+
const bestIdx = top[0]?.index ?? -1;
|
|
132
|
+
const bestProb = top[0]?.prob ?? 0;
|
|
133
|
+
const jev = {
|
|
134
|
+
answers: [
|
|
135
|
+
{
|
|
136
|
+
type: "choice",
|
|
137
|
+
key: "provider",
|
|
138
|
+
value: bestIdx >= 0 ? candidateNames[bestIdx] : "",
|
|
139
|
+
prob: bestProb,
|
|
140
|
+
top: top.map((t) => ({ option: candidateNames[t.index], prob: t.prob })),
|
|
141
|
+
},
|
|
142
|
+
{ type: "score", key: "complexity", value: complexity },
|
|
143
|
+
{ type: "noul", key: "needs_code", value: needsCode, prob: codeProb },
|
|
144
|
+
],
|
|
145
|
+
elapsed_ms: elapsed,
|
|
146
|
+
backend: "local-weights",
|
|
147
|
+
};
|
|
148
|
+
// 3. Confidence guard → System 2 fallback
|
|
149
|
+
if (bestProb < exports.MIN_CONFIDENCE || bestIdx < 0) {
|
|
150
|
+
const fb = fallbackRoute(prompt, available_models, budget_multiplier, `low confidence ${bestProb.toFixed(2)}`);
|
|
151
|
+
return { ...fb, jev };
|
|
152
|
+
}
|
|
153
|
+
const primary = candidateNames[bestIdx];
|
|
154
|
+
const profile = profiles[primary];
|
|
155
|
+
const fallbacks = top.slice(1, 3).map((t) => candidateNames[t.index]);
|
|
156
|
+
return {
|
|
157
|
+
primary_model: primary,
|
|
158
|
+
fallback_models: fallbacks,
|
|
159
|
+
confidence: bestProb,
|
|
160
|
+
reasoning: `jev single-pass (distilled): p=${bestProb.toFixed(3)} complexity=${complexity.toFixed(2)} needs_code=${needsCode}(${codeProb.toFixed(2)}) [${elapsed}ms]`,
|
|
161
|
+
estimated_cost: ((profile.cost_per_1k_input || 0) + (profile.cost_per_1k_output || 0)) / 2,
|
|
162
|
+
estimated_latency_ms: profile.latency_ms || 500,
|
|
163
|
+
provider_type: profile.type,
|
|
164
|
+
jev,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/** Async variant with remote backend support. */
|
|
168
|
+
async function jevRouteAsync(prompt, available_models, budget_multiplier = 1.0) {
|
|
169
|
+
if ((0, remote_1.remoteConfigured)()) {
|
|
170
|
+
const profiles = getModelProfilesSafe();
|
|
171
|
+
const candidates = (available_models && available_models.length
|
|
172
|
+
? available_models
|
|
173
|
+
: Object.keys(profiles)).filter((n) => profiles[n]);
|
|
174
|
+
const remote = await (0, remote_1.remoteDecide)({
|
|
175
|
+
state: prompt,
|
|
176
|
+
questions: [
|
|
177
|
+
{
|
|
178
|
+
type: "choice",
|
|
179
|
+
key: "provider",
|
|
180
|
+
description: "best model for this query",
|
|
181
|
+
options: candidates.map((m) => optionTextForModel(m, profiles[m])),
|
|
182
|
+
},
|
|
183
|
+
],
|
|
184
|
+
});
|
|
185
|
+
if (remote) {
|
|
186
|
+
const choice = remote.answers[0];
|
|
187
|
+
if (choice && choice.type === "choice") {
|
|
188
|
+
// map option text back to model name
|
|
189
|
+
const idx = candidates.findIndex((m) => choice.value.startsWith(m + " "));
|
|
190
|
+
const primary = idx >= 0 ? candidates[idx] : candidates.find((c) => choice.value.includes(c));
|
|
191
|
+
if (primary) {
|
|
192
|
+
const profile = profiles[primary];
|
|
193
|
+
return {
|
|
194
|
+
primary_model: primary,
|
|
195
|
+
fallback_models: [],
|
|
196
|
+
confidence: choice.prob,
|
|
197
|
+
reasoning: `jev remote (${remote.backend}) [${remote.elapsed_ms}ms]`,
|
|
198
|
+
estimated_cost: ((profile.cost_per_1k_input || 0) + (profile.cost_per_1k_output || 0)) / 2,
|
|
199
|
+
estimated_latency_ms: profile.latency_ms || 500,
|
|
200
|
+
provider_type: profile.type,
|
|
201
|
+
jev: remote,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return jevRoute(prompt, available_models, budget_multiplier);
|
|
208
|
+
}
|
|
209
|
+
// ---------------------------------------------------------------------------
|
|
210
|
+
// internals
|
|
211
|
+
// ---------------------------------------------------------------------------
|
|
212
|
+
const advancedRouter_2 = require("../advancedRouter");
|
|
213
|
+
function getModelProfilesSafe() {
|
|
214
|
+
// MODEL_PROFILES is populated by the first routeQuery call (profile cache).
|
|
215
|
+
if (Object.keys(advancedRouter_2.MODEL_PROFILES).length === 0)
|
|
216
|
+
(0, advancedRouter_1.routeQuery)("warmup");
|
|
217
|
+
return advancedRouter_2.MODEL_PROFILES;
|
|
218
|
+
}
|
|
219
|
+
function fallbackRoute(prompt, available_models, budget_multiplier, why) {
|
|
220
|
+
const d = (0, advancedRouter_1.routeQuery)(prompt, available_models, budget_multiplier);
|
|
221
|
+
return {
|
|
222
|
+
...d,
|
|
223
|
+
reasoning: `system2-fallback (${why}): ${d.reasoning}`,
|
|
224
|
+
jev: {
|
|
225
|
+
answers: [],
|
|
226
|
+
elapsed_ms: 0,
|
|
227
|
+
backend: "fallback-heuristic",
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=jevRouter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jevRouter.js","sourceRoot":"","sources":["../../../src/routing/jev/jevRouter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OptionAttention — a pure-TypeScript System One decision engine.
|
|
3
|
+
*
|
|
4
|
+
* Port of the architecture popularized by vinnylarouge/jevlike (835★):
|
|
5
|
+
*
|
|
6
|
+
* Each option becomes a query vector. The query assigns attention weights
|
|
7
|
+
* to the context tokens; those weights produce one attended context vector
|
|
8
|
+
* per option. A shared dot product turns each (option, context) pair into
|
|
9
|
+
* one score. A softmax across options yields calibrated probabilities —
|
|
10
|
+
* all in a single forward pass, no autoregressive generation.
|
|
11
|
+
*
|
|
12
|
+
* Why this architecture for A3M:
|
|
13
|
+
* - Dynamic option sets: providers come and go; unseen options are scored
|
|
14
|
+
* through their text (name + strengths + tier), so the engine generalizes
|
|
15
|
+
* to providers it was never trained on.
|
|
16
|
+
* - Zero dependencies: byte-level embeddings, ~25k parameters, weights ship
|
|
17
|
+
* as JSON inside the npm package.
|
|
18
|
+
* - CPU-fast: single matmul chain, sub-millisecond for 100+ options.
|
|
19
|
+
*/
|
|
20
|
+
export interface OptionAttentionWeights {
|
|
21
|
+
/** Hashed trigram embedding table: VOCAB × D. */
|
|
22
|
+
emb: number[][];
|
|
23
|
+
/** Option projection: D × D. */
|
|
24
|
+
wq: number[][];
|
|
25
|
+
bq: number[];
|
|
26
|
+
/** Shared scoring vector: D. */
|
|
27
|
+
w: number[];
|
|
28
|
+
b: number[];
|
|
29
|
+
/** Score head (context pooled → sigmoid): D + 2. */
|
|
30
|
+
ws: number[];
|
|
31
|
+
bs: number[];
|
|
32
|
+
/** Temperature for calibrated softmax. */
|
|
33
|
+
temperature: number;
|
|
34
|
+
dim: number;
|
|
35
|
+
}
|
|
36
|
+
/** Number of trigram hash buckets (must match tools/train_jev.py). */
|
|
37
|
+
export declare const VOCAB = 2048;
|
|
38
|
+
/**
|
|
39
|
+
* Hashed trigram tokenization — character trigrams give much sharper text
|
|
40
|
+
* discrimination than raw bytes ("chat" vs "code" produce disjoint buckets).
|
|
41
|
+
*/
|
|
42
|
+
export declare function tokenize(text: string): number[];
|
|
43
|
+
export declare function resetQueryCache(): void;
|
|
44
|
+
export interface ChoiceResult {
|
|
45
|
+
probs: number[];
|
|
46
|
+
top: Array<{
|
|
47
|
+
index: number;
|
|
48
|
+
prob: number;
|
|
49
|
+
}>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Score N options against a context in one pass.
|
|
53
|
+
* Attention: a_ij = softmax_j( q_i · E_j / √D ), c_i = Σ_j a_ij E_j
|
|
54
|
+
* Score: s_i = w · (q_i ⊙ c_i) + b, probs = softmax(s / T)
|
|
55
|
+
*/
|
|
56
|
+
export declare function scoreOptions(context: string, options: string[], weights: OptionAttentionWeights): ChoiceResult;
|
|
57
|
+
/** Context → scalar in [0,1] via sigmoid(w_s · meanPool + b_s). */
|
|
58
|
+
export declare function scoreScalar(context: string, weights: OptionAttentionWeights): number;
|
|
59
|
+
/** Boolean decision with calibrated probability (2-way choice). */
|
|
60
|
+
export declare function scoreNoul(context: string, questionText: string, weights: OptionAttentionWeights): {
|
|
61
|
+
value: boolean;
|
|
62
|
+
prob: number;
|
|
63
|
+
};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OptionAttention — a pure-TypeScript System One decision engine.
|
|
4
|
+
*
|
|
5
|
+
* Port of the architecture popularized by vinnylarouge/jevlike (835★):
|
|
6
|
+
*
|
|
7
|
+
* Each option becomes a query vector. The query assigns attention weights
|
|
8
|
+
* to the context tokens; those weights produce one attended context vector
|
|
9
|
+
* per option. A shared dot product turns each (option, context) pair into
|
|
10
|
+
* one score. A softmax across options yields calibrated probabilities —
|
|
11
|
+
* all in a single forward pass, no autoregressive generation.
|
|
12
|
+
*
|
|
13
|
+
* Why this architecture for A3M:
|
|
14
|
+
* - Dynamic option sets: providers come and go; unseen options are scored
|
|
15
|
+
* through their text (name + strengths + tier), so the engine generalizes
|
|
16
|
+
* to providers it was never trained on.
|
|
17
|
+
* - Zero dependencies: byte-level embeddings, ~25k parameters, weights ship
|
|
18
|
+
* as JSON inside the npm package.
|
|
19
|
+
* - CPU-fast: single matmul chain, sub-millisecond for 100+ options.
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.VOCAB = void 0;
|
|
23
|
+
exports.tokenize = tokenize;
|
|
24
|
+
exports.resetQueryCache = resetQueryCache;
|
|
25
|
+
exports.scoreOptions = scoreOptions;
|
|
26
|
+
exports.scoreScalar = scoreScalar;
|
|
27
|
+
exports.scoreNoul = scoreNoul;
|
|
28
|
+
/** Number of trigram hash buckets (must match tools/train_jev.py). */
|
|
29
|
+
exports.VOCAB = 2048;
|
|
30
|
+
/**
|
|
31
|
+
* FNV-1a 32-bit hash of a character trigram → bucket id.
|
|
32
|
+
* Must match the Python trainer exactly.
|
|
33
|
+
*/
|
|
34
|
+
function trigramHash(b0, b1, b2) {
|
|
35
|
+
let h = 0x811c9dc5;
|
|
36
|
+
h = Math.imul(h ^ (b0 & 0xff), 0x01000193) >>> 0;
|
|
37
|
+
h = Math.imul(h ^ (b1 & 0xff), 0x01000193) >>> 0;
|
|
38
|
+
h = Math.imul(h ^ (b2 & 0xff), 0x01000193) >>> 0;
|
|
39
|
+
return h % exports.VOCAB;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Hashed trigram tokenization — character trigrams give much sharper text
|
|
43
|
+
* discrimination than raw bytes ("chat" vs "code" produce disjoint buckets).
|
|
44
|
+
*/
|
|
45
|
+
function tokenize(text) {
|
|
46
|
+
const s = " " + text + " ";
|
|
47
|
+
const out = [];
|
|
48
|
+
const cap = 384;
|
|
49
|
+
for (let i = 0; i + 2 < s.length && out.length < cap; i++) {
|
|
50
|
+
out.push(trigramHash(s.charCodeAt(i), s.charCodeAt(i + 1), s.charCodeAt(i + 2)));
|
|
51
|
+
}
|
|
52
|
+
if (out.length === 0)
|
|
53
|
+
out.push(trigramHash(32, 32, 32));
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
function meanPool(rows, weights) {
|
|
57
|
+
const D = weights.dim;
|
|
58
|
+
const out = new Array(D).fill(0);
|
|
59
|
+
if (rows.length === 0)
|
|
60
|
+
return out;
|
|
61
|
+
for (const r of rows)
|
|
62
|
+
for (let d = 0; d < D; d++)
|
|
63
|
+
out[d] += r[d];
|
|
64
|
+
for (let d = 0; d < D; d++)
|
|
65
|
+
out[d] /= rows.length;
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
function embed(tokens, weights) {
|
|
69
|
+
return tokens.map((t) => weights.emb[t % exports.VOCAB]);
|
|
70
|
+
}
|
|
71
|
+
/** Cache: option text → query vector. Option texts are static per provider
|
|
72
|
+
* profile, so q_i never changes between calls — skip the W_q matmul. */
|
|
73
|
+
const queryCache = new Map();
|
|
74
|
+
function resetQueryCache() {
|
|
75
|
+
queryCache.clear();
|
|
76
|
+
}
|
|
77
|
+
/** Option text → query vector q_i = W_q · meanPool(bytes) + b_q */
|
|
78
|
+
function optionQuery(optionText, weights) {
|
|
79
|
+
const hit = queryCache.get(optionText);
|
|
80
|
+
if (hit)
|
|
81
|
+
return hit;
|
|
82
|
+
const D = weights.dim;
|
|
83
|
+
const h = meanPool(embed(tokenize(optionText), weights), weights);
|
|
84
|
+
const q = new Array(D).fill(0);
|
|
85
|
+
for (let i = 0; i < D; i++) {
|
|
86
|
+
let s = weights.bq[i];
|
|
87
|
+
for (let j = 0; j < D; j++)
|
|
88
|
+
s += weights.wq[i][j] * h[j];
|
|
89
|
+
q[i] = Math.tanh(s);
|
|
90
|
+
}
|
|
91
|
+
if (queryCache.size > 512)
|
|
92
|
+
queryCache.clear();
|
|
93
|
+
queryCache.set(optionText, q);
|
|
94
|
+
return q;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Score N options against a context in one pass.
|
|
98
|
+
* Attention: a_ij = softmax_j( q_i · E_j / √D ), c_i = Σ_j a_ij E_j
|
|
99
|
+
* Score: s_i = w · (q_i ⊙ c_i) + b, probs = softmax(s / T)
|
|
100
|
+
*/
|
|
101
|
+
function scoreOptions(context, options, weights) {
|
|
102
|
+
const D = weights.dim;
|
|
103
|
+
const E = embed(tokenize(context), weights);
|
|
104
|
+
const scale = 1 / Math.sqrt(D);
|
|
105
|
+
const probs = [];
|
|
106
|
+
for (const opt of options) {
|
|
107
|
+
const q = optionQuery(opt, weights);
|
|
108
|
+
// attention over context tokens
|
|
109
|
+
const attn = E.map((e) => {
|
|
110
|
+
let dot = 0;
|
|
111
|
+
for (let d = 0; d < D; d++)
|
|
112
|
+
dot += q[d] * e[d];
|
|
113
|
+
return dot * scale;
|
|
114
|
+
});
|
|
115
|
+
const maxA = Math.max(...attn, 0);
|
|
116
|
+
const exps = attn.map((a) => Math.exp(a - maxA));
|
|
117
|
+
const sumA = exps.reduce((a, b) => a + b, 0) || 1;
|
|
118
|
+
// attended context vector c_i
|
|
119
|
+
const c = new Array(D).fill(0);
|
|
120
|
+
for (let j = 0; j < E.length; j++) {
|
|
121
|
+
const a = exps[j] / sumA;
|
|
122
|
+
if (a < 1e-6)
|
|
123
|
+
continue;
|
|
124
|
+
for (let d = 0; d < D; d++)
|
|
125
|
+
c[d] += a * E[j][d];
|
|
126
|
+
}
|
|
127
|
+
// score_i = w · (q ⊙ c) + b
|
|
128
|
+
let s = weights.b[0];
|
|
129
|
+
for (let d = 0; d < D; d++)
|
|
130
|
+
s += weights.w[d] * q[d] * c[d];
|
|
131
|
+
probs.push(s / weights.temperature);
|
|
132
|
+
}
|
|
133
|
+
const maxS = Math.max(...probs);
|
|
134
|
+
const expP = probs.map((p) => Math.exp(p - maxS));
|
|
135
|
+
const sumP = expP.reduce((a, b) => a + b, 0) || 1;
|
|
136
|
+
const final = expP.map((e) => e / sumP);
|
|
137
|
+
const top = final
|
|
138
|
+
.map((prob, index) => ({ index, prob }))
|
|
139
|
+
.sort((a, b) => b.prob - a.prob)
|
|
140
|
+
.slice(0, 5);
|
|
141
|
+
return { probs: final, top };
|
|
142
|
+
}
|
|
143
|
+
/** Context → scalar in [0,1] via sigmoid(w_s · meanPool + b_s). */
|
|
144
|
+
function scoreScalar(context, weights) {
|
|
145
|
+
const D = weights.dim;
|
|
146
|
+
const p = meanPool(embed(tokenize(context), weights), weights);
|
|
147
|
+
let s = weights.bs[0];
|
|
148
|
+
for (let d = 0; d < D; d++)
|
|
149
|
+
s += weights.ws[d] * p[d];
|
|
150
|
+
return 1 / (1 + Math.exp(-s));
|
|
151
|
+
}
|
|
152
|
+
/** Boolean decision with calibrated probability (2-way choice). */
|
|
153
|
+
function scoreNoul(context, questionText, weights) {
|
|
154
|
+
const r = scoreOptions(context, [questionText + " — yes", questionText + " — no"], weights);
|
|
155
|
+
const yesProb = r.probs[0];
|
|
156
|
+
return { value: yesProb >= 0.5, prob: Math.max(yesProb, 1 - yesProb) };
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=optionAttention.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"optionAttention.js","sourceRoot":"","sources":["../../../src/routing/jev/optionAttention.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;GAkBG;;;AAsCH,4BAeC;AAmBD,0CAEC;AA6BD,oCA4CC;AAGD,kCAMC;AAGD,8BAQC;AApJD,sEAAsE;AACzD,QAAA,KAAK,GAAG,IAAI,CAAC;AAE1B;;;GAGG;AACH,SAAS,WAAW,CAAC,EAAU,EAAE,EAAU,EAAE,EAAU;IACrD,IAAI,CAAC,GAAG,UAAU,CAAC;IACnB,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IACjD,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IACjD,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,aAAK,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,SAAgB,QAAQ,CAAC,IAAY;IACnC,MAAM,CAAC,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,CAAC;IAC3B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,GAAG,GAAG,GAAG,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1D,GAAG,CAAC,IAAI,CACN,WAAW,CACT,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EACf,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,EACnB,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CACpB,CACF,CAAC;IACJ,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IACxD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,QAAQ,CAAC,IAAgB,EAAE,OAA+B;IACjE,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IACtB,MAAM,GAAG,GAAG,IAAI,KAAK,CAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACzC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAClC,KAAK,MAAM,CAAC,IAAI,IAAI;QAAE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC;IAClD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,KAAK,CAAC,MAAgB,EAAE,OAA+B;IAC9D,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,aAAK,CAAC,CAAC,CAAC;AACnD,CAAC;AAED;wEACwE;AACxE,MAAM,UAAU,GAAG,IAAI,GAAG,EAAoB,CAAC;AAE/C,SAAgB,eAAe;IAC7B,UAAU,CAAC,KAAK,EAAE,CAAC;AACrB,CAAC;AAED,mEAAmE;AACnE,SAAS,WAAW,CAAC,UAAkB,EAAE,OAA+B;IACtE,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACvC,IAAI,GAAG;QAAE,OAAO,GAAG,CAAC;IACpB,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IACtB,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;IAClE,MAAM,CAAC,GAAG,IAAI,KAAK,CAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,IAAI,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAAE,CAAC,IAAI,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtB,CAAC;IACD,IAAI,UAAU,CAAC,IAAI,GAAG,GAAG;QAAE,UAAU,CAAC,KAAK,EAAE,CAAC;IAC9C,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC;AACX,CAAC;AAOD;;;;GAIG;AACH,SAAgB,YAAY,CAC1B,OAAe,EACf,OAAiB,EACjB,OAA+B;IAE/B,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IACtB,MAAM,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAE/B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACpC,gCAAgC;QAChC,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACvB,IAAI,GAAG,GAAG,CAAC,CAAC;YACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;gBAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/C,OAAO,GAAG,GAAG,KAAK,CAAC;QACrB,CAAC,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAClD,8BAA8B;QAC9B,MAAM,CAAC,GAAG,IAAI,KAAK,CAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAClC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;YACzB,IAAI,CAAC,GAAG,IAAI;gBAAE,SAAS;YACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;gBAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,CAAC;QACD,4BAA4B;QAC5B,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAAE,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IAClD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAExC,MAAM,GAAG,GAAG,KAAK;SACd,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;SACvC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC;SAC/B,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACf,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AAC/B,CAAC;AAED,mEAAmE;AACnE,SAAgB,WAAW,CAAC,OAAe,EAAE,OAA+B;IAC1E,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IACtB,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;IAC/D,IAAI,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;QAAE,CAAC,IAAI,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,mEAAmE;AACnE,SAAgB,SAAS,CACvB,OAAe,EACf,YAAoB,EACpB,OAA+B;IAE/B,MAAM,CAAC,GAAG,YAAY,CAAC,OAAO,EAAE,CAAC,YAAY,GAAG,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;IAC5F,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3B,OAAO,EAAE,KAAK,EAAE,OAAO,IAAI,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC;AACzE,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote backend for Jev-compatible endpoints.
|
|
3
|
+
*
|
|
4
|
+
* Works with:
|
|
5
|
+
* - api.typesafe.ai (commercial Jev, "System One")
|
|
6
|
+
* - ekzhang/openjev-sglang (open, Jev HTTP API on SGLang; self-host on Modal)
|
|
7
|
+
*
|
|
8
|
+
* Configure via env:
|
|
9
|
+
* A3M_JEV_URL — endpoint base (e.g. https://your-server.modal.direct)
|
|
10
|
+
* A3M_JEV_API_KEY — optional bearer token
|
|
11
|
+
*/
|
|
12
|
+
import type { JevRequest, JevResponse } from "./types";
|
|
13
|
+
export declare function remoteConfigured(): boolean;
|
|
14
|
+
export declare function remoteDecide(req: JevRequest, timeoutMs?: number): Promise<JevResponse | null>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Remote backend for Jev-compatible endpoints.
|
|
4
|
+
*
|
|
5
|
+
* Works with:
|
|
6
|
+
* - api.typesafe.ai (commercial Jev, "System One")
|
|
7
|
+
* - ekzhang/openjev-sglang (open, Jev HTTP API on SGLang; self-host on Modal)
|
|
8
|
+
*
|
|
9
|
+
* Configure via env:
|
|
10
|
+
* A3M_JEV_URL — endpoint base (e.g. https://your-server.modal.direct)
|
|
11
|
+
* A3M_JEV_API_KEY — optional bearer token
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.remoteConfigured = remoteConfigured;
|
|
15
|
+
exports.remoteDecide = remoteDecide;
|
|
16
|
+
function remoteConfigured() {
|
|
17
|
+
return Boolean(process.env.A3M_JEV_URL);
|
|
18
|
+
}
|
|
19
|
+
async function remoteDecide(req, timeoutMs = 2000) {
|
|
20
|
+
const base = process.env.A3M_JEV_URL;
|
|
21
|
+
if (!base)
|
|
22
|
+
return null;
|
|
23
|
+
const key = process.env.A3M_JEV_API_KEY || "";
|
|
24
|
+
const controller = new AbortController();
|
|
25
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
26
|
+
const t0 = Date.now();
|
|
27
|
+
try {
|
|
28
|
+
const res = await fetch(`${base.replace(/\/$/, "")}/v1/decide`, {
|
|
29
|
+
method: "POST",
|
|
30
|
+
headers: {
|
|
31
|
+
"content-type": "application/json",
|
|
32
|
+
...(key ? { authorization: `Bearer ${key}` } : {}),
|
|
33
|
+
},
|
|
34
|
+
body: JSON.stringify(req),
|
|
35
|
+
signal: controller.signal,
|
|
36
|
+
});
|
|
37
|
+
if (!res.ok)
|
|
38
|
+
return null;
|
|
39
|
+
const data = (await res.json());
|
|
40
|
+
if (!Array.isArray(data.answers))
|
|
41
|
+
return null;
|
|
42
|
+
return {
|
|
43
|
+
answers: data.answers,
|
|
44
|
+
elapsed_ms: Date.now() - t0,
|
|
45
|
+
backend: "remote",
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
clearTimeout(timer);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=remote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote.js","sourceRoot":"","sources":["../../../src/routing/jev/remote.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAIH,4CAEC;AAED,oCA+BC;AAnCD,SAAgB,gBAAgB;IAC9B,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAC1C,CAAC;AAEM,KAAK,UAAU,YAAY,CAAC,GAAe,EAAE,SAAS,GAAG,IAAI;IAClE,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;IACrC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC;IAE9C,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;IAC9D,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACtB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,EAAE;YAC9D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACnD;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;YACzB,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QACzB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA0B,CAAC;QACzD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC;QAC9C,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAiC;YAC/C,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE;YAC3B,OAAO,EAAE,QAAQ;SAClB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC"}
|