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,822 @@
|
|
|
1
|
+
# chat
|
|
2
|
+
|
|
3
|
+
[English](README.md) | **日本語**
|
|
4
|
+
|
|
5
|
+
[mlx-vlm](https://github.com/Blaizzy/mlx-vlm) で、OpenAI 互換のチャット補完 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
|
+
以下の機能に対応しています。
|
|
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` | チャット補完 | OpenAI 互換の Chat Completions API。 |
|
|
24
|
+
| `GET /v1/models` | モデル一覧 | 利用可能なモデルの一覧を返す。 |
|
|
25
|
+
| `GET /v1/chat/openapi.json` | OpenAPI | 詳細な入出力仕様、使い方、TIPS を返す。 |
|
|
26
|
+
|
|
27
|
+
- 独自拡張機能:
|
|
28
|
+
- `fps`: video の変換フレームレート
|
|
29
|
+
- `use_audio_in_video`: video 内音声をモデル入力に含めるか
|
|
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 | MLX 上で Qwen マルチモーダルモデルを駆動。 |
|
|
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 | 不要 | 21.8 GB | `qwen3-omni`(デフォルト)。text + image + audio + video、tool-call prefill=JSON。Talker(音声*出力*)は非公開で出力は text/tool-calls のみ。audio 入力は 1 リクエスト最大 **1 つ**(音声付き video の demux 音声も含む)。 |
|
|
48
|
+
| [mlx-community/Qwen3.6-27B-4bit](https://huggingface.co/mlx-community/Qwen3.6-27B-4bit) | Apache-2.0 | 不要 | 16.1 GB | `qwen3.6-27b`。text + image のみ、tool-call prefill=Hermes/XML。reasoning はデフォルト OFF。 |
|
|
49
|
+
|
|
50
|
+
- 選択したモデルが対応しないモダリティの part を送ると **HTTP 400**。
|
|
51
|
+
|
|
52
|
+
## Notes
|
|
53
|
+
|
|
54
|
+
chat は **mlx-vlm** で実装していますが、バグ回避のためにいくつかパッチを当てています。
|
|
55
|
+
このパッチは、**mlx-vlm** のアップデートで壊れる可能性があることを認識してください。
|
|
56
|
+
|
|
57
|
+
**mlx-vlm** は `mlx-vlm==0.6.3` に固定にしています。
|
|
58
|
+
アップデートの際は、下記のパッチの内容を再確認し、必要に応じて修正してください。
|
|
59
|
+
詳細は、docstring に記載してあります。
|
|
60
|
+
|
|
61
|
+
| # | 内容 | 場所 | 対象モデル |
|
|
62
|
+
|---|------|------|-----------|
|
|
63
|
+
| A | 音声をパスでなく float32 配列で渡す | `_models/qwen3_omni.py` | omni |
|
|
64
|
+
| B | ステレオ音声のリサンプル不整合を自前ロードで回避 | `_utils/load_audio_mono.py` | omni |
|
|
65
|
+
| C | mlx 0.31.x 用 `mx.where` / `mx.scatter` shim | `_models/qwen3_omni.py` `_ensure_mlx_compat` | omni(image+video 同時) |
|
|
66
|
+
| E | ストリーミング detokenizer の UTF-8 デコード緩和 | `_operations/ensure_streaming_detokenizer_compat.py` | 両モデル(stream) |
|
|
67
|
+
| F | トークン ID からのテキスト復元(stream) | `_operations/stream_text_from_tokens.py` | qwen3.6(stream) |
|
|
68
|
+
|
|
69
|
+
**A. 音声を float32 配列で渡す:**
|
|
70
|
+
- **場所**: `_models/qwen3_omni.py` の `run`(`audio_arrays = [load_audio_mono(p, sr=sr) ...]`)
|
|
71
|
+
- **理由**: mlx-vlm の qwen3-omni 分岐は、生の音声 **パス** を受け取ると
|
|
72
|
+
`could not convert string to float` でクラッシュする。`generate(audio=...)` には
|
|
73
|
+
ndarray を渡す必要がある。
|
|
74
|
+
- **トリガ**: omni に音声入力があるすべてのケース。
|
|
75
|
+
|
|
76
|
+
**B. ステレオ音声のリサンプル不整合:**
|
|
77
|
+
- **場所**: `_utils/load_audio_mono.py`(A の配列ロードをこの自前関数で行う)
|
|
78
|
+
- **理由**: mlx-vlm の `utils.load_audio` にバグがある。`read_audio` は音声を
|
|
79
|
+
`(samples, channels)`(チャンネルラスト)で返すが、`load_audio` は
|
|
80
|
+
- リサンプルを `resample_audio(..., axis=-1)` = **チャンネル軸**に対して行い、
|
|
81
|
+
- ダウンミックスを `mean(axis=1)` = 同じくチャンネル軸で行う
|
|
82
|
+
と軸の扱いが矛盾している。結果、**レートの異なるステレオ音声**(典型的に
|
|
83
|
+
48kHz / 44.1kHz stereo の wav)は時間軸がリサンプルされず、48kHz のサンプルが
|
|
84
|
+
そのまま 16kHz として omni に渡り、**音声を認識できない**。モノラルは 1 次元で
|
|
85
|
+
`axis=-1` がたまたま時間軸になるため正しく動く。
|
|
86
|
+
- **回避策**: `load_audio_mono` では **先にモノラル化してからリサンプル**するため、
|
|
87
|
+
`resample_audio` のデフォルト `axis=-1` が必ず時間軸になり、レート変換が正しく行われる
|
|
88
|
+
(48k mono / 48k stereo / 44.1k stereo / 16k stereo すべて 16000 サンプルへ)。
|
|
89
|
+
- **video 内音声への影響**: なし。`_operations/parse_messages.py` の `_extract_audio`
|
|
90
|
+
が ffmpeg `-ac 1 -ar 16000` で **最初からモノラル 16kHz** に demux するため、
|
|
91
|
+
リサンプル・ダウンミックス自体が発生せずバグ条件に該当しない。
|
|
92
|
+
|
|
93
|
+
**C. mlx 0.31.x 互換 shim(`mx.where` / `mx.scatter`):**
|
|
94
|
+
- **場所**: `_models/qwen3_omni.py` の `_ensure_mlx_compat`(`run` 冒頭で呼ぶ)
|
|
95
|
+
- **理由**: mlx-vlm の `qwen3_omni_moe/thinker.py` は **image + video を同時に
|
|
96
|
+
入力する経路**(visual_embeds_multiscale / deepstack 結合)で、mlx 0.31.x に存在
|
|
97
|
+
しない API を使う:
|
|
98
|
+
- 1 引数形式の `mx.where(mask)[0]`(True のインデックス取得)→ TypeError
|
|
99
|
+
- フリー関数 `mx.scatter(a, idx, vals, ax)` → AttributeError
|
|
100
|
+
|
|
101
|
+
image 単独・video 単独は別経路で問題なし。site-packages を書き換えず、互換実装を
|
|
102
|
+
グラフトして回避(冪等・加算的で他経路に影響なし)。
|
|
103
|
+
- **トリガ**: omni に image と video を **同時に**渡したときのみ。
|
|
104
|
+
|
|
105
|
+
**E. ストリーミング detokenizer の UTF-8 デコード緩和:**
|
|
106
|
+
- **場所**: `_operations/ensure_streaming_detokenizer_compat.py`(stream 経路で呼ぶ)
|
|
107
|
+
- **理由**: mlx-vlm の `BPEStreamingDetokenizer.add_token` は、バッファした
|
|
108
|
+
バイト列を **strict UTF-8** でデコードする。フラッシュ境界で不正な UTF-8 になる
|
|
109
|
+
バイトトークン列があるとストリーミング応答がクラッシュする。`finalize` 側は
|
|
110
|
+
同じデコードを寛容に処理しているので、streaming 経路も `errors="replace"` で
|
|
111
|
+
同等に緩和する。
|
|
112
|
+
- **トリガ**: 両モデルの `stream=true`。
|
|
113
|
+
|
|
114
|
+
**F. トークン ID からのテキスト復元(qwen3.6 stream):**
|
|
115
|
+
- **場所**: `_operations/stream_text_from_tokens.py`
|
|
116
|
+
- **理由**: バグ回避というより互換ラッパ。mlx-vlm の `_ServerTokenStreamer` /
|
|
117
|
+
`make_streaming_detokenizer` が利用可能なら、それでトークン ID からテキストを
|
|
118
|
+
復元する。利用不可なら素通り(`yield from chunks`)。
|
|
119
|
+
|
|
120
|
+
## Quickstart
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
MODEL=qwen3.6-27b
|
|
124
|
+
MODEL=qwen3-omni
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### text
|
|
128
|
+
|
|
129
|
+
```sh
|
|
130
|
+
jq -n \
|
|
131
|
+
--arg model "$MODEL" \
|
|
132
|
+
'{
|
|
133
|
+
model: $model,
|
|
134
|
+
messages: [
|
|
135
|
+
{role: "user", content: "こんにちは"}
|
|
136
|
+
]
|
|
137
|
+
}' |
|
|
138
|
+
curl -sS "http://localhost:${PORT:-8000}/v1/chat/completions" \
|
|
139
|
+
-H 'Content-Type: application/json' \
|
|
140
|
+
--data-binary @- |
|
|
141
|
+
jq -r '.choices[0].message.content'
|
|
142
|
+
# こんにちは!何かお手伝いできることはありますか?
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
ストリーミング:
|
|
146
|
+
|
|
147
|
+
```sh
|
|
148
|
+
jq -n \
|
|
149
|
+
--arg model "$MODEL" \
|
|
150
|
+
'{
|
|
151
|
+
model: $model,
|
|
152
|
+
stream: true,
|
|
153
|
+
messages: [
|
|
154
|
+
{role: "user", content: "日本の首都はどこ?一言で。"}
|
|
155
|
+
]
|
|
156
|
+
}' |
|
|
157
|
+
curl -N "http://localhost:${PORT:-8000}/v1/chat/completions" \
|
|
158
|
+
-H 'Content-Type: application/json' \
|
|
159
|
+
--data-binary @-
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### max_completion_tokens
|
|
163
|
+
|
|
164
|
+
```sh
|
|
165
|
+
jq -n \
|
|
166
|
+
--arg model "$MODEL" \
|
|
167
|
+
'{
|
|
168
|
+
model: $model,
|
|
169
|
+
messages: [
|
|
170
|
+
{role: "user", content: "python について説明してください。"}
|
|
171
|
+
],
|
|
172
|
+
max_completion_tokens: 50
|
|
173
|
+
}' |
|
|
174
|
+
curl -sS http://localhost:${PORT:-8000}/v1/chat/completions \
|
|
175
|
+
-H 'Content-Type: application/json' \
|
|
176
|
+
--data-binary @- |
|
|
177
|
+
jq -r '.choices[0].message.content'
|
|
178
|
+
# Python(パイソン)は、世界で最も人気のある汎用プログラミング言語の一つです。その最大の特徴は**「書きやすさ」と「読みやすさ」**であり、初心者からプロのエンジニアまで幅広く使われています。
|
|
179
|
+
#
|
|
180
|
+
# 以下に、
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### tool_call
|
|
184
|
+
|
|
185
|
+
```sh
|
|
186
|
+
jq -n \
|
|
187
|
+
--arg model "$MODEL" \
|
|
188
|
+
'{
|
|
189
|
+
model: $model,
|
|
190
|
+
messages: [
|
|
191
|
+
{role: "user", content: "東京と大阪の天気は?タイマーを30秒にセットして。"}
|
|
192
|
+
],
|
|
193
|
+
tools: [
|
|
194
|
+
{
|
|
195
|
+
type: "function",
|
|
196
|
+
function: {
|
|
197
|
+
name: "get_weather",
|
|
198
|
+
parameters: {
|
|
199
|
+
type: "object",
|
|
200
|
+
properties: {
|
|
201
|
+
location: {type: "string"}
|
|
202
|
+
},
|
|
203
|
+
required: ["location"]
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
type: "function",
|
|
209
|
+
function: {
|
|
210
|
+
name: "set_timer",
|
|
211
|
+
parameters: {
|
|
212
|
+
type: "object",
|
|
213
|
+
properties: {
|
|
214
|
+
seconds: {type: "integer"}
|
|
215
|
+
},
|
|
216
|
+
required: ["seconds"]
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
}' |
|
|
222
|
+
curl -sS http://localhost:${PORT:-8000}/v1/chat/completions \
|
|
223
|
+
-H 'Content-Type: application/json' \
|
|
224
|
+
--data-binary @- |
|
|
225
|
+
jq '.choices[0].message.tool_calls'
|
|
226
|
+
# [
|
|
227
|
+
# {
|
|
228
|
+
# "id": "call_5bf5c0b6ecbd4944bfaba514",
|
|
229
|
+
# "type": "function",
|
|
230
|
+
# "function": {
|
|
231
|
+
# "name": "get_weather",
|
|
232
|
+
# "arguments": "{\"location\": \"東京\"}"
|
|
233
|
+
# }
|
|
234
|
+
# },
|
|
235
|
+
# {
|
|
236
|
+
# "id": "call_9f98db50e2ec4d1898710972",
|
|
237
|
+
# "type": "function",
|
|
238
|
+
# "function": {
|
|
239
|
+
# "name": "get_weather",
|
|
240
|
+
# "arguments": "{\"location\": \"大阪\"}"
|
|
241
|
+
# }
|
|
242
|
+
# },
|
|
243
|
+
# {
|
|
244
|
+
# "id": "call_786091eb2e2547b29eb96b35",
|
|
245
|
+
# "type": "function",
|
|
246
|
+
# "function": {
|
|
247
|
+
# "name": "set_timer",
|
|
248
|
+
# "arguments": "{\"seconds\": 30}"
|
|
249
|
+
# }
|
|
250
|
+
# }
|
|
251
|
+
# ]
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### tool_choice
|
|
255
|
+
|
|
256
|
+
tool_choice は下記の 3 パターンで指定可能。
|
|
257
|
+
- `auto`: モデルにツール選択を任せる(デフォルト)
|
|
258
|
+
- `any` | `required`: ツール選択を強制(ツールが複数ある場合はモデルが選ぶ)
|
|
259
|
+
- `{"type":"function","function":{"name":...}}`: 特定のツール呼び出しを強制
|
|
260
|
+
|
|
261
|
+
#### auto
|
|
262
|
+
|
|
263
|
+
```sh
|
|
264
|
+
jq -n \
|
|
265
|
+
--arg model "$MODEL" \
|
|
266
|
+
'{
|
|
267
|
+
model: $model,
|
|
268
|
+
messages: [
|
|
269
|
+
{role: "user", content: "こんにちは"}
|
|
270
|
+
],
|
|
271
|
+
tools: [
|
|
272
|
+
{
|
|
273
|
+
type: "function",
|
|
274
|
+
function: {
|
|
275
|
+
name: "get_weather",
|
|
276
|
+
parameters: {
|
|
277
|
+
type: "object",
|
|
278
|
+
properties: {
|
|
279
|
+
location: {type: "string"}
|
|
280
|
+
},
|
|
281
|
+
required: ["location"]
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
type: "function",
|
|
287
|
+
function: {
|
|
288
|
+
name: "set_timer",
|
|
289
|
+
parameters: {
|
|
290
|
+
type: "object",
|
|
291
|
+
properties: {
|
|
292
|
+
seconds: {type: "integer"}
|
|
293
|
+
},
|
|
294
|
+
required: ["seconds"]
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
]
|
|
299
|
+
}' |
|
|
300
|
+
curl -sS http://localhost:${PORT:-8000}/v1/chat/completions \
|
|
301
|
+
-H 'Content-Type: application/json' \
|
|
302
|
+
--data-binary @- |
|
|
303
|
+
jq '.choices[0].message'
|
|
304
|
+
# {
|
|
305
|
+
# "role": "assistant",
|
|
306
|
+
# "content": "こんにちは!今日はどんなお手伝いが必要ですか?"
|
|
307
|
+
# }
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
#### any / required
|
|
311
|
+
|
|
312
|
+
```sh
|
|
313
|
+
jq -n \
|
|
314
|
+
--arg model "$MODEL" \
|
|
315
|
+
'{
|
|
316
|
+
model: $model,
|
|
317
|
+
messages: [
|
|
318
|
+
{role: "user", content: "こんにちは"}
|
|
319
|
+
],
|
|
320
|
+
tools: [
|
|
321
|
+
{
|
|
322
|
+
type: "function",
|
|
323
|
+
function: {
|
|
324
|
+
name: "get_weather",
|
|
325
|
+
parameters: {
|
|
326
|
+
type: "object",
|
|
327
|
+
properties: {
|
|
328
|
+
location: {type: "string"}
|
|
329
|
+
},
|
|
330
|
+
required: ["location"]
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
type: "function",
|
|
336
|
+
function: {
|
|
337
|
+
name: "set_timer",
|
|
338
|
+
parameters: {
|
|
339
|
+
type: "object",
|
|
340
|
+
properties: {
|
|
341
|
+
seconds: {type: "integer"}
|
|
342
|
+
},
|
|
343
|
+
required: ["seconds"]
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
],
|
|
348
|
+
tool_choice: "any"
|
|
349
|
+
}' |
|
|
350
|
+
curl -sS http://localhost:${PORT:-8000}/v1/chat/completions \
|
|
351
|
+
-H 'Content-Type: application/json' \
|
|
352
|
+
--data-binary @- |
|
|
353
|
+
jq '.choices[0].message'
|
|
354
|
+
# {
|
|
355
|
+
# "role": "assistant",
|
|
356
|
+
# "content": null,
|
|
357
|
+
# "tool_calls": [
|
|
358
|
+
# {
|
|
359
|
+
# "id": "call_d9fc6f940c23476c98e2b2a8",
|
|
360
|
+
# "type": "function",
|
|
361
|
+
# "function": {
|
|
362
|
+
# "name": "get_weather",
|
|
363
|
+
# "arguments": "{\"location\": \"Tokyo\"}"
|
|
364
|
+
# }
|
|
365
|
+
# }
|
|
366
|
+
# ]
|
|
367
|
+
# }
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
#### specific
|
|
371
|
+
|
|
372
|
+
```sh
|
|
373
|
+
jq -n \
|
|
374
|
+
--arg model "$MODEL" \
|
|
375
|
+
'{
|
|
376
|
+
model: $model,
|
|
377
|
+
messages: [
|
|
378
|
+
{role: "user", content: "こんにちは"}
|
|
379
|
+
],
|
|
380
|
+
tools: [
|
|
381
|
+
{
|
|
382
|
+
type: "function",
|
|
383
|
+
function: {
|
|
384
|
+
name: "get_weather",
|
|
385
|
+
parameters: {
|
|
386
|
+
type: "object",
|
|
387
|
+
properties: {
|
|
388
|
+
location: {type: "string"}
|
|
389
|
+
},
|
|
390
|
+
required: ["location"]
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
type: "function",
|
|
396
|
+
function: {
|
|
397
|
+
name: "set_timer",
|
|
398
|
+
parameters: {
|
|
399
|
+
type: "object",
|
|
400
|
+
properties: {
|
|
401
|
+
seconds: {type: "integer"}
|
|
402
|
+
},
|
|
403
|
+
required: ["seconds"]
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
],
|
|
408
|
+
tool_choice: {
|
|
409
|
+
type: "function",
|
|
410
|
+
function: {name: "get_weather"}
|
|
411
|
+
}
|
|
412
|
+
}' |
|
|
413
|
+
curl -sS http://localhost:${PORT:-8000}/v1/chat/completions \
|
|
414
|
+
-H 'Content-Type: application/json' \
|
|
415
|
+
--data-binary @- |
|
|
416
|
+
jq '.choices[0].message'
|
|
417
|
+
# {
|
|
418
|
+
# "role": "assistant",
|
|
419
|
+
# "content": null,
|
|
420
|
+
# "tool_calls": [
|
|
421
|
+
# {
|
|
422
|
+
# "id": "call_b4df9a6d995c4735b8f10387",
|
|
423
|
+
# "type": "function",
|
|
424
|
+
# "function": {
|
|
425
|
+
# "name": "get_weather",
|
|
426
|
+
# "arguments": "{\"location\": \"Tokyo\"}"
|
|
427
|
+
# }
|
|
428
|
+
# }
|
|
429
|
+
# ]
|
|
430
|
+
# }
|
|
431
|
+
```
|
|
432
|
+
> [!NOTE]
|
|
433
|
+
> any/required や specific は、文脈に関係なくツールを呼び出します
|
|
434
|
+
> あまりに文脈と乖離したツールしかない場合、特に `qwen3-omni` では不正なレスポンスが生成されがちです
|
|
435
|
+
|
|
436
|
+
### parallel_tool_calls
|
|
437
|
+
|
|
438
|
+
parallel_tool_calls は、デフォルトが `true` です。
|
|
439
|
+
単一のツール呼び出しを強制したいときは、`parallel_tool_calls: false` を指定します。
|
|
440
|
+
|
|
441
|
+
```sh
|
|
442
|
+
jq -n \
|
|
443
|
+
--arg model "$MODEL" \
|
|
444
|
+
'{
|
|
445
|
+
model: $model,
|
|
446
|
+
messages: [
|
|
447
|
+
{role: "user", content: "東京と大阪の天気は?"}
|
|
448
|
+
],
|
|
449
|
+
tools: [
|
|
450
|
+
{
|
|
451
|
+
type: "function",
|
|
452
|
+
function: {
|
|
453
|
+
name: "get_weather",
|
|
454
|
+
parameters: {
|
|
455
|
+
type: "object",
|
|
456
|
+
properties: {
|
|
457
|
+
location: {type: "string"}
|
|
458
|
+
},
|
|
459
|
+
required: ["location"]
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
],
|
|
464
|
+
parallel_tool_calls: false
|
|
465
|
+
}' |
|
|
466
|
+
curl -sS http://localhost:${PORT:-8000}/v1/chat/completions \
|
|
467
|
+
-H 'Content-Type: application/json' \
|
|
468
|
+
--data-binary @- |
|
|
469
|
+
jq '.choices[0].message'
|
|
470
|
+
# {
|
|
471
|
+
# "role": "assistant",
|
|
472
|
+
# "content": null,
|
|
473
|
+
# "tool_calls": [
|
|
474
|
+
# {
|
|
475
|
+
# "id": "call_060acbd57cfe4c4eb8464158",
|
|
476
|
+
# "type": "function",
|
|
477
|
+
# "function": {
|
|
478
|
+
# "name": "get_weather",
|
|
479
|
+
# "arguments": "{\"location\": \"東京\"}"
|
|
480
|
+
# }
|
|
481
|
+
# }
|
|
482
|
+
# ]
|
|
483
|
+
# }
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
### continuation
|
|
487
|
+
|
|
488
|
+
system, user, assistant, tool, assistant, human... のような複数ターンのメッセージを処理する。
|
|
489
|
+
|
|
490
|
+
```sh
|
|
491
|
+
jq -n \
|
|
492
|
+
--arg model "$MODEL" \
|
|
493
|
+
'{
|
|
494
|
+
model: $model,
|
|
495
|
+
messages: [
|
|
496
|
+
{role: "system", content: "語尾に「にゃ」をつけて答えてください"},
|
|
497
|
+
{role: "user", content: "こんにちは"},
|
|
498
|
+
{role: "assistant", content: "こんにちはにゃ!何かお手伝いできることはありますかにゃ?"},
|
|
499
|
+
{role: "user", content: "今日の天気は?"},
|
|
500
|
+
{role: "assistant", tool_calls: [
|
|
501
|
+
{
|
|
502
|
+
id: "call_123",
|
|
503
|
+
type: "function",
|
|
504
|
+
function: {
|
|
505
|
+
name: "get_weather",
|
|
506
|
+
arguments: "{\"location\": \"Tokyo\"}"
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
]},
|
|
510
|
+
{role: "tool", content: "東京の天気は晴れ、最高気温25度、最低気温15度です。"}
|
|
511
|
+
],
|
|
512
|
+
tools: [
|
|
513
|
+
{
|
|
514
|
+
type: "function",
|
|
515
|
+
function: {
|
|
516
|
+
name: "get_weather",
|
|
517
|
+
parameters: {
|
|
518
|
+
type: "object",
|
|
519
|
+
properties: {
|
|
520
|
+
location: {type: "string"}
|
|
521
|
+
},
|
|
522
|
+
required: ["location"]
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
]
|
|
527
|
+
}' |
|
|
528
|
+
curl -sS http://localhost:${PORT:-8000}/v1/chat/completions \
|
|
529
|
+
-H 'Content-Type: application/json' \
|
|
530
|
+
--data-binary @- |
|
|
531
|
+
jq -r '.choices[0].message'
|
|
532
|
+
# {
|
|
533
|
+
# "role": "assistant",
|
|
534
|
+
# "content": "東京の天気は晴れ、最高気温25度、最低気温15度ですにゃ!"
|
|
535
|
+
# }
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
### image
|
|
539
|
+
|
|
540
|
+
```sh
|
|
541
|
+
jq -n \
|
|
542
|
+
--arg model "$MODEL" \
|
|
543
|
+
--rawfile img <(base64 -i tests/assets/miineko.png | tr -d '\n') \
|
|
544
|
+
'{
|
|
545
|
+
model: $model,
|
|
546
|
+
messages: [
|
|
547
|
+
{role: "user", content: [
|
|
548
|
+
{type: "image_url", image_url: {url: "data:image/png;base64,\($img)"}},
|
|
549
|
+
{type: "text", text: "この画像を一言で説明して"}
|
|
550
|
+
]}
|
|
551
|
+
]
|
|
552
|
+
}' |
|
|
553
|
+
curl -sS http://localhost:${PORT:-8000}/v1/chat/completions \
|
|
554
|
+
-H 'Content-Type: application/json' \
|
|
555
|
+
--data-binary @- | jq -r '.choices[0].message.content'
|
|
556
|
+
# 「ピクセルアートで描かれたピンクの猫の顔」
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
### audio
|
|
560
|
+
|
|
561
|
+
```sh
|
|
562
|
+
jq -n \
|
|
563
|
+
--rawfile audio <(base64 -i tests/assets/song.wav | tr -d '\n') \
|
|
564
|
+
'{
|
|
565
|
+
model: "qwen3-omni",
|
|
566
|
+
messages: [
|
|
567
|
+
{
|
|
568
|
+
role: "user",
|
|
569
|
+
content: [
|
|
570
|
+
{type: "input_audio", input_audio: {data: $audio, format: "wav"}},
|
|
571
|
+
{type: "text", text: "この audio の歌詞を短く引用してください。また、この音楽の雰囲気や構成も1文で説明してください。"}
|
|
572
|
+
]
|
|
573
|
+
}
|
|
574
|
+
]
|
|
575
|
+
}' |
|
|
576
|
+
curl -sS "http://localhost:${PORT:-8000}/v1/chat/completions" \
|
|
577
|
+
-H 'Content-Type: application/json' \
|
|
578
|
+
--data-binary @- | jq -r '.choices[0].message.content'
|
|
579
|
+
# **歌詞の引用:**
|
|
580
|
+
# 「加速する世界の片端から君の声が聞こえてくる。揺れる心抱えながら、一歩ずつ前を向いて…」
|
|
581
|
+
#
|
|
582
|
+
# **雰囲気・構成の説明:**
|
|
583
|
+
# 電子音と力強いシンセポップのギターが交錯し、情熱的で懐かしさを感じさせるメロディーが特徴的な楽曲です。
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
> [!NOTE]
|
|
587
|
+
> audio 入力は `qwen3-omni` のみサポート。
|
|
588
|
+
|
|
589
|
+
### video
|
|
590
|
+
|
|
591
|
+
**映像のみ:**
|
|
592
|
+
```sh
|
|
593
|
+
jq -n \
|
|
594
|
+
--rawfile video <(base64 -i tests/assets/pv.mp4 | tr -d '\n') \
|
|
595
|
+
'{
|
|
596
|
+
model: "qwen3-omni",
|
|
597
|
+
messages: [
|
|
598
|
+
{
|
|
599
|
+
role: "user",
|
|
600
|
+
content: [
|
|
601
|
+
{type: "video_url", video_url: {url: "data:video/mp4;base64,\($video)"}},
|
|
602
|
+
{type:"text",text:"この video の映像の展開を一文で説明してください。"}
|
|
603
|
+
]
|
|
604
|
+
}
|
|
605
|
+
],
|
|
606
|
+
use_audio_in_video: false,
|
|
607
|
+
max_completion_tokens: 6000
|
|
608
|
+
}' |
|
|
609
|
+
curl -sS "http://localhost:${PORT:-8000}/v1/chat/completions" \
|
|
610
|
+
-H 'Content-Type: application/json' \
|
|
611
|
+
--data-binary @- | jq -r '.choices[0].message.content'
|
|
612
|
+
# ピンクのピクセルアートのクマが草原の小道を歩き、川を渡って村に到着しました。
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
**映像 + 音声:**
|
|
616
|
+
```sh
|
|
617
|
+
jq -n \
|
|
618
|
+
--rawfile video <(base64 -i tests/assets/pv.mp4 | tr -d '\n') \
|
|
619
|
+
'{
|
|
620
|
+
model: "qwen3-omni",
|
|
621
|
+
messages: [
|
|
622
|
+
{
|
|
623
|
+
role: "user",
|
|
624
|
+
content: [
|
|
625
|
+
{type: "video_url", video_url: {url: "data:video/mp4;base64,\($video)"}},
|
|
626
|
+
{type:"text",text:"この video の音声には歌がありますか?ある場合は聞き取れる歌詞の一部を短く引用し、映像の展開も一文で説明してください。"}
|
|
627
|
+
]
|
|
628
|
+
}
|
|
629
|
+
],
|
|
630
|
+
max_completion_tokens: 6000
|
|
631
|
+
}' |
|
|
632
|
+
curl -sS "http://localhost:${PORT:-8000}/v1/chat/completions" \
|
|
633
|
+
-H 'Content-Type: application/json' \
|
|
634
|
+
--data-binary @- | jq -r '.choices[0].message.content'
|
|
635
|
+
# はい、歌があります。
|
|
636
|
+
#
|
|
637
|
+
# **聞き取れる歌詞の一部**:
|
|
638
|
+
# 加速する世界の中から
|
|
639
|
+
# 君の声が聞こえてくる
|
|
640
|
+
# 揺れる心を抱えながら
|
|
641
|
+
# 一歩ずつ前を向いて
|
|
642
|
+
#
|
|
643
|
+
# **映像の展開**:
|
|
644
|
+
# ピクセルアートのピンクのクマが画面を下から登場し、カメラが後退して広大な色鮮やかな村の風景を捉えます。
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
> [!NOTE]
|
|
648
|
+
> video 入力は `qwen3-omni` のみサポート。
|
|
649
|
+
|
|
650
|
+
### video (not use audio) + audio
|
|
651
|
+
|
|
652
|
+
```bash
|
|
653
|
+
jq -n \
|
|
654
|
+
--rawfile video <(base64 -i tests/assets/pv.mp4 | tr -d '\n') \
|
|
655
|
+
--rawfile audio <(base64 -i tests/assets/song.wav | tr -d '\n') \
|
|
656
|
+
'{
|
|
657
|
+
model: "qwen3-omni",
|
|
658
|
+
messages: [
|
|
659
|
+
{
|
|
660
|
+
role: "user",
|
|
661
|
+
content: [
|
|
662
|
+
{type: "video_url", video_url: {url: "data:video/mp4;base64,\($video)"}},
|
|
663
|
+
{type: "input_audio", input_audio: {data: $audio, format: "wav"}},
|
|
664
|
+
{type: "text", text: "audio から聞き取れる歌詞の一部を短く引用してください。また、video の映像の展開も一文で説明してください。"}
|
|
665
|
+
]
|
|
666
|
+
}
|
|
667
|
+
],
|
|
668
|
+
use_audio_in_video: false,
|
|
669
|
+
max_completion_tokens: 6000
|
|
670
|
+
}' |
|
|
671
|
+
curl -sS "http://localhost:${PORT:-8000}/v1/chat/completions" \
|
|
672
|
+
-H 'Content-Type: application/json' \
|
|
673
|
+
--data-binary @- | jq -r '.choices[0].message.content'
|
|
674
|
+
# **歌詞の一部の短く引用:**
|
|
675
|
+
# 「加速する世界の中で
|
|
676
|
+
# 君の声が聞こえてくる
|
|
677
|
+
# 揺れる心抱えながら
|
|
678
|
+
# 一歩ずつ前を向いて」
|
|
679
|
+
#
|
|
680
|
+
# **video の映像の展開:**
|
|
681
|
+
# アニメのキャラクターが、暖かみのある居酒屋で複数のビールを前に楽しそうに笑いながら手を振るシーン。
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
> [!NOTE]
|
|
685
|
+
> `qwen3-omni` は audio と video の part を受け付ける。
|
|
686
|
+
> Qwen3-Omni は 1 リクエストにつき audio 入力を最大 *1 つ* しか使わない。
|
|
687
|
+
> video に音声があれば自動で demux されて audio として数えられるため、
|
|
688
|
+
> 音声付き video と別の audio part を同時に渡さないこと。
|
|
689
|
+
|
|
690
|
+
### video + image
|
|
691
|
+
|
|
692
|
+
> [!NOTE]
|
|
693
|
+
> 事前に ffmpeg で1秒間隔のフレーム画像を抽出しておく例:
|
|
694
|
+
> mkdir -p tests/assets/pv_frames
|
|
695
|
+
> ffmpeg -y -i tests/assets/pv.mp4 -vf fps=1 -start_number 1 tests/assets/pv_frames/t%d.jpg
|
|
696
|
+
|
|
697
|
+
```sh
|
|
698
|
+
jq -n \
|
|
699
|
+
--rawfile video <(base64 -i tests/assets/pv.mp4 | tr -d '\n') \
|
|
700
|
+
--slurpfile frames <(
|
|
701
|
+
for i in {1..30}; do
|
|
702
|
+
jq -n --arg i "$i" --rawfile img <(base64 -i "tests/assets/pv_frames/t${i}.jpg" | tr -d '\n') '
|
|
703
|
+
[
|
|
704
|
+
{type: "text", text: "t=[\($i)秒]"},
|
|
705
|
+
{type: "image_url", image_url: {url: "data:image/jpeg;base64,\($img)"}}
|
|
706
|
+
]
|
|
707
|
+
'
|
|
708
|
+
done | jq -s 'flatten'
|
|
709
|
+
) \
|
|
710
|
+
'{
|
|
711
|
+
model: "qwen3-omni",
|
|
712
|
+
messages: [
|
|
713
|
+
{
|
|
714
|
+
role: "user",
|
|
715
|
+
content: (
|
|
716
|
+
[
|
|
717
|
+
{type: "text", text: "まず動画と音声です。"},
|
|
718
|
+
{type: "video_url", video_url: {url: "data:video/mp4;base64,\($video)"}},
|
|
719
|
+
{type: "text", text: "次に、同じ動画から1秒間隔で抜き出した秒数ラベル付きフレームです。"}
|
|
720
|
+
]
|
|
721
|
+
+ $frames[0]
|
|
722
|
+
+ [
|
|
723
|
+
{type: "text", text: "この video の歌詞の一部を短く引用してください。次に、最も印象的・象徴的な瞬間の秒数(t=◯秒)を1つ選んで、その理由を1文で説明してください。"}
|
|
724
|
+
]
|
|
725
|
+
)
|
|
726
|
+
}
|
|
727
|
+
],
|
|
728
|
+
max_completion_tokens: 6000
|
|
729
|
+
}' | \
|
|
730
|
+
curl -sS "http://localhost:${PORT:-8000}/v1/chat/completions" \
|
|
731
|
+
-H 'Content-Type: application/json' \
|
|
732
|
+
--data-binary @- | jq -r '.choices[0].message.content'
|
|
733
|
+
# 詞(一部): 「加速する世界の中から君の声が聞こえてくる」
|
|
734
|
+
#
|
|
735
|
+
# 最も印象的で象徴的な瞬間: t=12秒
|
|
736
|
+
#
|
|
737
|
+
# 説明: 一匹の小さなトカゲが登場し、物語の始まりや新たな道のりを象徴している。
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
> [!NOTE]
|
|
741
|
+
> frame 画像が多いと、レスポンスが不安定になりがち。
|
|
742
|
+
|
|
743
|
+
### video + image + tools
|
|
744
|
+
|
|
745
|
+
```sh
|
|
746
|
+
jq -n \
|
|
747
|
+
--rawfile video <(base64 -i tests/assets/pv.mp4 | tr -d '\n') \
|
|
748
|
+
--slurpfile frames <(
|
|
749
|
+
for i in {1..30}; do
|
|
750
|
+
jq -n --arg i "$i" --rawfile img <(base64 -i "tests/assets/pv_frames/t${i}.jpg" | tr -d '\n') '
|
|
751
|
+
[
|
|
752
|
+
{type: "text", text: "t=\($i)秒"},
|
|
753
|
+
{type: "image_url", image_url: {url: "data:image/jpeg;base64,\($img)"}}
|
|
754
|
+
]
|
|
755
|
+
'
|
|
756
|
+
done | jq -s 'flatten'
|
|
757
|
+
) \
|
|
758
|
+
'{
|
|
759
|
+
model: "qwen3-omni",
|
|
760
|
+
tools: [
|
|
761
|
+
{
|
|
762
|
+
type: "function",
|
|
763
|
+
function: {
|
|
764
|
+
name: "record_highlight",
|
|
765
|
+
description: "動画の中で最も印象的な瞬間の秒数と、その理由を記録する",
|
|
766
|
+
parameters: {
|
|
767
|
+
type: "object",
|
|
768
|
+
properties: {
|
|
769
|
+
timestamp_seconds: {
|
|
770
|
+
type: "integer",
|
|
771
|
+
description: "最も印象的なフレームの秒数(t=◯秒の◯)"
|
|
772
|
+
},
|
|
773
|
+
reason: {
|
|
774
|
+
type: "string",
|
|
775
|
+
description: "その瞬間が印象的な理由(映像と楽曲の両面から)"
|
|
776
|
+
}
|
|
777
|
+
},
|
|
778
|
+
required: ["timestamp_seconds", "reason"]
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
],
|
|
783
|
+
tool_choice: {
|
|
784
|
+
type: "function",
|
|
785
|
+
function: {name: "record_highlight"}
|
|
786
|
+
},
|
|
787
|
+
messages: [
|
|
788
|
+
{
|
|
789
|
+
role: "user",
|
|
790
|
+
content: (
|
|
791
|
+
[
|
|
792
|
+
{type: "text", text: "まず動画と音声です。"},
|
|
793
|
+
{type: "video_url", video_url: {url: "data:video/mp4;base64,\($video)"}},
|
|
794
|
+
{type: "text", text: "次に、同じ動画から1秒間隔で抜き出した秒数ラベル付きフレームです。"}
|
|
795
|
+
]
|
|
796
|
+
+ $frames[0]
|
|
797
|
+
+ [
|
|
798
|
+
{type: "text", text: "映像・楽曲・フレームを分析し、最も印象的・象徴的な瞬間を一つ選んでください。選んだら、その秒数と、その理由を、1文で説明してください。"}
|
|
799
|
+
]
|
|
800
|
+
)
|
|
801
|
+
}
|
|
802
|
+
],
|
|
803
|
+
max_completion_tokens: 6000
|
|
804
|
+
}' | \
|
|
805
|
+
curl -sS "http://localhost:${PORT:-8000}/v1/chat/completions" \
|
|
806
|
+
-H 'Content-Type: application/json' \
|
|
807
|
+
--data-binary @- | jq -r '.choices[0].message'
|
|
808
|
+
# {
|
|
809
|
+
# "role": "assistant",
|
|
810
|
+
# "content": null,
|
|
811
|
+
# "tool_calls": [
|
|
812
|
+
# {
|
|
813
|
+
# "id": "call_58247d6050ca4d11a10fabcc",
|
|
814
|
+
# "type": "function",
|
|
815
|
+
# "function": {
|
|
816
|
+
# "name": "record_highlight",
|
|
817
|
+
# "arguments": "{\"timestamp_seconds\":27, \"reason\": \"この瞬間のカメラの位置が最も安定しており、森の小道を歩くキリンと村の景色をバランスよく捉えており、物語の世界観を象徴的に表現している。\"}"
|
|
818
|
+
# }
|
|
819
|
+
# }
|
|
820
|
+
# ]
|
|
821
|
+
# }
|
|
822
|
+
```
|