fix(tts): correct cosy audio end interval - #2264
Conversation
Review:
|
6f4d5ec to
b09486a
Compare
Review:
|
b09486a to
1801f66
Compare
Review:
|
1801f66 to
dc39efa
Compare
Review:
|
|
|
Review: fix(tts): correct cosy audio end interval The change is correct in direction and well scoped. 1. Measured endpoint does not match the documented semantics The docs define the field as the interval between first audio chunk arrival and last audio chunk arrival. The new code measures first chunk to
def _calculate_request_event_interval_ms(self) -> int:
if self._first_audio_chunk_ts is None or self._last_audio_chunk_ts is None:
return 0
return int((self._last_audio_chunk_ts - self._first_audio_chunk_ts).total_seconds() * 1000)Tracking 2. It is reset only in 3. Cross-extension inconsistency
4. Test feedback The new assertions are good regression coverage. In particular
Security and performance Nothing of concern. Two Summary Approve in spirit. Items 1 and 2 are worth folding in before merge (small, local changes), item 3 is a follow-up, item 4 is optional tightening. |
CosyVoice hardening updateThe branch now contains the complete repository-owned CosyVoice hardening change, split into focused commits so the functional and test diffs are easy to review. Runtime
Diagnostics and tests
Current limits
|
|
Reviewed the full diff (19 files, ~2.1k added / ~1.2k removed). This is effectively a rewrite of the extension rather than the interval fix the title suggests. The direction is good — the old Findings below, ordered by severity. 1. Blocking: empty final chunk ends the request while synthesis is still in flight In if t.text_input_end:
if not text and self.first_chunk:
await self._finish_request_once(t.request_id, TTSAudioEndReason.REQUEST_END)
return
await self.client.complete(t.request_id)
Concrete failure:
Result: the caller gets a successful A trailing empty chunk carrying 2. Default
The README advises sizing to 1.5–2x peak concurrency, but the default that ships is 1. If a worker process can host more than one graph or channel — which the singleton-pool design explicitly anticipates — the default configuration breaks under any concurrency at all. Recommend either raising the default, or having pool exhaustion fall back to an unpooled synthesizer instead of failing the request. 3.
Related: 4. Previously Similarly, Smaller items
Security Nothing alarming. Note that Test coverage The Gaps, all on newly added surface area:
Conventions Please confirm Nice work on the lifecycle model overall — the lease/active-task split is a genuine improvement over what was there. Findings 1 and 2 are the ones I would want resolved before merge. |
|
Review: fix(tts): correct cosy audio end interval Solid rework of the Cosy TTS lifecycle. Pool-based preconnect, explicit watchdogs, and structured Correctness
Quality
Security Good: Dependencies
Test coverage
These are the paths most likely to regress silently, and they are all unit-testable with the existing Before merge Per |
|
Review of the cosy_tts_python changes. The core interval fix looks right, and several parts of the rewrite are genuine improvements: moving blocking DashScope calls off the event loop with One process note first: the title says "correct cosy audio end interval" but the diff is a ~1200-line rewrite of the client lifecycle, connection pooling, config extraction, and error classification. Most of my comments concern the parts beyond the stated fix. Landing the interval fix separately from the pooling rewrite would be easier to review and much safer to revert if the pool misbehaves in production. I could not run the tests or import 1. 2. 3. Race between |
|
Review: fix(tts): correct cosy audio end interval Reviewed the full diff (~1977/-1229 across 19 files). The headline fix is right, but the PR bundles a large rewrite alongside it, and a few things are worth confirming before merge. The core fix is correct
The old code used 1. Blocking question: does the base class accept This is my main concern. The PR passes
Worth noting the unit tests would not catch this: they patch 2.
elif cls._signature != signature:
raise ValueError("Cosy TTS pool is already initialized with different credentials, ...")The README documents this, and the constraint is genuinely imposed by DashScope authenticating at handshake time, so the design is defensible. But it is a real behavioral regression in configuration flexibility: previously each extension instance built its own Two smaller things in the same class:
3. value = self.params.pop(param_name)
if not self.is_black_list_params(param_name):
setattr(self, param_name, value)The Relatedly, 4. Per 5. Global-state leakage between tests in
@pytest.fixture(autouse=True)
def _clean_shared_pool():
_reset_shared_pool()
yield
_reset_shared_pool()6. Version string duplicated into a header and asserted on
Smaller notes
Test coverage Consolidating five hand-rolled streamer classes into
The Summary: the interval fix is correct and well-tested. Item 1 is a genuine blocker until the |
|
Reviewed the full diff (19 files, +2014/-1245). The headline fix is right and matches repo convention: One blocking bug and a few things worth tightening. 1. Blocking: empty final chunk aborts a request that has real text In if t.text_input_end:
if not text and self.first_chunk:
await self._finish_request_once(t.request_id, TTSAudioEndReason.REQUEST_END)
return
await self.client.complete(t.request_id)
The old code used if not text and self.request_text_characters == 0:Worth a regression test: two 2. Error classification Per 3. lease = await asyncio.to_thread(SharedPool.borrow, self.config, callback)
callback.bind_task(lease.synthesizer.get_last_request_id())This reads the task id before 4.
with cls._lock:
current_pool = cls._pool
if lease.pool is current_pool:
lease.pool.return_synthesizer(lease.synthesizer)A concurrent 5. Version string duplicated a third time
6. Test hygiene
Coverage is otherwise solid: 7. Smaller notes
Before pushing Per sudo docker exec ten_agent_dev bash -c "cd /app && task format && task check && task lint"Overall a good, well-structured refactor. The lifecycle is genuinely easier to reason about than what it replaces and the interval fix is correct. Section 1 is the one I would want fixed before merge; 2 through 4 are correctness issues I would want at least answered. |
|
Reviewed the full diff (19 files, +2018/-1244). This is a solid rewrite of the Cosy TTS lifecycle — the pooled SDK path, single-writer 1. In if not text and self.first_chunk:
await self._finish_request_once(t.request_id, TTSAudioEndReason.REQUEST_END)
return
await self.client.complete(t.request_id)
The old code used a dedicated 2.
3. Every other extension in the repo declares 4. The first extension instance in a worker wins the pool config; a second instance with a different
5.
6. Smaller items
Test coverage Good: the Gaps worth adding:
Commit messages and branch name follow the conventional-commit rules in |
|
Reviewed the full diff (19 files, +2042/-1247). This is a large rewrite of The titled fix is correct and matches convention
1. The reasoning in the comment is sound for the normal path, but it leaves One wedged task holds one of only 2. Dump writes can be silently dropped
3. If the task is cancelled between 4. Pool signature-mismatch diagnostic is thin
5.
6. Magic numbers in 20000 (per-chunk chars) and 200000 (per-task chars) are inline literals raised as bare 7. Sample-rate validation is now strict -- confirm intended Previously an unsupported rate warned and fell back to 8. Security: pinning and redaction both improved
Nit: 9. Test coverage: much improved, three gaps
10. Conventions and CI Commits are conventional and correctly scoped, though Please confirm Net: the interval fix is right, the pooling architecture is a genuine improvement, and the test consolidation pays for itself. Items 1, 2, and 3 are the ones I would want addressed or explicitly waved off before merge -- item 1 has a production-starvation shape. |
No description provided.