Part II: Pipeline

Pipeline and configuration

A cascaded system: Telugu speech in, a Telugu text answer out, with a Whisper-family recognizer feeding an instruction-tuned LLM. Both models stay loaded and are reused across a whole evaluation.

Architecture

Speech inputWAV / FLAC
→
Denoiseoptional, asr.denoise
→
ASRvasista22/whisper-telugu-small
→
LLMQwen2.5-1.5B-Instruct
→
Telugu text response
FileRole
config.yamlModels, revisions, device, precision, decoding, paths.
asr.pyASRWrapper: decodes audio with soundfile, averages to mono, optionally denoises, resamples to the model's rate, transcribes with a Hugging Face ASR pipeline. Timing is synchronized.
llm.pyLLMWrapper: applies the chat template (system + user), generates, returns only the newly generated text. Stateless: no history is kept between calls.
pipeline.pySpeechPipeline composes the two, rejects an empty transcript before calling the LLM, and exposes the JSON CLI.
denoise.pySpectral subtraction used by the ASR stage when enabled. See Denoising extension.

What is timed

Model choices

StageUsedOriginal defaultWhy changed
ASRvasista22/whisper-telugu-smallopenai/whisper-large-v3Large-v3 plus a 7B LLM do not fit in about 6.5 GB free VRAM. The general openai/whisper-small was tried and rejected: see below.
LLMQwen/Qwen2.5-1.5B-InstructQwen/Qwen2.5-7B-InstructMemory (about 3 GB fp16 vs. about 15 GB).
Why not the general whisper-small Even with Telugu forced, openai/whisper-small transcribed this corpus's Telugu audio into Devanagari-looking text and looped on short clips. The first full clean run under it scored corpus WER 2.56 and CER 2.69, and was discarded. The Telugu-only fine-tune fixed it (WER 0.293). Full story in the decision log.
Why language: null The Telugu fine-tune ships a generation_config.json that predates transformers' language/task validation. Passing either to generate() raises ValueError: The generation config is outdated..., even for valid values (reproduced on transformers 5.15.0 and 4.57.6). ASRWrapper therefore treats a falsy language as "pass neither language nor task". Because the checkpoint is Telugu-only, nothing is lost. For a general multilingual Whisper checkpoint, set language: telugu and task defaults to transcribe.

Config reference: config.yaml

Relative filesystem paths resolve from the YAML file's directory. CLI path overrides resolve from the current directory.

paths

KeyDefaultMeaning
paths.audiodata/sample_te.wavDefault input for pipeline.py when --audio is not given. No file is bundled.
paths.outputoutputs/result.jsonWhere the pipeline's JSON result is saved (UTF-8, Telugu preserved).
paths.cache_dir.cache/huggingfaceHugging Face model cache.

runtime

KeyDefaultMeaning
runtime.deviceautoauto, cpu, cuda, cuda:N or mps. auto prefers CUDA, then MPS, then CPU. Errors if a requested accelerator is unavailable.
runtime.dtypeautofloat32, float16 or bfloat16. auto is float16 on CUDA, float32 elsewhere. float16 on CPU is rejected.

asr

KeyValue usedMeaning
asr.model_namevasista22/whisper-telugu-smallAny Transformers-compatible Whisper (or IndicWhisper) checkpoint or local directory. Non-Whisper architectures are rejected.
asr.revisionmainModel commit. Left unpinned for this checkpoint; see Limitations.
asr.languagenullSee the warning above. A value like telugu forces the language and sets task.
asr.chunk_length_s30Chunking window for the ASR pipeline. Must be positive.
asr.batch_size1Must be at least 1. The wrapper handles one request at a time.
asr.denoisefalseSpectral-subtraction front end. true only in config_denoised.yaml.
asr.generation.max_new_tokens256Decoder cap. (Transformers also warns that max_length is set; max_new_tokens wins.)
asr.generation.num_beams1Greedy. Must be a positive integer.
asr.generation.do_samplefalseMust be false for paired evaluation; evaluate.py enforces it for the LLM and verify_task2.py for both.

llm

KeyValue usedMeaning
llm.model_nameQwen/Qwen2.5-1.5B-InstructA causal instruction model with a chat template supporting system and user roles. Base models need their own prompt adapter.
llm.revision989aa7980e4cf806f80c7fef2b1adb7bc71aa306Pinned commit.
llm.system_prompt"You are a helpful assistant. Answer the user's question clearly and concisely in Telugu using Telugu script. If the request is unclear, ask for clarification. Do not invent facts."The prompt the hallucination test measures against: it explicitly allows abstaining.
llm.max_input_tokens2048Longer prompts raise an error rather than being silently truncated.
llm.generation.max_new_tokens256Response budget. Prompt plus budget must fit the model's context.
llm.generation.do_samplefalseGreedy, for a repeatable baseline.
llm.generation.temperature, top_p, repetition_penalty0.7, 0.9, 1.05Used only when sampling. When do_sample is false, temperature and top_p are dropped before generation.

The two config files

config_denoised.yaml is identical to config.yaml except for asr.denoise: true (and slightly shorter comments, with asr.revision: main noted as unpinned). It exists so the baseline-vs-improved ablation differs in exactly one setting.

Output schema

pipeline.py prints and saves one JSON object (PipelineResult):

FieldTypeMeaning
audio_pathstringResolved path of the input file.
transcriptstringASR output.
responsestringLLM answer to the transcript.
asr_secondsfloatSee what is timed.
llm_secondsfloat
total_secondsfloat

These records are evaluation inputs, not scores. WER and response quality need reference labels, which is what the evaluator adds.

Built-in guards