Skip to content

Commit 65a1ab7

Browse files
Merge pull request #59 from JigsawStack/fix/v3checks
Fix/v3checks
2 parents 7f49f0a + bfeb4dd commit 65a1ab7

28 files changed

+629
-517
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@ pyproject.toml
3030
uv.lock
3131

3232
.ruff_cache/
33+
local_tests/

jigsawstack/__init__.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def __init__(
107107
api_url=api_url,
108108
disable_request_logging=disable_request_logging,
109109
)
110-
110+
111111
self.embedding = Embedding(
112112
api_key=api_key,
113113
api_url=api_url,
@@ -123,8 +123,7 @@ def __init__(
123123
api_key=api_key,
124124
api_url=api_url,
125125
disable_request_logging=disable_request_logging,
126-
)
127-
126+
).classify
128127

129128

130129
class AsyncJigsawStack:
@@ -218,7 +217,6 @@ def __init__(
218217
disable_request_logging=disable_request_logging,
219218
)
220219

221-
222220
self.embedding = AsyncEmbedding(
223221
api_key=api_key,
224222
api_url=api_url,
@@ -235,8 +233,7 @@ def __init__(
235233
api_key=api_key,
236234
api_url=api_url,
237235
disable_request_logging=disable_request_logging,
238-
)
239-
236+
).classify
240237

241238

242239
# Create a global instance of the Web class

jigsawstack/_types.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from typing_extensions import NotRequired, TypedDict
2+
3+
4+
class UsageInfo(TypedDict):
5+
input_tokens: int
6+
output_tokens: int
7+
inference_time_tokens: int
8+
total_tokens: int
9+
10+
11+
class BaseResponse(TypedDict):
12+
success: bool
13+
_usage: NotRequired[UsageInfo]

jigsawstack/audio.py

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from typing_extensions import NotRequired, TypedDict, Literal
88
from .custom_typing import SupportedAccents
99
from .helpers import build_path
10+
from ._types import BaseResponse
1011

1112

1213
class SpeechToTextParams(TypedDict):
@@ -27,15 +28,28 @@ class ChunkParams(TypedDict):
2728

2829
class BySpeakerParams(ChunkParams):
2930
speaker: str
31+
timestamp: tuple[int, int]
32+
text: str
3033

3134

32-
class SpeechToTextResponse(TypedDict):
33-
success: bool
35+
class SpeechToTextResponse(BaseResponse):
3436
text: str
3537
chunks: List[ChunkParams]
3638
speakers: Optional[List[BySpeakerParams]]
3739

3840

41+
class SpeechToTextWebhookResponse(BaseResponse):
42+
status: Literal["processing", "error"]
43+
"""
44+
the status of the transcription process
45+
"""
46+
47+
id: str
48+
"""
49+
the id of the transcription process
50+
"""
51+
52+
3953
class Audio(ClientConfig):
4054
config: RequestConfig
4155

@@ -53,17 +67,19 @@ def __init__(
5367
)
5468

5569
@overload
56-
def speech_to_text(self, params: SpeechToTextParams) -> SpeechToTextResponse: ...
70+
def speech_to_text(
71+
self, params: SpeechToTextParams
72+
) -> Union[SpeechToTextResponse, SpeechToTextWebhookResponse]: ...
5773
@overload
5874
def speech_to_text(
5975
self, blob: bytes, options: Optional[SpeechToTextParams] = None
60-
) -> SpeechToTextResponse: ...
76+
) -> Union[SpeechToTextResponse, SpeechToTextWebhookResponse]: ...
6177

6278
def speech_to_text(
6379
self,
6480
blob: Union[SpeechToTextParams, bytes],
6581
options: Optional[SpeechToTextParams] = None,
66-
) -> SpeechToTextResponse:
82+
) -> Union[SpeechToTextResponse, SpeechToTextWebhookResponse]:
6783
if isinstance(
6884
blob, dict
6985
): # If params is provided as a dict, we assume it's the first argument
@@ -110,17 +126,17 @@ def __init__(
110126
@overload
111127
async def speech_to_text(
112128
self, params: SpeechToTextParams
113-
) -> SpeechToTextResponse: ...
129+
) -> Union[SpeechToTextResponse, SpeechToTextWebhookResponse]: ...
114130
@overload
115131
async def speech_to_text(
116132
self, blob: bytes, options: Optional[SpeechToTextParams] = None
117-
) -> SpeechToTextResponse: ...
133+
) -> Union[SpeechToTextResponse, SpeechToTextWebhookResponse]: ...
118134

