Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
889675f
got basic eddy form running
Alex-Wengg Oct 12, 2025
0c01b95
integrated the chunking algo
Alex-Wengg Oct 12, 2025
fb9342e
download in cpp of the dataset
Alex-Wengg Oct 12, 2025
7218d01
streaming algo service
Alex-Wengg Oct 12, 2025
7eb3e4b
the inner tdt skip blank loop
Alex-Wengg Oct 13, 2025
c3ce93b
add normalizer
Alex-Wengg Oct 14, 2025
d18481e
text normatlization
Alex-Wengg Oct 15, 2025
60aa7cc
support NPU now
Alex-Wengg Oct 16, 2025
b782564
download hg models with cpp
Alex-Wengg Oct 16, 2025
66cb78b
parakeet: fix windowed mel; port FluidAudio dedup; type‑safety; chunk…
Alex-Wengg Oct 17, 2025
74815b8
first comment address
Alex-Wengg Oct 19, 2025
f184672
2nd phase of comments addressc:wq
Alex-Wengg Oct 19, 2025
6183311
address commenets and breakup the openvino parakeet file c
Alex-Wengg Oct 19, 2025
209e4df
3 phase of changes
Alex-Wengg Oct 19, 2025
b6f2c64
4th phase of comments addressed
Alex-Wengg Oct 19, 2025
755ffa6
update benchmark pipeline
Alex-Wengg Oct 20, 2025
e325f81
updated to support fluidinference repo model download instead
Alex-Wengg Oct 20, 2025
8616c66
Brandon's minor nit edits
BrandonWeng Oct 21, 2025
8a5ae4a
mel spec on CPU
BrandonWeng Oct 21, 2025
6339328
update benchmark.py
Alex-Wengg Oct 21, 2025
a339223
Replace dr_wav with libsndfile + libsamplerate; mel spec on CPU
Alex-Wengg Oct 21, 2025
45ddb87
Refactor tokenizer, remove auto-fetch, simplify preprocessor
Alex-Wengg Oct 21, 2025
5447738
Document why parakeet_openvino_impl.hpp is in src/ not include/
Alex-Wengg Oct 21, 2025
26744c5
Clarify preprocessor comments: no dynamic input, just short vs long a…
Alex-Wengg Oct 21, 2025
8a70eca
Add spacing and comments to parakeet_decoder.cpp for readability
Alex-Wengg Oct 21, 2025
9478f3f
Refactor: address all PR code review feedback
Alex-Wengg Oct 21, 2025
7824170
Fix preprocessor dynamic shape handling to restore 2% WER
Alex-Wengg Oct 21, 2025
ebe7d06
Refactor: clean up error handling and improve code spacing
Alex-Wengg Oct 21, 2025
335def4
3rd round of code comments to address
Alex-Wengg Oct 21, 2025
0241967
addressing cpp code risks
Alex-Wengg Oct 21, 2025
544e3f9
minor comments address
Alex-Wengg Oct 22, 2025
ef961f4
minor comments address
Alex-Wengg Oct 22, 2025
10f5cd3
improve downloading models for users
Alex-Wengg Oct 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 41 additions & 70 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,83 +1,54 @@
# Prerequisites
*.d

# Compiled Object files
*.slo
*.lo
*.o
*.obj

# Precompiled Headers
*.gch
*.pch

# Linker files
*.ilk

# Debugger Files
*.pdb

# Compiled Dynamic libraries
*.so
*.dylib
*.dll

# Fortran module files
*.mod
*.smod

# Compiled Static libraries
*.lai
*.la
*.a
*.lib

# Executables
*.exe
*.out
*.app

# debug information files
*.dwo

# Build directories
build/
cmake-build-*/
out/

# Model files and cache
models/
cache/
*.blob
# Model files (too large for git)
models/**/*.bin
models/**/*.blob

# Test audio (can be large)
test_audio/

# IDE
.vscode/
.vs/
.idea/
*.swp
*.swo
.claude/
*.suo
*.user

# Python
__pycache__/
*.pyc
.venv/
venv/
# Compiled
*.o
*.obj
*.so
*.dll
*.dylib
*.a
*.lib

# Node.js
node_modules/
dist/
*.tsbuildinfo
# Cache
.cache/
*.cache
cache/

# .NET
bin/
obj/
*.user
*.suo
# Build artifacts
**/obj/
**/bin/Debug/
**/bin/Release/

# OS
.DS_Store
Thumbs.db
# IDE/Editor specific
.claude/
*.sln
*.vcxproj
*.vcxproj.filters
*.vcxproj.user

