#pragma once #include "decode_types.hpp" #include #include namespace pk { // CTC greedy decode (collapse repeats, then drop blank) — the standard CTC // decoding rule, matching NeMo's GreedyCTCInfer. // // logits: row-major [T, vocab_plus_1] (logits[t*vocab_plus_1 + v]). // For each frame t: id_t = argmax_v logits[t, v]. // Collapse consecutive-duplicate ids, THEN remove every id == blank_id. // // For the hybrid CTC head, blank_id == vocab_size and vocab_plus_1 == // vocab_size + 1, so blank is the last column. // // Returns the surviving (non-blank, de-duplicated) token ids. // // If `tokens` is non-null it is filled (one entry per returned id, in order) // with per-token metadata matching NeMo's timestamps=True + 'max_prob' // confidence (see TokenInfo): frame = the collapsed token's run-START frame // (NeMo `start_offset`), conf = min over the token's consecutive argmax run of // the per-frame max_prob confidence, span = 1. The id-only path (tokens == // nullptr) is unchanged. std::vector ctc_greedy(const std::vector& logits, int T, int vocab_plus_1, int blank_id, std::vector* tokens = nullptr); } // namespace pk