Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
76173da
add OmniPayloadStruct (msgspec) alongside TypedDict for runtime paylo…
divyanshsinghvi Apr 25, 2026
dbc16d5
tighten dict to OmniPayload in qwen3_omni, qwen3_tts, mimo_audio, mix…
divyanshsinghvi Apr 25, 2026
01429d5
add validate_payload boundary helper that raises on schema drift
divyanshsinghvi Apr 25, 2026
baae107
migrate qwen3_tts talker2code2wav_async_chunk to construct OmniPayloa…
divyanshsinghvi Apr 25, 2026
55f6b24
migrate qwen3_omni talker2code2wav_async_chunk to OmniPayloadStruct, …
divyanshsinghvi Apr 25, 2026
4e31b65
keep codes.audio as torch.Tensor end-to-end, convert to list only at …
divyanshsinghvi Apr 25, 2026
a6f031e
migrate qwen3_omni thinker2talker_async_chunk to construct OmniPayloa…
divyanshsinghvi Apr 25, 2026
cb904b0
migrate qwen3_omni thinker2talker (full payload) to construct OmniPay…
divyanshsinghvi Apr 25, 2026
a50f745
migrate mimo_audio llm2code2wav_async_chunk to OmniPayloadStruct
divyanshsinghvi Apr 25, 2026
d9e1624
qwen3_tts and cosyvoice3: write meta.left_context_size as int, drop l…
divyanshsinghvi Apr 25, 2026
d8d510e
drop defensive int() casts now that producers write meta.left_context…
divyanshsinghvi Apr 25, 2026
992f61e
drop redundant top-level cosyvoice3 token_offset (same value as meta.…
divyanshsinghvi Apr 25, 2026
2fcab85
migrate qwen2_5_omni thinker2talker to OmniPayloadStruct, add output_…
divyanshsinghvi Apr 25, 2026
fb99cbb
migrate voxtral_tts and fish_speech async_chunk producers to OmniPayl…
divyanshsinghvi Apr 25, 2026
56bc097
fix voxcpm latent2vae_async_chunk: write nested codes.audio + meta.fi…
divyanshsinghvi Apr 25, 2026
2263532
add encode_payload/decode_payload helpers (msgspec-native) for OmniPa…
divyanshsinghvi Apr 25, 2026
238d14a
drop tautological tests for TypedDict construction and msgspec attr a…
divyanshsinghvi Apr 25, 2026
12fc0be
drop flatten_payload/unflatten_payload from pooler_output path; data …
divyanshsinghvi Apr 25, 2026
d595ed2
trim ai-slop docstrings, align data_entry_keys header with project co…
divyanshsinghvi Apr 25, 2026
f874199
make build_mm_cpu and to_payload_element handle nested dicts of tenso…
divyanshsinghvi Apr 25, 2026
84d7e5c
switch additional_information wire type to OmniPayloadStruct, drop le…
divyanshsinghvi Apr 25, 2026
93b76de
convert dict to OmniPayloadStruct at additional_information assignmen…
divyanshsinghvi Apr 25, 2026
25c674b
fix stale AdditionalInformationPayload import in core/sched/output.py
divyanshsinghvi Apr 25, 2026
02cc628
drop bfloat16 from encode/decode round-trip dtype test
divyanshsinghvi Apr 26, 2026
4c550b6
Merge remote-tracking branch 'origin/main' into payload-msgspec-struct
divyanshsinghvi Apr 26, 2026
04ed253
fix tests for nested meta.left_context_size and tensor codes.audio
divyanshsinghvi Apr 26, 2026
242132b
revert additional_information wire type from OmniPayloadStruct to Add…
divyanshsinghvi Apr 26, 2026
28cce90
revert pooler_output wire format from dict[str, Any] to dict[str, tor…
divyanshsinghvi Apr 26, 2026
8787428
update qwen3_tts and voxtral_tts async-chunk test assertions for nest…
divyanshsinghvi Apr 26, 2026
b90c384
revert producer-side flatten_payload in gpu_ar_model_runner
divyanshsinghvi Apr 26, 2026
b82fd5e
update cosyvoice3 and voxcpm test assertions for nested meta/codes la…
divyanshsinghvi Apr 26, 2026
1ed9132
migrate cosyvoice3 prompt-conditioning tensors to embed.*
divyanshsinghvi Apr 26, 2026
9d021fc
update cosyvoice3 stage_input_processor tests for nested embed.* layout
divyanshsinghvi Apr 26, 2026
9e38527
fix test_generation_mode for nested meta.left_context_size
divyanshsinghvi Apr 26, 2026
ce59a17
recurse into nested dicts in prefix-cache mm_payload unwrap; restore …
divyanshsinghvi Apr 26, 2026
22d1bbc
restore flatten/unflatten/serialize/deserialize tests (skip tautologi…
divyanshsinghvi Apr 26, 2026
d4e7f34
migrate cosyvoice3 talker2code2wav_async_chunk producer to OmniPayloa…
divyanshsinghvi Apr 26, 2026
c1e7a97
narrow OmniPayloadStruct.speaker/language from Any to list[str] | str…
divyanshsinghvi Apr 26, 2026
f7d4f65
Merge branch 'main' into payload-msgspec-struct
divyanshsinghvi Apr 26, 2026
d8f4942
flatten nested multimodal_outputs at prefix-cache boundary
divyanshsinghvi Apr 26, 2026
adebc20
migrate cosyvoice3 code2wav consumer to typed OmniPayloadStruct access
divyanshsinghvi Apr 27, 2026
5cbb0f7
DEBUG: add PCDIAG logs to prefix-cache write/read paths
divyanshsinghvi Apr 27, 2026
6180aaf
DEBUG: log num_computed_tokens at scheduled_new_reqs
divyanshsinghvi Apr 27, 2026
dee4f27
remove PCDIAG diagnostic logs from prefix cache + model runner
divyanshsinghvi Apr 27, 2026
f6e3199
return OmniPayloadStruct from async_chunk producers, drop to_dict at …
divyanshsinghvi Apr 27, 2026
4d70016
fix chunk_transfer_adapter test fixture: producer mock returns OmniPa…
divyanshsinghvi Apr 27, 2026
a479da4
add wire-equivalence test for OmniPayloadStruct vs to_dict
divyanshsinghvi Apr 27, 2026
78bf298
type producer hook + pin struct/dict wire asymmetry
divyanshsinghvi Apr 28, 2026
fc4b9e9
unify chunk-payload accumulators on shared depth-2 merger
divyanshsinghvi Apr 28, 2026
e7e3ff2
delete unused encode_payload/decode_payload helpers
divyanshsinghvi Apr 28, 2026
21e4f3d
read next_stage_prompt_len from meta with legacy-flat fallback
divyanshsinghvi Apr 28, 2026
7ecfe8a
preserve empty top-level lists in build_mm_cpu
divyanshsinghvi Apr 28, 2026
1a30f92
Merge branch 'main' into payload-msgspec-struct
divyanshsinghvi Apr 28, 2026
ba7e952
add _send_single_request edge-case tests (struct-without-meta, empty …
divyanshsinghvi Apr 28, 2026
a56b45d
port pre-standardize accumulator semantics to nested layout
divyanshsinghvi Apr 28, 2026
258a25b
Merge branch 'main' into payload-msgspec-struct
divyanshsinghvi May 7, 2026
bb97535
Merge branch 'main' into payload-msgspec-struct
divyanshsinghvi May 7, 2026
b4a3df3
Merge branch 'main' into payload-msgspec-struct
divyanshsinghvi May 11, 2026
036a918
fix(test): use attribute access on OmniPayloadStruct in async chunk test
divyanshsinghvi May 12, 2026
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
2 changes: 1 addition & 1 deletion tests/core/sched/test_chunk_scheduling_coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ def test_generation_mode(self):
self.assertEqual(req.prompt_token_ids, [10, 20, 30])
self.assertEqual(req.num_computed_tokens, 0)
self.assertIsNone(req.additional_information)
self.assertEqual(req._omni_initial_model_buffer, {"left_context_size": 25})
self.assertEqual(req._omni_initial_model_buffer, {"meta": {"left_context_size": 25}})


class TestChunkCoordinatorPostprocess(unittest.TestCase):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from vllm.v1.core.sched.scheduler import Scheduler as VLLMScheduler
from vllm.v1.request import RequestStatus

from vllm_omni.data_entry_keys import OmniPayload
from vllm_omni.data_entry_keys import CodesStruct, MetaStruct, OmniPayload, OmniPayloadStruct
from vllm_omni.distributed.omni_connectors.transfer_adapter.base import OmniTransferAdapterBase
from vllm_omni.distributed.omni_connectors.transfer_adapter.chunk_transfer_adapter import (
OmniChunkTransferAdapter,
Expand Down Expand Up @@ -140,11 +140,54 @@ def test_save_async(build_adapter):
assert task["is_finished"] is False


def test_send_single_request_struct_without_meta_does_not_crash(build_adapter, monkeypatch):
"""Producer may return a struct with ``meta=None`` (e.g. payload that
carries only ``embed`` or ``codes``). The sender's ``meta is not None``
guard handles this without AttributeError; ``finished_flag`` is None and
the cleanup path is not triggered.
"""
adapter, _ = build_adapter(stage_id=1)
request = _req("req-no-meta", RequestStatus.WAITING, external_req_id="ext-no-meta")

adapter.custom_process_next_stage_input_func = lambda **kwargs: OmniPayloadStruct(
codes=CodesStruct(audio=torch.tensor([1, 2], dtype=torch.long)),
)
cleanup_calls = []
monkeypatch.setattr(adapter, "cleanup", lambda *a, **kw: cleanup_calls.append((a, kw)))

adapter._send_single_request({"pooling_output": None, "request": request, "is_finished": False})

assert cleanup_calls == [] # no terminal cleanup; meta.finished is unobservable


def test_send_single_request_empty_struct_goes_on_wire(build_adapter, monkeypatch):
"""Pin the contract: an explicitly empty ``OmniPayloadStruct()`` passes
the ``payload_data is None`` check and gets sent. To skip a chunk, the
producer must return ``None``, not an empty struct. (Filtering empty
structs at the adapter would require introspecting all struct fields on
every send and was rejected for cost vs. value.)
"""
adapter, connector = build_adapter(stage_id=1)
request = _req("req-empty", RequestStatus.WAITING, external_req_id="ext-empty")

adapter.custom_process_next_stage_input_func = lambda **kwargs: OmniPayloadStruct()
monkeypatch.setattr(adapter, "cleanup", lambda *a, **kw: None)

adapter._send_single_request({"pooling_output": None, "request": request, "is_finished": False})

assert connector.put.called
sent_payload = connector.put.call_args.kwargs["data"]
assert isinstance(sent_payload, OmniPayloadStruct)
assert sent_payload.meta is None # confirms it's the empty struct on the wire


def test_send_single_request_cleans_up_after_finished_payload(build_adapter, monkeypatch):
adapter, _ = build_adapter(stage_id=1)
request = _req("req-finished", RequestStatus.FINISHED_STOPPED, external_req_id="ext-finished")

adapter.custom_process_next_stage_input_func = lambda **kwargs: {"x": [1], "finished": True}
adapter.custom_process_next_stage_input_func = lambda **kwargs: OmniPayloadStruct(
meta=MetaStruct(finished=torch.tensor(True, dtype=torch.bool))
)
cleanup_calls = []
monkeypatch.setattr(adapter, "cleanup", lambda *a, **kw: cleanup_calls.append((a, kw)))

Expand Down Expand Up @@ -604,3 +647,42 @@ def _super_finish(_self, request_ids, finished_status):
OmniARScheduler.finish_requests(sched, ["r1"], RequestStatus.FINISHED_ABORTED)

assert order == ["adapter", "super"]


def test_wire_round_trip_struct_to_dict_contract():
"""Pin the wire contract: encoding ``OmniPayloadStruct`` and decoding it
yields a dict equivalent to ``to_dict(struct)``.

The chunk-adapter sender uses struct attribute access while the receiver
uses dict-key access. This works only because ``OmniMsgpackDecoder`` has
no target type and decodes structs back to plain dicts. If this test
breaks, the receiver's dict access will silently drop fields or KeyError.
"""
from vllm_omni.data_entry_keys import CodesStruct, to_dict
from vllm_omni.distributed.omni_connectors.utils.serialization import (
OmniMsgpackDecoder,
OmniMsgpackEncoder,
)

struct = OmniPayloadStruct(
meta=MetaStruct(
finished=torch.tensor(True, dtype=torch.bool),
left_context_size=12,
),
codes=CodesStruct(audio=torch.tensor([1, 2, 3], dtype=torch.int64)),
)

encoded = OmniMsgpackEncoder().encode(struct)
decoded = OmniMsgpackDecoder().decode(encoded)

assert isinstance(decoded, dict)
assert isinstance(decoded["meta"], dict)
assert isinstance(decoded["meta"]["finished"], torch.Tensor)
assert bool(decoded["meta"]["finished"].item()) is True
assert decoded["meta"]["left_context_size"] == 12
assert torch.equal(decoded["codes"]["audio"], torch.tensor([1, 2, 3], dtype=torch.int64))

expected = to_dict(struct)
assert set(decoded.keys()) == set(expected.keys())
assert set(decoded["meta"].keys()) == set(expected["meta"].keys())
assert set(decoded["codes"].keys()) == set(expected["codes"].keys())
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,12 @@ def test_forward_prefers_token_offset_when_present():

runtime_info = [
{
"speech_token": torch.tensor([[1, 2, 3]], dtype=torch.long),
"speech_feat": torch.tensor([[[0.1, 0.2], [0.3, 0.4]]], dtype=torch.float32),
"embedding": torch.tensor([[0.5, 0.6]], dtype=torch.float32),
"token_offset": 2,
"left_context_size": 1,
"embed": {
"speech_token": torch.tensor([[1, 2, 3]], dtype=torch.long),
"speech_feat": torch.tensor([[[0.1, 0.2], [0.3, 0.4]]], dtype=torch.float32),
"embedding": torch.tensor([[0.5, 0.6]], dtype=torch.float32),
},
"meta": {"left_context_size": 2},
}
]

Expand All @@ -193,10 +194,12 @@ def test_forward_falls_back_to_left_context_size_for_backward_compat():

runtime_info = [
{
"speech_token": torch.tensor([[1, 2, 3]], dtype=torch.long),
"speech_feat": torch.tensor([[[0.1, 0.2], [0.3, 0.4]]], dtype=torch.float32),
"embedding": torch.tensor([[0.5, 0.6]], dtype=torch.float32),
"left_context_size": 2,
"embed": {
"speech_token": torch.tensor([[1, 2, 3]], dtype=torch.long),
"speech_feat": torch.tensor([[[0.1, 0.2], [0.3, 0.4]]], dtype=torch.float32),
"embedding": torch.tensor([[0.5, 0.6]], dtype=torch.float32),
},
"meta": {"left_context_size": 2},
}
]

Expand All @@ -214,10 +217,12 @@ def test_forward_ignores_single_request_padded_tail_tokens():
model = _make_code2wav_model(with_stride_cfg=True)
runtime_info = [
{
"speech_token": torch.tensor([[1, 2, 3]], dtype=torch.long),
"speech_feat": torch.tensor([[[0.1, 0.2], [0.3, 0.4]]], dtype=torch.float32),
"embedding": torch.tensor([[0.5, 0.6]], dtype=torch.float32),
"token_offset": 0,
"embed": {
"speech_token": torch.tensor([[1, 2, 3]], dtype=torch.long),
"speech_feat": torch.tensor([[[0.1, 0.2], [0.3, 0.4]]], dtype=torch.float32),
"embedding": torch.tensor([[0.5, 0.6]], dtype=torch.float32),
},
"meta": {"left_context_size": 0},
}
]

Expand All @@ -238,10 +243,12 @@ def test_forward_uses_non_stream_decode_without_chunk_metadata():

runtime_info = [
{
"speech_token": torch.tensor([[1, 2, 3]], dtype=torch.long),
"speech_feat": torch.tensor([[[0.1, 0.2], [0.3, 0.4]]], dtype=torch.float32),
"embedding": torch.tensor([[0.5, 0.6]], dtype=torch.float32),
"prefix_ids": [101, 102],
"embed": {
"speech_token": torch.tensor([[1, 2, 3]], dtype=torch.long),
"speech_feat": torch.tensor([[[0.1, 0.2], [0.3, 0.4]]], dtype=torch.float32),
"embedding": torch.tensor([[0.5, 0.6]], dtype=torch.float32),
},
"ids": {"prompt": [101, 102]},
"generated_len": 3,
}
]
Expand Down Expand Up @@ -275,12 +282,16 @@ def test_forward_reuses_streaming_cache_state_between_chunks():
)
runtime_info = [
{
"req_id": ["rid-stream"],
"speech_token": torch.tensor([[1, 2, 3]], dtype=torch.long),
"speech_feat": torch.tensor([[[0.1, 0.2], [0.3, 0.4]]], dtype=torch.float32),
"embedding": torch.tensor([[0.5, 0.6]], dtype=torch.float32),
"token_offset": 0,
"stream_finished": torch.tensor(False),
"embed": {
"speech_token": torch.tensor([[1, 2, 3]], dtype=torch.long),
"speech_feat": torch.tensor([[[0.1, 0.2], [0.3, 0.4]]], dtype=torch.float32),
"embedding": torch.tensor([[0.5, 0.6]], dtype=torch.float32),
},
"meta": {
"req_id": ["rid-stream"],
"stream_finished": torch.tensor(False),
"left_context_size": 0,
},
}
]

Expand Down Expand Up @@ -321,12 +332,16 @@ def test_forward_clears_streaming_cache_on_terminal_chunk():
)
runtime_info = [
{
"req_id": ["rid-stream"],
"speech_token": torch.tensor([[1, 2, 3]], dtype=torch.long),
"speech_feat": torch.tensor([[[0.1, 0.2], [0.3, 0.4]]], dtype=torch.float32),
"embedding": torch.tensor([[0.5, 0.6]], dtype=torch.float32),
"token_offset": 0,
"stream_finished": torch.tensor(False),
"embed": {
"speech_token": torch.tensor([[1, 2, 3]], dtype=torch.long),
"speech_feat": torch.tensor([[[0.1, 0.2], [0.3, 0.4]]], dtype=torch.float32),
"embedding": torch.tensor([[0.5, 0.6]], dtype=torch.float32),
},
"meta": {
"req_id": ["rid-stream"],
"stream_finished": torch.tensor(False),
"left_context_size": 0,
},
}
]

Expand All @@ -338,7 +353,7 @@ def test_forward_clears_streaming_cache_on_terminal_chunk():
)
assert "rid-stream" in model._stream_vocoder_cache_by_req

runtime_info[0]["stream_finished"] = torch.tensor(True)
runtime_info[0]["meta"]["stream_finished"] = torch.tensor(True)
out = model.forward(
input_ids=torch.tensor([0, 1, 2], dtype=torch.long),
positions=torch.tensor([0, 1, 2], dtype=torch.long),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,11 @@ def test_talker2code2wav_async_chunk_final_payload_uses_absolute_token_offset():
external_req_id="rid-0",
output_token_ids=[1, 2, 6562, 3],
additional_information={
"speech_token": [torch.tensor([[11, 12, 13]])],
"speech_feat": [torch.tensor([[[0.1, 0.2], [0.3, 0.4]]])],
"embedding": [torch.tensor([[0.5, 0.6]])],
"embed": {
"speech_token": [torch.tensor([[11, 12, 13]])],
"speech_feat": [torch.tensor([[[0.1, 0.2], [0.3, 0.4]]])],
"embedding": [torch.tensor([[0.5, 0.6]])],
},
},
is_finished=lambda: True,
)
Expand All @@ -79,15 +81,14 @@ def test_talker2code2wav_async_chunk_final_payload_uses_absolute_token_offset():
)

assert payload is not None
assert payload["meta"]["finished"].item() is True
assert payload["codes"]["audio"] == [1, 2, 3]
assert payload["token_offset"] == 0
assert payload["left_context_size"] == 0
assert payload["req_id"] == ["rid-0"]
assert payload["stream_finished"].item() is True
assert "speech_token" in payload
assert "speech_feat" in payload
assert "embedding" in payload
assert payload.meta.finished.item() is True
assert payload.codes.audio.tolist() == [1, 2, 3]
assert payload.meta.left_context_size == 0
assert payload.meta.req_id == ["rid-0"]
assert payload.meta.stream_finished.item() is True
assert payload.embed.speech_token is not None
assert payload.embed.speech_feat is not None
assert payload.embed.embedding is not None


def test_talker2code2wav_async_chunk_emits_eof_when_finished_without_valid_codes():
Expand All @@ -107,8 +108,8 @@ def test_talker2code2wav_async_chunk_emits_eof_when_finished_without_valid_codes
)

