jev-web 0.7.2 → 0.9.0

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/src/encode.mjs CHANGED
@@ -1,83 +1,83 @@
1
- // jev-web — pure input builder for open-jev-shaped models.
2
- //
3
- // Layout produced (mirrors the reference export):
4
- // [CLS] [STATE] state [Q] instructions [OPT] option … [SEP]
5
- //
6
- // `seg` carries a span slot per token: option tokens get their pair index,
7
- // question-instruction tokens get `totalPairs + question index`, everything
8
- // else -1. `pair_q` / `pair_opt` list the question slot and pair slot for
9
- // every (question, option) pair; `groups` groups pair indices per question.
10
- // The ONNX graph consumes these directly (see the model's export docs).
11
-
12
- export class DecisionInputTooLongError extends Error {
13
- constructor(message) {
14
- super(message);
15
- this.name = "DecisionInputTooLongError";
16
- }
17
- }
18
-
19
- // Runtime-independent: take pre-tokenized ids and lay out the sequence.
20
- export function buildDecisionInput({
21
- stateIds,
22
- markers, // { cls, sep, state, question, option } single token ids
23
- questions, // [{ type, instructionIds: number[], optionIds: number[][] }]
24
- maxStateTokens = 256,
25
- maxLen = 512,
26
- }) {
27
- if (!Array.isArray(stateIds)) throw new TypeError("stateIds must be an array of token ids");
28
- if (!Array.isArray(questions) || questions.length === 0) {
29
- throw new TypeError("questions must be a non-empty array of tokenized questions");
30
- }
31
- for (const key of ["cls", "sep", "state", "question", "option"]) {
32
- if (!Number.isInteger(markers?.[key])) throw new TypeError(`markers.${key} must be a token id`);
33
- }
34
-
35
- const truncated = stateIds.length > maxStateTokens;
36
- const state = truncated ? stateIds.slice(0, maxStateTokens) : stateIds;
37
-
38
- const inputIds = [markers.cls, markers.state, ...state];
39
- const seg = inputIds.map(() => -1);
40
- const pairQ = [];
41
- const pairOpt = [];
42
- const groups = [];
43
- const totalPairs = questions.reduce((n, q) => n + q.optionIds.length, 0);
44
-
45
- questions.forEach((q, qi) => {
46
- inputIds.push(markers.question, ...q.instructionIds);
47
- seg.push(-1, ...q.instructionIds.map(() => totalPairs + qi));
48
- groups.push(
49
- q.optionIds.map((ids) => {
50
- inputIds.push(markers.option, ...ids);
51
- seg.push(-1, ...ids.map(() => pairOpt.length));
52
- pairQ.push(totalPairs + qi);
53
- pairOpt.push(pairOpt.length);
54
- return pairOpt.length - 1;
55
- }),
56
- );
57
- });
58
- inputIds.push(markers.sep);
59
- seg.push(-1);
60
-
61
- if (inputIds.length > maxLen) {
62
- throw new DecisionInputTooLongError(
63
- `decision input is ${inputIds.length} tokens, over the ${maxLen}-token limit ` +
64
- `(state capped at ${maxStateTokens}) — shorten the questions or the state`,
65
- );
66
- }
67
- return { inputIds, seg, pairQ, pairOpt, groups, truncated, length: inputIds.length, totalPairs };
68
- }
69
-
70
- // Shared marker lookup: every marker must encode to exactly one token id.
71
- // (Custom typed-decision exports add [STATE]/[Q]/[OPT] to the tokenizer; if
72
- // they are missing, the model is not a typed-decision export.)
73
- export function typedMarkerIds(encodeFn, { markers = ["[STATE]", "[Q]", "[OPT]"], cls = "[CLS]", sep = "[SEP]" } = {}) {
74
- const one = (text) => {
75
- const ids = encodeFn(text);
76
- if (!Array.isArray(ids) || ids.length !== 1) {
77
- throw new Error(`marker ${text} must encode to exactly one token (got ${ids?.length ?? 0})`);
78
- }
79
- return ids[0];
80
- };
81
- const [state, question, option] = markers.map(one);
82
- return { cls: one(cls), sep: one(sep), state, question, option };
83
- }
1
+ // jev-web — pure input builder for open-jev-shaped models.
2
+ //
3
+ // Layout produced (mirrors the reference export):
4
+ // [CLS] [STATE] state [Q] instructions [OPT] option … [SEP]
5
+ //
6
+ // `seg` carries a span slot per token: option tokens get their pair index,
7
+ // question-instruction tokens get `totalPairs + question index`, everything
8
+ // else -1. `pair_q` / `pair_opt` list the question slot and pair slot for
9
+ // every (question, option) pair; `groups` groups pair indices per question.
10
+ // The ONNX graph consumes these directly (see the model's export docs).
11
+
12
+ export class DecisionInputTooLongError extends Error {
13
+ constructor(message) {
14
+ super(message);
15
+ this.name = "DecisionInputTooLongError";
16
+ }
17
+ }
18
+
19
+ // Runtime-independent: take pre-tokenized ids and lay out the sequence.
20
+ export function buildDecisionInput({
21
+ stateIds,
22
+ markers, // { cls, sep, state, question, option } single token ids
23
+ questions, // [{ type, instructionIds: number[], optionIds: number[][] }]
24
+ maxStateTokens = 256,
25
+ maxLen = 512,
26
+ }) {
27
+ if (!Array.isArray(stateIds)) throw new TypeError("stateIds must be an array of token ids");
28
+ if (!Array.isArray(questions) || questions.length === 0) {
29
+ throw new TypeError("questions must be a non-empty array of tokenized questions");
30
+ }
31
+ for (const key of ["cls", "sep", "state", "question", "option"]) {
32
+ if (!Number.isInteger(markers?.[key])) throw new TypeError(`markers.${key} must be a token id`);
33
+ }
34
+
35
+ const truncated = stateIds.length > maxStateTokens;
36
+ const state = truncated ? stateIds.slice(0, maxStateTokens) : stateIds;
37
+
38
+ const inputIds = [markers.cls, markers.state, ...state];
39
+ const seg = inputIds.map(() => -1);
40
+ const pairQ = [];
41
+ const pairOpt = [];
42
+ const groups = [];
43
+ const totalPairs = questions.reduce((n, q) => n + q.optionIds.length, 0);
44
+
45
+ questions.forEach((q, qi) => {
46
+ inputIds.push(markers.question, ...q.instructionIds);
47
+ seg.push(-1, ...q.instructionIds.map(() => totalPairs + qi));
48
+ groups.push(
49
+ q.optionIds.map((ids) => {
50
+ inputIds.push(markers.option, ...ids);
51
+ seg.push(-1, ...ids.map(() => pairOpt.length));
52
+ pairQ.push(totalPairs + qi);
53
+ pairOpt.push(pairOpt.length);
54
+ return pairOpt.length - 1;
55
+ }),
56
+ );
57
+ });
58
+ inputIds.push(markers.sep);
59
+ seg.push(-1);
60
+
61
+ if (inputIds.length > maxLen) {
62
+ throw new DecisionInputTooLongError(
63
+ `decision input is ${inputIds.length} tokens, over the ${maxLen}-token limit ` +
64
+ `(state capped at ${maxStateTokens}) — shorten the questions or the state`,
65
+ );
66
+ }
67
+ return { inputIds, seg, pairQ, pairOpt, groups, truncated, length: inputIds.length, totalPairs };
68
+ }
69
+
70
+ // Shared marker lookup: every marker must encode to exactly one token id.
71
+ // (Custom typed-decision exports add [STATE]/[Q]/[OPT] to the tokenizer; if
72
+ // they are missing, the model is not a typed-decision export.)
73
+ export function typedMarkerIds(encodeFn, { markers = ["[STATE]", "[Q]", "[OPT]"], cls = "[CLS]", sep = "[SEP]" } = {}) {
74
+ const one = (text) => {
75
+ const ids = encodeFn(text);
76
+ if (!Array.isArray(ids) || ids.length !== 1) {
77
+ throw new Error(`marker ${text} must encode to exactly one token (got ${ids?.length ?? 0})`);
78
+ }
79
+ return ids[0];
80
+ };
81
+ const [state, question, option] = markers.map(one);
82
+ return { cls: one(cls), sep: one(sep), state, question, option };
83
+ }
package/src/index.mjs CHANGED
@@ -1,113 +1,197 @@
1
- // jev-web — public API (typed decisions in the browser).
2
- export { createDecider } from "./session.mjs";
3
- export {
4
- registerDecisionFamily, createDecisionRuntime,
5
- listDecisionFamilies, getDecisionFamily,
6
- } from "./registry.mjs";
7
- export { normalizeQuestions, QUESTION_TYPES, NOUL_OPTIONS } from "./questions.mjs";
8
- export { buildDecisionInput, typedMarkerIds, DecisionInputTooLongError } from "./encode.mjs";
9
- export { answersFromScores, softmaxWithTemperature } from "./answers.mjs";
10
- export {
11
- createLayaDecider,
12
- buildLayaSequence,
13
- collateLayaItems,
14
- layaAnswersFromLogits,
15
- layaTokenizerAdapter,
16
- renderLayaOptions,
17
- layaTempBucket,
18
- clampTemperature,
19
- LAYA_DEFAULT_MODEL,
20
- LAYA_DEFAULT_REVISION,
21
- LAYA_DEFAULT_SUBFOLDER,
22
- LAYA_DEFAULT_TEMPERATURES,
23
- LAYA_DEFAULT_TEMPERATURES_BY_OPTIONS,
24
- LAYA_DEFAULT_MAX_LEN,
25
- LAYA_DEFAULT_HEAD_MAX_LEN,
26
- LAYA_DEFAULT_MAX_PREFIXES,
27
- LAYA_QTYPE,
28
- LAYA_TEMP_MIN,
29
- LAYA_TEMP_MAX,
30
- } from "./laya.mjs";
31
- export {
32
- createStrandsDecider,
33
- renderStrandsQuestion,
34
- renderStrandsState,
35
- renderStrandsContent,
36
- buildStrandsBatch,
37
- collateStrandsItems,
38
- strandsOptionTokenIndices,
39
- strandsAnswersFromLogits,
40
- strandsChoiceConfidence,
41
- strandsScoreConfidence,
42
- STRANDS_DEFAULT_MODEL,
43
- STRANDS_DEFAULT_REVISION,
44
- STRANDS_DEFAULT_FILE,
45
- STRANDS_TEMPERATURE,
46
- STRANDS_TEMPERATURE_BY_KIND,
47
- STRANDS_ORDINAL_SMOOTHING,
48
- STRANDS_DEFAULT_MAX_LEN,
49
- STRANDS_MAX_QUESTION_FRACTION,
50
- STRANDS_KIND,
51
- } from "./strands.mjs";
52
- export {
53
- createBekkoDecider,
54
- renderBekkoContent,
55
- renderBekkoRequest,
56
- tokenizeBekkoRequest,
57
- collateBekkoDocs,
58
- bekkoSoftmax,
59
- bekkoAnswerFromLogits,
60
- BEKKO_DEFAULT_MODEL,
61
- BEKKO_DEFAULT_REVISION,
62
- BEKKO_DEFAULT_SUBDIR,
63
- BEKKO_68M_MODEL,
64
- BEKKO_68M_REVISION,
65
- BEKKO_400M_MODEL,
66
- BEKKO_400M_REVISION,
67
- BEKKO_VARIANTS,
68
- BEKKO_ATTENTION_BUDGET,
69
- BEKKO_DEFAULT_YES,
70
- BEKKO_DEFAULT_NO,
71
- BEKKO_NOUL_DESCRIPTIONS,
72
- } from "./bekko.mjs";
73
- export {
74
- createDecision2Decider,
75
- renderDecision2Content,
76
- renderDecision2Options,
77
- buildDecision2Segments,
78
- tokenizeDecision2Segments,
79
- decision2Softmax,
80
- decision2AnswerFromLogits,
81
- DECISION2_DEFAULT_MODEL,
82
- DECISION2_DEFAULT_REVISION,
83
- DECISION2_DEFAULT_FILE,
84
- DECISION2_EOS_MODEL,
85
- DECISION2_EOS_REVISION,
86
- DECISION2_SOL_MODEL,
87
- DECISION2_SOL_REVISION,
88
- DECISION2_VARIANTS,
89
- DECISION2_MAX_INPUT_TOKENS,
90
- DECISION2_NOUL_DESCRIPTIONS,
91
- } from "./decision2.mjs";
92
- export {
93
- createKevDecider,
94
- escapeKevText,
95
- packKevSequence,
96
- KEV_DEFAULT_MODEL,
97
- KEV_DEFAULT_REVISION,
98
- KEV_4B_MODEL,
99
- KEV_4B_REVISION,
100
- KEV_VARIANTS,
101
- } from "./kev.mjs";
102
- export {
103
- DEFAULT_MODEL,
104
- DEFAULT_REVISION,
105
- DEFAULT_TEMPERATURE,
106
- DEFAULT_MARKERS,
107
- DEFAULT_MAX_STATE_TOKENS,
108
- DEFAULT_MAX_LEN,
109
- resolveDevice,
110
- resolveDtype,
111
- detectWebGPU,
112
- loadModelConfig,
1
+ // jev-web — public API (typed decisions in the browser).
2
+ export { createDecider } from "./session.mjs";
3
+ export {
4
+ registerDecisionFamily, createDecisionRuntime,
5
+ listDecisionFamilies, getDecisionFamily,
6
+ } from "./registry.mjs";
7
+ export { normalizeQuestions, QUESTION_TYPES, NOUL_OPTIONS } from "./questions.mjs";
8
+ export { buildDecisionInput, typedMarkerIds, DecisionInputTooLongError } from "./encode.mjs";
9
+ export { answersFromScores, softmaxWithTemperature } from "./answers.mjs";
10
+ export {
11
+ createLayaDecider,
12
+ buildLayaSequence,
13
+ collateLayaItems,
14
+ layaAnswersFromLogits,
15
+ layaTokenizerAdapter,
16
+ renderLayaOptions,
17
+ layaTempBucket,
18
+ clampTemperature,
19
+ LAYA_DEFAULT_MODEL,
20
+ LAYA_DEFAULT_REVISION,
21
+ LAYA_DEFAULT_SUBFOLDER,
22
+ LAYA_DEFAULT_TEMPERATURES,
23
+ LAYA_DEFAULT_TEMPERATURES_BY_OPTIONS,
24
+ LAYA_DEFAULT_MAX_LEN,
25
+ LAYA_DEFAULT_HEAD_MAX_LEN,
26
+ LAYA_DEFAULT_MAX_PREFIXES,
27
+ LAYA_QTYPE,
28
+ LAYA_TEMP_MIN,
29
+ LAYA_TEMP_MAX,
30
+ } from "./laya.mjs";
31
+ export {
32
+ createStrandsDecider,
33
+ renderStrandsQuestion,
34
+ renderStrandsState,
35
+ renderStrandsContent,
36
+ buildStrandsBatch,
37
+ collateStrandsItems,
38
+ strandsOptionTokenIndices,
39
+ strandsAnswersFromLogits,
40
+ strandsChoiceConfidence,
41
+ strandsScoreConfidence,
42
+ parseStrandsCalibration,
43
+ loadStrandsCalibration,
44
+ STRANDS_DEFAULT_MODEL,
45
+ STRANDS_DEFAULT_REVISION,
46
+ STRANDS_DEFAULT_FILE,
47
+ STRANDS_TEMPERATURE,
48
+ STRANDS_TEMPERATURE_BY_KIND,
49
+ STRANDS_ORDINAL_SMOOTHING,
50
+ STRANDS_DEFAULT_MAX_LEN,
51
+ STRANDS_MAX_QUESTION_FRACTION,
52
+ STRANDS_KIND,
53
+ STRANDS_CONFIG_FILES,
54
+ STRANDS_VARIANTS,
55
+ } from "./strands.mjs";
56
+ export {
57
+ createBekkoDecider,
58
+ renderBekkoContent,
59
+ renderBekkoRequest,
60
+ tokenizeBekkoRequest,
61
+ collateBekkoDocs,
62
+ bekkoSoftmax,
63
+ bekkoAnswerFromLogits,
64
+ BEKKO_DEFAULT_MODEL,
65
+ BEKKO_DEFAULT_REVISION,
66
+ BEKKO_DEFAULT_SUBDIR,
67
+ BEKKO_68M_MODEL,
68
+ BEKKO_68M_REVISION,
69
+ BEKKO_400M_MODEL,
70
+ BEKKO_400M_REVISION,
71
+ BEKKO_VARIANTS,
72
+ BEKKO_ATTENTION_BUDGET,
73
+ BEKKO_DEFAULT_YES,
74
+ BEKKO_DEFAULT_NO,
75
+ BEKKO_NOUL_DESCRIPTIONS,
76
+ } from "./bekko.mjs";
77
+ export {
78
+ createDecision2Decider,
79
+ renderDecision2Content,
80
+ renderDecision2Options,
81
+ buildDecision2Segments,
82
+ tokenizeDecision2Segments,
83
+ decision2Softmax,
84
+ decision2AnswerFromLogits,
85
+ DECISION2_DEFAULT_MODEL,
86
+ DECISION2_DEFAULT_REVISION,
87
+ DECISION2_DEFAULT_FILE,
88
+ DECISION2_EOS_MODEL,
89
+ DECISION2_EOS_REVISION,
90
+ DECISION2_SOL_MODEL,
91
+ DECISION2_SOL_REVISION,
92
+ DECISION2_VARIANTS,
93
+ DECISION2_MAX_INPUT_TOKENS,
94
+ DECISION2_NOUL_DESCRIPTIONS,
95
+ } from "./decision2.mjs";
96
+ export {
97
+ createKevDecider,
98
+ escapeKevText,
99
+ packKevSequence,
100
+ KEV_DEFAULT_MODEL,
101
+ KEV_DEFAULT_REVISION,
102
+ KEV_4B_MODEL,
103
+ KEV_4B_REVISION,
104
+ KEV_VARIANTS,
105
+ } from "./kev.mjs";
106
+ export {
107
+ createVegaDecider,
108
+ buildVegaPrompt,
109
+ packVegaBatch,
110
+ packVegaChunks,
111
+ vegaQuestionDef,
112
+ vegaOptionTexts,
113
+ vegaThermalFeatures,
114
+ vegaThermalProbabilities,
115
+ vegaAnswers,
116
+ vegaOptionLabels,
117
+ renderVegaText,
118
+ vegaJsonDumps,
119
+ vegaRoute,
120
+ vegaTextPositions,
121
+ emptyVegaPast,
122
+ poolVegaHidden,
123
+ VEGA_DEFAULT_MODEL,
124
+ VEGA_DEFAULT_REVISION,
125
+ VEGA_TORSO_FILE,
126
+ VEGA_ENGINE_FILE,
127
+ VEGA_Q8_DEFAULT_MODEL,
128
+ VEGA_Q8_DEFAULT_REVISION,
129
+ VEGA_Q8_DEFAULT_SUBFOLDER,
130
+ VEGA_Q8_EMBED_FILE,
131
+ VEGA_Q8_DECODER_FILE,
132
+ VEGA_Q8_ENGINE_FILE,
133
+ VEGA_VARIANTS,
134
+ VEGA_QTYPE,
135
+ VEGA_QTYPE_NAMES,
136
+ VEGA_DEFAULTS,
137
+ VEGA_DEFAULT_THETA,
138
+ } from "./vega.mjs";
139
+ export {
140
+ createClefDecider,
141
+ encodeClefRecord,
142
+ packClefBatch,
143
+ clefQuestionOptions,
144
+ clefAnswers,
145
+ renderClefContent,
146
+ CLEF_DEFAULT_MODEL,
147
+ CLEF_DEFAULT_REVISION,
148
+ CLEF_DEFAULT_FILE,
149
+ CLEF_DEFAULT_MAX_LEN,
150
+ CLEF_SYSTEM_PROMPT,
151
+ CLEF_QTYPE,
152
+ CLEF_QTYPE_NAMES,
153
+ CLEF_NOUL_DESCRIPTIONS,
154
+ CLEF_DEFAULTS,
155
+ } from "./clef.mjs";
156
+ export {
157
+ createDecision3Decider,
158
+ buildDecision3Prompt,
159
+ decision3Messages,
160
+ renderDecision3Chat,
161
+ normalizeDecision3Question,
162
+ decision3OptionTexts,
163
+ decision3CandidateCodes,
164
+ decision3ProbsFromLogits,
165
+ decision3Confidence,
166
+ decision3Answers,
167
+ packDecision3Batch,
168
+ renderDecision3Json,
169
+ renderDecision3Canonical,
170
+ describeDecision3Value,
171
+ DECISION3_DEFAULT_MODEL,
172
+ DECISION3_DEFAULT_REVISION,
173
+ DECISION3_TORSO_FILE,
174
+ DECISION3_READOUT_FILE,
175
+ DECISION3_DEFAULT_BATCH_SIZE,
176
+ DECISION3_DEFAULT_MAX_LEN,
177
+ DECISION3_MAX_OPTIONS,
178
+ DECISION3_SCORE_LEVELS,
179
+ DECISION3_SYSTEM_PROMPT,
180
+ DECISION3_NOUL_DESCRIPTIONS,
181
+ DECISION3_DEFAULT_INSTRUCTIONS,
182
+ DECISION3_DEFAULTS,
183
+ DECISION3_VARIANTS,
184
+ DECISION3_DEFAULT_CODES,
185
+ } from "./decision3.mjs";
186
+ export {
187
+ DEFAULT_MODEL,
188
+ DEFAULT_REVISION,
189
+ DEFAULT_TEMPERATURE,
190
+ DEFAULT_MARKERS,
191
+ DEFAULT_MAX_STATE_TOKENS,
192
+ DEFAULT_MAX_LEN,
193
+ resolveDevice,
194
+ resolveDtype,
195
+ detectWebGPU,
196
+ loadModelConfig,
113
197
  } from "./config.mjs";