119135
async def speech_to_text(
120136
self,
121137
blob: Union[SpeechToTextParams, bytes],
122138
options: Optional[SpeechToTextParams] = None,
123-
) -> SpeechToTextResponse:
139+
) -> Union[SpeechToTextResponse, SpeechToTextWebhookResponse]:
124140
if isinstance(blob, dict):
125141
resp = await AsyncRequest(
126142
config=self.config,

jigsawstack/classification.py

Lines changed: 13 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -3,110 +3,63 @@
33
from .request import Request, RequestConfig
44
from .async_request import AsyncRequest, AsyncRequestConfig
55
from ._config import ClientConfig
6+
from ._types import BaseResponse
67

78

8-
class DatasetItemText(TypedDict):
9-
type: Literal["text"]
9+
class DatasetItem(TypedDict):
10+
type: Literal["text", "image"]
1011
"""
1112
Type of the dataset item: text
1213
"""
13-
14-
value: str
15-
"""
16-
Value of the dataset item
17-
"""
18-
1914

20-
class DatasetItemImage(TypedDict):
21-
type: Literal["image"]
22-
"""
23-
Type of the dataset item: image
24-
"""
25-
2615
value: str
2716
"""
2817
Value of the dataset item
2918
"""
3019

3120

32-
class LabelItemText(TypedDict):
21+
class LabelItem(TypedDict):
3322
key: NotRequired[str]
3423
"""
3524
Optional key for the label
3625
"""
37-
38-
type: Literal["text"]
26+
27+
type: Literal["text", "image"]
3928
"""
4029
Type of the label: text
4130
"""
42-
43-
value: str
44-
"""
45-
Value of the label
46-
"""
4731

48-
49-
class LabelItemImage(TypedDict):
50-
key: NotRequired[str]
51-
"""
52-
Optional key for the label
53-
"""
54-
55-
type: Literal["image", "text"]
56-
"""
57-
Type of the label: image or text
58-
"""
59-
6032
value: str
6133
"""
6234
Value of the label
6335
"""
6436

6537

66-
class ClassificationTextParams(TypedDict):
67-
dataset: List[DatasetItemText]
38+
class ClassificationParams(TypedDict):
39+
dataset: List[DatasetItem]
6840
"""
6941
List of text dataset items to classify
7042
"""
71-
72-
labels: List[LabelItemText]
43+
44+
labels: List[LabelItem]
7345
"""
7446
List of text labels for classification
7547
"""
76-
77-
multiple_labels: NotRequired[bool]
78-
"""
79-
Whether to allow multiple labels per item
80-
"""
8148

82-
83-
class ClassificationImageParams(TypedDict):
84-
dataset: List[DatasetItemImage]
85-
"""
86-
List of image dataset items to classify
87-
"""
88-
89-
labels: List[LabelItemImage]
90-
"""
91-
List of labels for classification
92-
"""
93-
9449
multiple_labels: NotRequired[bool]
9550
"""
9651
Whether to allow multiple labels per item
9752
"""
9853

9954

100-
class ClassificationResponse(TypedDict):
55+
class ClassificationResponse(BaseResponse):
10156
predictions: List[Union[str, List[str]]]
10257
"""
10358
Classification predictions - single labels or multiple labels per item
10459
"""
10560

10661

107-
10862
class Classification(ClientConfig):
109-
11063
config: RequestConfig
11164

11265
def __init__(
@@ -122,16 +75,7 @@ def __init__(
12275
disable_request_logging=disable_request_logging,
12376
)
12477

125-
def text(self, params: ClassificationTextParams) -> ClassificationResponse:
126-
path = "/classification"
127-
resp = Request(
128-
config=self.config,
129-
path=path,
130-
params=cast(Dict[Any, Any], params),
131-
verb="post",
132-
).perform_with_content()
133-
return resp
134-
def image(self, params: ClassificationImageParams) -> ClassificationResponse:
78+
def classify(self, params: ClassificationParams) -> ClassificationResponse:
13579
path = "/classification"
13680
resp = Request(
13781
config=self.config,
@@ -142,7 +86,6 @@ def image(self, params: ClassificationImageParams) -> ClassificationResponse:
14286
return resp
14387

14488

145-
14689
class AsyncClassification(ClientConfig):
14790
config: AsyncRequestConfig
14891

@@ -159,7 +102,7 @@ def __init__(
159102
disable_request_logging=disable_request_logging,
160103
)
161104

162-
async def text(self, params: ClassificationTextParams) -> ClassificationResponse:
105+
async def classify(self, params: ClassificationParams) -> ClassificationResponse:
163106
path = "/classification"
164107
resp = await AsyncRequest(
165108
config=self.config,
@@ -168,13 +111,3 @@ async def text(self, params: ClassificationTextParams) -> ClassificationResponse
168111
verb="post",
169112
).perform_with_content()
170113
return resp
171-
172-
async def image(self, params: ClassificationImageParams) -> ClassificationResponse:
173-
path = "/classification"
174-
resp = await AsyncRequest(
175-
config=self.config,
176-
path=path,
177-
params=cast(Dict[Any, Any], params),
178-
verb="post",
179-
).perform_with_content()
180-
return resp

jigsawstack/embedding.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from typing import List, Union
66
from ._config import ClientConfig
77
from .helpers import build_path
8+
from ._types import BaseResponse
89

910

1011
class EmbeddingParams(TypedDict):
@@ -13,17 +14,20 @@ class EmbeddingParams(TypedDict):
1314
type: Literal["text", "text-other", "image", "audio", "pdf"]
1415
url: NotRequired[str]
1516
file_store_key: NotRequired[str]
16-
token_overflow_mode: NotRequired[Literal["truncate", "chunk", "error"]] = "chunk"
17+
token_overflow_mode: NotRequired[Literal["truncate", "error"]]
1718

1819

19-
class EmbeddingResponse(TypedDict):
20-
success: bool
20+
class Chunk(TypedDict):
21+
text: str
22+
timestamp: List[int]
23+
24+
25+
class EmbeddingResponse(BaseResponse):
2126
embeddings: List[List[float]]
22-
chunks: List[str]
27+
chunks: List[Chunk]
2328

2429

2530
class Embedding(ClientConfig):
26-
2731
config: RequestConfig
2832

2933
def __init__(
@@ -42,14 +46,16 @@ def __init__(
4246
@overload
4347
def execute(self, params: EmbeddingParams) -> EmbeddingResponse: ...
4448
@overload
45-
def execute(self, blob: bytes, options: EmbeddingParams = None) -> EmbeddingResponse: ...
49+
def execute(
50+
self, blob: bytes, options: EmbeddingParams = None
51+
) -> EmbeddingResponse: ...
4652

4753
def execute(
4854
self,
4955
blob: Union[EmbeddingParams, bytes],
5056
options: EmbeddingParams = None,
5157
) -> EmbeddingResponse:
52-
path="/embedding"
58+
path = "/embedding"
5359
if isinstance(blob, dict):
5460
resp = Request(
5561
config=self.config,
@@ -76,7 +82,6 @@ def execute(
7682

7783

7884
class AsyncEmbedding(ClientConfig):
79-
8085
config: RequestConfig
8186

8287
def __init__(
@@ -95,14 +100,16 @@ def __init__(
95100
@overload
96101
async def execute(self, params: EmbeddingParams) -> EmbeddingResponse: ...
97102
@overload
98-
async def execute(self, blob: bytes, options: EmbeddingParams = None) -> EmbeddingResponse: ...
103+
async def execute(
104+
self, blob: bytes, options: EmbeddingParams = None
105+
) -> EmbeddingResponse: ...
99106

100107
async def execute(
101108
self,
102109
blob: Union[EmbeddingParams, bytes],
103110
options: EmbeddingParams = None,
104111
) -> EmbeddingResponse:
105-
path="/embedding"
112+
path = "/embedding"
106113
if isinstance(blob, dict):
107114
resp = await AsyncRequest(
108115
config=self.config,

0 commit comments

Comments
 (0)