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,81 @@
|
|
|
1
|
+
"""Image API (depthpro): ``POST /v1/image/depthpro/estimate``."""
|
|
2
|
+
|
|
3
|
+
from fastapi import APIRouter, Depends, HTTPException
|
|
4
|
+
from fastapi.responses import Response
|
|
5
|
+
|
|
6
|
+
from kiapi.api import (
|
|
7
|
+
REQUIRE_AUTH,
|
|
8
|
+
build_job_responses,
|
|
9
|
+
get_accept,
|
|
10
|
+
get_ctx,
|
|
11
|
+
get_worker,
|
|
12
|
+
register_capability_endpoints,
|
|
13
|
+
submit_and_maybe_wait,
|
|
14
|
+
)
|
|
15
|
+
from kiapi.capabilities.depthpro import (
|
|
16
|
+
EstimateRequest,
|
|
17
|
+
ValidationError,
|
|
18
|
+
handle_estimate,
|
|
19
|
+
validate_estimate,
|
|
20
|
+
)
|
|
21
|
+
from kiapi.core.app import AppContext
|
|
22
|
+
from kiapi.core.model import UnknownModelError, model_registry
|
|
23
|
+
from kiapi.core.worker import Worker
|
|
24
|
+
|
|
25
|
+
from ._views.estimate_response import EstimateResponse
|
|
26
|
+
|
|
27
|
+
router = APIRouter(dependencies=REQUIRE_AUTH)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@router.post(
|
|
31
|
+
"/v1/image/depthpro/estimate",
|
|
32
|
+
responses=build_job_responses("image/png", result_model=EstimateResponse),
|
|
33
|
+
)
|
|
34
|
+
async def estimate(
|
|
35
|
+
req: EstimateRequest,
|
|
36
|
+
accept: str | None = Depends(get_accept),
|
|
37
|
+
ctx: AppContext = Depends(get_ctx),
|
|
38
|
+
worker: Worker = Depends(get_worker),
|
|
39
|
+
) -> Response:
|
|
40
|
+
"""Estimate a depth map from one image (Depth Pro, image-to-depth).
|
|
41
|
+
|
|
42
|
+
Produces a grayscale depth PNG (near = bright, far = dark) and, unless
|
|
43
|
+
`include_depth_data` is false, a compressed NPZ holding the raw float depth
|
|
44
|
+
array plus min/max depth. The same endpoint serves both `sync` and `async`
|
|
45
|
+
via `mode`.
|
|
46
|
+
|
|
47
|
+
Sync content negotiation: when exactly one artifact is produced (i.e.
|
|
48
|
+
`include_depth_data=false`) and the client does not ask for JSON, the raw PNG
|
|
49
|
+
bytes are returned with `X-Kiapi-File-Id` / `X-Kiapi-Job-Id` headers — so
|
|
50
|
+
`curl -o depth.png` just works. Otherwise (JSON requested, two artifacts, or
|
|
51
|
+
async) the Job JSON is returned, whose `result` follows EstimateResponse.
|
|
52
|
+
|
|
53
|
+
A `quantize` value differing from the resident model runs a one-off transient
|
|
54
|
+
model (slower, not reused). Async returns 202 immediately; poll
|
|
55
|
+
GET /v1/jobs/{job_id} and fetch artifacts via GET /v1/files/{file_id}.
|
|
56
|
+
"""
|
|
57
|
+
try:
|
|
58
|
+
spec = model_registry.resolve("depthpro", req.model)
|
|
59
|
+
except UnknownModelError as exc:
|
|
60
|
+
raise HTTPException(status_code=400, detail=str(exc)) # noqa: B904
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
validate_estimate(req)
|
|
64
|
+
except ValidationError as exc:
|
|
65
|
+
raise HTTPException(status_code=422, detail=str(exc)) # noqa: B904
|
|
66
|
+
|
|
67
|
+
def thunk(): # type: ignore
|
|
68
|
+
return handle_estimate(ctx, req)
|
|
69
|
+
|
|
70
|
+
return await submit_and_maybe_wait(
|
|
71
|
+
ctx,
|
|
72
|
+
worker,
|
|
73
|
+
type="depthpro",
|
|
74
|
+
params=req.gen_params() | {"model": spec.name, "mode": req.mode},
|
|
75
|
+
thunk=thunk,
|
|
76
|
+
mode=req.mode,
|
|
77
|
+
accept=accept,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
register_capability_endpoints(router, name="depthpro", base_path="/v1/image/depthpro")
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""``/v1/image/ernie/{generate,edit}`` result payload (the Job ``result`` shape).
|
|
2
|
+
|
|
3
|
+
Mirrors the dict returned by ``capabilities/ernie/_models/ernie._store_image`` so
|
|
4
|
+
the produced image result is self-describing in OpenAPI. It is an output-side
|
|
5
|
+
projection of the model result (not a model-coupled view), so it lives under
|
|
6
|
+
``api/image/ernie/_views``. ``generate`` and ``edit`` produce the same shape, so
|
|
7
|
+
both endpoints share this one view.
|
|
8
|
+
|
|
9
|
+
``ImageResponse`` is the sole public element; nested pieces stay private.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
from pydantic import BaseModel, Field
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class _Timings(BaseModel):
|
|
18
|
+
total_s: float = Field(
|
|
19
|
+
description="Wall-clock generation time in seconds (model run only)."
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ImageResponse(BaseModel):
|
|
24
|
+
"""Capability-specific ``result`` for a succeeded ernie generate/edit job."""
|
|
25
|
+
|
|
26
|
+
model: str = Field(
|
|
27
|
+
description="Resolved model variant that produced the image (turbo | base)."
|
|
28
|
+
)
|
|
29
|
+
prompt: str = Field(description="The prompt used for the run.")
|
|
30
|
+
|
|
31
|
+
file_id: str = Field(
|
|
32
|
+
description=(
|
|
33
|
+
"Files-API id of the produced image. Fetch metadata at "
|
|
34
|
+
"GET /v1/files/{id} or bytes at /download. This is also the artifact "
|
|
35
|
+
"returned as raw bytes by a single-artifact sync call."
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
image_bytes: int = Field(description="Size of the produced image in bytes.")
|
|
39
|
+
|
|
40
|
+
width: int = Field(description="Width in pixels of the produced image.")
|
|
41
|
+
height: int = Field(description="Height in pixels of the produced image.")
|
|
42
|
+
|
|
43
|
+
params: dict[str, Any] = Field(
|
|
44
|
+
description=(
|
|
45
|
+
"Resolved parameters actually used for the run (model, seed, steps, "
|
|
46
|
+
"guidance, quantize, scheduler, format, quality, loras, …), so the "
|
|
47
|
+
"result is reproducible."
|
|
48
|
+
)
|
|
49
|
+
)
|
|
50
|
+
timings: _Timings = Field(description="kiapi extension: server-side timing.")
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"""Image API (ernie): ERNIE-Image generate/edit/train."""
|
|
2
|
+
|
|
3
|
+
from fastapi import APIRouter, Depends, HTTPException
|
|
4
|
+
from fastapi.responses import Response
|
|
5
|
+
|
|
6
|
+
from kiapi.api import (
|
|
7
|
+
REQUIRE_AUTH,
|
|
8
|
+
build_job_responses,
|
|
9
|
+
build_train_responses,
|
|
10
|
+
get_accept,
|
|
11
|
+
get_ctx,
|
|
12
|
+
get_worker,
|
|
13
|
+
register_capability_endpoints,
|
|
14
|
+
submit_and_maybe_wait,
|
|
15
|
+
)
|
|
16
|
+
from kiapi.capabilities.ernie import (
|
|
17
|
+
EditRequest,
|
|
18
|
+
GenerateRequest,
|
|
19
|
+
TrainRequest,
|
|
20
|
+
ValidationError,
|
|
21
|
+
handle_edit,
|
|
22
|
+
handle_generate,
|
|
23
|
+
handle_train,
|
|
24
|
+
validate_edit,
|
|
25
|
+
validate_generate,
|
|
26
|
+
)
|
|
27
|
+
from kiapi.core.app import AppContext
|
|
28
|
+
from kiapi.core.file import FileIDRef
|
|
29
|
+
from kiapi.core.model import UnknownModelError, model_registry
|
|
30
|
+
from kiapi.core.worker import Worker
|
|
31
|
+
|
|
32
|
+
from ._views.image_response import ImageResponse
|
|
33
|
+
|
|
34
|
+
router = APIRouter(dependencies=REQUIRE_AUTH)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@router.post(
|
|
38
|
+
"/v1/image/ernie/generate",
|
|
39
|
+
responses=build_job_responses(
|
|
40
|
+
"image/png", "image/jpeg", "image/webp", result_model=ImageResponse
|
|
41
|
+
),
|
|
42
|
+
)
|
|
43
|
+
async def generate_ernie_endpoint(
|
|
44
|
+
req: GenerateRequest,
|
|
45
|
+
accept: str | None = Depends(get_accept),
|
|
46
|
+
ctx: AppContext = Depends(get_ctx),
|
|
47
|
+
worker: Worker = Depends(get_worker),
|
|
48
|
+
) -> Response:
|
|
49
|
+
"""Generate an image from a text prompt (ERNIE-Image, text-to-image).
|
|
50
|
+
|
|
51
|
+
No input image — use `/v1/image/ernie/edit` for image-to-image. The same
|
|
52
|
+
endpoint serves both `sync` and `async` via `mode`. Variant defaults differ:
|
|
53
|
+
`turbo` (default) is fast and uses few steps; `base` is higher quality and
|
|
54
|
+
slower.
|
|
55
|
+
|
|
56
|
+
Sync content negotiation: a single image is produced, so unless the client
|
|
57
|
+
asks for JSON the raw image bytes are returned with `X-Kiapi-File-Id` /
|
|
58
|
+
`X-Kiapi-Job-Id` headers — `curl -o out.png` just works. With
|
|
59
|
+
`Accept: application/json` (or async) the Job JSON is returned, whose
|
|
60
|
+
`result` follows ImageResponse.
|
|
61
|
+
|
|
62
|
+
Any `loras` or a `quantize` differing from the resident model runs a one-off
|
|
63
|
+
transient model (slower, not reused). Async returns 202 immediately; poll
|
|
64
|
+
GET /v1/jobs/{job_id} and fetch the artifact via GET /v1/files/{file_id}.
|
|
65
|
+
"""
|
|
66
|
+
try:
|
|
67
|
+
spec = model_registry.resolve("ernie", req.model)
|
|
68
|
+
except UnknownModelError as exc:
|
|
69
|
+
raise HTTPException(status_code=400, detail=str(exc)) # noqa: B904
|
|
70
|
+
try:
|
|
71
|
+
validate_generate(req, variant=spec.name)
|
|
72
|
+
except ValidationError as exc:
|
|
73
|
+
raise HTTPException(status_code=422, detail=str(exc)) # noqa: B904
|
|
74
|
+
|
|
75
|
+
def thunk(): # type: ignore
|
|
76
|
+
return handle_generate(ctx, req)
|
|
77
|
+
|
|
78
|
+
return await submit_and_maybe_wait(
|
|
79
|
+
ctx,
|
|
80
|
+
worker,
|
|
81
|
+
type="ernie",
|
|
82
|
+
params=req.gen_params() | {"model": spec.name, "mode": req.mode},
|
|
83
|
+
thunk=thunk,
|
|
84
|
+
mode=req.mode,
|
|
85
|
+
accept=accept,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@router.post(
|
|
90
|
+
"/v1/image/ernie/edit",
|
|
91
|
+
responses=build_job_responses(
|
|
92
|
+
"image/png", "image/jpeg", "image/webp", result_model=ImageResponse
|
|
93
|
+
),
|
|
94
|
+
)
|
|
95
|
+
async def edit_ernie_endpoint(
|
|
96
|
+
req: EditRequest,
|
|
97
|
+
accept: str | None = Depends(get_accept),
|
|
98
|
+
ctx: AppContext = Depends(get_ctx),
|
|
99
|
+
worker: Worker = Depends(get_worker),
|
|
100
|
+
) -> Response:
|
|
101
|
+
"""Edit a single input image with a prompt (ERNIE-Image, image-to-image).
|
|
102
|
+
|
|
103
|
+
Takes one `image` (FileRef) plus a `prompt`; `image_strength` controls how
|
|
104
|
+
much of the input is preserved (lower = closer to input). Output must be
|
|
105
|
+
square by default (a guard around an mflux 0.18.0 non-square img2img issue),
|
|
106
|
+
overrideable via `KIAPI_ERNIE_EDIT_REQUIRE_SQUARE=0`. The same endpoint
|
|
107
|
+
serves both `sync` and `async` via `mode`.
|
|
108
|
+
|
|
109
|
+
Sync content negotiation, transient-model behavior (`loras` / `quantize`
|
|
110
|
+
override), and the ImageResponse `result` shape match
|
|
111
|
+
`/v1/image/ernie/generate`.
|
|
112
|
+
"""
|
|
113
|
+
try:
|
|
114
|
+
spec = model_registry.resolve("ernie", req.model)
|
|
115
|
+
except UnknownModelError as exc:
|
|
116
|
+
raise HTTPException(status_code=400, detail=str(exc)) # noqa: B904
|
|
117
|
+
try:
|
|
118
|
+
validate_edit(req, variant=spec.name)
|
|
119
|
+
except ValidationError as exc:
|
|
120
|
+
raise HTTPException(status_code=422, detail=str(exc)) # noqa: B904
|
|
121
|
+
|
|
122
|
+
def thunk(): # type: ignore
|
|
123
|
+
return handle_edit(ctx, req)
|
|
124
|
+
|
|
125
|
+
return await submit_and_maybe_wait(
|
|
126
|
+
ctx,
|
|
127
|
+
worker,
|
|
128
|
+
type="ernie-edit",
|
|
129
|
+
params=req.gen_params() | {"model": spec.name, "mode": req.mode},
|
|
130
|
+
thunk=thunk,
|
|
131
|
+
mode=req.mode,
|
|
132
|
+
accept=accept,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@router.post("/v1/image/ernie/train", responses=build_train_responses())
|
|
137
|
+
async def train_ernie_endpoint(
|
|
138
|
+
req: TrainRequest,
|
|
139
|
+
ctx: AppContext = Depends(get_ctx),
|
|
140
|
+
worker: Worker = Depends(get_worker),
|
|
141
|
+
) -> Response:
|
|
142
|
+
"""Train a LoRA adapter on a captioned image set (ERNIE-Image, always async).
|
|
143
|
+
|
|
144
|
+
Long-running, so this endpoint is always async: it returns 202 with a
|
|
145
|
+
job_id — poll GET /v1/jobs/{job_id}. The `dataset` is a Files-API ZIP whose
|
|
146
|
+
images each have a same-stem `.txt` caption. On success the job's `result`
|
|
147
|
+
holds `adapter_file_id` (the trained `.safetensors`, also the artifact),
|
|
148
|
+
`adapter_bytes`, `num_images`, the resolved `config`, `lora_targets`, and
|
|
149
|
+
`timings`; the adapter can then be passed back via `loras` on generate/edit.
|
|
150
|
+
"""
|
|
151
|
+
try:
|
|
152
|
+
spec = model_registry.resolve("ernie", req.model)
|
|
153
|
+
except UnknownModelError as exc:
|
|
154
|
+
raise HTTPException(status_code=400, detail=str(exc)) # noqa: B904
|
|
155
|
+
if (
|
|
156
|
+
isinstance(req.dataset, FileIDRef)
|
|
157
|
+
and ctx.file_store.get(req.dataset.file_id) is None
|
|
158
|
+
):
|
|
159
|
+
raise HTTPException(
|
|
160
|
+
status_code=400, detail=f"unknown dataset file_id {req.dataset.file_id!r}"
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
def thunk(): # type: ignore
|
|
164
|
+
return handle_train(ctx, req)
|
|
165
|
+
|
|
166
|
+
return await submit_and_maybe_wait(
|
|
167
|
+
ctx,
|
|
168
|
+
worker,
|
|
169
|
+
type="ernie-train",
|
|
170
|
+
params={
|
|
171
|
+
"model": spec.name,
|
|
172
|
+
"dataset": req.dataset.model_dump(mode="json"),
|
|
173
|
+
"num_epochs": req.num_epochs,
|
|
174
|
+
"lora_rank": req.lora_rank,
|
|
175
|
+
},
|
|
176
|
+
thunk=thunk,
|
|
177
|
+
mode="async",
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
register_capability_endpoints(router, name="ernie", base_path="/v1/image/ernie")
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""``/v1/image/flux2/{generate,edit}`` result payload (the Job ``result`` shape).
|
|
2
|
+
|
|
3
|
+
Mirrors the dict returned by ``capabilities/flux2/_models/flux2._store_image`` so
|
|
4
|
+
the produced image result is self-describing in OpenAPI. It is an output-side
|
|
5
|
+
projection of the model result (not a model-coupled view), so it lives under
|
|
6
|
+
``api/image/flux2/_views``. ``generate`` and ``edit`` produce the same shape, so
|
|
7
|
+
both endpoints share this one view.
|
|
8
|
+
|
|
9
|
+
``ImageResponse`` is the sole public element; nested pieces stay private.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
from pydantic import BaseModel, Field
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class _Timings(BaseModel):
|
|
18
|
+
total_s: float = Field(
|
|
19
|
+
description="Wall-clock generation time in seconds (model run only)."
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ImageResponse(BaseModel):
|
|
24
|
+
"""Capability-specific ``result`` for a succeeded flux2 generate/edit job."""
|
|
25
|
+
|
|
26
|
+
model: str = Field(
|
|
27
|
+
description=(
|
|
28
|
+
"Resolved model variant that produced the image "
|
|
29
|
+
"(klein-9b | klein-base-4b | klein-base-9b)."
|
|
30
|
+
)
|
|
31
|
+
)
|
|
32
|
+
prompt: str = Field(description="The prompt used for the run.")
|
|
33
|
+
|
|
34
|
+
file_id: str = Field(
|
|
35
|
+
description=(
|
|
36
|
+
"Files-API id of the produced image. Fetch metadata at "
|
|
37
|
+
"GET /v1/files/{id} or bytes at /download. This is also the artifact "
|
|
38
|
+
"returned as raw bytes by a single-artifact sync call."
|
|
39
|
+
)
|
|
40
|
+
)
|
|
41
|
+
image_bytes: int = Field(description="Size of the produced image in bytes.")
|
|
42
|
+
|
|
43
|
+
width: int = Field(description="Width in pixels of the produced image.")
|
|
44
|
+
height: int = Field(description="Height in pixels of the produced image.")
|
|
45
|
+
|
|
46
|
+
params: dict[str, Any] = Field(
|
|
47
|
+
description=(
|
|
48
|
+
"Resolved parameters actually used for the run (model, seed, steps, "
|
|
49
|
+
"guidance, quantize, scheduler, format, quality, loras, …), so the "
|
|
50
|
+
"result is reproducible."
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
timings: _Timings = Field(description="kiapi extension: server-side timing.")
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"""Image API (flux2): FLUX.2 generate/edit/train."""
|
|
2
|
+
|
|
3
|
+
from fastapi import APIRouter, Depends, HTTPException
|
|
4
|
+
from fastapi.responses import Response
|
|
5
|
+
|
|
6
|
+
from kiapi.api import (
|
|
7
|
+
REQUIRE_AUTH,
|
|
8
|
+
build_job_responses,
|
|
9
|
+
build_train_responses,
|
|
10
|
+
get_accept,
|
|
11
|
+
get_ctx,
|
|
12
|
+
get_worker,
|
|
13
|
+
register_capability_endpoints,
|
|
14
|
+
submit_and_maybe_wait,
|
|
15
|
+
)
|
|
16
|
+
from kiapi.capabilities.flux2 import (
|
|
17
|
+
EditRequest,
|
|
18
|
+
GenerateRequest,
|
|
19
|
+
TrainRequest,
|
|
20
|
+
ValidationError,
|
|
21
|
+
handle_edit,
|
|
22
|
+
handle_generate,
|
|
23
|
+
handle_train,
|
|
24
|
+
settings_manager,
|
|
25
|
+
validate_edit,
|
|
26
|
+
validate_generate,
|
|
27
|
+
)
|
|
28
|
+
from kiapi.core.app import AppContext
|
|
29
|
+
from kiapi.core.file import FileIDRef
|
|
30
|
+
from kiapi.core.model import UnknownModelError, model_registry
|
|
31
|
+
from kiapi.core.worker import Worker
|
|
32
|
+
|
|
33
|
+
from ._views.image_response import ImageResponse
|
|
34
|
+
|
|
35
|
+
router = APIRouter(dependencies=REQUIRE_AUTH)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@router.post(
|
|
39
|
+
"/v1/image/flux2/generate",
|
|
40
|
+
responses=build_job_responses(
|
|
41
|
+
"image/png", "image/jpeg", "image/webp", result_model=ImageResponse
|
|
42
|
+
),
|
|
43
|
+
)
|
|
44
|
+
async def generate_flux2_endpoint(
|
|
45
|
+
req: GenerateRequest,
|
|
46
|
+
accept: str | None = Depends(get_accept),
|
|
47
|
+
ctx: AppContext = Depends(get_ctx),
|
|
48
|
+
worker: Worker = Depends(get_worker),
|
|
49
|
+
) -> Response:
|
|
50
|
+
"""Generate an image from a text prompt (FLUX.2 Klein, text-to-image / img2img).
|
|
51
|
+
|
|
52
|
+
Plain text-to-image by default; supply `init_image` (+ optional
|
|
53
|
+
`image_strength`) to run img2img instead — use `/v1/image/flux2/edit` for
|
|
54
|
+
multi-reference editing. The same endpoint serves both `sync` and `async` via
|
|
55
|
+
`mode`. Variant defaults differ: `klein-9b` (default) is distilled and fast
|
|
56
|
+
(few steps, unquantized); `klein-base-4b` / `klein-base-9b` are slower base
|
|
57
|
+
variants (more steps, q8).
|
|
58
|
+
|
|
59
|
+
Sync content negotiation: a single image is produced, so unless the client
|
|
60
|
+
asks for JSON the raw image bytes are returned with `X-Kiapi-File-Id` /
|
|
61
|
+
`X-Kiapi-Job-Id` headers — `curl -o out.png` just works. With
|
|
62
|
+
`Accept: application/json` (or async) the Job JSON is returned, whose
|
|
63
|
+
`result` follows ImageResponse.
|
|
64
|
+
|
|
65
|
+
Any `loras` or a `quantize` differing from the resident model runs a one-off
|
|
66
|
+
transient model (slower, not reused). Async returns 202 immediately; poll
|
|
67
|
+
GET /v1/jobs/{job_id} and fetch the artifact via GET /v1/files/{file_id}.
|
|
68
|
+
"""
|
|
69
|
+
try:
|
|
70
|
+
spec = model_registry.resolve("flux2", req.model)
|
|
71
|
+
except UnknownModelError as exc:
|
|
72
|
+
raise HTTPException(status_code=400, detail=str(exc)) # noqa: B904
|
|
73
|
+
try:
|
|
74
|
+
validate_generate(req, variant=spec.name)
|
|
75
|
+
except ValidationError as exc:
|
|
76
|
+
raise HTTPException(status_code=422, detail=str(exc)) # noqa: B904
|
|
77
|
+
|
|
78
|
+
def thunk(): # type: ignore
|
|
79
|
+
return handle_generate(ctx, req)
|
|
80
|
+
|
|
81
|
+
return await submit_and_maybe_wait(
|
|
82
|
+
ctx,
|
|
83
|
+
worker,
|
|
84
|
+
type="flux2",
|
|
85
|
+
params=req.gen_params() | {"model": spec.name, "mode": req.mode},
|
|
86
|
+
thunk=thunk,
|
|
87
|
+
mode=req.mode,
|
|
88
|
+
accept=accept,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@router.post(
|
|
93
|
+
"/v1/image/flux2/edit",
|
|
94
|
+
responses=build_job_responses(
|
|
95
|
+
"image/png", "image/jpeg", "image/webp", result_model=ImageResponse
|
|
96
|
+
),
|
|
97
|
+
)
|
|
98
|
+
async def edit_flux2_endpoint(
|
|
99
|
+
req: EditRequest,
|
|
100
|
+
accept: str | None = Depends(get_accept),
|
|
101
|
+
ctx: AppContext = Depends(get_ctx),
|
|
102
|
+
worker: Worker = Depends(get_worker),
|
|
103
|
+
) -> Response:
|
|
104
|
+
"""Edit / combine one or more reference images with a prompt (FLUX.2 Klein).
|
|
105
|
+
|
|
106
|
+
Takes a list of `images` (FileRefs, multi-reference editing) plus a `prompt`;
|
|
107
|
+
`image_strength` controls how much of the input is preserved (lower = closer
|
|
108
|
+
to input). For plain image-to-image from a single seed image, use `init_image`
|
|
109
|
+
on `/v1/image/flux2/generate` instead. The same endpoint serves both `sync`
|
|
110
|
+
and `async` via `mode`.
|
|
111
|
+
|
|
112
|
+
Sync content negotiation, transient-model behavior (`loras` / `quantize`
|
|
113
|
+
override), and the ImageResponse `result` shape match
|
|
114
|
+
`/v1/image/flux2/generate`.
|
|
115
|
+
"""
|
|
116
|
+
try:
|
|
117
|
+
spec = model_registry.resolve("flux2", req.model)
|
|
118
|
+
except UnknownModelError as exc:
|
|
119
|
+
raise HTTPException(status_code=400, detail=str(exc)) # noqa: B904
|
|
120
|
+
try:
|
|
121
|
+
validate_edit(req, variant=spec.name)
|
|
122
|
+
except ValidationError as exc:
|
|
123
|
+
raise HTTPException(status_code=422, detail=str(exc)) # noqa: B904
|
|
124
|
+
|
|
125
|
+
def thunk(): # type: ignore
|
|
126
|
+
return handle_edit(ctx, req)
|
|
127
|
+
|
|
128
|
+
return await submit_and_maybe_wait(
|
|
129
|
+
ctx,
|
|
130
|
+
worker,
|
|
131
|
+
type="flux2-edit",
|
|
132
|
+
params=req.gen_params() | {"model": spec.name, "mode": req.mode},
|
|
133
|
+
thunk=thunk,
|
|
134
|
+
mode=req.mode,
|
|
135
|
+
accept=accept,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@router.post("/v1/image/flux2/train", responses=build_train_responses())
|
|
140
|
+
async def train_flux2_endpoint(
|
|
141
|
+
req: TrainRequest,
|
|
142
|
+
ctx: AppContext = Depends(get_ctx),
|
|
143
|
+
worker: Worker = Depends(get_worker),
|
|
144
|
+
) -> Response:
|
|
145
|
+
"""Train a LoRA adapter on an image dataset (FLUX.2 Klein base, always async).
|
|
146
|
+
|
|
147
|
+
Long-running, so this endpoint is always async: it returns 202 with a
|
|
148
|
+
job_id — poll GET /v1/jobs/{job_id}. Only the base variants
|
|
149
|
+
(`klein-base-4b` default, `klein-base-9b`) are trainable. `training_mode`
|
|
150
|
+
selects the dataset layout: `text` uses captioned images (same-stem `.txt`),
|
|
151
|
+
`edit` uses `*_in.*` / `*_out.*` pairs with `*_in.txt` prompts; the `dataset`
|
|
152
|
+
is a Files-API ZIP. On success the job's `result` holds `adapter_file_id`
|
|
153
|
+
(the trained `.safetensors`, also the artifact), `adapter_bytes`,
|
|
154
|
+
`training_mode`, the resolved `config`, `lora_targets`, `checkpoint`, and
|
|
155
|
+
`timings`; the adapter can then be passed back via `loras` on generate/edit.
|
|
156
|
+
"""
|
|
157
|
+
settings = settings_manager.get_settings()
|
|
158
|
+
|
|
159
|
+
try:
|
|
160
|
+
spec = model_registry.resolve(
|
|
161
|
+
"flux2", req.model or settings.train_default_model
|
|
162
|
+
)
|
|
163
|
+
except UnknownModelError as exc:
|
|
164
|
+
raise HTTPException(status_code=400, detail=str(exc)) # noqa: B904
|
|
165
|
+
if "base" not in spec.name:
|
|
166
|
+
raise HTTPException(
|
|
167
|
+
status_code=400,
|
|
168
|
+
detail="Flux2 training requires klein-base-4b or klein-base-9b",
|
|
169
|
+
)
|
|
170
|
+
if (
|
|
171
|
+
isinstance(req.dataset, FileIDRef)
|
|
172
|
+
and ctx.file_store.get(req.dataset.file_id) is None
|
|
173
|
+
):
|
|
174
|
+
raise HTTPException(
|
|
175
|
+
status_code=400, detail=f"unknown dataset file_id {req.dataset.file_id!r}"
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
def thunk(): # type: ignore
|
|
179
|
+
return handle_train(ctx, req)
|
|
180
|
+
|
|
181
|
+
return await submit_and_maybe_wait(
|
|
182
|
+
ctx,
|
|
183
|
+
worker,
|
|
184
|
+
type="flux2-train",
|
|
185
|
+
params={
|
|
186
|
+
"model": spec.name,
|
|
187
|
+
"dataset": req.dataset.model_dump(mode="json"),
|
|
188
|
+
"training_mode": req.training_mode,
|
|
189
|
+
"num_epochs": req.num_epochs,
|
|
190
|
+
"lora_rank": req.lora_rank,
|
|
191
|
+
},
|
|
192
|
+
thunk=thunk,
|
|
193
|
+
mode="async",
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
register_capability_endpoints(router, name="flux2", base_path="/v1/image/flux2")
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""``/v1/image/ideogram4/generate`` result payload (the Job ``result`` shape).
|
|
2
|
+
|
|
3
|
+
Mirrors the dict returned by ``capabilities/ideogram4/_models/ideogram4._store_image``
|
|
4
|
+
so the produced image result is self-describing in OpenAPI. It is an output-side
|
|
5
|
+
projection of the model result (not a model-coupled view), so it lives under
|
|
6
|
+
``api/image/ideogram4/_views``.
|
|
7
|
+
|
|
8
|
+
``ImageResponse`` is the sole public element; nested pieces stay private.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from pydantic import BaseModel, Field
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class _Timings(BaseModel):
|
|
17
|
+
total_s: float = Field(
|
|
18
|
+
description="Wall-clock generation time in seconds (model run only)."
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ImageResponse(BaseModel):
|
|
23
|
+
"""Capability-specific ``result`` for a succeeded ideogram4 generate job."""
|
|
24
|
+
|
|
25
|
+
model: str = Field(description="Resolved model variant that produced the image.")
|
|
26
|
+
prompt: str | dict[str, Any] = Field(
|
|
27
|
+
description="The prompt used for the run (plain text or JSON caption)."
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
file_id: str = Field(
|
|
31
|
+
description=(
|
|
32
|
+
"Files-API id of the produced image. Fetch metadata at "
|
|
33
|
+
"GET /v1/files/{id} or bytes at /download. This is also the artifact "
|
|
34
|
+
"returned as raw bytes by a single-artifact sync call."
|
|
35
|
+
)
|
|
36
|
+
)
|
|
37
|
+
image_bytes: int = Field(description="Size of the produced image in bytes.")
|
|
38
|
+
|
|
39
|
+
width: int = Field(description="Width in pixels of the produced image.")
|
|
40
|
+
height: int = Field(description="Height in pixels of the produced image.")
|
|
41
|
+
|
|
42
|
+
params: dict[str, Any] = Field(
|
|
43
|
+
description=(
|
|
44
|
+
"Resolved parameters actually used for the run (model, prompt, preset, "
|
|
45
|
+
"seed, width, height, quantize, format, quality, …), so the result is "
|
|
46
|
+
"reproducible."
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
safety_filter_note: str = Field(
|
|
50
|
+
description=(
|
|
51
|
+
"Reminder that Ideogram 4 may return an 'Image blocked by safety filter' "
|
|
52
|
+
"image, which kiapi stores as the artifact rather than raising an error."
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
timings: _Timings = Field(description="kiapi extension: server-side timing.")
|