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.
Files changed (465) hide show
  1. kiapi/__init__.py +3 -0
  2. kiapi/__main__.py +4 -0
  3. kiapi/api/__init__.py +26 -0
  4. kiapi/api/_constants/require_auth.py +14 -0
  5. kiapi/api/_helpers/build_job_responses.py +73 -0
  6. kiapi/api/_helpers/build_openapi.py +55 -0
  7. kiapi/api/_helpers/build_train_responses.py +21 -0
  8. kiapi/api/_helpers/get_accept.py +20 -0
  9. kiapi/api/_helpers/get_ctx.py +7 -0
  10. kiapi/api/_helpers/get_worker.py +7 -0
  11. kiapi/api/_helpers/register_capability_endpoints.py +70 -0
  12. kiapi/api/_helpers/submit_and_maybe_wait.py +113 -0
  13. kiapi/api/_settings.py +50 -0
  14. kiapi/api/_views/async_job_response.py +21 -0
  15. kiapi/api/_views/capability_model_spec.py +49 -0
  16. kiapi/api/app.py +150 -0
  17. kiapi/api/audio/acestep/_views/extract_response.py +57 -0
  18. kiapi/api/audio/acestep/_views/track_response.py +57 -0
  19. kiapi/api/audio/acestep/router.py +190 -0
  20. kiapi/api/audio/audiogen/_views/audio_response.py +46 -0
  21. kiapi/api/audio/audiogen/router.py +77 -0
  22. kiapi/api/chat/_views/chat_completion_response.py +71 -0
  23. kiapi/api/chat/router.py +253 -0
  24. kiapi/api/embedding/_views/embedding_response.py +35 -0
  25. kiapi/api/embedding/router.py +82 -0
  26. kiapi/api/files/_operations/get_file.py +14 -0
  27. kiapi/api/files/_operations/get_file_id.py +18 -0
  28. kiapi/api/files/_views/file_delete_response.py +14 -0
  29. kiapi/api/files/_views/file_list_response.py +15 -0
  30. kiapi/api/files/router.py +105 -0
  31. kiapi/api/health/_views/health_response.py +26 -0
  32. kiapi/api/health/router.py +28 -0
  33. kiapi/api/image/depthpro/_views/estimate_response.py +70 -0
  34. kiapi/api/image/depthpro/router.py +81 -0
  35. kiapi/api/image/ernie/_views/image_response.py +50 -0
  36. kiapi/api/image/ernie/router.py +181 -0
  37. kiapi/api/image/flux2/_views/image_response.py +53 -0
  38. kiapi/api/image/flux2/router.py +197 -0
  39. kiapi/api/image/ideogram4/_views/image_response.py +55 -0
  40. kiapi/api/image/ideogram4/router.py +87 -0
  41. kiapi/api/image/qwen/_views/image_response.py +47 -0
  42. kiapi/api/image/qwen/router.py +141 -0
  43. kiapi/api/image/seedvr2/_views/image_response.py +50 -0
  44. kiapi/api/image/seedvr2/router.py +83 -0
  45. kiapi/api/image/zimage/_views/image_response.py +49 -0
  46. kiapi/api/image/zimage/router.py +131 -0
  47. kiapi/api/jobs/_operations/get_job_id.py +18 -0
  48. kiapi/api/jobs/_views/job_delete_response.py +19 -0
  49. kiapi/api/jobs/_views/job_list_response.py +15 -0
  50. kiapi/api/jobs/router.py +62 -0
  51. kiapi/api/models/_schemas/openai_model_spec.py +26 -0
  52. kiapi/api/models/_views/model_list_response.py +15 -0
  53. kiapi/api/models/router.py +29 -0
  54. kiapi/api/video/ltx2/_views/__init__.py +1 -0
  55. kiapi/api/video/ltx2/_views/video_response.py +59 -0
  56. kiapi/api/video/ltx2/router.py +89 -0
  57. kiapi/api/web/_views/__init__.py +7 -0
  58. kiapi/api/web/_views/fetch_api_request.py +26 -0
  59. kiapi/api/web/_views/fetch_error_response.py +25 -0
  60. kiapi/api/web/router.py +302 -0
  61. kiapi/capabilities/__init__.py +24 -0
  62. kiapi/capabilities/_exceptions/CapabilityError.py +2 -0
  63. kiapi/capabilities/_exceptions/ValidationError.py +2 -0
  64. kiapi/capabilities/_helpers/attach_mflux_progress.py +50 -0
  65. kiapi/capabilities/_helpers/get_file_path.py +20 -0
  66. kiapi/capabilities/_helpers/resolve_file_ref.py +16 -0
  67. kiapi/capabilities/acestep/README.ja.md +174 -0
  68. kiapi/capabilities/acestep/README.md +167 -0
  69. kiapi/capabilities/acestep/__init__.py +37 -0
  70. kiapi/capabilities/acestep/_constants/description.py +122 -0
  71. kiapi/capabilities/acestep/_exceptions/ace_step_engine_error.py +2 -0
  72. kiapi/capabilities/acestep/_helpers/register.py +96 -0
  73. kiapi/capabilities/acestep/_models/acestep.py +105 -0
  74. kiapi/capabilities/acestep/_operations/handle_cover.py +23 -0
  75. kiapi/capabilities/acestep/_operations/handle_extract.py +38 -0
  76. kiapi/capabilities/acestep/_operations/handle_generate.py +18 -0
  77. kiapi/capabilities/acestep/_operations/handle_repaint.py +25 -0
  78. kiapi/capabilities/acestep/_operations/resolve_ace_step_paths.py +30 -0
  79. kiapi/capabilities/acestep/_operations/resolve_cover_params.py +21 -0
  80. kiapi/capabilities/acestep/_operations/resolve_engine.py +10 -0
  81. kiapi/capabilities/acestep/_operations/resolve_extract_params.py +24 -0
  82. kiapi/capabilities/acestep/_operations/resolve_generate_params.py +18 -0
  83. kiapi/capabilities/acestep/_operations/resolve_repaint_params.py +22 -0
  84. kiapi/capabilities/acestep/_schemas/ace_step_paths.py +29 -0
  85. kiapi/capabilities/acestep/_services/ace_step_engine.py +143 -0
  86. kiapi/capabilities/acestep/_settings.py +82 -0
  87. kiapi/capabilities/acestep/_views/ace_step_base.py +61 -0
  88. kiapi/capabilities/acestep/_views/cover_params.py +26 -0
  89. kiapi/capabilities/acestep/_views/cover_request.py +49 -0
  90. kiapi/capabilities/acestep/_views/extract_params.py +24 -0
  91. kiapi/capabilities/acestep/_views/extract_request.py +33 -0
  92. kiapi/capabilities/acestep/_views/generate_params.py +25 -0
  93. kiapi/capabilities/acestep/_views/generate_request.py +54 -0
  94. kiapi/capabilities/acestep/_views/repaint_params.py +27 -0
  95. kiapi/capabilities/acestep/_views/repaint_request.py +51 -0
  96. kiapi/capabilities/acestep/_views/track_params.py +7 -0
  97. kiapi/capabilities/acestep/worker_subprocess.py +247 -0
  98. kiapi/capabilities/audiogen/README.ja.md +49 -0
  99. kiapi/capabilities/audiogen/README.md +48 -0
  100. kiapi/capabilities/audiogen/__init__.py +25 -0
  101. kiapi/capabilities/audiogen/_constants/description.py +60 -0
  102. kiapi/capabilities/audiogen/_helpers/attach_audiogen_progress.py +27 -0
  103. kiapi/capabilities/audiogen/_helpers/register.py +42 -0
  104. kiapi/capabilities/audiogen/_helpers/validate_generate.py +14 -0
  105. kiapi/capabilities/audiogen/_models/audiogen.py +98 -0
  106. kiapi/capabilities/audiogen/_operations/handle_generate.py +27 -0
  107. kiapi/capabilities/audiogen/_operations/resolve_generate_params.py +25 -0
  108. kiapi/capabilities/audiogen/_settings.py +34 -0
  109. kiapi/capabilities/audiogen/_views/generate_params.py +14 -0
  110. kiapi/capabilities/audiogen/_views/generate_request.py +96 -0
  111. kiapi/capabilities/chat/README.ja.md +822 -0
  112. kiapi/capabilities/chat/README.md +806 -0
  113. kiapi/capabilities/chat/__init__.py +25 -0
  114. kiapi/capabilities/chat/_constants/description.py +163 -0
  115. kiapi/capabilities/chat/_helpers/register.py +67 -0
  116. kiapi/capabilities/chat/_models/qwen3_5.py +183 -0
  117. kiapi/capabilities/chat/_models/qwen3_omni.py +242 -0
  118. kiapi/capabilities/chat/_operations/apply_template.py +74 -0
  119. kiapi/capabilities/chat/_operations/completed_hermes_tool_call_text.py +9 -0
  120. kiapi/capabilities/chat/_operations/emit_streaming_response.py +297 -0
  121. kiapi/capabilities/chat/_operations/ensure_streaming_detokenizer_compat.py +49 -0
  122. kiapi/capabilities/chat/_operations/format_response.py +72 -0
  123. kiapi/capabilities/chat/_operations/handle_chat.py +25 -0
  124. kiapi/capabilities/chat/_operations/parse_hermes_tool_calls.py +63 -0
  125. kiapi/capabilities/chat/_operations/parse_json_tool_calls.py +66 -0
  126. kiapi/capabilities/chat/_operations/parse_messages.py +326 -0
  127. kiapi/capabilities/chat/_operations/resolve_chat_params.py +50 -0
  128. kiapi/capabilities/chat/_operations/stream_text_from_tokens.py +32 -0
  129. kiapi/capabilities/chat/_operations/strip_tool_calls.py +15 -0
  130. kiapi/capabilities/chat/_settings.py +74 -0
  131. kiapi/capabilities/chat/_utils/apply_parallel_tool_call_policy.py +17 -0
  132. kiapi/capabilities/chat/_utils/apply_seed.py +8 -0
  133. kiapi/capabilities/chat/_utils/load_audio_mono.py +31 -0
  134. kiapi/capabilities/chat/_utils/load_mlx_vlm.py +12 -0
  135. kiapi/capabilities/chat/_utils/warmup_params.py +26 -0
  136. kiapi/capabilities/chat/_views/chat_params.py +34 -0
  137. kiapi/capabilities/chat/_views/chat_request.py +153 -0
  138. kiapi/capabilities/depthpro/README.ja.md +131 -0
  139. kiapi/capabilities/depthpro/README.md +124 -0
  140. kiapi/capabilities/depthpro/__init__.py +23 -0
  141. kiapi/capabilities/depthpro/_constants/description.py +39 -0
  142. kiapi/capabilities/depthpro/_helpers/register.py +46 -0
  143. kiapi/capabilities/depthpro/_helpers/validate_estimate.py +32 -0
  144. kiapi/capabilities/depthpro/_models/depthpro.py +144 -0
  145. kiapi/capabilities/depthpro/_operations/handle_estimate.py +50 -0
  146. kiapi/capabilities/depthpro/_operations/is_quantize_override.py +12 -0
  147. kiapi/capabilities/depthpro/_operations/resolve_estimate_params.py +24 -0
  148. kiapi/capabilities/depthpro/_settings.py +46 -0
  149. kiapi/capabilities/depthpro/_views/estimate_params.py +21 -0
  150. kiapi/capabilities/depthpro/_views/estimate_request.py +63 -0
  151. kiapi/capabilities/embedding/README.ja.md +137 -0
  152. kiapi/capabilities/embedding/README.md +128 -0
  153. kiapi/capabilities/embedding/__init__.py +24 -0
  154. kiapi/capabilities/embedding/_constants/description.py +47 -0
  155. kiapi/capabilities/embedding/_helpers/register.py +66 -0
  156. kiapi/capabilities/embedding/_models/qwen3_text.py +53 -0
  157. kiapi/capabilities/embedding/_models/qwen3_vl.py +97 -0
  158. kiapi/capabilities/embedding/_operations/format_response.py +24 -0
  159. kiapi/capabilities/embedding/_operations/handle_embed.py +24 -0
  160. kiapi/capabilities/embedding/_operations/parse_inputs.py +108 -0
  161. kiapi/capabilities/embedding/_operations/resolve_embed_params.py +18 -0
  162. kiapi/capabilities/embedding/_settings.py +27 -0
  163. kiapi/capabilities/embedding/_utils/to_vector.py +20 -0
  164. kiapi/capabilities/embedding/_views/embed_params.py +17 -0
  165. kiapi/capabilities/embedding/_views/embed_request.py +39 -0
  166. kiapi/capabilities/ernie/README.ja.md +242 -0
  167. kiapi/capabilities/ernie/README.md +223 -0
  168. kiapi/capabilities/ernie/__init__.py +34 -0
  169. kiapi/capabilities/ernie/_constants/description.py +71 -0
  170. kiapi/capabilities/ernie/_helpers/register.py +60 -0
  171. kiapi/capabilities/ernie/_helpers/validate_edit.py +19 -0
  172. kiapi/capabilities/ernie/_helpers/validate_generate.py +8 -0
  173. kiapi/capabilities/ernie/_models/ernie.py +356 -0
  174. kiapi/capabilities/ernie/_operations/handle_edit.py +39 -0
  175. kiapi/capabilities/ernie/_operations/handle_generate.py +38 -0
  176. kiapi/capabilities/ernie/_operations/handle_train.py +77 -0
  177. kiapi/capabilities/ernie/_operations/is_quantize_override.py +16 -0
  178. kiapi/capabilities/ernie/_operations/resolve_edit_params.py +44 -0
  179. kiapi/capabilities/ernie/_operations/resolve_generate_params.py +40 -0
  180. kiapi/capabilities/ernie/_operations/resolve_lora_params.py +23 -0
  181. kiapi/capabilities/ernie/_operations/resolve_train_params.py +43 -0
  182. kiapi/capabilities/ernie/_operations/validate_common.py +33 -0
  183. kiapi/capabilities/ernie/_schemas/lora_ref.py +27 -0
  184. kiapi/capabilities/ernie/_settings.py +151 -0
  185. kiapi/capabilities/ernie/_views/edit_params.py +36 -0
  186. kiapi/capabilities/ernie/_views/edit_request.py +142 -0
  187. kiapi/capabilities/ernie/_views/generate_params.py +32 -0
  188. kiapi/capabilities/ernie/_views/generate_request.py +127 -0
  189. kiapi/capabilities/ernie/_views/train_params.py +28 -0
  190. kiapi/capabilities/ernie/_views/train_request.py +96 -0
  191. kiapi/capabilities/flux2/README.ja.md +260 -0
  192. kiapi/capabilities/flux2/README.md +241 -0
  193. kiapi/capabilities/flux2/__init__.py +36 -0
  194. kiapi/capabilities/flux2/_constants/description.py +81 -0
  195. kiapi/capabilities/flux2/_helpers/register.py +98 -0
  196. kiapi/capabilities/flux2/_helpers/validate_edit.py +12 -0
  197. kiapi/capabilities/flux2/_helpers/validate_generate.py +8 -0
  198. kiapi/capabilities/flux2/_models/flux2.py +396 -0
  199. kiapi/capabilities/flux2/_operations/handle_edit.py +44 -0
  200. kiapi/capabilities/flux2/_operations/handle_generate.py +46 -0
  201. kiapi/capabilities/flux2/_operations/handle_train.py +105 -0
  202. kiapi/capabilities/flux2/_operations/is_quantize_override.py +16 -0
  203. kiapi/capabilities/flux2/_operations/resolve_edit_params.py +43 -0
  204. kiapi/capabilities/flux2/_operations/resolve_generate_params.py +44 -0
  205. kiapi/capabilities/flux2/_operations/resolve_lora_params.py +23 -0
  206. kiapi/capabilities/flux2/_operations/resolve_train_params.py +42 -0
  207. kiapi/capabilities/flux2/_operations/role_spec.py +13 -0
  208. kiapi/capabilities/flux2/_operations/split_repo.py +11 -0
  209. kiapi/capabilities/flux2/_operations/validate_common.py +35 -0
  210. kiapi/capabilities/flux2/_schemas/lora_ref.py +27 -0
  211. kiapi/capabilities/flux2/_settings.py +181 -0
  212. kiapi/capabilities/flux2/_views/edit_params.py +36 -0
  213. kiapi/capabilities/flux2/_views/edit_request.py +145 -0
  214. kiapi/capabilities/flux2/_views/generate_params.py +36 -0
  215. kiapi/capabilities/flux2/_views/generate_request.py +150 -0
  216. kiapi/capabilities/flux2/_views/train_params.py +32 -0
  217. kiapi/capabilities/flux2/_views/train_request.py +102 -0
  218. kiapi/capabilities/ideogram4/README.ja.md +230 -0
  219. kiapi/capabilities/ideogram4/README.md +219 -0
  220. kiapi/capabilities/ideogram4/__init__.py +24 -0
  221. kiapi/capabilities/ideogram4/_constants/description.py +65 -0
  222. kiapi/capabilities/ideogram4/_helpers/register.py +44 -0
  223. kiapi/capabilities/ideogram4/_helpers/validate_generate.py +31 -0
  224. kiapi/capabilities/ideogram4/_models/ideogram4.py +120 -0
  225. kiapi/capabilities/ideogram4/_operations/handle_generate.py +30 -0
  226. kiapi/capabilities/ideogram4/_operations/is_quantize_override.py +12 -0
  227. kiapi/capabilities/ideogram4/_operations/resolve_generate_params.py +30 -0
  228. kiapi/capabilities/ideogram4/_settings.py +89 -0
  229. kiapi/capabilities/ideogram4/_views/generate_params.py +27 -0
  230. kiapi/capabilities/ideogram4/_views/generate_request.py +118 -0
  231. kiapi/capabilities/ltx2/README.ja.md +287 -0
  232. kiapi/capabilities/ltx2/README.md +274 -0
  233. kiapi/capabilities/ltx2/__init__.py +26 -0
  234. kiapi/capabilities/ltx2/_constants/description.py +81 -0
  235. kiapi/capabilities/ltx2/_helpers/register.py +58 -0
  236. kiapi/capabilities/ltx2/_helpers/validate_generate.py +42 -0
  237. kiapi/capabilities/ltx2/_models/ltx2.py +106 -0
  238. kiapi/capabilities/ltx2/_operations/detect_mode.py +19 -0
  239. kiapi/capabilities/ltx2/_operations/handle_generate.py +52 -0
  240. kiapi/capabilities/ltx2/_operations/resolve_generate_params.py +31 -0
  241. kiapi/capabilities/ltx2/_settings.py +93 -0
  242. kiapi/capabilities/ltx2/_views/generate_params.py +34 -0
  243. kiapi/capabilities/ltx2/_views/generate_request.py +151 -0
  244. kiapi/capabilities/qwen/README.ja.md +251 -0
  245. kiapi/capabilities/qwen/README.md +235 -0
  246. kiapi/capabilities/qwen/__init__.py +30 -0
  247. kiapi/capabilities/qwen/_constants/description.py +53 -0
  248. kiapi/capabilities/qwen/_helpers/register.py +60 -0
  249. kiapi/capabilities/qwen/_helpers/validate_edit.py +12 -0
  250. kiapi/capabilities/qwen/_helpers/validate_generate.py +12 -0
  251. kiapi/capabilities/qwen/_models/qwen.py +224 -0
  252. kiapi/capabilities/qwen/_operations/handle_edit.py +44 -0
  253. kiapi/capabilities/qwen/_operations/handle_generate.py +46 -0
  254. kiapi/capabilities/qwen/_operations/is_quantize_override.py +15 -0
  255. kiapi/capabilities/qwen/_operations/resolve_edit_params.py +35 -0
  256. kiapi/capabilities/qwen/_operations/resolve_generate_params.py +39 -0
  257. kiapi/capabilities/qwen/_operations/resolve_lora_params.py +23 -0
  258. kiapi/capabilities/qwen/_operations/validate_common.py +32 -0
  259. kiapi/capabilities/qwen/_schemas/lora_ref.py +27 -0
  260. kiapi/capabilities/qwen/_settings.py +107 -0
  261. kiapi/capabilities/qwen/_views/edit_params.py +36 -0
  262. kiapi/capabilities/qwen/_views/edit_request.py +138 -0
  263. kiapi/capabilities/qwen/_views/generate_params.py +37 -0
  264. kiapi/capabilities/qwen/_views/generate_request.py +149 -0
  265. kiapi/capabilities/seedvr2/README.ja.md +234 -0
  266. kiapi/capabilities/seedvr2/README.md +219 -0
  267. kiapi/capabilities/seedvr2/__init__.py +24 -0
  268. kiapi/capabilities/seedvr2/_constants/description.py +46 -0
  269. kiapi/capabilities/seedvr2/_helpers/register.py +60 -0
  270. kiapi/capabilities/seedvr2/_helpers/validate_upscale.py +52 -0
  271. kiapi/capabilities/seedvr2/_models/seedvr2.py +140 -0
  272. kiapi/capabilities/seedvr2/_operations/handle_upscale.py +42 -0
  273. kiapi/capabilities/seedvr2/_operations/is_quantize_override.py +12 -0
  274. kiapi/capabilities/seedvr2/_operations/resolve_upscale_params.py +30 -0
  275. kiapi/capabilities/seedvr2/_settings.py +74 -0
  276. kiapi/capabilities/seedvr2/_views/upscale_params.py +27 -0
  277. kiapi/capabilities/seedvr2/_views/upscale_request.py +94 -0
  278. kiapi/capabilities/web/README.ja.md +187 -0
  279. kiapi/capabilities/web/README.md +171 -0
  280. kiapi/capabilities/web/__init__.py +30 -0
  281. kiapi/capabilities/web/_constants/description.py +38 -0
  282. kiapi/capabilities/web/_exceptions/FetchError.py +24 -0
  283. kiapi/capabilities/web/_exceptions/SearchBackendError.py +11 -0
  284. kiapi/capabilities/web/_helpers/register.py +59 -0
  285. kiapi/capabilities/web/_models/crawl4ai.py +32 -0
  286. kiapi/capabilities/web/_models/searxng.py +44 -0
  287. kiapi/capabilities/web/_operations/handle_fetch.py +145 -0
  288. kiapi/capabilities/web/_operations/handle_search.py +56 -0
  289. kiapi/capabilities/web/_operations/resolve_fetch_params.py +19 -0
  290. kiapi/capabilities/web/_operations/resolve_search_params.py +34 -0
  291. kiapi/capabilities/web/_operations/resolve_searxng_config_dir.py +21 -0
  292. kiapi/capabilities/web/_services/__init__.py +1 -0
  293. kiapi/capabilities/web/_services/web_backend_process.py +144 -0
  294. kiapi/capabilities/web/_settings.py +138 -0
  295. kiapi/capabilities/web/_views/fetch_params.py +27 -0
  296. kiapi/capabilities/web/_views/fetch_request.py +29 -0
  297. kiapi/capabilities/web/_views/fetch_result.py +20 -0
  298. kiapi/capabilities/web/_views/search_params.py +43 -0
  299. kiapi/capabilities/web/_views/search_request.py +93 -0
  300. kiapi/capabilities/web/_views/search_response.py +49 -0
  301. kiapi/capabilities/web/resources/__init__.py +0 -0
  302. kiapi/capabilities/web/resources/searxng/__init__.py +0 -0
  303. kiapi/capabilities/web/resources/searxng/settings.yml +11 -0
  304. kiapi/capabilities/zimage/README.ja.md +249 -0
  305. kiapi/capabilities/zimage/README.md +231 -0
  306. kiapi/capabilities/zimage/__init__.py +34 -0
  307. kiapi/capabilities/zimage/_constants/description.py +73 -0
  308. kiapi/capabilities/zimage/_helpers/register.py +62 -0
  309. kiapi/capabilities/zimage/_helpers/validate_generate.py +37 -0
  310. kiapi/capabilities/zimage/_models/zimage.py +278 -0
  311. kiapi/capabilities/zimage/_operations/handle_generate.py +38 -0
  312. kiapi/capabilities/zimage/_operations/handle_train.py +78 -0
  313. kiapi/capabilities/zimage/_operations/is_quantize_override.py +11 -0
  314. kiapi/capabilities/zimage/_operations/resolve_generate_params.py +39 -0
  315. kiapi/capabilities/zimage/_operations/resolve_lora_params.py +23 -0
  316. kiapi/capabilities/zimage/_operations/resolve_train_params.py +38 -0
  317. kiapi/capabilities/zimage/_schemas/lora_ref.py +27 -0
  318. kiapi/capabilities/zimage/_settings.py +166 -0
  319. kiapi/capabilities/zimage/_views/generate_params.py +23 -0
  320. kiapi/capabilities/zimage/_views/generate_request.py +127 -0
  321. kiapi/capabilities/zimage/_views/train_params.py +22 -0
  322. kiapi/capabilities/zimage/_views/train_request.py +101 -0
  323. kiapi/cli/__init__.py +11 -0
  324. kiapi/cli/_helpers/dedupe_resources.py +12 -0
  325. kiapi/cli/_helpers/register_all_capabilities.py +36 -0
  326. kiapi/cli/_helpers/run_resources.py +24 -0
  327. kiapi/cli/_helpers/select_specs.py +67 -0
  328. kiapi/cli/activate/_operations/preflight_hf_access.py +129 -0
  329. kiapi/cli/activate/cli.py +37 -0
  330. kiapi/cli/check/_helpers/check_audio_acestep_turbo.py +22 -0
  331. kiapi/cli/check/_helpers/check_audio_acestep_xl_base.py +22 -0
  332. kiapi/cli/check/_helpers/check_audio_audiogen_medium.py +24 -0
  333. kiapi/cli/check/_helpers/check_chat_chat_qwen3_6_27b.py +19 -0
  334. kiapi/cli/check/_helpers/check_chat_chat_qwen3_omni.py +19 -0
  335. kiapi/cli/check/_helpers/check_embedding_embedding_qwen3_embedding_8b.py +14 -0
  336. kiapi/cli/check/_helpers/check_embedding_embedding_qwen3_vl_embedding_2b.py +19 -0
  337. kiapi/cli/check/_helpers/check_image_depthpro_base.py +21 -0
  338. kiapi/cli/check/_helpers/check_image_ernie_base.py +23 -0
  339. kiapi/cli/check/_helpers/check_image_ernie_turbo.py +23 -0
  340. kiapi/cli/check/_helpers/check_image_flux2_klein_9b.py +23 -0
  341. kiapi/cli/check/_helpers/check_image_flux2_klein_base_4b.py +23 -0
  342. kiapi/cli/check/_helpers/check_image_flux2_klein_base_9b.py +23 -0
  343. kiapi/cli/check/_helpers/check_image_ideogram4_fp8.py +23 -0
  344. kiapi/cli/check/_helpers/check_image_qwen_edit_2509.py +27 -0
  345. kiapi/cli/check/_helpers/check_image_qwen_image.py +23 -0
  346. kiapi/cli/check/_helpers/check_image_seedvr2_3b.py +23 -0
  347. kiapi/cli/check/_helpers/check_image_seedvr2_7b.py +23 -0
  348. kiapi/cli/check/_helpers/check_image_zimage_base.py +23 -0
  349. kiapi/cli/check/_helpers/check_image_zimage_turbo.py +23 -0
  350. kiapi/cli/check/_helpers/check_video_ltx2_distilled.py +26 -0
  351. kiapi/cli/check/_helpers/check_web_web_fetch.py +14 -0
  352. kiapi/cli/check/_helpers/check_web_web_search.py +14 -0
  353. kiapi/cli/check/_operations/build_check_result.py +20 -0
  354. kiapi/cli/check/_operations/check_context.py +10 -0
  355. kiapi/cli/check/_operations/create_sample_image.py +46 -0
  356. kiapi/cli/check/_schemas/check_result.py +12 -0
  357. kiapi/cli/check/cli.py +89 -0
  358. kiapi/cli/cli.py +29 -0
  359. kiapi/cli/config/cli.py +17 -0
  360. kiapi/cli/config/edit/cli.py +32 -0
  361. kiapi/cli/config/init/cli.py +33 -0
  362. kiapi/cli/config/show/cli.py +13 -0
  363. kiapi/cli/config/template/cli.py +36 -0
  364. kiapi/cli/deactivate/cli.py +49 -0
  365. kiapi/cli/run/asgi.py +16 -0
  366. kiapi/cli/run/cli.py +59 -0
  367. kiapi/cli/service/__init__.py +5 -0
  368. kiapi/cli/service/_services/service_manager.py +107 -0
  369. kiapi/cli/service/cli.py +19 -0
  370. kiapi/cli/service/install/cli.py +17 -0
  371. kiapi/cli/service/start/cli.py +22 -0
  372. kiapi/cli/service/status/cli.py +81 -0
  373. kiapi/cli/service/stop/cli.py +19 -0
  374. kiapi/cli/service/uninstall/cli.py +16 -0
  375. kiapi/cli/status/cli.py +226 -0
  376. kiapi/core/app/__init__.py +16 -0
  377. kiapi/core/app/_schemas/app_context.py +28 -0
  378. kiapi/core/app/_services/user_directory.py +59 -0
  379. kiapi/core/app/_settings.py +46 -0
  380. kiapi/core/capability/__init__.py +11 -0
  381. kiapi/core/capability/_schemas/capability_spec.py +17 -0
  382. kiapi/core/capability/_services/capability_spec_registry.py +21 -0
  383. kiapi/core/config/__init__.py +11 -0
  384. kiapi/core/config/_exceptions/user_config_error.py +2 -0
  385. kiapi/core/config/_helpers/get_user_settings_path.py +7 -0
  386. kiapi/core/config/_helpers/load_user_settings.py +54 -0
  387. kiapi/core/file/__init__.py +37 -0
  388. kiapi/core/file/_helpers/create_file_store.py +7 -0
  389. kiapi/core/file/_helpers/resolve_file_ref.py +90 -0
  390. kiapi/core/file/_schemas/file_data_url_ref.py +19 -0
  391. kiapi/core/file/_schemas/file_id_ref.py +16 -0
  392. kiapi/core/file/_schemas/file_record.py +46 -0
  393. kiapi/core/file/_schemas/file_url_ref.py +16 -0
  394. kiapi/core/file/_services/file_store.py +138 -0
  395. kiapi/core/file/_settings.py +22 -0
  396. kiapi/core/file/_types/file_id.py +2 -0
  397. kiapi/core/file/_types/file_ref.py +12 -0
  398. kiapi/core/file/_views/resolved_file_ref.py +16 -0
  399. kiapi/core/job/__init__.py +24 -0
  400. kiapi/core/job/_enums/job_status.py +9 -0
  401. kiapi/core/job/_helpers/creep_progress.py +123 -0
  402. kiapi/core/job/_models/job.py +121 -0
  403. kiapi/core/job/_services/job_store.py +33 -0
  404. kiapi/core/job/_services/progress_reporter.py +79 -0
  405. kiapi/core/job/_types/job_id.py +3 -0
  406. kiapi/core/job/_types/job_result.py +5 -0
  407. kiapi/core/job/_types/job_type.py +4 -0
  408. kiapi/core/logging/__init__.py +14 -0
  409. kiapi/core/logging/_helpers/get_log_level.py +8 -0
  410. kiapi/core/logging/_helpers/setup_logger.py +14 -0
  411. kiapi/core/logging/_settings.py +34 -0
  412. kiapi/core/logging/_types/log_level.py +3 -0
  413. kiapi/core/memory/__init__.py +21 -0
  414. kiapi/core/memory/_exceptions/memory_budget_error.py +2 -0
  415. kiapi/core/memory/_helpers/create_memory_manager.py +17 -0
  416. kiapi/core/memory/_operations/log_memory_limit.py +29 -0
  417. kiapi/core/memory/_operations/resolve_effective_memory_limit_gb.py +13 -0
  418. kiapi/core/memory/_operations/resolve_framework_strategy.py +42 -0
  419. kiapi/core/memory/_schemas/framework_strategy.py +14 -0
  420. kiapi/core/memory/_schemas/memory_stats.py +24 -0
  421. kiapi/core/memory/_schemas/resident_model.py +14 -0
  422. kiapi/core/memory/_schemas/resident_model_stats.py +49 -0
  423. kiapi/core/memory/_services/memory_manager.py +257 -0
  424. kiapi/core/memory/_settings.py +36 -0
  425. kiapi/core/memory/_types/framework_name.py +4 -0
  426. kiapi/core/memory/_types/resident_key.py +4 -0
  427. kiapi/core/model/__init__.py +36 -0
  428. kiapi/core/model/_exceptions/unknown_model_error.py +2 -0
  429. kiapi/core/model/_schemas/model_spec.py +145 -0
  430. kiapi/core/model/_services/model_registry.py +85 -0
  431. kiapi/core/model/_types/model_alias.py +2 -0
  432. kiapi/core/model/_types/model_domain.py +6 -0
  433. kiapi/core/model/_types/model_family.py +5 -0
  434. kiapi/core/model/_types/model_key.py +8 -0
  435. kiapi/core/model/_types/model_name.py +4 -0
  436. kiapi/core/model/_types/model_repo.py +3 -0
  437. kiapi/core/net/__init__.py +16 -0
  438. kiapi/core/net/_exceptions/unsafe_url_error.py +7 -0
  439. kiapi/core/net/_helpers/verify_public_url.py +68 -0
  440. kiapi/core/net/_settings.py +28 -0
  441. kiapi/core/setup/__init__.py +25 -0
  442. kiapi/core/setup/_exceptions/setup_required_error.py +2 -0
  443. kiapi/core/setup/_schemas/docker_image_resource.py +37 -0
  444. kiapi/core/setup/_schemas/hf_snapshot_resource.py +50 -0
  445. kiapi/core/setup/_schemas/local_path_resource.py +43 -0
  446. kiapi/core/setup/_schemas/python_package_resource.py +58 -0
  447. kiapi/core/setup/_schemas/python_venv_resource.py +63 -0
  448. kiapi/core/setup/_schemas/setup_status.py +7 -0
  449. kiapi/core/setup/_schemas/url_file_resource.py +43 -0
  450. kiapi/core/setup/_services/setup_manager.py +331 -0
  451. kiapi/core/setup/_types/setup_resource.py +21 -0
  452. kiapi/core/setup/_types/setup_target.py +11 -0
  453. kiapi/core/workdir/__init__.py +8 -0
  454. kiapi/core/workdir/_helpers/create_work_dir.py +11 -0
  455. kiapi/core/workdir/_settings.py +21 -0
  456. kiapi/core/worker/__init__.py +23 -0
  457. kiapi/core/worker/_helpers/create_worker.py +9 -0
  458. kiapi/core/worker/_services/worker.py +165 -0
  459. kiapi/core/worker/_settings.py +36 -0
  460. kiapi/core/worker/_types/job_thunk.py +6 -0
  461. kiapi-0.1.0.dist-info/METADATA +337 -0
  462. kiapi-0.1.0.dist-info/RECORD +465 -0
  463. kiapi-0.1.0.dist-info/WHEEL +4 -0
  464. kiapi-0.1.0.dist-info/entry_points.txt +2 -0
  465. 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
+ ```