fix(api-space): force Whisper decode scores via GenerationConfig; strip dangling grazie tail after .?!
Browse filesHF Whisper ignored output_scores when return_dict_in_generate stayed false on the
config; deep-copy generation_config and set both flags.
Extend dangling Italian tail cleanup to drop hallucinated GRAZIE after sentence
punctuation only (not standalone grazie or comma-led grazie).
Co-authored-by: Cursor <cursoragent@cursor.com>
main.py
CHANGED
|
@@ -10,6 +10,7 @@ Response JSON: {"text": "......."}
|
|
| 10 |
|
| 11 |
from __future__ import annotations
|
| 12 |
|
|
|
|
| 13 |
import math
|
| 14 |
import os
|
| 15 |
import re
|
|
@@ -440,12 +441,19 @@ def _clean_text_artifacts(text: str) -> str:
|
|
| 440 |
|
| 441 |
|
| 442 |
def _strip_dangling_italian_tail(text: str) -> str:
|
| 443 |
-
"""Remove only
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 444 |
t = (text or "").strip()
|
| 445 |
if not t:
|
| 446 |
return ""
|
| 447 |
t = re.sub(r"(?i)([.!?])\s+(e|ed)\s*$", r"\1", t)
|
| 448 |
t = re.sub(r"(?i)\s+(e|ed)\s*$", "", t)
|
|
|
|
|
|
|
| 449 |
return t.strip()
|
| 450 |
|
| 451 |
|
|
@@ -1023,9 +1031,24 @@ class WhisperASRSingle:
|
|
| 1023 |
if logprob_threshold is not None and no_speech_threshold is not None:
|
| 1024 |
gen_common["logprob_threshold"] = logprob_threshold
|
| 1025 |
|
| 1026 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1027 |
try:
|
| 1028 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1029 |
except TypeError:
|
| 1030 |
try:
|
| 1031 |
out = self._generate_ids(model, input_features, dict(gen_common))
|
|
|
|
| 10 |
|
| 11 |
from __future__ import annotations
|
| 12 |
|
| 13 |
+
import copy
|
| 14 |
import math
|
| 15 |
import os
|
| 16 |
import re
|
|
|
|
| 441 |
|
| 442 |
|
| 443 |
def _strip_dangling_italian_tail(text: str) -> str:
|
| 444 |
+
"""Remove only lightweight dangling tails (no broad phrase blocklists).
|
| 445 |
+
|
| 446 |
+
- Final lone conjunction ``E`` / ``ED`` (after punctuation or EOS).
|
| 447 |
+
- Final standalone ``GRAZIE`` / ``GRAZIE.`` only after sentence-ending ``.?!``
|
| 448 |
+
(Whisper often hallucinates a polite tail after a complete clause — not injecting text).
|
| 449 |
+
"""
|
| 450 |
t = (text or "").strip()
|
| 451 |
if not t:
|
| 452 |
return ""
|
| 453 |
t = re.sub(r"(?i)([.!?])\s+(e|ed)\s*$", r"\1", t)
|
| 454 |
t = re.sub(r"(?i)\s+(e|ed)\s*$", "", t)
|
| 455 |
+
# "? grazie." / "... grazie" hallucination tail — keep bare "GRAZIE" or "SÌ, GRAZIE" untouched.
|
| 456 |
+
t = re.sub(r"(?i)([.!?])\s+GRAZIE\.?\s*$", r"\1", t)
|
| 457 |
return t.strip()
|
| 458 |
|
| 459 |
|
|
|
|
| 1031 |
if logprob_threshold is not None and no_speech_threshold is not None:
|
| 1032 |
gen_common["logprob_threshold"] = logprob_threshold
|
| 1033 |
|
| 1034 |
+
# Whisper may ignore kwargs unless applied on GenerationConfig; without this,
|
| 1035 |
+
# output_scores is dropped and avg_logprob stays None (see transformers warning).
|
| 1036 |
+
try:
|
| 1037 |
+
gen_cfg = copy.deepcopy(model.generation_config)
|
| 1038 |
+
gen_cfg.return_dict_in_generate = True
|
| 1039 |
+
gen_cfg.output_scores = True
|
| 1040 |
+
except Exception:
|
| 1041 |
+
gen_cfg = None
|
| 1042 |
+
|
| 1043 |
try:
|
| 1044 |
+
if gen_cfg is not None:
|
| 1045 |
+
out = self._generate_ids(model, input_features, {**gen_common, "generation_config": gen_cfg})
|
| 1046 |
+
else:
|
| 1047 |
+
out = self._generate_ids(
|
| 1048 |
+
model,
|
| 1049 |
+
input_features,
|
| 1050 |
+
{**gen_common, "return_dict_in_generate": True, "output_scores": True},
|
| 1051 |
+
)
|
| 1052 |
except TypeError:
|
| 1053 |
try:
|
| 1054 |
out = self._generate_ids(model, input_features, dict(gen_common))
|