Skip to content

Fix Fun-ASR-Nano CTC batch fallback#3187

Merged
LauraGPT merged 1 commit into
mainfrom
codex/fun-asr-nano-ctc-batch-fallback-20260708
Jul 8, 2026
Merged

Fix Fun-ASR-Nano CTC batch fallback#3187
LauraGPT merged 1 commit into
mainfrom
codex/fun-asr-nano-ctc-batch-fallback-20260708

Conversation

@LauraGPT

@LauraGPT LauraGPT commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • preserve the existing no-CTC batched LLM path
  • when CTC timestamps are active, split multi-segment input back through the single-segment inference path instead of passing the whole batch into inference_prepare
  • add a regression test for multi-segment Fun-ASR-Nano input with a CTC decoder

Root Cause

inference_llm skipped _inference_llm_batch when ctc_decoder existed, but then passed all VAD segments into inference_prepare, which intentionally rejects multi-item input with NotImplementedError("batch decoding is not implemented").

Verification

  • RED: python3 -m pytest tests/test_fun_asr_nano_ctc_batch_fallback.py -q failed with NotImplementedError: batch decoding is not implemented before the fix
  • GREEN: python3 -m pytest tests/test_fun_asr_nano_ctc_batch_fallback.py tests/test_fun_asr_nano_autocast_device.py tests/test_fun_asr_nano_openai_response.py tests/test_fun_asr_nano_repetition_penalty.py -q -> 13 passed
  • python3 -m py_compile funasr/models/fun_asr_nano/model.py tests/test_fun_asr_nano_ctc_batch_fallback.py
  • git diff --cached --check -- funasr/models/fun_asr_nano/model.py tests/test_fun_asr_nano_ctc_batch_fallback.py

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements sequential processing for multi-segment inputs when CTC timestamps are active by introducing the _inference_llm_ctc_sequential method along with helper functions _slice_batch_value and _merge_inference_meta, supported by a new unit test. The review feedback identifies two key issues: a potential runtime crash when key is None or out of bounds during sequential execution, and incorrect fallback behavior in _slice_batch_value where the entire original value is returned if the index is out of bounds. Code suggestions are provided to resolve both issues.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

results = []
meta_data = {}
for i, data_i in enumerate(data_in):
key_i = [key[i]] if key is not None and i < len(key) else None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If key is None or if its length is less than the number of segments in data_in, key_i will be set to None. When self.inference_llm is recursively called with key=None, it will crash with a TypeError: 'NoneType' object is not subscriptable when attempting to access key[0] (e.g., at lines 885 and 960). To prevent this runtime crash, we should provide a fallback key (such as a generated random key or index-based key) when key is unavailable or out of bounds.

Suggested change
key_i = [key[i]] if key is not None and i < len(key) else None
key_i = [key[i]] if key is not None and i < len(key) else [f"rand_key_{i}"]

Comment on lines +800 to +809
def _slice_batch_value(value, index):
if value is None:
return None
if isinstance(value, torch.Tensor) and value.ndim > 0 and value.shape[0] > index:
return value[index : index + 1]
if isinstance(value, list) and len(value) > index:
return [value[index]]
if isinstance(value, tuple) and len(value) > index:
return (value[index],)
return value

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In _slice_batch_value, if value is a multi-element Tensor, list, or tuple, but index is out of bounds (i.e., index >= len(value)), the function falls through and returns the entire original value. This is incorrect because the downstream code expects a single-item slice or None for the out-of-bounds index. We should explicitly return None when the index is out of bounds for these sequence types.

Suggested change
def _slice_batch_value(value, index):
if value is None:
return None
if isinstance(value, torch.Tensor) and value.ndim > 0 and value.shape[0] > index:
return value[index : index + 1]
if isinstance(value, list) and len(value) > index:
return [value[index]]
if isinstance(value, tuple) and len(value) > index:
return (value[index],)
return value
def _slice_batch_value(value, index):
if value is None:
return None
if isinstance(value, torch.Tensor) and value.ndim > 0:
return value[index : index + 1] if value.shape[0] > index else None
if isinstance(value, list):
return [value[index]] if len(value) > index else None
if isinstance(value, tuple):
return (value[index],) if len(value) > index else None
return value

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant