Toy commited on
Commit
8608d22
·
1 Parent(s): 3d83bad

Add another tab for uploading an image to generate a new image

Browse files
Files changed (3) hide show
  1. app.py +121 -0
  2. pyproject.toml +1 -0
  3. uv.lock +91 -0
app.py CHANGED
@@ -4,6 +4,9 @@ from transformers import pipeline, CLIPProcessor, CLIPModel
4
  from simple_train import simple_train
5
  import glob
6
  from pathlib import Path
 
 
 
7
 
8
 
9
  MODEL_ID = os.getenv("MODEL_ID", "stabilityai/sdxl-turbo")
@@ -183,6 +186,103 @@ def load_trained_model(model_selection):
183
  else:
184
  return load_classifier("openai/clip-vit-base-patch32")
185
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  # ---------- UI ----------
187
  with gr.Blocks() as demo:
188
  gr.Markdown("# 🌸 SDXL-Turbo — Text → Image + Flower Identifier")
@@ -240,6 +340,20 @@ with gr.Blocks() as demo:
240
  gr.Markdown("### Training Status")
241
  training_output = gr.Markdown()
242
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  # Wire events
244
  go.click(generate, [prompt, steps, width, height, seed], [out])
245
  # Auto-send generated image to Identify tab
@@ -253,6 +367,13 @@ with gr.Blocks() as demo:
253
  load_model_btn.click(load_trained_model, inputs=[model_dropdown], outputs=[model_status])
254
  train_btn.click(start_training, inputs=[epochs, batch_size, learning_rate], outputs=[training_output])
255
 
 
 
 
 
 
 
 
256
  # Initialize data count on load
257
  demo.load(count_training_images, outputs=[data_status])
258
 
 
4
  from simple_train import simple_train
5
  import glob
6
  from pathlib import Path
7
+ from PIL import Image
8
+ import numpy as np
9
+ from sklearn.cluster import KMeans
10
 
11
 
12
  MODEL_ID = os.getenv("MODEL_ID", "stabilityai/sdxl-turbo")
 
186
  else:
187
  return load_classifier("openai/clip-vit-base-patch32")
188
 
189
+ # French-style arrangement functions
190
+ def extract_dominant_colors(image, num_colors=5):
191
+ """Extract dominant colors from an image using k-means clustering"""
192
+ if image is None:
193
+ return [], "No image provided"
194
+
195
+ # Convert PIL image to numpy array
196
+ img_array = np.array(image)
197
+
198
+ # Reshape image to be a list of pixels
199
+ pixels = img_array.reshape(-1, 3)
200
+
201
+ # Use k-means to find dominant colors
202
+ kmeans = KMeans(n_clusters=num_colors, random_state=42, n_init=10)
203
+ kmeans.fit(pixels)
204
+
205
+ # Get the colors and convert to RGB values
206
+ colors = kmeans.cluster_centers_.astype(int)
207
+
208
+ # Convert to color names/descriptions
209
+ color_names = []
210
+ for color in colors:
211
+ r, g, b = color
212
+ if r > 200 and g > 200 and b > 200:
213
+ color_names.append("white")
214
+ elif r < 50 and g < 50 and b < 50:
215
+ color_names.append("black")
216
+ elif r > g and r > b:
217
+ if r > 150 and g < 100:
218
+ color_names.append("red" if g < 50 else "pink")
219
+ else:
220
+ color_names.append("coral")
221
+ elif g > r and g > b:
222
+ if b < 100:
223
+ color_names.append("yellow" if g > 200 and r > 150 else "green")
224
+ else:
225
+ color_names.append("teal")
226
+ elif b > r and b > g:
227
+ if r < 100:
228
+ color_names.append("blue" if b > 150 else "navy")
229
+ else:
230
+ color_names.append("purple" if r > g else "lavender")
231
+ elif r > 150 and g > 100 and b < 100:
232
+ color_names.append("orange")
233
+ else:
234
+ color_names.append("cream")
235
+
236
+ return color_names, colors
237
+
238
+ def analyze_and_generate_french_style(image):
239
+ """Analyze uploaded flower image and generate French-style arrangement"""
240
+ if image is None:
241
+ return None, "Please upload an image", ""
242
+
243
+ # Identify the flower type
244
+ if zs_classifier is None:
245
+ return None, "Model not loaded", ""
246
+
247
+ try:
248
+ # Identify flower
249
+ results = zs_classifier(
250
+ image,
251
+ candidate_labels=FLOWER_LABELS,
252
+ hypothesis_template="a photo of a {}"
253
+ )
254
+
255
+ top_flower = results[0]["label"] if results else "flower"
256
+ confidence = results[0]["score"] if results else 0
257
+
258
+ # Extract dominant colors
259
+ color_names, color_rgb = extract_dominant_colors(image, num_colors=3)
260
+
261
+ # Create color description
262
+ main_colors = color_names[:3] # Top 3 colors
263
+ color_desc = ", ".join(main_colors)
264
+
265
+ # Generate French-style prompt
266
+ prompt = f"elegant French-style floral arrangement featuring {top_flower}s in {color_desc} colors, displayed in a clear crystal vase on a marble kitchen countertop, soft natural lighting, minimalist French country kitchen background, professional photography, sophisticated composition"
267
+
268
+ # Generate the image
269
+ generated_image = generate(prompt, steps=4, width=1024, height=1024, seed=-1)
270
+
271
+ # Create analysis summary
272
+ analysis = f"""
273
+ **🌸 Flower Analysis:**
274
+ - **Type:** {top_flower} (confidence: {confidence:.2%})
275
+ - **Dominant Colors:** {color_desc}
276
+
277
+ **🇫🇷 Generated Prompt:**
278
+ "{prompt}"
279
+ """
280
+
281
+ return generated_image, "✅ Analysis complete! French-style arrangement generated.", analysis
282
+
283
+ except Exception as e:
284
+ return None, f"❌ Error: {str(e)}", ""
285
+
286
  # ---------- UI ----------
