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,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
+ ```