41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
# File 'lib/cohere/transcribe/configuration.rb', line 41
def validate!(options)
unless defined?(TranscriptionOptions) && options.is_a?(TranscriptionOptions)
raise TypeError, "options must be a TranscriptionOptions instance"
end
validate_model_reference!(options.model, option: "--model", description: "Model")
validate_revision!(options.model_revision, option: "--model-revision")
if local_reference?(options.model, description: "Model") && options.model_revision
invalid!("--model-revision cannot be used with a local model directory")
end
validate_model_reference!(options.adapter, option: "--adapter", description: "Adapter") unless options.adapter.nil?
invalid!("--adapter-revision requires --adapter") if options.adapter_revision && options.adapter.nil?
validate_revision!(options.adapter_revision, option: "--adapter-revision")
if !options.adapter.nil? &&
local_reference?(options.adapter, description: "Adapter") && options.adapter_revision
invalid!("--adapter-revision cannot be used with a local adapter directory")
end
BOOLEAN_OPTIONS.each do |name|
value = options.public_send(name)
invalid!("--#{name.to_s.tr("_", "-")} must be a boolean") unless [true, false].include?(value)
end
INTEGER_OPTIONS.each do |name|
value = options.public_send(name)
next if value.nil? || value.is_a?(Integer)
invalid!("--#{name.to_s.tr("_", "-")} must be an integer")
end
REAL_OPTIONS.each do |name|
value = options.public_send(name)
next if value.nil? || (value.is_a?(Numeric) && !value.is_a?(Complex))
invalid!("--#{name.to_s.tr("_", "-")} must be a real number")
end
CHOICES.each do |name, choices|
value = options.public_send(name)
next if value.is_a?(String) && choices.include?(value)
invalid!("--#{name.to_s.tr("_", "-")} must be one of: #{choices.sort.join(", ")}")
end
invalid!("--text-only conflicts with --alignment word") if options.text_only && options.alignment == "word"
publication = options.publication
if !publication.nil? && (!defined?(PublicationOptions) || !publication.is_a?(PublicationOptions))
invalid!("publication must be a PublicationOptions instance or nil")
end
formats = publication&.formats&.map(&:to_s)
text_mode = options.text_only || options.alignment == "none"
invalid!("Plain-text mode supports only --formats txt") if text_mode && formats && formats.uniq != ["txt"]
positive_finite!(options.audio_memory_gb, "--audio-memory-gb")
positive_integer_if_set!(options.preprocess_workers, "--preprocess-workers")
packed_vad = options.vad == "silero" && %w[auto torch].include?(options.vad_engine)
if packed_vad
unless positive_integer?(options.vad_batch_size) && positive_integer?(options.vad_block_frames)
invalid!("--vad-batch-size and --vad-block-frames must be positive")
end
if options.vad_batch_size * options.vad_block_frames > MAX_TORCH_VAD_PADDED_FRAMES
invalid!(
"--vad-batch-size * --vad-block-frames must not exceed " \
"#{format("%<frames>d", frames: MAX_TORCH_VAD_PADDED_FRAMES)} frames"
)
end
end
positive_integer_if_set!(options.vad_threads, "--vad-threads")
invalid!("--vad-threads applies only to packed Torch Silero VAD") if options.vad_threads && !packed_vad
positive_integer_if_set!(options.batch_size, "--batch-size")
positive_integer_if_set!(options.batch_max_size, "--batch-max-size")
if options.batch_size && options.batch_max_size && options.batch_max_size < options.batch_size
invalid!("--batch-max-size must be at least --batch-size")
end
invalid!("--batch-max-size requires --adaptive-batch") if options.batch_max_size && !options.adaptive_batch
positive_finite_if_set!(options.batch_audio_seconds, "--batch-audio-seconds")
unless finite?(options.batch_vram_target) && options.batch_vram_target.between?(0.50, 0.98)
invalid!("--batch-vram-target must be between 0.50 and 0.98")
end
invalid!("--align-batch-size must be positive") if (options.alignment == "word") && !positive_integer?(options.align_batch_size)
positive_finite!(options.max_dur, "--max-dur")
invalid!("--min-dur must be finite") unless finite?(options.min_dur)
invalid!("Require 0 <= --min-dur <= --max-dur") if options.vad != "none" && !options.min_dur.between?(0, options.max_dur)
if options.vad == "none" && options.max_dur < ASR_FIXED_MIN_SECONDS
invalid!(
"--vad none requires --max-dur >= #{ASR_FIXED_MIN_SECONDS.to_i} second " \
"to bound segment count and memory use"
)
end
case options.vad
when "silero"
invalid!("--vad-threshold must be between 0 and 1") unless finite?(options.vad_threshold) && options.vad_threshold.between?(0, 1)
unless options.min_silence_ms.is_a?(Integer) && options.speech_pad_ms.is_a?(Integer)
invalid!("--min-silence-ms and --speech-pad-ms must be integers")
end
if options.min_silence_ms.negative? || options.speech_pad_ms.negative?
invalid!("--min-silence-ms and --speech-pad-ms must be non-negative")
end
when "auditok"
if (options.max_silence.is_a?(Numeric) && options.max_silence.negative?) ||
(options.energy_threshold.is_a?(Numeric) && options.energy_threshold.negative?)
invalid!("Auditok silence and energy thresholds must be finite and non-negative")
end
invalid!("--vad auditok requires --min-dur > 0") unless options.min_dur.positive?
if options.max_silence.is_a?(Numeric) && options.max_silence >= options.max_dur
invalid!("--vad auditok requires --max-silence < --max-dur")
end
end
invalid!("--vad-merge is supported only with --vad silero") if options.vad_merge && options.vad != "silero"
invalid!("--max-new-tokens must be positive") unless positive_integer?(options.max_new_tokens)
invalid!("--max-retry-tokens must be an integer") unless options.max_retry_tokens.is_a?(Integer)
invalid!("--max-retry-tokens must be at least --max-new-tokens") if options.max_retry_tokens < options.max_new_tokens
thresholds = [
options.vad_threshold, options.max_silence, options.energy_threshold,
options.max_cue_dur, options.max_gap
]
invalid!("All numeric thresholds and cue limits must be finite") unless thresholds.all? { |v| finite?(v) }
if options.alignment != "none" &&
(!positive_integer?(options.max_chars) || options.max_cue_dur <= 0 || options.max_gap.negative?)
invalid!("Subtitle cue limits must be positive (and --max-gap non-negative)")
end
options
end
|