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,278 @@
|
|
|
1
|
+
"""Handler for Z-Image generation/training via mflux."""
|
|
2
|
+
|
|
3
|
+
import gc
|
|
4
|
+
import json
|
|
5
|
+
import time
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from types import SimpleNamespace
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from kiapi.capabilities import attach_mflux_progress
|
|
11
|
+
from kiapi.core.file import FileStore
|
|
12
|
+
from kiapi.core.model import ModelSpec
|
|
13
|
+
from kiapi.core.workdir import create_work_dir
|
|
14
|
+
|
|
15
|
+
from .._settings import settings_manager
|
|
16
|
+
from .._views.generate_params import GenerateParams
|
|
17
|
+
from .._views.train_params import TrainParams
|
|
18
|
+
|
|
19
|
+
FEATURES = {"text"}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _model_config(variant: str) -> Any:
|
|
23
|
+
from mflux.models.common.config import ModelConfig # type: ignore
|
|
24
|
+
|
|
25
|
+
return ModelConfig.z_image() if variant == "base" else ModelConfig.z_image_turbo()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def build_model(
|
|
29
|
+
spec: ModelSpec,
|
|
30
|
+
*,
|
|
31
|
+
quantize: int | None,
|
|
32
|
+
lora_paths: list[str] | None = None,
|
|
33
|
+
lora_scales: list[float] | None = None,
|
|
34
|
+
) -> Any:
|
|
35
|
+
from mflux.models.z_image import ZImageTurbo # type: ignore
|
|
36
|
+
|
|
37
|
+
return ZImageTurbo(
|
|
38
|
+
quantize=quantize,
|
|
39
|
+
model_path=spec.repo,
|
|
40
|
+
lora_paths=lora_paths or None,
|
|
41
|
+
lora_scales=lora_scales or None,
|
|
42
|
+
model_config=_model_config(spec.name),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def load(spec: ModelSpec) -> SimpleNamespace:
|
|
47
|
+
quantize = settings_manager.get_settings().default_quantize.get(spec.name)
|
|
48
|
+
model = build_model(spec, quantize=quantize)
|
|
49
|
+
return SimpleNamespace(model=model, spec=spec, quantize=quantize)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def warmup(payload: SimpleNamespace) -> None:
|
|
53
|
+
payload.model.generate_image(
|
|
54
|
+
seed=0, prompt="warmup", num_inference_steps=1, width=256, height=256
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _store_image(
|
|
59
|
+
image: Any,
|
|
60
|
+
*,
|
|
61
|
+
fmt: str,
|
|
62
|
+
quality: int,
|
|
63
|
+
files: FileStore,
|
|
64
|
+
meta: dict[str, Any],
|
|
65
|
+
) -> dict[str, Any]:
|
|
66
|
+
pil = getattr(image, "image", image)
|
|
67
|
+
ext = "jpg" if fmt == "jpeg" else fmt
|
|
68
|
+
tmp_dir = create_work_dir("image/zimage")
|
|
69
|
+
out_path = tmp_dir / f"image.{ext}"
|
|
70
|
+
save_kwargs: dict[str, Any] = {}
|
|
71
|
+
if fmt in ("jpeg", "webp"):
|
|
72
|
+
save_kwargs["quality"] = quality
|
|
73
|
+
if fmt == "jpeg":
|
|
74
|
+
pil = pil.convert("RGB")
|
|
75
|
+
pil.save(out_path, format=fmt.upper(), **save_kwargs)
|
|
76
|
+
if not out_path.exists():
|
|
77
|
+
raise RuntimeError("generation finished but no image file was produced")
|
|
78
|
+
rec = files.put_path(
|
|
79
|
+
out_path,
|
|
80
|
+
filename=f"image_{int(time.time())}.{ext}",
|
|
81
|
+
content_type=f"image/{fmt}",
|
|
82
|
+
meta=meta,
|
|
83
|
+
move=True,
|
|
84
|
+
)
|
|
85
|
+
return {"file_id": rec.file_id, "image_bytes": rec.size, **meta}
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _generate(model: Any, params: GenerateParams, files: FileStore) -> dict[str, Any]:
|
|
89
|
+
t0 = time.time()
|
|
90
|
+
attach_mflux_progress(model)
|
|
91
|
+
image = model.generate_image(
|
|
92
|
+
seed=params.seed,
|
|
93
|
+
prompt=params.prompt,
|
|
94
|
+
num_inference_steps=params.steps,
|
|
95
|
+
width=params.width,
|
|
96
|
+
height=params.height,
|
|
97
|
+
guidance=params.guidance,
|
|
98
|
+
negative_prompt=params.negative_prompt,
|
|
99
|
+
)
|
|
100
|
+
total_s = round(time.time() - t0, 2)
|
|
101
|
+
meta = {
|
|
102
|
+
"model": params.model,
|
|
103
|
+
"prompt": params.prompt,
|
|
104
|
+
"params": params.model_dump(),
|
|
105
|
+
"width": params.width,
|
|
106
|
+
"height": params.height,
|
|
107
|
+
"timings": {"total_s": total_s},
|
|
108
|
+
}
|
|
109
|
+
return _store_image(
|
|
110
|
+
image, fmt=params.format, quality=params.quality, files=files, meta=meta
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def run_generate(
|
|
115
|
+
payload: SimpleNamespace, params: GenerateParams, files: FileStore
|
|
116
|
+
) -> dict[str, Any]:
|
|
117
|
+
return _generate(payload.model, params, files)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def run_generate_transient(
|
|
121
|
+
spec: ModelSpec,
|
|
122
|
+
params: GenerateParams,
|
|
123
|
+
files: FileStore,
|
|
124
|
+
*,
|
|
125
|
+
lora_paths: list[str],
|
|
126
|
+
lora_scales: list[float],
|
|
127
|
+
) -> dict[str, Any]:
|
|
128
|
+
model = build_model(
|
|
129
|
+
spec, quantize=params.quantize, lora_paths=lora_paths, lora_scales=lora_scales
|
|
130
|
+
)
|
|
131
|
+
try:
|
|
132
|
+
return _generate(model, params, files)
|
|
133
|
+
finally:
|
|
134
|
+
_free(model)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def _free(model: Any) -> None:
|
|
138
|
+
del model
|
|
139
|
+
gc.collect()
|
|
140
|
+
import mlx.core as mx
|
|
141
|
+
|
|
142
|
+
mx.clear_cache()
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
_MFLUX_TRAIN_NAME = {"turbo": "z-image-turbo", "base": "z-image"}
|
|
146
|
+
_BLOCK_RANGE = {"start": 0, "end": 30}
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _default_lora_targets(rank: int, include_ff: bool) -> list[dict[str, Any]]:
|
|
150
|
+
attn = ["attention.to_q", "attention.to_k", "attention.to_v", "attention.to_out.0"]
|
|
151
|
+
ff = ["feed_forward.w1", "feed_forward.w2", "feed_forward.w3"] if include_ff else []
|
|
152
|
+
targets = [
|
|
153
|
+
{
|
|
154
|
+
"module_path": f"layers.{{block}}.{name}",
|
|
155
|
+
"blocks": dict(_BLOCK_RANGE),
|
|
156
|
+
"rank": rank,
|
|
157
|
+
}
|
|
158
|
+
for name in (*attn, *ff)
|
|
159
|
+
]
|
|
160
|
+
targets += [
|
|
161
|
+
{"module_path": "cap_embedder.1", "rank": rank},
|
|
162
|
+
{"module_path": "all_final_layer.2-1.linear", "rank": rank},
|
|
163
|
+
]
|
|
164
|
+
return targets
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def _build_train_config(
|
|
168
|
+
spec: ModelSpec,
|
|
169
|
+
params: TrainParams,
|
|
170
|
+
data_dirname: str,
|
|
171
|
+
out_dir: Path,
|
|
172
|
+
) -> dict[str, Any]:
|
|
173
|
+
lora_layers = params.lora_layers or {
|
|
174
|
+
"targets": _default_lora_targets(params.lora_rank, params.lora_include_ff)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return {
|
|
178
|
+
"model": _MFLUX_TRAIN_NAME[spec.name],
|
|
179
|
+
"model_path": spec.repo,
|
|
180
|
+
"data": data_dirname,
|
|
181
|
+
"seed": params.seed,
|
|
182
|
+
"steps": params.steps,
|
|
183
|
+
"guidance": params.guidance,
|
|
184
|
+
"quantize": params.quantize,
|
|
185
|
+
"max_resolution": params.max_resolution,
|
|
186
|
+
"low_ram": params.low_ram,
|
|
187
|
+
"training_loop": {
|
|
188
|
+
"num_epochs": params.num_epochs,
|
|
189
|
+
"batch_size": params.batch_size,
|
|
190
|
+
"timestep_low": params.timestep_low,
|
|
191
|
+
"timestep_high": params.timestep_high,
|
|
192
|
+
},
|
|
193
|
+
"optimizer": {"name": "AdamW", "learning_rate": params.learning_rate},
|
|
194
|
+
"checkpoint": {
|
|
195
|
+
"save_frequency": params.save_frequency,
|
|
196
|
+
"output_path": str(out_dir),
|
|
197
|
+
},
|
|
198
|
+
"lora_layers": lora_layers,
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def train(
|
|
203
|
+
spec: ModelSpec,
|
|
204
|
+
params: TrainParams,
|
|
205
|
+
files: FileStore,
|
|
206
|
+
dataset_dir: str,
|
|
207
|
+
) -> dict[str, Any]:
|
|
208
|
+
import zipfile
|
|
209
|
+
|
|
210
|
+
from mflux.models.common.training.runner import TrainingRunner # type: ignore
|
|
211
|
+
from mflux.utils.exceptions import StopTrainingException # type: ignore
|
|
212
|
+
|
|
213
|
+
workdir = Path(dataset_dir).parent
|
|
214
|
+
out_dir = workdir / "out"
|
|
215
|
+
config = _build_train_config(spec, params, Path(dataset_dir).name, out_dir)
|
|
216
|
+
config_path = workdir / "train.json"
|
|
217
|
+
config_path.write_text(json.dumps(config, indent=2))
|
|
218
|
+
|
|
219
|
+
t0 = time.time()
|
|
220
|
+
try:
|
|
221
|
+
_adapter, training_spec = TrainingRunner.train(
|
|
222
|
+
config_path=str(config_path), resume_path=None
|
|
223
|
+
)
|
|
224
|
+
except StopTrainingException:
|
|
225
|
+
from mflux.models.common.training.state.training_spec import ( # type: ignore[import-untyped]
|
|
226
|
+
TrainingSpec,
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
training_spec = TrainingSpec.resolve(
|
|
230
|
+
config_path=str(config_path), resume_path=None
|
|
231
|
+
)
|
|
232
|
+
total_s = round(time.time() - t0, 2)
|
|
233
|
+
|
|
234
|
+
ckpt_dir = Path(training_spec.checkpoint.output_path) / "checkpoints"
|
|
235
|
+
zips = sorted(ckpt_dir.glob("*_checkpoint.zip"))
|
|
236
|
+
if not zips:
|
|
237
|
+
raise RuntimeError(
|
|
238
|
+
f"training finished but no checkpoint was produced in {ckpt_dir}"
|
|
239
|
+
)
|
|
240
|
+
latest = zips[-1]
|
|
241
|
+
|
|
242
|
+
adapter_bytes = None
|
|
243
|
+
with zipfile.ZipFile(latest) as zf:
|
|
244
|
+
for name in zf.namelist():
|
|
245
|
+
if name.endswith("_adapter.safetensors"):
|
|
246
|
+
adapter_bytes = zf.read(name)
|
|
247
|
+
break
|
|
248
|
+
if adapter_bytes is None:
|
|
249
|
+
raise RuntimeError(f"no *_adapter.safetensors inside {latest.name}")
|
|
250
|
+
|
|
251
|
+
meta = {
|
|
252
|
+
"model": spec.name,
|
|
253
|
+
"kind": "lora_adapter",
|
|
254
|
+
"config": {
|
|
255
|
+
k: config[k]
|
|
256
|
+
for k in (
|
|
257
|
+
"model",
|
|
258
|
+
"seed",
|
|
259
|
+
"steps",
|
|
260
|
+
"guidance",
|
|
261
|
+
"quantize",
|
|
262
|
+
"max_resolution",
|
|
263
|
+
"low_ram",
|
|
264
|
+
"training_loop",
|
|
265
|
+
"optimizer",
|
|
266
|
+
)
|
|
267
|
+
},
|
|
268
|
+
"lora_targets": len(config["lora_layers"]["targets"]),
|
|
269
|
+
"checkpoint": latest.name,
|
|
270
|
+
"timings": {"total_s": total_s},
|
|
271
|
+
}
|
|
272
|
+
rec = files.put_bytes(
|
|
273
|
+
adapter_bytes,
|
|
274
|
+
filename=f"zimage_lora_{spec.name}_{int(time.time())}.safetensors",
|
|
275
|
+
content_type="application/octet-stream",
|
|
276
|
+
meta=meta,
|
|
277
|
+
)
|
|
278
|
+
return {"adapter_file_id": rec.file_id, "adapter_bytes": rec.size, **meta}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Z-Image text-to-image service entry (worker-thread thunk body)."""
|
|
2
|
+
|
|
3
|
+
from kiapi.core.app import AppContext
|
|
4
|
+
from kiapi.core.file import FileID
|
|
5
|
+
from kiapi.core.job import JobResult
|
|
6
|
+
from kiapi.core.model import model_registry
|
|
7
|
+
|
|
8
|
+
from .._settings import settings_manager
|
|
9
|
+
from .._views.generate_request import GenerateRequest
|
|
10
|
+
from .is_quantize_override import is_quantize_override
|
|
11
|
+
from .resolve_generate_params import resolve_generate_params
|
|
12
|
+
from .resolve_lora_params import resolve_lora_params
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def handle_generate(
|
|
16
|
+
ctx: AppContext, req: GenerateRequest
|
|
17
|
+
) -> tuple[JobResult, list[FileID]]:
|
|
18
|
+
settings = settings_manager.get_settings()
|
|
19
|
+
spec = model_registry.resolve("zimage", req.model)
|
|
20
|
+
ctx.ensure_model_ready(spec)
|
|
21
|
+
lora_params = resolve_lora_params(ctx, req.loras)
|
|
22
|
+
override = is_quantize_override(settings, req, variant=spec.name)
|
|
23
|
+
params = resolve_generate_params(settings, req, variant=spec.name)
|
|
24
|
+
|
|
25
|
+
if lora_params.paths or override:
|
|
26
|
+
ctx.memory_manager.reserve(spec.weight_gb + spec.peak_headroom_gb)
|
|
27
|
+
result = spec.module.run_generate_transient(
|
|
28
|
+
spec,
|
|
29
|
+
params,
|
|
30
|
+
ctx.file_store,
|
|
31
|
+
lora_paths=lora_params.paths,
|
|
32
|
+
lora_scales=lora_params.scales,
|
|
33
|
+
)
|
|
34
|
+
else:
|
|
35
|
+
payload = ctx.memory_manager.acquire(spec)
|
|
36
|
+
result = spec.module.run_generate(payload, params, ctx.file_store)
|
|
37
|
+
|
|
38
|
+
return result, [result["file_id"]]
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""Z-Image LoRA finetune service entry (always-async worker-thread thunk)."""
|
|
2
|
+
|
|
3
|
+
import shutil
|
|
4
|
+
import zipfile
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from kiapi.capabilities import CapabilityError, get_file_path
|
|
8
|
+
from kiapi.core.app import AppContext
|
|
9
|
+
from kiapi.core.file import FileID
|
|
10
|
+
from kiapi.core.job import JobResult
|
|
11
|
+
from kiapi.core.model import model_registry
|
|
12
|
+
from kiapi.core.workdir import create_work_dir
|
|
13
|
+
|
|
14
|
+
from .._settings import settings_manager
|
|
15
|
+
from .._views.train_request import TrainRequest
|
|
16
|
+
from .resolve_train_params import resolve_train_params
|
|
17
|
+
|
|
18
|
+
_IMAGE_EXTS = {".jpg", ".jpeg", ".png", ".webp"}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def handle_train(ctx: AppContext, req: TrainRequest) -> tuple[JobResult, list[FileID]]:
|
|
22
|
+
settings = settings_manager.get_settings()
|
|
23
|
+
spec = model_registry.resolve("zimage", req.model)
|
|
24
|
+
ctx.ensure_model_ready(spec)
|
|
25
|
+
|
|
26
|
+
dataset_path = get_file_path(ctx.file_store, req.dataset, kind="dataset")
|
|
27
|
+
|
|
28
|
+
workdir = create_work_dir("train/zimage")
|
|
29
|
+
try:
|
|
30
|
+
data_dir = _extract_dataset(dataset_path, workdir / "data")
|
|
31
|
+
n_images = _validate_dataset(data_dir)
|
|
32
|
+
params = resolve_train_params(settings, req, variant=spec.name)
|
|
33
|
+
ctx.memory_manager.reserve(settings.train_reserve_gb)
|
|
34
|
+
result = spec.module.train(spec, params, ctx.file_store, str(data_dir))
|
|
35
|
+
result["num_images"] = n_images
|
|
36
|
+
return result, [result["adapter_file_id"]]
|
|
37
|
+
finally:
|
|
38
|
+
shutil.rmtree(workdir, ignore_errors=True)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _extract_dataset(zip_path: str, dest: Path) -> Path:
|
|
42
|
+
dest.mkdir(parents=True, exist_ok=True)
|
|
43
|
+
with zipfile.ZipFile(zip_path) as zf:
|
|
44
|
+
for member in zf.namelist():
|
|
45
|
+
target = (dest / member).resolve()
|
|
46
|
+
if not str(target).startswith(str(dest.resolve())):
|
|
47
|
+
raise CapabilityError(f"unsafe path in dataset zip: {member!r}")
|
|
48
|
+
zf.extractall(dest)
|
|
49
|
+
|
|
50
|
+
def _has_images(d: Path) -> bool:
|
|
51
|
+
return any(p.suffix.lower() in _IMAGE_EXTS for p in d.iterdir() if p.is_file())
|
|
52
|
+
|
|
53
|
+
if _has_images(dest):
|
|
54
|
+
return dest
|
|
55
|
+
subdirs = [p for p in dest.iterdir() if p.is_dir()]
|
|
56
|
+
if len(subdirs) == 1 and _has_images(subdirs[0]):
|
|
57
|
+
return subdirs[0]
|
|
58
|
+
raise CapabilityError(
|
|
59
|
+
"dataset zip must contain images (.jpg/.jpeg/.png/.webp) at the top level "
|
|
60
|
+
"or in a single subfolder"
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _validate_dataset(data_dir: Path) -> int:
|
|
65
|
+
images = [
|
|
66
|
+
p for p in data_dir.iterdir() if p.is_file() and p.suffix.lower() in _IMAGE_EXTS
|
|
67
|
+
]
|
|
68
|
+
if not images:
|
|
69
|
+
raise CapabilityError("dataset has no images")
|
|
70
|
+
missing = [
|
|
71
|
+
p.name
|
|
72
|
+
for p in images
|
|
73
|
+
if not p.stem.startswith("preview")
|
|
74
|
+
and not (data_dir / f"{p.stem}.txt").exists()
|
|
75
|
+
]
|
|
76
|
+
if missing:
|
|
77
|
+
raise CapabilityError(f"images missing a same-stem .txt caption: {missing}")
|
|
78
|
+
return len([p for p in images if not p.stem.startswith("preview")])
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""Decide whether a request's quantize differs from the variant default."""
|
|
2
|
+
|
|
3
|
+
from .._settings import ZimageSettings
|
|
4
|
+
from .._views.generate_request import GenerateRequest
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def is_quantize_override(
|
|
8
|
+
settings: ZimageSettings, req: GenerateRequest, *, variant: str
|
|
9
|
+
) -> bool:
|
|
10
|
+
default_quantize = settings.default_quantize.get(variant)
|
|
11
|
+
return req.quantize is not None and req.quantize != default_quantize
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Merge a generate request with settings defaults into GenerateParams."""
|
|
2
|
+
|
|
3
|
+
import random
|
|
4
|
+
|
|
5
|
+
from .._settings import ZimageSettings
|
|
6
|
+
from .._views.generate_params import GenerateParams
|
|
7
|
+
from .._views.generate_request import GenerateRequest
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def resolve_generate_params(
|
|
11
|
+
settings: ZimageSettings,
|
|
12
|
+
req: GenerateRequest,
|
|
13
|
+
*,
|
|
14
|
+
variant: str,
|
|
15
|
+
) -> GenerateParams:
|
|
16
|
+
return GenerateParams(
|
|
17
|
+
model=variant,
|
|
18
|
+
prompt=req.prompt,
|
|
19
|
+
negative_prompt=req.negative_prompt,
|
|
20
|
+
seed=req.seed if req.seed is not None else random.randint(0, 2**31 - 1),
|
|
21
|
+
width=req.width if req.width is not None else settings.default_width,
|
|
22
|
+
height=req.height if req.height is not None else settings.default_height,
|
|
23
|
+
steps=req.steps
|
|
24
|
+
if req.steps is not None
|
|
25
|
+
else settings.default_steps.get(variant, 9),
|
|
26
|
+
guidance=(
|
|
27
|
+
req.guidance
|
|
28
|
+
if req.guidance is not None
|
|
29
|
+
else settings.default_guidance.get(variant)
|
|
30
|
+
),
|
|
31
|
+
quantize=(
|
|
32
|
+
req.quantize
|
|
33
|
+
if req.quantize is not None
|
|
34
|
+
else settings.default_quantize.get(variant)
|
|
35
|
+
),
|
|
36
|
+
format=req.format,
|
|
37
|
+
quality=req.quality,
|
|
38
|
+
loras=req.loras,
|
|
39
|
+
)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from collections.abc import Iterable
|
|
2
|
+
from dataclasses import dataclass, field
|
|
3
|
+
|
|
4
|
+
from kiapi.capabilities import get_file_path
|
|
5
|
+
from kiapi.core.app import AppContext
|
|
6
|
+
|
|
7
|
+
from .._schemas.lora_ref import LoraRef
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class LoraParams:
|
|
12
|
+
paths: list[str] = field(default_factory=list)
|
|
13
|
+
scales: list[float] = field(default_factory=list)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def resolve_lora_params(ctx: AppContext, loras: Iterable[LoraRef]) -> LoraParams:
|
|
17
|
+
params = LoraParams()
|
|
18
|
+
|
|
19
|
+
for lr in loras:
|
|
20
|
+
params.paths.append(get_file_path(ctx.file_store, lr.file, kind="lora"))
|
|
21
|
+
params.scales.append(lr.scale)
|
|
22
|
+
|
|
23
|
+
return params
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Merge a train request with settings defaults into TrainParams."""
|
|
2
|
+
|
|
3
|
+
from .._settings import ZimageSettings
|
|
4
|
+
from .._views.train_params import TrainParams
|
|
5
|
+
from .._views.train_request import TrainRequest
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def resolve_train_params(
|
|
9
|
+
settings: ZimageSettings,
|
|
10
|
+
req: TrainRequest,
|
|
11
|
+
*,
|
|
12
|
+
variant: str,
|
|
13
|
+
) -> TrainParams:
|
|
14
|
+
steps = req.steps if req.steps is not None else settings.train_steps.get(variant, 9)
|
|
15
|
+
return TrainParams(
|
|
16
|
+
model=variant,
|
|
17
|
+
seed=req.seed,
|
|
18
|
+
steps=steps,
|
|
19
|
+
guidance=req.guidance,
|
|
20
|
+
quantize=req.quantize
|
|
21
|
+
if req.quantize is not None
|
|
22
|
+
else settings.train_quantize.get(variant),
|
|
23
|
+
max_resolution=req.max_resolution,
|
|
24
|
+
low_ram=req.low_ram,
|
|
25
|
+
num_epochs=req.num_epochs,
|
|
26
|
+
batch_size=req.batch_size,
|
|
27
|
+
timestep_low=(
|
|
28
|
+
req.timestep_low
|
|
29
|
+
if req.timestep_low is not None
|
|
30
|
+
else settings.train_timestep_low.get(variant, 0)
|
|
31
|
+
),
|
|
32
|
+
timestep_high=req.timestep_high if req.timestep_high is not None else steps,
|
|
33
|
+
learning_rate=req.learning_rate,
|
|
34
|
+
save_frequency=req.save_frequency if req.save_frequency is not None else 10**9,
|
|
35
|
+
lora_rank=req.lora_rank,
|
|
36
|
+
lora_include_ff=req.lora_include_ff,
|
|
37
|
+
lora_layers=req.lora_layers,
|
|
38
|
+
)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""A single LoRA adapter reference (file + scale) applied to a zimage run."""
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
from kiapi.core.file import FileRef
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class LoraRef(BaseModel):
|
|
9
|
+
"""One LoRA adapter to apply, by Files-API reference and blend scale.
|
|
10
|
+
|
|
11
|
+
Any lora forces a one-off transient model (slower, not reused). Up to 4 may
|
|
12
|
+
be passed in a request's ``loras`` list.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
file: FileRef = Field(
|
|
16
|
+
description=(
|
|
17
|
+
"The LoRA adapter (`.safetensors`) to apply, as a Files-API file id, "
|
|
18
|
+
"http(s) URL, or data URL. Train one via POST /v1/image/zimage/train."
|
|
19
|
+
),
|
|
20
|
+
)
|
|
21
|
+
scale: float = Field(
|
|
22
|
+
default=1.0,
|
|
23
|
+
description=(
|
|
24
|
+
"Blend strength for this adapter. 1.0 applies it at full weight; lower "
|
|
25
|
+
"values weaken its effect, higher values exaggerate it."
|
|
26
|
+
),
|
|
27
|
+
)
|