inferencesh 0.1.24__py3-none-any.whl → 0.3.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 +92 -32
- {inferencesh-0.1.24.dist-info → inferencesh-0.3.0.dist-info}/METADATA +4 -1
- inferencesh-0.3.0.dist-info/RECORD +8 -0
- inferencesh-0.1.24.dist-info/RECORD +0 -8
- {inferencesh-0.1.24.dist-info → inferencesh-0.3.0.dist-info}/WHEEL +0 -0
- {inferencesh-0.1.24.dist-info → inferencesh-0.3.0.dist-info}/entry_points.txt +0 -0
- {inferencesh-0.1.24.dist-info → inferencesh-0.3.0.dist-info}/licenses/LICENSE +0 -0
- {inferencesh-0.1.24.dist-info → inferencesh-0.3.0.dist-info}/top_level.txt +0 -0
inferencesh/sdk.py
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
from typing import Optional, Union
|
|
2
|
-
from pydantic import BaseModel, ConfigDict, PrivateAttr, model_validator
|
|
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,39 +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
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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')
|
|
122
126
|
@classmethod
|
|
123
|
-
def
|
|
124
|
-
"
|
|
125
|
-
if isinstance(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
elif isinstance(value, dict):
|
|
132
|
-
# If it's a dict, use normal validation
|
|
133
|
-
return cls(**value)
|
|
134
|
-
raise ValueError(f'Invalid input for File: {value}')
|
|
135
|
-
|
|
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
|
+
|
|
136
135
|
@model_validator(mode='after')
|
|
137
|
-
def
|
|
136
|
+
def validate_required_fields(self) -> 'File':
|
|
138
137
|
"""Validate that either uri or path is provided."""
|
|
139
138
|
if not self.uri and not self.path:
|
|
140
139
|
raise ValueError("Either 'uri' or 'path' must be provided")
|
|
@@ -147,7 +146,10 @@ class File(BaseModel):
|
|
|
147
146
|
self.path = os.path.abspath(self.uri)
|
|
148
147
|
elif self.uri:
|
|
149
148
|
self.path = self.uri
|
|
150
|
-
self.
|
|
149
|
+
if self.path:
|
|
150
|
+
self._populate_metadata()
|
|
151
|
+
else:
|
|
152
|
+
raise ValueError("Either 'uri' or 'path' must be provided")
|
|
151
153
|
|
|
152
154
|
def _is_url(self, path: str) -> bool:
|
|
153
155
|
"""Check if the path is a URL."""
|
|
@@ -234,13 +236,24 @@ class File(BaseModel):
|
|
|
234
236
|
|
|
235
237
|
def refresh_metadata(self) -> None:
|
|
236
238
|
"""Refresh all metadata from the file."""
|
|
237
|
-
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()
|
|
238
243
|
|
|
239
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
|
|
253
|
+
|
|
240
254
|
class ContextMessage(BaseModel):
|
|
241
|
-
role:
|
|
255
|
+
role: ContextMessageRole = Field(
|
|
242
256
|
description="The role of the message",
|
|
243
|
-
enum=["user", "assistant", "system"]
|
|
244
257
|
)
|
|
245
258
|
text: str = Field(
|
|
246
259
|
description="The text content of the message"
|
|
@@ -300,4 +313,51 @@ class LLMInputWithImage(LLMInput):
|
|
|
300
313
|
image: Optional[File] = Field(
|
|
301
314
|
description="The image to use for the model",
|
|
302
315
|
default=None
|
|
303
|
-
)
|
|
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.3.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.3.0.dist-info/licenses/LICENSE,sha256=OsgqEWIh2el_QMj0y8O1A5Q5Dl-dxqqYbFE6fszuR4s,1086
|
|
4
|
+
inferencesh-0.3.0.dist-info/METADATA,sha256=_06FcZ_2WJ7dS7DHhWmWDfmjR6rspTYZL7x9X0mUr5M,2728
|
|
5
|
+
inferencesh-0.3.0.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
|
6
|
+
inferencesh-0.3.0.dist-info/entry_points.txt,sha256=6IC-fyozAqW3ljsMLGCXxJ0_ui2Jb-2fLHtoH1RTnEE,45
|
|
7
|
+
inferencesh-0.3.0.dist-info/top_level.txt,sha256=TSMHg3T1ThMl1HGAWmzBClwOYH1ump5neof9BfHIwaA,12
|
|
8
|
+
inferencesh-0.3.0.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
inferencesh/__init__.py,sha256=hbKkgHCh0lCdhWyHs3FHHRd8JfLeHkTd1bT4v79Fi8M,192
|
|
2
|
-
inferencesh/sdk.py,sha256=u8GbIAn5clg_9zHUy99zu2AidgBION4f1KcMJnmjChg,12417
|
|
3
|
-
inferencesh-0.1.24.dist-info/licenses/LICENSE,sha256=OsgqEWIh2el_QMj0y8O1A5Q5Dl-dxqqYbFE6fszuR4s,1086
|
|
4
|
-
inferencesh-0.1.24.dist-info/METADATA,sha256=FM54ThOJtpP14Z1-DN2ZV0Mv0g73md2u8kW15mJfSE4,2612
|
|
5
|
-
inferencesh-0.1.24.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
|
6
|
-
inferencesh-0.1.24.dist-info/entry_points.txt,sha256=6IC-fyozAqW3ljsMLGCXxJ0_ui2Jb-2fLHtoH1RTnEE,45
|
|
7
|
-
inferencesh-0.1.24.dist-info/top_level.txt,sha256=TSMHg3T1ThMl1HGAWmzBClwOYH1ump5neof9BfHIwaA,12
|
|
8
|
-
inferencesh-0.1.24.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|