diff --git a/decart/models.py b/decart/models.py index f8a6563..93f8932 100644 --- a/decart/models.py +++ b/decart/models.py @@ -8,7 +8,6 @@ RealTimeModels = Literal[ # Canonical names "lucy", - "lucy-2", "lucy-2.1", "lucy-2.1-vton", "lucy-restyle", @@ -22,13 +21,11 @@ "mirage", "mirage_v2", "lucy_v2v_720p_rt", - "lucy_2_rt", "live_avatar", ] VideoModels = Literal[ # Canonical names "lucy-clip", - "lucy-2", "lucy-2.1", "lucy-2.1-vton", "lucy-restyle-2", @@ -42,7 +39,6 @@ # Deprecated names "lucy-pro-v2v", "lucy-restyle-v2v", - "lucy-2-v2v", ] ImageModels = Literal[ # Canonical names @@ -59,12 +55,10 @@ "mirage": "lucy-restyle", "mirage_v2": "lucy-restyle-2", "lucy_v2v_720p_rt": "lucy", - "lucy_2_rt": "lucy-2", "live_avatar": "live-avatar", # Video aliases "lucy-pro-v2v": "lucy-clip", "lucy-restyle-v2v": "lucy-restyle-2", - "lucy-2-v2v": "lucy-2", # Image aliases "lucy-pro-i2i": "lucy-image-2", } @@ -163,7 +157,7 @@ def validate_prompt_or_reference_image(self) -> "VideoRestyleInput": class VideoEdit2Input(DecartBaseModel): - """Input for lucy-2-v2v model. + """Input for Lucy 2.1 video editing models. Prompt is required but can be an empty string. Optional reference_image can also be provided. @@ -201,14 +195,6 @@ class ImageToImageInput(DecartBaseModel): height=704, input_schema=BaseModel, ), - "lucy-2": ModelDefinition( - name="lucy-2", - url_path="/v1/stream", - fps=20, - width=1280, - height=720, - input_schema=BaseModel, - ), "lucy-2.1": ModelDefinition( name="lucy-2.1", url_path="/v1/stream", @@ -299,14 +285,6 @@ class ImageToImageInput(DecartBaseModel): height=704, input_schema=BaseModel, ), - "lucy_2_rt": ModelDefinition( - name="lucy_2_rt", - url_path="/v1/stream", - fps=20, - width=1280, - height=720, - input_schema=BaseModel, - ), "live_avatar": ModelDefinition( name="live_avatar", url_path="/v1/stream", @@ -326,14 +304,6 @@ class ImageToImageInput(DecartBaseModel): height=704, input_schema=VideoToVideoInput, ), - "lucy-2": ModelDefinition( - name="lucy-2", - url_path="/v1/jobs/lucy-2", - fps=20, - width=1280, - height=720, - input_schema=VideoEdit2Input, - ), "lucy-2.1": ModelDefinition( name="lucy-2.1", url_path="/v1/jobs/lucy-2.1", @@ -424,14 +394,6 @@ class ImageToImageInput(DecartBaseModel): height=704, input_schema=VideoRestyleInput, ), - "lucy-2-v2v": ModelDefinition( - name="lucy-2-v2v", - url_path="/v1/jobs/lucy-2-v2v", - fps=20, - width=1280, - height=720, - input_schema=VideoEdit2Input, - ), }, "image": { # Canonical names @@ -483,7 +445,6 @@ def video(model: VideoModels) -> VideoModelDefinition: Available models: - "lucy-clip" - Video-to-video - - "lucy-2" - Video editing with reference image support - "lucy-2.1" - Video editing (newer, higher quality) - "lucy-restyle-2" - Video restyling with prompt or reference image - "lucy-motion" - Image-to-motion-video diff --git a/decart/tokens/client.py b/decart/tokens/client.py index 9528c25..70cbb4b 100644 --- a/decart/tokens/client.py +++ b/decart/tokens/client.py @@ -28,7 +28,7 @@ class TokensClient: # With expiry, model restrictions, and constraints: token = await client.tokens.create( expires_in=120, - allowed_models=["lucy-2"], + allowed_models=["lucy-2.1"], constraints={"realtime": {"maxSessionDuration": 300}}, ) ``` @@ -70,7 +70,7 @@ async def create( token = await client.tokens.create( metadata={"role": "viewer"}, expires_in=120, - allowed_models=["lucy-2"], + allowed_models=["lucy-2.1"], constraints={"realtime": {"maxSessionDuration": 300}}, ) ``` diff --git a/examples/realtime_synthetic.py b/examples/realtime_synthetic.py index ec93574..589c550 100644 --- a/examples/realtime_synthetic.py +++ b/examples/realtime_synthetic.py @@ -73,7 +73,7 @@ async def main(): print("Creating synthetic video track...") video_track = SyntheticVideoTrack() - model = models.realtime("lucy-2") + model = models.realtime("lucy-2.1") print(f"Using model: {model.name}") print(f"Model config - FPS: {model.fps}, Size: {model.width}x{model.height}") diff --git a/playground/playground.py b/playground/playground.py index 1211d67..8eebdf3 100644 --- a/playground/playground.py +++ b/playground/playground.py @@ -93,14 +93,13 @@ def _check_deps() -> None: REALTIME_MODELS = [ "lucy", - "lucy-2", "lucy-2.1", "lucy-2.1-vton", "lucy-restyle", "lucy-restyle-2", "live-avatar", ] -CAMERA_MODELS = {"lucy", "lucy-2", "lucy-2.1", "lucy-2.1-vton", "lucy-restyle", "lucy-restyle-2"} +CAMERA_MODELS = {"lucy", "lucy-2.1", "lucy-2.1-vton", "lucy-restyle", "lucy-restyle-2"} AVATAR_MODELS = {"live-avatar"} BANNER = """ @@ -188,7 +187,7 @@ def parse_args() -> argparse.Namespace: %(prog)s --model lucy-restyle-2 --prompt "Anime style" %(prog)s --model live-avatar --image avatar.png %(prog)s --model live-avatar --image avatar.png --audio speech.mp3 - %(prog)s --model lucy-2 --image ref.png --prompt "Lego World" + %(prog)s --model lucy-2.1 --image ref.png --prompt "Lego World" """, ) p.add_argument("--model", "-m", choices=REALTIME_MODELS, help="Model name") @@ -209,7 +208,7 @@ def select_model_interactive() -> str: note = "" if name in AVATAR_MODELS: note = " (requires --image)" - elif name in ("lucy-2", "lucy-2.1", "lucy-2.1-vton", "lucy-restyle-2"): + elif name in ("lucy-2.1", "lucy-2.1-vton", "lucy-restyle-2"): note = " (supports reference image)" print(f" {i}. {name}{note}") diff --git a/tests/test_models.py b/tests/test_models.py index 0d3ec66..dc040cf 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -24,12 +24,6 @@ def test_canonical_realtime_models() -> None: assert model.width == 1280 assert model.height == 704 - model = models.realtime("lucy-2") - assert model.name == "lucy-2" - assert model.fps == 20 - assert model.width == 1280 - assert model.height == 720 - model = models.realtime("lucy-2.1") assert model.name == "lucy-2.1" assert model.fps == 20 @@ -84,13 +78,6 @@ def test_canonical_video_models() -> None: assert model.name == "lucy-clip" assert model.url_path == "/v1/jobs/lucy-clip" - model = models.video("lucy-2") - assert model.name == "lucy-2" - assert model.url_path == "/v1/jobs/lucy-2" - assert model.fps == 20 - assert model.width == 1280 - assert model.height == 720 - model = models.video("lucy-2.1") assert model.name == "lucy-2.1" assert model.url_path == "/v1/jobs/lucy-2.1" @@ -133,15 +120,6 @@ def test_deprecated_video_models() -> None: assert len(w) == 1 assert "lucy-restyle-2" in str(w[0].message) - _warned_aliases.clear() - - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - model = models.video("lucy-2-v2v") - assert model.name == "lucy-2-v2v" - assert len(w) == 1 - assert '"lucy-2"' in str(w[0].message) - def test_canonical_image_models() -> None: model = models.image("lucy-image-2") diff --git a/tests/test_queue.py b/tests/test_queue.py index 54e87b7..73280eb 100644 --- a/tests/test_queue.py +++ b/tests/test_queue.py @@ -269,19 +269,19 @@ async def test_queue_includes_user_agent_header() -> None: assert headers["User-Agent"].startswith("decart-python-sdk/") -# Tests for lucy-2 +# Tests for lucy-2.1 @pytest.mark.asyncio -async def test_queue_lucy2_v2v_with_prompt() -> None: +async def test_queue_lucy21_v2v_with_prompt() -> None: client = DecartClient(api_key="test-key") with patch("decart.queue.client.submit_job") as mock_submit: - mock_submit.return_value = MagicMock(job_id="job-lucy2", status="pending") + mock_submit.return_value = MagicMock(job_id="job-lucy21", status="pending") job = await client.queue.submit( { - "model": models.video("lucy-2"), + "model": models.video("lucy-2.1"), "prompt": "Restyle the scene with softer contrast and warmer highlights", "data": b"fake video data", "enhance_prompt": True, @@ -289,42 +289,42 @@ async def test_queue_lucy2_v2v_with_prompt() -> None: } ) - assert job.job_id == "job-lucy2" + assert job.job_id == "job-lucy21" assert job.status == "pending" mock_submit.assert_called_once() @pytest.mark.asyncio -async def test_queue_lucy2_v2v_with_empty_prompt_and_reference_image() -> None: +async def test_queue_lucy21_v2v_with_empty_prompt_and_reference_image() -> None: client = DecartClient(api_key="test-key") with patch("decart.queue.client.submit_job") as mock_submit: - mock_submit.return_value = MagicMock(job_id="job-lucy2-ref", status="pending") + mock_submit.return_value = MagicMock(job_id="job-lucy21-ref", status="pending") job = await client.queue.submit( { - "model": models.video("lucy-2"), + "model": models.video("lucy-2.1"), "prompt": "", "reference_image": b"fake image data", "data": b"fake video data", } ) - assert job.job_id == "job-lucy2-ref" + assert job.job_id == "job-lucy21-ref" assert job.status == "pending" mock_submit.assert_called_once() @pytest.mark.asyncio -async def test_queue_lucy2_v2v_with_both_prompt_and_reference_image() -> None: +async def test_queue_lucy21_v2v_with_both_prompt_and_reference_image() -> None: client = DecartClient(api_key="test-key") with patch("decart.queue.client.submit_job") as mock_submit: - mock_submit.return_value = MagicMock(job_id="job-lucy2-both", status="pending") + mock_submit.return_value = MagicMock(job_id="job-lucy21-both", status="pending") job = await client.queue.submit( { - "model": models.video("lucy-2"), + "model": models.video("lucy-2.1"), "prompt": "Transform the scene", "reference_image": b"fake image data", "data": b"fake video data", @@ -332,7 +332,7 @@ async def test_queue_lucy2_v2v_with_both_prompt_and_reference_image() -> None: } ) - assert job.job_id == "job-lucy2-both" + assert job.job_id == "job-lucy21-both" assert job.status == "pending" mock_submit.assert_called_once() diff --git a/tests/test_realtime_unit.py b/tests/test_realtime_unit.py index d13e82d..49dc054 100644 --- a/tests/test_realtime_unit.py +++ b/tests/test_realtime_unit.py @@ -46,11 +46,11 @@ def test_realtime_models_available(): assert model2.height == 704 assert model2.url_path == "/v1/stream" - model2 = models.realtime("lucy-2") - assert model2.name == "lucy-2" + model2 = models.realtime("lucy-2.1") + assert model2.name == "lucy-2.1" assert model2.fps == 20 - assert model2.width == 1280 - assert model2.height == 720 + assert model2.width == 1088 + assert model2.height == 624 assert model2.url_path == "/v1/stream" diff --git a/tests/test_tokens.py b/tests/test_tokens.py index fb8ecf5..884661e 100644 --- a/tests/test_tokens.py +++ b/tests/test_tokens.py @@ -158,10 +158,10 @@ async def test_create_token_with_allowed_models() -> None: ) with patch.object(client, "_get_session", AsyncMock(return_value=mock_session)): - await client.tokens.create(allowed_models=["lucy-2"]) + await client.tokens.create(allowed_models=["lucy-2.1"]) call_kwargs = mock_session.post.call_args - assert call_kwargs.kwargs["json"] == {"allowedModels": ["lucy-2"]} + assert call_kwargs.kwargs["json"] == {"allowedModels": ["lucy-2.1"]} @pytest.mark.asyncio @@ -199,7 +199,7 @@ async def test_create_token_with_all_v2_fields() -> None: return_value={ "apiKey": "ek_test123", "expiresAt": "2024-12-15T12:10:00Z", - "permissions": {"models": ["lucy-2"]}, + "permissions": {"models": ["lucy-2.1"]}, "constraints": {"realtime": {"maxSessionDuration": 120}}, } ) @@ -213,19 +213,19 @@ async def test_create_token_with_all_v2_fields() -> None: result = await client.tokens.create( metadata={"role": "viewer"}, expires_in=120, - allowed_models=["lucy-2"], + allowed_models=["lucy-2.1"], constraints={"realtime": {"maxSessionDuration": 120}}, ) assert result.api_key == "ek_test123" assert result.expires_at == "2024-12-15T12:10:00Z" - assert result.permissions == {"models": ["lucy-2"]} + assert result.permissions == {"models": ["lucy-2.1"]} assert result.constraints == {"realtime": {"maxSessionDuration": 120}} call_kwargs = mock_session.post.call_args assert call_kwargs.kwargs["json"] == { "metadata": {"role": "viewer"}, "expiresIn": 120, - "allowedModels": ["lucy-2"], + "allowedModels": ["lucy-2.1"], "constraints": {"realtime": {"maxSessionDuration": 120}}, }