assert payload is not None
assert payload["codes"]["audio"] == []
assert payload["meta"]["finished"].item() is True
assert payload.codes.audio.tolist() == []
assert payload.meta.finished.item() is True


def test_talker2code2wav_async_chunk_does_not_reemit_without_new_tokens():
Expand All @@ -134,8 +135,8 @@ def test_talker2code2wav_async_chunk_does_not_reemit_without_new_tokens():
)

assert payload1 is not None
assert payload1["codes"]["audio"] == [1, 2]
assert payload1["token_offset"] == 0
assert payload1.codes.audio.tolist() == [1, 2]
assert payload1.meta.left_context_size == 0
assert payload2 is None


Expand Down Expand Up @@ -164,9 +165,9 @@ def test_talker2code2wav_async_chunk_waits_for_prelookahead_and_emits_cumulative

assert payload_pending is None
assert payload_ready is not None
assert payload_ready["codes"]["audio"] == [1, 2, 3]
assert payload_ready["token_offset"] == 0
assert payload_ready["meta"]["finished"].item() is False
assert payload_ready.codes.audio.tolist() == [1, 2, 3]
assert payload_ready.meta.left_context_size == 0
assert payload_ready.meta.finished.item() is False


def test_talker2code2wav_async_chunk_final_flush_uses_previous_token_offset():
Expand All @@ -193,13 +194,13 @@ def test_talker2code2wav_async_chunk_final_flush_uses_previous_token_offset():
)

