kiapi 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kiapi/__init__.py +3 -0
- kiapi/__main__.py +4 -0
- kiapi/api/__init__.py +26 -0
- kiapi/api/_constants/require_auth.py +14 -0
- kiapi/api/_helpers/build_job_responses.py +73 -0
- kiapi/api/_helpers/build_openapi.py +55 -0
- kiapi/api/_helpers/build_train_responses.py +21 -0
- kiapi/api/_helpers/get_accept.py +20 -0
- kiapi/api/_helpers/get_ctx.py +7 -0
- kiapi/api/_helpers/get_worker.py +7 -0
- kiapi/api/_helpers/register_capability_endpoints.py +70 -0
- kiapi/api/_helpers/submit_and_maybe_wait.py +113 -0
- kiapi/api/_settings.py +50 -0
- kiapi/api/_views/async_job_response.py +21 -0
- kiapi/api/_views/capability_model_spec.py +49 -0
- kiapi/api/app.py +150 -0
- kiapi/api/audio/acestep/_views/extract_response.py +57 -0
- kiapi/api/audio/acestep/_views/track_response.py +57 -0
- kiapi/api/audio/acestep/router.py +190 -0
- kiapi/api/audio/audiogen/_views/audio_response.py +46 -0
- kiapi/api/audio/audiogen/router.py +77 -0
- kiapi/api/chat/_views/chat_completion_response.py +71 -0
- kiapi/api/chat/router.py +253 -0
- kiapi/api/embedding/_views/embedding_response.py +35 -0
- kiapi/api/embedding/router.py +82 -0
- kiapi/api/files/_operations/get_file.py +14 -0
- kiapi/api/files/_operations/get_file_id.py +18 -0
- kiapi/api/files/_views/file_delete_response.py +14 -0
- kiapi/api/files/_views/file_list_response.py +15 -0
- kiapi/api/files/router.py +105 -0
- kiapi/api/health/_views/health_response.py +26 -0
- kiapi/api/health/router.py +28 -0
- kiapi/api/image/depthpro/_views/estimate_response.py +70 -0
- kiapi/api/image/depthpro/router.py +81 -0
- kiapi/api/image/ernie/_views/image_response.py +50 -0
- kiapi/api/image/ernie/router.py +181 -0
- kiapi/api/image/flux2/_views/image_response.py +53 -0
- kiapi/api/image/flux2/router.py +197 -0
- kiapi/api/image/ideogram4/_views/image_response.py +55 -0
- kiapi/api/image/ideogram4/router.py +87 -0
- kiapi/api/image/qwen/_views/image_response.py +47 -0
- kiapi/api/image/qwen/router.py +141 -0
- kiapi/api/image/seedvr2/_views/image_response.py +50 -0
- kiapi/api/image/seedvr2/router.py +83 -0
- kiapi/api/image/zimage/_views/image_response.py +49 -0
- kiapi/api/image/zimage/router.py +131 -0
- kiapi/api/jobs/_operations/get_job_id.py +18 -0
- kiapi/api/jobs/_views/job_delete_response.py +19 -0
- kiapi/api/jobs/_views/job_list_response.py +15 -0
- kiapi/api/jobs/router.py +62 -0
- kiapi/api/models/_schemas/openai_model_spec.py +26 -0
- kiapi/api/models/_views/model_list_response.py +15 -0
- kiapi/api/models/router.py +29 -0
- kiapi/api/video/ltx2/_views/__init__.py +1 -0
- kiapi/api/video/ltx2/_views/video_response.py +59 -0
- kiapi/api/video/ltx2/router.py +89 -0
- kiapi/api/web/_views/__init__.py +7 -0
- kiapi/api/web/_views/fetch_api_request.py +26 -0
- kiapi/api/web/_views/fetch_error_response.py +25 -0
- kiapi/api/web/router.py +302 -0
- kiapi/capabilities/__init__.py +24 -0
- kiapi/capabilities/_exceptions/CapabilityError.py +2 -0
- kiapi/capabilities/_exceptions/ValidationError.py +2 -0
- kiapi/capabilities/_helpers/attach_mflux_progress.py +50 -0
- kiapi/capabilities/_helpers/get_file_path.py +20 -0
- kiapi/capabilities/_helpers/resolve_file_ref.py +16 -0
- kiapi/capabilities/acestep/README.ja.md +174 -0
- kiapi/capabilities/acestep/README.md +167 -0
- kiapi/capabilities/acestep/__init__.py +37 -0
- kiapi/capabilities/acestep/_constants/description.py +122 -0
- kiapi/capabilities/acestep/_exceptions/ace_step_engine_error.py +2 -0
- kiapi/capabilities/acestep/_helpers/register.py +96 -0
- kiapi/capabilities/acestep/_models/acestep.py +105 -0
- kiapi/capabilities/acestep/_operations/handle_cover.py +23 -0
- kiapi/capabilities/acestep/_operations/handle_extract.py +38 -0
- kiapi/capabilities/acestep/_operations/handle_generate.py +18 -0
- kiapi/capabilities/acestep/_operations/handle_repaint.py +25 -0
- kiapi/capabilities/acestep/_operations/resolve_ace_step_paths.py +30 -0
- kiapi/capabilities/acestep/_operations/resolve_cover_params.py +21 -0
- kiapi/capabilities/acestep/_operations/resolve_engine.py +10 -0
- kiapi/capabilities/acestep/_operations/resolve_extract_params.py +24 -0
- kiapi/capabilities/acestep/_operations/resolve_generate_params.py +18 -0
- kiapi/capabilities/acestep/_operations/resolve_repaint_params.py +22 -0
- kiapi/capabilities/acestep/_schemas/ace_step_paths.py +29 -0
- kiapi/capabilities/acestep/_services/ace_step_engine.py +143 -0
- kiapi/capabilities/acestep/_settings.py +82 -0
- kiapi/capabilities/acestep/_views/ace_step_base.py +61 -0
- kiapi/capabilities/acestep/_views/cover_params.py +26 -0
- kiapi/capabilities/acestep/_views/cover_request.py +49 -0
- kiapi/capabilities/acestep/_views/extract_params.py +24 -0
- kiapi/capabilities/acestep/_views/extract_request.py +33 -0
- kiapi/capabilities/acestep/_views/generate_params.py +25 -0
- kiapi/capabilities/acestep/_views/generate_request.py +54 -0
- kiapi/capabilities/acestep/_views/repaint_params.py +27 -0
- kiapi/capabilities/acestep/_views/repaint_request.py +51 -0
- kiapi/capabilities/acestep/_views/track_params.py +7 -0
- kiapi/capabilities/acestep/worker_subprocess.py +247 -0
- kiapi/capabilities/audiogen/README.ja.md +49 -0
- kiapi/capabilities/audiogen/README.md +48 -0
- kiapi/capabilities/audiogen/__init__.py +25 -0
- kiapi/capabilities/audiogen/_constants/description.py +60 -0
- kiapi/capabilities/audiogen/_helpers/attach_audiogen_progress.py +27 -0
- kiapi/capabilities/audiogen/_helpers/register.py +42 -0
- kiapi/capabilities/audiogen/_helpers/validate_generate.py +14 -0
- kiapi/capabilities/audiogen/_models/audiogen.py +98 -0
- kiapi/capabilities/audiogen/_operations/handle_generate.py +27 -0
- kiapi/capabilities/audiogen/_operations/resolve_generate_params.py +25 -0
- kiapi/capabilities/audiogen/_settings.py +34 -0
- kiapi/capabilities/audiogen/_views/generate_params.py +14 -0
- kiapi/capabilities/audiogen/_views/generate_request.py +96 -0
- kiapi/capabilities/chat/README.ja.md +822 -0
- kiapi/capabilities/chat/README.md +806 -0
- kiapi/capabilities/chat/__init__.py +25 -0
- kiapi/capabilities/chat/_constants/description.py +163 -0
- kiapi/capabilities/chat/_helpers/register.py +67 -0
- kiapi/capabilities/chat/_models/qwen3_5.py +183 -0
- kiapi/capabilities/chat/_models/qwen3_omni.py +242 -0
- kiapi/capabilities/chat/_operations/apply_template.py +74 -0
- kiapi/capabilities/chat/_operations/completed_hermes_tool_call_text.py +9 -0
- kiapi/capabilities/chat/_operations/emit_streaming_response.py +297 -0
- kiapi/capabilities/chat/_operations/ensure_streaming_detokenizer_compat.py +49 -0
- kiapi/capabilities/chat/_operations/format_response.py +72 -0
- kiapi/capabilities/chat/_operations/handle_chat.py +25 -0
- kiapi/capabilities/chat/_operations/parse_hermes_tool_calls.py +63 -0
- kiapi/capabilities/chat/_operations/parse_json_tool_calls.py +66 -0
- kiapi/capabilities/chat/_operations/parse_messages.py +326 -0
- kiapi/capabilities/chat/_operations/resolve_chat_params.py +50 -0
- kiapi/capabilities/chat/_operations/stream_text_from_tokens.py +32 -0
- kiapi/capabilities/chat/_operations/strip_tool_calls.py +15 -0
- kiapi/capabilities/chat/_settings.py +74 -0
- kiapi/capabilities/chat/_utils/apply_parallel_tool_call_policy.py +17 -0
- kiapi/capabilities/chat/_utils/apply_seed.py +8 -0
- kiapi/capabilities/chat/_utils/load_audio_mono.py +31 -0
- kiapi/capabilities/chat/_utils/load_mlx_vlm.py +12 -0
- kiapi/capabilities/chat/_utils/warmup_params.py +26 -0
- kiapi/capabilities/chat/_views/chat_params.py +34 -0
- kiapi/capabilities/chat/_views/chat_request.py +153 -0
- kiapi/capabilities/depthpro/README.ja.md +131 -0
- kiapi/capabilities/depthpro/README.md +124 -0
- kiapi/capabilities/depthpro/__init__.py +23 -0
- kiapi/capabilities/depthpro/_constants/description.py +39 -0
- kiapi/capabilities/depthpro/_helpers/register.py +46 -0
- kiapi/capabilities/depthpro/_helpers/validate_estimate.py +32 -0
- kiapi/capabilities/depthpro/_models/depthpro.py +144 -0
- kiapi/capabilities/depthpro/_operations/handle_estimate.py +50 -0
- kiapi/capabilities/depthpro/_operations/is_quantize_override.py +12 -0
- kiapi/capabilities/depthpro/_operations/resolve_estimate_params.py +24 -0
- kiapi/capabilities/depthpro/_settings.py +46 -0
- kiapi/capabilities/depthpro/_views/estimate_params.py +21 -0
- kiapi/capabilities/depthpro/_views/estimate_request.py +63 -0
- kiapi/capabilities/embedding/README.ja.md +137 -0
- kiapi/capabilities/embedding/README.md +128 -0
- kiapi/capabilities/embedding/__init__.py +24 -0
- kiapi/capabilities/embedding/_constants/description.py +47 -0
- kiapi/capabilities/embedding/_helpers/register.py +66 -0
- kiapi/capabilities/embedding/_models/qwen3_text.py +53 -0
- kiapi/capabilities/embedding/_models/qwen3_vl.py +97 -0
- kiapi/capabilities/embedding/_operations/format_response.py +24 -0
- kiapi/capabilities/embedding/_operations/handle_embed.py +24 -0
- kiapi/capabilities/embedding/_operations/parse_inputs.py +108 -0
- kiapi/capabilities/embedding/_operations/resolve_embed_params.py +18 -0
- kiapi/capabilities/embedding/_settings.py +27 -0
- kiapi/capabilities/embedding/_utils/to_vector.py +20 -0
- kiapi/capabilities/embedding/_views/embed_params.py +17 -0
- kiapi/capabilities/embedding/_views/embed_request.py +39 -0
- kiapi/capabilities/ernie/README.ja.md +242 -0
- kiapi/capabilities/ernie/README.md +223 -0
- kiapi/capabilities/ernie/__init__.py +34 -0
- kiapi/capabilities/ernie/_constants/description.py +71 -0
- kiapi/capabilities/ernie/_helpers/register.py +60 -0
- kiapi/capabilities/ernie/_helpers/validate_edit.py +19 -0
- kiapi/capabilities/ernie/_helpers/validate_generate.py +8 -0
- kiapi/capabilities/ernie/_models/ernie.py +356 -0
- kiapi/capabilities/ernie/_operations/handle_edit.py +39 -0
- kiapi/capabilities/ernie/_operations/handle_generate.py +38 -0
- kiapi/capabilities/ernie/_operations/handle_train.py +77 -0
- kiapi/capabilities/ernie/_operations/is_quantize_override.py +16 -0
- kiapi/capabilities/ernie/_operations/resolve_edit_params.py +44 -0
- kiapi/capabilities/ernie/_operations/resolve_generate_params.py +40 -0
- kiapi/capabilities/ernie/_operations/resolve_lora_params.py +23 -0
- kiapi/capabilities/ernie/_operations/resolve_train_params.py +43 -0
- kiapi/capabilities/ernie/_operations/validate_common.py +33 -0
- kiapi/capabilities/ernie/_schemas/lora_ref.py +27 -0
- kiapi/capabilities/ernie/_settings.py +151 -0
- kiapi/capabilities/ernie/_views/edit_params.py +36 -0
- kiapi/capabilities/ernie/_views/edit_request.py +142 -0
- kiapi/capabilities/ernie/_views/generate_params.py +32 -0
- kiapi/capabilities/ernie/_views/generate_request.py +127 -0
- kiapi/capabilities/ernie/_views/train_params.py +28 -0
- kiapi/capabilities/ernie/_views/train_request.py +96 -0
- kiapi/capabilities/flux2/README.ja.md +260 -0
- kiapi/capabilities/flux2/README.md +241 -0
- kiapi/capabilities/flux2/__init__.py +36 -0
- kiapi/capabilities/flux2/_constants/description.py +81 -0
- kiapi/capabilities/flux2/_helpers/register.py +98 -0
- kiapi/capabilities/flux2/_helpers/validate_edit.py +12 -0
- kiapi/capabilities/flux2/_helpers/validate_generate.py +8 -0
- kiapi/capabilities/flux2/_models/flux2.py +396 -0
- kiapi/capabilities/flux2/_operations/handle_edit.py +44 -0
- kiapi/capabilities/flux2/_operations/handle_generate.py +46 -0
- kiapi/capabilities/flux2/_operations/handle_train.py +105 -0
- kiapi/capabilities/flux2/_operations/is_quantize_override.py +16 -0
- kiapi/capabilities/flux2/_operations/resolve_edit_params.py +43 -0
- kiapi/capabilities/flux2/_operations/resolve_generate_params.py +44 -0
- kiapi/capabilities/flux2/_operations/resolve_lora_params.py +23 -0
- kiapi/capabilities/flux2/_operations/resolve_train_params.py +42 -0
- kiapi/capabilities/flux2/_operations/role_spec.py +13 -0
- kiapi/capabilities/flux2/_operations/split_repo.py +11 -0
- kiapi/capabilities/flux2/_operations/validate_common.py +35 -0
- kiapi/capabilities/flux2/_schemas/lora_ref.py +27 -0
- kiapi/capabilities/flux2/_settings.py +181 -0
- kiapi/capabilities/flux2/_views/edit_params.py +36 -0
- kiapi/capabilities/flux2/_views/edit_request.py +145 -0
- kiapi/capabilities/flux2/_views/generate_params.py +36 -0
- kiapi/capabilities/flux2/_views/generate_request.py +150 -0
- kiapi/capabilities/flux2/_views/train_params.py +32 -0
- kiapi/capabilities/flux2/_views/train_request.py +102 -0
- kiapi/capabilities/ideogram4/README.ja.md +230 -0
- kiapi/capabilities/ideogram4/README.md +219 -0
- kiapi/capabilities/ideogram4/__init__.py +24 -0
- kiapi/capabilities/ideogram4/_constants/description.py +65 -0
- kiapi/capabilities/ideogram4/_helpers/register.py +44 -0
- kiapi/capabilities/ideogram4/_helpers/validate_generate.py +31 -0
- kiapi/capabilities/ideogram4/_models/ideogram4.py +120 -0
- kiapi/capabilities/ideogram4/_operations/handle_generate.py +30 -0
- kiapi/capabilities/ideogram4/_operations/is_quantize_override.py +12 -0
- kiapi/capabilities/ideogram4/_operations/resolve_generate_params.py +30 -0
- kiapi/capabilities/ideogram4/_settings.py +89 -0
- kiapi/capabilities/ideogram4/_views/generate_params.py +27 -0
- kiapi/capabilities/ideogram4/_views/generate_request.py +118 -0
- kiapi/capabilities/ltx2/README.ja.md +287 -0
- kiapi/capabilities/ltx2/README.md +274 -0
- kiapi/capabilities/ltx2/__init__.py +26 -0
- kiapi/capabilities/ltx2/_constants/description.py +81 -0
- kiapi/capabilities/ltx2/_helpers/register.py +58 -0
- kiapi/capabilities/ltx2/_helpers/validate_generate.py +42 -0
- kiapi/capabilities/ltx2/_models/ltx2.py +106 -0
- kiapi/capabilities/ltx2/_operations/detect_mode.py +19 -0
- kiapi/capabilities/ltx2/_operations/handle_generate.py +52 -0
- kiapi/capabilities/ltx2/_operations/resolve_generate_params.py +31 -0
- kiapi/capabilities/ltx2/_settings.py +93 -0
- kiapi/capabilities/ltx2/_views/generate_params.py +34 -0
- kiapi/capabilities/ltx2/_views/generate_request.py +151 -0
- kiapi/capabilities/qwen/README.ja.md +251 -0
- kiapi/capabilities/qwen/README.md +235 -0
- kiapi/capabilities/qwen/__init__.py +30 -0
- kiapi/capabilities/qwen/_constants/description.py +53 -0
- kiapi/capabilities/qwen/_helpers/register.py +60 -0
- kiapi/capabilities/qwen/_helpers/validate_edit.py +12 -0
- kiapi/capabilities/qwen/_helpers/validate_generate.py +12 -0
- kiapi/capabilities/qwen/_models/qwen.py +224 -0
- kiapi/capabilities/qwen/_operations/handle_edit.py +44 -0
- kiapi/capabilities/qwen/_operations/handle_generate.py +46 -0
- kiapi/capabilities/qwen/_operations/is_quantize_override.py +15 -0
- kiapi/capabilities/qwen/_operations/resolve_edit_params.py +35 -0
- kiapi/capabilities/qwen/_operations/resolve_generate_params.py +39 -0
- kiapi/capabilities/qwen/_operations/resolve_lora_params.py +23 -0
- kiapi/capabilities/qwen/_operations/validate_common.py +32 -0
- kiapi/capabilities/qwen/_schemas/lora_ref.py +27 -0
- kiapi/capabilities/qwen/_settings.py +107 -0
- kiapi/capabilities/qwen/_views/edit_params.py +36 -0
- kiapi/capabilities/qwen/_views/edit_request.py +138 -0
- kiapi/capabilities/qwen/_views/generate_params.py +37 -0
- kiapi/capabilities/qwen/_views/generate_request.py +149 -0
- kiapi/capabilities/seedvr2/README.ja.md +234 -0
- kiapi/capabilities/seedvr2/README.md +219 -0
- kiapi/capabilities/seedvr2/__init__.py +24 -0
- kiapi/capabilities/seedvr2/_constants/description.py +46 -0
- kiapi/capabilities/seedvr2/_helpers/register.py +60 -0
- kiapi/capabilities/seedvr2/_helpers/validate_upscale.py +52 -0
- kiapi/capabilities/seedvr2/_models/seedvr2.py +140 -0
- kiapi/capabilities/seedvr2/_operations/handle_upscale.py +42 -0
- kiapi/capabilities/seedvr2/_operations/is_quantize_override.py +12 -0
- kiapi/capabilities/seedvr2/_operations/resolve_upscale_params.py +30 -0
- kiapi/capabilities/seedvr2/_settings.py +74 -0
- kiapi/capabilities/seedvr2/_views/upscale_params.py +27 -0
- kiapi/capabilities/seedvr2/_views/upscale_request.py +94 -0
- kiapi/capabilities/web/README.ja.md +187 -0
- kiapi/capabilities/web/README.md +171 -0
- kiapi/capabilities/web/__init__.py +30 -0
- kiapi/capabilities/web/_constants/description.py +38 -0
- kiapi/capabilities/web/_exceptions/FetchError.py +24 -0
- kiapi/capabilities/web/_exceptions/SearchBackendError.py +11 -0
- kiapi/capabilities/web/_helpers/register.py +59 -0
- kiapi/capabilities/web/_models/crawl4ai.py +32 -0
- kiapi/capabilities/web/_models/searxng.py +44 -0
- kiapi/capabilities/web/_operations/handle_fetch.py +145 -0
- kiapi/capabilities/web/_operations/handle_search.py +56 -0
- kiapi/capabilities/web/_operations/resolve_fetch_params.py +19 -0
- kiapi/capabilities/web/_operations/resolve_search_params.py +34 -0
- kiapi/capabilities/web/_operations/resolve_searxng_config_dir.py +21 -0
- kiapi/capabilities/web/_services/__init__.py +1 -0
- kiapi/capabilities/web/_services/web_backend_process.py +144 -0
- kiapi/capabilities/web/_settings.py +138 -0
- kiapi/capabilities/web/_views/fetch_params.py +27 -0
- kiapi/capabilities/web/_views/fetch_request.py +29 -0
- kiapi/capabilities/web/_views/fetch_result.py +20 -0
- kiapi/capabilities/web/_views/search_params.py +43 -0
- kiapi/capabilities/web/_views/search_request.py +93 -0
- kiapi/capabilities/web/_views/search_response.py +49 -0
- kiapi/capabilities/web/resources/__init__.py +0 -0
- kiapi/capabilities/web/resources/searxng/__init__.py +0 -0
- kiapi/capabilities/web/resources/searxng/settings.yml +11 -0
- kiapi/capabilities/zimage/README.ja.md +249 -0
- kiapi/capabilities/zimage/README.md +231 -0
- kiapi/capabilities/zimage/__init__.py +34 -0
- kiapi/capabilities/zimage/_constants/description.py +73 -0
- kiapi/capabilities/zimage/_helpers/register.py +62 -0
- kiapi/capabilities/zimage/_helpers/validate_generate.py +37 -0
- kiapi/capabilities/zimage/_models/zimage.py +278 -0
- kiapi/capabilities/zimage/_operations/handle_generate.py +38 -0
- kiapi/capabilities/zimage/_operations/handle_train.py +78 -0
- kiapi/capabilities/zimage/_operations/is_quantize_override.py +11 -0
- kiapi/capabilities/zimage/_operations/resolve_generate_params.py +39 -0
- kiapi/capabilities/zimage/_operations/resolve_lora_params.py +23 -0
- kiapi/capabilities/zimage/_operations/resolve_train_params.py +38 -0
- kiapi/capabilities/zimage/_schemas/lora_ref.py +27 -0
- kiapi/capabilities/zimage/_settings.py +166 -0
- kiapi/capabilities/zimage/_views/generate_params.py +23 -0
- kiapi/capabilities/zimage/_views/generate_request.py +127 -0
- kiapi/capabilities/zimage/_views/train_params.py +22 -0
- kiapi/capabilities/zimage/_views/train_request.py +101 -0
- kiapi/cli/__init__.py +11 -0
- kiapi/cli/_helpers/dedupe_resources.py +12 -0
- kiapi/cli/_helpers/register_all_capabilities.py +36 -0
- kiapi/cli/_helpers/run_resources.py +24 -0
- kiapi/cli/_helpers/select_specs.py +67 -0
- kiapi/cli/activate/_operations/preflight_hf_access.py +129 -0
- kiapi/cli/activate/cli.py +37 -0
- kiapi/cli/check/_helpers/check_audio_acestep_turbo.py +22 -0
- kiapi/cli/check/_helpers/check_audio_acestep_xl_base.py +22 -0
- kiapi/cli/check/_helpers/check_audio_audiogen_medium.py +24 -0
- kiapi/cli/check/_helpers/check_chat_chat_qwen3_6_27b.py +19 -0
- kiapi/cli/check/_helpers/check_chat_chat_qwen3_omni.py +19 -0
- kiapi/cli/check/_helpers/check_embedding_embedding_qwen3_embedding_8b.py +14 -0
- kiapi/cli/check/_helpers/check_embedding_embedding_qwen3_vl_embedding_2b.py +19 -0
- kiapi/cli/check/_helpers/check_image_depthpro_base.py +21 -0
- kiapi/cli/check/_helpers/check_image_ernie_base.py +23 -0
- kiapi/cli/check/_helpers/check_image_ernie_turbo.py +23 -0
- kiapi/cli/check/_helpers/check_image_flux2_klein_9b.py +23 -0
- kiapi/cli/check/_helpers/check_image_flux2_klein_base_4b.py +23 -0
- kiapi/cli/check/_helpers/check_image_flux2_klein_base_9b.py +23 -0
- kiapi/cli/check/_helpers/check_image_ideogram4_fp8.py +23 -0
- kiapi/cli/check/_helpers/check_image_qwen_edit_2509.py +27 -0
- kiapi/cli/check/_helpers/check_image_qwen_image.py +23 -0
- kiapi/cli/check/_helpers/check_image_seedvr2_3b.py +23 -0
- kiapi/cli/check/_helpers/check_image_seedvr2_7b.py +23 -0
- kiapi/cli/check/_helpers/check_image_zimage_base.py +23 -0
- kiapi/cli/check/_helpers/check_image_zimage_turbo.py +23 -0
- kiapi/cli/check/_helpers/check_video_ltx2_distilled.py +26 -0
- kiapi/cli/check/_helpers/check_web_web_fetch.py +14 -0
- kiapi/cli/check/_helpers/check_web_web_search.py +14 -0
- kiapi/cli/check/_operations/build_check_result.py +20 -0
- kiapi/cli/check/_operations/check_context.py +10 -0
- kiapi/cli/check/_operations/create_sample_image.py +46 -0
- kiapi/cli/check/_schemas/check_result.py +12 -0
- kiapi/cli/check/cli.py +89 -0
- kiapi/cli/cli.py +29 -0
- kiapi/cli/config/cli.py +17 -0
- kiapi/cli/config/edit/cli.py +32 -0
- kiapi/cli/config/init/cli.py +33 -0
- kiapi/cli/config/show/cli.py +13 -0
- kiapi/cli/config/template/cli.py +36 -0
- kiapi/cli/deactivate/cli.py +49 -0
- kiapi/cli/run/asgi.py +16 -0
- kiapi/cli/run/cli.py +59 -0
- kiapi/cli/service/__init__.py +5 -0
- kiapi/cli/service/_services/service_manager.py +107 -0
- kiapi/cli/service/cli.py +19 -0
- kiapi/cli/service/install/cli.py +17 -0
- kiapi/cli/service/start/cli.py +22 -0
- kiapi/cli/service/status/cli.py +81 -0
- kiapi/cli/service/stop/cli.py +19 -0
- kiapi/cli/service/uninstall/cli.py +16 -0
- kiapi/cli/status/cli.py +226 -0
- kiapi/core/app/__init__.py +16 -0
- kiapi/core/app/_schemas/app_context.py +28 -0
- kiapi/core/app/_services/user_directory.py +59 -0
- kiapi/core/app/_settings.py +46 -0
- kiapi/core/capability/__init__.py +11 -0
- kiapi/core/capability/_schemas/capability_spec.py +17 -0
- kiapi/core/capability/_services/capability_spec_registry.py +21 -0
- kiapi/core/config/__init__.py +11 -0
- kiapi/core/config/_exceptions/user_config_error.py +2 -0
- kiapi/core/config/_helpers/get_user_settings_path.py +7 -0
- kiapi/core/config/_helpers/load_user_settings.py +54 -0
- kiapi/core/file/__init__.py +37 -0
- kiapi/core/file/_helpers/create_file_store.py +7 -0
- kiapi/core/file/_helpers/resolve_file_ref.py +90 -0
- kiapi/core/file/_schemas/file_data_url_ref.py +19 -0
- kiapi/core/file/_schemas/file_id_ref.py +16 -0
- kiapi/core/file/_schemas/file_record.py +46 -0
- kiapi/core/file/_schemas/file_url_ref.py +16 -0
- kiapi/core/file/_services/file_store.py +138 -0
- kiapi/core/file/_settings.py +22 -0
- kiapi/core/file/_types/file_id.py +2 -0
- kiapi/core/file/_types/file_ref.py +12 -0
- kiapi/core/file/_views/resolved_file_ref.py +16 -0
- kiapi/core/job/__init__.py +24 -0
- kiapi/core/job/_enums/job_status.py +9 -0
- kiapi/core/job/_helpers/creep_progress.py +123 -0
- kiapi/core/job/_models/job.py +121 -0
- kiapi/core/job/_services/job_store.py +33 -0
- kiapi/core/job/_services/progress_reporter.py +79 -0
- kiapi/core/job/_types/job_id.py +3 -0
- kiapi/core/job/_types/job_result.py +5 -0
- kiapi/core/job/_types/job_type.py +4 -0
- kiapi/core/logging/__init__.py +14 -0
- kiapi/core/logging/_helpers/get_log_level.py +8 -0
- kiapi/core/logging/_helpers/setup_logger.py +14 -0
- kiapi/core/logging/_settings.py +34 -0
- kiapi/core/logging/_types/log_level.py +3 -0
- kiapi/core/memory/__init__.py +21 -0
- kiapi/core/memory/_exceptions/memory_budget_error.py +2 -0
- kiapi/core/memory/_helpers/create_memory_manager.py +17 -0
- kiapi/core/memory/_operations/log_memory_limit.py +29 -0
- kiapi/core/memory/_operations/resolve_effective_memory_limit_gb.py +13 -0
- kiapi/core/memory/_operations/resolve_framework_strategy.py +42 -0
- kiapi/core/memory/_schemas/framework_strategy.py +14 -0
- kiapi/core/memory/_schemas/memory_stats.py +24 -0
- kiapi/core/memory/_schemas/resident_model.py +14 -0
- kiapi/core/memory/_schemas/resident_model_stats.py +49 -0
- kiapi/core/memory/_services/memory_manager.py +257 -0
- kiapi/core/memory/_settings.py +36 -0
- kiapi/core/memory/_types/framework_name.py +4 -0
- kiapi/core/memory/_types/resident_key.py +4 -0
- kiapi/core/model/__init__.py +36 -0
- kiapi/core/model/_exceptions/unknown_model_error.py +2 -0
- kiapi/core/model/_schemas/model_spec.py +145 -0
- kiapi/core/model/_services/model_registry.py +85 -0
- kiapi/core/model/_types/model_alias.py +2 -0
- kiapi/core/model/_types/model_domain.py +6 -0
- kiapi/core/model/_types/model_family.py +5 -0
- kiapi/core/model/_types/model_key.py +8 -0
- kiapi/core/model/_types/model_name.py +4 -0
- kiapi/core/model/_types/model_repo.py +3 -0
- kiapi/core/net/__init__.py +16 -0
- kiapi/core/net/_exceptions/unsafe_url_error.py +7 -0
- kiapi/core/net/_helpers/verify_public_url.py +68 -0
- kiapi/core/net/_settings.py +28 -0
- kiapi/core/setup/__init__.py +25 -0
- kiapi/core/setup/_exceptions/setup_required_error.py +2 -0
- kiapi/core/setup/_schemas/docker_image_resource.py +37 -0
- kiapi/core/setup/_schemas/hf_snapshot_resource.py +50 -0
- kiapi/core/setup/_schemas/local_path_resource.py +43 -0
- kiapi/core/setup/_schemas/python_package_resource.py +58 -0
- kiapi/core/setup/_schemas/python_venv_resource.py +63 -0
- kiapi/core/setup/_schemas/setup_status.py +7 -0
- kiapi/core/setup/_schemas/url_file_resource.py +43 -0
- kiapi/core/setup/_services/setup_manager.py +331 -0
- kiapi/core/setup/_types/setup_resource.py +21 -0
- kiapi/core/setup/_types/setup_target.py +11 -0
- kiapi/core/workdir/__init__.py +8 -0
- kiapi/core/workdir/_helpers/create_work_dir.py +11 -0
- kiapi/core/workdir/_settings.py +21 -0
- kiapi/core/worker/__init__.py +23 -0
- kiapi/core/worker/_helpers/create_worker.py +9 -0
- kiapi/core/worker/_services/worker.py +165 -0
- kiapi/core/worker/_settings.py +36 -0
- kiapi/core/worker/_types/job_thunk.py +6 -0
- kiapi-0.1.0.dist-info/METADATA +337 -0
- kiapi-0.1.0.dist-info/RECORD +465 -0
- kiapi-0.1.0.dist-info/WHEEL +4 -0
- kiapi-0.1.0.dist-info/entry_points.txt +2 -0
- kiapi-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# ltx2
|
|
2
|
+
|
|
3
|
+
**English** | [日本語](README.ja.md)
|
|
4
|
+
|
|
5
|
+
[mlx-video LTX-2](https://github.com/Blaizzy/mlx-video) provides short video generation functionality.
|
|
6
|
+
|
|
7
|
+
- **T2V**: Generate video from text
|
|
8
|
+
- **I2V**: animate image as first or last frame
|
|
9
|
+
- **A2V**: Drive motion and timing with voice
|
|
10
|
+
- **T2V + Audio**: Generate audio along with video
|
|
11
|
+
|
|
12
|
+
## API
|
|
13
|
+
|
|
14
|
+
| Endpoint | Name | Description |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| `POST /v1/video/ltx2/generate` | Video generation | Generate MP4 from JSON body and any `image` / `end_image` / `audio` FileRef. |
|
|
17
|
+
| `GET /v1/video/ltx2/models` | List of models | Return a list of available models. |
|
|
18
|
+
| `GET /v1/video/ltx2/openapi.json` | OpenAPI | Returns detailed input/output specifications, usage, and TIPS. |
|
|
19
|
+
|
|
20
|
+
Inferred mode:
|
|
21
|
+
|
|
22
|
+
| input | mode |
|
|
23
|
+
|---|---|
|
|
24
|
+
| No file attachment | T2V — Text to video |
|
|
25
|
+
| `image` FileRef | I2V — Animate the first frame |
|
|
26
|
+
| `image` + `end_image` FileRef | I2V — Specify first and last frame |
|
|
27
|
+
| `end_image` FileRef | I2V — Specify the last frame |
|
|
28
|
+
| `audio` FileRef | A2V — Drive motion/timing with audio |
|
|
29
|
+
| `image` + `audio` FileRef | A2V + I2V |
|
|
30
|
+
| `generate_audio: true` | T2V + Audio — also generates audio |
|
|
31
|
+
|
|
32
|
+
- `mode: "sync"` waits until completion and returns raw MP4 bytes by default for single artifacts.
|
|
33
|
+
If you want Job JSON, add `Accept: application/json`.
|
|
34
|
+
- `mode: "async"` returns `202` and `{job_id}`.
|
|
35
|
+
Check the progress with `GET /v1/jobs/{job_id}` and after completion use `result.file_id` or
|
|
36
|
+
Get MP4 with `artifacts[0]`.
|
|
37
|
+
- `audio` files and `generate_audio: true` are exclusive.
|
|
38
|
+
|
|
39
|
+
## API Docs
|
|
40
|
+
|
|
41
|
+
- [OpenAPI JSON](https://kiarina.github.io/kiapi/v1/video/ltx2/openapi.json)
|
|
42
|
+
- [Swagger UI](https://kiarina.github.io/kiapi/v1/video/ltx2/docs.html)
|
|
43
|
+
- [ReDoc](https://kiarina.github.io/kiapi/v1/video/ltx2/redoc.html)
|
|
44
|
+
|
|
45
|
+
## Dependencies
|
|
46
|
+
|
|
47
|
+
| Package | License | Description |
|
|
48
|
+
|---|---|---|
|
|
49
|
+
| [mlx-video](https://github.com/Blaizzy/mlx-video) | MIT | Run LTX-2 distilled pipeline on MLX. `pyproject.toml` pins known good git commits. |
|
|
50
|
+
|
|
51
|
+
## Models
|
|
52
|
+
|
|
53
|
+
| Model | License | Terms | Size | Description |
|
|
54
|
+
|---|---|---|---:|---|
|
|
55
|
+
| [prince-canuma/LTX-2-distilled](https://huggingface.co/prince-canuma/LTX-2-distilled) | [LTX-2 Community License Agreement](https://huggingface.co/Lightricks/LTX-2/blob/main/LICENSE) (derived from [Lightricks/LTX-2](https://huggingface.co/Lightricks/LTX-2) Compliant with repo itself (no model card / LICENSE) | HF gated. However, use and distribution require license agreement | 101 GB | `distilled` (default). Two-stage distilled pipeline. No CFG, about 11 steps inside. A transient model that loads/releases on every call. |
|
|
56
|
+
|
|
57
|
+
Key defaults and limits:
|
|
58
|
+
|
|
59
|
+
| Item | Default value | Constraints |
|
|
60
|
+
|---|---:|---|
|
|
61
|
+
| `width` | `512` | Positive multiple of 64. Upper limit `768`. |
|
|
62
|
+
| `height` | `512` | Positive multiple of 64. Upper limit `768`. |
|
|
63
|
+
| `num_frames` | `97` | `1 + 8*k`. Upper limit `721`. |
|
|
64
|
+
| `fps` | `24` | Positive integer. |
|
|
65
|
+
| `image_strength` | `1.0` | `0.0..1.0`. The degree to which I2V is constrained to the input frame. |
|
|
66
|
+
|
|
67
|
+
`duration = num_frames / fps`. At 24 fps, `97` takes about 4 seconds, `161` takes about 6.7 seconds,
|
|
68
|
+
`241` takes about 10 seconds, `481` takes about 20 seconds, and `721` takes about 30 seconds.
|
|
69
|
+
|
|
70
|
+
## Notes
|
|
71
|
+
|
|
72
|
+
- **transient model**:
|
|
73
|
+
LTX-2 is not a permanent model. Load, create, and free each call, and before execution
|
|
74
|
+
Reserve a temporary memory budget of approximately 40 GB with `memory.reserve()`. Therefore, `/health`
|
|
75
|
+
It will not remain in the resident model.
|
|
76
|
+
- **Response format**:
|
|
77
|
+
If sync produces only one MP4, it defaults to returning the raw MP4.
|
|
78
|
+
You can trace the metadata from the `X-Kiapi-File-Id` / `X-Kiapi-Job-Id` headers.
|
|
79
|
+
`Accept: application/json` returns Job JSON.
|
|
80
|
+
- **distilled has no negative guidance**:
|
|
81
|
+
There is no classifier-free guidance, so there is no negative prompt or `no zoom` / `don't ...`
|
|
82
|
+
Suppression instructions such as this do not work. The movement, composition, and texture you want, not what you want to avoid.
|
|
83
|
+
and adjust it with seed and `image_strength`.
|
|
84
|
+
- **I2V's `image_strength`**:
|
|
85
|
+
`1.0` is strongly fixed to the input frame. If you want to move clearly, set it to around `0.7`
|
|
86
|
+
Lowering it makes it easier to tolerate changes.
|
|
87
|
+
- **Progress**:
|
|
88
|
+
mlx-video does not expose per-step progress callbacks. kiapi is
|
|
89
|
+
Time-based, relative to `progress_eta_base_s`, scaled by number of frames and resolution.
|
|
90
|
+
Stream synthetic progress.
|
|
91
|
+
- **Notes on updating dependencies**:
|
|
92
|
+
`mlx-video` is pinned to git commit because the API is changeable. When updating
|
|
93
|
+
`_models/ltx2.py` calls `generate_video` and routes `PipelineType.DISTILLED`.
|
|
94
|
+
Please check it and verify it on the actual machine using `make verify-ltx2`.
|
|
95
|
+
|
|
96
|
+
## Quickstart
|
|
97
|
+
|
|
98
|
+
### generate — T2V
|
|
99
|
+
```bash
|
|
100
|
+
PARAMS=$(
|
|
101
|
+
jq -n \
|
|
102
|
+
--arg prompt "a cat walking through tall grass, sunny, shallow depth of field" \
|
|
103
|
+
'{
|
|
104
|
+
model: "distilled",
|
|
105
|
+
mode: "sync",
|
|
106
|
+
prompt: $prompt,
|
|
107
|
+
width: 512,
|
|
108
|
+
height: 512,
|
|
109
|
+
num_frames: 97,
|
|
110
|
+
fps: 24,
|
|
111
|
+
seed: 1
|
|
112
|
+
}'
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
curl -sS -X POST http://localhost:${PORT:-8000}/v1/video/ltx2/generate \
|
|
116
|
+
-H 'Content-Type: application/json' \
|
|
117
|
+
--data-binary "$PARAMS" \
|
|
118
|
+
-o ltx2.mp4
|
|
119
|
+
```
|
|
120
|
+
If you want Job JSON:
|
|
121
|
+
```bash
|
|
122
|
+
PARAMS=$(
|
|
123
|
+
jq -n \
|
|
124
|
+
--arg prompt "a small paper boat floating on a quiet pond, gentle ripples" \
|
|
125
|
+
'{
|
|
126
|
+
mode: "sync",
|
|
127
|
+
prompt: $prompt,
|
|
128
|
+
width: 512,
|
|
129
|
+
height: 512,
|
|
130
|
+
num_frames: 97,
|
|
131
|
+
seed: 2
|
|
132
|
+
}'
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
curl -sS -X POST http://localhost:${PORT:-8000}/v1/video/ltx2/generate \
|
|
136
|
+
-H 'Accept: application/json' \
|
|
137
|
+
-H 'Content-Type: application/json' \
|
|
138
|
+
--data-binary "$PARAMS" | jq .
|
|
139
|
+
```
|
|
140
|
+
### generate — I2V
|
|
141
|
+
|
|
142
|
+
Upload and reference the image you want to use for the first frame to the Files API.
|
|
143
|
+
```bash
|
|
144
|
+
IMAGE_ID=$(curl -sS -X POST http://localhost:${PORT:-8000}/v1/files \
|
|
145
|
+
-F "file=@first_frame.png;type=image/png" | jq -r .file_id)
|
|
146
|
+
|
|
147
|
+
PARAMS=$(
|
|
148
|
+
jq -n \
|
|
149
|
+
--arg image "$IMAGE_ID" \
|
|
150
|
+
--arg prompt "gentle wind, leaves moving, soft cinematic motion" \
|
|
151
|
+
'{
|
|
152
|
+
mode: "sync",
|
|
153
|
+
prompt: $prompt,
|
|
154
|
+
image: {type: "file_id", file_id: $image},
|
|
155
|
+
num_frames: 97,
|
|
156
|
+
image_strength: 0.7,
|
|
157
|
+
seed: 3
|
|
158
|
+
}'
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
curl -sS -X POST http://localhost:${PORT:-8000}/v1/video/ltx2/generate \
|
|
162
|
+
-H 'Content-Type: application/json' \
|
|
163
|
+
--data-binary "$PARAMS" \
|
|
164
|
+
-o ltx2-i2v.mp4
|
|
165
|
+
```
|
|
166
|
+
To specify the first and last frame:
|
|
167
|
+
```bash
|
|
168
|
+
IMAGE_ID=$(curl -sS -X POST http://localhost:${PORT:-8000}/v1/files \
|
|
169
|
+
-F "file=@first_frame.png;type=image/png" | jq -r .file_id)
|
|
170
|
+
END_IMAGE_ID=$(curl -sS -X POST http://localhost:${PORT:-8000}/v1/files \
|
|
171
|
+
-F "file=@last_frame.png;type=image/png" | jq -r .file_id)
|
|
172
|
+
|
|
173
|
+
PARAMS=$(
|
|
174
|
+
jq -n \
|
|
175
|
+
--arg image "$IMAGE_ID" \
|
|
176
|
+
--arg end_image "$END_IMAGE_ID" \
|
|
177
|
+
--arg prompt "a smooth transition from morning to sunset" \
|
|
178
|
+
'{
|
|
179
|
+
mode: "sync",
|
|
180
|
+
prompt: $prompt,
|
|
181
|
+
image: {type: "file_id", file_id: $image},
|
|
182
|
+
end_image: {type: "file_id", file_id: $end_image},
|
|
183
|
+
num_frames: 97,
|
|
184
|
+
image_strength: 0.8,
|
|
185
|
+
end_image_strength: 0.8,
|
|
186
|
+
seed: 4
|
|
187
|
+
}'
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
curl -sS -X POST http://localhost:${PORT:-8000}/v1/video/ltx2/generate \
|
|
191
|
+
-H 'Content-Type: application/json' \
|
|
192
|
+
--data-binary "$PARAMS" \
|
|
193
|
+
-o ltx2-first-last.mp4
|
|
194
|
+
```
|
|
195
|
+
### generate — A2V
|
|
196
|
+
|
|
197
|
+
When you upload and reference audio files to the Files API, audio drives motion, timing, and
|
|
198
|
+
Mixed to output MP4.
|
|
199
|
+
```bash
|
|
200
|
+
AUDIO_ID=$(curl -sS -X POST http://localhost:${PORT:-8000}/v1/files \
|
|
201
|
+
-F "file=@drums.wav;type=audio/wav" | jq -r .file_id)
|
|
202
|
+
|
|
203
|
+
PARAMS=$(
|
|
204
|
+
jq -n \
|
|
205
|
+
--arg audio "$AUDIO_ID" \
|
|
206
|
+
--arg prompt "a drummer on stage, energetic performance, stage lighting" \
|
|
207
|
+
'{
|
|
208
|
+
mode: "sync",
|
|
209
|
+
prompt: $prompt,
|
|
210
|
+
audio: {type: "file_id", file_id: $audio},
|
|
211
|
+
width: 512,
|
|
212
|
+
height: 512,
|
|
213
|
+
num_frames: 97,
|
|
214
|
+
seed: 5
|
|
215
|
+
}'
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
curl -sS -X POST http://localhost:${PORT:-8000}/v1/video/ltx2/generate \
|
|
219
|
+
-H 'Content-Type: application/json' \
|
|
220
|
+
--data-binary "$PARAMS" \
|
|
221
|
+
-o ltx2-a2v.mp4
|
|
222
|
+
```
|
|
223
|
+
### generate — T2V + Audio
|
|
224
|
+
|
|
225
|
+
Generates audio along with the video without using an audio file.
|
|
226
|
+
```bash
|
|
227
|
+
PARAMS=$(
|
|
228
|
+
jq -n \
|
|
229
|
+
--arg prompt "a tiny robot dancing in a neon room, playful electronic beat" \
|
|
230
|
+
'{
|
|
231
|
+
mode: "sync",
|
|
232
|
+
prompt: $prompt,
|
|
233
|
+
width: 512,
|
|
234
|
+
height: 512,
|
|
235
|
+
num_frames: 97,
|
|
236
|
+
generate_audio: true,
|
|
237
|
+
seed: 6
|
|
238
|
+
}'
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
curl -sS -X POST http://localhost:${PORT:-8000}/v1/video/ltx2/generate \
|
|
242
|
+
-H 'Content-Type: application/json' \
|
|
243
|
+
--data-binary "$PARAMS" \
|
|
244
|
+
-o ltx2-audio.mp4
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### async
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
PARAMS=$(
|
|
251
|
+
jq -n \
|
|
252
|
+
--arg prompt "a cinematic shot of clouds moving over a mountain lake" \
|
|
253
|
+
'{
|
|
254
|
+
mode: "async",
|
|
255
|
+
prompt: $prompt,
|
|
256
|
+
width: 512,
|
|
257
|
+
height: 512,
|
|
258
|
+
num_frames: 97,
|
|
259
|
+
seed: 7
|
|
260
|
+
}'
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
JOB=$(curl -sS -X POST http://localhost:${PORT:-8000}/v1/video/ltx2/generate \
|
|
264
|
+
-H 'Accept: application/json' \
|
|
265
|
+
-H 'Content-Type: application/json' \
|
|
266
|
+
--data-binary "$PARAMS" | jq -r .job_id)
|
|
267
|
+
|
|
268
|
+
curl -sS http://localhost:${PORT:-8000}/v1/jobs/$JOB | jq .
|
|
269
|
+
```
|
|
270
|
+
Once completed, use the Job's `artifacts[0]` or `result.file_id` to get the MP4.
|
|
271
|
+
```bash
|
|
272
|
+
FID=$(curl -sS http://localhost:${PORT:-8000}/v1/jobs/$JOB | jq -r .result.file_id)
|
|
273
|
+
curl -sS http://localhost:${PORT:-8000}/v1/files/$FID/download -o ltx2-async.mp4
|
|
274
|
+
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""ltx2 family — LTX-2 distilled video generation via mlx-video.
|
|
2
|
+
|
|
3
|
+
Endpoint: ``POST /v1/video/ltx2/generate`` (multipart; T2V/I2V/A2V inferred from
|
|
4
|
+
attached inputs). mlx-video loads and frees its own weights per call, so this
|
|
5
|
+
family is transient (``resident=False``): the service reserves budget room before
|
|
6
|
+
each run instead of holding a model.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from kiapi.capabilities import ValidationError
|
|
10
|
+
|
|
11
|
+
from ._helpers.register import register
|
|
12
|
+
from ._helpers.validate_generate import validate_generate
|
|
13
|
+
from ._operations.detect_mode import detect_mode
|
|
14
|
+
from ._operations.handle_generate import handle_generate
|
|
15
|
+
from ._settings import settings_manager
|
|
16
|
+
from ._views.generate_request import GenerateRequest
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"GenerateRequest", # ._views
|
|
20
|
+
"ValidationError", # kiapi.capabilities
|
|
21
|
+
"detect_mode", # ._operations
|
|
22
|
+
"handle_generate", # ._operations
|
|
23
|
+
"register", # ._helpers
|
|
24
|
+
"settings_manager", # ._settings
|
|
25
|
+
"validate_generate", # ._helpers
|
|
26
|
+
]
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
DESCRIPTION = """Short video generation with LTX-2 distilled.
|
|
2
|
+
|
|
3
|
+
LTX-2 generates short MP4 videos from text, optional image conditioning, and
|
|
4
|
+
optional audio.
|
|
5
|
+
|
|
6
|
+
## Upstream docs
|
|
7
|
+
- [mlx-video](https://github.com/Blaizzy/mlx-video) — the MLX engine kiapi runs
|
|
8
|
+
- [Lightricks/LTX-2](https://huggingface.co/Lightricks/LTX-2) — upstream model card and license source
|
|
9
|
+
- [prince-canuma/LTX-2-distilled](https://huggingface.co/prince-canuma/LTX-2-distilled) — distilled MLX weights used by kiapi
|
|
10
|
+
|
|
11
|
+
## Model
|
|
12
|
+
|
|
13
|
+
- **default model**: `distilled`
|
|
14
|
+
- **repo**: `prince-canuma/LTX-2-distilled`
|
|
15
|
+
- **pipeline**: two-stage distilled LTX-2 via `mlx-video`
|
|
16
|
+
- **residency**: transient. The pipeline is loaded for each job, run, then freed.
|
|
17
|
+
- **memory**: kiapi reserves about 40 GB for the transient run before generation.
|
|
18
|
+
|
|
19
|
+
The distilled pipeline does not use classifier-free guidance. Negative prompts
|
|
20
|
+
and suppression phrases such as `no zoom`, `do not move`, or `avoid blur` are not
|
|
21
|
+
reliable controls. Describe the desired subject, motion, framing, camera behavior,
|
|
22
|
+
lighting, and texture directly.
|
|
23
|
+
|
|
24
|
+
## Modes
|
|
25
|
+
|
|
26
|
+
The generation mode is inferred from attached inputs:
|
|
27
|
+
|
|
28
|
+
- **T2V**: prompt only
|
|
29
|
+
- **I2V**: prompt + `image`
|
|
30
|
+
- **I2V(first+last)**: prompt + `image` + `end_image`
|
|
31
|
+
- **I2V(last)**: prompt + `end_image`
|
|
32
|
+
- **A2V**: prompt + `audio`
|
|
33
|
+
- **A2V+I2V**: prompt + `image` + `audio`
|
|
34
|
+
- **T2V+Audio**: prompt + `generate_audio=true`
|
|
35
|
+
|
|
36
|
+
An uploaded or referenced `audio` file drives timing and is muxed into the MP4.
|
|
37
|
+
It cannot be combined with `generate_audio=true`.
|
|
38
|
+
|
|
39
|
+
## Practical Defaults
|
|
40
|
+
|
|
41
|
+
The server defaults target a useful quality/speed balance:
|
|
42
|
+
|
|
43
|
+
- `width`: 512
|
|
44
|
+
- `height`: 512
|
|
45
|
+
- `num_frames`: 97
|
|
46
|
+
- `fps`: 24
|
|
47
|
+
|
|
48
|
+
At 24 fps, common frame counts are roughly:
|
|
49
|
+
|
|
50
|
+
- `97`: about 4 seconds
|
|
51
|
+
- `161`: about 6.7 seconds
|
|
52
|
+
- `241`: about 10 seconds
|
|
53
|
+
- `481`: about 20 seconds
|
|
54
|
+
- `721`: about 30 seconds
|
|
55
|
+
|
|
56
|
+
`num_frames` must be `1 + 8*k`, and width/height must be multiples of 64.
|
|
57
|
+
|
|
58
|
+
## Tips
|
|
59
|
+
|
|
60
|
+
- Prefer positive direction over negative constraints. Write what should happen,
|
|
61
|
+
not what should be prevented.
|
|
62
|
+
- For I2V, `image_strength=1.0` keeps the first frame very stable. Lower values
|
|
63
|
+
around `0.7` allow more visible motion or composition change.
|
|
64
|
+
- Phrases like `looking at the camera` can encourage push-in/zoom behavior. If a
|
|
65
|
+
stable gaze is desired, try wording such as `looking ahead`.
|
|
66
|
+
- Use seed sweeps for composition, pose, and camera variation. A few seeds are
|
|
67
|
+
often more effective than over-constraining the prompt.
|
|
68
|
+
- 512x512 is the sweet spot for general use. Larger resolutions and longer frame
|
|
69
|
+
counts hold the single-flight queue for longer.
|
|
70
|
+
|
|
71
|
+
## Performance Notes
|
|
72
|
+
|
|
73
|
+
Generation time depends heavily on frame count and resolution. A 512x512,
|
|
74
|
+
97-frame job is the baseline used for synthetic progress; shorter/lower
|
|
75
|
+
resolution jobs complete faster, while long 721-frame jobs can occupy the worker
|
|
76
|
+
for much longer.
|
|
77
|
+
|
|
78
|
+
Because kiapi is single-flight, one LTX-2 job blocks all other heavy jobs until
|
|
79
|
+
it finishes. Use `mode="async"` for longer videos so clients can poll
|
|
80
|
+
`/v1/jobs/{job_id}` instead of holding an HTTP request open.
|
|
81
|
+
"""
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Register ltx2's models + OpenAPI description in the global registries."""
|
|
2
|
+
|
|
3
|
+
from kiapi.core.capability import CapabilitySpec, capability_spec_registry
|
|
4
|
+
from kiapi.core.model import ModelSpec, model_registry
|
|
5
|
+
from kiapi.core.setup import HfSnapshotResource, PythonPackageResource
|
|
6
|
+
|
|
7
|
+
from .._constants.description import DESCRIPTION
|
|
8
|
+
from .._models import ltx2
|
|
9
|
+
from .._settings import settings_manager
|
|
10
|
+
|
|
11
|
+
MLX_VIDEO_SPEC = (
|
|
12
|
+
"mlx-video @ git+https://github.com/Blaizzy/mlx-video.git"
|
|
13
|
+
"@87db56a51758fefb748a359b90a5283bb8ba4837"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def register() -> None:
|
|
18
|
+
capability_spec_registry.register(
|
|
19
|
+
CapabilitySpec(
|
|
20
|
+
name="ltx2",
|
|
21
|
+
domain="video",
|
|
22
|
+
title="kiapi LTX-2 API",
|
|
23
|
+
summary="Generate video from text, image, and music or audio inputs.",
|
|
24
|
+
description=DESCRIPTION,
|
|
25
|
+
openapi_path="/v1/video/ltx2/openapi.json",
|
|
26
|
+
docs_path="/v1/video/ltx2/docs",
|
|
27
|
+
redoc_path="/v1/video/ltx2/redoc",
|
|
28
|
+
path_prefixes=("/v1/video/ltx2",),
|
|
29
|
+
)
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
settings = settings_manager.get_settings()
|
|
33
|
+
|
|
34
|
+
model_registry.register(
|
|
35
|
+
ModelSpec(
|
|
36
|
+
name="distilled",
|
|
37
|
+
family="ltx2",
|
|
38
|
+
domain="video",
|
|
39
|
+
repo=settings.model_repo,
|
|
40
|
+
module=ltx2,
|
|
41
|
+
weight_gb=0.0, # transient: not held resident
|
|
42
|
+
peak_headroom_gb=40.0, # transient peak to reserve; reconciled on device
|
|
43
|
+
framework="mlx",
|
|
44
|
+
priority=0,
|
|
45
|
+
default=True,
|
|
46
|
+
resident=False,
|
|
47
|
+
setup_resources=(
|
|
48
|
+
PythonPackageResource(
|
|
49
|
+
package="mlx-video",
|
|
50
|
+
spec=MLX_VIDEO_SPEC,
|
|
51
|
+
import_name="mlx_video.models.ltx_2.generate",
|
|
52
|
+
verify_attrs=("PipelineType", "generate_video"),
|
|
53
|
+
label_name="mlx-video-ltx2",
|
|
54
|
+
),
|
|
55
|
+
HfSnapshotResource(repo=settings.model_repo, disk_gb=101.0),
|
|
56
|
+
),
|
|
57
|
+
)
|
|
58
|
+
)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Pure validation for LTX-2 generate requests."""
|
|
2
|
+
|
|
3
|
+
from kiapi.capabilities import ValidationError
|
|
4
|
+
|
|
5
|
+
from .._settings import settings_manager
|
|
6
|
+
from .._views.generate_request import GenerateRequest
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def validate_generate(req: GenerateRequest, *, variant: str, has_audio: bool) -> None:
|
|
10
|
+
settings = settings_manager.get_settings()
|
|
11
|
+
|
|
12
|
+
width = req.width if req.width is not None else settings.default_width
|
|
13
|
+
height = req.height if req.height is not None else settings.default_height
|
|
14
|
+
num_frames = (
|
|
15
|
+
req.num_frames if req.num_frames is not None else settings.default_num_frames
|
|
16
|
+
)
|
|
17
|
+
fps = req.fps if req.fps is not None else settings.default_fps
|
|
18
|
+
|
|
19
|
+
if width <= 0 or width % 64 != 0:
|
|
20
|
+
raise ValidationError(f"width must be a positive multiple of 64 (got {width})")
|
|
21
|
+
if height <= 0 or height % 64 != 0:
|
|
22
|
+
raise ValidationError(
|
|
23
|
+
f"height must be a positive multiple of 64 (got {height})"
|
|
24
|
+
)
|
|
25
|
+
if width > settings.max_width:
|
|
26
|
+
raise ValidationError(f"width {width} exceeds max {settings.max_width}")
|
|
27
|
+
if height > settings.max_height:
|
|
28
|
+
raise ValidationError(f"height {height} exceeds max {settings.max_height}")
|
|
29
|
+
if num_frames < 1 or (num_frames - 1) % 8 != 0:
|
|
30
|
+
raise ValidationError(
|
|
31
|
+
f"num_frames must be 1 + 8*k (e.g. 33, 97, 241, 481, 721); got {num_frames}"
|
|
32
|
+
)
|
|
33
|
+
if num_frames > settings.max_num_frames:
|
|
34
|
+
raise ValidationError(
|
|
35
|
+
f"num_frames {num_frames} exceeds max {settings.max_num_frames}"
|
|
36
|
+
)
|
|
37
|
+
if fps <= 0:
|
|
38
|
+
raise ValidationError(f"fps must be positive (got {fps})")
|
|
39
|
+
if has_audio and req.generate_audio:
|
|
40
|
+
raise ValidationError(
|
|
41
|
+
"cannot combine an audio file (A2V) with generate_audio; choose one"
|
|
42
|
+
)
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""Handler for LTX-2 distilled (text/image/audio → video; via mlx-video)."""
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from kiapi.core.file import FileStore
|
|
8
|
+
from kiapi.core.workdir import create_work_dir
|
|
9
|
+
|
|
10
|
+
from .._settings import LTX2Settings
|
|
11
|
+
from .._views.generate_params import GenerateParams
|
|
12
|
+
|
|
13
|
+
FEATURES = {"text", "image", "audio"}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def warmup(payload: object | None = None) -> None:
|
|
17
|
+
"""Prime kernels with a tiny T2V generation (artifact discarded)."""
|
|
18
|
+
from mlx_video.models.ltx_2.generate import ( # type: ignore
|
|
19
|
+
PipelineType,
|
|
20
|
+
generate_video,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
from .._settings import settings_manager
|
|
24
|
+
|
|
25
|
+
s = settings_manager.get_settings()
|
|
26
|
+
tmp = create_work_dir("video/ltx2/warmup")
|
|
27
|
+
generate_video(
|
|
28
|
+
model_repo=s.model_repo,
|
|
29
|
+
text_encoder_repo=s.text_encoder_repo, # pyright: ignore
|
|
30
|
+
prompt="warmup",
|
|
31
|
+
pipeline=PipelineType.DISTILLED,
|
|
32
|
+
height=256,
|
|
33
|
+
width=256,
|
|
34
|
+
num_frames=9,
|
|
35
|
+
fps=24,
|
|
36
|
+
seed=0,
|
|
37
|
+
output_path=str(tmp / "warm.mp4"),
|
|
38
|
+
verbose=False,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def run_generate(
|
|
43
|
+
params: GenerateParams,
|
|
44
|
+
settings: LTX2Settings,
|
|
45
|
+
files: FileStore,
|
|
46
|
+
staged: dict[str, Any],
|
|
47
|
+
mode: str,
|
|
48
|
+
) -> dict[str, Any]:
|
|
49
|
+
"""Blocking generation. Returns artifact metadata (the job's ``result``)."""
|
|
50
|
+
from mlx_video.models.ltx_2.generate import PipelineType, generate_video
|
|
51
|
+
|
|
52
|
+
tmp = create_work_dir("video/ltx2")
|
|
53
|
+
video_path = tmp / "video.mp4"
|
|
54
|
+
|
|
55
|
+
image = staged.get("image")
|
|
56
|
+
end_image = staged.get("end_image")
|
|
57
|
+
audio_file = staged.get("audio")
|
|
58
|
+
wants_audio = audio_file is not None or params.generate_audio
|
|
59
|
+
audio_out = str(tmp / "audio.wav") if wants_audio else None
|
|
60
|
+
|
|
61
|
+
t0 = time.time()
|
|
62
|
+
generate_video(
|
|
63
|
+
model_repo=settings.model_repo,
|
|
64
|
+
text_encoder_repo=settings.text_encoder_repo, # pyright: ignore
|
|
65
|
+
prompt=params.prompt,
|
|
66
|
+
pipeline=PipelineType.DISTILLED,
|
|
67
|
+
height=params.height,
|
|
68
|
+
width=params.width,
|
|
69
|
+
num_frames=params.num_frames,
|
|
70
|
+
fps=params.fps,
|
|
71
|
+
seed=params.seed,
|
|
72
|
+
output_path=str(video_path),
|
|
73
|
+
image=image,
|
|
74
|
+
image_strength=params.image_strength,
|
|
75
|
+
end_image=end_image,
|
|
76
|
+
end_image_strength=params.end_image_strength,
|
|
77
|
+
audio=params.generate_audio,
|
|
78
|
+
audio_file=audio_file,
|
|
79
|
+
output_audio_path=audio_out,
|
|
80
|
+
verbose=False,
|
|
81
|
+
)
|
|
82
|
+
total_s = round(time.time() - t0, 2)
|
|
83
|
+
|
|
84
|
+
if not video_path.exists():
|
|
85
|
+
raise RuntimeError("generation finished but no video file was produced")
|
|
86
|
+
|
|
87
|
+
# Audio (when requested) is muxed into video.mp4 by mlx-video; drop the wav.
|
|
88
|
+
has_audio = audio_out is not None and Path(audio_out).exists()
|
|
89
|
+
if audio_out is not None:
|
|
90
|
+
Path(audio_out).unlink(missing_ok=True)
|
|
91
|
+
|
|
92
|
+
meta = {
|
|
93
|
+
"mode": mode,
|
|
94
|
+
"prompt": params.prompt,
|
|
95
|
+
"params": params.gen_params(),
|
|
96
|
+
"has_audio": has_audio,
|
|
97
|
+
"timings": {"total_s": total_s},
|
|
98
|
+
}
|
|
99
|
+
rec = files.put_path(
|
|
100
|
+
video_path,
|
|
101
|
+
filename=f"video_{int(time.time())}.mp4",
|
|
102
|
+
content_type="video/mp4",
|
|
103
|
+
meta=meta,
|
|
104
|
+
move=True,
|
|
105
|
+
)
|
|
106
|
+
return {"file_id": rec.file_id, "video_bytes": rec.size, **meta}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Infer the LTX-2 generation mode from attached inputs."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def detect_mode(
|
|
5
|
+
*, has_image: bool, has_end_image: bool, has_audio: bool, generate_audio: bool
|
|
6
|
+
) -> str:
|
|
7
|
+
is_i2v = has_image or has_end_image
|
|
8
|
+
|
|
9
|
+
if has_audio:
|
|
10
|
+
return "A2V+I2V" if is_i2v else "A2V"
|
|
11
|
+
|
|
12
|
+
if is_i2v:
|
|
13
|
+
if has_image and has_end_image:
|
|
14
|
+
return "I2V(first+last)"
|
|
15
|
+
if has_end_image:
|
|
16
|
+
return "I2V(last)"
|
|
17
|
+
return "I2V"
|
|
18
|
+
|
|
19
|
+
return "T2V+Audio" if generate_audio else "T2V"
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""LTX-2 generate service entry (worker-thread thunk body)."""
|
|
2
|
+
|
|
3
|
+
from kiapi.capabilities import resolve_file_ref
|
|
4
|
+
from kiapi.core.app import AppContext
|
|
5
|
+
from kiapi.core.file import FileID
|
|
6
|
+
from kiapi.core.job import JobResult, creep_progress
|
|
7
|
+
from kiapi.core.model import model_registry
|
|
8
|
+
|
|
9
|
+
from .._settings import settings_manager
|
|
10
|
+
from .._views.generate_params import GenerateParams
|
|
11
|
+
from .._views.generate_request import GenerateRequest
|
|
12
|
+
from .resolve_generate_params import resolve_generate_params
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def handle_generate(
|
|
16
|
+
ctx: AppContext,
|
|
17
|
+
req: GenerateRequest,
|
|
18
|
+
mode: str,
|
|
19
|
+
) -> tuple[JobResult, list[FileID]]:
|
|
20
|
+
settings = settings_manager.get_settings()
|
|
21
|
+
spec = model_registry.resolve("ltx2", req.model)
|
|
22
|
+
ctx.ensure_model_ready(spec)
|
|
23
|
+
params = resolve_generate_params(settings, req, variant=spec.name)
|
|
24
|
+
staged = _resolve_staged_inputs(ctx, req)
|
|
25
|
+
|
|
26
|
+
ctx.memory_manager.reserve(spec.weight_gb + spec.peak_headroom_gb)
|
|
27
|
+
|
|
28
|
+
with creep_progress(eta_s=_calc_eta_s(params, settings.progress_eta_base_s)):
|
|
29
|
+
result = spec.module.run_generate(
|
|
30
|
+
params, settings, ctx.file_store, staged, mode
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
return result, [result["file_id"]]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _resolve_staged_inputs(ctx: AppContext, req: GenerateRequest) -> dict[str, str]:
|
|
37
|
+
staged: dict[str, str] = {}
|
|
38
|
+
if req.image is not None:
|
|
39
|
+
staged["image"] = resolve_file_ref(ctx.file_store, req.image, kind="image").path
|
|
40
|
+
if req.end_image is not None:
|
|
41
|
+
staged["end_image"] = resolve_file_ref(
|
|
42
|
+
ctx.file_store, req.end_image, kind="end_image"
|
|
43
|
+
).path
|
|
44
|
+
if req.audio is not None:
|
|
45
|
+
staged["audio"] = resolve_file_ref(ctx.file_store, req.audio, kind="audio").path
|
|
46
|
+
return staged
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _calc_eta_s(params: GenerateParams, base_s: float) -> float:
|
|
50
|
+
frames = params.num_frames / 97
|
|
51
|
+
pixels = (params.width * params.height) / (512 * 512)
|
|
52
|
+
return base_s * max(frames * pixels, 0.1)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Merge an LTX-2 generate request with settings defaults."""
|
|
2
|
+
|
|
3
|
+
import random
|
|
4
|
+
|
|
5
|
+
from .._settings import LTX2Settings
|
|
6
|
+
from .._views.generate_params import GenerateParams
|
|
7
|
+
from .._views.generate_request import GenerateRequest
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def resolve_generate_params(
|
|
11
|
+
settings: LTX2Settings,
|
|
12
|
+
req: GenerateRequest,
|
|
13
|
+
*,
|
|
14
|
+
variant: str,
|
|
15
|
+
) -> GenerateParams:
|
|
16
|
+
return GenerateParams(
|
|
17
|
+
model=variant,
|
|
18
|
+
prompt=req.prompt,
|
|
19
|
+
seed=req.seed if req.seed is not None else random.randint(0, 2**31 - 1),
|
|
20
|
+
width=req.width if req.width is not None else settings.default_width,
|
|
21
|
+
height=req.height if req.height is not None else settings.default_height,
|
|
22
|
+
num_frames=(
|
|
23
|
+
req.num_frames
|
|
24
|
+
if req.num_frames is not None
|
|
25
|
+
else settings.default_num_frames
|
|
26
|
+
),
|
|
27
|
+
fps=req.fps if req.fps is not None else settings.default_fps,
|
|
28
|
+
image_strength=req.image_strength,
|
|
29
|
+
end_image_strength=req.end_image_strength,
|
|
30
|
+
generate_audio=req.generate_audio,
|
|
31
|
+
)
|