hf-serve 0.1.0__tar.gz

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 (98) hide show
  1. hf_serve-0.1.0/PKG-INFO +215 -0
  2. hf_serve-0.1.0/README.md +170 -0
  3. hf_serve-0.1.0/pyproject.toml +136 -0
  4. hf_serve-0.1.0/src/hf_serve/__init__.py +0 -0
  5. hf_serve-0.1.0/src/hf_serve/cli.py +141 -0
  6. hf_serve-0.1.0/src/hf_serve/cli_utils.py +5 -0
  7. hf_serve-0.1.0/src/hf_serve/compatibility/__init__.py +0 -0
  8. hf_serve-0.1.0/src/hf_serve/compatibility/azure.py +14 -0
  9. hf_serve-0.1.0/src/hf_serve/compatibility/backwards.py +41 -0
  10. hf_serve-0.1.0/src/hf_serve/compatibility/google/__init__.py +0 -0
  11. hf_serve-0.1.0/src/hf_serve/compatibility/google/routers/__init__.py +0 -0
  12. hf_serve-0.1.0/src/hf_serve/compatibility/google/routers/health.py +11 -0
  13. hf_serve-0.1.0/src/hf_serve/compatibility/google/routers/predict.py +53 -0
  14. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/__init__.py +0 -0
  15. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/diffusers/__init__.py +0 -0
  16. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/diffusers/text_to_image.py +39 -0
  17. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/sentence_transformers/__init__.py +0 -0
  18. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/sentence_transformers/feature_extraction.py +34 -0
  19. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/sentence_transformers/sentence_similarity.py +35 -0
  20. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/sentence_transformers/text_ranking.py +43 -0
  21. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/transformers/__init__.py +0 -0
  22. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/transformers/any_to_any.py +15 -0
  23. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/transformers/audio_classification.py +18 -0
  24. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/transformers/automatic_speech_recognition.py +18 -0
  25. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/transformers/fill_mask.py +15 -0
  26. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/transformers/image_classification.py +18 -0
  27. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/transformers/image_segmentation.py +18 -0
  28. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/transformers/image_text_to_text.py +19 -0
  29. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/transformers/mask_generation.py +15 -0
  30. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/transformers/object_detection.py +18 -0
  31. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/transformers/table_question_answering.py +19 -0
  32. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/transformers/text_classification.py +18 -0
  33. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/transformers/text_generation.py +15 -0
  34. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/transformers/token_classification.py +21 -0
  35. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/transformers/zero_shot_classification.py +31 -0
  36. hf_serve-0.1.0/src/hf_serve/compatibility/google/schemas/transformers/zero_shot_image_classification.py +18 -0
  37. hf_serve-0.1.0/src/hf_serve/compatibility/text_embeddings_inference.py +10 -0
  38. hf_serve-0.1.0/src/hf_serve/file_validator.py +20 -0
  39. hf_serve-0.1.0/src/hf_serve/logging.py +15 -0
  40. hf_serve-0.1.0/src/hf_serve/middleware/__init__.py +5 -0
  41. hf_serve-0.1.0/src/hf_serve/middleware/logging.py +54 -0
  42. hf_serve-0.1.0/src/hf_serve/middleware/prometheus.py +48 -0
  43. hf_serve-0.1.0/src/hf_serve/middleware/request_id.py +31 -0
  44. hf_serve-0.1.0/src/hf_serve/openai/__init__.py +0 -0
  45. hf_serve-0.1.0/src/hf_serve/openai/routers/__init__.py +6 -0
  46. hf_serve-0.1.0/src/hf_serve/openai/routers/chat_completions.py +64 -0
  47. hf_serve-0.1.0/src/hf_serve/openai/routers/embeddings.py +27 -0
  48. hf_serve-0.1.0/src/hf_serve/openai/routers/images_generations.py +39 -0
  49. hf_serve-0.1.0/src/hf_serve/openai/routers/models.py +26 -0
  50. hf_serve-0.1.0/src/hf_serve/openai/schemas/__init__.py +0 -0
  51. hf_serve-0.1.0/src/hf_serve/openai/schemas/chat_completions.py +397 -0
  52. hf_serve-0.1.0/src/hf_serve/openai/schemas/embeddings.py +34 -0
  53. hf_serve-0.1.0/src/hf_serve/openai/schemas/images_generations.py +42 -0
  54. hf_serve-0.1.0/src/hf_serve/openai/tasks/__init__.py +0 -0
  55. hf_serve-0.1.0/src/hf_serve/openai/tasks/chat_completions.py +405 -0
  56. hf_serve-0.1.0/src/hf_serve/openai/tasks/embeddings.py +82 -0
  57. hf_serve-0.1.0/src/hf_serve/openai/tasks/images_generations.py +89 -0
  58. hf_serve-0.1.0/src/hf_serve/routers/__init__.py +15 -0
  59. hf_serve-0.1.0/src/hf_serve/routers/custom.py +39 -0
  60. hf_serve-0.1.0/src/hf_serve/routers/health.py +18 -0
  61. hf_serve-0.1.0/src/hf_serve/routers/metrics.py +10 -0
  62. hf_serve-0.1.0/src/hf_serve/routers/predict.py +41 -0
  63. hf_serve-0.1.0/src/hf_serve/routers/predict_image.py +59 -0
  64. hf_serve-0.1.0/src/hf_serve/routers/predict_media.py +114 -0
  65. hf_serve-0.1.0/src/hf_serve/serde/__init__.py +4 -0
  66. hf_serve-0.1.0/src/hf_serve/serde/audio.py +35 -0
  67. hf_serve-0.1.0/src/hf_serve/serde/image.py +29 -0
  68. hf_serve-0.1.0/src/hf_serve/server.py +1201 -0
  69. hf_serve-0.1.0/src/hf_serve/server_utils.py +44 -0
  70. hf_serve-0.1.0/src/hf_serve/tasks/__init__.py +0 -0
  71. hf_serve-0.1.0/src/hf_serve/tasks/custom.py +61 -0
  72. hf_serve-0.1.0/src/hf_serve/tasks/diffusers/__init__.py +0 -0
  73. hf_serve-0.1.0/src/hf_serve/tasks/diffusers/text_to_image.py +133 -0
  74. hf_serve-0.1.0/src/hf_serve/tasks/predictor.py +81 -0
  75. hf_serve-0.1.0/src/hf_serve/tasks/sentence_transformers/__init__.py +0 -0
  76. hf_serve-0.1.0/src/hf_serve/tasks/sentence_transformers/feature_extraction.py +157 -0
  77. hf_serve-0.1.0/src/hf_serve/tasks/sentence_transformers/sentence_similarity.py +127 -0
  78. hf_serve-0.1.0/src/hf_serve/tasks/sentence_transformers/text_ranking.py +152 -0
  79. hf_serve-0.1.0/src/hf_serve/tasks/transformers/__init__.py +0 -0
  80. hf_serve-0.1.0/src/hf_serve/tasks/transformers/any_to_any.py +86 -0
  81. hf_serve-0.1.0/src/hf_serve/tasks/transformers/audio_classification.py +99 -0
  82. hf_serve-0.1.0/src/hf_serve/tasks/transformers/automatic_speech_recognition.py +170 -0
  83. hf_serve-0.1.0/src/hf_serve/tasks/transformers/fill_mask.py +85 -0
  84. hf_serve-0.1.0/src/hf_serve/tasks/transformers/image_classification.py +92 -0
  85. hf_serve-0.1.0/src/hf_serve/tasks/transformers/image_segmentation.py +109 -0
  86. hf_serve-0.1.0/src/hf_serve/tasks/transformers/image_text_to_text.py +114 -0
  87. hf_serve-0.1.0/src/hf_serve/tasks/transformers/mask_generation.py +118 -0
  88. hf_serve-0.1.0/src/hf_serve/tasks/transformers/object_detection.py +95 -0
  89. hf_serve-0.1.0/src/hf_serve/tasks/transformers/table_question_answering.py +93 -0
  90. hf_serve-0.1.0/src/hf_serve/tasks/transformers/text_classification.py +83 -0
  91. hf_serve-0.1.0/src/hf_serve/tasks/transformers/text_generation.py +107 -0
  92. hf_serve-0.1.0/src/hf_serve/tasks/transformers/token_classification.py +88 -0
  93. hf_serve-0.1.0/src/hf_serve/tasks/transformers/zero_shot_audio_classification.py +120 -0
  94. hf_serve-0.1.0/src/hf_serve/tasks/transformers/zero_shot_classification.py +96 -0
  95. hf_serve-0.1.0/src/hf_serve/tasks/transformers/zero_shot_image_classification.py +101 -0
  96. hf_serve-0.1.0/src/hf_serve/types/__init__.py +4 -0
  97. hf_serve-0.1.0/src/hf_serve/types/form.py +10 -0
  98. hf_serve-0.1.0/src/hf_serve/types/task.py +32 -0
