baseten-loops-tinker 0.1.0__tar.gz

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.
@@ -0,0 +1,10 @@
1
+ .env
2
+ __pycache__/
3
+ *.pyc
4
+ *.pyo
5
+ .venv/
6
+ dist/
7
+ *.egg-info/
8
+ .pytest_cache/
9
+ .mypy_cache/
10
+ .ruff_cache/
@@ -0,0 +1,71 @@
1
+ Metadata-Version: 2.4
2
+ Name: baseten-loops-tinker
3
+ Version: 0.1.0
4
+ Summary: Drop-in tinker compatibility shim backed by the loops SDK
5
+ Requires-Python: >=3.13
6
+ Requires-Dist: baseten-loops>=0.1.0
7
+ Description-Content-Type: text/markdown
8
+
9
+ # loops-tinker
10
+
11
+ Drop-in compatibility shim that provides the `tinker` package namespace backed
12
+ by the `loops` SDK.
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ pip install loops-tinker
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ Existing code that uses `import tinker` works without modification:
23
+
24
+ ```python
25
+ import tinker
26
+
27
+ service_client = tinker.ServiceClient(training_project_id="proj_abc123")
28
+ training_client = service_client.create_lora_training_client(
29
+ base_model="Qwen/Qwen3-8B", rank=16,
30
+ )
31
+ sampling_client = service_client.create_sampling_client(model="Qwen/Qwen3-8B")
32
+ ```
33
+
34
+ All types are also available under `tinker.types`:
35
+
36
+ ```python
37
+ from tinker.types import SamplingParams, Datum, ModelInput
38
+ from tinker.types.tensor_data import TensorData
39
+ ```
40
+
41
+ ## Using with tinker-cookbook
42
+
43
+ `tinker-cookbook` depends on `tinker`, but you can swap in `loops-tinker` using
44
+ uv's `override-dependencies` to prevent the original `tinker` from being installed.
45
+
46
+ First add the override to `pyproject.toml` **before** installing any dependencies
47
+ (there is no CLI command for this). If `tinker-cookbook` is added first, the
48
+ original `tinker` gets installed and its files conflict with `loops-tinker`:
49
+
50
+ ```toml
51
+ [tool.uv]
52
+ override-dependencies = [
53
+ "tinker ; python_version < '0'",
54
+ ]
55
+ ```
56
+
57
+ Then add the dependencies:
58
+
59
+ ```bash
60
+ uv init
61
+ uv add tinker-cookbook
62
+ uv add "loops @ git+https://github.com/basetenlabs/loops#subdirectory=loops"
63
+ uv add "loops-tinker @ git+https://github.com/basetenlabs/loops#subdirectory=loops-tinker"
64
+ ```
65
+
66
+ `loops` is a transitive dep of `loops-tinker` but must be listed directly
67
+ because `[tool.uv.sources]` only applies to direct dependencies. **This won't
68
+ be needed once `loops` is published to PyPI.**
69
+
70
+ The `tinker` namespace will be provided by `loops-tinker` instead of the
71
+ original package.
@@ -0,0 +1,63 @@
1
+ # loops-tinker
2
+
3
+ Drop-in compatibility shim that provides the `tinker` package namespace backed
4
+ by the `loops` SDK.
5
+
6
+ ## Installation
7
+
8
+ ```bash
9
+ pip install loops-tinker
10
+ ```
11
+
12
+ ## Usage
13
+
14
+ Existing code that uses `import tinker` works without modification:
15
+
16
+ ```python
17
+ import tinker
18
+
19
+ service_client = tinker.ServiceClient(training_project_id="proj_abc123")
20
+ training_client = service_client.create_lora_training_client(
21
+ base_model="Qwen/Qwen3-8B", rank=16,
22
+ )
23
+ sampling_client = service_client.create_sampling_client(model="Qwen/Qwen3-8B")
24
+ ```
25
+
26
+ All types are also available under `tinker.types`:
27
+
28
+ ```python
29
+ from tinker.types import SamplingParams, Datum, ModelInput
30
+ from tinker.types.tensor_data import TensorData
31
+ ```
32
+
33
+ ## Using with tinker-cookbook
34
+
35
+ `tinker-cookbook` depends on `tinker`, but you can swap in `loops-tinker` using
36
+ uv's `override-dependencies` to prevent the original `tinker` from being installed.
37
+
38
+ First add the override to `pyproject.toml` **before** installing any dependencies
39
+ (there is no CLI command for this). If `tinker-cookbook` is added first, the
40
+ original `tinker` gets installed and its files conflict with `loops-tinker`:
41
+
42
+ ```toml
43
+ [tool.uv]
44
+ override-dependencies = [
45
+ "tinker ; python_version < '0'",
46
+ ]
47
+ ```
48
+
49
+ Then add the dependencies:
50
+
51
+ ```bash
52
+ uv init
53
+ uv add tinker-cookbook
54
+ uv add "loops @ git+https://github.com/basetenlabs/loops#subdirectory=loops"
55
+ uv add "loops-tinker @ git+https://github.com/basetenlabs/loops#subdirectory=loops-tinker"
56
+ ```
57
+
58
+ `loops` is a transitive dep of `loops-tinker` but must be listed directly
59
+ because `[tool.uv.sources]` only applies to direct dependencies. **This won't
60
+ be needed once `loops` is published to PyPI.**
61
+
62
+ The `tinker` namespace will be provided by `loops-tinker` instead of the
63
+ original package.
@@ -0,0 +1,16 @@
1
+ [project]
2
+ name = "baseten-loops-tinker"
3
+ version = "0.1.0"
4
+ description = "Drop-in tinker compatibility shim backed by the loops SDK"
5
+ readme = "README.md"
6
+ requires-python = ">=3.13"
7
+ dependencies = [
8
+ "baseten-loops>=0.1.0",
9
+ ]
10
+
11
+ [build-system]
12
+ requires = ["hatchling"]
13
+ build-backend = "hatchling.build"
14
+
15
+ [tool.hatch.build.targets.wheel]
16
+ packages = ["tinker"]
@@ -0,0 +1,24 @@
1
+ """Tinker compatibility shim — delegates to the loops SDK.
2
+
3
+ Install ``loops-tinker`` to use existing ``import tinker`` code with the
4
+ loops backend. This package re-exports the loops public API under the
5
+ ``tinker`` namespace so that tinker-cookbook recipes and other tinker-based
6
+ scripts work without modification.
7
+ """
8
+
9
+ from . import types # noqa: F401 — re-export the types subpackage
10
+ from .types import StopReason # noqa: F401
11
+ from ._errors import ( # noqa: F401
12
+ TinkerError,
13
+ APIError,
14
+ APIConnectionError,
15
+ APITimeoutError,
16
+ AuthenticationError,
17
+ BadRequestError,
18
+ RateLimitError,
19
+ )
20
+ from ._service_client import ServiceClient
21
+ from baseten.loops.training_client import TrainingClient # noqa: F401
22
+ from baseten.loops.training_client import OperationFuture as APIFuture
23
+ from baseten.loops.sampling_client import SamplingClient
24
+ from baseten.loops.models import * # noqa: F403
@@ -0,0 +1,34 @@
1
+ """Tinker-compatible exception hierarchy.
2
+
3
+ These mirror the upstream tinker SDK exception classes so that cookbook
4
+ code like ``except tinker.TinkerError`` or ``isinstance(e, tinker.BadRequestError)``
5
+ works against loops-tinker.
6
+ """
7
+
8
+
9
+ class TinkerError(Exception):
10
+ """Base class for all tinker/loops errors."""
11
+
12
+
13
+ class APIError(TinkerError):
14
+ """An error returned by the API."""
15
+
16
+
17
+ class APIConnectionError(APIError):
18
+ """Could not connect to the API."""
19
+
20
+
21
+ class APITimeoutError(APIConnectionError):
22
+ """Request timed out."""
23
+
24
+
25
+ class AuthenticationError(APIError):
26
+ """Invalid API key or credentials."""
27
+
28
+
29
+ class BadRequestError(APIError):
30
+ """The request was malformed."""
31
+
32
+
33
+ class RateLimitError(APIError):
34
+ """Rate limit exceeded."""
@@ -0,0 +1,36 @@
1
+ """Tinker-compatible ServiceClient adapter.
2
+
3
+ Adds ``_async`` method variants that the cookbook expects. These currently
4
+ delegate to the synchronous loops implementations.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import sys
10
+ from typing import Any
11
+
12
+ from baseten.loops.service_client import ServiceClient as _LoopsServiceClient
13
+ from baseten.loops.training_client import TrainingClient
14
+
15
+
16
+ def _warn_user_metadata(user_metadata: dict[str, str] | None) -> None:
17
+ if user_metadata:
18
+ print(
19
+ "loops-tinker: user_metadata is not yet supported and will be ignored",
20
+ file=sys.stderr,
21
+ )
22
+
23
+
24
+ class ServiceClient(_LoopsServiceClient):
25
+ """ServiceClient with async method variants for tinker-cookbook compatibility."""
26
+
27
+ async def create_lora_training_client_async(
28
+ self,
29
+ base_model: str,
30
+ rank: int = 16,
31
+ *,
32
+ user_metadata: dict[str, str] | None = None,
33
+ **kwargs: Any,
34
+ ) -> TrainingClient:
35
+ _warn_user_metadata(user_metadata)
36
+ return self.create_lora_training_client(base_model=base_model, rank=rank, **kwargs)
@@ -0,0 +1 @@
1
+ """Tinker lib compatibility — stubs for tinker.lib subpackages."""
@@ -0,0 +1,3 @@
1
+ from baseten.loops.training_client import OperationFuture as APIFuture
2
+
3
+ __all__ = ["APIFuture"]
@@ -0,0 +1,5 @@
1
+ """Tinker compatibility — re-exports public interfaces."""
2
+
3
+ from baseten.loops.training_client import OperationFuture as APIFuture
4
+
5
+ __all__ = ["APIFuture"]
@@ -0,0 +1,22 @@
1
+ """Tinker types compatibility — re-exports loops model types.
2
+
3
+ Supports ``from tinker import types`` and ``from tinker.types import X``
4
+ patterns used in tinker-cookbook recipes.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Literal, TypeAlias
10
+ from baseten.loops.models import * # noqa: F403
11
+ from tinker.types._image_asset_pointer_chunk import ImageAssetPointerChunk # noqa: F401
12
+
13
+ # Type aliases present in tinker.types but not modelled as classes in loops.
14
+ LossFnType: TypeAlias = Literal[
15
+ "cross_entropy",
16
+ "importance_sampling",
17
+ "ppo",
18
+ "cispo",
19
+ "dro",
20
+ ]
21
+
22
+ StopReason: TypeAlias = Literal["stop", "length"]
@@ -0,0 +1,26 @@
1
+ """Stub for tinker.types.ImageAssetPointerChunk.
2
+
3
+ Used by tinker-cookbook in isinstance checks for VLM data truncation.
4
+ Trainers does not have an equivalent type yet.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Literal
10
+
11
+ from pydantic import BaseModel
12
+
13
+
14
+ class ImageAssetPointerChunk(BaseModel):
15
+ format: Literal["png", "jpeg"]
16
+ location: str
17
+ expected_tokens: int | None = None
18
+ type: Literal["image_asset_pointer"] = "image_asset_pointer"
19
+
20
+ @property
21
+ def length(self) -> int:
22
+ if self.expected_tokens is None:
23
+ raise ValueError(
24
+ "ImageAssetPointerChunk expected_tokens needs to be set in order to compute the length"
25
+ )
26
+ return self.expected_tokens
@@ -0,0 +1,5 @@
1
+ """Compatibility re-export for ``from tinker.types.tensor_data import TensorData``."""
2
+
3
+ from baseten.loops.models import TensorData as TensorData
4
+
5
+ __all__ = ["TensorData"]