# Test files
test_*.wav
test_*.py
*_test.cpp

# Large archives
*.zip
openvino_*/

# Temporary scripts
download_*.bat
download_*.sh
run_*.bat
58 changes: 58 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Repository Guidelines

## Project Structure & Module Organization

- Source in `src/` (core, backends, `models/parakeet/`, pipelines, streaming); public headers in `include/eddy/`.
- Examples in `examples/cpp/` (`parakeet_cli.cpp`, `benchmark_librispeech.cpp`, optional `whisper_example.cpp`).
- Scripts in `scripts/` (model fetch); docs in `docs/` (e.g., `docs/Benchmark-Troubleshooting.md`).
- Assets: sample WAVs in repo root; models live under per-user app data, not in git.

## Build, Test, and Development Commands

- Configure: `cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DEDDY_ENABLE_OPENVINO=ON`
- Build tools: `cmake --build build --config Release --target eddy parakeet_cli benchmark_librispeech hf_fetch_models`
- Run CLI (NPU): `build\examples\cpp\Release\parakeet_cli.exe "<path-to-wav>" --device NPU`
- Benchmark (NPU): `build\examples\cpp\Release\benchmark_librispeech.exe --max-files 50 --device NPU`
- Tests (optional): configure with `-DBUILD_TESTING=ON`, then `ctest --test-dir build`
- Whisper (optional): add `-DEDDY_ENABLE_WHISPER=ON` and set `OpenVINOGenAI_DIR` if not auto-discovered.
- Python: always use `uv` commands, never use `pip` directly.

## Coding Style & Naming Conventions

- C++20; 2-space indentation; braces on the same line.
- Types/classes: PascalCase. Functions/variables/files: snake_case (e.g., `parakeet_openvino.cpp`).
- Keep headers under `include/eddy/...` mirrored by sources under `src/...`.
- Prefer small, focused functions; avoid inline comments unless clarifying non-obvious logic.

## Testing Guidelines

- Place unit/integration tests under `tests/` (enable with `-DBUILD_TESTING=ON`); name files `<area>_test.cpp`.
- Manual checks: use `parakeet_cli` and `benchmark_librispeech` with short WAVs and limited file counts.
- Cover new logic; document any gaps in the PR.

## Commit & Pull Request Guidelines

- Commits: imperative subject with optional scope (e.g., `parakeet: fix encoder port selection`).
- Keep changes focused; include rationale and before/after behavior.
- PRs should include summary, reproduction/validation steps, logs or screenshots, target device (CPU/NPU), and linked issues.

## Agent-Specific Instructions (Parakeet/OpenVINO)

- After editing `src/models/parakeet/` or related headers, clear compiled caches but keep downloaded models (Windows: `%LOCALAPPDATA%\eddy\models\parakeet-v2`, preserve `files/`). Quick PowerShell:

```powershell
$b = "$env:LOCALAPPDATA\eddy\models\parakeet-v2";
if (Test-Path $b) {
Get-ChildItem $b -File | Remove-Item -Force
Get-ChildItem $b -Directory | ? { $_.Name -ne 'files' } | Remove-Item -Recurse -Force
}
```

- Rebuild: `cmake --build build --config Release --target eddy parakeet_cli benchmark_librispeech hf_fetch_models`. First run after a cache clear will recompile models and may take minutes.

## Configuration & Models

- OpenVINO env: use `run_bench_npu.bat` to preload. If needed, set `OpenVINO_DIR` (e.g., `C:\Program Files (x86)\Intel\openvino_2025.0.0\runtime\cmake`).
- GenAI (Whisper): set `OpenVINOGenAI_DIR` when `EDDY_ENABLE_WHISPER=ON`.
- Download models: Models auto-download on first run via `hf_fetch_models`. Manual download: run `hf_fetch_models.exe` or visit <https://huggingface.co/FluidInference/parakeet-tdt-0.6b-v2-ov> (downloads into `%LOCALAPPDATA%\eddy\models\parakeet-v2\files`).
- Runtime knobs: `EDDY_OV_PERF`, `EDDY_OV_NUM_REQUESTS`, `EDDY_OV_THREADS`, `EDDY_CONTEXT_FRAMES`, `EDDY_BOUNDARY_SEARCH_FRAMES`, `EDDY_DISABLE_HOLDBACK=1`, `EDDY_DEDUP_PREV_TOKENS` (default 15).
85 changes: 67 additions & 18 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,34 @@
cmake_minimum_required(VERSION 3.22)
project(eddy LANGUAGES CXX)
project(eddy VERSION 0.1.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

option(EDDY_ENABLE_OPENVINO "Enable OpenVINO backend" ON)
# Enable interprocedural optimization (LTO/LTCG) for Release builds
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)