287
  with gr.Blocks() as demo:
288
  gr.Markdown("# 🌸 SDXL-Turbo — Text → Image + Flower Identifier")
 
340
  gr.Markdown("### Training Status")
341
  training_output = gr.Markdown()
342
 
343
+ with gr.TabItem("French Style"):
344
+ gr.Markdown("## 🇫🇷 French-Style Flower Arrangements")
345
+ gr.Markdown("Upload a flower image and generate an elegant French-style arrangement with matching colors!")
346
+
347
+ with gr.Row():
348
+ with gr.Column():
349
+ upload_img = gr.Image(label="Upload Flower Image", type="pil")
350
+ analyze_btn = gr.Button("🎨 Analyze & Generate French Style", variant="primary", size="lg")
351
+
352
+ with gr.Column():
353
+ french_result = gr.Image(label="Generated French-Style Arrangement", type="pil")
354
+ french_status = gr.Markdown()
355
+ analysis_details = gr.Markdown()
356
+
357
  # Wire events
358
  go.click(generate, [prompt, steps, width, height, seed], [out])
359
  # Auto-send generated image to Identify tab
 
367
  load_model_btn.click(load_trained_model, inputs=[model_dropdown], outputs=[model_status])
368
  train_btn.click(start_training, inputs=[epochs, batch_size, learning_rate], outputs=[training_output])
369
 
370
+ # French Style tab events
371
+ analyze_btn.click(
372
+ analyze_and_generate_french_style,
373
+ inputs=[upload_img],
374
+ outputs=[french_result, french_status, analysis_details]
375
+ )
376
+
377
  # Initialize data count on load
378
  demo.load(count_training_images, outputs=[data_status])
379
 
