tuft 0.1.0__py3-none-any.whl → 0.1.1__py3-none-any.whl

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,633 @@
1
+ Metadata-Version: 2.4
2
+ Name: tuft
3
+ Version: 0.1.1
4
+ Summary: A multi-tenant fine-tuning platform for LLMs with Tinker-compatible API
5
+ Author-email: TuFT Developers <tuft@list.alibaba-inc.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 agentscope-ai
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+ License-File: LICENSE
28
+ Requires-Python: >=3.11
29
+ Requires-Dist: fastapi>=0.125.0
30
+ Requires-Dist: httpx>=0.28.1
31
+ Requires-Dist: numpy<2.0.0
32
+ Requires-Dist: omegaconf>=2.3.0
33
+ Requires-Dist: opentelemetry-api>=1.20.0
34
+ Requires-Dist: opentelemetry-exporter-otlp>=1.20.0
35
+ Requires-Dist: opentelemetry-instrumentation-fastapi>=0.41b0
36
+ Requires-Dist: opentelemetry-instrumentation-logging>=0.41b0
37
+ Requires-Dist: opentelemetry-sdk>=1.20.0
38
+ Requires-Dist: psutil>=5.9.0
39
+ Requires-Dist: pynvml>=11.5.0
40
+ Requires-Dist: ray>=2.50.0
41
+ Requires-Dist: tinker>=0.7.0
42
+ Requires-Dist: transformers<5.0.0,>=4.57.3
43
+ Requires-Dist: typer>=0.20.1
44
+ Requires-Dist: uvicorn[standard]>=0.38.0
45
+ Provides-Extra: backend
46
+ Requires-Dist: datasets>=4.0.0; extra == 'backend'
47
+ Requires-Dist: huggingface-hub<1.0,>=0.20.0; extra == 'backend'
48
+ Requires-Dist: peft>=0.18.0; extra == 'backend'
49
+ Requires-Dist: trinity-rft[vllm]>=0.4.1; extra == 'backend'
50
+ Provides-Extra: dev
51
+ Requires-Dist: detect-secrets>=1.5.0; extra == 'dev'
52
+ Requires-Dist: nbqa>=1.9.1; extra == 'dev'
53
+ Requires-Dist: pre-commit>=4.5.1; extra == 'dev'
54
+ Requires-Dist: pyright>=1.1.408; extra == 'dev'
55
+ Requires-Dist: pytest-asyncio>=1.3.0; extra == 'dev'
56
+ Requires-Dist: pytest-json-ctrf; extra == 'dev'
57
+ Requires-Dist: pytest>=9.0.2; extra == 'dev'
58
+ Requires-Dist: ruff>=0.14.14; extra == 'dev'
59
+ Provides-Extra: persistence
60
+ Requires-Dist: redis>=5.0.0; extra == 'persistence'
61
+ Description-Content-Type: text/markdown
62
+
63
+ <div align="center">
64
+ <img src="assets/tuft-logo-colorful.svg" alt="TuFT Logo" width="400"/>
65
+ </div>
66
+
67
+ TuFT (**T**enant-**u**nified **F**ine**T**uning) is a multi-tenant platform that lets multiple users fine-tune LLMs on shared infrastructure through a unified API. Access it via the Tinker SDK or compatible clients.
68
+
69
+ Check out our [roadmap](#roadmap) to see what we're building next.
70
+
71
+ We're open source and welcome contributions! Join the community:
72
+ - [DingTalk Group](https://qr.dingtalk.com/action/joingroup?code=v1,k1,UWvzO6HHSeuvRQ5WXCOMJEijadQV+hDjhMIpiVr8qCs=&_dt_no_comment=1&origin=11?)
73
+ - [Discord](https://discord.gg/wEahC7ZJ)
74
+
75
+ ## Table of Contents
76
+
77
+ - [Quick Install](#quick-install)
78
+ - [Quick Start Example](#quick-start-example)
79
+ - [Installation](#installation)
80
+ - [Use the Pre-built Docker Image](#use-the-pre-built-docker-image)
81
+ - [User Guide](#user-guide)
82
+ - [Persistence](#persistence)
83
+ - [Observability (OpenTelemetry)](#observability-opentelemetry)
84
+ - [Architecture](#architecture)
85
+ - [Roadmap](#roadmap)
86
+ - [Development](#development)
87
+
88
+ ## Quick Install
89
+
90
+ > **Note**: This script supports unix platforms. For other platforms, see [Installation](#installation).
91
+
92
+ Install TuFT with a single command:
93
+
94
+ ```bash
95
+ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/agentscope-ai/tuft/main/scripts/install.sh)"
96
+ ```
97
+
98
+ This installs TuFT with full backend support (GPU dependencies, persistence, flash-attn) and a bundled Python environment to `~/.tuft`. After installation, restart your terminal and run:
99
+
100
+ ```bash
101
+ tuft
102
+ ```
103
+
104
+ ## Quick Start Example
105
+
106
+ This example demonstrates how to use TuFT for training and sampling with the [Tinker SDK](https://pypi.org/project/tinker/).
107
+ Make sure the server is running on port 10610 before running the code. See the [Run the server](#run-the-server) section below for instructions on starting the server.
108
+
109
+ ### 1. Data Preparation
110
+
111
+ Prepare your training data in the format expected by TuFT:
112
+
113
+ ```python
114
+ import tinker
115
+ from tinker import types
116
+
117
+ # Connect to the running TuFT server
118
+ client = tinker.ServiceClient(base_url="http://localhost:10610", api_key="local-dev-key")
119
+
120
+ # Discover available base models
121
+ capabilities = client.get_server_capabilities()
122
+ base_model = capabilities.supported_models[0].model_name
123
+
124
+ print("Supported models:")
125
+ for model in capabilities.supported_models:
126
+ print("-", model.model_name or "(unknown)")
127
+
128
+ # Prepare training data
129
+ # In practice, you would use a tokenizer:
130
+ # tokenizer = training.get_tokenizer()
131
+ # prompt_tokens = tokenizer.encode("Hello from TuFT")
132
+ # target_tokens = tokenizer.encode(" Generalizing beyond the prompt")
133
+
134
+ # For this example, we use fake token IDs
135
+ prompt_tokens = [101, 42, 37, 102]
136
+ target_tokens = [101, 99, 73, 102]
137
+
138
+ datum = types.Datum(
139
+ model_input=types.ModelInput.from_ints(prompt_tokens),
140
+ loss_fn_inputs={
141
+ "target_tokens": types.TensorData(
142
+ data=target_tokens,
143
+ dtype="int64",
144
+ shape=[len(target_tokens)]
145
+ ),
146
+ "weights": types.TensorData(data=[1.0, 1.0, 1.0, 1.0], dtype="float32", shape=[4])
147
+ },
148
+ )
149
+ ```
150
+
151
+ **Example Output:**
152
+ ```
153
+ Supported models:
154
+ - Qwen/Qwen3-4B
155
+ - Qwen/Qwen3-8B
156
+ ```
157
+
158
+ ### 2. Training
159
+
160
+ Create a LoRA training client and perform forward/backward passes with optimizer steps:
161
+
162
+ ```python
163
+ # Create a LoRA training client
164
+ training = client.create_lora_training_client(base_model=base_model, rank=8)
165
+
166
+ # Run forward/backward pass
167
+ fwdbwd = training.forward_backward([datum], "cross_entropy").result(timeout=30)
168
+ print("Loss metrics:", fwdbwd.metrics)
169
+
170
+ # Apply optimizer update
171
+ optim = training.optim_step(types.AdamParams(learning_rate=1e-4)).result(timeout=30)
172
+ print("Optimizer metrics:", optim.metrics)
173
+ ```
174
+
175
+ **Example Output:**
176
+ ```
177
+ Loss metrics: {'loss:sum': 2.345, 'step:max': 0.0, 'grad_norm:mean': 0.123}
178
+ Optimizer metrics: {'learning_rate:mean': 0.0001, 'step:max': 1.0, 'update_norm:mean': 0.045}
179
+ ```
180
+
181
+ ### 3. Save Checkpoint
182
+
183
+ Save the trained model checkpoint and sampler weights:
184
+
185
+ ```python
186
+ # Save checkpoint for training resumption
187
+ checkpoint = training.save_state("demo-checkpoint").result(timeout=60)
188
+ print("Checkpoint saved to:", checkpoint.path)
189
+
190
+ # Save sampler weights for inference
191
+ sampler_weights = training.save_weights_for_sampler("demo-sampler").result(timeout=60)
192
+ print("Sampler weights saved to:", sampler_weights.path)
193
+
194
+ # Inspect session information
195
+ rest = client.create_rest_client()
196
+ session_id = client.holder.get_session_id()
197
+ session_info = rest.get_session(session_id).result(timeout=30)
198
+ print("Session contains training runs:", session_info.training_run_ids)
199
+ ```
200
+
201
+ **Example Output:**
202
+ ```
203
+ Checkpoint saved to: tinker://550e8400-e29b-41d4-a716-446655440000/weights/checkpoint-001
204
+ Sampler weights saved to: tinker://550e8400-e29b-41d4-a716-446655440000/sampler_weights/sampler-001
205
+ Session contains training runs: ['550e8400-e29b-41d4-a716-446655440000']
206
+ ```
207
+
208
+ ### 4. Sampling
209
+
210
+ Load the saved weights and generate tokens:
211
+
212
+ ```python
213
+ # Create a sampling client with saved weights
214
+ sampling = client.create_sampling_client(model_path=sampler_weights.path)
215
+
216
+ # Prepare prompt for sampling
217
+ # sample_prompt = tokenizer.encode("Tell me something inspiring.")
218
+ sample_prompt = [101, 57, 12, 7, 102]
219
+
220
+ # Generate tokens
221
+ sample = sampling.sample(
222
+ prompt=types.ModelInput.from_ints(sample_prompt),
223
+ num_samples=1,
224
+ sampling_params=types.SamplingParams(max_tokens=5, temperature=0.5),
225
+ ).result(timeout=30)
226
+
227
+ if sample.sequences:
228
+ print("Sample tokens:", sample.sequences[0].tokens)
229
+ # Decode tokens to text:
230
+ # sample_text = tokenizer.decode(sample.sequences[0].tokens)
231
+ # print("Generated text:", sample_text)
232
+ ```
233
+
234
+ **Example Output:**
235
+ ```
236
+ Sample tokens: [101, 57, 12, 7, 42, 102]
237
+ ```
238
+
239
+ > **Note**: Replace fake token IDs with actual tokenizer calls when you have a tokenizer available locally.
240
+
241
+ ## Installation
242
+
243
+ > **Tip**: For a quick one-command setup, see [Quick Install](#quick-install). This section is for users who prefer to manage their own Python environment or need more control over the installation.
244
+
245
+ We recommend using [uv](https://github.com/astral-sh/uv) for dependency management.
246
+
247
+ ### Install from Source Code
248
+
249
+ 1. Clone the repository:
250
+
251
+ ```bash
252
+ git clone https://github.com/agentscope-ai/TuFT
253
+ ```
254
+
255
+ 2. Create a virtual environment:
256
+
257
+ ```bash
258
+ cd TuFT
259
+ uv venv --python 3.12
260
+ ```
261
+
262
+ 3. Activate environment:
263
+
264
+ ```bash
265
+ source .venv/bin/activate
266
+ ```
267
+
268
+ 4. Install dependencies:
269
+
270
+ ```bash
271
+ # Install minimal dependencies for non-development installs
272
+ uv sync
273
+
274
+ # If you need to develop or run tests, install dev dependencies
275
+ uv sync --extra dev
276
+
277
+ # If you want to run the full feature set (e.g., model serving, persistence),
278
+ # please install all dependencies
279
+ uv sync --all-extras
280
+ python scripts/install_flash_attn.py
281
+ # If you face issues with flash-attn installation, you can try installing it manually:
282
+ # uv pip install flash-attn --no-build-isolation
283
+ ```
284
+
285
+
286
+
287
+ ### Install via PyPI
288
+
289
+ You can also install TuFT directly from PyPI:
290
+
291
+ ```bash
292
+ uv pip install tuft
293
+
294
+ # Install optional dependencies as needed
295
+ uv pip install "tuft[dev,backend,persistence]"
296
+ ```
297
+
298
+ ### Run the server
299
+
300
+ The CLI starts a FastAPI server:
301
+
302
+ ```bash
303
+ tuft --port 10610 --config /path/to/tuft_config.yaml
304
+ ```
305
+
306
+ The config file `tuft_config.yaml` specifies server settings including available base models, authentication, persistence, and telemetry. Below is a minimal example.
307
+
308
+ ```yaml
309
+ supported_models:
310
+ - model_name: Qwen/Qwen3-4B
311
+ model_path: Qwen/Qwen3-4B
312
+ max_model_len: 32768
313
+ tensor_parallel_size: 1
314
+ - model_name: Qwen/Qwen3-8B
315
+ model_path: Qwen/Qwen3-8B
316
+ max_model_len: 32768
317
+ tensor_parallel_size: 1
318
+ ```
319
+
320
+ See [`config/tuft_config.example.yaml`](config/tuft_config.example.yaml) for a complete example configuration with all available options.
321
+
322
+ ## Use the Pre-built Docker Image
323
+
324
+ If you face issues with local installation or want to get started quickly,
325
+ you can use the pre-built Docker image.
326
+
327
+ 1. Pull the latest image from GitHub Container Registry:
328
+
329
+ ```bash
330
+ docker pull ghcr.io/agentscope-ai/tuft:latest
331
+ ```
332
+
333
+ 2. Run the Docker container and start the TuFT server on port 10610:
334
+
335
+ ```bash
336
+ docker run -it \
337
+ --gpus all \
338
+ --shm-size="128g" \
339
+ --rm \
340
+ -p 10610:10610 \
341
+ -v <host_dir>:/data \
342
+ ghcr.io/agentscope-ai/tuft:latest \
343
+ tuft --port 10610 --config /data/tuft_config.yaml
344
+ ```
345
+
346
+ Please replace `<host_dir>` with a directory on your host machine where you want to store model checkpoints and other data.
347
+ Suppose you have the following structure on your host machine:
348
+
349
+ ```plaintext
350
+ <host_dir>/
351
+ ├── checkpoints/
352
+ ├── Qwen3-4B/
353
+ ├── Qwen3-8B/
354
+ └── tuft_config.yaml
355
+ ```
356
+
357
+ The `tuft_config.yaml` file defines the server configuration, for example:
358
+ ```yaml
359
+ supported_models:
360
+ - model_name: Qwen/Qwen3-4B
361
+ model_path: /data/Qwen3-4B
362
+ max_model_len: 32768
363
+ tensor_parallel_size: 1
364
+ - model_name: Qwen/Qwen3-8B
365
+ model_path: /data/Qwen3-8B
366
+ max_model_len: 32768
367
+ tensor_parallel_size: 1
368
+ ```
369
+
370
+ ## User Guide
371
+ We provide practical examples to demonstrate how to use TuFT for training and sampling. The guides below cover both Supervised Fine-Tuning and Reinforcement Learning workflows, with links to runnable notebooks.
372
+
373
+ | Dataset | Task | Guide | Example |
374
+ |---|---|---|---|
375
+ | [no_robots](https://huggingface.co/datasets/HuggingFaceH4/no_robots) | Supervised Fine-Tuning (SFT) | [chat_sft.md](docs/chat_sft.md) | [chat_sft.ipynb](examples/chat_sft.ipynb) |
376
+ | [Countdown](https://huggingface.co/datasets/Jiayi-Pan/Countdown-Tasks-3to4) | Reinforcement Learning (RL) | [countdown_rl.md](docs/countdown_rl.md) | [countdown_rl.ipynb](examples/countdown_rl.ipynb) |
377
+
378
+
379
+ ## Persistence
380
+
381
+ TuFT supports optional Redis-based persistence for server state. When enabled,
382
+ the server can recover sessions, training runs, and pending futures after a restart.
383
+
384
+ To use persistence, install the optional dependency:
385
+
386
+ ```bash
387
+ uv pip install tuft[persistence]
388
+ ```
389
+
390
+ ### Persistence Modes
391
+
392
+ TuFT provides three persistence modes:
393
+
394
+ | Mode | Description | Use Case |
395
+ |------|-------------|----------|
396
+ | `disabled` | No persistence, data in-memory only | Development, testing without state recovery |
397
+ | `redis_url` | External Redis server | Production, multi-instance deployments |
398
+ | `file_redis` | File-backed store | Demos, small-scale testing |
399
+
400
+ ### Configuration
401
+
402
+ Add a `persistence` section to your `tuft_config.yaml` configuration file and choose one of the following modes.
403
+
404
+ #### Mode 1: Disabled (Default)
405
+
406
+ No configuration needed. All data is stored in memory and lost on restart.
407
+
408
+ ```yaml
409
+ # tuft_config.yaml
410
+ persistence:
411
+ mode: disabled
412
+ ```
413
+
414
+ #### Mode 2: External Redis Server
415
+
416
+ Use an external Redis server for production deployments:
417
+
418
+ ```yaml
419
+ # tuft_config.yaml
420
+ persistence:
421
+ mode: redis_url
422
+ redis_url: "redis://localhost:6379/0"
423
+ namespace: "tuft"
424
+ ```
425
+
426
+ You can start a local Redis instance using Docker:
427
+
428
+ ```bash
429
+ docker run -d --name TuFT-redis -p 6379:6379 redis:7-alpine
430
+ ```
431
+
432
+ #### Mode 3: File-backed Store
433
+
434
+ Use the file-backed store for demos or small-scale testing:
435
+
436
+ ```yaml
437
+ # tuft_config.yaml
438
+ persistence:
439
+ mode: file_redis
440
+ file_path: "~/.cache/tuft/file_redis.json"
441
+ namespace: "tuft"
442
+ ```
443
+
444
+ ## Observability (OpenTelemetry)
445
+
446
+ TuFT supports optional OpenTelemetry integration for distributed tracing, metrics, and logging.
447
+ This allows you to monitor your TuFT server using observability tools like SigNoz, Jaeger, or Grafana.
448
+
449
+ ### Configuration
450
+
451
+ Add the following `telemetry` section to your `tuft_config.yaml` configuration file:
452
+
453
+ ```yaml
454
+ # tuft_config.yaml
455
+ telemetry:
456
+ enabled: true
457
+ service_name: tuft
458
+ otlp_endpoint: http://localhost:4317 # Your OTLP collector endpoint
459
+ resource_attributes: {}
460
+ # example:
461
+ # deployment.environment: production
462
+ # service.version: 1.0.0
463
+ # service.namespace: my-namespace
464
+ ```
465
+
466
+ Alternatively, use environment variables:
467
+
468
+ ```bash
469
+ export TUFT_OTLP_ENDPOINT=http://localhost:4317
470
+ export TUFT_OTEL_DEBUG=1 # Enable console exporter for debugging
471
+ ```
472
+
473
+ ## Architecture
474
+
475
+ TuFT provides a unified service API for agentic model training and sampling. The system supports multiple LoRA adapters per base model and checkpoint management.
476
+
477
+ ```mermaid
478
+ graph TB
479
+ subgraph Client["Client Layer"]
480
+ SDK[Tinker SDK Client]
481
+ end
482
+
483
+ subgraph API["TuFT Service API"]
484
+ REST[Service API<br/>REST/HTTP]
485
+ Session[Session Management]
486
+ end
487
+
488
+ subgraph Backend["Backend Layer"]
489
+ Training[Training Backend<br/>Forward/Backward/Optim Step]
490
+ Sampling[Sampling Backend<br/>Token Generation]
491
+ end
492
+
493
+ subgraph Models["Model Layer"]
494
+ BaseModel[Base LLM Model]
495
+ LoRA[LoRA Adapters<br/>Multiple per Base Model]
496
+ end
497
+
498
+ subgraph Storage["Storage"]
499
+ Checkpoint[Model Checkpoints<br/>& LoRA Weights]
500
+ end
501
+
502
+ SDK --> REST
503
+ REST --> Session
504
+ Session --> Training
505
+ Session --> Sampling
506
+ Training --> BaseModel
507
+ Training --> LoRA
508
+ Sampling --> BaseModel
509
+ Sampling --> LoRA
510
+ Training --> Checkpoint
511
+ Sampling --> Checkpoint
512
+ ```
513
+
514
+ ### Key Components
515
+
516
+ - **Service API**: RESTful interface for training and sampling operations
517
+ - **Training Backend**: Handles forward/backward passes and optimizer steps for LoRA fine-tuning
518
+ - **Sampling Backend**: Generates tokens from trained models
519
+ - **Checkpoint Storage**: Manages model checkpoints and LoRA weights
520
+
521
+
522
+
523
+ ## Roadmap
524
+
525
+ ### Core Focus: Post-Training for Agent Scenarios
526
+
527
+ We focus on post-training for agentic models. The rollout phase in RL training involves reasoning, multi-turn conversations, and tool use, which tends to be asynchronous relative to the training phase. We aim to improve the throughput and resource efficiency of the overall system, building tools that are easy to use and integrate into existing workflows.
528
+
529
+ ### Architecture & Positioning
530
+
531
+ - **Horizontal platform**: Not a vertically integrated fine-tuning solution, but a flexible platform that plugs into different training frameworks and compute infrastructures
532
+ - **Code-first API**: Connects agentic training workflows with compute infrastructure through programmatic interfaces
533
+ - **Layer in AI stack**: Sits above the infrastructure layer (Kubernetes, cloud platforms, GPU clusters), integrating with training frameworks (PeFT, FSDP, vLLM, DeepSpeed) as implementation dependencies
534
+ - **Integration approach**: Works with existing ecosystems rather than replacing them
535
+
536
+ ### Near-Term (3 months)
537
+
538
+ - **Multi-machine, multi-GPU training**: Support distributed architectures using PeFT, FSDP, vLLM, DeepSpeed, etc.
539
+ - **Cloud-native deployment**: Integration with AWS, Alibaba Cloud, GCP, Azure and Kubernetes orchestration
540
+ - **Observability**: Monitoring system with real-time logs, GPU metrics, training progress, and debugging tools
541
+ - **Serverless GPU**: Lightweight runtime for diverse deployment scenarios, with multi-user and multi-tenant GPU resource sharing to improve utilization efficiency
542
+
543
+ ### Long-Term (6 months)
544
+
545
+ - **Environment-driven learning loop**: Standardized interfaces with WebShop, MiniWob++, BrowserEnv, Voyager and other agent training environments
546
+ - **Automated pipeline**: Task execution → feedback collection → data generation → model updates
547
+ - **Advanced RL paradigms**: RLAIF, Error Replay, and environment feedback mechanisms
548
+ - **Simulation sandboxes**: Lightweight local environments for rapid experimentation
549
+
550
+ ### Open Collaboration: We are Looking for Collaborators
551
+
552
+ This roadmap is not fixed, but rather a starting point for our journey with the open source community. Every feature design will be implemented through GitHub Issue discussions, PRs, and prototype validation. We sincerely welcome you to propose real-world use cases, performance bottlenecks, or innovative ideas—it is these voices that will collectively define the future of Agent post-training.
553
+
554
+ We welcome suggestions and contributions from the community! Join us on:
555
+ - [DingTalk Group](https://qr.dingtalk.com/action/joingroup?code=v1,k1,UWvzO6HHSeuvRQ5WXCOMJEijadQV+hDjhMIpiVr8qCs=&_dt_no_comment=1&origin=11?)
556
+ - [Discord](https://discord.gg/wEahC7ZJ) (on AgentScope's Server)
557
+
558
+ ## Development
559
+
560
+ ### Setup Development Environment
561
+
562
+ 1. Install [uv](https://github.com/astral-sh/uv) if you haven't already:
563
+
564
+ ```bash
565
+ curl -LsSf https://astral.sh/uv/install.sh | sh
566
+ ```
567
+
568
+ 2. Install dev dependencies:
569
+
570
+ ```bash
571
+ uv sync --extra dev
572
+ ```
573
+
574
+ 3. Set up pre-commit hooks:
575
+
576
+ ```bash
577
+ uv run pre-commit install
578
+ ```
579
+
580
+ ### Running Tests
581
+
582
+ ```bash
583
+ uv run pytest
584
+ ```
585
+
586
+ To skip integration tests:
587
+
588
+ ```bash
589
+ uv run pytest -m "not integration"
590
+ ```
591
+
592
+ For detailed testing instructions, including GPU tests, persistence testing, and writing new tests, see the [Testing Guide](docs/how_to_write_tests.md).
593
+
594
+ ### Linting and Type Checking
595
+
596
+ Run the linter:
597
+
598
+ ```bash
599
+ uv run ruff check .
600
+ uv run ruff format .
601
+ ```
602
+
603
+ Run the type checker:
604
+
605
+ ```bash
606
+ uv run pyright
607
+ ```
608
+
609
+ ### Notebook Linting
610
+
611
+ For Jupyter notebooks:
612
+
613
+ ```bash
614
+ uv run nbqa ruff notebooks/
615
+ ```
616
+
617
+ ### Secret Detection
618
+
619
+ Scan and update the secrets baseline:
620
+
621
+ ```bash
622
+ uv run detect-secrets scan > .secrets.baseline
623
+ ```
624
+
625
+ Audit detected secrets to mark false positives:
626
+
627
+ ```bash
628
+ uv run detect-secrets audit .secrets.baseline
629
+ ```
630
+
631
+ ### Contributing
632
+
633
+ Please ensure all tests pass and pre-commit hooks succeed before creating new PRs.
@@ -0,0 +1,35 @@
1
+ tuft/__init__.py,sha256=BJu6iJ_QGwcJXRXDgR1LjV25KgM6sVd7_WqIXVTEuVM,97
2
+ tuft/auth.py,sha256=2Wk9ATXlAiGm1Irpj66CfIyORuHzciSNAOzVwM8PeO0,1071
3
+ tuft/backend.py,sha256=ftiaaNds2MXroszZW8l6DEq515qiw1KmrODI3x6AHE4,10254
4
+ tuft/checkpoints.py,sha256=bObo2NzDrfzp5BiS6I_FIA3frLFic_sT4o4c-PEzfpk,6917
5
+ tuft/cli.py,sha256=PJ89JfrJ7wB5Zd-pe9rkWLcfavmWRtWLmQ_r1Y_Qdwk,2725
6
+ tuft/config.py,sha256=EGkDmnYNNHgtkEuffHoBE9R-hc2epAJe4sUEVBP_6Ug,4292
7
+ tuft/exceptions.py,sha256=_xdsL8bx3Y6jvC5VYHVCa73uAEWXxcl2YwVc09lJXFk,4088
8
+ tuft/futures.py,sha256=0gRLgDJJQRGGmULYsKdUs3VDsrLN8QfuFfXV00kxHO4,16375
9
+ tuft/sampling_controller.py,sha256=WIQ29aVD9JWuxZ8JV4a71nYZXh8Es2wtA4QhaaGRSXQ,15151
10
+ tuft/server.py,sha256=NUapRGdQbQH6PbuCfMZeMVi_7vM6nM7xmxepCPkgyko,24996
11
+ tuft/state.py,sha256=J9R5Wd9JlMtpYcaY_6t5RvgJbY3EX5ZJTZfoQhwZ9hU,12853
12
+ tuft/training_controller.py,sha256=fQI6sxtG3v2JYgbd1y501MLzuTUAp0NIvzv6cBOm-T8,29841
13
+ tuft/backends/__init__.py,sha256=7A6Pu-vEMbcMWapAh-zkI1O5WtBHO0OxwED8qAy9kAQ,262
14
+ tuft/backends/base_backend.py,sha256=bdlx3hRyEj00GKFlh2fAczn7h4zANz7bdKgXb_F18y4,3462
15
+ tuft/backends/hf_training_model.py,sha256=XQa598SpY7DnYYU0rTaHjlh-5dRCPueFtcdxrcjXWIc,16993
16
+ tuft/backends/sampling_backend.py,sha256=gf5laCMGbk9CrFuEJB0udKywVIimyU9-lqlwKok6j_w,10178
17
+ tuft/backends/training_backend.py,sha256=p1w-1i9-vxlocr97eumB46WZS5LxrTnxz4y86mKA950,13149
18
+ tuft/loss_fn/__init__.py,sha256=l6wNbeqV6_WCs0jIg3H89eTUUpTf50aitLnDb9lRdM4,1620
19
+ tuft/loss_fn/cispo.py,sha256=L8HhqJ0rJcfgqfEkk445bvaKsZNWNAqwqm_47M9SB1Y,1598
20
+ tuft/loss_fn/cross_entropy.py,sha256=e9D2U_G8TNXOlOvEw7OQj-YE1H5DldzG2HS2QjKBfe8,935
21
+ tuft/loss_fn/dro.py,sha256=6d3jDK1OybcoFjq5vDwiUrURyaV-EajGLMECyF_2mjE,1315
22
+ tuft/loss_fn/importance_sampling.py,sha256=MTxO63LBhghVCEyDQYptaziFmVvEiSTE9xeGoyo20wc,1090
23
+ tuft/loss_fn/ppo.py,sha256=YpIYWNWqv9Asr3tV8iq5erSDHlZD8VmgOmDJQFHVWSo,1678
24
+ tuft/persistence/__init__.py,sha256=U-yEVEgikbrTMLdwPS2S9GUwuQV-1Fnt9Y5key0r9bA,615
25
+ tuft/persistence/file_redis.py,sha256=hLGClNhd9OID9JZMP-RZTisyoXOvQ0ctv3czj01dgIY,8091
26
+ tuft/persistence/redis_store.py,sha256=9z1zbtUSXzaQP3bAH18eLd4OQ8YiJtFo4TgsZoGsGX4,15904
27
+ tuft/telemetry/__init__.py,sha256=dlSGiJ_pMElhwEe31olGg88ZrjoBeGUBn2P17qFNymM,336
28
+ tuft/telemetry/metrics.py,sha256=Yz6s2AQ5CptFXvEm-PbO-Ib17-aF0rnoG8vZxH-Pawo,11538
29
+ tuft/telemetry/provider.py,sha256=jGKqTMsP-WekKGCMN9QHwt-g_1Lk1xUOy1BO-__xG5I,6700
30
+ tuft/telemetry/tracing.py,sha256=GL-wEEQtzM1ycgfI4sMsHUeIC7qj5MyOH-sBwHihbsE,957
31
+ tuft-0.1.1.dist-info/METADATA,sha256=zH2lHrE8kZh2O61cvI7_uSyGCJ9obARa0FZGLnj0HQY,20375
32
+ tuft-0.1.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
33
+ tuft-0.1.1.dist-info/entry_points.txt,sha256=T48zU7Vdi2ZsARDeOZ9jK6XGuYNaCbSaUTd5POouLms,39
34
+ tuft-0.1.1.dist-info/licenses/LICENSE,sha256=fJHdoqbikZ-GATzLNmixfKDot1w_cJuHKY3mH4qSmYs,1069
35
+ tuft-0.1.1.dist-info/RECORD,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ tuft = tuft.cli:main
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Eric Zhu
3
+ Copyright (c) 2026 agentscope-ai
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
18
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
21
+ SOFTWARE.