-
Notifications
You must be signed in to change notification settings - Fork 59
171 lines (153 loc) · 7.07 KB
/
Copy pathci.yml
File metadata and controls
171 lines (153 loc) · 7.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
name: ci
on:
push:
pull_request:
# closed-loop job runs on pull_request (gate) and manual dispatch (see below).
workflow_dispatch:
jobs:
# -------------------------------------------------------------------------
# build: configure, compile, run model-independent unit tests.
# Runs on every push and pull_request. Never downloads a model — fast gate.
# -------------------------------------------------------------------------
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: configure
# GGML_NATIVE=OFF for portability in CI (no host-cpu ISA extensions)
run: cmake -B build -DPARAKEET_BUILD_TESTS=ON -DGGML_NATIVE=OFF
- name: build
run: cmake --build build -j
- name: test (model-independent only)
# -LE model excludes the model-labelled tests (check_convert,
# test_model_loader, check_baseline) that need the Python venv and the
# cached NeMo checkpoint. Those will run in a separate workflow_dispatch
# job once a models bundle is published (Phase 4).
run: ctest --test-dir build --output-on-failure -LE model
# -------------------------------------------------------------------------
# server-e2e: drive the real parakeet-server over HTTP.
#
# Runs on pull_request (merge gate) and manual workflow_dispatch. Not on every
# push: it downloads the ~125 MB tdt_ctc-110m-q4_k model via the alias path.
# Much lighter than closed-loop (no NeMo/Python venv) — it builds the server,
# then tests/server_e2e.sh starts it, transcribes tests/fixtures/speech.wav in
# json/text/verbose_json (with word timestamps), and checks the 400 paths.
# -------------------------------------------------------------------------
server-e2e:
if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake build-essential curl ca-certificates
- name: Configure
run: |
cmake -B build \
-DPARAKEET_BUILD_SERVER=ON \
-DPARAKEET_BUILD_TESTS=ON \
-DGGML_NATIVE=OFF
- name: Build parakeet-server
run: cmake --build build --target parakeet-server -j
- name: Run server e2e
# PARAKEET_SERVER_E2E=1 flips the test from skip (77) to a real run.
env:
PARAKEET_SERVER_E2E: "1"
# First-run model download speed varies on hosted runners; the job
# timeout remains the outer cap.
PARAKEET_SERVER_E2E_READY_TIMEOUT: "600"
run: ctest --test-dir build --output-on-failure -R '^server_e2e$'
# -------------------------------------------------------------------------
# closed-loop: full end-to-end transcript assertion.
#
# Runs on pull_request (merge gate) and manual workflow_dispatch. Not on every
# push, since this job downloads nvidia/parakeet-tdt_ctc-110m (~440 MB via
# NeMo/HuggingFace Hub) and installs the nemo_toolkit Python env (~60 min).
#
# What it does:
# 1. Check out the repo (submodules recursive).
# 2. Install system build deps + Python 3.12 + pip.
# 3. Create a venv and install CPU torch + scripts/requirements.txt
# (nemo_toolkit[asr] + gguf) — same setup as the developer guide.
# 4. Build the project (GGML_NATIVE=OFF for runner portability,
# PARAKEET_BUILD_TESTS=ON, PARAKEET_BUILD_CLI=ON).
# 5. Convert nvidia/parakeet-tdt_ctc-110m → /tmp/pk110m_cl.gguf
# (F32, default dtype; NeMo auto-downloads the checkpoint on first use).
# 6. Run `parakeet-cli transcribe` on tests/fixtures/speech.wav with
# --decoder tdt (the TDT head of the hybrid model).
# 7. Assert the output matches the committed NeMo reference transcript:
# "Well, I don't wish to see it any more, observed Phoebe,
# turning away her eyes. It is certainly very like the old portrait."
# Fail the job if it doesn't match.
# -------------------------------------------------------------------------
closed-loop:
if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Checkout (with submodules)
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install system build dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake build-essential python3 python3-venv python3-pip
- name: Set up Python venv
# CPU-only torch wheel; nemo_toolkit[asr] + gguf from requirements.txt.
# Mirror the developer setup documented in AGENTS.md / README.md.
run: |
python3 -m venv .venv
.venv/bin/pip install --quiet --upgrade pip
.venv/bin/pip install --quiet torch --index-url https://download.pytorch.org/whl/cpu
.venv/bin/pip install --quiet -r scripts/requirements.txt
- name: Configure CMake
run: |
cmake -B build \
-DPARAKEET_BUILD_TESTS=ON \
-DPARAKEET_BUILD_CLI=ON \
-DGGML_NATIVE=OFF
- name: Build
run: cmake --build build -j
- name: Convert nvidia/parakeet-tdt_ctc-110m to GGUF
# NeMo downloads the ~440 MB checkpoint from HuggingFace on first use.
# The resulting GGUF is ~438 MB (F32).
run: |
.venv/bin/python scripts/convert_parakeet_to_gguf.py \
--model nvidia/parakeet-tdt_ctc-110m \
--output /tmp/pk110m_cl.gguf
- name: Transcribe speech fixture with TDT decoder
run: |
./build/examples/cli/parakeet-cli transcribe \
--model /tmp/pk110m_cl.gguf \
--input tests/fixtures/speech.wav \
--decoder tdt \
> /tmp/cl_transcript.txt
echo "--- transcript ---"
cat /tmp/cl_transcript.txt
- name: Assert transcript matches NeMo reference
# Reference transcript (TDT head, hybrid 110m) committed to docs/parity.md
# and validated at WER 0.0 vs NeMo 2.7.3 (see docs/parity.md § Phase 3).
run: |
EXPECTED="Well, I don't wish to see it any more, observed Phoebe, turning away her eyes. It is certainly very like the old portrait."
ACTUAL="$(cat /tmp/cl_transcript.txt)"
python3 - <<'PYEOF'
import sys
expected = "Well, I don't wish to see it any more, observed Phoebe, turning away her eyes. It is certainly very like the old portrait."
with open("/tmp/cl_transcript.txt") as f:
actual = f.read().strip()
if actual == expected:
print("PASS: transcript matches NeMo reference (WER 0.0)")
sys.exit(0)
else:
print("FAIL: transcript mismatch")
print(f" expected: {expected!r}")
print(f" actual: {actual!r}")
sys.exit(1)
PYEOF