Metadata-Version: 2.5
Name: baseten-loops-tinker
Version: 0.18.0
Summary: Drop-in tinker compatibility shim backed by the loops SDK
License-Expression: MIT
License-File: LICENSE
Requires-Python: >=3.12
Requires-Dist: baseten-loops>=0.1.0
Description-Content-Type: text/markdown

# loops-tinker

Drop-in compatibility shim that provides the `tinker` package namespace backed
by the `loops` SDK.

## Installation

```bash
pip install loops-tinker
```

## Usage

Existing code that uses `import tinker` works without modification:

```python
import tinker

service_client = tinker.ServiceClient(training_project_id="proj_abc123")
training_client = service_client.create_lora_training_client(
    base_model="Qwen/Qwen3-8B", rank=16,
)
sampling_client = service_client.create_sampling_client(model="Qwen/Qwen3-8B")
```

All types are also available under `tinker.types`:

```python
from tinker.types import SamplingParams, Datum, ModelInput
from tinker.types.tensor_data import TensorData
```

## Using with tinker-cookbook

`tinker-cookbook` depends on `tinker`, but you can swap in `loops-tinker` using
uv's `override-dependencies` to prevent the original `tinker` from being installed.

First add the override to `pyproject.toml` **before** installing any dependencies
(there is no CLI command for this). If `tinker-cookbook` is added first, the
original `tinker` gets installed and its files conflict with `loops-tinker`:

```toml
[tool.uv]
override-dependencies = [
    "tinker ; python_version < '0'",
]
```

Then add the dependencies:

```bash
uv init
uv add tinker-cookbook
uv add "loops @ git+https://github.com/basetenlabs/loops#subdirectory=loops"
uv add "loops-tinker @ git+https://github.com/basetenlabs/loops#subdirectory=loops-tinker"
```

`loops` is a transitive dep of `loops-tinker` but must be listed directly
because `[tool.uv.sources]` only applies to direct dependencies. **This won't
be needed once `loops` is published to PyPI.**

The `tinker` namespace will be provided by `loops-tinker` instead of the
original package.

## Token provenance

Enable recording when creating the sampling client, as in Tinker:

```python
sampling_client = training_client.save_weights_and_get_sampling_client(
    record_stability_info=True,
)
response = await sampling_client.sample_async(
    prompt=prompt,
    num_samples=1,
    sampling_params=sampling_params,
    include_routed_experts=True,
)
sequence_id = response.sequences[0].sequence_id
```

`record_stability_info` defaults to `False`. Both sync and async versions of
`ServiceClient.create_sampling_client`, `TrainingClient.create_sampling_client`,
and `TrainingClient.save_weights_and_get_sampling_client` accept it. Every sample
from that client records data; there is no per-sample recording option.

Attach `PromptProvenanceSpan` and `SampledProvenanceSpan` references with
`Datum.with_provenance(model_input=..., loss_fn_inputs=...)`. The two lists tile
the input tokens and target-token rows respectively. Token data stays on the
server; the client passes only sequence references and spans.

Paired clients share the trainer's run and session. Standalone clients record
under their service session; trainers in that same session can consume those
references. The sampler must support route capture and the trainer must enable
R3 replay. `include_routed_experts=True` requests the route payload; it is a
Loops extension. The recording interface matches Tinker, but StableReinforce
and top-k recording are not implemented.

Retention differs from Tinker: Loops stores generic sampling records and payloads
in S3 or Cannery without implementing Tinker's inactivity expiry. Retention is
controlled by storage lifecycle policies, not the client session lifetime.
These records support R3; they are not StableReinforce stability artifacts.

Training references use `Datum.with_provenance(...)` exclusively. Route payload
locations are stored in sequence records, not returned on `SampledSequence`.
`include_routed_experts=True` requires a client created with
`record_stability_info=True`; it selects the `moe.routes` payload for that record.

Recording uses the existing service session, independently of sampler affinity.
See the [native SDK provenance requirements](../README.md#token-provenance) for
the server versions provenance needs.
