feat: add fast ASR backend - #2938
Conversation
|
✅ DCO Check Passed Thanks @BBC-Esq, all your commits are properly signed off. 🎉 |
Merge ProtectionsYour pull request matches the following merge protections and will not be merged until they are valid. 🟢 Enforce conventional commitWonderful, this rule succeeded.Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
3f7b50a to
85b6fef
Compare
|
Here goes nothing. I put a lot of time and effort into this PR and I jumped through all the freakin hoops as far as certifying the PR, correcting the syntax...Hopefully big company IBM does not equal shitty customer experience and/or online culture when simply trying to contribute to a cool idea. I don't even see a freakin button to request a review by whomever maintains this repo...Oh well, here goes nothing! |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
BBC-Esq
left a comment
There was a problem hiding this comment.
I'm trying my best to adhere to the multiple bots and their instructions...any help would be much appreciated. Thanks. lol.
|
Hi @BBC-Esq We’ll review it shortly and let you know if anything needs clarification or further work. We take all contributions seriously and will keep you posted on the status of this PR. If you have any questions in the meantime, just drop a comment here or open an issue. Thanks again for your work! |
Thanks for your response. I can try to change the PR to remove the unrelated scripts if need be. They were included by accident when I ran ruff on my entire fork's codebase so...or feel free to modify the PR to the discrete topic at hand. Was taken agack by the number of bots all with different criteria but I'll review the links you sent. |
|
Any chance this could be reviewed? |
Hello, you said you guys would be following up shortly? Is there anything preventing this from being merged? @ceberam |
|
@BBC-Esq let me follow up. We were right in the middle of a big refactoring to clean up the pipelines/stages/models/etc (see the merge conflicts). This is now getting finalized. |
ceberam
left a comment
There was a problem hiding this comment.
Thanks again @BBC-Esq for the contribution and for exploring improvements in the ASR backend.
I’ve reviewed the PR and I’m not comfortable with the current form for several reasons:
1. Licensing
The repository currently does not contain a LICENSE file. Without an explicit open-source license, there is no clear legal grant of rights to use, modify, or redistribute the code.
Since this project is part of the LF AI & Data, we need all dependencies to have a clear, identifiable open-source license. Even though this repository appears to be a fork of WhisperS2T (which is MIT-licensed), that license must be explicitly included in the forked repository for it to be valid for redistribution.
Until this is clarified and properly addressed upstream, we cannot safely introduce this dependency.
2. Project health
The repository currently has:
- No visible community adoption (0 stars/forks)
- Limited signals of review
- No documented benchmark results supporting the performance claims
If performance is the main motivation, it would help to include reproducible benchmarks or comparative results demonstrating the advantage over existing ASR backend models. Without that, it is difficult to justify introducing an additional dependency with unclear maintenance status.
3. PR scope and conflicts
This PR also includes styling and formatting changes across multiple files that are unrelated to the new dependency. While some of those changes may be acceptable in isolation (e.g., I also prefer str | None to Optional[str]), they are out of scope for this feature and make the review more difficult. Our CONTRIBUTING.md guidelines already describe how to run the automatic style checks locally, which should prevent unrelated formatting diffs. In addition, as pointed out by @PeterStaar-IBM , recent changes have introduced some merge conflicts that should be addressed once the refactoring has finalized.
I would be happy to re-review again once:
- The upstream repository clearly includes an appropriate open-source license.
- There is objective evidence supporting the claimed performance benefits.
- The PR is cleaned up to only include changes strictly required for the ASR feature.
- The merge conflicts are resolved.
Thanks again for the contribution and for understanding the need to keep compliance, scope, and maintainability in mind.
|
@ceberam I appreciate such a thorough and professional response. I, too, care about the code base and your message makes sense. LONG-WINDED RESPONSE HERE FOR LESS SCROLLING1) Regarding the license issue, I'll fix that this week. Thanks for the link to LFAI, didn't know about that. I'll check out actually joining the org...
Regarding "unclear maintenance" status, I totally get that. You don't want to modify your guys' code base, add a dependency (even an optional one), and then have a part of your code base outdated because someone abandons WhisperS2T-Reborn. At a minimum, it would just be a hassle to unwind the "integration" so to speak. Since I maintain WhisperS2T-Reborn, it logically makes sense to explain about my background a little to hopefully assuage your concern. First off, I'm a lawyer by trade but I program as hobby. I originally became fascinated by LLMs and machine learning upon learning about "vector databases" and how they enable the search-ability of massive amounts of data; for example, data obtained during discovery in a lawsuit. In my profession, there's frequently large amounts of data in the form of text messages, emails, audio recordings, video clips, etc... As an offshoot of that, transcribing audio and then being able to search it "semantically is a huge benefit for litigation purposes. It means that I no longer have to listen to hours of audio to pinpoint the minute/second where something was said that is important for litigation purposes, which ultimately saves the client billables. This is essentially what lead me to learn about Whisper models. The "vanilla" Whisper code, while revolutionary at the time, is painstakingly slow, which leads me to faster back-ends like Ctranslate2 upon which WhisperS2T-Reborn is based. That was 3-4 years ago now and I've been working with Whisper, vector databases, and other related technologies ever since. I was frequently in contact with the maintainer of the original "WhisperS2T" repository until he abandoned it in 2024 because he was offered a high-paying job, presumably using WhisperS2T to pad his resume. As you know, this frequently happens - i.e. people use their Github repositories to pad their resumes to land a high-paying job...nothing wrong with that, but often as part of a new job you can't work on competing open source projects and/or just don't have the time so... At any rate, I decided to maintain it since it was slowly becoming incompatible with other APIs such as transformers as their code bases improved/changed. I also maintain the models that WhisperS2T-Reborn relies upon by default, which you can see here on huggingface. I'd like to highlight that all of the models are converted from the original "float32" Whisper models, NOT the "float16" versions that OpenAI has decided to upload for better or worse. See the config here to see what I'm referring to. ORIGINALLY, OpenAI uploaded float32 versions of all models but then replaced them with float16 versions. I disagreed with this because, yes, float16 is compatible with more GPUs and the file size is less, but if you're running on CPU it'll just have to be upcast to float32 anyways and you cannot regain the quality loss from the initial conversion from float32 to float16. Moreover, more recent GPUs support bfloat16...People wishing for the additional stability that bfloat16 offers won't get it...after all, when converting a float16 model to bfloat16 you cannot regain the lost precision. In short, all of my models are converted from the original float32 versions so there is no quality loss. The WhisperS2T-Reborn library can choose the best model based on a user's hardware. For GPUs that support bfloat16, it'll choose bfloat16...and for older GPUs it'll fallback to float16. CPUs use float32 or...a user can still choose to use float32 on GPU for maximum quality. This required downloading the original float32 weights of all whisper models from the history of the various repositories, adding any updated configuration "JSON" files (e.g. if OpenAI found a bug in something), then converting them to the Ctranslate2 format. My repository provides float32, float16, and bfloatg16 versions of all Whisper models and the Ctranslate2 backend also supports "int8" if that's desirable. Moreover, regarding Ctranslate2, it has an excellent feature whereby it'll convert at runtime if need be. For example, if you accidentally downloaded a bfloat16 model but your GPU only supports float16, it'll automatically convert and run in float16 without a hitch. Granted, there's a very small quality loss but at least it will not throw an error. Ctranslate2 also recently adopted ROCm support in addition to CUDA, and already supports fast execution on both Intel and AMD cpus.
Basically, I've been working with Whisper models since approximately 2023 and don't plan to quite anytime soon, if that's any assurance regarding the "health" of the WhisperS2T-Reborn library... Regarding item 3, I'll redo the PR to only pertain to the subject matter...it's just that without those additional changes your review is throwing errors...would be willing to do a separate PR to resolve those errors, however. I'll also do the stylistic checks locally like you suggest. Cheers! |
9fa2a59 to
21a35cf
Compare
|
@ceberam Should be ready to review now. I updated the
A couple of questions, however...
Lastly, I'm attaching to this message some benchmarking scripts that actually utilize the docling pipeline as well. Should be pretty straighforward except notice how I like to pip install the cuda libraries and use the "set_cuda_paths" function instead of relying on a systemwide installation. Please let me know if you guys have any questions: |
126f49c to
9934d7a
Compare
|
Everything should be good now I believe. I fixed the few remaining workflow issues I believe and have requested a re-review. |
|
@ceberam or @PeterStaar-IBM I believe this is ready for review again. Is there anything I need to do? I've been updating my main branch as well as the development fork to incorporate the recent changes to the library as a whole. |
01d90f2 to
067ab1a
Compare
|
I rebased and fixed the lingering ruff issue, so I hope, so should be good... |
b8ebc43 to
786baff
Compare
Merge ProtectionsYour pull request matches the following merge protections and will not be merged until they are valid. 🟢 Enforce conventional commitWonderful, this rule succeeded.Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
cau-git
left a comment
There was a problem hiding this comment.
@BBC-Esq Thanks for maintaining this branch and keeping up with the changes. Time to get it across the finish line!
I have only small remarks below for alignment purposes and potential config simplification, see below.
A few things going beyond the scope of this PR (so, after we merge this), that would be appreciated:
- It would be good if whisper S2T reborn could actually pin the
revisionof the HF models it pulls and expose that, so we can have a fully reproducible setup on the side of docling. Meaning, any change in model weights would also reflect as a code/config update of the revision hash for clarity and to meet good security compliance practices. - We should build out the download facade for local offline usage like we do in other model families (used with
artifacts_pathanddocling-tools models downloadutility). This would also need to be done for the original openai Whisper.
Merge Protections🟢 Merge protection satisfied — ready to merge. Show 1 satisfied protection🟢 Enforce conventional commitMake sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
Hey @cau-git Thanks for your message. I hadn't yet had a chance to address the rest of the issues that @ceberam had mentioned and then got your messages...I fully plan to so we can get this across the finish line! However, IRL stuff has some up (i.e. job stuff that makes money for my family and I) that's urgent...so give me a week or 1.5 weeks and I'll address everything. Didn't want you guys to think I forgot about this. Still want to get it done ASAP. ;-) |
Signed-off-by: BBC, Esquire <bbc@chintellalaw.com> # Conflicts: # .github/max-lines-ignore
|
@cau-git and/or @ceberam. Quick question. Currently, my whispers2t-reborn repository pins the ctranslate2 dependency to 4.6.2. Originally, I intentionally did this because beginning with 4.6.3 ctranslate2 turns the cudnn reliance "off" by default in their published wheels....you must build manually to use cudnn because they implemented their own Conv1d CUDA operations, which were the only thing that cudnn was used for (and only specific to whisper models, no others). See here for the release notes: https://github.com/OpenNMT/CTranslate2/releases According to Jordimas, who I trust and have dealt with for awhile now, the speed difference is negligible...and with my own testing I can't tell the difference. See here: Question: Do you guys have a preference of (A) pinning to 4.6.2 so as to keep the minimal benefit of cudnn or (B) pin to higher release number so avoid the 300 MB+ cudnn dependency for cuda users. My thought is the latter, but I have no strong preference so wanted your feedback since I'm working on finalize in the PR. Thanks. [EDIT] I decided to pin Whisper-S2T-reborn to ctranslate2 4.6.2 or higher, but less than 5.0. This will allow users to specifically pip install the last version of ctranslate2 that uses cudnn (4.6.2) if they really wanted to without pip check throwing a conflict notice...while still keeping it under a 5+ likely breaking change. Otherwise, if they install like most users it'll pull in the non-cudnn-reliant version of ctranslate2. |
Align the precision option with the shared torch_dtype field used by the other ASR backends, per review. The resolved value is still passed to whisper_s2t / CTranslate2 as compute_type internally. Signed-off-by: BBC, Esquire <bbc@chintellalaw.com>
Align with docling's AcceleratorOptions naming and derive the default from AcceleratorOptions().num_threads (env-aware) instead of a static 4, per review. The value is still passed to whisper_s2t / CTranslate2 as cpu_threads internally. Signed-off-by: BBC, Esquire <bbc@chintellalaw.com>
docling's DocumentConverter processes one file at a time, so num_workers had no function. Remove it from the config and stop passing it to load_model; whisper_s2t / CTranslate2 already defaults to a single worker (inter_threads=1), so behavior is unchanged. Per review. Signed-off-by: BBC, Esquire <bbc@chintellalaw.com>
Cap the format-audio extra's whisper-s2t-reborn at >=1.6.2,<2 so a future major release with breaking changes is not pulled in automatically, per review. Signed-off-by: BBC, Esquire <bbc@chintellalaw.com>
The oversized ASR test exemption flagged in review was already resolved by splitting tests/test_asr.py into per-backend files, both under the 1000-line limit (737 and 363). Drop the remaining incidental trailing-newline diff so the PR no longer modifies this file. Per review. Signed-off-by: BBC, Esquire <bbc@chintellalaw.com>
Revert incidental formatting flagged in review: restore the base InlineAsrOptions.torch_dtype to Optional[str] (matching the file's existing style, now used by the new WhisperS2T fields too) instead of converting it to str | None, and restore the blank-line grouping in cli/main.py's ASR model dispatch. Only ASR-required changes remain in these files. Signed-off-by: BBC, Esquire <bbc@chintellalaw.com>
Per maintainer review, WhisperS2T must not be the default ASR backend. The auto-selecting WHISPER_* models now choose MLX on Apple Silicon and native Whisper on all other hardware; WhisperS2T is reachable only via the explicit WHISPER_*_S2T model types. Simplify the hardware probe accordingly (no longer needs CUDA / whisper-s2t detection) and update the auto-selection tests to lock in that WhisperS2T is never auto-selected. Signed-off-by: BBC, Esquire <bbc@chintellalaw.com>
Per review, consolidate the dispersed inline notes into a module docstring: the inline ASR option classes (native / MLX / WhisperS2T) and the auto-selection policy (MLX on Apple Silicon, native otherwise; WhisperS2T opt-in only), pointing to asr_model_specs for the concrete presets and AsrModelType. Signed-off-by: BBC, Esquire <bbc@chintellalaw.com>
Per review, document that CTranslate2 (the WhisperS2T backend) loads NVIDIA cuDNN/cuBLAS at runtime and may need them added to LD_LIBRARY_PATH on Linux with CUDA, including where the pip-wheel libraries are located. Signed-off-by: BBC, Esquire <bbc@chintellalaw.com>
whisper-s2t-reborn pulls a ctranslate2 (>=4.6.3) that no longer uses cuDNN by default, so only cuBLAS is loaded at runtime; drop the cuDNN references from the note. Signed-off-by: BBC, Esquire <bbc@chintellalaw.com>
…ate2 whisper-s2t-reborn 1.6.3 relaxes its ctranslate2 pin to >=4.6.2,<5, so the lock now resolves ctranslate2 to 4.8.0, which no longer loads cuDNN by default (matching the LD_LIBRARY_PATH note). ctranslate2 4.6.2 remains technically compatible if a user pins it explicitly. Bump the dependency lower bound and the import-error install hint, and re-lock (whisper-s2t-reborn 1.6.3, ctranslate2 4.8.0). Signed-off-by: BBC, Esquire <bbc@chintellalaw.com>
|
@cau-git @ceberam and whoever else. See these benchmarks. Let me know the best way to get the scripts to you. I can package them in a Claude skill ZIP if you'd like or paste the scripts in a piecemeal fashion. I used a new audio that's 18 minutes long to speed up the benchmarks instead of the 2 hour Sam Altman podcast, which I can send if need be. PLEASE NOTE:
All testing done on an RTX 4090. I'm just showing the results for the whisper models that docling CURRENTLY supports for simplicity. However, whisper-s2t-reborn additionally supports these models that docling's vanilla whisper implementation does not: tiny.en, base.en, small.en, distil-small.en, medium.en, distil-medium.en, distil-large-v3, distil-large-v3.5...all run with batch sizes 1, 2, 4, 8, 16, and 24. Without further ado...
|
|
Closing out my own question above re: pinning ctranslate2 4.6.2 vs 4.6.3 — resolved. Moved to requiring |
Merge Protections🟢 Merge protection satisfied — ready to merge. Show 1 satisfied protection🟢 Enforce conventional commitMake sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
|
@ceberam @cau-git — I believe the conditions from the February review are now addressed, and I've taken the path you proposed in June. Quick summary:
Most importantly, per your June 17 suggestion, WhisperS2T-Reborn is now opt-in / experimental rather than the default backend (ef212e6) — the default user experience is unchanged, and users must explicitly select it. That keeps docling's core dependency surface untouched while letting the community evaluate the backend in real-world use, which should also help address the maturity/adoption concern. @cau-git's alignment remarks are addressed (resolved threads), and the two items he flagged as out-of-scope — pinning/exposing the HF model Could you re-review when you have a chance? cc @PeterStaar-IBM @dolfim-ibm @vagenas |
Signed-off-by: BBC, Esquire <bbc@chintellalaw.com>
Merge Protections🟢 Merge protection satisfied — ready to merge. Show 1 satisfied protection🟢 Enforce conventional commitMake sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|






Add Fast WhisperS2T-Reborn (based on ctranslate2) ASR Backend
This PR adds support for the
whisper-s2t-rebornlibrary as a high-performance ASR backend option, providing significantly faster transcription speeds. Within the "pipeline," it automatically chooses this backend if the criteria are met - e.g. cuda, etc. Previously, it was eithe MLX with a simple fallback to vanilla openai whisper. Vanilla whisper is now the final fallback if neither MLX nor WhisperS2T are available.New Files/Classes:
InlineAsrWhisperS2TOptions- Configuration class for WhisperS2T with options for compute type, batch size, beam size, and more_WhisperS2TModel- Model wrapper class implementing the WhisperS2T transcription pipelineModified Files:
pipeline_options_asr_model.py- AddedWHISPER_S2TtoInferenceAsrFrameworkenum; AddedInlineAsrWhisperS2TOptionsconfiguration classasr_model_specs.py- Added 12 pre-configured model specs (tiny, base, small, medium, large-v3 + distilled variants); ExtendedAsrModelTypeenumasr_pipeline.py- Added_WhisperS2TModelclass with device parsing fix for CTranslate2 compatibility; UpdatedAsrPipelineto handle new backendcli/main.py- Added CLI support for all WhisperS2T model variantsNotes
_parse_device()helper to handle device strings like"cuda:0"→("cuda", 0)for CTranslate2 compatibilityI will give you the script I used to test this below. However, PLEASE note that I always use a "set_cuda_paths" that relies on pip-installed versions of CUDA/cuDNN. This function sets the relevant cuda-related paths to the pip-installed locations so I don't have to install/reinstall various versions of CUDA. If you want to test with the stereotypical systemwide installation don't use "set_cuda_paths."
That said, to run the test script: (1) create a venv, (2) activate it, (3) run the following command, and (4) run the script pasted below:
HERE IS THE SCRIPT: