Note: This project is mostly LLM-generated with minimal human supervision. Use at your own risk.
Self-hosted Tinker API compatible training service for LoRA adapter training
Open-Tinker is a fully compatible implementation of the Tinker Training API, designed to be a drop-in replacement for the official Tinker service. It enables LoRA (Low-Rank Adaptation) training for large language models using the adapters library.
- ✅ Full Tinker SDK Compatibility: Works seamlessly with the official Tinker Python SDK v0.14.0
- ✅ LoRA Training: Efficient adapter-based fine-tuning using the adapters library
- ✅ Async Operations: Celery-based task queue for background training
- ✅ Checkpoint Management: Save, load, and manage model checkpoints with tinker:// paths
- ✅ REST API: FastAPI-based service with automatic OpenAPI documentation
- ✅ Docker Ready: Easy deployment with Docker and docker-compose
- ✅ Production Ready: PostgreSQL database, Redis task queue, GPU support
- Python 3.12+
- PostgreSQL (for database)
- Redis (for task queue)
- CUDA-capable GPU (recommended for training)
- uv package manager
- Clone the repository
git clone https://github.com/your-org/open-tinker.git
cd open-tinker- Install dependencies with uv
uv sync- Set up environment
cp .env.example .env
# Edit .env with your configuration- Start PostgreSQL and Redis
Using Docker:
docker run -d --name postgres -p 5432:5432 -e POSTGRES_PASSWORD=postgres postgres:16
docker run -d --name redis -p 6379:6379 redis:7- Run the server
# Start the API server
uv run python -m open_tinker.main
# Or with uvicorn directly
uv run uvicorn open_tinker.main:app --host 0.0.0.0 --port 8000 --reload- Start the Celery worker (in a separate terminal)
uv run celery -A open_tinker.workers.celery_app worker --loglevel=infoThe API will be available at http://localhost:8000. Visit http://localhost:8000/docs for the interactive API documentation.
docker-compose up -dThis will start:
- Open-Tinker API server
- Celery worker with GPU support
- PostgreSQL database
- Redis cache
# Build the image
docker build -t open-tinker:latest .
# Run the container
docker run -d \
--name open-tinker-api \
--gpus all \
-p 8000:8000 \
-e DATABASE_URL=postgresql://postgres:postgres@db:5432/opentinker \
-e REDIS_URL=redis://redis:6379/0 \
open-tinker:latestOpen-Tinker targets Tinker SDK v0.14.0. It implements the full Tinker Training API specification and is designed as a drop-in backend for the official SDK. Older SDK versions are not supported.
Open-Tinker is designed to work with the official Tinker SDK v0.14.0:
import tinker
from tinker import types
# Point the SDK to your Open-Tinker instance
service_client = tinker.ServiceClient(
base_url="http://localhost:8000",
api_key="tml-your-api-key",
)
# Check available models
capabilities = service_client.get_server_capabilities()
print("Available models:", [m.model_name for m in capabilities.supported_models])
# Create a LoRA training client
training_client = service_client.create_lora_training_client(
base_model="Qwen/Qwen2.5-0.5B",
rank=32
)
tokenizer = training_client.get_tokenizer()
# Create training data
datum = types.Datum(
model_input=types.ModelInput.from_ints(tokenizer.encode("Hello world")),
loss_fn_inputs={
"target_tokens": types.TensorData.from_ints(tokenizer.encode(" world!")),
"weights": types.TensorData.from_floats([1.0] * len(tokenizer.encode(" world!"))),
}
)
# Forward-backward pass
result = training_client.forward_backward([datum], "cross_entropy").get()
# Optimizer step
training_client.optim_step(
types.AdamParams(learning_rate=1e-4)
).get()
# Save checkpoint
checkpoint_path = training_client.save_state(name="checkpoint-001").get().path
print(f"Checkpoint saved: {checkpoint_path}")
# Create sampling client and generate text
sampling_client = training_client.save_weights_and_get_sampling_client()
prompt = types.ModelInput.from_ints(tokenizer.encode("Hello"))
response = sampling_client.sample(
prompt=prompt,
num_samples=1,
sampling_params=types.SamplingParams(max_tokens=20, temperature=0.7),
).get()
print("Generated:", tokenizer.decode(response.sequences[0].tokens))Configuration is managed through environment variables (.env file). See .env.example for a complete template.
| Variable | Default | Description |
|---|---|---|
API_KEY_PREFIX |
tml- |
Required prefix for API keys |
API_KEYS |
[] |
Explicit list of allowed API keys (empty = any key with valid prefix) |
HOST |
0.0.0.0 |
Server bind address |
PORT |
8000 |
Server port |
DATABASE_URL |
postgresql://postgres:postgres@localhost:5432/opentinker |
PostgreSQL connection string |
REDIS_URL |
redis://localhost:6379/0 |
Redis connection string |
CELERY_BROKER_URL |
redis://localhost:6379/0 |
Celery broker URL |
CELERY_RESULT_BACKEND |
redis://localhost:6379/0 |
Celery result backend URL |
CHECKPOINT_STORAGE_PATH |
./checkpoints |
Path for checkpoint storage |
CHECKPOINT_STORAGE_TYPE |
filesystem |
Storage backend (filesystem or s3) |
MODELS_CACHE_DIR |
./models_cache |
Path for model cache |
SUPPORTED_MODELS |
["Qwen/Qwen2.5-0.5B",...] |
List of supported base models |
CUDA_VISIBLE_DEVICES |
0 |
GPU device(s) to use |
LOG_LEVEL |
INFO |
Logging level |
Open-Tinker implements the full Tinker API specification:
GET /api/v1/healthz- Health checkGET /api/v1/get_server_capabilities- Get supported modelsPOST /api/v1/create_session- Create a new sessionPOST /api/v1/session_heartbeat- Keep a session alive
POST /api/v1/create_model- Create new LoRA training modelPOST /api/v1/forward_backward- Execute forward/backward passPOST /api/v1/forward- Forward-only pass (no gradients)POST /api/v1/optim_step- Apply optimizer stepPOST /api/v1/save_weights- Save training checkpointPOST /api/v1/save_weights_for_sampler- Save weights for samplingPOST /api/v1/load_weights- Load checkpointPOST /api/v1/unload_model- Unload model from memoryPOST /api/v1/get_info- Get model infoPOST /api/v1/weights_info- Get checkpoint info by tinker path
POST /api/v1/create_sampling_session- Create sampling sessionPOST /api/v1/asample- Generate text samples
POST /api/v1/retrieve_future- Poll for async operation result
GET /api/v1/training_runs- List training runsGET /api/v1/training_runs/{training_run_id}- Get a training runGET /api/v1/training_runs/{training_run_id}/checkpoints- List checkpointsDELETE /api/v1/training_runs/{training_run_id}/checkpoints/{checkpoint_id}- Delete checkpointGET /api/v1/training_runs/{training_run_id}/checkpoints/{checkpoint_id}/archive- Download checkpointPOST /api/v1/training_runs/{training_run_id}/checkpoints/{checkpoint_id}/publish- Publish checkpointDELETE /api/v1/training_runs/{training_run_id}/checkpoints/{checkpoint_id}/publish- Unpublish checkpointPUT /api/v1/training_runs/{training_run_id}/checkpoints/{checkpoint_id}/ttl- Set checkpoint TTLGET /api/v1/checkpoints- List all checkpointsGET /api/v1/sessions- List sessionsGET /api/v1/sessions/{session_id}- Get session detailsGET /api/v1/samplers/{sampler_id}- Get sampler details
POST /api/v1/telemetry- Accept SDK telemetry (no-op stub)
See the API documentation for complete details.
# Install dev dependencies
uv sync --extra dev
# Run tests
uv run pytest
# Run with coverage
uv run pytest --cov=open_tinker --cov-report=htmlThis project uses Ruff for both formatting and linting.
# Format code
uv run ruff format src/ tests/
# Lint code
uv run ruff check src/ tests/
# Lint and auto-fix issues
uv run ruff check --fix src/ tests/┌─────────────────┐
│ Tinker SDK │
│ (Client) │
└────────┬────────┘
│ HTTP/REST
▼
┌─────────────────────────────────────────┐
│ FastAPI Application │
│ ┌─────────────────────────────────┐ │
│ │ API Routes (Training/Sampling) │ │
│ └─────────────┬───────────────────┘ │
│ │ │
│ ┌─────────────▼───────────────────┐ │
│ │ Authentication Middleware │ │
│ └─────────────┬───────────────────┘ │
└────────────────┼─────────────────────────┘
│
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌─────────┐
│ DB │ │ Redis │ │ Celery │
│ (PG) │ │ (Queue)│ │ Workers │
└────────┘ └────────┘ └────┬────┘
│
▼
┌──────────────────┐
│ Training Engine │
│ (adapters lib) │
└──────────────────┘
│
▼
┌──────────────────┐
│ GPU / Models │
└──────────────────┘
Contributions are welcome! Please read our contributing guidelines and code of conduct.
- Tinker - Original API specification
- adapters - LoRA training backend
- FastAPI - Web framework
- Celery - Task queue
- Documentation: http://localhost:8000/docs
- Issues: GitHub Issues