inferencesh 0.1.23__py3-none-any.whl → 0.2.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 inferencesh might be problematic. Click here for more details.
- inferencesh/sdk.py +96 -17
- {inferencesh-0.1.23.dist-info → inferencesh-0.2.0.dist-info}/METADATA +4 -1
- inferencesh-0.2.0.dist-info/RECORD +8 -0
- {inferencesh-0.1.23.dist-info → inferencesh-0.2.0.dist-info}/WHEEL +1 -1
- inferencesh-0.1.23.dist-info/RECORD +0 -8
- {inferencesh-0.1.23.dist-info → inferencesh-0.2.0.dist-info}/entry_points.txt +0 -0
- {inferencesh-0.1.23.dist-info → inferencesh-0.2.0.dist-info}/licenses/LICENSE +0 -0
- {inferencesh-0.1.23.dist-info → inferencesh-0.2.0.dist-info}/top_level.txt +0 -0
inferencesh/sdk.py
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
|
-
from typing import Optional, Union
|
|
2
|
-
from pydantic import BaseModel, ConfigDict, PrivateAttr, model_validator
|
|
1
|
+
from typing import Optional, Union
|
|
2
|
+
from pydantic import BaseModel, ConfigDict, PrivateAttr, model_validator, Field, field_validator
|
|
3
3
|
import mimetypes
|
|
4
4
|
import os
|
|
5
5
|
import urllib.request
|
|
6
6
|
import urllib.parse
|
|
7
7
|
import tempfile
|
|
8
|
-
from pydantic import Field
|
|
9
8
|
from typing import Any, Dict, List
|
|
10
9
|
|
|
11
10
|
import inspect
|
|
12
11
|
import ast
|
|
13
12
|
import textwrap
|
|
14
13
|
from collections import OrderedDict
|
|
14
|
+
from enum import Enum
|
|
15
|
+
import shutil
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
import hashlib
|
|
15
18
|
|
|
16
19
|
|
|
17
20
|
# inspired by https://github.com/pydantic/pydantic/issues/7580
|
|
@@ -102,20 +105,35 @@ class BaseApp(BaseModel):
|
|
|
102
105
|
|
|
103
106
|
class File(BaseModel):
|
|
104
107
|
"""A class representing a file in the inference.sh ecosystem."""
|
|
105
|
-
uri: Optional[str] = None # Original location (URL or file path)
|
|
108
|
+
uri: Optional[str] = Field(default=None) # Original location (URL or file path)
|
|
106
109
|
path: Optional[str] = None # Resolved local file path
|
|
107
110
|
content_type: Optional[str] = None # MIME type of the file
|
|
108
111
|
size: Optional[int] = None # File size in bytes
|
|
109
112
|
filename: Optional[str] = None # Original filename if available
|
|
110
113
|
_tmp_path: Optional[str] = PrivateAttr(default=None) # Internal storage for temporary file path
|
|
111
114
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
def __init__(self, initializer=None, **data):
|
|
116
|
+
if initializer is not None:
|
|
117
|
+
if isinstance(initializer, str):
|
|
118
|
+
data['uri'] = initializer
|
|
119
|
+
elif isinstance(initializer, File):
|
|
120
|
+
data = initializer.model_dump()
|
|
121
|
+
else:
|
|
122
|
+
raise ValueError(f'Invalid input for File: {initializer}')
|
|
123
|
+
super().__init__(**data)
|
|
124
|
+
|
|
125
|
+
@model_validator(mode='before')
|
|
126
|
+
@classmethod
|
|
127
|
+
def convert_str_to_file(cls, values):
|
|
128
|
+
print(f"check_uri_or_path input: {values}")
|
|
129
|
+
if isinstance(values, str): # Only accept strings
|
|
130
|
+
return {"uri": values}
|
|
131
|
+
elif isinstance(values, dict):
|
|
132
|
+
return values
|
|
133
|
+
raise ValueError(f'Invalid input for File: {values}')
|
|
134
|
+
|
|
117
135
|
@model_validator(mode='after')
|
|
118
|
-
def
|
|
136
|
+
def validate_required_fields(self) -> 'File':
|
|
119
137
|
"""Validate that either uri or path is provided."""
|
|
120
138
|
if not self.uri and not self.path:
|
|
121
139
|
raise ValueError("Either 'uri' or 'path' must be provided")
|
|
@@ -128,7 +146,10 @@ class File(BaseModel):
|
|
|
128
146
|
self.path = os.path.abspath(self.uri)
|
|
129
147
|
elif self.uri:
|
|
130
148
|
self.path = self.uri
|
|
131
|
-
self.
|
|
149
|
+
if self.path:
|
|
150
|
+
self._populate_metadata()
|
|
151
|
+
else:
|
|
152
|
+
raise ValueError("Either 'uri' or 'path' must be provided")
|
|
132
153
|
|
|
133
154
|
def _is_url(self, path: str) -> bool:
|
|
134
155
|
"""Check if the path is a URL."""
|
|
@@ -170,7 +191,7 @@ class File(BaseModel):
|
|
|
170
191
|
if tmp_file is not None and hasattr(self, '_tmp_path'):
|
|
171
192
|
try:
|
|
172
193
|
os.unlink(self._tmp_path)
|
|
173
|
-
except:
|
|
194
|
+
except (OSError, IOError):
|
|
174
195
|
pass
|
|
175
196
|
raise RuntimeError(f"Error downloading URL {original_url}: {str(e)}")
|
|
176
197
|
|
|
@@ -179,7 +200,7 @@ class File(BaseModel):
|
|
|
179
200
|
if hasattr(self, '_tmp_path') and self._tmp_path:
|
|
180
201
|
try:
|
|
181
202
|
os.unlink(self._tmp_path)
|
|
182
|
-
except:
|
|
203
|
+
except (OSError, IOError):
|
|
183
204
|
pass
|
|
184
205
|
|
|
185
206
|
def _populate_metadata(self) -> None:
|
|
@@ -215,13 +236,24 @@ class File(BaseModel):
|
|
|
215
236
|
|
|
216
237
|
def refresh_metadata(self) -> None:
|
|
217
238
|
"""Refresh all metadata from the file."""
|
|
218
|
-
self.
|
|
239
|
+
if os.path.exists(self.path):
|
|
240
|
+
self.content_type = self._guess_content_type()
|
|
241
|
+
self.size = self._get_file_size() # Always update size
|
|
242
|
+
self.filename = self._get_filename()
|
|
243
|
+
|
|
219
244
|
|
|
245
|
+
class ContextMessageRole(str, Enum):
|
|
246
|
+
USER = "user"
|
|
247
|
+
ASSISTANT = "assistant"
|
|
248
|
+
SYSTEM = "system"
|
|
249
|
+
|
|
250
|
+
class Message(BaseModel):
|
|
251
|
+
role: ContextMessageRole
|
|
252
|
+
content: str
|
|
220
253
|
|
|
221
254
|
class ContextMessage(BaseModel):
|
|
222
|
-
role:
|
|
255
|
+
role: ContextMessageRole = Field(
|
|
223
256
|
description="The role of the message",
|
|
224
|
-
enum=["user", "assistant", "system"]
|
|
225
257
|
)
|
|
226
258
|
text: str = Field(
|
|
227
259
|
description="The text content of the message"
|
|
@@ -281,4 +313,51 @@ class LLMInputWithImage(LLMInput):
|
|
|
281
313
|
image: Optional[File] = Field(
|
|
282
314
|
description="The image to use for the model",
|
|
283
315
|
default=None
|
|
284
|
-
)
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
class DownloadDir(str, Enum):
|
|
319
|
+
"""Standard download directories used by the SDK."""
|
|
320
|
+
DATA = "./data" # Persistent storage/cache directory
|
|
321
|
+
TEMP = "./tmp" # Temporary storage directory
|
|
322
|
+
CACHE = "./cache" # Cache directory
|
|
323
|
+
|
|
324
|
+
def download(url: str, directory: Union[str, Path, DownloadDir]) -> str:
|
|
325
|
+
"""Download a file to the specified directory and return its path.
|
|
326
|
+
|
|
327
|
+
Args:
|
|
328
|
+
url: The URL to download from
|
|
329
|
+
directory: The directory to save the file to. Can be a string path,
|
|
330
|
+
Path object, or DownloadDir enum value.
|
|
331
|
+
|
|
332
|
+
Returns:
|
|
333
|
+
str: The path to the downloaded file
|
|
334
|
+
"""
|
|
335
|
+
# Convert directory to Path
|
|
336
|
+
dir_path = Path(directory)
|
|
337
|
+
dir_path.mkdir(exist_ok=True)
|
|
338
|
+
|
|
339
|
+
# Create hash directory from URL
|
|
340
|
+
url_hash = hashlib.sha256(url.encode()).hexdigest()[:12]
|
|
341
|
+
hash_dir = dir_path / url_hash
|
|
342
|
+
hash_dir.mkdir(exist_ok=True)
|
|
343
|
+
|
|
344
|
+
# Keep original filename
|
|
345
|
+
filename = os.path.basename(urllib.parse.urlparse(url).path)
|
|
346
|
+
if not filename:
|
|
347
|
+
filename = 'download'
|
|
348
|
+
|
|
349
|
+
output_path = hash_dir / filename
|
|
350
|
+
|
|
351
|
+
# If file exists in directory and it's not a temp directory, return it
|
|
352
|
+
if output_path.exists() and directory != DownloadDir.TEMP:
|
|
353
|
+
return str(output_path)
|
|
354
|
+
|
|
355
|
+
# Download the file
|
|
356
|
+
file = File(url)
|
|
357
|
+
if file.path:
|
|
358
|
+
shutil.copy2(file.path, output_path)
|
|
359
|
+
# Prevent the File instance from deleting its temporary file
|
|
360
|
+
file._tmp_path = None
|
|
361
|
+
return str(output_path)
|
|
362
|
+
|
|
363
|
+
raise RuntimeError(f"Failed to download {url}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: inferencesh
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: inference.sh Python SDK
|
|
5
5
|
Author: Inference Shell Inc.
|
|
6
6
|
Author-email: "Inference Shell Inc." <hello@inference.sh>
|
|
@@ -13,6 +13,9 @@ Requires-Python: >=3.7
|
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
15
|
Requires-Dist: pydantic>=2.0.0
|
|
16
|
+
Provides-Extra: test
|
|
17
|
+
Requires-Dist: pytest>=7.0.0; extra == "test"
|
|
18
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "test"
|
|
16
19
|
Dynamic: author
|
|
17
20
|
Dynamic: license-file
|
|
18
21
|
Dynamic: requires-python
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
inferencesh/__init__.py,sha256=hbKkgHCh0lCdhWyHs3FHHRd8JfLeHkTd1bT4v79Fi8M,192
|
|
2
|
+
inferencesh/sdk.py,sha256=Yebi85zvWYHVnnf5CARHg-eOpOPM2mZ7SafRlaJuwdA,14554
|
|
3
|
+
inferencesh-0.2.0.dist-info/licenses/LICENSE,sha256=OsgqEWIh2el_QMj0y8O1A5Q5Dl-dxqqYbFE6fszuR4s,1086
|
|
4
|
+
inferencesh-0.2.0.dist-info/METADATA,sha256=AHDRrj_mW__FIxMgCPu1CRReJrTbk4uUZ0Ra60Cst1s,2728
|
|
5
|
+
inferencesh-0.2.0.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
|
6
|
+
inferencesh-0.2.0.dist-info/entry_points.txt,sha256=6IC-fyozAqW3ljsMLGCXxJ0_ui2Jb-2fLHtoH1RTnEE,45
|
|
7
|
+
inferencesh-0.2.0.dist-info/top_level.txt,sha256=TSMHg3T1ThMl1HGAWmzBClwOYH1ump5neof9BfHIwaA,12
|
|
8
|
+
inferencesh-0.2.0.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
inferencesh/__init__.py,sha256=hbKkgHCh0lCdhWyHs3FHHRd8JfLeHkTd1bT4v79Fi8M,192
|
|
2
|
-
inferencesh/sdk.py,sha256=MdGlTaZITc9nuE94jLU01L1LWsC5RKj-OpFre-x6CeI,11738
|
|
3
|
-
inferencesh-0.1.23.dist-info/licenses/LICENSE,sha256=OsgqEWIh2el_QMj0y8O1A5Q5Dl-dxqqYbFE6fszuR4s,1086
|
|
4
|
-
inferencesh-0.1.23.dist-info/METADATA,sha256=_S9CelUY7dd_6ECy-n3Dj-K562rN3cvQ5f1WLvXP5HQ,2612
|
|
5
|
-
inferencesh-0.1.23.dist-info/WHEEL,sha256=ck4Vq1_RXyvS4Jt6SI0Vz6fyVs4GWg7AINwpsaGEgPE,91
|
|
6
|
-
inferencesh-0.1.23.dist-info/entry_points.txt,sha256=6IC-fyozAqW3ljsMLGCXxJ0_ui2Jb-2fLHtoH1RTnEE,45
|
|
7
|
-
inferencesh-0.1.23.dist-info/top_level.txt,sha256=TSMHg3T1ThMl1HGAWmzBClwOYH1ump5neof9BfHIwaA,12
|
|
8
|
-
inferencesh-0.1.23.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|