@absolutejs/voice 0.0.22-beta.636 → 0.0.22-beta.637

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -49563,6 +49563,46 @@ var runSTTAdapterFixture = async (adapter, fixture, options = {}) => {
49563
49563
  };
49564
49564
  };
49565
49565
 
49566
+ // src/testing/confidenceCalibration.ts
49567
+ var clampConfidence2 = (value) => Math.max(0, Math.min(1, value));
49568
+ var calibrateVoiceConfidence = (samples, binCount = 10) => {
49569
+ const safeBinCount = Math.max(1, Math.round(binCount));
49570
+ const bins = Array.from({ length: safeBinCount }, (_, index) => {
49571
+ const lowerBound = index / safeBinCount;
49572
+ return {
49573
+ accuracy: 0,
49574
+ averageConfidence: 0,
49575
+ count: 0,
49576
+ lowerBound,
49577
+ upperBound: (index + 1) / safeBinCount
49578
+ };
49579
+ });
49580
+ let brierTotal = 0;
49581
+ for (const sample of samples) {
49582
+ const confidence = clampConfidence2(sample.confidence);
49583
+ const binIndex = Math.min(safeBinCount - 1, Math.floor(confidence * safeBinCount));
49584
+ const bin = bins[binIndex];
49585
+ bin.count += 1;
49586
+ bin.averageConfidence += confidence;
49587
+ bin.accuracy += sample.correct ? 1 : 0;
49588
+ brierTotal += (confidence - (sample.correct ? 1 : 0)) ** 2;
49589
+ }
49590
+ let expectedCalibrationError = 0;
49591
+ for (const bin of bins) {
49592
+ if (bin.count === 0)
49593
+ continue;
49594
+ bin.averageConfidence /= bin.count;
49595
+ bin.accuracy /= bin.count;
49596
+ expectedCalibrationError += bin.count / Math.max(1, samples.length) * Math.abs(bin.accuracy - bin.averageConfidence);
49597
+ }
49598
+ return {
49599
+ bins,
49600
+ brierScore: samples.length > 0 ? brierTotal / samples.length : 0,
49601
+ expectedCalibrationError,
49602
+ sampleCount: samples.length
49603
+ };
49604
+ };
49605
+
49566
49606
  // src/testing/criticalFields.ts
49567
49607
  var normalizeText4 = (value) => value.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}@.%+$'-]+/gu, " ").replace(/\s+/g, " ").trim();
49568
49608
  var normalizeDigits = (value) => normalizeSpokenNumbers(value).replace(/\D/g, "");
