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.
- baseten_loops_tinker-0.1.0/.gitignore +10 -0
- baseten_loops_tinker-0.1.0/PKG-INFO +71 -0
- baseten_loops_tinker-0.1.0/README.md +63 -0
- baseten_loops_tinker-0.1.0/pyproject.toml +16 -0
- baseten_loops_tinker-0.1.0/tinker/__init__.py +24 -0
- baseten_loops_tinker-0.1.0/tinker/_errors.py +34 -0
- baseten_loops_tinker-0.1.0/tinker/_service_client.py +36 -0
- baseten_loops_tinker-0.1.0/tinker/lib/__init__.py +1 -0
- baseten_loops_tinker-0.1.0/tinker/lib/public_interfaces/__init__.py +3 -0
- baseten_loops_tinker-0.1.0/tinker/lib/public_interfaces.py +5 -0
- baseten_loops_tinker-0.1.0/tinker/types/__init__.py +22 -0
- baseten_loops_tinker-0.1.0/tinker/types/_image_asset_pointer_chunk.py +26 -0
- baseten_loops_tinker-0.1.0/tinker/types/tensor_data.py +5 -0
|
@@ -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,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
|