@@ -0,0 +1,215 @@
1
+ Metadata-Version: 2.4
2
+ Name: hf-serve
3
+ Version: 0.1.0
4
+ Summary: Experimental Hugging Face API for Transformers, Diffusers and Sentence Transformers, written in Python.
5
+ Author: Alvaro Bartolome
6
+ Author-email: Alvaro Bartolome <alvaro.bartolome@huggingface.co>
7
+ License-Expression: Apache-2.0
8
+ Requires-Dist: uvicorn>=0.34.0
9
+ Requires-Dist: fastapi>=0.115.6
10
+ Requires-Dist: starlette>=1.0.1
11
+ Requires-Dist: prometheus-client>=0.21.1
12
+ Requires-Dist: torch
13
+ Requires-Dist: torchvision
14
+ Requires-Dist: torchcodec
15
+ Requires-Dist: diffusers>=0.37.0
16
+ Requires-Dist: transformers[accelerate,audio,chat-template,kernels,timm,vision]>=5.9.0
17
+ Requires-Dist: pydantic>=2.10.5
18
+ Requires-Dist: sentence-transformers>=5.5.1
19
+ Requires-Dist: sentencepiece>=0.2.0
20
+ Requires-Dist: protobuf>=5.29.3
21
+ Requires-Dist: peft>=0.14.0
22
+ Requires-Dist: pillow>=11.1.0
23
+ Requires-Dist: pydub>=0.25.0
24
+ Requires-Dist: python-multipart>=0.0.20
25
+ Requires-Dist: python-magic>=0.4.27
26
+ Requires-Dist: pandas>=2.3.3
27
+ Requires-Dist: torch>=2.5.1,<2.8.0 ; extra == 'cpu'
28
+ Requires-Dist: torchvision ; extra == 'cpu'
29
+ Requires-Dist: torchcodec<0.6 ; extra == 'cpu'
30
+ Requires-Dist: torch>=2.5.1,<2.8.0 ; extra == 'cuda'
31
+ Requires-Dist: torchvision ; extra == 'cuda'
32
+ Requires-Dist: torchcodec<0.6 ; extra == 'cuda'
33
+ Requires-Dist: torch>2.8.0 ; extra == 'cuda-130'
34
+ Requires-Dist: torchvision ; extra == 'cuda-130'
35
+ Requires-Dist: torchcodec ; extra == 'cuda-130'
36
+ Requires-Dist: flash-attn==2.8.3 ; extra == 'flash-attn'
37
+ Maintainer: Alvaro Bartolome, Juan Julian Cea, Erik Kaunismäki
38
+ Maintainer-email: Alvaro Bartolome <alvaro.bartolome@huggingface.co>, Juan Julian Cea <juan.moran@huggingface.co>, Erik Kaunismäki <erik.kaunismaki@huggingface.co>
39
+ Requires-Python: >=3.10, <3.13
40
+ Provides-Extra: cpu
41
+ Provides-Extra: cuda
42
+ Provides-Extra: cuda-130
43
+ Provides-Extra: flash-attn
44
+ Description-Content-Type: text/markdown
45
+
46
+ # `hf-serve`
47
+
48
+ > [!WARNING]
49
+ > This project is still experimental, meant to replace the former
50
+ > [`huggingface-inference-toolkit`](https://github.com/huggingface/huggingface-inference-toolkit).
51
+
52
+ ## Installation
53
+
54
+ First you need to setup your environment with [`uv`](https://github.com/astral-sh/uv) (or with your preferred Python environment manager).
55
+
56
+ ```bash
57
+ uv venv --python 3.12
58
+ source .venv/bin/activate
59
+ ```
60
+
61
+ > [!NOTE]
62
+ > Due to the need of `--preview-features extra-build-dependencies` to install
63
+ > [`flash-attn`](https://github.com/Dao-AILab/flash-attention) with `uv` without
64
+ > compiling it, but rather relying on the pre-built binaries, you need to use
65
+ > `uv` v0.8.13 (or higher, but beware on major updates since the feature is
66
+ > still experimental, so < v0.9.0 is recommended until stable).
67
+ >
68
+ > Reference: https://docs.astral.sh/uv/concepts/projects/config/#augmenting-build-dependencies
69
+ >
70
+ > To update `uv` once installed if `uv version` is lower than v0.8.13, simply
71
+ > `uv self update`.
72
+
73
+ Install it from the `uv.lock` file for CPU / MPS as follows:
74
+
75
+ ```bash
76
+ uv sync --active --frozen --extra cpu
77
+ ```
78
+
79
+ Alternatively, install it on NVIDIA CUDA 12.6 as follows:
80
+
81
+ ```bash
82
+ uv sync --active --frozen --extra cuda-126 --extra flash-attn --preview-features extra-build-dependencies
83
+ ```
84
+
85
+ Or if you have CUDA +13.0 then:
86
+
87
+ ```bash
88
+ uv sync --active --frozen --extra cuda-130 --extra flash-attn --preview-features extra-build-dependencies
89
+ ```
90
+
91
+ > [!WARNING]
92
+ > The default registry for the NVIDIA CUDA wheels for PyTorch is set to CUDA 12.6. If
93
+ > you want to install another PyTorch version as per the CUDA compatibility, then
94
+ > run e.g. `uv pip install -e . --torch-backend cu128`, but note it won't be relying
95
+ > on the `uv.lock` so some dependencies might mismatch.
96
+ >
97
+ > Reference: https://docs.astral.sh/uv/guides/integration/pytorch/#automatic-backend-selection
98
+
99
+ ```console
100
+ $ uv run hf-serve --help
101
+ ```
102
+
103
+ ## Examples
104
+
105
+ > [!NOTE]
106
+ > On the examples below, given the recently introduced `extra-build-dependencies`
107
+ > for `flash-attn` on CUDA as per https://docs.astral.sh/uv/concepts/projects/config/#build-isolation,
108
+ > it means that you'll need to run the examples as `uv run --preview-features extra-build-dependencies ...`
109
+ > to disable the warning:
110
+ > ```console
111
+ > warning: The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features extra-build-dependencies` to disable this warning.
112
+ > ```
113
+
114
+ ### 🤏 Run `HuggingFaceTB/SmolLM3-3B` with an OpenAI API
115
+
116
+ ```bash
117
+ uv run hf-serve --model-id HuggingFaceTB/SmolLM3-3B --task text-generation --dtype float16
118
+ ```
119
+
120
+ > [!NOTE]
121
+ > If you are running on an instance with NVIDIA GPU, it's recommended to install `hf-serve`
122
+ > with `flash-attn` extra in order to benefit from accelerated inference:
123
+ > ```bash
124
+ > uv sync --active --frozen --extra cuda --extra flash-attn --preview-features extra-build-dependencies
125
+ > ```
126
+
127
+ ### 🔵 Run `sentence-transformers/all-MiniLM-L6-v2` on Azure AI
128
+
129
+ ```bash
130
+ uv run hf-serve --model-id sentence-transformers/all-MiniLM-L6-v2 --task sentence-similarity --dtype float32 --cloud azure
131
+ ```
132
+
133
+ > [!WARNING]
134
+ > Given that Azure AI Foundry and Azure ML expect the inference route to be `/score`
135
+ > rather than `/predict`, which is the standard for Inference Endpoints API, and since
136
+ > `/score` is a redirect to `/predict`, then we need to send the `curl` request with the
137
+ > `-L/--location` flag so that it follows the redirect, otherwise we get an HTTP 307.
138
+ >
139
+ > ```bash
140
+ > curl -L http://localhost:8080/score -H "Content-Type: application/json" -d '{"inputs":{"source_sentence":"What is Deep Learning?","sentences":["Deep Learning is...","Deep Learning is not..."]}}'
141
+ > ```
142
+
143
+ ### 👂 Run `facebook/wav2vec2-base-960h` an `automatic-speech-recognition` model
144
+
145
+ > [!NOTE]
146
+ > Before running `automatic-speech-recognition` or really any of `audio-classification`
147
+ > or `zero-shot-audio-classification` you will need to install some system dependencies
148
+ > in advance for those to work as `ffmpeg` and `libmagic-dev`.
149
+
150
+ ```bash
151
+ uv run hf-serve --model-id facebook/wav2vec2-large-960h --task automatic-speech-recognition --dtype float16
152
+ ```
153
+
154
+ > [!WARNING]
155
+ > On MacOS, if you installed `ffmpeg` via `brew`, you will need to set the following
156
+ > environment variable in advance `DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib`
157
+ >
158
+ > Reference: https://github.com/pytorch/torchcodec/issues/570#issuecomment-2913609176
159
+
160
+ And, then you can send a sample request as:
161
+
162
+ ```bash
163
+ curl -L http://localhost:8080/predict \
164
+ -H "Content-Type: application/json" \
165
+ -d '{"inputs":"https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/1.flac"}'
166
+ ```
167
+
168
+ > [!WARNING]
169
+ > Given the nature of some tasks that need to support JSON, forms, and files,
170
+ > the `/predict` method for those is a redirect to the respective inner endpoint:
171
+ > `/predict-json`, `/predict-form`, and `/predict-file`. Those are non-standard
172
+ > but required to keep full compatibility with the current Hugging Face Inference
173
+ > Endpoints API Specification, but in reality the redirect response (HTTP 307)
174
+ > shouldn't be used as an routing route, but rather dedicated routes for those.
175
+
176
+ > [!NOTE]
177
+ > The OpenAI Audio Transcriptions API is still not yet part of `hf-serve` but it's
178
+ > on the roadmap and it will be released soon, stay tuned!
179
+
180
+ ### 🔈 Run `facebook/wav2vec2-lv-60-espeak-cv-ft` (with `phonemizer` and `espeak`)
181
+
182
+ > [!NOTE]
183
+ > Some models as e.g. `facebook/wav2vec2-lv-60-espeak-cv-ft`, rely on `phonemizer` for
184
+ > the "phonemization" of words and texts in many languages, based at the same time on
185
+ > different Text-To-Speech (TTS) backends as e.g. `espeak-ng` which is supports a lot
186
+ > of languages and IPA (International Phonetic Alphabet). This being said, such models
187
+ > require custom dependencies that need to be installed beforehand as those don't come
188
+ > as default `hf-serve` dependencies; whilst those can be installed as e.g. on MacOS:
189
+ >
190
+ > ```bash
191
+ > brew install ffmpeg
192
+ > brew install espeak
193
+ > ```
194
+
195
+ > [!WARNING]
196
+ > Beware that when installing `ffmpeg` with `brew` on a specific
197
+ > version as e.g. `brew install ffmpeg@7` as it will be installed as "keg-only",
198
+ > meaning that it won't be symlinked into `/opt/homebrew`, meaning that the path
199
+ > to the library won't be `/opt/homebrew/lib` but rather `/opt/homebrew/opt/ffmpeg/lib`
200
+ > instead, meaning that on MacOS you'll need to set `DYLD_FALLBACK_LIBRARY_PATH`
201
+ > to wherever the `ffmpeg` library is installed in.
202
+
203
+ To run `facebook/wav2vec2-lv-60-espeak-cv-ft` on e.g. MacOS, you need to run the following:
204
+
205
+ ```bash
206
+ DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib uv run hf-serve --model-id facebook/wav2vec2-lv-60-espeak-cv-ft --task automatic-speech-recognition --dtype float16 --device mps
207
+ ```
208
+
209
+ Note that if you have installed another version of `ffmpeg` with `brew` as e.g. `brew install ffmpeg@7`, you should use the following command instead:
210
+
211
+ ```bash
212
+ DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/opt/ffmpeg@7/lib uv run hf-serve --model-id facebook/wav2vec2-lv-60-espeak-cv-ft --task automatic-speech-recognition --dtype float16 --device mps
213
+ ```
214
+
215
+ The main difference relies on the path used for `DYLD_FALLBACK_LIBRARY_PATH` which is now pointing to the exact `brew`-installed version of `ffmpeg` instead. More information on the compatibility issues with `ffmpeg`, `torchcodec` and `torch` at https://github.com/meta-pytorch/torchcodec?tab=readme-ov-file#installing-torchcodec.
@@ -0,0 +1,170 @@
1
+ # `hf-serve`
2
+
3
+ > [!WARNING]
4
+ > This project is still experimental, meant to replace the former
5
+ > [`huggingface-inference-toolkit`](https://github.com/huggingface/huggingface-inference-toolkit).
6
+
7
+ ## Installation
8
+
9
+ First you need to setup your environment with [`uv`](https://github.com/astral-sh/uv) (or with your preferred Python environment manager).
10
+
11
+ ```bash
12
+ uv venv --python 3.12
13
+ source .venv/bin/activate
14
+ ```
15
+
16
+ > [!NOTE]
17
+ > Due to the need of `--preview-features extra-build-dependencies` to install
18
+ > [`flash-attn`](https://github.com/Dao-AILab/flash-attention) with `uv` without
19
+ > compiling it, but rather relying on the pre-built binaries, you need to use
20
+ > `uv` v0.8.13 (or higher, but beware on major updates since the feature is
21
+ > still experimental, so < v0.9.0 is recommended until stable).
22
+ >
23
+ > Reference: https://docs.astral.sh/uv/concepts/projects/config/#augmenting-build-dependencies
24
+ >
25
+ > To update `uv` once installed if `uv version` is lower than v0.8.13, simply
26
+ > `uv self update`.
27
+
28
+ Install it from the `uv.lock` file for CPU / MPS as follows:
29
+
30
+ ```bash
31
+ uv sync --active --frozen --extra cpu
32
+ ```
33
+
34
+ Alternatively, install it on NVIDIA CUDA 12.6 as follows:
35
+
36
+ ```bash
37
+ uv sync --active --frozen --extra cuda-126 --extra flash-attn --preview-features extra-build-dependencies
38
+ ```
39
+
40
+ Or if you have CUDA +13.0 then:
41
+
42
+ ```bash
43
+ uv sync --active --frozen --extra cuda-130 --extra flash-attn --preview-features extra-build-dependencies
44
+ ```
45
+
46
+ > [!WARNING]
47
+ > The default registry for the NVIDIA CUDA wheels for PyTorch is set to CUDA 12.6. If
48
+ > you want to install another PyTorch version as per the CUDA compatibility, then
49
+ > run e.g. `uv pip install -e . --torch-backend cu128`, but note it won't be relying
50
+ > on the `uv.lock` so some dependencies might mismatch.
51
+ >
52
+ > Reference: https://docs.astral.sh/uv/guides/integration/pytorch/#automatic-backend-selection
53
+
54
+ ```console
55
+ $ uv run hf-serve --help
56
+ ```
57
+
58
+ ## Examples
59
+
60
+ > [!NOTE]
61
+ > On the examples below, given the recently introduced `extra-build-dependencies`
62
+ > for `flash-attn` on CUDA as per https://docs.astral.sh/uv/concepts/projects/config/#build-isolation,
63
+ > it means that you'll need to run the examples as `uv run --preview-features extra-build-dependencies ...`
64
+ > to disable the warning:
65
+ > ```console
66
+ > warning: The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features extra-build-dependencies` to disable this warning.
67
+ > ```
68
+
69
+ ### 🤏 Run `HuggingFaceTB/SmolLM3-3B` with an OpenAI API
70
+
71
+ ```bash
72
+ uv run hf-serve --model-id HuggingFaceTB/SmolLM3-3B --task text-generation --dtype float16
73
+ ```
74
+
75
+ > [!NOTE]
76
+ > If you are running on an instance with NVIDIA GPU, it's recommended to install `hf-serve`
77
+ > with `flash-attn` extra in order to benefit from accelerated inference:
78
+ > ```bash
79
+ > uv sync --active --frozen --extra cuda --extra flash-attn --preview-features extra-build-dependencies
80
+ > ```
81
+
82
+ ### 🔵 Run `sentence-transformers/all-MiniLM-L6-v2` on Azure AI
83
+
84
+ ```bash
85
+ uv run hf-serve --model-id sentence-transformers/all-MiniLM-L6-v2 --task sentence-similarity --dtype float32 --cloud azure
86
+ ```
87
+
88
+ > [!WARNING]
89
+ > Given that Azure AI Foundry and Azure ML expect the inference route to be `/score`
90
+ > rather than `/predict`, which is the standard for Inference Endpoints API, and since
91
+ > `/score` is a redirect to `/predict`, then we need to send the `curl` request with the
92
+ > `-L/--location` flag so that it follows the redirect, otherwise we get an HTTP 307.
93
+ >
94
+ > ```bash
95
+ > curl -L http://localhost:8080/score -H "Content-Type: application/json" -d '{"inputs":{"source_sentence":"What is Deep Learning?","sentences":["Deep Learning is...","Deep Learning is not..."]}}'
96
+ > ```
97
+
98
+ ### 👂 Run `facebook/wav2vec2-base-960h` an `automatic-speech-recognition` model
99
+
100
+ > [!NOTE]
101
+ > Before running `automatic-speech-recognition` or really any of `audio-classification`
102
+ > or `zero-shot-audio-classification` you will need to install some system dependencies
103
+ > in advance for those to work as `ffmpeg` and `libmagic-dev`.
104
+
105
+ ```bash
106
+ uv run hf-serve --model-id facebook/wav2vec2-large-960h --task automatic-speech-recognition --dtype float16
107
+ ```
108
+
109
+ > [!WARNING]
110
+ > On MacOS, if you installed `ffmpeg` via `brew`, you will need to set the following
111
+ > environment variable in advance `DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib`
112
+ >
113
+ > Reference: https://github.com/pytorch/torchcodec/issues/570#issuecomment-2913609176
114
+
115
+ And, then you can send a sample request as:
116
+
117
+ ```bash
118
+ curl -L http://localhost:8080/predict \
119
+ -H "Content-Type: application/json" \
120
+ -d '{"inputs":"https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/1.flac"}'
121
+ ```
122
+
123
+ > [!WARNING]
124
+ > Given the nature of some tasks that need to support JSON, forms, and files,
125
+ > the `/predict` method for those is a redirect to the respective inner endpoint:
126
+ > `/predict-json`, `/predict-form`, and `/predict-file`. Those are non-standard
127
+ > but required to keep full compatibility with the current Hugging Face Inference
128
+ > Endpoints API Specification, but in reality the redirect response (HTTP 307)
129
+ > shouldn't be used as an routing route, but rather dedicated routes for those.
130
+
131
+ > [!NOTE]
132
+ > The OpenAI Audio Transcriptions API is still not yet part of `hf-serve` but it's
133
+ > on the roadmap and it will be released soon, stay tuned!
134
+
135
+ ### 🔈 Run `facebook/wav2vec2-lv-60-espeak-cv-ft` (with `phonemizer` and `espeak`)
136
+
137
+ > [!NOTE]
138
+ > Some models as e.g. `facebook/wav2vec2-lv-60-espeak-cv-ft`, rely on `phonemizer` for
139
+ > the "phonemization" of words and texts in many languages, based at the same time on
140
+ > different Text-To-Speech (TTS) backends as e.g. `espeak-ng` which is supports a lot
141
+ > of languages and IPA (International Phonetic Alphabet). This being said, such models
142
+ > require custom dependencies that need to be installed beforehand as those don't come
143
+ > as default `hf-serve` dependencies; whilst those can be installed as e.g. on MacOS:
144
+ >
145
+ > ```bash
146
+ > brew install ffmpeg
147
+ > brew install espeak
148
+ > ```
149
+
150
+ > [!WARNING]
151
+ > Beware that when installing `ffmpeg` with `brew` on a specific
152
+ > version as e.g. `brew install ffmpeg@7` as it will be installed as "keg-only",
153
+ > meaning that it won't be symlinked into `/opt/homebrew`, meaning that the path
154
+ > to the library won't be `/opt/homebrew/lib` but rather `/opt/homebrew/opt/ffmpeg/lib`
155
+ > instead, meaning that on MacOS you'll need to set `DYLD_FALLBACK_LIBRARY_PATH`
156
+ > to wherever the `ffmpeg` library is installed in.
157
+
158
+ To run `facebook/wav2vec2-lv-60-espeak-cv-ft` on e.g. MacOS, you need to run the following:
159
+
160
+ ```bash
161
+ DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib uv run hf-serve --model-id facebook/wav2vec2-lv-60-espeak-cv-ft --task automatic-speech-recognition --dtype float16 --device mps
162
+ ```
163
+
164
+ Note that if you have installed another version of `ffmpeg` with `brew` as e.g. `brew install ffmpeg@7`, you should use the following command instead:
165
+
166
+ ```bash
167
+ DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/opt/ffmpeg@7/lib uv run hf-serve --model-id facebook/wav2vec2-lv-60-espeak-cv-ft --task automatic-speech-recognition --dtype float16 --device mps
168
+ ```
169
+
170
+ The main difference relies on the path used for `DYLD_FALLBACK_LIBRARY_PATH` which is now pointing to the exact `brew`-installed version of `ffmpeg` instead. More information on the compatibility issues with `ffmpeg`, `torchcodec` and `torch` at https://github.com/meta-pytorch/torchcodec?tab=readme-ov-file#installing-torchcodec.
@@ -0,0 +1,136 @@
1
+ [project]
2
+ name = "hf-serve"
3
+ version = "0.1.0"
4
+ description = "Experimental Hugging Face API for Transformers, Diffusers and Sentence Transformers, written in Python."
5
+ readme = "README.md"
6
+ license = "Apache-2.0"
7
+ authors = [
8
+ { name = "Alvaro Bartolome", email = "alvaro.bartolome@huggingface.co" },
9
+ ]
10
+ maintainers = [
11
+ { name = "Alvaro Bartolome", email = "alvaro.bartolome@huggingface.co" },
12
+ { name = "Juan Julian Cea", email = "juan.moran@huggingface.co" },
13
+ { name = "Erik Kaunismäki", email = "erik.kaunismaki@huggingface.co" },
14
+ ]
15
+ requires-python = ">=3.10,<3.13"
16
+ dependencies = [
17
+ "uvicorn>=0.34.0",
18
+ "fastapi>=0.115.6",
19
+ # Floor pinned to the version that fixes CVE-2026-48710 (GHSA-86qp-5c8j-p5mr),
20
+ # Host header poisons request.url.path. The Starlette range FastAPI allows
21
+ # would otherwise let a fresh resolve drop back to vulnerable 0.x or 1.0.0.
22
+ "starlette>=1.0.1",
23
+ "prometheus-client>=0.21.1",
24
+ "torch",
25
+ "torchvision",
26
+ # NOTE: `torchcodec` as opposed to `torch` won't install the CUDA-compatible
27
+ # version by default but rather the CPU-only one.
28
+ # Reference: https://github.com/meta-pytorch/torchcodec?tab=readme-ov-file#installing-torchcodec
29
+ "torchcodec",
30
+ # NOTE: `diffusers` won't complain, but support for `transformers` 5.0.0+
31
+ # is still work in progress as per https://github.com/huggingface/diffusers/pull/12976
32
+ "diffusers>=0.37.0",
33
+ # NOTE: `torch-speech` is now `audio` in Transformers 5.0+ and `phonemizer`
34
+ # is included as a default dependency instead of an `audio` specific one.
35
+ # Anyway, `audio` models might need some system dependencies e.g. `espeak-ng`
36
+ "transformers[accelerate,audio,chat_template,kernels,timm,vision]>=5.9.0",
37
+ "pydantic>=2.10.5",
38
+ # NOTE: `optimum[onnxruntime]` seems to have a cap on `transformers<4.53.0`
39
+ # NOTE: `optimum` for ONNX recently migrated to `optimum-onnx` at https://github.com/huggingface/optimum-onnx
40
+ # but still has the cap on `transformers<4.56.0` which prevents us from relying on `main`
41
+ # "sentence-transformers[onnx]>=5.0.0",
42
+ # NOTE: for GPU that'd be the following
43
+ # "sentence-transformers[onnx-gpu]>=5.0.0",
44
+ "sentence-transformers>=5.5.1",
45
+ "sentencepiece>=0.2.0",
46
+ "protobuf>=5.29.3",
47
+ "peft>=0.14.0",
48
+ "pillow>=11.1.0",
49
+ # NOTE: `pydub` is required for `automatic-speech-recognition` to parse the
50
+ # audio bytes and calculate the audio duration in seconds
51
+ "pydub>=0.25.0",
52
+ "python-multipart>=0.0.20",
53
+ "python-magic>=0.4.27",
54
+ "pandas>=2.3.3",
55
+ ]
56
+
57
+ [project.optional-dependencies]
58
+ cpu = ["torch>=2.5.1,<2.8.0", "torchvision", "torchcodec<0.6"]
59
+ cuda = ["torch>=2.5.1,<2.8.0", "torchvision", "torchcodec<0.6"]
60
+ cuda-130 = ["torch>2.8.0", "torchvision", "torchcodec"]
61
+ flash-attn = ["flash-attn==2.8.3"]
62
+
63
+ # causal-1dconv = ["causal_conv1d==1.5.2"]
64
+ # NOTE: `flash-linear-attention` has a lock on `transformers`<4.5.6.0
65
+ # flash-linear-attention = ["flash-linear-attention==0.3.2"]
66
+
67
+ # NOTE: useful for Intel `auto-round` quants, most likely can be installed on the fly if needed (?)
68
+ # e.g. https://huggingface.co/Intel/Qwen3-Next-80B-A3B-Instruct-int4-mixed-AutoRound/tree/main
69
+ # Reference: https://github.com/intel/auto-round
70
+ # quantization = ["auto-round>=0.5.0", "gptqmodel==4.2.5", "bitsandbytes>=0.47.0"]
71
+
72
+ [build-system]
73
+ requires = ["uv_build>=0.9.26,<0.10.0"]
74
+ build-backend = "uv_build"
75
+
76
+ [project.scripts]
77
+ hf-serve = "hf_serve.cli:main"
78
+
79
+ [tool.ruff]
80
+ line-length = 112
81
+
82
+ [tool.ruff.lint]
83
+ select = ["I"]
84
+
85
+ [tool.ruff.lint.isort]
86
+ force-single-line = false
87
+
88
+ [tool.uv]
89
+ conflicts = [
90
+ [
91
+ { extra = "cpu" },
92
+ { extra = "cuda" },
93
+ { extra = "cuda-130" },
94
+ ],
95
+ ]
96
+
97
+ [tool.uv.sources]
98
+ torch = [
99
+ { index = "pytorch-cpu", extra = "cpu" },
100
+ { index = "pytorch-cu126", extra = "cuda" },
101
+ { index = "pytorch-cu130", extra = "cuda-130" },
102
+ ]
103
+ torchvision = [
104
+ { index = "pytorch-cpu", extra = "cpu" },
105
+ { index = "pytorch-cu126", extra = "cuda" },
106
+ { index = "pytorch-cu130", extra = "cuda-130" },
107
+ ]
108
+ torchcodec = [
109
+ { index = "pytorch-cpu", extra = "cpu" },
110
+ { index = "pytorch-cu126", extra = "cuda" },
111
+ { index = "pytorch-cu130", extra = "cuda-130" },
112
+ ]
113
+
114
+ [[tool.uv.index]]
115
+ name = "pytorch-cpu"
116
+ url = "https://download.pytorch.org/whl/cpu"
117
+ explicit = true
118
+
119
+ [[tool.uv.index]]
120
+ name = "pytorch-cu126"
121
+ url = "https://download.pytorch.org/whl/cu126"
122
+ explicit = true
123
+
124
+ [[tool.uv.index]]
125
+ name = "pytorch-cu130"
126
+ url = "https://download.pytorch.org/whl/cu130"
127
+ explicit = true
128
+
129
+ [tool.uv.extra-build-dependencies]
130
+ flash-attn = [{ requirement = "torch", match-runtime = true }]
131
+ # causal-1dconv = [{ requirement = "torch", match-runtime = true }]
132
+ # flash-linear-attention = [{ requirement = "torch", match-runtime = true }]
133
+ # gptqmodel = [{ requirement = "torch", match-runtime = true }]
134
+
135
+ [tool.uv.extra-build-variables]
136
+ flash-attn = { FLASH_ATTENTION_SKIP_CUDA_BUILD = "TRUE" }
File without changes
@@ -0,0 +1,141 @@
1
+ import argparse
2
+ import os
3
+ from typing import get_args
4
+
5
+ from hf_serve.cli_utils import strtobool
6
+ from hf_serve.compatibility.backwards import ensure_backwards_compatibility
7
+ from hf_serve.server import launch
8
+ from hf_serve.types.task import TaskTypes
9
+
10
+ # NOTE: required in order for the actual values for the environment variables
11
+ # to be set before the defaults are provided to the `argparse` arguments
12
+ ensure_backwards_compatibility()
13
+
14
+ parser = argparse.ArgumentParser(description="Hugging Face Serve API")
15
+
16
+ parser.add_argument(
17
+ "--host",
18
+ type=str,
19
+ default=os.getenv("HOST", None) or "0.0.0.0",
20
+ required=False,
21
+ help="The host into which the FastAPI API will be deployed to, defaults to 0.0.0.0. It can also be set via the environment variable `HOST`.",
22
+ )
23
+
24
+ parser.add_argument(
25
+ "--port",
26
+ type=int,
27
+ default=os.getenv("PORT", None) or 8080,
28
+ required=False,
29
+ help="The port in which the FastAPI API will listen to, defaults to 8080. It can also be set via the environment variable `PORT`.",
30
+ )
31
+
32
+ # NOTE: only one of `--model-id` or `--model-dir` should be provided
33
+ parser.add_argument(
34
+ "--model-id",
35
+ type=str,
36
+ default=os.getenv("MODEL_ID", None),
37
+ help="The model ID on the Hugging Face Hub. It can also be set via the environment variable `MODEL_ID`.",
38
+ )
39
+
40
+ parser.add_argument(
41
+ "--model-dir",
42
+ type=str,
43
+ default=os.getenv("MODEL_DIR", None),
44
+ help="A local directory that contains a Hugging Face compatible model. It can also be set via the environment variable `MODEL_DIR`.",
45
+ )
46
+
47
+ parser.add_argument(
48
+ "--revision",
49
+ type=str,
50
+ default=os.getenv("REVISION", None) or None,
51
+ help="The revision of model on the Hugging Face Hub. It can also be set via the environment variable `REVISION`.",
52
+ )
53
+
54
+ parser.add_argument(
55
+ "--task",
56
+ type=str,
57
+ default=os.getenv("TASK", None),
58
+ choices=get_args(TaskTypes),
59
+ help="Any of the supported tasks for either Transformers, Diffusers, or Sentence Transformers. It can also be set via the environment variable `TASK`.",
60
+ )
61
+
62
+ parser.add_argument(
63
+ "--device",
64
+ type=str,
65
+ default=os.getenv("DEVICE", None) or "auto",
66
+ choices=["auto", "balanced", "cuda", "cpu", "mps"],
67
+ required=False,
68
+ help="The device on which the model weights will be loaded into, defaults to auto that selects an accelerator if available, otherwise it falls back to the CPU. It can also be set via the environment variable `DEVICE`.",
69
+ )
70
+
71
+ parser.add_argument(
72
+ "--dtype",
73
+ type=str,
74
+ # NOTE: This might seem weird, but if `DTYPE=""` then it won't be None,
75
+ # hence its value will be `""` but since we don't want that, we need to add
76
+ # the check `or None` to make sure that if `""` is set, then we default to
77
+ # `None`
78
+ default=os.getenv("DTYPE", None) or None,
79
+ choices=["float32", "float16", "bfloat16", "float8", "int8", "int4"],
80
+ required=False,
81
+ help="The PyTorch dtype in which the model weights will be loaded, defaults to None meaning that the default dtype for the given model will be used i.e., the dtype in which the model weights are available. It can also be set via the environment variable `DTYPE`.",
82
+ )
83
+
84
+ parser.add_argument(
85
+ "--trust-remote-code",
86
+ # TODO(alvarobartt): Eventually review this, as I'm not super happy with this line here
87
+ default=strtobool(os.getenv("TRUST_REMOTE_CODE", None)) or False,
88
+ action="store_true",
89
+ required=False,
90
+ help="Whether to trust remote code execution from the Hugging Face Hub, more information at https://huggingface.co/docs/transformers/v4.57.3/en/models#custom-models. Defaults to False, as it's not recommended unless required.",
91
+ )
92
+
93
+ # TODO(juanjucm): validate accepted_mimetypes values based on the task.
94
+ # Check processor's accepted file formats (e.g. ffmpeg for audio (https://www.ffmpeg.org/general.html#File-Formats))
95
+ parser.add_argument(
96
+ "--accepted-mimetypes",
97
+ type=str,
98
+ default=os.getenv("ACCEPTED_MIMETYPES", None) or None,
99
+ required=False,
100
+ help="A comma-separated list of accepted MIME types for file uploads. By default, each task will have all valid MIME types (e.g. audio/* for audio tasks, image/* for image tasks). It can also be set via the environment variable `ACCEPTED_MIMETYPES`.",
101
+ )
102
+
103
+ parser.add_argument(
104
+ "--max-file-size",
105
+ type=int,
106
+ # TODO: Maybe remove the `or None` and instead of checking that `if max_file_size is not None`
107
+ # we could just `if not max_file_size` (which handles `""`)
108
+ default=os.getenv("MAX_FILE_SIZE", None) or None,
109
+ required=False,
110
+ help="The maximum file size in bytes for file uploads (e.g 10485760 for 10MB). By default, no file size limit is considered. It can also be set via the environment variable `MAX_FILE_SIZE`.",
111
+ )
112
+
113
+ parser.add_argument(
114
+ "--cloud",
115
+ type=str,
116
+ default=os.getenv("CLOUD", None) or None,
117
+ choices=["azure", "google"],
118
+ required=False,
119
+ help="To be defined when deploying on a cloud provider to ensure that it's compatible with the provider expectations e.g. `/score` route needs to be exposed for Azure AI Foundry and Azure ML deployments (among others); or e.g. `instances` needs to be a list of inputs for Vertex AI (among others).",
120
+ )
121
+
122
+
123
+ def main() -> None:
124
+ args = parser.parse_args()
125
+
126
+ launch(
127
+ host=args.host,
128
+ port=args.port,
129
+ model_id=args.model_id,
130
+ model_dir=args.model_dir,
131
+ revision=args.revision,
132
+ task=args.task,
133
+ device=args.device,
134
+ dtype=args.dtype,
135
+ trust_remote_code=args.trust_remote_code,
136
+ # TODO(juanjucm): This can most likely be a list, and it will automatically be formatted this way
137
+ # without having to handle that here
138
+ accepted_mimetypes=args.accepted_mimetypes.split(",") if args.accepted_mimetypes else None,
139
+ max_file_size=args.max_file_size,
140
+ cloud=args.cloud,
141
+ )
@@ -0,0 +1,5 @@
1
+ from typing import Optional
2
+
3
+
4
+ def strtobool(value: Optional[str]) -> bool:
5
+ return True if value is not None and value.lower() in {"y", "yes", "t", "true", "on", "1"} else False
File without changes