xinference 1.10.0__py3-none-any.whl → 1.11.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.

Potentially problematic release.


This version of xinference might be problematic. Click here for more details.

Files changed (328) hide show
  1. xinference/_version.py +3 -3
  2. xinference/api/restful_api.py +473 -31
  3. xinference/client/restful/async_restful_client.py +178 -8
  4. xinference/client/restful/restful_client.py +151 -3
  5. xinference/core/supervisor.py +99 -53
  6. xinference/core/worker.py +10 -0
  7. xinference/deploy/cmdline.py +15 -0
  8. xinference/model/audio/core.py +21 -6
  9. xinference/model/audio/indextts2.py +166 -0
  10. xinference/model/audio/model_spec.json +58 -21
  11. xinference/model/image/model_spec.json +159 -90
  12. xinference/model/image/stable_diffusion/core.py +13 -4
  13. xinference/model/llm/__init__.py +6 -2
  14. xinference/model/llm/llm_family.json +1299 -174
  15. xinference/model/llm/mlx/distributed_models/core.py +41 -0
  16. xinference/model/llm/mlx/distributed_models/qwen2.py +1 -2
  17. xinference/model/llm/sglang/core.py +44 -11
  18. xinference/model/llm/tool_parsers/deepseek_r1_tool_parser.py +94 -32
  19. xinference/model/llm/tool_parsers/qwen_tool_parser.py +29 -4
  20. xinference/model/llm/transformers/chatglm.py +3 -0
  21. xinference/model/llm/transformers/core.py +129 -36
  22. xinference/model/llm/transformers/multimodal/minicpmv45.py +340 -0
  23. xinference/model/llm/transformers/multimodal/qwen2_vl.py +34 -8
  24. xinference/model/llm/transformers/utils.py +23 -0
  25. xinference/model/llm/utils.py +48 -32
  26. xinference/model/llm/vllm/core.py +207 -72
  27. xinference/model/utils.py +74 -31
  28. xinference/thirdparty/audiotools/__init__.py +10 -0
  29. xinference/thirdparty/audiotools/core/__init__.py +4 -0
  30. xinference/thirdparty/audiotools/core/audio_signal.py +1682 -0
  31. xinference/thirdparty/audiotools/core/display.py +194 -0
  32. xinference/thirdparty/audiotools/core/dsp.py +390 -0
  33. xinference/thirdparty/audiotools/core/effects.py +647 -0
  34. xinference/thirdparty/audiotools/core/ffmpeg.py +211 -0
  35. xinference/thirdparty/audiotools/core/loudness.py +320 -0
  36. xinference/thirdparty/audiotools/core/playback.py +252 -0
  37. xinference/thirdparty/audiotools/core/templates/__init__.py +0 -0
  38. xinference/thirdparty/audiotools/core/templates/headers.html +322 -0
  39. xinference/thirdparty/audiotools/core/templates/pandoc.css +407 -0
  40. xinference/thirdparty/audiotools/core/templates/widget.html +52 -0
  41. xinference/thirdparty/audiotools/core/util.py +671 -0
  42. xinference/thirdparty/audiotools/core/whisper.py +97 -0
  43. xinference/thirdparty/audiotools/data/__init__.py +3 -0
  44. xinference/thirdparty/audiotools/data/datasets.py +517 -0
  45. xinference/thirdparty/audiotools/data/preprocess.py +81 -0
  46. xinference/thirdparty/audiotools/data/transforms.py +1592 -0
  47. xinference/thirdparty/audiotools/metrics/__init__.py +6 -0
  48. xinference/thirdparty/audiotools/metrics/distance.py +131 -0
  49. xinference/thirdparty/audiotools/metrics/quality.py +159 -0
  50. xinference/thirdparty/audiotools/metrics/spectral.py +247 -0
  51. xinference/thirdparty/audiotools/ml/__init__.py +5 -0
  52. xinference/thirdparty/audiotools/ml/accelerator.py +184 -0
  53. xinference/thirdparty/audiotools/ml/decorators.py +440 -0
  54. xinference/thirdparty/audiotools/ml/experiment.py +90 -0
  55. xinference/thirdparty/audiotools/ml/layers/__init__.py +2 -0
  56. xinference/thirdparty/audiotools/ml/layers/base.py +328 -0
  57. xinference/thirdparty/audiotools/ml/layers/spectral_gate.py +127 -0
  58. xinference/thirdparty/audiotools/post.py +140 -0
  59. xinference/thirdparty/audiotools/preference.py +600 -0
  60. xinference/thirdparty/fish_speech/fish_speech/text/chn_text_norm/text.py +1 -1
  61. xinference/thirdparty/indextts/BigVGAN/ECAPA_TDNN.py +656 -0
  62. xinference/thirdparty/indextts/BigVGAN/__init__.py +0 -0
  63. xinference/thirdparty/indextts/BigVGAN/activations.py +122 -0
  64. xinference/thirdparty/indextts/BigVGAN/alias_free_activation/__init__.py +0 -0
  65. xinference/thirdparty/indextts/BigVGAN/alias_free_activation/cuda/.gitignore +1 -0
  66. xinference/thirdparty/indextts/BigVGAN/alias_free_activation/cuda/__init__.py +0 -0
  67. xinference/thirdparty/indextts/BigVGAN/alias_free_activation/cuda/activation1d.py +76 -0
  68. xinference/thirdparty/indextts/BigVGAN/alias_free_activation/cuda/anti_alias_activation.cpp +23 -0
  69. xinference/thirdparty/indextts/BigVGAN/alias_free_activation/cuda/anti_alias_activation_cuda.cu +256 -0
  70. xinference/thirdparty/indextts/BigVGAN/alias_free_activation/cuda/compat.h +29 -0
  71. xinference/thirdparty/indextts/BigVGAN/alias_free_activation/cuda/load.py +121 -0
  72. xinference/thirdparty/indextts/BigVGAN/alias_free_activation/cuda/type_shim.h +92 -0
  73. xinference/thirdparty/indextts/BigVGAN/alias_free_activation/torch/__init__.py +6 -0
  74. xinference/thirdparty/indextts/BigVGAN/alias_free_activation/torch/act.py +31 -0
  75. xinference/thirdparty/indextts/BigVGAN/alias_free_activation/torch/filter.py +102 -0
  76. xinference/thirdparty/indextts/BigVGAN/alias_free_activation/torch/resample.py +58 -0
  77. xinference/thirdparty/indextts/BigVGAN/alias_free_torch/__init__.py +6 -0
  78. xinference/thirdparty/indextts/BigVGAN/alias_free_torch/act.py +29 -0
  79. xinference/thirdparty/indextts/BigVGAN/alias_free_torch/filter.py +96 -0
  80. xinference/thirdparty/indextts/BigVGAN/alias_free_torch/resample.py +49 -0
  81. xinference/thirdparty/indextts/BigVGAN/bigvgan.py +534 -0
  82. xinference/thirdparty/indextts/BigVGAN/models.py +451 -0
  83. xinference/thirdparty/indextts/BigVGAN/nnet/CNN.py +546 -0
  84. xinference/thirdparty/indextts/BigVGAN/nnet/__init__.py +0 -0
  85. xinference/thirdparty/indextts/BigVGAN/nnet/linear.py +89 -0
  86. xinference/thirdparty/indextts/BigVGAN/nnet/normalization.py +670 -0
  87. xinference/thirdparty/indextts/BigVGAN/utils.py +101 -0
  88. xinference/thirdparty/indextts/__init__.py +0 -0
  89. xinference/thirdparty/indextts/cli.py +65 -0
  90. xinference/thirdparty/indextts/gpt/__init__.py +0 -0
  91. xinference/thirdparty/indextts/gpt/conformer/__init__.py +0 -0
  92. xinference/thirdparty/indextts/gpt/conformer/attention.py +312 -0
  93. xinference/thirdparty/indextts/gpt/conformer/embedding.py +163 -0
  94. xinference/thirdparty/indextts/gpt/conformer/subsampling.py +348 -0
  95. xinference/thirdparty/indextts/gpt/conformer_encoder.py +520 -0
  96. xinference/thirdparty/indextts/gpt/model.py +713 -0
  97. xinference/thirdparty/indextts/gpt/model_v2.py +747 -0
  98. xinference/thirdparty/indextts/gpt/perceiver.py +317 -0
  99. xinference/thirdparty/indextts/gpt/transformers_beam_search.py +1013 -0
  100. xinference/thirdparty/indextts/gpt/transformers_generation_utils.py +4747 -0
  101. xinference/thirdparty/indextts/gpt/transformers_gpt2.py +1878 -0
  102. xinference/thirdparty/indextts/gpt/transformers_modeling_utils.py +5525 -0
  103. xinference/thirdparty/indextts/infer.py +690 -0
  104. xinference/thirdparty/indextts/infer_v2.py +739 -0
  105. xinference/thirdparty/indextts/s2mel/dac/__init__.py +16 -0
  106. xinference/thirdparty/indextts/s2mel/dac/__main__.py +36 -0
  107. xinference/thirdparty/indextts/s2mel/dac/model/__init__.py +4 -0
  108. xinference/thirdparty/indextts/s2mel/dac/model/base.py +294 -0
  109. xinference/thirdparty/indextts/s2mel/dac/model/dac.py +400 -0
  110. xinference/thirdparty/indextts/s2mel/dac/model/discriminator.py +228 -0
  111. xinference/thirdparty/indextts/s2mel/dac/model/encodec.py +320 -0
  112. xinference/thirdparty/indextts/s2mel/dac/nn/__init__.py +3 -0
  113. xinference/thirdparty/indextts/s2mel/dac/nn/layers.py +33 -0
  114. xinference/thirdparty/indextts/s2mel/dac/nn/loss.py +368 -0
  115. xinference/thirdparty/indextts/s2mel/dac/nn/quantize.py +339 -0
  116. xinference/thirdparty/indextts/s2mel/dac/utils/__init__.py +123 -0
  117. xinference/thirdparty/indextts/s2mel/dac/utils/decode.py +95 -0
  118. xinference/thirdparty/indextts/s2mel/dac/utils/encode.py +94 -0
  119. xinference/thirdparty/indextts/s2mel/hf_utils.py +12 -0
  120. xinference/thirdparty/indextts/s2mel/modules/alias_free_torch/__init__.py +5 -0
  121. xinference/thirdparty/indextts/s2mel/modules/alias_free_torch/act.py +29 -0
  122. xinference/thirdparty/indextts/s2mel/modules/alias_free_torch/filter.py +96 -0
  123. xinference/thirdparty/indextts/s2mel/modules/alias_free_torch/resample.py +57 -0
  124. xinference/thirdparty/indextts/s2mel/modules/audio.py +82 -0
  125. xinference/thirdparty/indextts/s2mel/modules/bigvgan/activations.py +120 -0
  126. xinference/thirdparty/indextts/s2mel/modules/bigvgan/alias_free_activation/cuda/__init__.py +0 -0
  127. xinference/thirdparty/indextts/s2mel/modules/bigvgan/alias_free_activation/cuda/activation1d.py +77 -0
  128. xinference/thirdparty/indextts/s2mel/modules/bigvgan/alias_free_activation/cuda/anti_alias_activation.cpp +23 -0
  129. xinference/thirdparty/indextts/s2mel/modules/bigvgan/alias_free_activation/cuda/anti_alias_activation_cuda.cu +246 -0
  130. xinference/thirdparty/indextts/s2mel/modules/bigvgan/alias_free_activation/cuda/compat.h +29 -0
  131. xinference/thirdparty/indextts/s2mel/modules/bigvgan/alias_free_activation/cuda/load.py +86 -0
  132. xinference/thirdparty/indextts/s2mel/modules/bigvgan/alias_free_activation/cuda/type_shim.h +92 -0
  133. xinference/thirdparty/indextts/s2mel/modules/bigvgan/alias_free_activation/torch/__init__.py +6 -0
  134. xinference/thirdparty/indextts/s2mel/modules/bigvgan/alias_free_activation/torch/act.py +30 -0
  135. xinference/thirdparty/indextts/s2mel/modules/bigvgan/alias_free_activation/torch/filter.py +101 -0
  136. xinference/thirdparty/indextts/s2mel/modules/bigvgan/alias_free_activation/torch/resample.py +58 -0
  137. xinference/thirdparty/indextts/s2mel/modules/bigvgan/bigvgan.py +492 -0
  138. xinference/thirdparty/indextts/s2mel/modules/bigvgan/config.json +63 -0
  139. xinference/thirdparty/indextts/s2mel/modules/bigvgan/env.py +18 -0
  140. xinference/thirdparty/indextts/s2mel/modules/bigvgan/meldataset.py +354 -0
  141. xinference/thirdparty/indextts/s2mel/modules/bigvgan/utils.py +99 -0
  142. xinference/thirdparty/indextts/s2mel/modules/campplus/DTDNN.py +115 -0
  143. xinference/thirdparty/indextts/s2mel/modules/campplus/classifier.py +70 -0
  144. xinference/thirdparty/indextts/s2mel/modules/campplus/layers.py +253 -0
  145. xinference/thirdparty/indextts/s2mel/modules/commons.py +632 -0
  146. xinference/thirdparty/indextts/s2mel/modules/diffusion_transformer.py +257 -0
  147. xinference/thirdparty/indextts/s2mel/modules/encodec.py +292 -0
  148. xinference/thirdparty/indextts/s2mel/modules/flow_matching.py +171 -0
  149. xinference/thirdparty/indextts/s2mel/modules/gpt_fast/generate.py +436 -0
  150. xinference/thirdparty/indextts/s2mel/modules/gpt_fast/model.py +360 -0
  151. xinference/thirdparty/indextts/s2mel/modules/gpt_fast/quantize.py +622 -0
  152. xinference/thirdparty/indextts/s2mel/modules/hifigan/f0_predictor.py +55 -0
  153. xinference/thirdparty/indextts/s2mel/modules/hifigan/generator.py +454 -0
  154. xinference/thirdparty/indextts/s2mel/modules/layers.py +354 -0
  155. xinference/thirdparty/indextts/s2mel/modules/length_regulator.py +141 -0
  156. xinference/thirdparty/indextts/s2mel/modules/openvoice/__init__.py +0 -0
  157. xinference/thirdparty/indextts/s2mel/modules/openvoice/api.py +186 -0
  158. xinference/thirdparty/indextts/s2mel/modules/openvoice/attentions.py +465 -0
  159. xinference/thirdparty/indextts/s2mel/modules/openvoice/checkpoints_v2/converter/config.json +57 -0
  160. xinference/thirdparty/indextts/s2mel/modules/openvoice/commons.py +160 -0
  161. xinference/thirdparty/indextts/s2mel/modules/openvoice/mel_processing.py +183 -0
  162. xinference/thirdparty/indextts/s2mel/modules/openvoice/models.py +499 -0
  163. xinference/thirdparty/indextts/s2mel/modules/openvoice/modules.py +598 -0
  164. xinference/thirdparty/indextts/s2mel/modules/openvoice/openvoice_app.py +275 -0
  165. xinference/thirdparty/indextts/s2mel/modules/openvoice/se_extractor.py +153 -0
  166. xinference/thirdparty/indextts/s2mel/modules/openvoice/transforms.py +209 -0
  167. xinference/thirdparty/indextts/s2mel/modules/openvoice/utils.py +194 -0
  168. xinference/thirdparty/indextts/s2mel/modules/quantize.py +229 -0
  169. xinference/thirdparty/indextts/s2mel/modules/rmvpe.py +631 -0
  170. xinference/thirdparty/indextts/s2mel/modules/vocos/__init__.py +4 -0
  171. xinference/thirdparty/indextts/s2mel/modules/vocos/heads.py +164 -0
  172. xinference/thirdparty/indextts/s2mel/modules/vocos/helpers.py +71 -0
  173. xinference/thirdparty/indextts/s2mel/modules/vocos/loss.py +114 -0
  174. xinference/thirdparty/indextts/s2mel/modules/vocos/models.py +118 -0
  175. xinference/thirdparty/indextts/s2mel/modules/vocos/modules.py +213 -0
  176. xinference/thirdparty/indextts/s2mel/modules/vocos/pretrained.py +51 -0
  177. xinference/thirdparty/indextts/s2mel/modules/vocos/spectral_ops.py +192 -0
  178. xinference/thirdparty/indextts/s2mel/modules/wavenet.py +174 -0
  179. xinference/thirdparty/indextts/s2mel/optimizers.py +96 -0
  180. xinference/thirdparty/indextts/s2mel/wav2vecbert_extract.py +148 -0
  181. xinference/thirdparty/indextts/utils/__init__.py +0 -0
  182. xinference/thirdparty/indextts/utils/arch_util.py +120 -0
  183. xinference/thirdparty/indextts/utils/checkpoint.py +34 -0
  184. xinference/thirdparty/indextts/utils/common.py +121 -0
  185. xinference/thirdparty/indextts/utils/feature_extractors.py +50 -0
  186. xinference/thirdparty/indextts/utils/front.py +536 -0
  187. xinference/thirdparty/indextts/utils/maskgct/models/codec/__init__.py +0 -0
  188. xinference/thirdparty/indextts/utils/maskgct/models/codec/amphion_codec/codec.py +427 -0
  189. xinference/thirdparty/indextts/utils/maskgct/models/codec/amphion_codec/quantize/__init__.py +11 -0
  190. xinference/thirdparty/indextts/utils/maskgct/models/codec/amphion_codec/quantize/factorized_vector_quantize.py +150 -0
  191. xinference/thirdparty/indextts/utils/maskgct/models/codec/amphion_codec/quantize/lookup_free_quantize.py +77 -0
  192. xinference/thirdparty/indextts/utils/maskgct/models/codec/amphion_codec/quantize/residual_vq.py +177 -0
  193. xinference/thirdparty/indextts/utils/maskgct/models/codec/amphion_codec/quantize/vector_quantize.py +401 -0
  194. xinference/thirdparty/indextts/utils/maskgct/models/codec/amphion_codec/vocos.py +881 -0
  195. xinference/thirdparty/indextts/utils/maskgct/models/codec/codec_dataset.py +264 -0
  196. xinference/thirdparty/indextts/utils/maskgct/models/codec/codec_inference.py +515 -0
  197. xinference/thirdparty/indextts/utils/maskgct/models/codec/codec_sampler.py +126 -0
  198. xinference/thirdparty/indextts/utils/maskgct/models/codec/codec_trainer.py +166 -0
  199. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/__init__.py +0 -0
  200. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/alias_free_torch/__init__.py +5 -0
  201. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/alias_free_torch/act.py +29 -0
  202. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/alias_free_torch/filter.py +96 -0
  203. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/alias_free_torch/resample.py +57 -0
  204. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/facodec_dataset.py +98 -0
  205. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/facodec_inference.py +137 -0
  206. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/facodec_trainer.py +776 -0
  207. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/modules/JDC/__init__.py +1 -0
  208. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/modules/JDC/bst.t7 +0 -0
  209. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/modules/JDC/model.py +219 -0
  210. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/modules/attentions.py +437 -0
  211. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/modules/commons.py +331 -0
  212. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/modules/gradient_reversal.py +35 -0
  213. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/modules/layers.py +460 -0
  214. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/modules/quantize.py +741 -0
  215. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/modules/style_encoder.py +110 -0
  216. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/modules/wavenet.py +224 -0
  217. xinference/thirdparty/indextts/utils/maskgct/models/codec/facodec/optimizer.py +104 -0
  218. xinference/thirdparty/indextts/utils/maskgct/models/codec/kmeans/repcodec_model.py +210 -0
  219. xinference/thirdparty/indextts/utils/maskgct/models/codec/kmeans/vocos.py +850 -0
  220. xinference/thirdparty/indextts/utils/maskgct/models/codec/melvqgan/melspec.py +108 -0
  221. xinference/thirdparty/indextts/utils/maskgct/models/codec/ns3_codec/README.md +216 -0
  222. xinference/thirdparty/indextts/utils/maskgct/models/codec/ns3_codec/__init__.py +6 -0
  223. xinference/thirdparty/indextts/utils/maskgct/models/codec/ns3_codec/alias_free_torch/__init__.py +5 -0
  224. xinference/thirdparty/indextts/utils/maskgct/models/codec/ns3_codec/alias_free_torch/act.py +29 -0
  225. xinference/thirdparty/indextts/utils/maskgct/models/codec/ns3_codec/alias_free_torch/filter.py +96 -0
  226. xinference/thirdparty/indextts/utils/maskgct/models/codec/ns3_codec/alias_free_torch/resample.py +57 -0
  227. xinference/thirdparty/indextts/utils/maskgct/models/codec/ns3_codec/facodec.py +1222 -0
  228. xinference/thirdparty/indextts/utils/maskgct/models/codec/ns3_codec/gradient_reversal.py +35 -0
  229. xinference/thirdparty/indextts/utils/maskgct/models/codec/ns3_codec/melspec.py +102 -0
  230. xinference/thirdparty/indextts/utils/maskgct/models/codec/ns3_codec/quantize/__init__.py +7 -0
  231. xinference/thirdparty/indextts/utils/maskgct/models/codec/ns3_codec/quantize/fvq.py +116 -0
  232. xinference/thirdparty/indextts/utils/maskgct/models/codec/ns3_codec/quantize/rvq.py +87 -0
  233. xinference/thirdparty/indextts/utils/maskgct/models/codec/ns3_codec/transformer.py +234 -0
  234. xinference/thirdparty/indextts/utils/maskgct/models/codec/speechtokenizer/model.py +184 -0
  235. xinference/thirdparty/indextts/utils/maskgct/models/codec/speechtokenizer/modules/__init__.py +27 -0
  236. xinference/thirdparty/indextts/utils/maskgct/models/codec/speechtokenizer/modules/conv.py +346 -0
  237. xinference/thirdparty/indextts/utils/maskgct/models/codec/speechtokenizer/modules/lstm.py +46 -0
  238. xinference/thirdparty/indextts/utils/maskgct/models/codec/speechtokenizer/modules/norm.py +37 -0
  239. xinference/thirdparty/indextts/utils/maskgct/models/codec/speechtokenizer/modules/quantization/__init__.py +14 -0
  240. xinference/thirdparty/indextts/utils/maskgct/models/codec/speechtokenizer/modules/quantization/ac.py +317 -0
  241. xinference/thirdparty/indextts/utils/maskgct/models/codec/speechtokenizer/modules/quantization/core_vq.py +388 -0
  242. xinference/thirdparty/indextts/utils/maskgct/models/codec/speechtokenizer/modules/quantization/distrib.py +135 -0
  243. xinference/thirdparty/indextts/utils/maskgct/models/codec/speechtokenizer/modules/quantization/vq.py +125 -0
  244. xinference/thirdparty/indextts/utils/maskgct/models/codec/speechtokenizer/modules/seanet.py +414 -0
  245. xinference/thirdparty/indextts/utils/maskgct/models/codec/vevo/vevo_repcodec.py +592 -0
  246. xinference/thirdparty/indextts/utils/maskgct/models/tts/maskgct/ckpt/wav2vec2bert_stats.pt +0 -0
  247. xinference/thirdparty/indextts/utils/maskgct/models/tts/maskgct/llama_nar.py +650 -0
  248. xinference/thirdparty/indextts/utils/maskgct/models/tts/maskgct/maskgct_s2a.py +503 -0
  249. xinference/thirdparty/indextts/utils/maskgct_utils.py +259 -0
  250. xinference/thirdparty/indextts/utils/text_utils.py +41 -0
  251. xinference/thirdparty/indextts/utils/typical_sampling.py +30 -0
  252. xinference/thirdparty/indextts/utils/utils.py +93 -0
  253. xinference/thirdparty/indextts/utils/webui_utils.py +42 -0
  254. xinference/thirdparty/indextts/utils/xtransformers.py +1247 -0
  255. xinference/thirdparty/indextts/vqvae/__init__.py +0 -0
  256. xinference/thirdparty/indextts/vqvae/xtts_dvae.py +395 -0
  257. xinference/thirdparty/melo/text/chinese_mix.py +2 -2
  258. xinference/types.py +9 -0
  259. xinference/ui/gradio/media_interface.py +66 -8
  260. xinference/ui/web/ui/build/asset-manifest.json +6 -6
  261. xinference/ui/web/ui/build/index.html +1 -1
  262. xinference/ui/web/ui/build/static/css/main.5ea97072.css +2 -0
  263. xinference/ui/web/ui/build/static/css/main.5ea97072.css.map +1 -0
  264. xinference/ui/web/ui/build/static/js/main.45e78536.js +3 -0
  265. xinference/ui/web/ui/build/static/js/{main.1086c759.js.LICENSE.txt → main.45e78536.js.LICENSE.txt} +0 -7
  266. xinference/ui/web/ui/build/static/js/main.45e78536.js.map +1 -0
  267. xinference/ui/web/ui/node_modules/.cache/babel-loader/089c38df5f52348d212ed868dda5c518a42e0c2762caed4175487c0405830c35.json +1 -0
  268. xinference/ui/web/ui/node_modules/.cache/babel-loader/2b6e3a5b6eb2c5c5f2d007e68cd46c372721cd52bf63508adcdb21ecf79241d8.json +1 -0
  269. xinference/ui/web/ui/node_modules/.cache/babel-loader/2d887825fd07a56f872eda4420da25fba0b5b62a23bdcc6c6da1a5281887f618.json +1 -0
  270. xinference/ui/web/ui/node_modules/.cache/babel-loader/4001f9c3e64e73a4f2158826650c174a59d5e3f89ddecddf17cbb6bb688cc4ca.json +1 -0
  271. xinference/ui/web/ui/node_modules/.cache/babel-loader/4a7018a69e6b7f90fc313248c2aa86f2a8f1eb1db120df586047a8023549b44b.json +1 -0
  272. xinference/ui/web/ui/node_modules/.cache/babel-loader/64b12aaa1c1d1bf53820ada8a63769067c0ccc5aab46b32348eb1917ae7f2a11.json +1 -0
  273. xinference/ui/web/ui/node_modules/.cache/babel-loader/7275b67c78ec76ce38a686bb8a576d8c9cecf54e1573614c84859d538efb9be5.json +1 -0
  274. xinference/ui/web/ui/node_modules/.cache/babel-loader/a68b6ee3b31eadc051fb95ce8f8ccb9c2e8b52c60f290dbab545a1917e065282.json +1 -0
  275. xinference/ui/web/ui/node_modules/.cache/babel-loader/ae8771cc37693feb160fa8727231312a0c54ef2d1d1ca893be568cd70016ca7e.json +1 -0
  276. xinference/ui/web/ui/node_modules/.cache/babel-loader/bb4e8722d2d41d87f1fce3661bc8937bffe9448e231fc5f0462630849e851592.json +1 -0
  277. xinference/ui/web/ui/node_modules/.cache/babel-loader/be6aada1ee4adc2bbf65dbe56d17db32bb3b5478be05d6b527805a8ba6cfb2b9.json +1 -0
  278. xinference/ui/web/ui/node_modules/.cache/babel-loader/de91c352653c233cf0cb6674e6e04049a44fd0e1156560de65d5c4620521391e.json +1 -0
  279. xinference/ui/web/ui/node_modules/.cache/babel-loader/e85f7002fc325c83b9c9cd8a1619e5b3ebc701d30e811afc284b88e6ae710cb5.json +1 -0
  280. xinference/ui/web/ui/node_modules/.cache/babel-loader/e8b603c78944bf3d213639078bfe155ff5c0dfa4048a93cbb967cad6a4eb4ff3.json +1 -0
  281. xinference/ui/web/ui/node_modules/.cache/babel-loader/ea2a26361204e70cf1018d6990fb6354bed82b3ac69690391e0f100385e7abb7.json +1 -0
  282. xinference/ui/web/ui/node_modules/.cache/babel-loader/f05535160a508b2a312de546a6de234776c613db276479ea4253c0b1bdeeb7d6.json +1 -0
  283. xinference/ui/web/ui/node_modules/.cache/babel-loader/f09ba9e11106bd59a0de10cc85c55084097729dcab575f43dfcf07375961ed87.json +1 -0
  284. xinference/ui/web/ui/node_modules/.package-lock.json +0 -33
  285. xinference/ui/web/ui/package-lock.json +0 -34
  286. xinference/ui/web/ui/package.json +0 -1
  287. xinference/ui/web/ui/src/locales/en.json +9 -3
  288. xinference/ui/web/ui/src/locales/ja.json +9 -3
  289. xinference/ui/web/ui/src/locales/ko.json +9 -3
  290. xinference/ui/web/ui/src/locales/zh.json +9 -3
  291. {xinference-1.10.0.dist-info → xinference-1.11.0.dist-info}/METADATA +24 -6
  292. {xinference-1.10.0.dist-info → xinference-1.11.0.dist-info}/RECORD +296 -77
  293. xinference/ui/web/ui/build/static/css/main.013f296b.css +0 -2
  294. xinference/ui/web/ui/build/static/css/main.013f296b.css.map +0 -1
  295. xinference/ui/web/ui/build/static/js/main.1086c759.js +0 -3
  296. xinference/ui/web/ui/build/static/js/main.1086c759.js.map +0 -1
  297. xinference/ui/web/ui/node_modules/.cache/babel-loader/0b0f77000cc1b482ca091cfbcae511dfe02f08916971645fad21d0b1234d04a2.json +0 -1
  298. xinference/ui/web/ui/node_modules/.cache/babel-loader/1c5f8ff423a7c9202bea60b15680f04b1e9964b445b0da3f86c6ff70cf24e797.json +0 -1
  299. xinference/ui/web/ui/node_modules/.cache/babel-loader/44ce7993e344980e3ed4f13e8f69237d4a5dfc60e37ca6b54f51f8ee1357bd67.json +0 -1
  300. xinference/ui/web/ui/node_modules/.cache/babel-loader/4aec1cc414ac3ebb3481d3d915e4db597d9127de813291346eacb8554ab170d4.json +0 -1
  301. xinference/ui/web/ui/node_modules/.cache/babel-loader/644cfec52f3c57a6e222ce60f112237a1efefe9835efd9aad857a685f53d8eed.json +0 -1
  302. xinference/ui/web/ui/node_modules/.cache/babel-loader/663436f72af53fe0d72394f56d003fa4e0bba489e5bb4e483fd34b00f84637f7.json +0 -1
  303. xinference/ui/web/ui/node_modules/.cache/babel-loader/69db82ca9bfe27fe417cc6cf2b1716b09be9c6f0cd198530f12bfc60e801bbcf.json +0 -1
  304. xinference/ui/web/ui/node_modules/.cache/babel-loader/85087e27618d740c236bf159f30e0219db443ab55f0997388eed5fde6f9e90cc.json +0 -1
  305. xinference/ui/web/ui/node_modules/.cache/babel-loader/88b07838348864aa86c672be3bbca1e9f58f6f3a2881b32070ec27f4e7b449d1.json +0 -1
  306. xinference/ui/web/ui/node_modules/.cache/babel-loader/8b8cd408ccfbe115acef27ccfa5b233da8597131a2a5712add13e1e4d5d4504b.json +0 -1
  307. xinference/ui/web/ui/node_modules/.cache/babel-loader/a23824fe746b9c6ca5eee9159b5764d1ff1653c1d856288c0f75c742bbb0023b.json +0 -1
  308. xinference/ui/web/ui/node_modules/.cache/babel-loader/a3eb18af328280b139693c9092dff2a0ef8c9a967e6c8956ceee0996611f1984.json +0 -1
  309. xinference/ui/web/ui/node_modules/.cache/babel-loader/bc1aacc65a102db325ca61bcd2f681e1ae22c36a1f1d98a6ff5e4ad49dc7544f.json +0 -1
  310. xinference/ui/web/ui/node_modules/.cache/babel-loader/c682fd521747c19dae437d83ce3235a306ce6b68e24a117bc57c27ebb8d1f1ca.json +0 -1
  311. xinference/ui/web/ui/node_modules/.cache/babel-loader/d5c224be7081f18cba1678b7874a9782eba895df004874ff8f243f94ba79942a.json +0 -1
  312. xinference/ui/web/ui/node_modules/.cache/babel-loader/f7f18bfb539b036a6a342176dd98a85df5057a884a8da978d679f2a0264883d0.json +0 -1
  313. xinference/ui/web/ui/node_modules/clipboard/.babelrc.json +0 -11
  314. xinference/ui/web/ui/node_modules/clipboard/.eslintrc.json +0 -24
  315. xinference/ui/web/ui/node_modules/clipboard/.prettierrc.json +0 -9
  316. xinference/ui/web/ui/node_modules/clipboard/bower.json +0 -18
  317. xinference/ui/web/ui/node_modules/clipboard/composer.json +0 -25
  318. xinference/ui/web/ui/node_modules/clipboard/package.json +0 -63
  319. xinference/ui/web/ui/node_modules/delegate/package.json +0 -31
  320. xinference/ui/web/ui/node_modules/good-listener/bower.json +0 -11
  321. xinference/ui/web/ui/node_modules/good-listener/package.json +0 -35
  322. xinference/ui/web/ui/node_modules/select/bower.json +0 -13
  323. xinference/ui/web/ui/node_modules/select/package.json +0 -29
  324. xinference/ui/web/ui/node_modules/tiny-emitter/package.json +0 -53
  325. {xinference-1.10.0.dist-info → xinference-1.11.0.dist-info}/WHEEL +0 -0
  326. {xinference-1.10.0.dist-info → xinference-1.11.0.dist-info}/entry_points.txt +0 -0
  327. {xinference-1.10.0.dist-info → xinference-1.11.0.dist-info}/licenses/LICENSE +0 -0
  328. {xinference-1.10.0.dist-info → xinference-1.11.0.dist-info}/top_level.txt +0 -0