if(MSVC)
# Favor fast math and aggressive inlining for Release
# Use flags string to avoid malformed generator expressions on MSBuild
string(APPEND CMAKE_CXX_FLAGS_RELEASE " /O2 /Oi /Ot /Ob3 /fp:fast")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
# Equivalent optimization flags for GCC/Clang
string(APPEND CMAKE_CXX_FLAGS_RELEASE " -O3 -ffast-math -finline-functions")
endif()

option(EDDY_BUILD_EXAMPLES "Build examples" ON)
option(EDDY_BUILD_CSHARP "Build C# bindings" OFF)
option(EDDY_ENABLE_WHISPER "Enable Whisper (OpenVINO GenAI) support" ON)

if(EDDY_ENABLE_OPENVINO)
find_package(OpenVINO REQUIRED COMPONENTS Runtime)
# Core dependencies
find_package(OpenVINO REQUIRED COMPONENTS Runtime)
find_package(SndFile REQUIRED)
find_package(SampleRate REQUIRED)

# Whisper support (enabled by default, disable with -DEDDY_ENABLE_WHISPER=OFF)
if(EDDY_ENABLE_WHISPER)
find_package(OpenVINOGenAI REQUIRED)
endif()

Expand All @@ -25,38 +43,65 @@ target_include_directories(eddy

target_sources(eddy
PRIVATE
# Core utilities
src/core/runtime.cpp
src/core/model.cpp
src/core/app_dir.cpp
src/utils/audio_utils.cpp
src/utils/ensure_models.cpp
src/utils/openvino_utils.cpp

# OpenVINO backend
src/backends/openvino_backend.cpp

# Parakeet TDT v2 implementation
src/models/parakeet-v2/parakeet_openvino.cpp
src/models/parakeet-v2/parakeet_preprocessor.cpp
src/models/parakeet-v2/parakeet_encoder.cpp
src/models/parakeet-v2/parakeet_decoder.cpp
src/models/parakeet-v2/parakeet_chunking.cpp
src/models/parakeet-v2/tokenizer.cpp
)

if(EDDY_ENABLE_OPENVINO)
target_sources(eddy PRIVATE
src/pipelines/whisper_pipeline.cpp
src/pipelines/audio_utils.cpp
)
target_compile_definitions(eddy PUBLIC EDDY_WITH_OPENVINO=1)
target_link_libraries(eddy PUBLIC openvino::runtime openvino::genai)
# Link dependencies
target_compile_definitions(eddy PUBLIC EDDY_WITH_OPENVINO=1)
target_link_libraries(eddy
PUBLIC
openvino::runtime
SndFile::sndfile
SampleRate::samplerate
)

if(WIN32)
target_link_libraries(eddy PRIVATE Shell32)
endif()

# Whisper support (enabled by default)
if(EDDY_ENABLE_WHISPER)
target_sources(eddy PRIVATE src/pipelines/whisper_pipeline.cpp)
target_compile_definitions(eddy PUBLIC EDDY_WITH_OPENVINO_GENAI=1)
target_link_libraries(eddy PUBLIC openvino::genai)
endif()

install(TARGETS eddy EXPORT eddyTargets ARCHIVE DESTINATION lib LIBRARY DESTINATION lib RUNTIME DESTINATION bin)
install(EXPORT eddyTargets FILE eddyTargets.cmake NAMESPACE eddy:: DESTINATION lib/cmake/eddy)
install(DIRECTORY include/ DESTINATION include)
install(DIRECTORY include/
DESTINATION include
PATTERN "detail" EXCLUDE)

include(CMakePackageConfigHelpers)
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/eddyConfigVersion.cmake
VERSION 0.1.0
VERSION ${PROJECT_VERSION}
COMPATIBILITY AnyNewerVersion
)
set(EDDY_ENABLE_OPENVINO_CONFIG ${EDDY_ENABLE_OPENVINO})
configure_file(cmake/eddyConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/eddyConfig.cmake @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/eddyConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/eddyConfigVersion.cmake DESTINATION lib/cmake/eddy)

