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,806 @@
|
|
|
1
|
+
# chat
|
|
2
|
+
|
|
3
|
+
**English** | [日本語](README.ja.md)
|
|
4
|
+
|
|
5
|
+
[mlx-vlm](https://github.com/Blaizzy/mlx-vlm) provides an OpenAI-compatible chat completion API.
|
|
6
|
+
|
|
7
|
+
- **vlm** (text + image):
|
|
8
|
+
- Qwen3.6-27B-4bit
|
|
9
|
+
- **omni** (text + image + audio + video):
|
|
10
|
+
- Qwen3-Omni-30B-A3B-Instruct-4bit
|
|
11
|
+
|
|
12
|
+
It supports the following functions.
|
|
13
|
+
|
|
14
|
+
- streaming
|
|
15
|
+
- tool call
|
|
16
|
+
- tool choice (auto, any, specific)
|
|
17
|
+
- parallel tool calls
|
|
18
|
+
|
|
19
|
+
## API
|
|
20
|
+
|
|
21
|
+
| Endpoint | Name | Description |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| `POST /v1/chat/completions` | Chat Completions | OpenAI-compatible Chat Completions API. |
|
|
24
|
+
| `GET /v1/models` | Model list | Returns a list of available models. |
|
|
25
|
+
| `GET /v1/chat/openapi.json` | OpenAPI | Returns detailed input/output specifications, usage, and TIPS. |
|
|
26
|
+
|
|
27
|
+
- Unique extensions:
|
|
28
|
+
- `fps`: Conversion frame rate of video
|
|
29
|
+
- `use_audio_in_video`: Whether to include audio in video in model input
|
|
30
|
+
|
|
31
|
+
## API Docs
|
|
32
|
+
|
|
33
|
+
- [OpenAPI JSON](https://kiarina.github.io/kiapi/v1/chat/openapi.json)
|
|
34
|
+
- [Swagger UI](https://kiarina.github.io/kiapi/v1/chat/docs.html)
|
|
35
|
+
- [ReDoc](https://kiarina.github.io/kiapi/v1/chat/redoc.html)
|
|
36
|
+
|
|
37
|
+
## Dependencies
|
|
38
|
+
|
|
39
|
+
| Package | License | Description |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| [mlx-vlm](https://github.com/Blaizzy/mlx-vlm) | MIT | Drive Qwen multimodal models on MLX. |
|
|
42
|
+
|
|
43
|
+
## Models
|
|
44
|
+
|
|
45
|
+
| Model | License | Terms | Size | Description |
|
|
46
|
+
|---|---|---|---:|---|
|
|
47
|
+
| [mlx-community/Qwen3-Omni-30B-A3B-Instruct-4bit](https://huggingface.co/mlx-community/Qwen3-Omni-30B-A3B-Instruct-4bit) | Apache-2.0 | Not required | 21.8 GB | `qwen3-omni` (default). text + image + audio + video, tool-call prefill=JSON. Talker (audio *output*) is private and only outputs text/tool-calls. Maximum of **1** audio input per request (including demux audio for video with audio). |
|
|
48
|
+
| [mlx-community/Qwen3.6-27B-4bit](https://huggingface.co/mlx-community/Qwen3.6-27B-4bit) | Apache-2.0 | Not required | 16.1 GB | `qwen3.6-27b`. text + image only, tool-call prefill=Hermes/XML. Reasoning is OFF by default. |
|
|
49
|
+
|
|
50
|
+
- **HTTP 400** when sending a part of a modality that is not supported by the selected model.
|
|
51
|
+
|
|
52
|
+
## Notes
|
|
53
|
+
|
|
54
|
+
Chat is implemented using **mlx-vlm**, but some patches have been added to avoid bugs.
|
|
55
|
+
Please be aware that this patch may break with updates to **mlx-vlm**.
|
|
56
|
+
|
|
57
|
+
**mlx-vlm** is fixed to `mlx-vlm==0.6.3`.
|
|
58
|
+
When updating, please reconfirm the contents of the patch below and make corrections as necessary.
|
|
59
|
+
Details are in the docstring.
|
|
60
|
+
|
|
61
|
+
| # | Contents | Location | Target models |
|
|
62
|
+
|---|------|------|------------|
|
|
63
|
+
| A | Pass audio as a float32 array instead of a path | `_models/qwen3_omni.py` | omni |
|
|
64
|
+
| B | Avoid stereo audio resampling inconsistency by loading it yourself | `_utils/load_audio_mono.py` | omni |
|
|
65
|
+
| C | `mx.where` / `mx.scatter` shim for mlx 0.31.x | `_models/qwen3_omni.py` `_ensure_mlx_compat` | omni (image+video simultaneously) |
|
|
66
|
+
| E | UTF-8 decoding relaxation for streaming detokenizer | `_operations/ensure_streaming_detokenizer_compat.py` | Both models (stream) |
|
|
67
|
+
| F | Text recovery from token ID (stream) | `_operations/stream_text_from_tokens.py` | qwen3.6 (stream) |
|
|
68
|
+
|
|
69
|
+
**A. Pass the audio as a float32 array:**
|
|
70
|
+
- **Location**: `run`(`audio_arrays = [load_audio_mono(p, sr=sr) ...]`) in `_models/qwen3_omni.py`
|
|
71
|
+
- **Reason**: The qwen3-omni branch of mlx-vlm fails when it receives the raw audio **path**
|
|
72
|
+
Crash with `could not convert string to float`. `generate(audio=...)` has
|
|
73
|
+
You need to pass ndarray.
|
|
74
|
+
- **Trigger**: All cases where omni has audio input.
|
|
75
|
+
|
|
76
|
+
**B. Stereo audio resample mismatch:**
|
|
77
|
+
- **Location**: `_utils/load_audio_mono.py` (Load the array of A using this own function)
|
|
78
|
+
- **Reason**: There is a bug in `utils.load_audio` of mlx-vlm. `read_audio` reads the audio
|
|
79
|
+
`(samples, channels)` (channel last) is returned, but `load_audio` is
|
|
80
|
+
- Resample to `resample_audio(..., axis=-1)` = **channel axis**,
|
|
81
|
+
- Downmix `mean(axis=1)` = same channel axis
|
|
82
|
+
The handling of the axis is inconsistent. The result is **stereo audio with different rates** (typically
|
|
83
|
+
48kHz / 44.1kHz stereo wav), the time axis is not resampled, and the 48kHz sample is
|
|
84
|
+
It is passed to omni as 16kHz, and the audio cannot be recognized. Mono is one dimensional
|
|
85
|
+
`axis=-1` happens to be the time axis, so it works correctly.
|
|
86
|
+
- **Workaround**: `load_audio_mono` **converts to monaural first and then resamples**, so
|
|
87
|
+
The default `axis=-1` of `resample_audio` is always the time axis and rate conversion is performed correctly.
|
|
88
|
+
(48k mono / 48k stereo / 44.1k stereo / 16k stereo all to 16000 samples).
|
|
89
|
+
- **Impact on audio in video**: None. `_extract_audio` in `_operations/parse_messages.py`
|
|
90
|
+
To demux to monaural 16kHz from the beginning with ffmpeg `-ac 1 -ar 16000`,
|
|
91
|
+
Resample/downmix itself does not occur and does not fall under the bug condition.
|
|
92
|
+
|
|
93
|
+
**C. mlx 0.31.x compatible shim (`mx.where` / `mx.scatter`):**
|
|
94
|
+
- **Location**: `_ensure_mlx_compat` in `_models/qwen3_omni.py` (called at the beginning of `run`)
|
|
95
|
+
- **Reason**: `qwen3_omni_moe/thinker.py` of mlx-vlm does not support **image + video at the same time.
|
|
96
|
+
Input route** (visual_embeds_multiscale / deepstack join), present in mlx 0.31.x
|
|
97
|
+
Use APIs that do not:
|
|
98
|
+
- 1 argument format `mx.where(mask)[0]` (get index of True) → TypeError
|
|
99
|
+
- Free function `mx.scatter(a, idx, vals, ax)` → AttributeError
|
|
100
|
+
|
|
101
|
+
There is no problem with image alone/video alone using a different route. Do not rewrite site-packages and provide a compatible implementation.
|
|
102
|
+
Avoid by grafting (idempotent/additive, no effect on other routes).
|
|
103
|
+
- **Trigger**: Only when image and video are passed to omni **at the same time**.
|
|
104
|
+
|
|
105
|
+
**E. UTF-8 decoding relaxation for streaming detokenizer:**
|
|
106
|
+
- **Location**: `_operations/ensure_streaming_detokenizer_compat.py` (called via stream route)
|
|
107
|
+
- **Reason**: `BPEStreamingDetokenizer.add_token` of mlx-vlm is
|
|
108
|
+
Decode bytes using **strict UTF-8**. Invalid UTF-8 at flash boundaries
|
|
109
|
+
Byte token string causes streaming response to crash. On the `finalize` side,
|
|
110
|
+
The streaming route is also `errors="replace"` because it handles the same decoding tolerantly.
|
|
111
|
+
Equivalently mitigate.
|
|
112
|
+
- **Trigger**: `stream=true` for both models.
|
|
113
|
+
|
|
114
|
+
**F. Text recovery from token ID (qwen3.6 stream):**
|
|
115
|
+
- **Location**: `_operations/stream_text_from_tokens.py`
|
|
116
|
+
- **Reason**: More of a compatibility wrapper than a bug avoidance. `_ServerTokenStreamer` / in mlx-vlm
|
|
117
|
+
If `make_streaming_detokenizer` is available, it will extract the text from the token ID.
|
|
118
|
+
Restore. If it is not available, pass through (`yield from chunks`).
|
|
119
|
+
|
|
120
|
+
## Quickstart
|
|
121
|
+
```bash
|
|
122
|
+
MODEL=qwen3.6-27b
|
|
123
|
+
MODEL=qwen3-omni
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### text
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
jq -n \
|
|
130
|
+
--arg model "$MODEL" \
|
|
131
|
+
'{
|
|
132
|
+
model: $model,
|
|
133
|
+
messages: [
|
|
134
|
+
{role: "user", content: "こんにちは"}
|
|
135
|
+
]
|
|
136
|
+
}' |
|
|
137
|
+
curl -sS "http://localhost:${PORT:-8000}/v1/chat/completions" \
|
|
138
|
+
-H 'Content-Type: application/json' \
|
|
139
|
+
--data-binary @- |
|
|
140
|
+
jq -r '.choices[0].message.content'
|
|
141
|
+
# こんにちは!何かお手伝いできることはありますか?
|
|
142
|
+
```
|
|
143
|
+
Streaming:
|
|
144
|
+
```sh
|
|
145
|
+
jq -n \
|
|
146
|
+
--arg model "$MODEL" \
|
|
147
|
+
'{
|
|
148
|
+
model: $model,
|
|
149
|
+
stream: true,
|
|
150
|
+
messages: [
|
|
151
|
+
{role: "user", content: "日本の首都はどこ?一言で。"}
|
|
152
|
+
]
|
|
153
|
+
}' |
|
|
154
|
+
curl -N "http://localhost:${PORT:-8000}/v1/chat/completions" \
|
|
155
|
+
-H 'Content-Type: application/json' \
|
|
156
|
+
--data-binary @-
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### max_completion_tokens
|
|
160
|
+
|
|
161
|
+
```sh
|
|
162
|
+
jq -n \
|
|
163
|
+
--arg model "$MODEL" \
|
|
164
|
+
'{
|
|
165
|
+
model: $model,
|
|
166
|
+
messages: [
|
|
167
|
+
{role: "user", content: "python について説明してください。"}
|
|
168
|
+
],
|
|
169
|
+
max_completion_tokens: 50
|
|
170
|
+
}' |
|
|
171
|
+
curl -sS http://localhost:${PORT:-8000}/v1/chat/completions \
|
|
172
|
+
-H 'Content-Type: application/json' \
|
|
173
|
+
--data-binary @- |
|
|
174
|
+
jq -r '.choices[0].message.content'
|
|
175
|
+
# Python(パイソン)は、世界で最も人気のある汎用プログラミング言語の一つです。その最大の特徴は**「書きやすさ」と「読みやすさ」**であり、初心者からプロのエンジニアまで幅広く使われています。
|
|
176
|
+
#
|
|
177
|
+
# 以下に、
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### tool_call
|
|
181
|
+
|
|
182
|
+
```sh
|
|
183
|
+
jq -n \
|
|
184
|
+
--arg model "$MODEL" \
|
|
185
|
+
'{
|
|
186
|
+
model: $model,
|
|
187
|
+
messages: [
|
|
188
|
+
{role: "user", content: "東京と大阪の天気は?タイマーを30秒にセットして。"}
|
|
189
|
+
],
|
|
190
|
+
tools: [
|
|
191
|
+
{
|
|
192
|
+
type: "function",
|
|
193
|
+
function: {
|
|
194
|
+
name: "get_weather",
|
|
195
|
+
parameters: {
|
|
196
|
+
type: "object",
|
|
197
|
+
properties: {
|
|
198
|
+
location: {type: "string"}
|
|
199
|
+
},
|
|
200
|
+
required: ["location"]
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
type: "function",
|
|
206
|
+
function: {
|
|
207
|
+
name: "set_timer",
|
|
208
|
+
parameters: {
|
|
209
|
+
type: "object",
|
|
210
|
+
properties: {
|
|
211
|
+
seconds: {type: "integer"}
|
|
212
|
+
},
|
|
213
|
+
required: ["seconds"]
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
]
|
|
218
|
+
}' |
|
|
219
|
+
curl -sS http://localhost:${PORT:-8000}/v1/chat/completions \
|
|
220
|
+
-H 'Content-Type: application/json' \
|
|
221
|
+
--data-binary @- |
|
|
222
|
+
jq '.choices[0].message.tool_calls'
|
|
223
|
+
# [
|
|
224
|
+
# {
|
|
225
|
+
# "id": "call_5bf5c0b6ecbd4944bfaba514",
|
|
226
|
+
# "type": "function",
|
|
227
|
+
# "function": {
|
|
228
|
+
# "name": "get_weather",
|
|
229
|
+
# "arguments": "{\"location\": \"東京\"}"
|
|
230
|
+
# }
|
|
231
|
+
# },
|
|
232
|
+
# {
|
|
233
|
+
# "id": "call_9f98db50e2ec4d1898710972",
|
|
234
|
+
# "type": "function",
|
|
235
|
+
# "function": {
|
|
236
|
+
# "name": "get_weather",
|
|
237
|
+
# "arguments": "{\"location\": \"大阪\"}"
|
|
238
|
+
# }
|
|
239
|
+
# },
|
|
240
|
+
# {
|
|
241
|
+
# "id": "call_786091eb2e2547b29eb96b35",
|
|
242
|
+
# "type": "function",
|
|
243
|
+
# "function": {
|
|
244
|
+
# "name": "set_timer",
|
|
245
|
+
# "arguments": "{\"seconds\": 30}"
|
|
246
|
+
# }
|
|
247
|
+
# }
|
|
248
|
+
# ]
|
|
249
|
+
```
|
|
250
|
+
### tool_choice
|
|
251
|
+
|
|
252
|
+
tool_choice can be specified in the following 3 patterns.
|
|
253
|
+
- `auto`: Let the model select the tool (default)
|
|
254
|
+
- `any` | `required`: Force tool selection (if there are multiple tools, the model will choose)
|
|
255
|
+
- `{"type":"function","function":{"name":...}}`: Force a specific tool call
|
|
256
|
+
|
|
257
|
+
#### auto
|
|
258
|
+
```sh
|
|
259
|
+
jq -n \
|
|
260
|
+
--arg model "$MODEL" \
|
|
261
|
+
'{
|
|
262
|
+
model: $model,
|
|
263
|
+
messages: [
|
|
264
|
+
{role: "user", content: "こんにちは"}
|
|
265
|
+
],
|
|
266
|
+
tools: [
|
|
267
|
+
{
|
|
268
|
+
type: "function",
|
|
269
|
+
function: {
|
|
270
|
+
name: "get_weather",
|
|
271
|
+
parameters: {
|
|
272
|
+
type: "object",
|
|
273
|
+
properties: {
|
|
274
|
+
location: {type: "string"}
|
|
275
|
+
},
|
|
276
|
+
required: ["location"]
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
type: "function",
|
|
282
|
+
function: {
|
|
283
|
+
name: "set_timer",
|
|
284
|
+
parameters: {
|
|
285
|
+
type: "object",
|
|
286
|
+
properties: {
|
|
287
|
+
seconds: {type: "integer"}
|
|
288
|
+
},
|
|
289
|
+
required: ["seconds"]
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
]
|
|
294
|
+
}' |
|
|
295
|
+
curl -sS http://localhost:${PORT:-8000}/v1/chat/completions \
|
|
296
|
+
-H 'Content-Type: application/json' \
|
|
297
|
+
--data-binary @- |
|
|
298
|
+
jq '.choices[0].message'
|
|
299
|
+
# {
|
|
300
|
+
# "role": "assistant",
|
|
301
|
+
# "content": "こんにちは!今日はどんなお手伝いが必要ですか?"
|
|
302
|
+
# }
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
#### any / required
|
|
306
|
+
|
|
307
|
+
```sh
|
|
308
|
+
jq -n \
|
|
309
|
+
--arg model "$MODEL" \
|
|
310
|
+
'{
|
|
311
|
+
model: $model,
|
|
312
|
+
messages: [
|
|
313
|
+
{role: "user", content: "こんにちは"}
|
|
314
|
+
],
|
|
315
|
+
tools: [
|
|
316
|
+
{
|
|
317
|
+
type: "function",
|
|
318
|
+
function: {
|
|
319
|
+
name: "get_weather",
|
|
320
|
+
parameters: {
|
|
321
|
+
type: "object",
|
|
322
|
+
properties: {
|
|
323
|
+
location: {type: "string"}
|
|
324
|
+
},
|
|
325
|
+
required: ["location"]
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
type: "function",
|
|
331
|
+
function: {
|
|
332
|
+
name: "set_timer",
|
|
333
|
+
parameters: {
|
|
334
|
+
type: "object",
|
|
335
|
+
properties: {
|
|
336
|
+
seconds: {type: "integer"}
|
|
337
|
+
},
|
|
338
|
+
required: ["seconds"]
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
],
|
|
343
|
+
tool_choice: "any"
|
|
344
|
+
}' |
|
|
345
|
+
curl -sS http://localhost:${PORT:-8000}/v1/chat/completions \
|
|
346
|
+
-H 'Content-Type: application/json' \
|
|
347
|
+
--data-binary @- |
|
|
348
|
+
jq '.choices[0].message'
|
|
349
|
+
# {
|
|
350
|
+
# "role": "assistant",
|
|
351
|
+
# "content": null,
|
|
352
|
+
# "tool_calls": [
|
|
353
|
+
# {
|
|
354
|
+
# "id": "call_d9fc6f940c23476c98e2b2a8",
|
|
355
|
+
# "type": "function",
|
|
356
|
+
# "function": {
|
|
357
|
+
# "name": "get_weather",
|
|
358
|
+
# "arguments": "{\"location\": \"Tokyo\"}"
|
|
359
|
+
# }
|
|
360
|
+
# }
|
|
361
|
+
# ]
|
|
362
|
+
# }
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
#### specific
|
|
366
|
+
|
|
367
|
+
```sh
|
|
368
|
+
jq -n \
|
|
369
|
+
--arg model "$MODEL" \
|
|
370
|
+
'{
|
|
371
|
+
model: $model,
|
|
372
|
+
messages: [
|
|
373
|
+
{role: "user", content: "こんにちは"}
|
|
374
|
+
],
|
|
375
|
+
tools: [
|
|
376
|
+
{
|
|
377
|
+
type: "function",
|
|
378
|
+
function: {
|
|
379
|
+
name: "get_weather",
|
|
380
|
+
parameters: {
|
|
381
|
+
type: "object",
|
|
382
|
+
properties: {
|
|
383
|
+
location: {type: "string"}
|
|
384
|
+
},
|
|
385
|
+
required: ["location"]
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
type: "function",
|
|
391
|
+
function: {
|
|
392
|
+
name: "set_timer",
|
|
393
|
+
parameters: {
|
|
394
|
+
type: "object",
|
|
395
|
+
properties: {
|
|
396
|
+
seconds: {type: "integer"}
|
|
397
|
+
},
|
|
398
|
+
required: ["seconds"]
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
],
|
|
403
|
+
tool_choice: {
|
|
404
|
+
type: "function",
|
|
405
|
+
function: {name: "get_weather"}
|
|
406
|
+
}
|
|
407
|
+
}' |
|
|
408
|
+
curl -sS http://localhost:${PORT:-8000}/v1/chat/completions \
|
|
409
|
+
-H 'Content-Type: application/json' \
|
|
410
|
+
--data-binary @- |
|
|
411
|
+
jq '.choices[0].message'
|
|
412
|
+
# {
|
|
413
|
+
# "role": "assistant",
|
|
414
|
+
# "content": null,
|
|
415
|
+
# "tool_calls": [
|
|
416
|
+
# {
|
|
417
|
+
# "id": "call_b4df9a6d995c4735b8f10387",
|
|
418
|
+
# "type": "function",
|
|
419
|
+
# "function": {
|
|
420
|
+
# "name": "get_weather",
|
|
421
|
+
# "arguments": "{\"location\": \"Tokyo\"}"
|
|
422
|
+
# }
|
|
423
|
+
# }
|
|
424
|
+
# ]
|
|
425
|
+
# }
|
|
426
|
+
```
|
|
427
|
+
> [!NOTE]
|
|
428
|
+
> any/required or specific calls the tool regardless of context
|
|
429
|
+
> If you only have tools that are too out of context, `qwen3-omni` in particular tends to generate incorrect responses
|
|
430
|
+
|
|
431
|
+
### parallel_tool_calls
|
|
432
|
+
|
|
433
|
+
parallel_tool_calls defaults to `true`.
|
|
434
|
+
If you want to force a single tool call, specify `parallel_tool_calls: false`.
|
|
435
|
+
```sh
|
|
436
|
+
jq -n \
|
|
437
|
+
--arg model "$MODEL" \
|
|
438
|
+
'{
|
|
439
|
+
model: $model,
|
|
440
|
+
messages: [
|
|
441
|
+
{role: "user", content: "東京と大阪の天気は?"}
|
|
442
|
+
],
|
|
443
|
+
tools: [
|
|
444
|
+
{
|
|
445
|
+
type: "function",
|
|
446
|
+
function: {
|
|
447
|
+
name: "get_weather",
|
|
448
|
+
parameters: {
|
|
449
|
+
type: "object",
|
|
450
|
+
properties: {
|
|
451
|
+
location: {type: "string"}
|
|
452
|
+
},
|
|
453
|
+
required: ["location"]
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
],
|
|
458
|
+
parallel_tool_calls: false
|
|
459
|
+
}' |
|
|
460
|
+
curl -sS http://localhost:${PORT:-8000}/v1/chat/completions \
|
|
461
|
+
-H 'Content-Type: application/json' \
|
|
462
|
+
--data-binary @- |
|
|
463
|
+
jq '.choices[0].message'
|
|
464
|
+
# {
|
|
465
|
+
# "role": "assistant",
|
|
466
|
+
# "content": null,
|
|
467
|
+
# "tool_calls": [
|
|
468
|
+
# {
|
|
469
|
+
# "id": "call_060acbd57cfe4c4eb8464158",
|
|
470
|
+
# "type": "function",
|
|
471
|
+
# "function": {
|
|
472
|
+
# "name": "get_weather",
|
|
473
|
+
# "arguments": "{\"location\": \"東京\"}"
|
|
474
|
+
# }
|
|
475
|
+
# }
|
|
476
|
+
# ]
|
|
477
|
+
# }
|
|
478
|
+
```
|
|
479
|
+
### continuation
|
|
480
|
+
|
|
481
|
+
Handle multi-turn messages like system, user, assistant, tool, assistant, human...
|
|
482
|
+
```sh
|
|
483
|
+
jq -n \
|
|
484
|
+
--arg model "$MODEL" \
|
|
485
|
+
'{
|
|
486
|
+
model: $model,
|
|
487
|
+
messages: [
|
|
488
|
+
{role: "system", content: "語尾に「にゃ」をつけて答えてください"},
|
|
489
|
+
{role: "user", content: "こんにちは"},
|
|
490
|
+
{role: "assistant", content: "こんにちはにゃ!何かお手伝いできることはありますかにゃ?"},
|
|
491
|
+
{role: "user", content: "今日の天気は?"},
|
|
492
|
+
{role: "assistant", tool_calls: [
|
|
493
|
+
{
|
|
494
|
+
id: "call_123",
|
|
495
|
+
type: "function",
|
|
496
|
+
function: {
|
|
497
|
+
name: "get_weather",
|
|
498
|
+
arguments: "{\"location\": \"Tokyo\"}"
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
]},
|
|
502
|
+
{role: "tool", content: "東京の天気は晴れ、最高気温25度、最低気温15度です。"}
|
|
503
|
+
],
|
|
504
|
+
tools: [
|
|
505
|
+
{
|
|
506
|
+
type: "function",
|
|
507
|
+
function: {
|
|
508
|
+
name: "get_weather",
|
|
509
|
+
parameters: {
|
|
510
|
+
type: "object",
|
|
511
|
+
properties: {
|
|
512
|
+
location: {type: "string"}
|
|
513
|
+
},
|
|
514
|
+
required: ["location"]
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
]
|
|
519
|
+
}' |
|
|
520
|
+
curl -sS http://localhost:${PORT:-8000}/v1/chat/completions \
|
|
521
|
+
-H 'Content-Type: application/json' \
|
|
522
|
+
--data-binary @- |
|
|
523
|
+
jq -r '.choices[0].message'
|
|
524
|
+
# {
|
|
525
|
+
# "role": "assistant",
|
|
526
|
+
# "content": "東京の天気は晴れ、最高気温25度、最低気温15度ですにゃ!"
|
|
527
|
+
# }
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
### image
|
|
531
|
+
|
|
532
|
+
```sh
|
|
533
|
+
jq -n \
|
|
534
|
+
--arg model "$MODEL" \
|
|
535
|
+
--rawfile img <(base64 -i tests/assets/miineko.png | tr -d '\n') \
|
|
536
|
+
'{
|
|
537
|
+
model: $model,
|
|
538
|
+
messages: [
|
|
539
|
+
{role: "user", content: [
|
|
540
|
+
{type: "image_url", image_url: {url: "data:image/png;base64,\($img)"}},
|
|
541
|
+
{type: "text", text: "この画像を一言で説明して"}
|
|
542
|
+
]}
|
|
543
|
+
]
|
|
544
|
+
}' |
|
|
545
|
+
curl -sS http://localhost:${PORT:-8000}/v1/chat/completions \
|
|
546
|
+
-H 'Content-Type: application/json' \
|
|
547
|
+
--data-binary @- | jq -r '.choices[0].message.content'
|
|
548
|
+
# 「ピクセルアートで描かれたピンクの猫の顔」
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### audio
|
|
552
|
+
|
|
553
|
+
```sh
|
|
554
|
+
jq -n \
|
|
555
|
+
--rawfile audio <(base64 -i tests/assets/song.wav | tr -d '\n') \
|
|
556
|
+
'{
|
|
557
|
+
model: "qwen3-omni",
|
|
558
|
+
messages: [
|
|
559
|
+
{
|
|
560
|
+
role: "user",
|
|
561
|
+
content: [
|
|
562
|
+
{type: "input_audio", input_audio: {data: $audio, format: "wav"}},
|
|
563
|
+
{type: "text", text: "この audio の歌詞を短く引用してください。また、この音楽の雰囲気や構成も1文で説明してください。"}
|
|
564
|
+
]
|
|
565
|
+
}
|
|
566
|
+
]
|
|
567
|
+
}' |
|
|
568
|
+
curl -sS "http://localhost:${PORT:-8000}/v1/chat/completions" \
|
|
569
|
+
-H 'Content-Type: application/json' \
|
|
570
|
+
--data-binary @- | jq -r '.choices[0].message.content'
|
|
571
|
+
# **歌詞の引用:**
|
|
572
|
+
# 「加速する世界の片端から君の声が聞こえてくる。揺れる心抱えながら、一歩ずつ前を向いて…」
|
|
573
|
+
#
|
|
574
|
+
# **雰囲気・構成の説明:**
|
|
575
|
+
# 電子音と力強いシンセポップのギターが交錯し、情熱的で懐かしさを感じさせるメロディーが特徴的な楽曲です。
|
|
576
|
+
```
|
|
577
|
+
> [!NOTE]
|
|
578
|
+
> Audio input is only supported by `qwen3-omni`.
|
|
579
|
+
|
|
580
|
+
### video
|
|
581
|
+
|
|
582
|
+
**Video only:**
|
|
583
|
+
```sh
|
|
584
|
+
jq -n \
|
|
585
|
+
--rawfile video <(base64 -i tests/assets/pv.mp4 | tr -d '\n') \
|
|
586
|
+
'{
|
|
587
|
+
model: "qwen3-omni",
|
|
588
|
+
messages: [
|
|
589
|
+
{
|
|
590
|
+
role: "user",
|
|
591
|
+
content: [
|
|
592
|
+
{type: "video_url", video_url: {url: "data:video/mp4;base64,\($video)"}},
|
|
593
|
+
{type:"text",text:"この video の映像の展開を一文で説明してください。"}
|
|
594
|
+
]
|
|
595
|
+
}
|
|
596
|
+
],
|
|
597
|
+
use_audio_in_video: false,
|
|
598
|
+
max_completion_tokens: 6000
|
|
599
|
+
}' |
|
|
600
|
+
curl -sS "http://localhost:${PORT:-8000}/v1/chat/completions" \
|
|
601
|
+
-H 'Content-Type: application/json' \
|
|
602
|
+
--data-binary @- | jq -r '.choices[0].message.content'
|
|
603
|
+
# ピンクのピクセルアートのクマが草原の小道を歩き、川を渡って村に到着しました。
|
|
604
|
+
```
|
|
605
|
+
**Video + Audio:**
|
|
606
|
+
```sh
|
|
607
|
+
jq -n \
|
|
608
|
+
--rawfile video <(base64 -i tests/assets/pv.mp4 | tr -d '\n') \
|
|
609
|
+
'{
|
|
610
|
+
model: "qwen3-omni",
|
|
611
|
+
messages: [
|
|
612
|
+
{
|
|
613
|
+
role: "user",
|
|
614
|
+
content: [
|
|
615
|
+
{type: "video_url", video_url: {url: "data:video/mp4;base64,\($video)"}},
|
|
616
|
+
{type:"text",text:"この video の音声には歌がありますか?ある場合は聞き取れる歌詞の一部を短く引用し、映像の展開も一文で説明してください。"}
|
|
617
|
+
]
|
|
618
|
+
}
|
|
619
|
+
],
|
|
620
|
+
max_completion_tokens: 6000
|
|
621
|
+
}' |
|
|
622
|
+
curl -sS "http://localhost:${PORT:-8000}/v1/chat/completions" \
|
|
623
|
+
-H 'Content-Type: application/json' \
|
|
624
|
+
--data-binary @- | jq -r '.choices[0].message.content'
|
|
625
|
+
# はい、歌があります。
|
|
626
|
+
#
|
|
627
|
+
# **聞き取れる歌詞の一部**:
|
|
628
|
+
# 加速する世界の中から
|
|
629
|
+
# 君の声が聞こえてくる
|
|
630
|
+
# 揺れる心を抱えながら
|
|
631
|
+
# 一歩ずつ前を向いて
|
|
632
|
+
#
|
|
633
|
+
# **映像の展開**:
|
|
634
|
+
# ピクセルアートのピンクのクマが画面を下から登場し、カメラが後退して広大な色鮮やかな村の風景を捉えます。
|
|
635
|
+
```
|
|
636
|
+
> [!NOTE]
|
|
637
|
+
> Video input is only supported by `qwen3-omni`.
|
|
638
|
+
|
|
639
|
+
### video (not use audio) + audio
|
|
640
|
+
```bash
|
|
641
|
+
jq -n \
|
|
642
|
+
--rawfile video <(base64 -i tests/assets/pv.mp4 | tr -d '\n') \
|
|
643
|
+
--rawfile audio <(base64 -i tests/assets/song.wav | tr -d '\n') \
|
|
644
|
+
'{
|
|
645
|
+
model: "qwen3-omni",
|
|
646
|
+
messages: [
|
|
647
|
+
{
|
|
648
|
+
role: "user",
|
|
649
|
+
content: [
|
|
650
|
+
{type: "video_url", video_url: {url: "data:video/mp4;base64,\($video)"}},
|
|
651
|
+
{type: "input_audio", input_audio: {data: $audio, format: "wav"}},
|
|
652
|
+
{type: "text", text: "audio から聞き取れる歌詞の一部を短く引用してください。また、video の映像の展開も一文で説明してください。"}
|
|
653
|
+
]
|
|
654
|
+
}
|
|
655
|
+
],
|
|
656
|
+
use_audio_in_video: false,
|
|
657
|
+
max_completion_tokens: 6000
|
|
658
|
+
}' |
|
|
659
|
+
curl -sS "http://localhost:${PORT:-8000}/v1/chat/completions" \
|
|
660
|
+
-H 'Content-Type: application/json' \
|
|
661
|
+
--data-binary @- | jq -r '.choices[0].message.content'
|
|
662
|
+
# **歌詞の一部の短く引用:**
|
|
663
|
+
# 「加速する世界の中で
|
|
664
|
+
# 君の声が聞こえてくる
|
|
665
|
+
# 揺れる心抱えながら
|
|
666
|
+
# 一歩ずつ前を向いて」
|
|
667
|
+
#
|
|
668
|
+
# **video の映像の展開:**
|
|
669
|
+
# アニメのキャラクターが、暖かみのある居酒屋で複数のビールを前に楽しそうに笑いながら手を振るシーン。
|
|
670
|
+
```
|
|
671
|
+
> [!NOTE]
|
|
672
|
+
> `qwen3-omni` accepts audio and video parts.
|
|
673
|
+
> Qwen3-Omni uses at most *one* audio input per request.
|
|
674
|
+
> If video has audio, it will be automatically demuxed and counted as audio, so
|
|
675
|
+
> Do not pass a video with audio and another audio part at the same time.
|
|
676
|
+
|
|
677
|
+
### video + image
|
|
678
|
+
|
|
679
|
+
> [!NOTE]
|
|
680
|
+
> Example of extracting frame images at 1 second intervals using ffmpeg in advance:
|
|
681
|
+
> mkdir -p tests/assets/pv_frames
|
|
682
|
+
> ffmpeg -y -i tests/assets/pv.mp4 -vf fps=1 -start_number 1 tests/assets/pv_frames/t%d.jpg
|
|
683
|
+
```sh
|
|
684
|
+
jq -n \
|
|
685
|
+
--rawfile video <(base64 -i tests/assets/pv.mp4 | tr -d '\n') \
|
|
686
|
+
--slurpfile frames <(
|
|
687
|
+
for i in {1..30}; do
|
|
688
|
+
jq -n --arg i "$i" --rawfile img <(base64 -i "tests/assets/pv_frames/t${i}.jpg" | tr -d '\n') '
|
|
689
|
+
[
|
|
690
|
+
{type: "text", text: "t=[\($i)秒]"},
|
|
691
|
+
{type: "image_url", image_url: {url: "data:image/jpeg;base64,\($img)"}}
|
|
692
|
+
]
|
|
693
|
+
'
|
|
694
|
+
done | jq -s 'flatten'
|
|
695
|
+
) \
|
|
696
|
+
'{
|
|
697
|
+
model: "qwen3-omni",
|
|
698
|
+
messages: [
|
|
699
|
+
{
|
|
700
|
+
role: "user",
|
|
701
|
+
content: (
|
|
702
|
+
[
|
|
703
|
+
{type: "text", text: "まず動画と音声です。"},
|
|
704
|
+
{type: "video_url", video_url: {url: "data:video/mp4;base64,\($video)"}},
|
|
705
|
+
{type: "text", text: "次に、同じ動画から1秒間隔で抜き出した秒数ラベル付きフレームです。"}
|
|
706
|
+
]
|
|
707
|
+
+ $frames[0]
|
|
708
|
+
+ [
|
|
709
|
+
{type: "text", text: "この video の歌詞の一部を短く引用してください。次に、最も印象的・象徴的な瞬間の秒数(t=◯秒)を1つ選んで、その理由を1文で説明してください。"}
|
|
710
|
+
]
|
|
711
|
+
)
|
|
712
|
+
}
|
|
713
|
+
],
|
|
714
|
+
max_completion_tokens: 6000
|
|
715
|
+
}' | \
|
|
716
|
+
curl -sS "http://localhost:${PORT:-8000}/v1/chat/completions" \
|
|
717
|
+
-H 'Content-Type: application/json' \
|
|
718
|
+
--data-binary @- | jq -r '.choices[0].message.content'
|
|
719
|
+
# 詞(一部): 「加速する世界の中から君の声が聞こえてくる」
|
|
720
|
+
#
|
|
721
|
+
# 最も印象的で象徴的な瞬間: t=12秒
|
|
722
|
+
#
|
|
723
|
+
# 説明: 一匹の小さなトカゲが登場し、物語の始まりや新たな道のりを象徴している。
|
|
724
|
+
```
|
|
725
|
+
> [!NOTE]
|
|
726
|
+
> If there are many frame images, the response tends to be unstable.
|
|
727
|
+
|
|
728
|
+
### video + image + tools
|
|
729
|
+
```sh
|
|
730
|
+
jq -n \
|
|
731
|
+
--rawfile video <(base64 -i tests/assets/pv.mp4 | tr -d '\n') \
|
|
732
|
+
--slurpfile frames <(
|
|
733
|
+
for i in {1..30}; do
|
|
734
|
+
jq -n --arg i "$i" --rawfile img <(base64 -i "tests/assets/pv_frames/t${i}.jpg" | tr -d '\n') '
|
|
735
|
+
[
|
|
736
|
+
{type: "text", text: "t=\($i)秒"},
|
|
737
|
+
{type: "image_url", image_url: {url: "data:image/jpeg;base64,\($img)"}}
|
|
738
|
+
]
|
|
739
|
+
'
|
|
740
|
+
done | jq -s 'flatten'
|
|
741
|
+
) \
|
|
742
|
+
'{
|
|
743
|
+
model: "qwen3-omni",
|
|
744
|
+
tools: [
|
|
745
|
+
{
|
|
746
|
+
type: "function",
|
|
747
|
+
function: {
|
|
748
|
+
name: "record_highlight",
|
|
749
|
+
description: "動画の中で最も印象的な瞬間の秒数と、その理由を記録する",
|
|
750
|
+
parameters: {
|
|
751
|
+
type: "object",
|
|
752
|
+
properties: {
|
|
753
|
+
timestamp_seconds: {
|
|
754
|
+
type: "integer",
|
|
755
|
+
description: "最も印象的なフレームの秒数(t=◯秒の◯)"
|
|
756
|
+
},
|
|
757
|
+
reason: {
|
|
758
|
+
type: "string",
|
|
759
|
+
description: "その瞬間が印象的な理由(映像と楽曲の両面から)"
|
|
760
|
+
}
|
|
761
|
+
},
|
|
762
|
+
required: ["timestamp_seconds", "reason"]
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
],
|
|
767
|
+
tool_choice: {
|
|
768
|
+
type: "function",
|
|
769
|
+
function: {name: "record_highlight"}
|
|
770
|
+
},
|
|
771
|
+
messages: [
|
|
772
|
+
{
|
|
773
|
+
role: "user",
|
|
774
|
+
content: (
|
|
775
|
+
[
|
|
776
|
+
{type: "text", text: "まず動画と音声です。"},
|
|
777
|
+
{type: "video_url", video_url: {url: "data:video/mp4;base64,\($video)"}},
|
|
778
|
+
{type: "text", text: "次に、同じ動画から1秒間隔で抜き出した秒数ラベル付きフレームです。"}
|
|
779
|
+
]
|
|
780
|
+
+ $frames[0]
|
|
781
|
+
+ [
|
|
782
|
+
{type: "text", text: "映像・楽曲・フレームを分析し、最も印象的・象徴的な瞬間を一つ選んでください。選んだら、その秒数と、その理由を、1文で説明してください。"}
|
|
783
|
+
]
|
|
784
|
+
)
|
|
785
|
+
}
|
|
786
|
+
],
|
|
787
|
+
max_completion_tokens: 6000
|
|
788
|
+
}' | \
|
|
789
|
+
curl -sS "http://localhost:${PORT:-8000}/v1/chat/completions" \
|
|
790
|
+
-H 'Content-Type: application/json' \
|
|
791
|
+
--data-binary @- | jq -r '.choices[0].message'
|
|
792
|
+
# {
|
|
793
|
+
# "role": "assistant",
|
|
794
|
+
# "content": null,
|
|
795
|
+
# "tool_calls": [
|
|
796
|
+
# {
|
|
797
|
+
# "id": "call_58247d6050ca4d11a10fabcc",
|
|
798
|
+
# "type": "function",
|
|
799
|
+
# "function": {
|
|
800
|
+
# "name": "record_highlight",
|
|
801
|
+
# "arguments": "{\"timestamp_seconds\":27, \"reason\": \"この瞬間のカメラの位置が最も安定しており、森の小道を歩くキリンと村の景色をバランスよく捉えており、物語の世界観を象徴的に表現している。\"}"
|
|
802
|
+
# }
|
|
803
|
+
# }
|
|
804
|
+
# ]
|
|
805
|
+
# }
|
|
806
|
+
```
|