pyproject.toml CHANGED
@@ -8,6 +8,7 @@ dependencies = [
8
  "diffusers>=0.35.1",
9
  "gradio>=5.44.0",
10
  "pillow>=11.3.0",
 
11
  "torch>=2.8.0",
12
  "torchvision>=0.23.0",
13
  "transformers[torch]>=4.55.4",
 
8
  "diffusers>=0.35.1",
9
  "gradio>=5.44.0",
10
  "pillow>=11.3.0",
11
+ "scikit-learn>=1.7.1",
12
  "torch>=2.8.0",
13
  "torchvision>=0.23.0",
14
  "transformers[torch]>=4.55.4",
uv.lock CHANGED
@@ -247,6 +247,7 @@ dependencies = [
247
  { name = "diffusers" },
248
  { name = "gradio" },
249
  { name = "pillow" },
 
250
  { name = "torch" },
251
  { name = "torchvision" },
252
  { name = "transformers", extra = ["torch"] },
@@ -257,6 +258,7 @@ requires-dist = [
257
  { name = "diffusers", specifier = ">=0.35.1" },
258
  { name = "gradio", specifier = ">=5.44.0" },
259
  { name = "pillow", specifier = ">=11.3.0" },
 
260
  { name = "torch", specifier = ">=2.8.0" },
261
  { name = "torchvision", specifier = ">=0.23.0" },
262
  { name = "transformers", extras = ["torch"], specifier = ">=4.55.4" },
@@ -442,6 +444,15 @@ wheels = [
442
  { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
443
  ]
444
 
 
 
 
 
 
 
 
 
 
445
  [[package]]
446
  name = "markdown-it-py"
447
  version = "4.0.0"
@@ -1059,6 +1070,77 @@ wheels = [
1059
  { url = "https://files.pythonhosted.org/packages/2c/c3/c0be1135726618dc1e28d181b8c442403d8dbb9e273fd791de2d4384bcdd/safetensors-0.6.2-cp38-abi3-win_amd64.whl", hash = "sha256:c7b214870df923cbc1593c3faee16bec59ea462758699bd3fee399d00aac072c", size = 320192, upload-time = "2025-08-08T13:13:59.467Z" },
1060
  ]
1061
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1062
  [[package]]
1063
  name = "semantic-version"
1064
  version = "2.10.0"
@@ -1128,6 +1210,15 @@ wheels = [
1128
  { url = "https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl", hash = "sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5", size = 6299353, upload-time = "2025-04-27T18:04:59.103Z" },
1129
  ]
1130
 
 
 
 
 
 
 
 
 
 
1131
  [[package]]
1132
  name = "tokenizers"
1133
  version = "0.21.4"
 
247
  { name = "diffusers" },
248
  { name = "gradio" },
249
  { name = "pillow" },
250
+ { name = "scikit-learn" },
251
  { name = "torch" },
252
  { name = "torchvision" },
253
  { name = "transformers", extra = ["torch"] },
 
258
  { name = "diffusers", specifier = ">=0.35.1" },
259
  { name = "gradio", specifier = ">=5.44.0" },
260
  { name = "pillow", specifier = ">=11.3.0" },
261
+ { name = "scikit-learn", specifier = ">=1.7.1" },
262
  { name = "torch", specifier = ">=2.8.0" },
263
  { name = "torchvision", specifier = ">=0.23.0" },
264
  { name = "transformers", extras = ["torch"], specifier = ">=4.55.4" },
 
444
  { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
445
  ]
446
 
447
+ [[package]]
448
+ name = "joblib"
449
+ version = "1.5.1"
450
+ source = { registry = "https://pypi.org/simple" }
451
+ sdist = { url = "https://files.pythonhosted.org/packages/dc/fe/0f5a938c54105553436dbff7a61dc4fed4b1b2c98852f8833beaf4d5968f/joblib-1.5.1.tar.gz", hash = "sha256:f4f86e351f39fe3d0d32a9f2c3d8af1ee4cec285aafcb27003dda5205576b444", size = 330475, upload-time = "2025-05-23T12:04:37.097Z" }
452
+ wheels = [
453
+ { url = "https://files.pythonhosted.org/packages/7d/4f/1195bbac8e0c2acc5f740661631d8d750dc38d4a32b23ee5df3cde6f4e0d/joblib-1.5.1-py3-none-any.whl", hash = "sha256:4719a31f054c7d766948dcd83e9613686b27114f190f717cec7eaa2084f8a74a", size = 307746, upload-time = "2025-05-23T12:04:35.124Z" },
454
+ ]
455
+
456
  [[package]]
457
  name = "markdown-it-py"
458
  version = "4.0.0"
 
1070
  { url = "https://files.pythonhosted.org/packages/2c/c3/c0be1135726618dc1e28d181b8c442403d8dbb9e273fd791de2d4384bcdd/safetensors-0.6.2-cp38-abi3-win_amd64.whl", hash = "sha256:c7b214870df923cbc1593c3faee16bec59ea462758699bd3fee399d00aac072c", size = 320192, upload-time = "2025-08-08T13:13:59.467Z" },
1071
  ]
1072
 
1073
+ [[package]]
1074
+ name = "scikit-learn"
1075
+ version = "1.7.1"
1076
+ source = { registry = "https://pypi.org/simple" }
1077
+ dependencies = [
1078
+ { name = "joblib" },
1079
+ { name = "numpy" },
1080
+ { name = "scipy" },
1081
+ { name = "threadpoolctl" },
1082
+ ]
1083
+ sdist = { url = "https://files.pythonhosted.org/packages/41/84/5f4af978fff619706b8961accac84780a6d298d82a8873446f72edb4ead0/scikit_learn-1.7.1.tar.gz", hash = "sha256:24b3f1e976a4665aa74ee0fcaac2b8fccc6ae77c8e07ab25da3ba6d3292b9802", size = 7190445, upload-time = "2025-07-18T08:01:54.5Z" }
1084
+ wheels = [
1085
+ { url = "https://files.pythonhosted.org/packages/52/f8/e0533303f318a0f37b88300d21f79b6ac067188d4824f1047a37214ab718/scikit_learn-1.7.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b7839687fa46d02e01035ad775982f2470be2668e13ddd151f0f55a5bf123bae", size = 9213143, upload-time = "2025-07-18T08:01:32.942Z" },
1086
+ { url = "https://files.pythonhosted.org/packages/71/f3/f1df377d1bdfc3e3e2adc9c119c238b182293e6740df4cbeac6de2cc3e23/scikit_learn-1.7.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:a10f276639195a96c86aa572ee0698ad64ee939a7b042060b98bd1930c261d10", size = 8591977, upload-time = "2025-07-18T08:01:34.967Z" },
1087
+ { url = "https://files.pythonhosted.org/packages/99/72/c86a4cd867816350fe8dee13f30222340b9cd6b96173955819a5561810c5/scikit_learn-1.7.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:13679981fdaebc10cc4c13c43344416a86fcbc61449cb3e6517e1df9d12c8309", size = 9436142, upload-time = "2025-07-18T08:01:37.397Z" },
1088
+ { url = "https://files.pythonhosted.org/packages/e8/66/277967b29bd297538dc7a6ecfb1a7dce751beabd0d7f7a2233be7a4f7832/scikit_learn-1.7.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4f1262883c6a63f067a980a8cdd2d2e7f2513dddcef6a9eaada6416a7a7cbe43", size = 9282996, upload-time = "2025-07-18T08:01:39.721Z" },
1089
+ { url = "https://files.pythonhosted.org/packages/e2/47/9291cfa1db1dae9880420d1e07dbc7e8dd4a7cdbc42eaba22512e6bde958/scikit_learn-1.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:ca6d31fb10e04d50bfd2b50d66744729dbb512d4efd0223b864e2fdbfc4cee11", size = 8707418, upload-time = "2025-07-18T08:01:42.124Z" },
1090
+ { url = "https://files.pythonhosted.org/packages/61/95/45726819beccdaa34d3362ea9b2ff9f2b5d3b8bf721bd632675870308ceb/scikit_learn-1.7.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:781674d096303cfe3d351ae6963ff7c958db61cde3421cd490e3a5a58f2a94ae", size = 9561466, upload-time = "2025-07-18T08:01:44.195Z" },
1091
+ { url = "https://files.pythonhosted.org/packages/ee/1c/6f4b3344805de783d20a51eb24d4c9ad4b11a7f75c1801e6ec6d777361fd/scikit_learn-1.7.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:10679f7f125fe7ecd5fad37dd1aa2daae7e3ad8df7f3eefa08901b8254b3e12c", size = 9040467, upload-time = "2025-07-18T08:01:46.671Z" },
1092
+ { url = "https://files.pythonhosted.org/packages/6f/80/abe18fe471af9f1d181904203d62697998b27d9b62124cd281d740ded2f9/scikit_learn-1.7.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1f812729e38c8cb37f760dce71a9b83ccfb04f59b3dca7c6079dcdc60544fa9e", size = 9532052, upload-time = "2025-07-18T08:01:48.676Z" },
1093
+ { url = "https://files.pythonhosted.org/packages/14/82/b21aa1e0c4cee7e74864d3a5a721ab8fcae5ca55033cb6263dca297ed35b/scikit_learn-1.7.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:88e1a20131cf741b84b89567e1717f27a2ced228e0f29103426102bc2e3b8ef7", size = 9361575, upload-time = "2025-07-18T08:01:50.639Z" },
1094
+ { url = "https://files.pythonhosted.org/packages/f2/20/f4777fcd5627dc6695fa6b92179d0edb7a3ac1b91bcd9a1c7f64fa7ade23/scikit_learn-1.7.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b1bd1d919210b6a10b7554b717c9000b5485aa95a1d0f177ae0d7ee8ec750da5", size = 9277310, upload-time = "2025-07-18T08:01:52.547Z" },
1095
+ ]
1096
+
1097
+ [[package]]
1098
+ name = "scipy"
1099
+ version = "1.16.1"
1100
+ source = { registry = "https://pypi.org/simple" }
1101
+ dependencies = [
1102
+ { name = "numpy" },
1103
+ ]
1104
+ sdist = { url = "https://files.pythonhosted.org/packages/f5/4a/b927028464795439faec8eaf0b03b011005c487bb2d07409f28bf30879c4/scipy-1.16.1.tar.gz", hash = "sha256:44c76f9e8b6e8e488a586190ab38016e4ed2f8a038af7cd3defa903c0a2238b3", size = 30580861, upload-time = "2025-07-27T16:33:30.834Z" }
1105
+ wheels = [
1106
+ { url = "https://files.pythonhosted.org/packages/93/0b/b5c99382b839854a71ca9482c684e3472badc62620287cbbdab499b75ce6/scipy-1.16.1-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:5451606823a5e73dfa621a89948096c6528e2896e40b39248295d3a0138d594f", size = 36533717, upload-time = "2025-07-27T16:28:51.706Z" },
1107
+ { url = "https://files.pythonhosted.org/packages/eb/e5/69ab2771062c91e23e07c12e7d5033a6b9b80b0903ee709c3c36b3eb520c/scipy-1.16.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:89728678c5ca5abd610aee148c199ac1afb16e19844401ca97d43dc548a354eb", size = 28570009, upload-time = "2025-07-27T16:28:57.017Z" },
1108
+ { url = "https://files.pythonhosted.org/packages/f4/69/bd75dbfdd3cf524f4d753484d723594aed62cfaac510123e91a6686d520b/scipy-1.16.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e756d688cb03fd07de0fffad475649b03cb89bee696c98ce508b17c11a03f95c", size = 20841942, upload-time = "2025-07-27T16:29:01.152Z" },
1109
+ { url = "https://files.pythonhosted.org/packages/ea/74/add181c87663f178ba7d6144b370243a87af8476664d5435e57d599e6874/scipy-1.16.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:5aa2687b9935da3ed89c5dbed5234576589dd28d0bf7cd237501ccfbdf1ad608", size = 23498507, upload-time = "2025-07-27T16:29:05.202Z" },
1110
+ { url = "https://files.pythonhosted.org/packages/1d/74/ece2e582a0d9550cee33e2e416cc96737dce423a994d12bbe59716f47ff1/scipy-1.16.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0851f6a1e537fe9399f35986897e395a1aa61c574b178c0d456be5b1a0f5ca1f", size = 33286040, upload-time = "2025-07-27T16:29:10.201Z" },
1111
+ { url = "https://files.pythonhosted.org/packages/e4/82/08e4076df538fb56caa1d489588d880ec7c52d8273a606bb54d660528f7c/scipy-1.16.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fedc2cbd1baed37474b1924c331b97bdff611d762c196fac1a9b71e67b813b1b", size = 35176096, upload-time = "2025-07-27T16:29:17.091Z" },
1112
+ { url = "https://files.pythonhosted.org/packages/fa/79/cd710aab8c921375711a8321c6be696e705a120e3011a643efbbcdeeabcc/scipy-1.16.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2ef500e72f9623a6735769e4b93e9dcb158d40752cdbb077f305487e3e2d1f45", size = 35490328, upload-time = "2025-07-27T16:29:22.928Z" },
1113
+ { url = "https://files.pythonhosted.org/packages/71/73/e9cc3d35ee4526d784520d4494a3e1ca969b071fb5ae5910c036a375ceec/scipy-1.16.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:978d8311674b05a8f7ff2ea6c6bce5d8b45a0cb09d4c5793e0318f448613ea65", size = 37939921, upload-time = "2025-07-27T16:29:29.108Z" },
1114
+ { url = "https://files.pythonhosted.org/packages/21/12/c0efd2941f01940119b5305c375ae5c0fcb7ec193f806bd8f158b73a1782/scipy-1.16.1-cp313-cp313-win_amd64.whl", hash = "sha256:81929ed0fa7a5713fcdd8b2e6f73697d3b4c4816d090dd34ff937c20fa90e8ab", size = 38479462, upload-time = "2025-07-27T16:30:24.078Z" },
1115
+ { url = "https://files.pythonhosted.org/packages/7a/19/c3d08b675260046a991040e1ea5d65f91f40c7df1045fffff412dcfc6765/scipy-1.16.1-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:bcc12db731858abda693cecdb3bdc9e6d4bd200213f49d224fe22df82687bdd6", size = 36938832, upload-time = "2025-07-27T16:29:35.057Z" },
1116
+ { url = "https://files.pythonhosted.org/packages/81/f2/ce53db652c033a414a5b34598dba6b95f3d38153a2417c5a3883da429029/scipy-1.16.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:744d977daa4becb9fc59135e75c069f8d301a87d64f88f1e602a9ecf51e77b27", size = 29093084, upload-time = "2025-07-27T16:29:40.201Z" },
1117
+ { url = "https://files.pythonhosted.org/packages/a9/ae/7a10ff04a7dc15f9057d05b33737ade244e4bd195caa3f7cc04d77b9e214/scipy-1.16.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:dc54f76ac18073bcecffb98d93f03ed6b81a92ef91b5d3b135dcc81d55a724c7", size = 21365098, upload-time = "2025-07-27T16:29:44.295Z" },
1118
+ { url = "https://files.pythonhosted.org/packages/36/ac/029ff710959932ad3c2a98721b20b405f05f752f07344622fd61a47c5197/scipy-1.16.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:367d567ee9fc1e9e2047d31f39d9d6a7a04e0710c86e701e053f237d14a9b4f6", size = 23896858, upload-time = "2025-07-27T16:29:48.784Z" },
1119
+ { url = "https://files.pythonhosted.org/packages/71/13/d1ef77b6bd7898720e1f0b6b3743cb945f6c3cafa7718eaac8841035ab60/scipy-1.16.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4cf5785e44e19dcd32a0e4807555e1e9a9b8d475c6afff3d21c3c543a6aa84f4", size = 33438311, upload-time = "2025-07-27T16:29:54.164Z" },
1120
+ { url = "https://files.pythonhosted.org/packages/2d/e0/e64a6821ffbb00b4c5b05169f1c1fddb4800e9307efe3db3788995a82a2c/scipy-1.16.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3d0b80fb26d3e13a794c71d4b837e2a589d839fd574a6bbb4ee1288c213ad4a3", size = 35279542, upload-time = "2025-07-27T16:30:00.249Z" },
1121
+ { url = "https://files.pythonhosted.org/packages/57/59/0dc3c8b43e118f1e4ee2b798dcc96ac21bb20014e5f1f7a8e85cc0653bdb/scipy-1.16.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8503517c44c18d1030d666cb70aaac1cc8913608816e06742498833b128488b7", size = 35667665, upload-time = "2025-07-27T16:30:05.916Z" },
1122
+ { url = "https://files.pythonhosted.org/packages/45/5f/844ee26e34e2f3f9f8febb9343748e72daeaec64fe0c70e9bf1ff84ec955/scipy-1.16.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:30cc4bb81c41831ecfd6dc450baf48ffd80ef5aed0f5cf3ea775740e80f16ecc", size = 38045210, upload-time = "2025-07-27T16:30:11.655Z" },
1123
+ { url = "https://files.pythonhosted.org/packages/8d/d7/210f2b45290f444f1de64bc7353aa598ece9f0e90c384b4a156f9b1a5063/scipy-1.16.1-cp313-cp313t-win_amd64.whl", hash = "sha256:c24fa02f7ed23ae514460a22c57eca8f530dbfa50b1cfdbf4f37c05b5309cc39", size = 38593661, upload-time = "2025-07-27T16:30:17.825Z" },
1124
+ { url = "https://files.pythonhosted.org/packages/81/ea/84d481a5237ed223bd3d32d6e82d7a6a96e34756492666c260cef16011d1/scipy-1.16.1-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:796a5a9ad36fa3a782375db8f4241ab02a091308eb079746bc0f874c9b998318", size = 36525921, upload-time = "2025-07-27T16:30:30.081Z" },
1125
+ { url = "https://files.pythonhosted.org/packages/4e/9f/d9edbdeff9f3a664807ae3aea383e10afaa247e8e6255e6d2aa4515e8863/scipy-1.16.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:3ea0733a2ff73fd6fdc5fecca54ee9b459f4d74f00b99aced7d9a3adb43fb1cc", size = 28564152, upload-time = "2025-07-27T16:30:35.336Z" },
1126
+ { url = "https://files.pythonhosted.org/packages/3b/95/8125bcb1fe04bc267d103e76516243e8d5e11229e6b306bda1024a5423d1/scipy-1.16.1-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:85764fb15a2ad994e708258bb4ed8290d1305c62a4e1ef07c414356a24fcfbf8", size = 20836028, upload-time = "2025-07-27T16:30:39.421Z" },
1127
+ { url = "https://files.pythonhosted.org/packages/77/9c/bf92e215701fc70bbcd3d14d86337cf56a9b912a804b9c776a269524a9e9/scipy-1.16.1-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:ca66d980469cb623b1759bdd6e9fd97d4e33a9fad5b33771ced24d0cb24df67e", size = 23489666, upload-time = "2025-07-27T16:30:43.663Z" },
1128
+ { url = "https://files.pythonhosted.org/packages/5e/00/5e941d397d9adac41b02839011594620d54d99488d1be5be755c00cde9ee/scipy-1.16.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e7cc1ffcc230f568549fc56670bcf3df1884c30bd652c5da8138199c8c76dae0", size = 33358318, upload-time = "2025-07-27T16:30:48.982Z" },
1129
+ { url = "https://files.pythonhosted.org/packages/0e/87/8db3aa10dde6e3e8e7eb0133f24baa011377d543f5b19c71469cf2648026/scipy-1.16.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3ddfb1e8d0b540cb4ee9c53fc3dea3186f97711248fb94b4142a1b27178d8b4b", size = 35185724, upload-time = "2025-07-27T16:30:54.26Z" },
1130
+ { url = "https://files.pythonhosted.org/packages/89/b4/6ab9ae443216807622bcff02690262d8184078ea467efee2f8c93288a3b1/scipy-1.16.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4dc0e7be79e95d8ba3435d193e0d8ce372f47f774cffd882f88ea4e1e1ddc731", size = 35554335, upload-time = "2025-07-27T16:30:59.765Z" },
1131
+ { url = "https://files.pythonhosted.org/packages/9c/9a/d0e9dc03c5269a1afb60661118296a32ed5d2c24298af61b676c11e05e56/scipy-1.16.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f23634f9e5adb51b2a77766dac217063e764337fbc816aa8ad9aaebcd4397fd3", size = 37960310, upload-time = "2025-07-27T16:31:06.151Z" },
1132
+ { url = "https://files.pythonhosted.org/packages/5e/00/c8f3130a50521a7977874817ca89e0599b1b4ee8e938bad8ae798a0e1f0d/scipy-1.16.1-cp314-cp314-win_amd64.whl", hash = "sha256:57d75524cb1c5a374958a2eae3d84e1929bb971204cc9d52213fb8589183fc19", size = 39319239, upload-time = "2025-07-27T16:31:59.942Z" },
1133
+ { url = "https://files.pythonhosted.org/packages/f2/f2/1ca3eda54c3a7e4c92f6acef7db7b3a057deb135540d23aa6343ef8ad333/scipy-1.16.1-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:d8da7c3dd67bcd93f15618938f43ed0995982eb38973023d46d4646c4283ad65", size = 36939460, upload-time = "2025-07-27T16:31:11.865Z" },
1134
+ { url = "https://files.pythonhosted.org/packages/80/30/98c2840b293a132400c0940bb9e140171dcb8189588619048f42b2ce7b4f/scipy-1.16.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:cc1d2f2fd48ba1e0620554fe5bc44d3e8f5d4185c8c109c7fbdf5af2792cfad2", size = 29093322, upload-time = "2025-07-27T16:31:17.045Z" },
1135
+ { url = "https://files.pythonhosted.org/packages/c1/e6/1e6e006e850622cf2a039b62d1a6ddc4497d4851e58b68008526f04a9a00/scipy-1.16.1-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:21a611ced9275cb861bacadbada0b8c0623bc00b05b09eb97f23b370fc2ae56d", size = 21365329, upload-time = "2025-07-27T16:31:21.188Z" },
1136
+ { url = "https://files.pythonhosted.org/packages/8e/02/72a5aa5b820589dda9a25e329ca752842bfbbaf635e36bc7065a9b42216e/scipy-1.16.1-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:8dfbb25dffc4c3dd9371d8ab456ca81beeaf6f9e1c2119f179392f0dc1ab7695", size = 23897544, upload-time = "2025-07-27T16:31:25.408Z" },
1137
+ { url = "https://files.pythonhosted.org/packages/2b/dc/7122d806a6f9eb8a33532982234bed91f90272e990f414f2830cfe656e0b/scipy-1.16.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f0ebb7204f063fad87fc0a0e4ff4a2ff40b2a226e4ba1b7e34bf4b79bf97cd86", size = 33442112, upload-time = "2025-07-27T16:31:30.62Z" },
1138
+ { url = "https://files.pythonhosted.org/packages/24/39/e383af23564daa1021a5b3afbe0d8d6a68ec639b943661841f44ac92de85/scipy-1.16.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f1b9e5962656f2734c2b285a8745358ecb4e4efbadd00208c80a389227ec61ff", size = 35286594, upload-time = "2025-07-27T16:31:36.112Z" },
1139
+ { url = "https://files.pythonhosted.org/packages/95/47/1a0b0aff40c3056d955f38b0df5d178350c3d74734ec54f9c68d23910be5/scipy-1.16.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e1a106f8c023d57a2a903e771228bf5c5b27b5d692088f457acacd3b54511e4", size = 35665080, upload-time = "2025-07-27T16:31:42.025Z" },
1140
+ { url = "https://files.pythonhosted.org/packages/64/df/ce88803e9ed6e27fe9b9abefa157cf2c80e4fa527cf17ee14be41f790ad4/scipy-1.16.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:709559a1db68a9abc3b2c8672c4badf1614f3b440b3ab326d86a5c0491eafae3", size = 38050306, upload-time = "2025-07-27T16:31:48.109Z" },
1141
+ { url = "https://files.pythonhosted.org/packages/6e/6c/a76329897a7cae4937d403e623aa6aaea616a0bb5b36588f0b9d1c9a3739/scipy-1.16.1-cp314-cp314t-win_amd64.whl", hash = "sha256:c0c804d60492a0aad7f5b2bb1862f4548b990049e27e828391ff2bf6f7199998", size = 39427705, upload-time = "2025-07-27T16:31:53.96Z" },
1142
+ ]
1143
+
1144
  [[package]]
1145
  name = "semantic-version"
1146
  version = "2.10.0"
 
1210
  { url = "https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl", hash = "sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5", size = 6299353, upload-time = "2025-04-27T18:04:59.103Z" },
1211
  ]
1212
 
1213
+ [[package]]
1214
+ name = "threadpoolctl"
1215
+ version = "3.6.0"
1216
+ source = { registry = "https://pypi.org/simple" }
1217
+ sdist = { url = "https://files.pythonhosted.org/packages/b7/4d/08c89e34946fce2aec4fbb45c9016efd5f4d7f24af8e5d93296e935631d8/threadpoolctl-3.6.0.tar.gz", hash = "sha256:8ab8b4aa3491d812b623328249fab5302a68d2d71745c8a4c719a2fcaba9f44e", size = 21274, upload-time = "2025-03-13T13:49:23.031Z" }
1218
+ wheels = [
1219
+ { url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" },
1220
+ ]
1221
+
1222
  [[package]]
1223
  name = "tokenizers"
1224
  version = "0.21.4"