@@ -49833,6 +49873,15 @@ var toFixtureBenchmarkResult = (fixture, result, elapsedMs) => {
49833
49873
  const expectedTerms = scoreExpectedTerms(result.finalText, fixture.expectedTerms);
49834
49874
  const criticalFields = scoreVoiceCriticalFields(result.finalText, fixture.expectedCriticalFields);
49835
49875
  const speakerTurns = scoreSpeakerTurns(fixture, result);
49876
+ const transcriptConfidence = average2(result.finalEvents.map((event) => {
49877
+ if (typeof event.transcript.confidence === "number") {
49878
+ return event.transcript.confidence;
49879
+ }
49880
+ return average2([
49881
+ ...(event.transcript.words ?? []).map((word) => word.confidence),
49882
+ ...(event.transcript.tokens ?? []).map((token) => token.confidence)
49883
+ ]);
49884
+ }));
49836
49885
  return {
49837
49886
  accuracy: result.accuracy,
49838
49887
  closeCount: result.closeEvents.length,
@@ -49856,6 +49905,7 @@ var toFixtureBenchmarkResult = (fixture, result, elapsedMs) => {
49856
49905
  timeToEndOfTurnMs,
49857
49906
  timeToFirstFinalMs,
49858
49907
  timeToFirstPartialMs,
49908
+ transcriptConfidence: roundMetric4(transcriptConfidence),
49859
49909
  title: fixture.title
49860
49910
  };
49861
49911
  };
@@ -49969,6 +50019,12 @@ var summarizeSTTBenchmark = (adapterId, fixtures) => {
49969
50019
  const passCount = fixtures.filter((fixture) => fixture.passes).length;
49970
50020
  return {
49971
50021
  adapterId,
50022
+ confidenceCalibration: calibrateVoiceConfidence(fixtures.flatMap((fixture) => typeof fixture.transcriptConfidence === "number" ? [
50023
+ {
50024
+ confidence: fixture.transcriptConfidence,
50025
+ correct: fixture.passes
50026
+ }
50027
+ ] : [])),
49972
50028
  averageCharErrorRate: roundMetric4(average2(fixtures.map((fixture) => fixture.accuracy.charErrorRate))) ?? 0,
49973
50029
  averageElapsedMs: roundMetric4(average2(fixtures.map((fixture) => fixture.elapsedMs)), 2) ?? 0,
49974
50030
  averageEndOfTurnCount: roundMetric4(average2(fixtures.map((fixture) => fixture.endOfTurnCount)), 2) ?? 0,
@@ -1,6 +1,7 @@
1
1
  import type { STTAdapter, STTAdapterOpenOptions } from "../core/types";
2
2
  import { type VoiceSTTAdapterHarnessOptions, type VoiceSTTAdapterHarnessResult } from "./stt";
3
3
  import type { VoiceTestFixture } from "./fixtures";
4
+ import { type VoiceConfidenceCalibrationReport } from "./confidenceCalibration";
4
5
  import { type VoiceCriticalFieldAccuracy } from "./criticalFields";
5
6
  export type VoiceExpectedTermAccuracy = {
6
7
  allMatched: boolean;
@@ -41,6 +42,7 @@ export type VoiceSTTBenchmarkFixtureResult = {
41
42
  timeToEndOfTurnMs?: number;
42
43
  timeToFirstFinalMs?: number;
43
44
  timeToFirstPartialMs?: number;
45
+ transcriptConfidence?: number;
44
46
  title: string;
45
47
  };
46
48
  export type VoiceSTTBenchmarkSummary = {
@@ -67,6 +69,7 @@ export type VoiceSTTBenchmarkSummary = {
67
69
  totalErrorCount: number;
68
70
  wordAccuracyRate: number;
69
71
  groupSummaries: VoiceSTTBenchmarkFixtureSummary[];
72
+ confidenceCalibration: VoiceConfidenceCalibrationReport;
70
73
  };
71
74
  export type VoiceSTTBenchmarkFixtureSummary = {
72
75
  group: VoiceSTTFixtureEnvironment;
@@ -367,6 +367,46 @@ var runSTTAdapterFixture = async (adapter, fixture, options = {}) => {
367
367
  };
368
368
  };
369
369
 
370
+ // src/testing/confidenceCalibration.ts
371
+ var clampConfidence = (value) => Math.max(0, Math.min(1, value));
372
+ var calibrateVoiceConfidence = (samples, binCount = 10) => {
373
+ const safeBinCount = Math.max(1, Math.round(binCount));
374
+ const bins = Array.from({ length: safeBinCount }, (_, index) => {
375
+ const lowerBound = index / safeBinCount;
376
+ return {
377
+ accuracy: 0,
378
+ averageConfidence: 0,
379
+ count: 0,
380
+ lowerBound,
381
+ upperBound: (index + 1) / safeBinCount
382
+ };
383
+ });
384
+ let brierTotal = 0;
385
+ for (const sample of samples) {
386
+ const confidence = clampConfidence(sample.confidence);
387
+ const binIndex = Math.min(safeBinCount - 1, Math.floor(confidence * safeBinCount));
388
+ const bin = bins[binIndex];
389
+ bin.count += 1;
390
+ bin.averageConfidence += confidence;
391
+ bin.accuracy += sample.correct ? 1 : 0;
392
+ brierTotal += (confidence - (sample.correct ? 1 : 0)) ** 2;
393
+ }
394
+ let expectedCalibrationError = 0;
395
+ for (const bin of bins) {
396
+ if (bin.count === 0)
397
+ continue;
398
+ bin.averageConfidence /= bin.count;
399
+ bin.accuracy /= bin.count;
400
+ expectedCalibrationError += bin.count / Math.max(1, samples.length) * Math.abs(bin.accuracy - bin.averageConfidence);
401
+ }
402
+ return {
403
+ bins,
404
+ brierScore: samples.length > 0 ? brierTotal / samples.length : 0,
405
+ expectedCalibrationError,
406
+ sampleCount: samples.length
407
+ };
408
+ };
409
+
370
410
  // src/core/numberNormalizer.ts
371
411
  var ONES = {
372
412
  eight: 8,
@@ -822,6 +862,15 @@ var toFixtureBenchmarkResult = (fixture, result, elapsedMs) => {
822
862
  const expectedTerms = scoreExpectedTerms(result.finalText, fixture.expectedTerms);
823
863
  const criticalFields = scoreVoiceCriticalFields(result.finalText, fixture.expectedCriticalFields);
824
864
  const speakerTurns = scoreSpeakerTurns(fixture, result);
865
+ const transcriptConfidence = average(result.finalEvents.map((event) => {
866
+ if (typeof event.transcript.confidence === "number") {
867
+ return event.transcript.confidence;
868
+ }
869
+ return average([
870
+ ...(event.transcript.words ?? []).map((word) => word.confidence),
871
+ ...(event.transcript.tokens ?? []).map((token) => token.confidence)
872
+ ]);
873
+ }));
825
874
  return {
826
875
  accuracy: result.accuracy,
827
876
  closeCount: result.closeEvents.length,
@@ -845,6 +894,7 @@ var toFixtureBenchmarkResult = (fixture, result, elapsedMs) => {
845
894
  timeToEndOfTurnMs,
846
895
  timeToFirstFinalMs,
847
896
  timeToFirstPartialMs,
897
+ transcriptConfidence: roundMetric(transcriptConfidence),
848
898
  title: fixture.title
849
899
  };
850
900
  };
@@ -958,6 +1008,12 @@ var summarizeSTTBenchmark = (adapterId, fixtures) => {
958
1008
  const passCount = fixtures.filter((fixture) => fixture.passes).length;
959
1009
  return {
960
1010
  adapterId,
1011
+ confidenceCalibration: calibrateVoiceConfidence(fixtures.flatMap((fixture) => typeof fixture.transcriptConfidence === "number" ? [
1012
+ {
1013
+ confidence: fixture.transcriptConfidence,
1014
+ correct: fixture.passes
1015
+ }
1016
+ ] : [])),
961
1017
  averageCharErrorRate: roundMetric(average(fixtures.map((fixture) => fixture.accuracy.charErrorRate))) ?? 0,
962
1018
  averageElapsedMs: roundMetric(average(fixtures.map((fixture) => fixture.elapsedMs)), 2) ?? 0,
963
1019
  averageEndOfTurnCount: roundMetric(average(fixtures.map((fixture) => fixture.endOfTurnCount)), 2) ?? 0,
@@ -1030,45 +1086,6 @@ var summarizeSTTBenchmarkSeries = (input) => {
1030
1086
  }
1031
1087
  };
1032
1088
  };
1033
- // src/testing/confidenceCalibration.ts
1034
- var clampConfidence = (value) => Math.max(0, Math.min(1, value));
1035
- var calibrateVoiceConfidence = (samples, binCount = 10) => {
1036
- const safeBinCount = Math.max(1, Math.round(binCount));
1037
- const bins = Array.from({ length: safeBinCount }, (_, index) => {
1038
- const lowerBound = index / safeBinCount;
1039
- return {
1040
- accuracy: 0,
1041
- averageConfidence: 0,
1042
- count: 0,
1043
- lowerBound,
1044
- upperBound: (index + 1) / safeBinCount
1045
- };
1046
- });
1047
- let brierTotal = 0;
1048
- for (const sample of samples) {
1049
- const confidence = clampConfidence(sample.confidence);
1050
- const binIndex = Math.min(safeBinCount - 1, Math.floor(confidence * safeBinCount));
1051
- const bin = bins[binIndex];
1052
- bin.count += 1;
1053
- bin.averageConfidence += confidence;
1054
- bin.accuracy += sample.correct ? 1 : 0;
1055
- brierTotal += (confidence - (sample.correct ? 1 : 0)) ** 2;
1056
- }
1057
- let expectedCalibrationError = 0;
1058
- for (const bin of bins) {
1059
- if (bin.count === 0)
1060
- continue;
1061
- bin.averageConfidence /= bin.count;
1062
- bin.accuracy /= bin.count;
1063
- expectedCalibrationError += bin.count / Math.max(1, samples.length) * Math.abs(bin.accuracy - bin.averageConfidence);
1064
- }
1065
- return {
1066
- bins,
1067
- brierScore: samples.length > 0 ? brierTotal / samples.length : 0,
1068
- expectedCalibrationError,
1069
- sampleCount: samples.length
1070
- };
1071
- };
1072
1089
  // src/core/correction.ts
1073
1090
  var escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1074
1091
  var buildAliasMatcher = (alias) => new RegExp(`(?<![\\p{L}\\p{N}'])${escapeRegExp(alias)}(?![\\p{L}\\p{N}'])`, "giu");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.636",
3
+ "version": "0.0.22-beta.637",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",