assert payload_stream is not None
assert payload_stream["meta"]["finished"].item() is False
assert payload_stream["codes"]["audio"] == [3, 4, 5]
assert payload_stream["token_offset"] == 0
assert payload_stream.meta.finished.item() is False
assert payload_stream.codes.audio.tolist() == [3, 4, 5]
assert payload_stream.meta.left_context_size == 0
assert payload_final is not None
assert payload_final["meta"]["finished"].item() is True
assert payload_final["codes"]["audio"] == [3, 4, 5, 6]
assert payload_final["token_offset"] == 2
assert payload_final.meta.finished.item() is True
assert payload_final.codes.audio.tolist() == [3, 4, 5, 6]
assert payload_final.meta.left_context_size == 2


def test_talker2code2wav_async_chunk_respects_prompt_token_pad_on_first_chunk():
Expand All @@ -208,7 +209,7 @@ def test_talker2code2wav_async_chunk_respects_prompt_token_pad_on_first_chunk():
external_req_id="rid-pad",
output_token_ids=[8, 9, 10],
additional_information={
"speech_token": [torch.tensor([[1, 2, 3]])],
"embed": {"speech_token": [torch.tensor([[1, 2, 3]])]},
},
is_finished=lambda: False,
)
Expand All @@ -229,8 +230,8 @@ def test_talker2code2wav_async_chunk_respects_prompt_token_pad_on_first_chunk():

assert payload_pending is None
assert payload_ready is not None
assert payload_ready["codes"]["audio"] == [8, 9, 10, 11]
assert payload_ready["token_offset"] == 0
assert payload_ready.codes.audio.tolist() == [8, 9, 10, 11]
assert payload_ready.meta.left_context_size == 0


def test_talker2code2wav_async_chunk_emits_terminal_eof_without_duplicate_audio():
Expand All @@ -256,8 +257,8 @@ def test_talker2code2wav_async_chunk_emits_terminal_eof_without_duplicate_audio(
)

assert payload_stream is not None
assert payload_stream["meta"]["finished"].item() is False
assert payload_stream["codes"]["audio"] == [3, 4]
assert payload_stream.meta.finished.item() is False
assert payload_stream.codes.audio.tolist() == [3, 4]
assert payload_final is not None
assert payload_final["meta"]["finished"].item() is True
assert payload_final["codes"]["audio"] == []
assert payload_final.meta.finished.item() is True
assert payload_final.codes.audio.tolist() == []
Loading
Loading