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,356 @@
|
|
|
1
|
+
"""Handler for ERNIE-Image generation/edit/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 .._views.edit_params import EditParams
|
|
16
|
+
from .._views.generate_params import GenerateParams
|
|
17
|
+
from .._views.train_params import TrainParams
|
|
18
|
+
|
|
19
|
+
FEATURES = {"text", "image"}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _model_name(spec: ModelSpec) -> str:
|
|
23
|
+
return "ernie-image" if spec.name == "base" else "ernie-image-turbo"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _model_config(spec: ModelSpec) -> Any:
|
|
27
|
+
from mflux.models.common.config import ModelConfig # type: ignore
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
ModelConfig.ernie_image()
|
|
31
|
+
if spec.name == "base"
|
|
32
|
+
else ModelConfig.ernie_image_turbo()
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def build_model(
|
|
37
|
+
spec: ModelSpec,
|
|
38
|
+
*,
|
|
39
|
+
quantize: int | None,
|
|
40
|
+
lora_paths: list[str] | None = None,
|
|
41
|
+
lora_scales: list[float] | None = None,
|
|
42
|
+
) -> Any:
|
|
43
|
+
from mflux.models.ernie_image import ErnieImage # type: ignore
|
|
44
|
+
|
|
45
|
+
return ErnieImage(
|
|
46
|
+
quantize=quantize,
|
|
47
|
+
model_path=spec.repo,
|
|
48
|
+
lora_paths=lora_paths or None,
|
|
49
|
+
lora_scales=lora_scales or None,
|
|
50
|
+
model_config=_model_config(spec),
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def load(spec: ModelSpec) -> SimpleNamespace:
|
|
55
|
+
from .._settings import settings_manager
|
|
56
|
+
|
|
57
|
+
quantize = settings_manager.get_settings().default_quantize.get(spec.name)
|
|
58
|
+
model = build_model(spec, quantize=quantize)
|
|
59
|
+
return SimpleNamespace(model=model, spec=spec, quantize=quantize)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def warmup(payload: SimpleNamespace) -> None:
|
|
63
|
+
payload.model.generate_image(
|
|
64
|
+
seed=0, prompt="warmup", num_inference_steps=1, width=256, height=256
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _store_image(
|
|
69
|
+
image: Any,
|
|
70
|
+
*,
|
|
71
|
+
fmt: str,
|
|
72
|
+
quality: int,
|
|
73
|
+
files: FileStore,
|
|
74
|
+
meta: dict[str, Any],
|
|
75
|
+
) -> dict[str, Any]:
|
|
76
|
+
pil = getattr(image, "image", image)
|
|
77
|
+
ext = "jpg" if fmt == "jpeg" else fmt
|
|
78
|
+
tmp_dir = create_work_dir("image/ernie")
|
|
79
|
+
out_path = tmp_dir / f"image.{ext}"
|
|
80
|
+
save_kwargs: dict[str, Any] = {}
|
|
81
|
+
if fmt in ("jpeg", "webp"):
|
|
82
|
+
save_kwargs["quality"] = quality
|
|
83
|
+
if fmt == "jpeg":
|
|
84
|
+
pil = pil.convert("RGB")
|
|
85
|
+
pil.save(out_path, format=fmt.upper(), **save_kwargs)
|
|
86
|
+
if not out_path.exists():
|
|
87
|
+
raise RuntimeError("generation finished but no image file was produced")
|
|
88
|
+
rec = files.put_path(
|
|
89
|
+
out_path,
|
|
90
|
+
filename=f"ernie_{int(time.time())}.{ext}",
|
|
91
|
+
content_type=f"image/{fmt}",
|
|
92
|
+
meta=meta,
|
|
93
|
+
move=True,
|
|
94
|
+
)
|
|
95
|
+
return {"file_id": rec.file_id, "image_bytes": rec.size, **meta}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _generate(model: Any, params: GenerateParams, files: FileStore) -> dict[str, Any]:
|
|
99
|
+
t0 = time.time()
|
|
100
|
+
attach_mflux_progress(model)
|
|
101
|
+
image = model.generate_image(
|
|
102
|
+
seed=params.seed,
|
|
103
|
+
prompt=params.prompt,
|
|
104
|
+
negative_prompt=params.negative_prompt,
|
|
105
|
+
num_inference_steps=params.steps,
|
|
106
|
+
width=params.width,
|
|
107
|
+
height=params.height,
|
|
108
|
+
guidance=params.guidance,
|
|
109
|
+
scheduler=params.scheduler,
|
|
110
|
+
)
|
|
111
|
+
total_s = round(time.time() - t0, 2)
|
|
112
|
+
meta = {
|
|
113
|
+
"model": params.model,
|
|
114
|
+
"prompt": params.prompt,
|
|
115
|
+
"params": params.model_dump(),
|
|
116
|
+
"width": params.width,
|
|
117
|
+
"height": params.height,
|
|
118
|
+
"timings": {"total_s": total_s},
|
|
119
|
+
}
|
|
120
|
+
return _store_image(
|
|
121
|
+
image, fmt=params.format, quality=params.quality, files=files, meta=meta
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _edit(model: Any, params: EditParams, files: FileStore) -> dict[str, Any]:
|
|
126
|
+
t0 = time.time()
|
|
127
|
+
attach_mflux_progress(model)
|
|
128
|
+
image = model.generate_image(
|
|
129
|
+
seed=params.seed,
|
|
130
|
+
prompt=params.prompt,
|
|
131
|
+
negative_prompt=params.negative_prompt,
|
|
132
|
+
image_path=params.image_path,
|
|
133
|
+
image_strength=params.image_strength,
|
|
134
|
+
num_inference_steps=params.steps,
|
|
135
|
+
width=params.width,
|
|
136
|
+
height=params.height,
|
|
137
|
+
guidance=params.guidance,
|
|
138
|
+
scheduler=params.scheduler,
|
|
139
|
+
)
|
|
140
|
+
total_s = round(time.time() - t0, 2)
|
|
141
|
+
meta = {
|
|
142
|
+
"model": params.model,
|
|
143
|
+
"prompt": params.prompt,
|
|
144
|
+
"params": params.model_dump(exclude={"image_path"}),
|
|
145
|
+
"width": params.width,
|
|
146
|
+
"height": params.height,
|
|
147
|
+
"timings": {"total_s": total_s},
|
|
148
|
+
}
|
|
149
|
+
return _store_image(
|
|
150
|
+
image, fmt=params.format, quality=params.quality, files=files, meta=meta
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def run_generate(
|
|
155
|
+
payload: SimpleNamespace, params: GenerateParams, files: FileStore
|
|
156
|
+
) -> dict[str, Any]:
|
|
157
|
+
return _generate(payload.model, params, files)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def run_edit(
|
|
161
|
+
payload: SimpleNamespace, params: EditParams, files: FileStore
|
|
162
|
+
) -> dict[str, Any]:
|
|
163
|
+
return _edit(payload.model, params, files)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def run_generate_transient(
|
|
167
|
+
spec: ModelSpec,
|
|
168
|
+
params: GenerateParams,
|
|
169
|
+
files: FileStore,
|
|
170
|
+
*,
|
|
171
|
+
lora_paths: list[str],
|
|
172
|
+
lora_scales: list[float],
|
|
173
|
+
) -> dict[str, Any]:
|
|
174
|
+
model = build_model(
|
|
175
|
+
spec, quantize=params.quantize, lora_paths=lora_paths, lora_scales=lora_scales
|
|
176
|
+
)
|
|
177
|
+
try:
|
|
178
|
+
return _generate(model, params, files)
|
|
179
|
+
finally:
|
|
180
|
+
_free(model)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def run_edit_transient(
|
|
184
|
+
spec: ModelSpec,
|
|
185
|
+
params: EditParams,
|
|
186
|
+
files: FileStore,
|
|
187
|
+
*,
|
|
188
|
+
lora_paths: list[str],
|
|
189
|
+
lora_scales: list[float],
|
|
190
|
+
) -> dict[str, Any]:
|
|
191
|
+
model = build_model(
|
|
192
|
+
spec, quantize=params.quantize, lora_paths=lora_paths, lora_scales=lora_scales
|
|
193
|
+
)
|
|
194
|
+
try:
|
|
195
|
+
return _edit(model, params, files)
|
|
196
|
+
finally:
|
|
197
|
+
_free(model)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def _free(model: Any) -> None:
|
|
201
|
+
del model
|
|
202
|
+
gc.collect()
|
|
203
|
+
import mlx.core as mx
|
|
204
|
+
|
|
205
|
+
mx.clear_cache()
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
_BLOCK_RANGE = {"start": 0, "end": 36}
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def _default_lora_targets(rank: int, include_ff: bool) -> list[dict[str, Any]]:
|
|
212
|
+
attn = [
|
|
213
|
+
"self_attention.to_q",
|
|
214
|
+
"self_attention.to_k",
|
|
215
|
+
"self_attention.to_v",
|
|
216
|
+
"self_attention.to_out.0",
|
|
217
|
+
]
|
|
218
|
+
targets = [
|
|
219
|
+
{
|
|
220
|
+
"module_path": f"layers.{{block}}.{name}",
|
|
221
|
+
"blocks": dict(_BLOCK_RANGE),
|
|
222
|
+
"rank": rank,
|
|
223
|
+
}
|
|
224
|
+
for name in attn
|
|
225
|
+
]
|
|
226
|
+
targets.append({"module_path": "text_proj", "rank": rank})
|
|
227
|
+
if include_ff:
|
|
228
|
+
targets += [
|
|
229
|
+
{
|
|
230
|
+
"module_path": f"layers.{{block}}.mlp.{name}",
|
|
231
|
+
"blocks": dict(_BLOCK_RANGE),
|
|
232
|
+
"rank": rank,
|
|
233
|
+
}
|
|
234
|
+
for name in ("gate_proj", "up_proj", "linear_fc2")
|
|
235
|
+
]
|
|
236
|
+
targets += [
|
|
237
|
+
{"module_path": "time_embedding.linear_1", "rank": rank},
|
|
238
|
+
{"module_path": "time_embedding.linear_2", "rank": rank},
|
|
239
|
+
{"module_path": "adaln_modulation", "rank": rank},
|
|
240
|
+
{"module_path": "final_norm.linear", "rank": rank},
|
|
241
|
+
]
|
|
242
|
+
return targets
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def _build_train_config(
|
|
246
|
+
spec: ModelSpec,
|
|
247
|
+
params: TrainParams,
|
|
248
|
+
data_dirname: str,
|
|
249
|
+
out_dir: Path,
|
|
250
|
+
) -> dict[str, Any]:
|
|
251
|
+
lora_layers = params.lora_layers or {
|
|
252
|
+
"targets": _default_lora_targets(params.lora_rank, params.lora_include_ff)
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return {
|
|
256
|
+
"model": _model_name(spec),
|
|
257
|
+
"model_path": spec.repo,
|
|
258
|
+
"data": data_dirname,
|
|
259
|
+
"seed": params.seed,
|
|
260
|
+
"steps": params.steps,
|
|
261
|
+
"guidance": params.guidance,
|
|
262
|
+
"quantize": params.quantize,
|
|
263
|
+
"max_resolution": params.max_resolution,
|
|
264
|
+
"low_ram": params.low_ram,
|
|
265
|
+
"training_loop": {
|
|
266
|
+
"num_epochs": params.num_epochs,
|
|
267
|
+
"batch_size": params.batch_size,
|
|
268
|
+
"timestep_low": params.timestep_low,
|
|
269
|
+
"timestep_high": params.timestep_high,
|
|
270
|
+
},
|
|
271
|
+
"optimizer": {"name": "AdamW", "learning_rate": params.learning_rate},
|
|
272
|
+
"checkpoint": {
|
|
273
|
+
"save_frequency": params.save_frequency,
|
|
274
|
+
"output_path": str(out_dir),
|
|
275
|
+
},
|
|
276
|
+
"lora_layers": lora_layers,
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def train(
|
|
281
|
+
spec: ModelSpec,
|
|
282
|
+
params: TrainParams,
|
|
283
|
+
files: FileStore,
|
|
284
|
+
dataset_dir: str,
|
|
285
|
+
) -> dict[str, Any]:
|
|
286
|
+
import zipfile
|
|
287
|
+
|
|
288
|
+
from mflux.models.common.training.runner import TrainingRunner # type: ignore
|
|
289
|
+
from mflux.utils.exceptions import StopTrainingException # type: ignore
|
|
290
|
+
|
|
291
|
+
workdir = Path(dataset_dir).parent
|
|
292
|
+
out_dir = workdir / "out"
|
|
293
|
+
config = _build_train_config(spec, params, Path(dataset_dir).name, out_dir)
|
|
294
|
+
config_path = workdir / "train.json"
|
|
295
|
+
config_path.write_text(json.dumps(config, indent=2))
|
|
296
|
+
|
|
297
|
+
t0 = time.time()
|
|
298
|
+
try:
|
|
299
|
+
_adapter, training_spec = TrainingRunner.train(
|
|
300
|
+
config_path=str(config_path), resume_path=None
|
|
301
|
+
)
|
|
302
|
+
except StopTrainingException:
|
|
303
|
+
from mflux.models.common.training.state.training_spec import ( # type: ignore[import-untyped]
|
|
304
|
+
TrainingSpec,
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
training_spec = TrainingSpec.resolve(
|
|
308
|
+
config_path=str(config_path), resume_path=None
|
|
309
|
+
)
|
|
310
|
+
total_s = round(time.time() - t0, 2)
|
|
311
|
+
|
|
312
|
+
ckpt_dir = Path(training_spec.checkpoint.output_path) / "checkpoints"
|
|
313
|
+
zips = sorted(ckpt_dir.glob("*_checkpoint.zip"))
|
|
314
|
+
if not zips:
|
|
315
|
+
raise RuntimeError(
|
|
316
|
+
f"training finished but no checkpoint was produced in {ckpt_dir}"
|
|
317
|
+
)
|
|
318
|
+
latest = zips[-1]
|
|
319
|
+
|
|
320
|
+
adapter_bytes = None
|
|
321
|
+
with zipfile.ZipFile(latest) as zf:
|
|
322
|
+
for name in zf.namelist():
|
|
323
|
+
if name.endswith("_adapter.safetensors"):
|
|
324
|
+
adapter_bytes = zf.read(name)
|
|
325
|
+
break
|
|
326
|
+
if adapter_bytes is None:
|
|
327
|
+
raise RuntimeError(f"no *_adapter.safetensors inside {latest.name}")
|
|
328
|
+
|
|
329
|
+
meta = {
|
|
330
|
+
"model": spec.name,
|
|
331
|
+
"kind": "lora_adapter",
|
|
332
|
+
"config": {
|
|
333
|
+
k: config[k]
|
|
334
|
+
for k in (
|
|
335
|
+
"model",
|
|
336
|
+
"seed",
|
|
337
|
+
"steps",
|
|
338
|
+
"guidance",
|
|
339
|
+
"quantize",
|
|
340
|
+
"max_resolution",
|
|
341
|
+
"low_ram",
|
|
342
|
+
"training_loop",
|
|
343
|
+
"optimizer",
|
|
344
|
+
)
|
|
345
|
+
},
|
|
346
|
+
"lora_targets": len(config["lora_layers"]["targets"]),
|
|
347
|
+
"checkpoint": latest.name,
|
|
348
|
+
"timings": {"total_s": total_s},
|
|
349
|
+
}
|
|
350
|
+
rec = files.put_bytes(
|
|
351
|
+
adapter_bytes,
|
|
352
|
+
filename=f"ernie_lora_{spec.name}_{int(time.time())}.safetensors",
|
|
353
|
+
content_type="application/octet-stream",
|
|
354
|
+
meta=meta,
|
|
355
|
+
)
|
|
356
|
+
return {"adapter_file_id": rec.file_id, "adapter_bytes": rec.size, **meta}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""ERNIE-Image single-image edit service entry (worker-thread thunk body)."""
|
|
2
|
+
|
|
3
|
+
from kiapi.capabilities import get_file_path
|
|
4
|
+
from kiapi.core.app import AppContext
|
|
5
|
+
from kiapi.core.file import FileID
|
|
6
|
+
from kiapi.core.job import JobResult
|
|
7
|
+
from kiapi.core.model import model_registry
|
|
8
|
+
|
|
9
|
+
from .._settings import settings_manager
|
|
10
|
+
from .._views.edit_request import EditRequest
|
|
11
|
+
from .is_quantize_override import is_quantize_override
|
|
12
|
+
from .resolve_edit_params import resolve_edit_params
|
|
13
|
+
from .resolve_lora_params import resolve_lora_params
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def handle_edit(ctx: AppContext, req: EditRequest) -> tuple[JobResult, list[FileID]]:
|
|
17
|
+
settings = settings_manager.get_settings()
|
|
18
|
+
spec = model_registry.resolve("ernie", req.model)
|
|
19
|
+
ctx.ensure_model_ready(spec)
|
|
20
|
+
image_path = get_file_path(ctx.file_store, req.image, kind="image")
|
|
21
|
+
lora_params = resolve_lora_params(ctx, req.loras)
|
|
22
|
+
override = is_quantize_override(settings, req, variant=spec.name)
|
|
23
|
+
params = resolve_edit_params(
|
|
24
|
+
settings, req, variant=spec.name, image_path=image_path
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
if lora_params.paths or override:
|
|
28
|
+
ctx.memory_manager.reserve(spec.weight_gb + spec.peak_headroom_gb)
|
|
29
|
+
result = spec.module.run_edit_transient(
|
|
30
|
+
spec,
|
|
31
|
+
params,
|
|
32
|
+
ctx.file_store,
|
|
33
|
+
lora_paths=lora_params.paths,
|
|
34
|
+
lora_scales=lora_params.scales,
|
|
35
|
+
)
|
|
36
|
+
else:
|
|
37
|
+
payload = ctx.memory_manager.acquire(spec)
|
|
38
|
+
result = spec.module.run_edit(payload, params, ctx.file_store)
|
|
39
|
+
return result, [result["file_id"]]
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""ERNIE-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("ernie", 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,77 @@
|
|
|
1
|
+
"""ERNIE-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("ernie", 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/ernie")
|
|
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 at the top level or in a single subfolder"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _validate_dataset(data_dir: Path) -> int:
|
|
64
|
+
images = [
|
|
65
|
+
p for p in data_dir.iterdir() if p.is_file() and p.suffix.lower() in _IMAGE_EXTS
|
|
66
|
+
]
|
|
67
|
+
if not images:
|
|
68
|
+
raise CapabilityError("dataset has no images")
|
|
69
|
+
missing = [
|
|
70
|
+
p.name
|
|
71
|
+
for p in images
|
|
72
|
+
if not p.stem.startswith("preview")
|
|
73
|
+
and not (data_dir / f"{p.stem}.txt").exists()
|
|
74
|
+
]
|
|
75
|
+
if missing:
|
|
76
|
+
raise CapabilityError(f"images missing a same-stem .txt caption: {missing}")
|
|
77
|
+
return len([p for p in images if not p.stem.startswith("preview")])
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Decide whether a request's quantize differs from the variant default.
|
|
2
|
+
|
|
3
|
+
A True result means the resident model (quantized at its default) can't serve the
|
|
4
|
+
request, so ``handle_*`` runs a one-off transient model instead.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .._settings import ErnieSettings
|
|
8
|
+
from .._views.edit_request import EditRequest
|
|
9
|
+
from .._views.generate_request import GenerateRequest
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def is_quantize_override(
|
|
13
|
+
settings: ErnieSettings, req: GenerateRequest | EditRequest, *, variant: str
|
|
14
|
+
) -> bool:
|
|
15
|
+
default_quantize = settings.default_quantize.get(variant)
|
|
16
|
+
return req.quantize is not None and req.quantize != default_quantize
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Merge an edit request with settings defaults into the complete EditParams."""
|
|
2
|
+
|
|
3
|
+
import random
|
|
4
|
+
|
|
5
|
+
from .._settings import ErnieSettings
|
|
6
|
+
from .._views.edit_params import EditParams
|
|
7
|
+
from .._views.edit_request import EditRequest
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def resolve_edit_params(
|
|
11
|
+
settings: ErnieSettings,
|
|
12
|
+
req: EditRequest,
|
|
13
|
+
*,
|
|
14
|
+
variant: str,
|
|
15
|
+
image_path: str,
|
|
16
|
+
) -> EditParams:
|
|
17
|
+
return EditParams(
|
|
18
|
+
model=variant,
|
|
19
|
+
prompt=req.prompt,
|
|
20
|
+
negative_prompt=req.negative_prompt,
|
|
21
|
+
image_file_id="",
|
|
22
|
+
image_path=image_path,
|
|
23
|
+
image_strength=req.image_strength,
|
|
24
|
+
seed=req.seed if req.seed is not None else random.randint(0, 2**31 - 1),
|
|
25
|
+
width=req.width if req.width is not None else settings.default_width,
|
|
26
|
+
height=req.height if req.height is not None else settings.default_height,
|
|
27
|
+
steps=req.steps
|
|
28
|
+
if req.steps is not None
|
|
29
|
+
else settings.default_steps.get(variant, 8),
|
|
30
|
+
guidance=(
|
|
31
|
+
req.guidance
|
|
32
|
+
if req.guidance is not None
|
|
33
|
+
else settings.default_guidance.get(variant, 1.0)
|
|
34
|
+
),
|
|
35
|
+
quantize=(
|
|
36
|
+
req.quantize
|
|
37
|
+
if req.quantize is not None
|
|
38
|
+
else settings.default_quantize.get(variant)
|
|
39
|
+
),
|
|
40
|
+
scheduler=req.scheduler,
|
|
41
|
+
format=req.format,
|
|
42
|
+
quality=req.quality,
|
|
43
|
+
loras=req.loras,
|
|
44
|
+
)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Merge a generate request with settings defaults into the complete GenerateParams."""
|
|
2
|
+
|
|
3
|
+
import random
|
|
4
|
+
|
|
5
|
+
from .._settings import ErnieSettings
|
|
6
|
+
from .._views.generate_params import GenerateParams
|
|
7
|
+
from .._views.generate_request import GenerateRequest
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def resolve_generate_params(
|
|
11
|
+
settings: ErnieSettings,
|
|
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, 8),
|
|
26
|
+
guidance=(
|
|
27
|
+
req.guidance
|
|
28
|
+
if req.guidance is not None
|
|
29
|
+
else settings.default_guidance.get(variant, 1.0)
|
|
30
|
+
),
|
|
31
|
+
quantize=(
|
|
32
|
+
req.quantize
|
|
33
|
+
if req.quantize is not None
|
|
34
|
+
else settings.default_quantize.get(variant)
|
|
35
|
+
),
|
|
36
|
+
scheduler=req.scheduler,
|
|
37
|
+
format=req.format,
|
|
38
|
+
quality=req.quality,
|
|
39
|
+
loras=req.loras,
|
|
40
|
+
)
|
|
@@ -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,43 @@
|
|
|
1
|
+
"""Merge a train request with settings defaults into the complete TrainParams."""
|
|
2
|
+
|
|
3
|
+
from .._settings import ErnieSettings
|
|
4
|
+
from .._views.train_params import TrainParams
|
|
5
|
+
from .._views.train_request import TrainRequest
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def resolve_train_params(
|
|
9
|
+
settings: ErnieSettings,
|
|
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, 8)
|
|
15
|
+
return TrainParams(
|
|
16
|
+
seed=req.seed,
|
|
17
|
+
steps=steps,
|
|
18
|
+
guidance=(
|
|
19
|
+
req.guidance
|
|
20
|
+
if req.guidance is not None
|
|
21
|
+
else settings.default_guidance.get(variant, 1.0)
|
|
22
|
+
),
|
|
23
|
+
quantize=(
|
|
24
|
+
req.quantize
|
|
25
|
+
if req.quantize is not None
|
|
26
|
+
else settings.train_quantize.get(variant, 8)
|
|
27
|
+
),
|
|
28
|
+
max_resolution=req.max_resolution,
|
|
29
|
+
low_ram=req.low_ram,
|
|
30
|
+
num_epochs=req.num_epochs,
|
|
31
|
+
batch_size=req.batch_size,
|
|
32
|
+
timestep_low=(
|
|
33
|
+
req.timestep_low
|
|
34
|
+
if req.timestep_low is not None
|
|
35
|
+
else settings.train_timestep_low.get(variant, 1)
|
|
36
|
+
),
|
|
37
|
+
timestep_high=req.timestep_high if req.timestep_high is not None else steps,
|
|
38
|
+
learning_rate=req.learning_rate,
|
|
39
|
+
save_frequency=req.save_frequency if req.save_frequency is not None else 10**9,
|
|
40
|
+
lora_rank=req.lora_rank,
|
|
41
|
+
lora_include_ff=req.lora_include_ff,
|
|
42
|
+
lora_layers=req.lora_layers,
|
|
43
|
+
)
|