Conversation
…es work T0.1: capture current HEAD client-facing surface so the post-refactor comparison (T8.1) shows only this spec's changes. No code changes.
…1.6) - execute_all_sync forwards timeout to ray.get (T1.1) - resolve effective ray.get timeout before choosing execute_method and flip priority to 'decorator wins, instance is fallback' at both dispatch sites; fix the 0-treated-as-falsy trap; bound __len__/__next__ bare ray.get (T1.2, T1.5) - decorator timeout=10 on ping; timeout=3600 on save/add_adapter_to_model/ resume_from_checkpoint/tinker_load/load_full_weights_from_path (T1.3) - TaskQueueConfig default execution_timeout 120->1800; effective_execution_timeout (0 -> 3600) as the single bound source; startup warning on 0 (T1.4) - infra unit tests, no GPU/Megatron/server deps (T1.6)
…2.1-T2.4, T6.1) - twinkle_client/types/base.py: StrictRequest/ResponseModel/DataModel + backend_only() helper/reader; naming rulings in module docstring (defined, not applied) (T6.1) - twinkle_client/types/errors.py: ErrorCategory + ErrorPayload(ResponseModel) (T2.1) - task_errors.py: task_error_payload builds ErrorPayload dict (request_id/error_code, traceback split+tail-trim, User carries no traceback); error_payload_from_stored backfills legacy two-field payloads without ValidationError (T2.2) - worker: single-line error summary + full traceback in traceback field; TimeoutError and Ray_Get_Timeout -> 504/Server, others -> 500/Server (T2.3) - tests for ErrorPayload + updated task_errors test (T2.4)
…e 6, T6.2-T6.3) - QueueStateLiteral in types/errors.py, values sourced to match server QueueState; consistency test asserts equal value sets (T6.2) - T6.3 realized as a guard test (per user ruling): twinkle_client already shares 18 public names with tinker.types by design (tinker-compatible client), so the literal 'no intersection' cannot hold without renaming twinkle. Guard instead asserts no src/twinkle module binds a tinker and a twinkle_client type to the same local name (tinker must be aliased when both coexist).
…T3.8) - call_backend: dedicated ThreadPoolExecutor (no max_workers=1) + per-replica opt-in Admission_Gate; gate released from the worker thread's finally so a wait_for-cancelled coroutine cannot free it while the call is still in flight; fast-fail BackendBusyError when the gate is held by a leaked call (T3.1) - ModelManagement enables the gate; SamplerManagement does not - worker maps BackendBusyError -> 503/Server - mechanical: 27 model/twinkle + 14 model/tinker + 8 sampler/twinkle + 4 sampler/tinker + 3 model/app direct backend calls -> await call_backend (T3.2-T3.5) - check_model_health async + admit=False ping; _cleanup_adapter via gate; /healthz awaits (T3.5, T3.6) - AST static check over src/twinkle/server/** + shared exemptions file (T3.7) - blocking-boundary integration tests (T3.8)
… T4.1-T4.3) - set _ray_get_timeout = effective execution timeout on model/sampler backends, effective for both sync and async dispatch (T4.1) - ComputeWorker fires an optional on_backend_timeout hook after a timeout; ModelManagement probes actor liveness (admit=False ping) and sets a health bit that /healthz reflects (503) and a successful probe auto-clears (T4.2) - worker skips a dequeued task whose record is already terminal (R3#8); document record-terminal (queue_timeout+T) vs resource-release (Collect_Width*T) bounds in EN+ZH Server docs (T4.3)
…1-T5.6) - FutureRecord.replica_id set at creation, never overwritten (T5.1) - ReplicaRegistry last_seen as a separate key (max_loras type unchanged); refreshed in _on_request_start; ModelManager.get_alive_replica_ids (T5.2) - cleanup_expired rewrite: never deletes a non-terminal record; orphans and over-absolute-ttl records are written failed; signature adds alive_replica_ids + absolute_ttl; ServerState.set_execution_bounds injects queue_timeout/T/ Collect_Width; age uses the stored-timestamp clock convention (T5.3) - do-not-regress guard extended to terminal->terminal (warn on different, silent drop on same) (T5.4) - sampler _stream_generator: 60s per-get + total-lifetime bound, ray Queue shutdown in finally, empty-actor structured error (T5.5) - state hygiene tests via Ray-free FileBackend (T5.6)
- delete TWINKLE_FAIL_FAST from the 4 cookbook server configs (T7.1) - delete Layer 1 (safe_loss/SafeLossWrapper/_zero_loss) + OptimizerGroup.__setattr__ auto-wrap hook + the test_micro_batch safe_loss import/case (T7.2) - delete Layer 2 (@nccl_safe decorator, _force_zero_backward, _iter_model_params) and its two decoration points + import in transformers_model (T7.3) - delete Layer 4: the forward_step_func post-processing try/except in megatron.py, exceptions now propagate; drop the _is_fail_fast import (T7.4) - delete Fail_Fast_Switch: _is_fail_fast + env_propagation NCCL_SAFE_ENV_KEYS/ build_nccl_safe_env_vars and its call (T7.5) - nccl_safe_megatron rewritten to unconditional rank-attributed log + re-raise, no tinker/forward_only params, no degraded return; module docstring records the lost coverage window (T7.6, T7.9) - rewrite both GPU-gated e2e tests to assert failed-terminal + subsequent-success and drop degradation symbols (T7.7) - unified static check asserting the 8 symbols are absent (T7.8)
…e 8, T8.1/T8.2/T8.4) - test_client_api_contract.py: OpenAPI surface == pre-impl baseline (T0.1), schedule_task_and_wait retained, only new client modules base.py/errors.py (T8.1) - new checks are auto-run by CI 'pytest tests'; lint.yaml runs pre-commit --all-files; applied yapf/isort/pyupgrade auto-fixes so all hooks pass on changed src files (T8.2) - tests/server/README.md documents the mock-backend evidence boundary (T8.4)
…endent Root cause: _now_iso() wrote naive local time while _parse_timestamp() reads a naive ISO string as UTC; compared against a time.time()-based cutoff this skewed every expiry check by the host's UTC offset (premature deletion west of UTC, over-retention east; invisible on UTC/CI hosts). Fix (option A): _now_iso() now emits UTC-aware ISO; future_manager reuses it for record writes and its cleanup 'now' reverts to time.time() (both UTC epoch). _parse_timestamp is unchanged and still parses legacy naive records as UTC (same as before). Not a wire-schema change (R8 unaffected). Adds a timezone-independent regression test asserting a freshly written record parses to within 1s of time.time(); the suite passes under TZ=America/Los_Angeles.
# Conflicts: # src/twinkle/server/model/app.py
…m/gen bounds) Complete the server-execution-guarantees spec by routing the remaining sampler paths through the Blocking_Call_Boundary and bounding every long-lived operation: - sampler: submit/collect/cancel generation, unload, and streaming now go through call_backend; _await_generation is bounded by the effective execution timeout and _stream_queue enforces a double timeout (total + per-token) instead of blocking indefinitely. - task queue: thread collect_width through _init_task_queue so state hygiene computes the absolute survival TTL without a separate set_execution_bounds hop. - errors: stream/generation failures surface as ErrorPayload wire frames rather than silent drops. - deps: bump tinker to 0.29.0 (python>=3.11) and refresh poetry.lock. - tests/docs: add error-wire, stream-guarantee and nccl_safe coverage; refresh the client API contract baseline (zero wire change).
tinker 0.29.0 turned its tensor request types into dataclasses, which breaks FastAPI OpenAPI generation. Revert the pin and the code that had been migrated to the 0.29.0 API: - pyproject: tinker 0.29.0 -> 0.16.1; restore poetry.lock to match - sampler/tinker_handlers: use 0.16.1 SampledSequence/SampleResponse fields - contract harness: fastapi 0.136 ModelField compat; normalize :path route converters so the baseline stores client-facing paths - regenerate client_api_baseline.json against tinker 0.16.1 - test fixtures: add call_backend/_task_queue_config; drop 0.29-only assertion
…ecycle Implements the server-request-lifecycle spec (Part 2). A single HTTP request's server-side duration is now decoupled from task execution time: submit enqueues and returns a TaskEnvelope immediately, and the client's future layer polls a dedicated retrieve endpoint. The motivation is narrow and load-bearing: the client's per-request timeout was 600s while most ingress gateways cut idle connections at 60s, so data-plane endpoints (forward_backward, sample) were already unusable behind a real gateway. Every single HTTP request is now bounded by the 30s long-poll window regardless of how long the task runs. This does not improve throughput or training speed -- the compute queue is still serial and GPU utilisation is unchanged. Server: - new twinkle/server/lifecycle/: envelope.py (the one FutureRecord -> TaskEnvelope mapping point), poll_config.py (single declaration of the long-poll window and interval, shared by both retrieve endpoints), submit.py (run_submit shell plus the to_backend_inputs / backend_kwargs / input_metrics seams left for Part 3) - new POST /twinkle/retrieve_future and POST /twinkle/cancel - preflight now raises RequestRejectedError subclasses, so a rejected request returns a real status code and writes zero future records - TwinkleServerError handler puts ErrorPayload fields at the response top level - delete schedule_task_and_wait, run_task (both copies), QueuedTask.completion, _complete_result/_complete_error and persist_status; the future record is now the only delivery channel for results and failures - delete TaskStatus.RATE_LIMITED (limiting is now HTTP 429), the get_state_dict endpoint and the upload_status endpoint Client: - new types/lifecycle.py (TaskEnvelope), _future.py (the only polling loop), exceptions.py (TwinkleHTTPError / TaskFailedError / TaskCancelledError / TaskWaitTimeoutError / TaskRecordLostError) - three separate 600s timeout literals collapse into _HTTP_TIMEOUT = 90 - public methods keep their synchronous signatures and return types, so cookbook scripts and integration tests are unchanged Breaking changes: queued endpoints return TaskEnvelope instead of a business model; task failure raises TaskFailedError (HTTP 200 + payload) instead of requests.HTTPError (HTTP 500); get_state_dict is removed (use save + read the checkpoint). Verified on real PPU hardware (Qwen3.5-4B, 8x ZW810): SFT/DPO/GRPO x twinkle/tinker on the transformers backend and SFT x twinkle/tinker on megatron, 8/8 passing with losses identical to the pre-refactor run. Unit suite: 360 passed, 0 failed.
…ixins - move sampler weight resolution to sampler/weights.py and streaming bridge to sampler/backends/streaming.py so handlers stay thin - rename utils/lifecycle to utils/session_resource: the package holds session-scoped resource mixins, not the request lifecycle owned by twinkle/server/lifecycle - add static guards for adapter-name mapping and package-root imports - declare grimp test dependency used by the import-boundary guards
…ing disambiguation Move HTTP-boundary-decidable request problems out of the async training path: - Single shared request models (twinkle_client.types) with field roles (control / backend_kwarg / passthrough); client builds via build_request + model_dump_json instead of hand-assembling json_data. - StrictRequest on all twinkle-native routes; unified RequestValidationError -> ErrorPayload (422/501) registered on the shared deployment app builder. - Wire schema for inline `inputs` validated at HTTP ingress (strict int leaves, homogeneous batch, extension-field preservation); single shared `is_encoded` predicate in twinkle.data_format.encoding replaces three copies. - run_submit preflight (assert_request_supported) rejects backend-incompatible fields and unavailable endpoints before seq claim / enqueue -> zero DP ranks. - Passthrough keys forwarded unjudged (no spelling heuristic). Naming disambiguation (client/server contract fix): - Prefix sampler-domain models (SamplerAddAdapterRequest / SetTemplate* / CreateResponse) so they no longer collide with model.py; the sampler handler now binds sampler_types explicitly. Fixes add_adapter_to_sampler validating against model.py's `config: Optional[str]` and rejecting the dict the client sends. - Remove dead model.AddAdapterResponse and server.WeightsInfoResponse. - training.py response envelopes inherit ResponseModel. - Regenerate contract route inventory; add regression tests pinning the sampler binding and the dict-config acceptance.
Auto-fixes flagged by CI on b928a17 (pre-commit run --all-files): - sampler/twinkle_handlers.py: isort import order + wrap the 122-char create() signature (E501). - validation/backend_compat.py: pyupgrade Optional[str] -> str | None.
…ing code Remove src/twinkle_client from the pre-commit exemptions (flake8/isort/yapf/ pyupgrade + the whitespace/EOL/quote fixers) so the client is linted like the server, and bring the existing (previously-unchecked) client code to a green `pre-commit run --all-files`: - isort/yapf/pyupgrade/double-quote normalization across the client package. - Wrap over-length tool/description/error strings (implicit concatenation, content preserved) in auto/agent/tools.py and utils/patch_tinker.py. - Rename ambiguous loop var `l` -> `line` (E741) in auto/agent/monitor.py. - `# noqa: E402` on the intentional late import in twinkle_client/__init__.py. - setup.cfg per-file-ignores: E501 for auto/agent/monitor.py (embedded LLM prompt with verbatim long lines). - types/__init__.py: scoped `# yapf: disable` around the re-export block so the 45-name `from .model import (...)` stops oscillating between isort's aligned wrap and yapf's hanging wrap (isort still owns the ordering).
…ut cleanup Server: - Rename utils/validation.py -> utils/auth.py to end the collision with the server/validation preflight package (auth/session helpers vs request checks). - Rename model/utils.py -> model/data_plane_inputs.py to name what it does. Client: - Rename http/http_utils.py -> http/client.py and http/utils.py -> http/context.py; update all importers. - Split auto/agent/tools.py into tool_schemas.py (schemas), server_tools.py and search_tools.py (ToolExecutor mixins); add test_auto_agent_tools.py. - Rework rollout/multi_turn.py into an explicit _RolloutState with _initialize_state / _process_sequence helpers. All touched files pass `pre-commit run --all-files` (client now linted).
…pe; repair PPU full test suite - multi_lora: mirror PeftModel.__init__ adapter dtype autocast on each add_adapter slot (drop unconditional float() normalization) - transformers: make _ensure_lora_dtype a @staticmethod; update call site - align tests with PEFT 0.18.1 target-parameter shapes and transport API; loosen slow-startup/backend timeouts - refresh twinkle client cookbooks/docs for client-as-factory usage
…ng R6-R13) - R6: bounded fail-open session liveness via last_liveness_confirmed_at - R7: full ABC hooks + cluster-global processor lease quota (429/User) - R8: ConcurrencyError->StateBackendError(503); close() releases handle only, flush_all() for teardown; backend contract docstrings - R9: drop **kwargs pseudo-polymorphism; ModelManager quota -> 429/User - R10: Twinkle-native ErrorPayload single exit; EndpointUnavailableError moved to server/exceptions.py; no-HTTPException static guard - R11: FutureFailureRecord domain failure; protocol-boundary wire mapping - R12: client ErrorPayload parse with details/traceback, lowercase category - R13: remove unrunnable sampler 'torch' option Verified: unit/contract regression (361 passed) + full 2x2x3 E2E matrix (transformers+megatron x twinkle+tinker x sft/dpo/grpo, 12/12 passed incl. save-LoRA/state + resume).
…verState/BackendGate split (server-module-boundaries Track C) Structural (behaviour-preserving) module-boundary work: - server/utils/ dissolved: task_queue/, session_resource/ promoted to server/; auth.py -> middleware/auth.py; task_errors.py -> server/; backend_dispatch.py -> config/; ray_serve_patch.py -> twinkle/patch/ray_serve.py. device/template utils stay. - common/ removed: datum.py -> model/tinker_datum.py, router.py -> model/routing.py. - validation/errors.py merged into deployment.validation_error_handler; validation/ now holds only backend_compat. - ServerState split into ResourceCleanupCoordinator + ResourceCountPublisher (idempotency guard moved with the impl); actor_name -> cache_key. - BackendGate extracted from TaskQueueMixin (pure callable wrapper); worker owns notify_new_task + the single queue-depth writer. - tinker_load path resolution moved to the handler; backends take checkpoint_name/ output_dir and no longer import server.checkpoint. - gateway services.py -> use_cases.py (dropped one-line forwards); supported_model_names public property; per-instance template cache; gateway/routes.py route constants. - init_twinkle_runtime -> server/runtime.py (with ncpu_proc_per_node passthrough). - tq_utils.py -> data_format/tq_fields.py (+ TQ field constants; async_rl shim removed). - lifecycle/protocols.py declares the host contract; run_submit/input_metrics annotated. - utils bucket export shrunk; telemetry middleware.py split into metrics.py + http_middleware.py; dropped stale re-exports (FullModeBusyError, PersistenceConfig, TelemetryConfig, _resolve_client_save_dir). fix(telemetry): per-deployment metric caches moved onto MetricsRegistry instance so MetricsRegistry.reset() invalidates them (adapters no longer keep NoOp instruments). Also: added tests (tq_fields, proxy, runtime, protocols, metrics-cache-invalidation), updated imports/test harnesses, and removed spec-clause reference annotations from code comments/docstrings. Verified: regression baseline 291 passed / 16 skipped; full 2x2x3 E2E (transformers & megatron x twinkle & tinker x sft/dpo/grpo) all passed; flake8/yapf clean.
…s TYPE_CHECKING forward-refs, flake8 line length)
…er.py (pre-commit --all-files clean)
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
One or more issues must be addressed before approval.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 5
Open (7)
Base-model inference incorrectly requires an adapter resource · New Dict LoRA configs fail client-side validation · New Undefined AsyncOpenAI annotation causes flake8 failure · New Undefined AsyncOpenAI annotation causes flake8 failure · New Configured API key is not sent with requests · New Removing file persistence mode breaks existing deployments · New Module-level importorskip hides TensorDict-independent test · New
What changed in this PR
Hardens Twinkle’s server/client request lifecycle with strict shared schemas, bounded execution, persistent futures, and supporting refactors.
Changes:
- Adds unified protocol models, validation, error payloads, and async submit/retrieve handling.
- Refactors server state, task queues, telemetry, routing, sampler/model paths, and persistence.
- Reworks client transport/imports and updates tests, docs, notebooks, and examples.
| File | Description |
|---|---|
| tests/utils/test_nccl_safe.py | Updated as part of this pull request. |
| tests/twinkle_client/test_import_surface.py | Updated as part of this pull request. |
| tests/twinkle_client/test_data_plane_async.py | Updated as part of this pull request. |
| tests/twinkle_client/test_component_rpc.py | Updated as part of this pull request. |
| tests/twinkle_client/test_auto_agent_tools.py | Updated as part of this pull request. |
| tests/twinkle_client/test_async_rl_workers.py | Updated as part of this pull request. |
| tests/twinkle_agentic/evaluator/test_client_sampler.py | Updated as part of this pull request. |
| tests/server/validation/__init__.py | Updated as part of this pull request. |
| tests/server/utils/test_task_errors.py | Updated as part of this pull request. |
| tests/server/utils/test_rate_limiter.py | Updated as part of this pull request. |
| tests/server/utils/task_queue/test_config.py | Updated as part of this pull request. |
| tests/server/test_runtime.py | Updated as part of this pull request. |
| tests/server/test_deployment_exception_boundary.py | Updated as part of this pull request. |
| tests/server/telemetry/test_metrics_cache_invalidation.py | Updated as part of this pull request. |
| tests/server/static/test_utils_bucket_is_light.py | Updated as part of this pull request. |
| tests/server/static/test_no_twinkle_http_exception.py | Updated as part of this pull request. |
| tests/server/static/test_no_package_root_imports.py | Updated as part of this pull request. |
| tests/server/static/test_client_architecture_imports.py | Updated as part of this pull request. |
| tests/server/static/backend_call_exemptions.py | Updated as part of this pull request. |
| tests/server/static/__init__.py | Updated as part of this pull request. |
| tests/server/state/test_leader_election.py | Updated as part of this pull request. |
| tests/server/start_e2e_server.py | Updated as part of this pull request. |
| tests/server/sampler/test_twinkle_async_rows.py | Updated as part of this pull request. |
| tests/server/sampler/test_tinker_handlers.py | Updated as part of this pull request. |
| tests/server/sampler/test_resolve_sampler_weights.py | Updated as part of this pull request. |
| tests/server/sampler/test_mock_sampler.py | Updated as part of this pull request. |
| tests/server/model/test_tinker_handlers.py | Updated as part of this pull request. |
| tests/server/model/test_tinker_compat_output.py | Updated as part of this pull request. |
| tests/server/model/test_replica_lifecycle.py | Updated as part of this pull request. |
| tests/server/model/test_mock_model.py | Updated as part of this pull request. |
| tests/server/lifecycle/test_to_backend_inputs.py | Updated as part of this pull request. |
| tests/server/lifecycle/test_tinker_retrieve_regression.py | Updated as part of this pull request. |
| tests/server/lifecycle/test_protocols.py | Updated as part of this pull request. |
| tests/server/lifecycle/test_envelope_coverage.py | Updated as part of this pull request. |
| tests/server/lifecycle/__init__.py | Updated as part of this pull request. |
| tests/server/integration/test_mock_mode_startup.py | Updated as part of this pull request. |
| tests/server/integration/test_full_param_e2e.py | Updated as part of this pull request. |
| tests/server/integration/test_full_cycle_e2e.py | Updated as part of this pull request. |
| tests/server/integration/test_dpo_e2e.py | Updated as part of this pull request. |
| tests/server/integration/e2e_helpers.py | Updated as part of this pull request. |
| tests/server/gateway/test_proxy.py | Updated as part of this pull request. |
| tests/server/gateway/test_openai_handlers.py | Updated as part of this pull request. |
| tests/server/fixtures/server_config_mock.yaml | Updated as part of this pull request. |
| tests/server/data_plane/test_store.py | Updated as part of this pull request. |
| tests/server/data_plane/test_proxy.py | Updated as part of this pull request. |
| tests/server/contract/update_baseline.py | Updated as part of this pull request. |
| tests/server/contract/test_protocol_migration.py | Updated as part of this pull request. |
| tests/server/contract/test_error_wire.py | Updated as part of this pull request. |
| tests/server/conftest.py | Updated as part of this pull request. |
| tests/server/config/server_config_4b_e2e.yaml | Updated as part of this pull request. |
| tests/server/config/server_config_4b_e2e_megatron.yaml | Updated as part of this pull request. |
| tests/sampler/test_vllm_startup_lock.py | Updated as part of this pull request. |
| tests/model/test_multi_lora_dtype.py | Updated as part of this pull request. |
| tests/model/test_micro_batch.py | Updated as part of this pull request. |
| tests/loss/test_grpo_gkd.py | Updated as part of this pull request. |
| tests/data_format/test_tq_fields.py | Updated as part of this pull request. |
| src/twinkle/utils/import_utils.py | Updated as part of this pull request. |
| src/twinkle/server/validation/__init__.py | Updated as part of this pull request. |
| src/twinkle/server/utils/task_queue/config.py | Updated as part of this pull request. |
| src/twinkle/server/utils/task_errors.py | Updated as part of this pull request. |
| src/twinkle/server/utils/lifecycle/__init__.py | Updated as part of this pull request. |
| src/twinkle/server/utils/__init__.py | Updated as part of this pull request. |
| src/twinkle/server/telemetry/worker_init.py | Updated as part of this pull request. |
| src/twinkle/server/telemetry/tracing.py | Updated as part of this pull request. |
| src/twinkle/server/telemetry/http_middleware.py | Updated as part of this pull request. |
| src/twinkle/server/telemetry/__init__.py | Updated as part of this pull request. |
| src/twinkle/server/task_queue/types.py | Updated as part of this pull request. |
| src/twinkle/server/task_queue/__init__.py | Updated as part of this pull request. |
| src/twinkle/server/task_errors.py | Updated as part of this pull request. |
| src/twinkle/server/state/session_manager.py | Updated as part of this pull request. |
| src/twinkle/server/state/sampling_manager.py | Updated as part of this pull request. |
| src/twinkle/server/state/base.py | Updated as part of this pull request. |
| src/twinkle/server/state/backend/redis_backend.py | Updated as part of this pull request. |
| src/twinkle/server/state/backend/memory_backend.py | Updated as part of this pull request. |
| src/twinkle/server/state/backend/factory.py | Updated as part of this pull request. |
| src/twinkle/server/state/backend/base.py | Updated as part of this pull request. |
| src/twinkle/server/state/backend/__init__.py | Updated as part of this pull request. |
| src/twinkle/server/state/__init__.py | Updated as part of this pull request. |
| src/twinkle/server/session_resource/adapter.py | Updated as part of this pull request. |
| src/twinkle/server/session_resource/__init__.py | Updated as part of this pull request. |
| src/twinkle/server/sampler/weights.py | Updated as part of this pull request. |
| src/twinkle/server/sampler/backends/streaming.py | Updated as part of this pull request. |
| src/twinkle/server/sampler/backends/mock_sampler.py | Updated as part of this pull request. |
| src/twinkle/server/sampler/backends/__init__.py | Updated as part of this pull request. |
| src/twinkle/server/runtime.py | Updated as part of this pull request. |
| src/twinkle/server/processor/app.py | Updated as part of this pull request. |
| src/twinkle/server/model/routing.py | Updated as part of this pull request. |
| src/twinkle/server/model/data_plane_inputs.py | Updated as part of this pull request. |
| src/twinkle/server/model/backends/mock_model.py | Updated as part of this pull request. |
| src/twinkle/server/middleware/auth.py | Updated as part of this pull request. |
| src/twinkle/server/middleware/__init__.py | Updated as part of this pull request. |
| src/twinkle/server/lifecycle/protocols.py | Updated as part of this pull request. |
| src/twinkle/server/lifecycle/__init__.py | Updated as part of this pull request. |
| src/twinkle/server/launcher/server_launcher.py | Updated as part of this pull request. |
| src/twinkle/server/launcher/env_propagation.py | Updated as part of this pull request. |
| src/twinkle/server/gateway/routes.py | Updated as part of this pull request. |
| src/twinkle/server/gateway/app.py | Updated as part of this pull request. |
| src/twinkle/server/data_plane/store.py | Updated as part of this pull request. |
| src/twinkle/server/data_plane/proxy.py | Updated as part of this pull request. |
| src/twinkle/server/data_plane/handlers.py | Updated as part of this pull request. |
| src/twinkle/server/config/server_config.py | Updated as part of this pull request. |
| src/twinkle/server/config/persistence.py | Updated as part of this pull request. |
| src/twinkle/server/config/backend_dispatch.py | Updated as part of this pull request. |
| src/twinkle/server/common/__init__.py | Updated as part of this pull request. |
| src/twinkle/server/checkpoint/twinkle.py | Updated as part of this pull request. |
| src/twinkle/server/checkpoint/tinker.py | Updated as part of this pull request. |
| src/twinkle/server/checkpoint/checkpoint_manager.py | Updated as part of this pull request. |
| src/twinkle/server/checkpoint/__init__.py | Updated as part of this pull request. |
| src/twinkle/sampler/vllm_sampler/vllm_sampler.py | Updated as part of this pull request. |
| src/twinkle/sampler/base.py | Updated as part of this pull request. |
| src/twinkle/protocol/types/training.py | Updated as part of this pull request. |
| src/twinkle/protocol/types/session.py | Updated as part of this pull request. |
| src/twinkle/protocol/types/server.py | Updated as part of this pull request. |
| src/twinkle/protocol/types/processor.py | Updated as part of this pull request. |
| src/twinkle/protocol/types/checkpoint.py | Updated as part of this pull request. |
| src/twinkle/protocol/json_utils.py | Updated as part of this pull request. |
| src/twinkle/protocol/headers.py | Updated as part of this pull request. |
| src/twinkle/protocol/__init__.py | Updated as part of this pull request. |
| src/twinkle/patch/ray_serve.py | Updated as part of this pull request. |
| src/twinkle/model/transformers/transformers.py | Updated as part of this pull request. |
| src/twinkle/model/optimizer_group.py | Updated as part of this pull request. |
| src/twinkle/model/multi_lora.py | Updated as part of this pull request. |
| src/twinkle/model/megatron/multi_lora_megatron.py | Updated as part of this pull request. |
| src/twinkle/model/megatron/__init__.py | Updated as part of this pull request. |
| src/twinkle/model/__init__.py | Updated as part of this pull request. |
| src/twinkle/loss/grpo.py | Updated as part of this pull request. |
| src/twinkle/infra/_ray/ray_helper.py | Updated as part of this pull request. |
| src/twinkle/dataset/base.py | Updated as part of this pull request. |
| src/twinkle/data_format/tq_fields.py | Updated as part of this pull request. |
| src/twinkle/data_format/encoding.py | Updated as part of this pull request. |
| src/twinkle/data_format/__init__.py | Updated as part of this pull request. |
| src/twinkle/_lazy_module.py | Updated as part of this pull request. |
| src/twinkle/__init__.py | Updated as part of this pull request. |
| src/twinkle_client/utils/patch_tinker.py | Updated as part of this pull request. |
| src/twinkle_client/utils/__init__.py | Updated as part of this pull request. |
| src/twinkle_client/types/server.py | Updated as part of this pull request. |
| src/twinkle_client/types/processor.py | Updated as part of this pull request. |
| src/twinkle_client/types/__init__.py | Updated as part of this pull request. |
| src/twinkle_client/skills/modelscope_provider.py | Updated as part of this pull request. |
| src/twinkle_client/skills/manager.py | Updated as part of this pull request. |
| src/twinkle_client/skills/bundled/twinkle-training.md | Updated as part of this pull request. |
| src/twinkle_client/skills/base.py | Updated as part of this pull request. |
| src/twinkle_client/sampler/__init__.py | Updated as part of this pull request. |
| src/twinkle_client/py.typed | Updated as part of this pull request. |
| src/twinkle_client/processor/base.py | Updated as part of this pull request. |
| src/twinkle_client/processor/__init__.py | Updated as part of this pull request. |
| src/twinkle_client/model/__init__.py | Updated as part of this pull request. |
| src/twinkle_client/http/utils.py | Updated as part of this pull request. |
| src/twinkle_client/http/__init__.py | Updated as part of this pull request. |
| src/twinkle_client/dataset/packing_dataset.py | Updated as part of this pull request. |
| src/twinkle_client/dataset/__init__.py | Updated as part of this pull request. |
| src/twinkle_client/dataloader/__init__.py | Updated as part of this pull request. |
| src/twinkle_client/common/remote_component.py | Updated as part of this pull request. |
| src/twinkle_client/common/component_rpc.py | Updated as part of this pull request. |
| src/twinkle_client/common/__init__.py | Updated as part of this pull request. |
| src/twinkle_client/auto/runtime.py | Updated as part of this pull request. |
| src/twinkle_client/auto/connection.py | Updated as part of this pull request. |
| src/twinkle_client/auto/app.py | Updated as part of this pull request. |
| src/twinkle_client/auto/agent/search_tools.py | Updated as part of this pull request. |
| src/twinkle_client/auto/agent/monitor.py | Updated as part of this pull request. |
| src/twinkle_client/auto/agent/core.py | Updated as part of this pull request. |
| src/twinkle_client/async_rl/workers.py | Updated as part of this pull request. |
| src/twinkle_client/__init__.py | Updated as part of this pull request. |
| src/twinkle_agentic/async_rl/tq_utils.py | Updated as part of this pull request. |
| src/twinkle_agentic/async_rl/pipeline.py | Updated as part of this pull request. |
| src/twinkle_agentic/async_rl/data_plane.py | Updated as part of this pull request. |
| setup.cfg | Updated as part of this pull request. |
| README.md | Updated as part of this pull request. |
| README_ZH.md | Updated as part of this pull request. |
| pyproject.toml | Updated as part of this pull request. |
| notebook/short_math_grpo.ipynb | Updated as part of this pull request. |
| notebook/self_cognition.ipynb | Updated as part of this pull request. |
| notebook/sample.ipynb | Updated as part of this pull request. |
| notebook/multi_modal.ipynb | Updated as part of this pull request. |
| notebook/dpo.ipynb | Updated as part of this pull request. |
| docs/source_zh/使用指引/训练服务.md | Updated as part of this pull request. |
| docs/source_zh/使用指引/服务端和客户端/Tinker兼容客户端.md | Updated as part of this pull request. |
| docs/source_zh/使用指引/快速开始.md | Updated as part of this pull request. |
| docs/source_zh/使用指引/Qwen3.5最佳实践.md | Updated as part of this pull request. |
| docs/source_zh/使用指引/Embedding训练.md | Updated as part of this pull request. |
| docs/source_en/Usage Guide/Train-as-a-Service.md | Updated as part of this pull request. |
| docs/source_en/Usage Guide/Server and Client/Tinker-Compatible-Client.md | Updated as part of this pull request. |
| docs/source_en/Usage Guide/Quick-Start.md | Updated as part of this pull request. |
| docs/source_en/Usage Guide/Introduction-with-Qwen3.5.md | Updated as part of this pull request. |
| docs/source_en/Usage Guide/Embedding-Training.md | Updated as part of this pull request. |
| cookbook/client/twinkle/upload_to_hub.py | Updated as part of this pull request. |
| cookbook/client/twinkle/self_cognition.py | Updated as part of this pull request. |
| cookbook/client/twinkle/sample.py | Updated as part of this pull request. |
| cookbook/client/twinkle/multi_modal.py | Updated as part of this pull request. |
| cookbook/client/twinkle/embedding.py | Updated as part of this pull request. |
| cookbook/client/twinkle/dpo.py | Updated as part of this pull request. |
| cookbook/client/tinker/upload_to_hub.py | Updated as part of this pull request. |
| cookbook/client/tinker/self_cognition.py | Updated as part of this pull request. |
| cookbook/client/tinker/multi_modal.py | Updated as part of this pull request. |
| cookbook/client/tinker/dpo.py | Updated as part of this pull request. |
| cookbook/client/server/transformer/server_config.yaml | Updated as part of this pull request. |
| cookbook/client/server/megatron/server_config.yaml | Updated as part of this pull request. |
| cookbook/client/server/megatron/server_config_4b.yaml | Updated as part of this pull request. |
| cookbook/client/async_rl/server_config.yaml | Updated as part of this pull request. |
| cookbook/client/async_rl/client_orchestrated_grpo.py | Updated as part of this pull request. |
| .pre-commit-config.yaml | Updated as part of this pull request. |
| .gitignore | Updated as part of this pull request. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| ENCODED_INPUT_KEYS: tuple[str, ...] = ('input_ids', 'input_embedding') | ||
|
|
||
|
|
||
| def is_encoded(entry: Any) -> bool: |
There was a problem hiding this comment.
这个看起来不是 data_format,迁移 utils?
There was a problem hiding this comment.
这是判断输入是不是“模型已经编码好的数据”,属于数据格式逻辑,不是通用工具;放 data_format 可能更合适
| """ | ||
| import ray | ||
| return ray.get(RayHelper.execute_all_async(method_name, workers_and_args)) | ||
| return ray.get(RayHelper.execute_all_async(method_name, workers_and_args), timeout=timeout) |
There was a problem hiding this comment.
如果增加 timeout,内部 hang 住会不会导致后续请求卡死
There was a problem hiding this comment.
这里机制链路是:
- 服务端把调用发给多个 Ray actor,得到一组 future。
ray.get(futures, timeout=T)最多等T秒。- 所有 actor 及时返回,就正常汇总结果;任意 actor 卡住导致整批未完成,就抛出超时异常。
- 队列捕获异常,把该请求写成失败终态,客户端轮询 future 时拿到超时错误。
- 超时后系统会检查模型还活不活;如果上一条任务其实还卡着,就先拒绝新请求,直接告诉用户“后端忙”,避免大家一起排队卡住。
- 等卡住的任务自己结束后,系统会自动恢复,新请求可以继续进来。
核心是:不能保证立刻杀死卡住的 actor,但能保证调用方不会无限等待,也不会让后续请求无止境堆积。默认执行 timeout 是 1800 秒(30 分钟)
| entropies = _outputs.get('entropies', None) | ||
| unpacked_logits = _outputs.get('logits', None) | ||
| except Exception as e: | ||
| # Data processing error (e.g. unpack_packed_sequences dimension mismatch). |
There was a problem hiding this comment.
这里去掉 try-except 的原因呢
There was a problem hiding this comment.
以前出错会偷偷吞掉,再返回零 loss 假装训练成功;现在改成直接报错,让调用方知道训练确实失败了
| _last_grad_norm: float = 0.0 | ||
|
|
||
| def __setattr__(self, name, value): | ||
| if name == 'loss_instance' and value is not None: |
There was a problem hiding this comment.
同上,同样是删掉“出错就用零 loss 顶替”的逻辑



Summary
Hardens Twinkle's serving path with explicit execution bounds, an asynchronous submit/retrieve lifecycle, and strict client/server wire contracts. The client and server now share protocol models, reject invalid requests before GPU work is enqueued, and preserve complete failures through
ErrorPayload.Key changes
Execution guarantees
call_backendplus a per-replica admission gate.TWINKLE_FAIL_FASTswitch; post-timeout liveness probing records backend health.ErrorPayloadframes.Async request lifecycle
run_submit/submit_and_peeksubmit shell and persistentFutureRecordstate.TaskEnvelope; the client future layer retrieves terminal results without holding the original HTTP connection open.(session, adapter, seq_id).Shared strict wire contracts
twinkle.protocol.types; the client builds typed requests and serializes them once before transport.StrictRequestat Twinkle-native HTTP ingress: unknown top-level fields, body tokens, incompatible backend fields, and unavailable endpoints fail before enqueueing work.Client and structural cleanup
ClientTransport/ClientContextownership for routing, session, auth, retry, and request serialization.memoryandredis.Breaking changes
memoryorredis.Validation
pre-commitpasses for all touched files.tinker_myltargeted validation:40 passed, 3 skipped, covering request construction, async client component wire shapes, TensorDict import behavior, and server request-wire contracts.