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,356 @@
1
+ """Handler for ERNIE-Image generation/edit/training via mflux."""
2
+
3
+ import gc
4
+ import json
5
+ import time
6
+ from pathlib import Path
7
+ from types import SimpleNamespace
8
+ from typing import Any
9
+
10
+ from kiapi.capabilities import attach_mflux_progress
11
+ from kiapi.core.file import FileStore
12
+ from kiapi.core.model import ModelSpec
13
+ from kiapi.core.workdir import create_work_dir
14
+
15
+ from .._views.edit_params import EditParams
16
+ from .._views.generate_params import GenerateParams
17
+ from .._views.train_params import TrainParams
18
+
19
+ FEATURES = {"text", "image"}
20
+
21
+
22
+ def _model_name(spec: ModelSpec) -> str:
23
+ return "ernie-image" if spec.name == "base" else "ernie-image-turbo"
24
+
25
+
26
+ def _model_config(spec: ModelSpec) -> Any:
27
+ from mflux.models.common.config import ModelConfig # type: ignore
28
+
29
+ return (
30
+ ModelConfig.ernie_image()
31
+ if spec.name == "base"
32
+ else ModelConfig.ernie_image_turbo()
33
+ )
34
+
35
+
36
+ def build_model(
37
+ spec: ModelSpec,
38
+ *,
39
+ quantize: int | None,
40
+ lora_paths: list[str] | None = None,
41
+ lora_scales: list[float] | None = None,
42
+ ) -> Any:
43
+ from mflux.models.ernie_image import ErnieImage # type: ignore
44
+
45
+ return ErnieImage(
46
+ quantize=quantize,
47
+ model_path=spec.repo,
48
+ lora_paths=lora_paths or None,
49
+ lora_scales=lora_scales or None,
50
+ model_config=_model_config(spec),
51
+ )
52
+
53
+
54
+ def load(spec: ModelSpec) -> SimpleNamespace:
55
+ from .._settings import settings_manager
56
+
57
+ quantize = settings_manager.get_settings().default_quantize.get(spec.name)
58
+ model = build_model(spec, quantize=quantize)
59
+ return SimpleNamespace(model=model, spec=spec, quantize=quantize)
60
+
61
+
62
+ def warmup(payload: SimpleNamespace) -> None:
63
+ payload.model.generate_image(
64
+ seed=0, prompt="warmup", num_inference_steps=1, width=256, height=256
65
+ )
66
+
67
+
68
+ def _store_image(
69
+ image: Any,
70
+ *,
71
+ fmt: str,
72
+ quality: int,
73
+ files: FileStore,
74
+ meta: dict[str, Any],
75
+ ) -> dict[str, Any]:
76
+ pil = getattr(image, "image", image)
77
+ ext = "jpg" if fmt == "jpeg" else fmt
78
+ tmp_dir = create_work_dir("image/ernie")
79
+ out_path = tmp_dir / f"image.{ext}"
80
+ save_kwargs: dict[str, Any] = {}
81
+ if fmt in ("jpeg", "webp"):
82
+ save_kwargs["quality"] = quality
83
+ if fmt == "jpeg":
84
+ pil = pil.convert("RGB")
85
+ pil.save(out_path, format=fmt.upper(), **save_kwargs)
86
+ if not out_path.exists():
87
+ raise RuntimeError("generation finished but no image file was produced")
88
+ rec = files.put_path(
89
+ out_path,
90
+ filename=f"ernie_{int(time.time())}.{ext}",
91
+ content_type=f"image/{fmt}",
92
+ meta=meta,
93
+ move=True,
94
+ )
95
+ return {"file_id": rec.file_id, "image_bytes": rec.size, **meta}
96
+
97
+
98
+ def _generate(model: Any, params: GenerateParams, files: FileStore) -> dict[str, Any]:
99
+ t0 = time.time()
100
+ attach_mflux_progress(model)
101
+ image = model.generate_image(
102
+ seed=params.seed,
103
+ prompt=params.prompt,
104
+ negative_prompt=params.negative_prompt,
105
+ num_inference_steps=params.steps,
106
+ width=params.width,
107
+ height=params.height,
108
+ guidance=params.guidance,
109
+ scheduler=params.scheduler,
110
+ )
111
+ total_s = round(time.time() - t0, 2)
112
+ meta = {
113
+ "model": params.model,
114
+ "prompt": params.prompt,
115
+ "params": params.model_dump(),
116
+ "width": params.width,
117
+ "height": params.height,
118
+ "timings": {"total_s": total_s},
119
+ }
120
+ return _store_image(
121
+ image, fmt=params.format, quality=params.quality, files=files, meta=meta
122
+ )
123
+
124
+
125
+ def _edit(model: Any, params: EditParams, files: FileStore) -> dict[str, Any]:
126
+ t0 = time.time()
127
+ attach_mflux_progress(model)
128
+ image = model.generate_image(
129
+ seed=params.seed,
130
+ prompt=params.prompt,
131
+ negative_prompt=params.negative_prompt,
132
+ image_path=params.image_path,
133
+ image_strength=params.image_strength,
134
+ num_inference_steps=params.steps,
135
+ width=params.width,
136
+ height=params.height,
137
+ guidance=params.guidance,
138
+ scheduler=params.scheduler,
139
+ )
140
+ total_s = round(time.time() - t0, 2)
141
+ meta = {
142
+ "model": params.model,
143
+ "prompt": params.prompt,
144
+ "params": params.model_dump(exclude={"image_path"}),
145
+ "width": params.width,
146
+ "height": params.height,
147
+ "timings": {"total_s": total_s},
148
+ }
149
+ return _store_image(
150
+ image, fmt=params.format, quality=params.quality, files=files, meta=meta
151
+ )
152
+
153
+
154
+ def run_generate(
155
+ payload: SimpleNamespace, params: GenerateParams, files: FileStore
156
+ ) -> dict[str, Any]:
157
+ return _generate(payload.model, params, files)
158
+
159
+
160
+ def run_edit(
161
+ payload: SimpleNamespace, params: EditParams, files: FileStore
162
+ ) -> dict[str, Any]:
163
+ return _edit(payload.model, params, files)
164
+
165
+
166
+ def run_generate_transient(
167
+ spec: ModelSpec,
168
+ params: GenerateParams,
169
+ files: FileStore,
170
+ *,
171
+ lora_paths: list[str],
172
+ lora_scales: list[float],
173
+ ) -> dict[str, Any]:
174
+ model = build_model(
175
+ spec, quantize=params.quantize, lora_paths=lora_paths, lora_scales=lora_scales
176
+ )
177
+ try:
178
+ return _generate(model, params, files)
179
+ finally:
180
+ _free(model)
181
+
182
+
183
+ def run_edit_transient(
184
+ spec: ModelSpec,
185
+ params: EditParams,
186
+ files: FileStore,
187
+ *,
188
+ lora_paths: list[str],
189
+ lora_scales: list[float],
190
+ ) -> dict[str, Any]:
191
+ model = build_model(
192
+ spec, quantize=params.quantize, lora_paths=lora_paths, lora_scales=lora_scales
193
+ )
194
+ try:
195
+ return _edit(model, params, files)
196
+ finally:
197
+ _free(model)
198
+
199
+
200
+ def _free(model: Any) -> None:
201
+ del model
202
+ gc.collect()
203
+ import mlx.core as mx
204
+
205
+ mx.clear_cache()
206
+
207
+
208
+ _BLOCK_RANGE = {"start": 0, "end": 36}
209
+
210
+
211
+ def _default_lora_targets(rank: int, include_ff: bool) -> list[dict[str, Any]]:
212
+ attn = [
213
+ "self_attention.to_q",
214
+ "self_attention.to_k",
215
+ "self_attention.to_v",
216
+ "self_attention.to_out.0",
217
+ ]
218
+ targets = [
219
+ {
220
+ "module_path": f"layers.{{block}}.{name}",
221
+ "blocks": dict(_BLOCK_RANGE),
222
+ "rank": rank,
223
+ }
224
+ for name in attn
225
+ ]
226
+ targets.append({"module_path": "text_proj", "rank": rank})
227
+ if include_ff:
228
+ targets += [
229
+ {
230
+ "module_path": f"layers.{{block}}.mlp.{name}",
231
+ "blocks": dict(_BLOCK_RANGE),
232
+ "rank": rank,
233
+ }
234
+ for name in ("gate_proj", "up_proj", "linear_fc2")
235
+ ]
236
+ targets += [
237
+ {"module_path": "time_embedding.linear_1", "rank": rank},
238
+ {"module_path": "time_embedding.linear_2", "rank": rank},
239
+ {"module_path": "adaln_modulation", "rank": rank},
240
+ {"module_path": "final_norm.linear", "rank": rank},
241
+ ]
242
+ return targets
243
+
244
+
245
+ def _build_train_config(
246
+ spec: ModelSpec,
247
+ params: TrainParams,
248
+ data_dirname: str,
249
+ out_dir: Path,
250
+ ) -> dict[str, Any]:
251
+ lora_layers = params.lora_layers or {
252
+ "targets": _default_lora_targets(params.lora_rank, params.lora_include_ff)
253
+ }
254
+
255
+ return {
256
+ "model": _model_name(spec),
257
+ "model_path": spec.repo,
258
+ "data": data_dirname,
259
+ "seed": params.seed,
260
+ "steps": params.steps,
261
+ "guidance": params.guidance,
262
+ "quantize": params.quantize,
263
+ "max_resolution": params.max_resolution,
264
+ "low_ram": params.low_ram,
265
+ "training_loop": {
266
+ "num_epochs": params.num_epochs,
267
+ "batch_size": params.batch_size,
268
+ "timestep_low": params.timestep_low,
269
+ "timestep_high": params.timestep_high,
270
+ },
271
+ "optimizer": {"name": "AdamW", "learning_rate": params.learning_rate},
272
+ "checkpoint": {
273
+ "save_frequency": params.save_frequency,
274
+ "output_path": str(out_dir),
275
+ },
276
+ "lora_layers": lora_layers,
277
+ }
278
+
279
+
280
+ def train(
281
+ spec: ModelSpec,
282
+ params: TrainParams,
283
+ files: FileStore,
284
+ dataset_dir: str,
285
+ ) -> dict[str, Any]:
286
+ import zipfile
287
+
288
+ from mflux.models.common.training.runner import TrainingRunner # type: ignore
289
+ from mflux.utils.exceptions import StopTrainingException # type: ignore
290
+
291
+ workdir = Path(dataset_dir).parent
292
+ out_dir = workdir / "out"
293
+ config = _build_train_config(spec, params, Path(dataset_dir).name, out_dir)
294
+ config_path = workdir / "train.json"
295
+ config_path.write_text(json.dumps(config, indent=2))
296
+
297
+ t0 = time.time()
298
+ try:
299
+ _adapter, training_spec = TrainingRunner.train(
300
+ config_path=str(config_path), resume_path=None
301
+ )
302
+ except StopTrainingException:
303
+ from mflux.models.common.training.state.training_spec import ( # type: ignore[import-untyped]
304
+ TrainingSpec,
305
+ )
306
+
307
+ training_spec = TrainingSpec.resolve(
308
+ config_path=str(config_path), resume_path=None
309
+ )
310
+ total_s = round(time.time() - t0, 2)
311
+
312
+ ckpt_dir = Path(training_spec.checkpoint.output_path) / "checkpoints"
313
+ zips = sorted(ckpt_dir.glob("*_checkpoint.zip"))
314
+ if not zips:
315
+ raise RuntimeError(
316
+ f"training finished but no checkpoint was produced in {ckpt_dir}"
317
+ )
318
+ latest = zips[-1]
319
+
320
+ adapter_bytes = None
321
+ with zipfile.ZipFile(latest) as zf:
322
+ for name in zf.namelist():
323
+ if name.endswith("_adapter.safetensors"):
324
+ adapter_bytes = zf.read(name)
325
+ break
326
+ if adapter_bytes is None:
327
+ raise RuntimeError(f"no *_adapter.safetensors inside {latest.name}")
328
+
329
+ meta = {
330
+ "model": spec.name,
331
+ "kind": "lora_adapter",
332
+ "config": {
333
+ k: config[k]
334
+ for k in (
335
+ "model",
336
+ "seed",
337
+ "steps",
338
+ "guidance",
339
+ "quantize",
340
+ "max_resolution",
341
+ "low_ram",
342
+ "training_loop",
343
+ "optimizer",
344
+ )
345
+ },
346
+ "lora_targets": len(config["lora_layers"]["targets"]),
347
+ "checkpoint": latest.name,
348
+ "timings": {"total_s": total_s},
349
+ }
350
+ rec = files.put_bytes(
351
+ adapter_bytes,
352
+ filename=f"ernie_lora_{spec.name}_{int(time.time())}.safetensors",
353
+ content_type="application/octet-stream",
354
+ meta=meta,
355
+ )
356
+ return {"adapter_file_id": rec.file_id, "adapter_bytes": rec.size, **meta}
@@ -0,0 +1,39 @@
1
+ """ERNIE-Image single-image edit service entry (worker-thread thunk body)."""
2
+
3
+ from kiapi.capabilities import get_file_path
4
+ from kiapi.core.app import AppContext
5
+ from kiapi.core.file import FileID
6
+ from kiapi.core.job import JobResult
7
+ from kiapi.core.model import model_registry
8
+
9
+ from .._settings import settings_manager
10
+ from .._views.edit_request import EditRequest
11
+ from .is_quantize_override import is_quantize_override
12
+ from .resolve_edit_params import resolve_edit_params
13
+ from .resolve_lora_params import resolve_lora_params
14
+
15
+
16
+ def handle_edit(ctx: AppContext, req: EditRequest) -> tuple[JobResult, list[FileID]]:
17
+ settings = settings_manager.get_settings()
18
+ spec = model_registry.resolve("ernie", req.model)
19
+ ctx.ensure_model_ready(spec)
20
+ image_path = get_file_path(ctx.file_store, req.image, kind="image")
21
+ lora_params = resolve_lora_params(ctx, req.loras)
22
+ override = is_quantize_override(settings, req, variant=spec.name)
23
+ params = resolve_edit_params(
24
+ settings, req, variant=spec.name, image_path=image_path
25
+ )
26
+
27
+ if lora_params.paths or override:
28
+ ctx.memory_manager.reserve(spec.weight_gb + spec.peak_headroom_gb)
29
+ result = spec.module.run_edit_transient(
30
+ spec,
31
+ params,
32
+ ctx.file_store,
33
+ lora_paths=lora_params.paths,
34
+ lora_scales=lora_params.scales,
35
+ )
36
+ else:
37
+ payload = ctx.memory_manager.acquire(spec)
38
+ result = spec.module.run_edit(payload, params, ctx.file_store)
39
+ return result, [result["file_id"]]
@@ -0,0 +1,38 @@
1
+ """ERNIE-Image text-to-image service entry (worker-thread thunk body)."""
2
+
3
+ from kiapi.core.app import AppContext
4
+ from kiapi.core.file import FileID
5
+ from kiapi.core.job import JobResult
6
+ from kiapi.core.model import model_registry
7
+
8
+ from .._settings import settings_manager
9
+ from .._views.generate_request import GenerateRequest
10
+ from .is_quantize_override import is_quantize_override
11
+ from .resolve_generate_params import resolve_generate_params
12
+ from .resolve_lora_params import resolve_lora_params
13
+
14
+
15
+ def handle_generate(
16
+ ctx: AppContext, req: GenerateRequest
17
+ ) -> tuple[JobResult, list[FileID]]:
18
+ settings = settings_manager.get_settings()
19
+ spec = model_registry.resolve("ernie", req.model)
20
+ ctx.ensure_model_ready(spec)
21
+ lora_params = resolve_lora_params(ctx, req.loras)
22
+ override = is_quantize_override(settings, req, variant=spec.name)
23
+ params = resolve_generate_params(settings, req, variant=spec.name)
24
+
25
+ if lora_params.paths or override:
26
+ ctx.memory_manager.reserve(spec.weight_gb + spec.peak_headroom_gb)
27
+ result = spec.module.run_generate_transient(
28
+ spec,
29
+ params,
30
+ ctx.file_store,
31
+ lora_paths=lora_params.paths,
32
+ lora_scales=lora_params.scales,
33
+ )
34
+ else:
35
+ payload = ctx.memory_manager.acquire(spec)
36
+ result = spec.module.run_generate(payload, params, ctx.file_store)
37
+
38
+ return result, [result["file_id"]]
@@ -0,0 +1,77 @@
1
+ """ERNIE-Image LoRA finetune service entry (always-async worker-thread thunk)."""
2
+
3
+ import shutil
4
+ import zipfile
5
+ from pathlib import Path
6
+
7
+ from kiapi.capabilities import CapabilityError, get_file_path
8
+ from kiapi.core.app import AppContext
9
+ from kiapi.core.file import FileID
10
+ from kiapi.core.job import JobResult
11
+ from kiapi.core.model import model_registry
12
+ from kiapi.core.workdir import create_work_dir
13
+
14
+ from .._settings import settings_manager
15
+ from .._views.train_request import TrainRequest
16
+ from .resolve_train_params import resolve_train_params
17
+
18
+ _IMAGE_EXTS = {".jpg", ".jpeg", ".png", ".webp"}
19
+
20
+
21
+ def handle_train(ctx: AppContext, req: TrainRequest) -> tuple[JobResult, list[FileID]]:
22
+ settings = settings_manager.get_settings()
23
+ spec = model_registry.resolve("ernie", req.model)
24
+ ctx.ensure_model_ready(spec)
25
+
26
+ dataset_path = get_file_path(ctx.file_store, req.dataset, kind="dataset")
27
+
28
+ workdir = create_work_dir("train/ernie")
29
+ try:
30
+ data_dir = _extract_dataset(dataset_path, workdir / "data")
31
+ n_images = _validate_dataset(data_dir)
32
+ params = resolve_train_params(settings, req, variant=spec.name)
33
+ ctx.memory_manager.reserve(settings.train_reserve_gb)
34
+ result = spec.module.train(spec, params, ctx.file_store, str(data_dir))
35
+ result["num_images"] = n_images
36
+ return result, [result["adapter_file_id"]]
37
+ finally:
38
+ shutil.rmtree(workdir, ignore_errors=True)
39
+
40
+
41
+ def _extract_dataset(zip_path: str, dest: Path) -> Path:
42
+ dest.mkdir(parents=True, exist_ok=True)
43
+ with zipfile.ZipFile(zip_path) as zf:
44
+ for member in zf.namelist():
45
+ target = (dest / member).resolve()
46
+ if not str(target).startswith(str(dest.resolve())):
47
+ raise CapabilityError(f"unsafe path in dataset zip: {member!r}")
48
+ zf.extractall(dest)
49
+
50
+ def _has_images(d: Path) -> bool:
51
+ return any(p.suffix.lower() in _IMAGE_EXTS for p in d.iterdir() if p.is_file())
52
+
53
+ if _has_images(dest):
54
+ return dest
55
+ subdirs = [p for p in dest.iterdir() if p.is_dir()]
56
+ if len(subdirs) == 1 and _has_images(subdirs[0]):
57
+ return subdirs[0]
58
+ raise CapabilityError(
59
+ "dataset zip must contain images at the top level or in a single subfolder"
60
+ )
61
+
62
+
63
+ def _validate_dataset(data_dir: Path) -> int:
64
+ images = [
65
+ p for p in data_dir.iterdir() if p.is_file() and p.suffix.lower() in _IMAGE_EXTS
66
+ ]
67
+ if not images:
68
+ raise CapabilityError("dataset has no images")
69
+ missing = [
70
+ p.name
71
+ for p in images
72
+ if not p.stem.startswith("preview")
73
+ and not (data_dir / f"{p.stem}.txt").exists()
74
+ ]
75
+ if missing:
76
+ raise CapabilityError(f"images missing a same-stem .txt caption: {missing}")
77
+ return len([p for p in images if not p.stem.startswith("preview")])
@@ -0,0 +1,16 @@
1
+ """Decide whether a request's quantize differs from the variant default.
2
+
3
+ A True result means the resident model (quantized at its default) can't serve the
4
+ request, so ``handle_*`` runs a one-off transient model instead.
5
+ """
6
+
7
+ from .._settings import ErnieSettings
8
+ from .._views.edit_request import EditRequest
9
+ from .._views.generate_request import GenerateRequest
10
+
11
+
12
+ def is_quantize_override(
13
+ settings: ErnieSettings, req: GenerateRequest | EditRequest, *, variant: str
14
+ ) -> bool:
15
+ default_quantize = settings.default_quantize.get(variant)
16
+ return req.quantize is not None and req.quantize != default_quantize
@@ -0,0 +1,44 @@
1
+ """Merge an edit request with settings defaults into the complete EditParams."""
2
+
3
+ import random
4
+
5
+ from .._settings import ErnieSettings
6
+ from .._views.edit_params import EditParams
7
+ from .._views.edit_request import EditRequest
8
+
9
+
10
+ def resolve_edit_params(
11
+ settings: ErnieSettings,
12
+ req: EditRequest,
13
+ *,
14
+ variant: str,
15
+ image_path: str,
16
+ ) -> EditParams:
17
+ return EditParams(
18
+ model=variant,
19
+ prompt=req.prompt,
20
+ negative_prompt=req.negative_prompt,
21
+ image_file_id="",
22
+ image_path=image_path,
23
+ image_strength=req.image_strength,
24
+ seed=req.seed if req.seed is not None else random.randint(0, 2**31 - 1),
25
+ width=req.width if req.width is not None else settings.default_width,
26
+ height=req.height if req.height is not None else settings.default_height,
27
+ steps=req.steps
28
+ if req.steps is not None
29
+ else settings.default_steps.get(variant, 8),
30
+ guidance=(
31
+ req.guidance
32
+ if req.guidance is not None
33
+ else settings.default_guidance.get(variant, 1.0)
34
+ ),
35
+ quantize=(
36
+ req.quantize
37
+ if req.quantize is not None
38
+ else settings.default_quantize.get(variant)
39
+ ),
40
+ scheduler=req.scheduler,
41
+ format=req.format,
42
+ quality=req.quality,
43
+ loras=req.loras,
44
+ )
@@ -0,0 +1,40 @@
1
+ """Merge a generate request with settings defaults into the complete GenerateParams."""
2
+
3
+ import random
4
+
5
+ from .._settings import ErnieSettings
6
+ from .._views.generate_params import GenerateParams
7
+ from .._views.generate_request import GenerateRequest
8
+
9
+
10
+ def resolve_generate_params(
11
+ settings: ErnieSettings,
12
+ req: GenerateRequest,
13
+ *,
14
+ variant: str,
15
+ ) -> GenerateParams:
16
+ return GenerateParams(
17
+ model=variant,
18
+ prompt=req.prompt,
19
+ negative_prompt=req.negative_prompt,
20
+ seed=req.seed if req.seed is not None else random.randint(0, 2**31 - 1),
21
+ width=req.width if req.width is not None else settings.default_width,
22
+ height=req.height if req.height is not None else settings.default_height,
23
+ steps=req.steps
24
+ if req.steps is not None
25
+ else settings.default_steps.get(variant, 8),
26
+ guidance=(
27
+ req.guidance
28
+ if req.guidance is not None
29
+ else settings.default_guidance.get(variant, 1.0)
30
+ ),
31
+ quantize=(
32
+ req.quantize
33
+ if req.quantize is not None
34
+ else settings.default_quantize.get(variant)
35
+ ),
36
+ scheduler=req.scheduler,
37
+ format=req.format,
38
+ quality=req.quality,
39
+ loras=req.loras,
40
+ )
@@ -0,0 +1,23 @@
1
+ from collections.abc import Iterable
2
+ from dataclasses import dataclass, field
3
+
4
+ from kiapi.capabilities import get_file_path
5
+ from kiapi.core.app import AppContext
6
+
7
+ from .._schemas.lora_ref import LoraRef
8
+
9
+
10
+ @dataclass
11
+ class LoraParams:
12
+ paths: list[str] = field(default_factory=list)
13
+ scales: list[float] = field(default_factory=list)
14
+
15
+
16
+ def resolve_lora_params(ctx: AppContext, loras: Iterable[LoraRef]) -> LoraParams:
17
+ params = LoraParams()
18
+
19
+ for lr in loras:
20
+ params.paths.append(get_file_path(ctx.file_store, lr.file, kind="lora"))
21
+ params.scales.append(lr.scale)
22
+
23
+ return params
@@ -0,0 +1,43 @@
1
+ """Merge a train request with settings defaults into the complete TrainParams."""
2
+
3
+ from .._settings import ErnieSettings
4
+ from .._views.train_params import TrainParams
5
+ from .._views.train_request import TrainRequest
6
+
7
+
8
+ def resolve_train_params(
9
+ settings: ErnieSettings,
10
+ req: TrainRequest,
11
+ *,
12
+ variant: str,
13
+ ) -> TrainParams:
14
+ steps = req.steps if req.steps is not None else settings.train_steps.get(variant, 8)
15
+ return TrainParams(
16
+ seed=req.seed,
17
+ steps=steps,
18
+ guidance=(
19
+ req.guidance
20
+ if req.guidance is not None
21
+ else settings.default_guidance.get(variant, 1.0)
22
+ ),
23
+ quantize=(
24
+ req.quantize
25
+ if req.quantize is not None
26
+ else settings.train_quantize.get(variant, 8)
27
+ ),
28
+ max_resolution=req.max_resolution,
29
+ low_ram=req.low_ram,
30
+ num_epochs=req.num_epochs,
31
+ batch_size=req.batch_size,
32
+ timestep_low=(
33
+ req.timestep_low
34
+ if req.timestep_low is not None
35
+ else settings.train_timestep_low.get(variant, 1)
36
+ ),
37
+ timestep_high=req.timestep_high if req.timestep_high is not None else steps,
38
+ learning_rate=req.learning_rate,
39
+ save_frequency=req.save_frequency if req.save_frequency is not None else 10**9,
40
+ lora_rank=req.lora_rank,
41
+ lora_include_ff=req.lora_include_ff,
42
+ lora_layers=req.lora_layers,
43
+ )