nexaai 1.0.4rc13__cp310-cp310-win_amd64.whl → 1.0.4rc15__cp310-cp310-win_amd64.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 nexaai might be problematic. Click here for more details.
- nexaai/_stub.cp310-win_amd64.pyd +0 -0
- nexaai/_version.py +1 -1
- nexaai/binds/common_bind.cp310-win_amd64.pyd +0 -0
- nexaai/binds/embedder_bind.cp310-win_amd64.pyd +0 -0
- nexaai/binds/llm_bind.cp310-win_amd64.pyd +0 -0
- nexaai/binds/nexa_bridge.dll +0 -0
- nexaai/binds/nexa_llama_cpp/ggml-base.dll +0 -0
- nexaai/binds/nexa_llama_cpp/ggml-cpu.dll +0 -0
- nexaai/binds/nexa_llama_cpp/ggml-cuda.dll +0 -0
- nexaai/binds/nexa_llama_cpp/ggml-vulkan.dll +0 -0
- nexaai/binds/nexa_llama_cpp/ggml.dll +0 -0
- nexaai/binds/nexa_llama_cpp/llama.dll +0 -0
- nexaai/binds/nexa_llama_cpp/mtmd.dll +0 -0
- nexaai/binds/nexa_llama_cpp/nexa_plugin.dll +0 -0
- nexaai/cv.py +1 -0
- nexaai/utils/progress_tracker.py +21 -12
- nexaai/vlm_impl/mlx_vlm_impl.py +82 -38
- {nexaai-1.0.4rc13.dist-info → nexaai-1.0.4rc15.dist-info}/METADATA +9 -8
- {nexaai-1.0.4rc13.dist-info → nexaai-1.0.4rc15.dist-info}/RECORD +21 -21
- {nexaai-1.0.4rc13.dist-info → nexaai-1.0.4rc15.dist-info}/WHEEL +0 -0
- {nexaai-1.0.4rc13.dist-info → nexaai-1.0.4rc15.dist-info}/top_level.txt +0 -0
nexaai/_stub.cp310-win_amd64.pyd
CHANGED
|
Binary file
|
nexaai/_version.py
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
nexaai/binds/nexa_bridge.dll
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
nexaai/cv.py
CHANGED
nexaai/utils/progress_tracker.py
CHANGED
|
@@ -62,8 +62,8 @@ class DownloadProgressTracker:
|
|
|
62
62
|
self.last_display_length = 0
|
|
63
63
|
|
|
64
64
|
# Speed tracking
|
|
65
|
-
self.last_downloaded =
|
|
66
|
-
self.last_time = time
|
|
65
|
+
self.last_downloaded = None # Use None to indicate no previous measurement
|
|
66
|
+
self.last_time = None # Use None to indicate no previous time measurement
|
|
67
67
|
self.speed_history = []
|
|
68
68
|
self.max_speed_history = 10
|
|
69
69
|
|
|
@@ -101,18 +101,27 @@ class DownloadProgressTracker:
|
|
|
101
101
|
def calculate_speed(self, current_downloaded: int) -> float:
|
|
102
102
|
"""Calculate download speed in bytes per second."""
|
|
103
103
|
current_time = time.time()
|
|
104
|
-
time_diff = current_time - self.last_time
|
|
105
104
|
|
|
106
|
-
if
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
# Add to speed history for smoothing
|
|
111
|
-
self.speed_history.append(speed)
|
|
112
|
-
if len(self.speed_history) > self.max_speed_history:
|
|
113
|
-
self.speed_history.pop(0)
|
|
105
|
+
# Check if we have a previous measurement to compare against
|
|
106
|
+
if self.last_time is not None and self.last_downloaded is not None:
|
|
107
|
+
time_diff = current_time - self.last_time
|
|
114
108
|
|
|
115
|
-
#
|
|
109
|
+
# Only calculate if we have a meaningful time difference (avoid division by very small numbers)
|
|
110
|
+
if time_diff > 0.5: # At least 500ms between measurements
|
|
111
|
+
bytes_diff = current_downloaded - self.last_downloaded
|
|
112
|
+
|
|
113
|
+
# Only calculate speed if bytes actually changed
|
|
114
|
+
if bytes_diff >= 0: # Allow 0 for periods with no progress
|
|
115
|
+
speed = bytes_diff / time_diff
|
|
116
|
+
|
|
117
|
+
# Add to speed history for smoothing
|
|
118
|
+
self.speed_history.append(speed)
|
|
119
|
+
if len(self.speed_history) > self.max_speed_history:
|
|
120
|
+
self.speed_history.pop(0)
|
|
121
|
+
|
|
122
|
+
# Return the average of historical speeds if we have any
|
|
123
|
+
# This ensures we show the last known speed even when skipping updates
|
|
124
|
+
if self.speed_history:
|
|
116
125
|
return sum(self.speed_history) / len(self.speed_history)
|
|
117
126
|
|
|
118
127
|
return 0.0
|
nexaai/vlm_impl/mlx_vlm_impl.py
CHANGED
|
@@ -76,8 +76,10 @@ class MlxVlmImpl(VLM):
|
|
|
76
76
|
raise RuntimeError("MLX VLM not loaded")
|
|
77
77
|
|
|
78
78
|
try:
|
|
79
|
-
# Convert MultiModalMessage to MLX format
|
|
80
79
|
mlx_messages = []
|
|
80
|
+
total_images = 0
|
|
81
|
+
total_audios = 0
|
|
82
|
+
|
|
81
83
|
for msg in messages:
|
|
82
84
|
# Create a simple object with role and content attributes
|
|
83
85
|
class MLXChatMessage:
|
|
@@ -85,19 +87,38 @@ class MlxVlmImpl(VLM):
|
|
|
85
87
|
self.role = role
|
|
86
88
|
self.content = content
|
|
87
89
|
|
|
88
|
-
#
|
|
89
|
-
# This is a simplified approach - the actual implementation may need
|
|
90
|
-
# more sophisticated handling of different content types
|
|
90
|
+
# Extract text content and count media files
|
|
91
91
|
text_content = ""
|
|
92
|
+
first_content = True
|
|
93
|
+
|
|
92
94
|
for content_item in msg["content"]:
|
|
93
|
-
|
|
95
|
+
content_type = content_item.get("type", "")
|
|
96
|
+
|
|
97
|
+
if content_type == "text":
|
|
98
|
+
if not first_content:
|
|
99
|
+
text_content += " "
|
|
94
100
|
text_content += content_item.get("text", "")
|
|
95
|
-
|
|
96
|
-
|
|
101
|
+
first_content = False
|
|
102
|
+
elif content_type == "image":
|
|
103
|
+
total_images += 1
|
|
104
|
+
elif content_type == "audio":
|
|
105
|
+
total_audios += 1
|
|
97
106
|
|
|
98
107
|
mlx_messages.append(MLXChatMessage(msg["role"], text_content))
|
|
99
108
|
|
|
100
|
-
|
|
109
|
+
if total_images > 0 or total_audios > 0:
|
|
110
|
+
# Use apply_chat_template_with_media when media is present
|
|
111
|
+
return self._mlx_vlm.apply_chat_template_with_media(
|
|
112
|
+
mlx_messages,
|
|
113
|
+
num_images=total_images,
|
|
114
|
+
num_audios=total_audios,
|
|
115
|
+
tools=tools,
|
|
116
|
+
enable_thinking=False # Default to False, could be made configurable
|
|
117
|
+
)
|
|
118
|
+
else:
|
|
119
|
+
# Use regular apply_chat_template for text-only messages
|
|
120
|
+
return self._mlx_vlm.apply_chat_template(mlx_messages)
|
|
121
|
+
|
|
101
122
|
except Exception as e:
|
|
102
123
|
raise RuntimeError(f"Failed to apply chat template: {str(e)}")
|
|
103
124
|
|
|
@@ -107,9 +128,6 @@ class MlxVlmImpl(VLM):
|
|
|
107
128
|
raise RuntimeError("MLX VLM not loaded")
|
|
108
129
|
|
|
109
130
|
try:
|
|
110
|
-
# Get MLX config classes
|
|
111
|
-
_, MLXSamplerConfig, MLXGenerationConfig, _ = get_mlx_configs()
|
|
112
|
-
|
|
113
131
|
# Convert GenerationConfig to MLX format
|
|
114
132
|
mlx_gen_config = MLXGenerationConfig()
|
|
115
133
|
mlx_gen_config.max_tokens = g_cfg.max_tokens
|
|
@@ -130,25 +148,57 @@ class MlxVlmImpl(VLM):
|
|
|
130
148
|
mlx_sampler_config.grammar_string = g_cfg.sampler_config.grammar_string
|
|
131
149
|
mlx_gen_config.sampler_config = mlx_sampler_config
|
|
132
150
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
151
|
+
import queue
|
|
152
|
+
import threading
|
|
153
|
+
|
|
154
|
+
# Create a queue for streaming tokens
|
|
155
|
+
token_queue = queue.Queue()
|
|
156
|
+
exception_container = [None]
|
|
157
|
+
self.reset_cancel() # Reset cancel flag before generation
|
|
137
158
|
|
|
138
|
-
|
|
139
|
-
|
|
159
|
+
def token_callback(token: str, user_data: Any = None) -> bool:
|
|
160
|
+
if self._cancel_event.is_set():
|
|
161
|
+
token_queue.put(('end', None))
|
|
162
|
+
return False
|
|
163
|
+
try:
|
|
164
|
+
token_queue.put(('token', token))
|
|
165
|
+
return True
|
|
166
|
+
except Exception as e:
|
|
167
|
+
exception_container[0] = e
|
|
168
|
+
return False
|
|
140
169
|
|
|
141
|
-
#
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
170
|
+
# Run generation in a separate thread
|
|
171
|
+
def generate():
|
|
172
|
+
try:
|
|
173
|
+
self._mlx_vlm.generate_stream(prompt, mlx_gen_config, token_callback)
|
|
174
|
+
except Exception as e:
|
|
175
|
+
exception_container[0] = e
|
|
176
|
+
finally:
|
|
177
|
+
token_queue.put(('end', None))
|
|
178
|
+
|
|
179
|
+
thread = threading.Thread(target=generate)
|
|
180
|
+
thread.start()
|
|
181
|
+
|
|
182
|
+
# Yield tokens as they come from the queue
|
|
183
|
+
while True:
|
|
184
|
+
if exception_container[0]:
|
|
185
|
+
raise exception_container[0]
|
|
186
|
+
|
|
187
|
+
try:
|
|
188
|
+
msg_type, token = token_queue.get(timeout=0.1)
|
|
189
|
+
if msg_type == 'end':
|
|
147
190
|
break
|
|
148
|
-
|
|
149
|
-
yield
|
|
150
|
-
|
|
151
|
-
|
|
191
|
+
elif msg_type == 'token':
|
|
192
|
+
yield token
|
|
193
|
+
except queue.Empty:
|
|
194
|
+
if not thread.is_alive():
|
|
195
|
+
break
|
|
196
|
+
continue
|
|
197
|
+
|
|
198
|
+
thread.join()
|
|
199
|
+
|
|
200
|
+
if exception_container[0]:
|
|
201
|
+
raise exception_container[0]
|
|
152
202
|
|
|
153
203
|
except Exception as e:
|
|
154
204
|
raise RuntimeError(f"Failed to generate streaming text: {str(e)}")
|
|
@@ -168,9 +218,6 @@ class MlxVlmImpl(VLM):
|
|
|
168
218
|
raise RuntimeError("MLX VLM not loaded")
|
|
169
219
|
|
|
170
220
|
try:
|
|
171
|
-
# Get MLX config classes
|
|
172
|
-
_, MLXSamplerConfig, MLXGenerationConfig, _ = get_mlx_configs()
|
|
173
|
-
|
|
174
221
|
# Convert GenerationConfig to MLX format
|
|
175
222
|
mlx_gen_config = MLXGenerationConfig()
|
|
176
223
|
mlx_gen_config.max_tokens = g_cfg.max_tokens
|
|
@@ -191,15 +238,12 @@ class MlxVlmImpl(VLM):
|
|
|
191
238
|
mlx_sampler_config.grammar_string = g_cfg.sampler_config.grammar_string
|
|
192
239
|
mlx_gen_config.sampler_config = mlx_sampler_config
|
|
193
240
|
|
|
194
|
-
#
|
|
195
|
-
|
|
241
|
+
# Simple token callback that just continues
|
|
242
|
+
def token_callback(token: str, user_data: Any = None) -> bool:
|
|
243
|
+
return not self._cancel_event.is_set()
|
|
196
244
|
|
|
197
|
-
# MLX
|
|
198
|
-
|
|
199
|
-
return result.text
|
|
200
|
-
else:
|
|
201
|
-
# Fallback if result is just a string
|
|
202
|
-
return str(result)
|
|
245
|
+
# Use MLX streaming generation and return the full result
|
|
246
|
+
return self._mlx_vlm.generate_stream(prompt, mlx_gen_config, token_callback)
|
|
203
247
|
|
|
204
248
|
except Exception as e:
|
|
205
249
|
raise RuntimeError(f"Failed to generate text: {str(e)}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nexaai
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4rc15
|
|
4
4
|
Summary: Python bindings for NexaSDK C-lib backend
|
|
5
5
|
Author-email: "Nexa AI, Inc." <dev@nexa.ai>
|
|
6
6
|
Project-URL: Homepage, https://github.com/NexaAI/nexasdk-bridge
|
|
@@ -17,10 +17,11 @@ Requires-Dist: tqdm
|
|
|
17
17
|
Requires-Dist: hf_xet
|
|
18
18
|
Requires-Dist: numpy
|
|
19
19
|
Requires-Dist: httpx
|
|
20
|
-
|
|
21
|
-
Requires-Dist: mlx
|
|
22
|
-
Requires-Dist:
|
|
23
|
-
Requires-Dist:
|
|
24
|
-
Requires-Dist:
|
|
25
|
-
Requires-Dist:
|
|
26
|
-
Requires-Dist:
|
|
20
|
+
Requires-Dist: mlx
|
|
21
|
+
Requires-Dist: mlx-lm
|
|
22
|
+
Requires-Dist: scipy
|
|
23
|
+
Requires-Dist: soundfile
|
|
24
|
+
Requires-Dist: Pillow
|
|
25
|
+
Requires-Dist: opencv-python
|
|
26
|
+
Requires-Dist: shapely
|
|
27
|
+
Requires-Dist: pyclipper
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
nexaai/__init__.py,sha256=d1bC_PUNduXYYPLrzKLyS0RapvcrKzLQGJREsoBZvXM,1977
|
|
2
|
-
nexaai/_stub.cp310-win_amd64.pyd,sha256=
|
|
3
|
-
nexaai/_version.py,sha256=
|
|
2
|
+
nexaai/_stub.cp310-win_amd64.pyd,sha256=C8_5OyVPadKYiSnRiPWYNr6Y7TJCu76TAZV3lBhcqjI,10752
|
|
3
|
+
nexaai/_version.py,sha256=65huyjVsErx2svghMx8d4OaeLV72OhoKTE2Wt_RlEgk,147
|
|
4
4
|
nexaai/asr.py,sha256=1XnwbrSoweBfIVAH6LbILv0DMStTQe_Uq5U_f-EyArY,1873
|
|
5
5
|
nexaai/base.py,sha256=qQBCiQVNzgpkQjZX9aiFDEdbAAe56TROKC3WnWra2Zg,1021
|
|
6
6
|
nexaai/common.py,sha256=00cP8uT9NdldBI3dRNHrQFx-uhdgtOGGxRAx4p96nw4,1586
|
|
7
|
-
nexaai/cv.py,sha256=
|
|
7
|
+
nexaai/cv.py,sha256=90lrW6o77E6uNMk5MYWsLp2f-fhLacjWTT1ENDhVYEg,3120
|
|
8
8
|
nexaai/embedder.py,sha256=FtJtMKrniejTCi8_-ePLOymfkH8j1VzUqteOqGy5cO4,2279
|
|
9
9
|
nexaai/image_gen.py,sha256=oliLxFN7Bd_3wzP4F6frMJ7GPvRn-1kn_8kAtdcy_pY,4258
|
|
10
10
|
nexaai/llm.py,sha256=7V60E1cI1tt6CZ1ti2-tPqkYS56TcJE_kIhvyRyIBeQ,3194
|
|
@@ -16,18 +16,18 @@ nexaai/asr_impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
16
16
|
nexaai/asr_impl/mlx_asr_impl.py,sha256=UpGOtl4JZmcmDRa56z5OyIozFVjfsYpKw_vYU_7HoWk,3282
|
|
17
17
|
nexaai/asr_impl/pybind_asr_impl.py,sha256=C0Qnx-WDNmyC72dxuZVfUwuAoUSMvpo8IfOOkEbqsFA,1493
|
|
18
18
|
nexaai/binds/__init__.py,sha256=tYvy0pFhoY29GstDT5r-oRiPRarPLECvJAkcamJItOg,83
|
|
19
|
-
nexaai/binds/common_bind.cp310-win_amd64.pyd,sha256=
|
|
20
|
-
nexaai/binds/embedder_bind.cp310-win_amd64.pyd,sha256
|
|
21
|
-
nexaai/binds/llm_bind.cp310-win_amd64.pyd,sha256=
|
|
22
|
-
nexaai/binds/nexa_bridge.dll,sha256=
|
|
23
|
-
nexaai/binds/nexa_llama_cpp/ggml-base.dll,sha256=
|
|
24
|
-
nexaai/binds/nexa_llama_cpp/ggml-cpu.dll,sha256=
|
|
25
|
-
nexaai/binds/nexa_llama_cpp/ggml-cuda.dll,sha256=
|
|
26
|
-
nexaai/binds/nexa_llama_cpp/ggml-vulkan.dll,sha256=
|
|
27
|
-
nexaai/binds/nexa_llama_cpp/ggml.dll,sha256=
|
|
28
|
-
nexaai/binds/nexa_llama_cpp/llama.dll,sha256=
|
|
29
|
-
nexaai/binds/nexa_llama_cpp/mtmd.dll,sha256=
|
|
30
|
-
nexaai/binds/nexa_llama_cpp/nexa_plugin.dll,sha256=
|
|
19
|
+
nexaai/binds/common_bind.cp310-win_amd64.pyd,sha256=tsCwzARi5fu-66q24KKLnWnBhNOt4UEbXbssgv4MPTw,201216
|
|
20
|
+
nexaai/binds/embedder_bind.cp310-win_amd64.pyd,sha256=-JroOPxqlTEIU1BirfvjE0vqF__WCvsJaiuE3toWoyI,182784
|
|
21
|
+
nexaai/binds/llm_bind.cp310-win_amd64.pyd,sha256=e7BWEt6TzJocCe_Qb3dB1c-73n6ETL9uPOMuTEsT0Ew,160256
|
|
22
|
+
nexaai/binds/nexa_bridge.dll,sha256=HPGaSjp3uuNGWXKhxvNbyiwxuyLFWr6TzIBxTlaweqQ,176640
|
|
23
|
+
nexaai/binds/nexa_llama_cpp/ggml-base.dll,sha256=WiLohLZ6F5t9Vc0o65CjOMijPjuSH6-G586FOwOJLFE,514560
|
|
24
|
+
nexaai/binds/nexa_llama_cpp/ggml-cpu.dll,sha256=vUHtE3B6dAuJu-WCmXCD7GKayM5HBcoYHw7DVXMvG-4,663552
|
|
25
|
+
nexaai/binds/nexa_llama_cpp/ggml-cuda.dll,sha256=2O7SF6N6VUYPq2yf3l-KFvEpee2X6Yh_7vSbfgWVi2o,315100160
|
|
26
|
+
nexaai/binds/nexa_llama_cpp/ggml-vulkan.dll,sha256=vhNQXlF9_0f5WQkzckQ4lGzmI0ccTPWDODhWlej1ebs,26204160
|
|
27
|
+
nexaai/binds/nexa_llama_cpp/ggml.dll,sha256=VYw6ZxxvlZf4Gi2jkTaOeWSB_pZCIuex4hBd6cWwSWI,66560
|
|
28
|
+
nexaai/binds/nexa_llama_cpp/llama.dll,sha256=Zp6IS6RSJ72vDulABng_9Q59tKvi3znbm13pJwazzNY,1587712
|
|
29
|
+
nexaai/binds/nexa_llama_cpp/mtmd.dll,sha256=9350YqtbNICY1eV1gLB7flBu6NpRUoMf3ESIyH3uoiI,560128
|
|
30
|
+
nexaai/binds/nexa_llama_cpp/nexa_plugin.dll,sha256=DeKJPc4fgbgC14iBPghfjGID9vuT3FEkvx9FT6BDk1s,1086464
|
|
31
31
|
nexaai/cv_impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
32
32
|
nexaai/cv_impl/mlx_cv_impl.py,sha256=vYN8ASbDr-VlQcia0ydpE3tUfnRcRIoRVQDAOhlZB_4,3250
|
|
33
33
|
nexaai/cv_impl/pybind_cv_impl.py,sha256=oXT7Hcurg2YH_qgvwpGtgeQcIFxt6uzT9xN-cLvRHcU,1029
|
|
@@ -49,11 +49,11 @@ nexaai/tts_impl/pybind_tts_impl.py,sha256=JmWWoluN6I8325IwPL_Np8RLUq_yMENPoyszQ9
|
|
|
49
49
|
nexaai/utils/avatar_fetcher.py,sha256=D01f8je-37Nd68zGw8MYK2m7y3fvGlC6h0KR-aN9kdU,3925
|
|
50
50
|
nexaai/utils/decode.py,sha256=0Z9jDH4ICzw4YXj8nD4L-sMouDaev-TISGRQ4KzidWE,421
|
|
51
51
|
nexaai/utils/model_manager.py,sha256=Ksl-tKq-a3miTUxEn6-SSOC_KVdn6RPjcUdkWmDDwCk,49767
|
|
52
|
-
nexaai/utils/progress_tracker.py,sha256=
|
|
52
|
+
nexaai/utils/progress_tracker.py,sha256=FmJBoOlzfQdc-TmccEav0cBR_iSNrrcskG3Fm1OrEJA,15482
|
|
53
53
|
nexaai/vlm_impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
54
|
-
nexaai/vlm_impl/mlx_vlm_impl.py,sha256=
|
|
54
|
+
nexaai/vlm_impl/mlx_vlm_impl.py,sha256=O0NA0zkJ4mhv5lT4EBSVineGe_F0Rsz4ITQvaX_VgIk,10651
|
|
55
55
|
nexaai/vlm_impl/pybind_vlm_impl.py,sha256=WGC21LaQnr4LEiytXX8wVBMLJDG75GIweW3kEMxJGXE,8561
|
|
56
|
-
nexaai-1.0.
|
|
57
|
-
nexaai-1.0.
|
|
58
|
-
nexaai-1.0.
|
|
59
|
-
nexaai-1.0.
|
|
56
|
+
nexaai-1.0.4rc15.dist-info/METADATA,sha256=eHwHTGzl4PN_GfTApdOqE5dQTesECMWRo6r6CYZe7rY,910
|
|
57
|
+
nexaai-1.0.4rc15.dist-info/WHEEL,sha256=KUuBC6lxAbHCKilKua8R9W_TM71_-9Sg5uEP3uDWcoU,101
|
|
58
|
+
nexaai-1.0.4rc15.dist-info/top_level.txt,sha256=LRE2YERlrZk2vfuygnSzsEeqSknnZbz3Z1MHyNmBU4w,7
|
|
59
|
+
nexaai-1.0.4rc15.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|