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.
Binary file
package/package.json CHANGED
@@ -1,60 +1,64 @@
1
- {
2
- "name": "jev-web",
3
- "version": "0.7.2",
4
- "description": "Run open-jev-, Laya- and Strands-Decider-shaped typed-decision models in the browser: one state plus typed questions in, calibrated probabilities out.",
5
- "type": "module",
6
- "license": "MIT",
7
- "repository": {
8
- "type": "git",
9
- "url": "git+https://github.com/warsang/jev-web.git"
10
- },
11
- "homepage": "https://warsang.github.io/jev-web/",
12
- "bugs": {
13
- "url": "https://github.com/warsang/jev-web/issues"
14
- },
15
- "exports": {
16
- ".": "./src/index.mjs"
17
- },
18
- "files": [
19
- "src/",
20
- "docs/",
21
- "README.md"
22
- ],
23
- "keywords": [
24
- "open-jev",
25
- "laya",
26
- "strands-decider",
27
- "typed-decisions",
28
- "onnx",
29
- "transformers.js",
30
- "webgpu",
31
- "browser",
32
- "classification"
33
- ],
34
- "scripts": {
35
- "dev": "vite",
36
- "build:dev": "vite build",
37
- "demo": "vite --config vite.demo.config.js",
38
- "build:demo": "vite build --config vite.demo.config.js",
39
- "test": "node --test test/*.test.mjs"
40
- },
41
- "peerDependencies": {
42
- "@huggingface/transformers": ">=3.0.0",
43
- "onnxruntime-web": ">=1.17.0"
44
- },
45
- "peerDependenciesMeta": {
46
- "@huggingface/transformers": {
47
- "optional": true
48
- },
49
- "onnxruntime-web": {
50
- "optional": true
51
- }
52
- },
53
- "devDependencies": {
54
- "@huggingface/transformers": "^4.3.0",
55
- "vite": "^6.3.5"
56
- },
57
- "engines": {
58
- "node": ">=20"
59
- }
60
- }
1
+ {
2
+ "name": "jev-web",
3
+ "version": "0.9.0",
4
+ "description": "Run open-jev-, Laya-, Strands-Decider-, Bekko-, Decision-, Kev-, Vega-, clef-shaped typed-decision models in the browser: one state plus typed questions in, calibrated probabilities out.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/warsang/jev-web.git"
10
+ },
11
+ "homepage": "https://warsang.github.io/jev-web/",
12
+ "bugs": {
13
+ "url": "https://github.com/warsang/jev-web/issues"
14
+ },
15
+ "exports": {
16
+ ".": "./src/index.mjs"
17
+ },
18
+ "files": [
19
+ "src/",
20
+ "docs/",
21
+ "README.md"
22
+ ],
23
+ "keywords": [
24
+ "open-jev",
25
+ "laya",
26
+ "strands-decider",
27
+ "bekko",
28
+ "decision2",
29
+ "decision3",
30
+ "kev",
31
+ "vega",
32
+ "clef",
33
+ "typed-decisions",
34
+ "onnx",
35
+ "transformers.js",
36
+ "webgpu",
37
+ "browser",
38
+ "classification"
39
+ ],
40
+ "scripts": {
41
+ "dev": "vite",
42
+ "build:dev": "vite build",
43
+ "demo": "vite --config vite.demo.config.js",
44
+ "build:demo": "vite build --config vite.demo.config.js",
45
+ "test": "node --test test/*.test.mjs"
46
+ },
47
+ "peerDependencies": {
48
+ "@huggingface/transformers": ">=3.0.0",
49
+ "onnxruntime-web": ">=1.17.0"
50
+ },
51
+ "peerDependenciesMeta": {
52
+ "@huggingface/transformers": {
53
+ "optional": true
54
+ }
55
+ },
56
+ "devDependencies": {
57
+ "@huggingface/transformers": "^4.3.0",
58
+ "onnxruntime-web": "1.31.0-dev.20260914-8d85527a0",
59
+ "vite": "^6.3.5"
60
+ },
61
+ "engines": {
62
+ "node": ">=20"
63
+ }
64
+ }
package/src/answers.mjs CHANGED
@@ -1,36 +1,36 @@
1
- // jev-web — score → answer decoding for typed-decision models.
2
- //
3
- // The graph returns one logit per (question, option) pair. Each question's
4
- // options form a softmax group; a post-hoc temperature (fitted by the model
5
- // authors) calibrates the distribution.
6
-
7
- export function softmaxWithTemperature(logits, temperature = 1) {
8
- const t = Number.isFinite(temperature) && temperature > 0 ? temperature : 1;
9
- if (!Array.isArray(logits) || logits.length === 0) throw new TypeError("logits must be a non-empty array");
10
- const max = Math.max(...logits);
11
- const exps = logits.map((x) => Math.exp((Number(x) - max) / t));
12
- const sum = exps.reduce((a, b) => a + b, 0);
13
- return exps.map((e) => e / sum);
14
- }
15
-
16
- export function answersFromScores(scores, { questions, groups, temperature = 1 }) {
17
- if (!Array.isArray(scores)) throw new TypeError("scores must be an array");
18
- return questions.map((q, i) => {
19
- const pairIndices = groups[i];
20
- const probs = softmaxWithTemperature(pairIndices.map((p) => scores[p]), temperature);
21
- const probabilities = Object.fromEntries(q.options.map((option, j) => [option, probs[j]]));
22
- const confidence = Math.max(...probs);
23
- const best = probs.indexOf(confidence);
24
-
25
- if (q.type === "choice") {
26
- return { type: "choice", choice: q.options[best], index: best, probabilities, confidence };
27
- }
28
- if (q.type === "score") {
29
- const expected = probs.reduce((acc, p, j) => acc + p * j, 0);
30
- return { type: "score", score: expected, level: best, probabilities, confidence };
31
- }
32
- // noul: probabilities are { no, yes }; the answer is p(yes).
33
- const yes = probabilities[q.options[1]];
34
- return { type: "noul", noul: yes, probabilities, confidence: Math.max(yes, 1 - yes) };
35
- });
36
- }
1
+ // jev-web — score → answer decoding for typed-decision models.
2
+ //
3
+ // The graph returns one logit per (question, option) pair. Each question's
4
+ // options form a softmax group; a post-hoc temperature (fitted by the model
5
+ // authors) calibrates the distribution.
6
+
7
+ export function softmaxWithTemperature(logits, temperature = 1) {
8
+ const t = Number.isFinite(temperature) && temperature > 0 ? temperature : 1;
9
+ if (!Array.isArray(logits) || logits.length === 0) throw new TypeError("logits must be a non-empty array");
10
+ const max = Math.max(...logits);
11
+ const exps = logits.map((x) => Math.exp((Number(x) - max) / t));
12
+ const sum = exps.reduce((a, b) => a + b, 0);
13
+ return exps.map((e) => e / sum);
14
+ }
15
+
16
+ export function answersFromScores(scores, { questions, groups, temperature = 1 }) {
17
+ if (!Array.isArray(scores)) throw new TypeError("scores must be an array");
18
+ return questions.map((q, i) => {
19
+ const pairIndices = groups[i];
20
+ const probs = softmaxWithTemperature(pairIndices.map((p) => scores[p]), temperature);
21
+ const probabilities = Object.fromEntries(q.options.map((option, j) => [option, probs[j]]));
22
+ const confidence = Math.max(...probs);
23
+ const best = probs.indexOf(confidence);
24
+
25
+ if (q.type === "choice") {
26
+ return { type: "choice", choice: q.options[best], index: best, probabilities, confidence };
27
+ }
28
+ if (q.type === "score") {
29
+ const expected = probs.reduce((acc, p, j) => acc + p * j, 0);
30
+ return { type: "score", score: expected, level: best, probabilities, confidence };
31
+ }
32
+ // noul: probabilities are { no, yes }; the answer is p(yes).
33
+ const yes = probabilities[q.options[1]];
34
+ return { type: "noul", noul: yes, probabilities, confidence: Math.max(yes, 1 - yes) };
35
+ });
36
+ }