if(EDDY_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()

# Build a shared C API shim (eddy_c) that exposes the extern "C" FFI
# C API shim (always build; Whisper calls are no-ops if EDDY_ENABLE_WHISPER=OFF)
add_library(eddy_c SHARED src/eddy_c.cpp)
target_include_directories(eddy_c
PUBLIC
Expand All @@ -65,10 +110,14 @@ target_include_directories(eddy_c
)
target_link_libraries(eddy_c PRIVATE eddy)
target_compile_definitions(eddy_c PRIVATE EDDY_BUILD_SHARED=1)

install(TARGETS eddy_c RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)
install(TARGETS eddy_c
EXPORT eddyTargets
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)

include(CTest)
if(BUILD_TESTING)
# Only add tests if requested and the folder exists
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/CMakeLists.txt")
add_subdirectory(tests)
endif()
58 changes: 55 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,75 @@

eddy is a C++ inference library designed for native runtimes and multi-vendor edge NPUs, exposing a consistent C++ API plus language bindings for app developers (C#; more to follow). The current milestone focuses on the OpenVINO 2025.x backend for the Parakeet-TDT speech model family while we bring additional runtimes online.

## Platform Support

- Supported: Windows and Linux.
- Not supported: Apple platforms (macOS/iOS). For Apple, use FluidAudio (FA).

## Repository Layout

- `include/` – public headers for the runtime, backend abstractions, and model bridges.
- `src/` – backend/runtime implementations and model-specific glue code.
- `docs/` – design notes and usage guides.
- `benchmarks/` – Python scripts for LibriSpeech ASR benchmarking (see [benchmarks/README.md](benchmarks/README.md)).

## Building
## Dependencies

### Required
- **OpenVINO** (2025.x) - AI inference runtime
- **libsndfile** - Audio file I/O (WAV, FLAC, OGG, etc.)
- **libsamplerate** - High-quality audio resampling

### Optional
- **OpenVINO GenAI** - For Whisper support

### Installing with vcpkg (recommended)

```bash
# Install vcpkg dependencies (uses vcpkg.json manifest)
vcpkg install

# Or manually install specific packages
vcpkg install openvino libsndfile libsamplerate
Copy link
Member

Choose a reason for hiding this comment

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

ACcording to GPT - precompiling the libraries and .d files are preferred over users manually installing deps for C++ SDKs but do push abck here

Excellent question — this is a subtle but crucial decision when distributing a C++ SDK. The short answer is:

✅ Most modern C++ SDKs ship dependencies as statically linked libraries, or via embedded source / vendored builds (CMake ExternalProject, FetchContent, etc.) — not DLLs.

Let’s break down the common patterns and tradeoffs so you can choose the right one for your SDK.

🧩 1. Static Linking (Most Common for SDKs)

✅ Recommended for SDKs / developer libraries.

How it works

You compile dependencies (.lib or .a) into your SDK’s .lib / .dll or .so.

Consumers don’t need to install those libs separately.

Why it’s preferred

Zero runtime DLL hassles (no “missing .dll” errors).

Version safety — your SDK controls which version of libsndfile/libsamplerate it uses.

Easier for cross-platform builds and packaging (one .lib or .a per platform).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i gave it a try and it created like 25 extra files. maybe not in this pr

```

## Building

```bash
# Configure with vcpkg toolchain
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=[path-to-vcpkg]/scripts/buildsystems/vcpkg.cmake

# Or specify OpenVINO manually if not using vcpkg
cmake -S . -B build -DOpenVINO_DIR=/opt/intel/openvino/runtime/cmake
cmake --build build

# Build
cmake --build build --config Release
```

The build emits the static target `eddy` with all required dependencies.

### Optional Whisper Support

```bash
cmake -S . -B build -DEDDY_ENABLE_WHISPER=ON -DOpenVINOGenAI_DIR="<path-to-genai-cmake>"
```

The build emits the static target `eddy` with OpenVINO linked in when `EDDY_ENABLE_OPENVINO=ON` (default).
## Models (auto-download on first run)

Models will automatically download from `FluidInference/parakeet-tdt-0.6b-v2-ov` on first use.

Cached at: `%LOCALAPPDATA%\eddy\models\parakeet-v2\files\`

Manual download: Run `hf_fetch_models.exe` or visit <https://huggingface.co/FluidInference/parakeet-tdt-0.6b-v2-ov>

To disable auto-download: set `EDDY_DISABLE_AUTO_FETCH=1`

## Parakeet OpenVINO Prototype

Refer to `docs/parakeet_openvino.md` for instructions on pulling the exported model from Hugging Face and running a smoke test through the new `OpenVINOParakeet` wrapper.

## Roadmap Snapshot

- Flesh out Parakeet preprocessing (feature pipeline, tokenizer, decoder).
- Add telemetry and zero-copy buffers per backend.
- Introduce unit and integration tests (GoogleTest) with small audio fixtures.
Expand Down
Loading