@@ -74,6 +74,7 @@ class AsyncRESTfulModelHandle:
74
74
  self._model_uid = model_uid
75
75
  self._base_url = base_url
76
76
  self.auth_headers = auth_headers
77
+ self.timeout = aiohttp.ClientTimeout(total=1800)
77
78
  self.session = aiohttp.ClientSession(
78
79
  connector=aiohttp.TCPConnector(force_close=True)
79
80
  )
@@ -285,7 +286,7 @@ class AsyncRESTfulImageModelHandle(AsyncRESTfulModelHandle):
285
286
 
286
287
  async def image_to_image(
287
288
  self,
288
- image: Union[str, bytes],
289
+ image: Union[str, bytes, List[Union[str, bytes]]],
289
290
  prompt: str,
290
291
  negative_prompt: Optional[str] = None,
291
292
  n: int = 1,
@@ -298,7 +299,7 @@ class AsyncRESTfulImageModelHandle(AsyncRESTfulModelHandle):
298
299
 
299
300
  Parameters
300
301
  ----------
301
- image: `Union[str, bytes]`
302
+ image: `Union[str, bytes, List[Union[str, bytes]]]`
302
303
  The ControlNet input condition to provide guidance to the `unet` for generation. If the type is
303
304
  specified as `torch.FloatTensor`, it is passed to ControlNet as is. `PIL.Image.Image` can also be
304
305
  accepted as an image. The dimensions of the output image defaults to `image`'s dimensions. If height
@@ -338,8 +339,25 @@ class AsyncRESTfulImageModelHandle(AsyncRESTfulModelHandle):
338
339
  files: List[Any] = []
339
340
  for key, value in params.items():
340
341
  files.append((key, (None, value)))
341
- files.append(("image", ("image", image, "application/octet-stream")))
342
- response = await self.session.post(url, files=files, headers=self.auth_headers)
342
+
343
+ # Handle both single image and list of images
344
+ if isinstance(image, list):
345
+ if len(image) == 0:
346
+ raise ValueError("Image list cannot be empty")
347
+ elif len(image) == 1:
348
+ # Single image in list, use it directly
349
+ files.append(("image", ("image", image[0], "application/octet-stream")))
350
+ else:
351
+ # Multiple images - send all images with same field name
352
+ # FastAPI will collect them into a list
353
+ for img_data in image:
354
+ files.append(
355
+ ("image", ("image", img_data, "application/octet-stream"))
356
+ )
357
+ else:
358
+ # Single image
359
+ files.append(("image", ("image", image, "application/octet-stream")))
360
+ response = await self.session.post(url, data=files, headers=self.auth_headers)
343
361
  if response.status != 200:
344
362
  raise RuntimeError(
345
363
  f"Failed to variants the images, detail: {await _get_error_string(response)}"
@@ -349,6 +367,157 @@ class AsyncRESTfulImageModelHandle(AsyncRESTfulModelHandle):
349
367
  await _release_response(response)
350
368
  return response_data
351
369
 
370
+ async def image_edit(
371
+ self,
372
+ image: Union[Union[str, bytes], List[Union[str, bytes]]],
373
+ prompt: str,
374
+ mask: Optional[Union[str, bytes]] = None,
375
+ n: int = 1,
376
+ size: Optional[str] = None,
377
+ response_format: str = "url",
378
+ **kwargs,
379
+ ) -> "ImageList":
380
+ """
381
+ Edit image(s) by the input text and optional mask.
382
+
383
+ Parameters
384
+ ----------
385
+ image: `Union[Union[str, bytes], List[Union[str, bytes]]]`
386
+ The input image(s) to edit. Can be:
387
+ - Single image: file path, URL, or binary image data
388
+ - Multiple images: list of file paths, URLs, or binary image data
389
+ When multiple images are provided, the first image is used as the primary image
390
+ and subsequent images are used as reference images for better editing results.
391
+ prompt: `str`
392
+ The prompt or prompts to guide image editing. If not defined, you need to pass `prompt_embeds`.
393
+ mask: `Optional[Union[str, bytes]]`, optional
394
+ An optional mask image. White pixels in the mask are repainted while black pixels are preserved.
395
+ If provided, this will trigger inpainting mode. If not provided, this will trigger image-to-image mode.
396
+ n: `int`, defaults to 1
397
+ The number of images to generate per prompt. Must be between 1 and 10.
398
+ size: `Optional[str]`, optional
399
+ The width*height in pixels of the generated image. If not specified, uses the original image size.
400
+ response_format: `str`, defaults to `url`
401
+ The format in which the generated images are returned. Must be one of url or b64_json.
402
+ **kwargs
403
+ Additional parameters to pass to the model.
404
+
405
+ Returns
406
+ -------
407
+ ImageList
408
+ A list of edited image objects.
409
+
410
+ Raises
411
+ ------
412
+ RuntimeError
413
+ If the image editing request fails.
414
+
415
+ Examples
416
+ --------
417
+ # Single image editing
418
+ result = await model.image_edit(
419
+ image="path/to/image.png",
420
+ prompt="make this image look like a painting"
421
+ )
422
+
423
+ # Multiple image editing with reference images
424
+ result = await model.image_edit(
425
+ image=["primary_image.png", "reference1.jpg", "reference2.png"],
426
+ prompt="edit the main image using the style from reference images"
427
+ )
428
+ """
429
+ url = f"{self._base_url}/v1/images/edits"
430
+ params = {
431
+ "model": self._model_uid,
432
+ "prompt": prompt,
433
+ "n": n,
434
+ "size": size,
435
+ "response_format": response_format,
436
+ "kwargs": json.dumps(kwargs),
437
+ }
438
+ params = _filter_params(params)
439
+ files: List[Any] = []
440
+ for key, value in params.items():
441
+ files.append((key, (None, value)))
442
+
443
+ # Handle single image or multiple images
444
+ import aiohttp
445
+
446
+ data = aiohttp.FormData()
447
+
448
+ # Add all parameters as form fields
449
+ for key, value in params.items():
450
+ if value is not None:
451
+ data.add_field(key, str(value))
452
+
453
+ # Handle single image or multiple images
454
+ if isinstance(image, list):
455
+ # Validate image list is not empty
456
+ if len(image) == 0:
457
+ raise ValueError("Image list cannot be empty")
458
+ # Multiple images - send as image[] array
459
+ for i, img in enumerate(image):
460
+ if isinstance(img, str):
461
+ # File path - read file content
462
+ with open(img, "rb") as f:
463
+ content = f.read()
464
+ data.add_field(
465
+ f"image[]",
466
+ content,
467
+ filename=f"image_{i}.png",
468
+ content_type="image/png",
469
+ )
470
+ else:
471
+ # Binary data
472
+ data.add_field(
473
+ f"image[]",
474
+ img,
475
+ filename=f"image_{i}.png",
476
+ content_type="image/png",
477
+ )
478
+ else:
479
+ # Single image
480
+ if isinstance(image, str):
481
+ # File path - read file content
482
+ with open(image, "rb") as f:
483
+ content = f.read()
484
+ data.add_field(
485
+ "image", content, filename="image.png", content_type="image/png"
486
+ )
487
+ else:
488
+ # Binary data
489
+ data.add_field(
490
+ "image", image, filename="image.png", content_type="image/png"
491
+ )
492
+
493
+ if mask is not None:
494
+ if isinstance(mask, str):
495
+ # File path - read file content
496
+ with open(mask, "rb") as f:
497
+ content = f.read()
498
+ data.add_field(
499
+ "mask", content, filename="mask.png", content_type="image/png"
500
+ )
501
+ else:
502
+ # Binary data
503
+ data.add_field(
504
+ "mask", mask, filename="mask.png", content_type="image/png"
505
+ )
506
+
507
+ try:
508
+ response = await self.session.post(
509
+ url, data=data, headers=self.auth_headers
510
+ )
511
+ if response.status != 200:
512
+ raise RuntimeError(
513
+ f"Failed to edit the images, detail: {await _get_error_string(response)}"
514
+ )
515
+
516
+ response_data = await response.json()
517
+ return response_data
518
+ finally:
519
+ await _release_response(response) if "response" in locals() else None
520
+
352
521
  async def inpainting(
353
522
  self,
354
523
  image: Union[str, bytes],
@@ -419,7 +588,7 @@ class AsyncRESTfulImageModelHandle(AsyncRESTfulModelHandle):
419
588
  ("mask_image", mask_image, "application/octet-stream"),
420
589
  )
421
590
  )
422
- response = await self.session.post(url, files=files, headers=self.auth_headers)
591
+ response = await self.session.post(url, data=files, headers=self.auth_headers)
423
592
  if response.status != 200:
424
593
  raise RuntimeError(
425
594
  f"Failed to inpaint the images, detail: {await _get_error_string(response)}"
@@ -440,7 +609,7 @@ class AsyncRESTfulImageModelHandle(AsyncRESTfulModelHandle):
440
609
  for key, value in params.items():
441
610
  files.append((key, (None, value)))
442
611
  files.append(("image", ("image", image, "application/octet-stream")))
443
- response = await self.session.post(url, files=files, headers=self.auth_headers)
612
+ response = await self.session.post(url, data=files, headers=self.auth_headers)
444
613
  if response.status != 200:
445
614
  raise RuntimeError(
446
615
  f"Failed to ocr the images, detail: {await _get_error_string(response)}"
@@ -530,7 +699,7 @@ class AsyncRESTfulVideoModelHandle(AsyncRESTfulModelHandle):
530
699
  for key, value in params.items():
531
700
  files.append((key, (None, value)))
532
701
  files.append(("image", ("image", image, "application/octet-stream")))
533
- response = await self.session.post(url, files=files, headers=self.auth_headers)
702
+ response = await self.session.post(url, data=files, headers=self.auth_headers)
534
703
  if response.status != 200:
535
704
  raise RuntimeError(
536
705
  f"Failed to create the video from image, detail: {await _get_error_string(response)}"
@@ -970,8 +1139,9 @@ class AsyncClient:
970
1139
  self.base_url = base_url
971
1140
  self._headers: Dict[str, str] = {}
972
1141
  self._cluster_authed = False
1142
+ self.timeout = aiohttp.ClientTimeout(total=1800)
973
1143
  self.session = aiohttp.ClientSession(
974
- connector=aiohttp.TCPConnector(force_close=True)
1144
+ connector=aiohttp.TCPConnector(force_close=True), timeout=self.timeout
975
1145
  )
976
1146
  self._check_cluster_authenticated()
977
1147
  if api_key is not None and self._cluster_authed:
@@ -250,7 +250,7 @@ class RESTfulImageModelHandle(RESTfulModelHandle):
250
250
 
251
251
  def image_to_image(
252
252
  self,
253
- image: Union[str, bytes],
253
+ image: Union[str, bytes, List[Union[str, bytes]]],
254
254
  prompt: str,
255
255
  negative_prompt: Optional[str] = None,
256
256
  n: int = 1,
@@ -263,7 +263,7 @@ class RESTfulImageModelHandle(RESTfulModelHandle):
263
263
 
264
264
  Parameters
265
265
  ----------
266
- image: `Union[str, bytes]`
266
+ image: `Union[str, bytes, List[Union[str, bytes]]]`
267
267
  The ControlNet input condition to provide guidance to the `unet` for generation. If the type is
268
268
  specified as `torch.FloatTensor`, it is passed to ControlNet as is. `PIL.Image.Image` can also be
269
269
  accepted as an image. The dimensions of the output image defaults to `image`'s dimensions. If height
@@ -302,7 +302,24 @@ class RESTfulImageModelHandle(RESTfulModelHandle):
302
302
  files: List[Any] = []
303
303
  for key, value in params.items():
304
304
  files.append((key, (None, value)))
305
- files.append(("image", ("image", image, "application/octet-stream")))
305
+
306
+ # Handle both single image and list of images
307
+ if isinstance(image, list):
308
+ if len(image) == 0:
309
+ raise ValueError("Image list cannot be empty")
310
+ elif len(image) == 1:
311
+ # Single image in list, use it directly
312
+ files.append(("image", ("image", image[0], "application/octet-stream")))
313
+ else:
314
+ # Multiple images - send all images with same field name
315
+ # FastAPI will collect them into a list
316
+ for img_data in image:
317
+ files.append(
318
+ ("image", ("image", img_data, "application/octet-stream"))
319
+ )
320
+ else:
321
+ # Single image
322
+ files.append(("image", ("image", image, "application/octet-stream")))
306
323
  response = self.session.post(url, files=files, headers=self.auth_headers)
307
324
  if response.status_code != 200:
308
325
  raise RuntimeError(
@@ -312,6 +329,137 @@ class RESTfulImageModelHandle(RESTfulModelHandle):
312
329
  response_data = response.json()
313
330
  return response_data
314
331
 
332
+ def image_edit(
333
+ self,
334
+ image: Union[Union[str, bytes], List[Union[str, bytes]]],
335
+ prompt: str,
336
+ mask: Optional[Union[str, bytes]] = None,
337
+ n: int = 1,
338
+ size: Optional[str] = None,
339
+ response_format: str = "url",
340
+ **kwargs,
341
+ ) -> "ImageList":
342
+ """
343
+ Edit image(s) by the input text and optional mask.
344
+
345
+ Parameters
346
+ ----------
347
+ image: `Union[Union[str, bytes], List[Union[str, bytes]]]`
348
+ The input image(s) to edit. Can be:
349
+ - Single image: file path, URL, or binary image data
350
+ - Multiple images: list of file paths, URLs, or binary image data
351
+ When multiple images are provided, the first image is used as the primary image
352
+ and subsequent images are used as reference images for better editing results.
353
+ prompt: `str`
354
+ The prompt or prompts to guide image editing. If not defined, you need to pass `prompt_embeds`.
355
+ mask: `Optional[Union[str, bytes]]`, optional
356
+ An optional mask image. White pixels in the mask are repainted while black pixels are preserved.
357
+ If provided, this will trigger inpainting mode. If not provided, this will trigger image-to-image mode.
358
+ n: `int`, defaults to 1
359
+ The number of images to generate per prompt. Must be between 1 and 10.
360
+ size: `Optional[str]`, optional
361
+ The width*height in pixels of the generated image. If not specified, uses the original image size.
362
+ response_format: `str`, defaults to `url`
363
+ The format in which the generated images are returned. Must be one of url or b64_json.
364
+ **kwargs
365
+ Additional parameters to pass to the model.
366
+
367
+ Returns
368
+ -------
369
+ ImageList
370
+ A list of edited image objects.
371
+
372
+ Raises
373
+ ------
374
+ RuntimeError
375
+ If the image editing request fails.
376
+
377
+ Examples
378
+ --------
379
+ # Single image editing
380
+ result = model.image_edit(
381
+ image="path/to/image.png",
382
+ prompt="make this image look like a painting"
383
+ )
384
+
385
+ # Multiple image editing with reference images
386
+ result = model.image_edit(
387
+ image=["primary_image.png", "reference1.jpg", "reference2.png"],
388
+ prompt="edit the main image using the style from reference images"
389
+ )
390
+ """
391
+ url = f"{self._base_url}/v1/images/edits"
392
+ params = {
393
+ "model": self._model_uid,
394
+ "prompt": prompt,
395
+ "n": n,
396
+ "size": size,
397
+ "response_format": response_format,
398
+ "kwargs": json.dumps(kwargs),
399
+ }
400
+ files: List[Any] = []
401
+ for key, value in params.items():
402
+ if value is not None:
403
+ files.append((key, (None, value)))
404
+
405
+ # Handle single image or multiple images using requests format
406
+ if isinstance(image, list):
407
+ # Validate image list is not empty
408
+ if len(image) == 0:
409
+ raise ValueError("Image list cannot be empty")
410
+ # Multiple images - send as image[] array
411
+ for i, img in enumerate(image):
412
+ if isinstance(img, str):
413
+ # File path - open file
414
+ f = open(img, "rb")
415
+ files.append(
416
+ (f"image[]", (f"image_{i}", f, "application/octet-stream"))
417
+ )
418
+ else:
419
+ # Binary data
420
+ files.append(
421
+ (f"image[]", (f"image_{i}", img, "application/octet-stream"))
422
+ )
423
+ else:
424
+ # Single image
425
+ if isinstance(image, str):
426
+ # File path - open file
427
+ f = open(image, "rb")
428
+ files.append(("image", ("image", f, "application/octet-stream")))
429
+ else:
430
+ # Binary data
431
+ files.append(("image", ("image", image, "application/octet-stream")))
432
+
433
+ if mask is not None:
434
+ if isinstance(mask, str):
435
+ # File path - open file
436
+ f = open(mask, "rb")
437
+ files.append(("mask", ("mask", f, "application/octet-stream")))
438
+ else:
439
+ # Binary data
440
+ files.append(("mask", ("mask", mask, "application/octet-stream")))
441
+
442
+ try:
443
+ response = self.session.post(url, files=files, headers=self.auth_headers)
444
+ if response.status_code != 200:
445
+ raise RuntimeError(
446
+ f"Failed to edit the images, detail: {_get_error_string(response)}"
447
+ )
448
+
449
+ response_data = response.json()
450
+ return response_data
451
+ finally:
452
+ # Close all opened files
453
+ for file_item in files:
454
+ if (
455
+ len(file_item) >= 2
456
+ and hasattr(file_item[1], "__len__")
457
+ and len(file_item[1]) >= 2
458
+ ):
459
+ file_obj = file_item[1][1]
460
+ if hasattr(file_obj, "close"):
461
+ file_obj.close()
462
+
315
463
  def inpainting(
316
464
  self,
317
465
  image: Union[str, bytes],