Skip to content

Commit 86cee4c

Browse files
stainless-app[bot]dulaj-metimofeev1995technillogue
authored
release: 2.4.0 (#297)
* fix: fixed autoscaling configs in deployments api * fix(jig): send {} for deployment autoscaling to unset if unset in config (#294) * fix: fix autoscaling config usage in jig (#298) * Fix & enrich tokenization example script (#296) * Fix script * Add parquet columnt to the list * feat(jig): move config.dockerfile to config.image.dockerfile_path and add an config.deploy.image option so that you don't have to always pass it as a flag (#287) * chore: fix lints (#299) * release: 2.4.0 --------- Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com> Co-authored-by: Dulaj Disanayaka <[email protected]> Co-authored-by: Egor Timofeev <[email protected]> Co-authored-by: technillogue <[email protected]>
1 parent f80a2b0 commit 86cee4c

File tree

13 files changed

+312
-71
lines changed

13 files changed

+312
-71
lines changed

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "2.3.2"
2+
".": "2.4.0"
33
}

.stats.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
configured_endpoints: 74
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/togetherai%2Ftogetherai-7a33f9086abc839141dcbfef36fc505b7c2618dc893a24e11a09e5bffe976bcf.yml
3-
openapi_spec_hash: dba6fe0b4f5f10181628be7e93718d3a
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/togetherai%2Ftogetherai-452048e531c558b879791ccc9788c3f3c23c50c808c909a6d95f47af360566a4.yml
3+
openapi_spec_hash: 11835b47ff4c2d1b4dbeed74c49908e1
44
config_hash: b66198d27b4d5c152688ff6cccfdeab5

CHANGELOG.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,26 @@
11
# Changelog
22

3+
## 2.4.0 (2026-03-11)
4+
5+
Full Changelog: [v2.3.2...v2.4.0](https://github.com/togethercomputer/together-py/compare/v2.3.2...v2.4.0)
6+
7+
### Features
8+
9+
* **jig:** move config.dockerfile to config.image.dockerfile_path and add an config.deploy.image option so that you don't have to always pass it as a flag ([#287](https://github.com/togethercomputer/together-py/issues/287)) ([16f64a5](https://github.com/togethercomputer/together-py/commit/16f64a58d8b83f137474ea3eabb31abdc7d38a5f))
10+
11+
12+
### Bug Fixes
13+
14+
* fix autoscaling config usage in jig ([#298](https://github.com/togethercomputer/together-py/issues/298)) ([a3b6657](https://github.com/togethercomputer/together-py/commit/a3b6657efb440bed6cc9f722e54bffd264a95270))
15+
* fixed autoscaling configs in deployments api ([d31204c](https://github.com/togethercomputer/together-py/commit/d31204c3e78340bb362ec8b44da9ee8b09e8f6ac))
16+
* **jig:** deployment tracking ([#300](https://github.com/togethercomputer/together-py/issues/300)) ([f80a2b0](https://github.com/togethercomputer/together-py/commit/f80a2b05ec9c5d917a5a327ac002e44dddd96b84))
17+
* **jig:** send {} for deployment autoscaling to unset if unset in config ([#294](https://github.com/togethercomputer/together-py/issues/294)) ([7657de3](https://github.com/togethercomputer/together-py/commit/7657de3ccc5ef077f8b413f67399d35724af21fd))
18+
19+
20+
### Chores
21+
22+
* fix lints ([#299](https://github.com/togethercomputer/together-py/issues/299)) ([2b35ec4](https://github.com/togethercomputer/together-py/commit/2b35ec46fa2414b14b589b16781c42990e697dd4))
23+
324
## 2.3.2 (2026-03-09)
425

526
Full Changelog: [v2.3.1...v2.3.2](https://github.com/togethercomputer/together-py/compare/v2.3.1...v2.3.2)

examples/tokenize_data.py

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -72,38 +72,56 @@ def pack_sequences(
7272
Sequence 3:
7373
['▁toys', '▁.', '</s>', '<s>', '▁but', '▁just', '▁one', '▁look']
7474
"""
75-
packed_sequences = []
76-
buffer = []
75+
packed_sequences: list[list[int]] = []
76+
packed_position_ids: list[list[int]] = []
77+
buffer: list[int] = []
78+
position_buffer: list[int] = []
7779

7880
for input_ids in batch["input_ids"]:
79-
# Add the current sequence to the buffer
80-
buffer.extend(input_ids)
81-
buffer.append(eos_token_id) # Add EOS at the end of each sequence
81+
# Truncate sequences that individually exceed max_seq_len (including EOS token).
82+
seq_with_eos = (input_ids + [eos_token_id])[:max_seq_len]
83+
# Position IDs reset to 0 at the start of each sub-sequence.
84+
seq_positions = list(range(len(seq_with_eos)))
8285

83-
# Check if buffer needs to be split into chunks
84-
while len(buffer) > max_seq_len:
85-
# Take a full chunk from the buffer and append it to packed_sequences
86-
packed_sequences.append(buffer[:max_seq_len])
87-
# Remove the processed chunk from the buffer
88-
buffer = buffer[max_seq_len:]
86+
# If adding this sequence would overflow, flush the current buffer first.
87+
# This ensures every chunk starts at a sequence boundary (position_ids[0] == 0).
88+
if buffer and len(buffer) + len(seq_with_eos) > max_seq_len:
89+
padding_length = max_seq_len - len(buffer)
90+
packed_sequences.append(buffer + [pad_token_id] * padding_length)
91+
packed_position_ids.append(position_buffer + [0] * padding_length)
92+
buffer = []
93+
position_buffer = []
94+
95+
buffer.extend(seq_with_eos)
96+
position_buffer.extend(seq_positions)
97+
98+
# Flush immediately if exactly full (no padding needed).
99+
if len(buffer) == max_seq_len:
100+
packed_sequences.append(buffer)
101+
packed_position_ids.append(position_buffer)
102+
buffer = []
103+
position_buffer = []
89104

90105
# Add the last buffer if it's exactly chunk_size
91106
if len(buffer) == max_seq_len:
92107
packed_sequences.append(buffer)
108+
packed_position_ids.append(position_buffer)
93109
elif len(buffer) > cutoff_size:
94110
# if the buffer is larger than the cutoff size, pad it to the chunk_size
95111
# if not, we do not include in the packed_sequences
96-
buffer.extend([pad_token_id] * (max_seq_len - len(buffer)))
112+
padding_length = max_seq_len - len(buffer)
113+
buffer.extend([pad_token_id] * padding_length)
114+
position_buffer.extend([0] * padding_length)
97115
packed_sequences.append(buffer)
116+
packed_position_ids.append(position_buffer)
98117

99-
output = {"input_ids": packed_sequences}
118+
output = {"input_ids": packed_sequences, "position_ids": packed_position_ids}
100119
if add_labels:
101120
output["labels"] = [
102121
[LOSS_IGNORE_INDEX if token_id == pad_token_id else token_id for token_id in example]
103122
for example in output["input_ids"]
104123
]
105124

106-
# mask attention for padding tokens, a better version would also mask cross-sequence dependencies
107125
output["attention_mask"] = [
108126
[0 if token_id == pad_token_id else 1 for token_id in example] for example in output["input_ids"]
109127
]

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "together"
3-
version = "2.3.2"
3+
version = "2.4.0"
44
description = "The official Python library for the together API"
55
dynamic = ["readme"]
66
license = "Apache-2.0"

src/together/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
22

33
__title__ = "together"
4-
__version__ = "2.3.2" # x-release-please-version
4+
__version__ = "2.4.0" # x-release-please-version

src/together/lib/cli/api/beta/jig/jig.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class ImageConfig:
7272
cmd: str = "python app.py"
7373
copy: list[str] = field(default_factory=list[str])
7474
auto_include_git: bool = False
75+
dockerfile_path: str = "Dockerfile"
7576

7677
@classmethod
7778
def from_dict(cls, data: dict[str, Any]) -> ImageConfig:
@@ -109,10 +110,11 @@ class DeployConfig:
109110
port: int = 8000
110111
environment_variables: dict[str, str] = field(default_factory=dict[str, str])
111112
command: list[str] | None = None
112-
autoscaling: dict[str, str | float | int] | None = None
113+
autoscaling: dict[str, Union[str, float, int]] = field(default_factory=dict[str, Union[str, float, int]])
113114
health_check_path: str = "/health"
114115
termination_grace_period_seconds: int = 300
115116
volume_mounts: list[VolumeMount] = field(default_factory=list[VolumeMount])
117+
image: str | None = None
116118

117119
@classmethod
118120
def from_dict(cls, data: dict[str, Any]) -> DeployConfig:
@@ -170,7 +172,6 @@ class Config:
170172
"""Main configuration from jig.toml or pyproject.toml"""
171173

172174
model_name: str = ""
173-
dockerfile: str = "Dockerfile"
174175
image: ImageConfig = field(default_factory=ImageConfig)
175176
deploy: DeployConfig = field(default_factory=DeployConfig)
176177
_path: Path = field(default_factory=lambda: Path("pyproject.toml"))
@@ -236,7 +237,6 @@ def load(cls, data: dict[str, Any], path: Path) -> Config:
236237
return cls(
237238
image=ImageConfig.from_dict(jig_config.get("image", {})),
238239
deploy=DeployConfig.from_dict(jig_config.get("deploy", {})),
239-
dockerfile=jig_config.get("dockerfile", "Dockerfile"),
240240
model_name=name,
241241
_path=path,
242242
_unique_name_hint=hint,
@@ -394,7 +394,7 @@ def _generate_dockerfile(config: Config) -> str:
394394

395395
def _dockerfile(config: Config) -> bool:
396396
"""Generate or update managed Dockerfile, returns False if user-managed"""
397-
dockerfile_path = Path(config.dockerfile)
397+
dockerfile_path = Path(config.image.dockerfile_path)
398398
if not dockerfile_path.exists():
399399
dockerfile_path.write_text(_generate_dockerfile(config))
400400
echo("\N{CHECK MARK} Generated Dockerfile")
@@ -570,12 +570,12 @@ def build(self, tag: str = "latest", warmup: bool = False, docker_args: str | No
570570
image = self.image(tag)
571571

572572
if not _dockerfile(self.config):
573-
echo(f"\N{INFORMATION SOURCE} Using existing {self.config.dockerfile} (not managed by jig)")
573+
echo(f"\N{INFORMATION SOURCE} Using existing {self.config.image.dockerfile_path} (not managed by jig)")
574574

575575
echo(f"Building {image}")
576576
cmd = ["docker", "build", "--platform", "linux/amd64", "-t", image, "."]
577-
if self.config.dockerfile != "Dockerfile":
578-
cmd.extend(["-f", self.config.dockerfile])
577+
if self.config.image.dockerfile_path != "Dockerfile":
578+
cmd.extend(["-f", self.config.image.dockerfile_path])
579579

580580
extra_args = docker_args or os.getenv("DOCKER_BUILD_EXTRA_ARGS", "")
581581
if extra_args:
@@ -609,8 +609,10 @@ def deploy(
609609
docker_args: str | None = None,
610610
existing_image: str | None = None,
611611
) -> None:
612-
if existing_image:
613-
deployment_image = existing_image
612+
if deployment_image := existing_image:
613+
echo(f"Deploying provided image {deployment_image}")
614+
elif deployment_image := self.config.deploy.image:
615+
echo(f"Deploying configured image {deployment_image}")
614616
else:
615617
self.build(tag, warmup, docker_args)
616618
self.push(tag)
@@ -822,7 +824,7 @@ def format_status(self, d: Deployment) -> str:
822824
]
823825

824826
if a := d.autoscaling:
825-
lines.append(f" Autoscaling: {a.get('metric', 'N/A')} {a.get('target', 'N/A')} (target)")
827+
lines.append(f" Autoscaling: {a.metric or 'N/A'} {a.target or 'N/A'} (target)")
826828
lines.append(f""" Replicas: {d.ready_replicas}/{d.desired_replicas} ready (min {d.min_replicas}, max {d.max_replicas})
827829
828830
Configuration:""")
@@ -971,7 +973,7 @@ def init() -> None:
971973
def dockerfile(jig: Jig) -> None:
972974
"""Generate Dockerfile"""
973975
if not _dockerfile(jig.config):
974-
msg = f"{jig.config.dockerfile} exists and is not managed by jig. Remove or rename the file to allow jig to manage dockerfile."
976+
msg = f"{jig.config.image.dockerfile_path} exists and is not managed by jig. Remove or rename the file to allow jig to manage dockerfile."
975977
raise JigError(msg)
976978

977979

src/together/lib/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
MAX_BASE64_IMAGE_LENGTH = len("data:image/jpeg;base64,") + 4 * MAX_IMAGE_BYTES // 3
4646

4747
# expected columns for Parquet files
48-
PARQUET_EXPECTED_COLUMNS = ["input_ids", "attention_mask", "labels"]
48+
PARQUET_EXPECTED_COLUMNS = ["input_ids", "attention_mask", "labels", "position_ids"]
4949

5050

5151
class DatasetFormat(enum.Enum):

src/together/resources/beta/jig/jig.py

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from __future__ import annotations
44

5-
from typing import Dict, Iterable
5+
from typing import Iterable
66
from typing_extensions import Literal
77

88
import httpx
@@ -122,7 +122,7 @@ def update(
122122
id: str,
123123
*,
124124
args: SequenceNotStr[str] | Omit = omit,
125-
autoscaling: Dict[str, str] | Omit = omit,
125+
autoscaling: jig_update_params.Autoscaling | Omit = omit,
126126
command: SequenceNotStr[str] | Omit = omit,
127127
cpu: float | Omit = omit,
128128
description: str | Omit = omit,
@@ -155,9 +155,8 @@ def update(
155155
args: Args overrides the container's CMD. Provide as an array of arguments (e.g.,
156156
["python", "app.py"])
157157
158-
autoscaling:
159-
Autoscaling configuration as key-value pairs. Example: {"metric":
160-
"QueueBacklogPerWorker", "target": "10"} to scale based on queue backlog
158+
autoscaling: Autoscaling configuration for the deployment. Omit or set to null to disable
159+
autoscaling
161160
162161
command: Command overrides the container's ENTRYPOINT. Provide as an array (e.g.,
163162
["/bin/sh", "-c"])
@@ -268,7 +267,7 @@ def deploy(
268267
image: str,
269268
name: str,
270269
args: SequenceNotStr[str] | Omit = omit,
271-
autoscaling: Dict[str, str] | Omit = omit,
270+
autoscaling: jig_deploy_params.Autoscaling | Omit = omit,
272271
command: SequenceNotStr[str] | Omit = omit,
273272
cpu: float | Omit = omit,
274273
description: str | Omit = omit,
@@ -303,9 +302,9 @@ def deploy(
303302
args: Args overrides the container's CMD. Provide as an array of arguments (e.g.,
304303
["python", "app.py"])
305304
306-
autoscaling:
307-
Autoscaling configuration as key-value pairs. Example: {"metric":
308-
"QueueBacklogPerWorker", "target": "10"} to scale based on queue backlog
305+
autoscaling: Autoscaling configuration. Example: {"metric": "QueueBacklogPerWorker",
306+
"target": 1.01} to scale based on queue backlog. Omit or set to null to disable
307+
autoscaling
309308
310309
command: Command overrides the container's ENTRYPOINT. Provide as an array (e.g.,
311310
["/bin/sh", "-c"])
@@ -534,7 +533,7 @@ async def update(
534533
id: str,
535534
*,
536535
args: SequenceNotStr[str] | Omit = omit,
537-
autoscaling: Dict[str, str] | Omit = omit,
536+
autoscaling: jig_update_params.Autoscaling | Omit = omit,
538537
command: SequenceNotStr[str] | Omit = omit,
539538
cpu: float | Omit = omit,
540539
description: str | Omit = omit,
@@ -567,9 +566,8 @@ async def update(
567566
args: Args overrides the container's CMD. Provide as an array of arguments (e.g.,
568567
["python", "app.py"])
569568
570-
autoscaling:
571-
Autoscaling configuration as key-value pairs. Example: {"metric":
572-
"QueueBacklogPerWorker", "target": "10"} to scale based on queue backlog
569+
autoscaling: Autoscaling configuration for the deployment. Omit or set to null to disable
570+
autoscaling
573571
574572
command: Command overrides the container's ENTRYPOINT. Provide as an array (e.g.,
575573
["/bin/sh", "-c"])
@@ -680,7 +678,7 @@ async def deploy(
680678
image: str,
681679
name: str,
682680
args: SequenceNotStr[str] | Omit = omit,
683-
autoscaling: Dict[str, str] | Omit = omit,
681+
autoscaling: jig_deploy_params.Autoscaling | Omit = omit,
684682
command: SequenceNotStr[str] | Omit = omit,
685683
cpu: float | Omit = omit,
686684
description: str | Omit = omit,
@@ -715,9 +713,9 @@ async def deploy(
715713
args: Args overrides the container's CMD. Provide as an array of arguments (e.g.,
716714
["python", "app.py"])
717715
718-
autoscaling:
719-
Autoscaling configuration as key-value pairs. Example: {"metric":
720-
"QueueBacklogPerWorker", "target": "10"} to scale based on queue backlog
716+
autoscaling: Autoscaling configuration. Example: {"metric": "QueueBacklogPerWorker",
717+
"target": 1.01} to scale based on queue backlog. Omit or set to null to disable
718+
autoscaling
721719
722720
command: Command overrides the container's ENTRYPOINT. Provide as an array (e.g.,
723721
["/bin/sh", "-c"])

0 commit comments

Comments
 (0)