Skip to content

Commit 3bd78ae

Browse files
committed
update twinkle
1 parent eec089a commit 3bd78ae

File tree

21 files changed

+618
-417
lines changed

21 files changed

+618
-417
lines changed

client_tools/client_generator.py

Lines changed: 88 additions & 116 deletions
Large diffs are not rendered by default.

src/twinkle/server/gateway/proxy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def _prepare_headers(self, request_headers) -> dict[str, str]:
6767
headers.pop('host', None)
6868
headers.pop('content-length', None)
6969
request_id = request_headers.get('X-Ray-Serve-Request-Id')
70-
if request_id is not None:
70+
if request_id is not None and not request_headers.get('serve_multiplexed_model_id'):
7171
headers['serve_multiplexed_model_id'] = request_id
7272
return headers
7373

src/twinkle/server/gateway/twinkle_gateway_handlers.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"""
77
from __future__ import annotations
88

9-
from fastapi import FastAPI, HTTPException, Request
9+
from fastapi import Depends, FastAPI, HTTPException, Request
1010
from typing import TYPE_CHECKING, Callable
1111

1212
if TYPE_CHECKING:
@@ -17,6 +17,8 @@
1717
from twinkle.server.utils.validation import get_token_from_request
1818
from twinkle.utils.logger import get_logger
1919
from twinkle_client.types.server import DeleteCheckpointResponse, HealthResponse, WeightsInfoRequest
20+
from twinkle_client.types.session import (CreateSessionRequest, CreateSessionResponse, SessionHeartbeatRequest,
21+
SessionHeartbeatResponse)
2022
from twinkle_client.types.training import (CheckpointsListResponse, TrainingRun, TrainingRunsResponse,
2123
WeightsInfoResponse)
2224

@@ -30,6 +32,26 @@ def _register_twinkle_routes(app: FastAPI, self_fn: Callable[[], GatewayServer])
3032
async def healthz(request: Request) -> HealthResponse:
3133
return HealthResponse(status='ok')
3234

35+
@app.post('/twinkle/create_session', response_model=CreateSessionResponse)
36+
async def create_session(
37+
request: Request,
38+
body: CreateSessionRequest,
39+
self: GatewayServer = Depends(self_fn),
40+
) -> CreateSessionResponse:
41+
session_id = self.state.create_session(body.model_dump())
42+
return CreateSessionResponse(session_id=session_id)
43+
44+
@app.post('/twinkle/session_heartbeat', response_model=SessionHeartbeatResponse)
45+
async def session_heartbeat(
46+
request: Request,
47+
body: SessionHeartbeatRequest,
48+
self: GatewayServer = Depends(self_fn),
49+
) -> SessionHeartbeatResponse:
50+
alive = self.state.touch_session(body.session_id)
51+
if not alive:
52+
raise HTTPException(status_code=404, detail='Unknown session')
53+
return SessionHeartbeatResponse()
54+
3355
@app.get('/twinkle/training_runs', response_model=TrainingRunsResponse)
3456
async def get_training_runs(request: Request, limit: int = 20, offset: int = 0) -> TrainingRunsResponse:
3557
token = get_token_from_request(request)

src/twinkle_client/__init__.py

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
# Copyright (c) ModelScope Contributors. All rights reserved.
22
from __future__ import annotations
3+
from typing import Optional
4+
35

46
def init_tinker_client(**kwargs) -> None:
57
"""Initialize Tinker client with Twinkle-specific headers.
68
7-
After calling this function, users can directly use:
9+
After calling this function, users can directly use::
10+
811
from tinker import ServiceClient
912
client = ServiceClient(base_url='...', api_key='...')
1013
@@ -13,39 +16,57 @@ def init_tinker_client(**kwargs) -> None:
1316
Args:
1417
**kwargs: Additional keyword arguments (currently unused, reserved for future)
1518
16-
Example:
17-
>>> from twinkle import init_tinker_client
19+
Example::
20+
21+
>>> from twinkle_client import init_tinker_client
1822
>>> init_tinker_client()
1923
>>> from tinker import ServiceClient
2024
>>> client = ServiceClient(base_url='http://localhost:8000', api_key='your_token')
2125
"""
2226
from twinkle.utils import requires
23-
27+
2428
requires('tinker')
2529
from twinkle_client.utils.patch_tinker import patch_tinker
2630

27-
# Apply patches to tinker library (includes header injection)
2831
patch_tinker()
2932

3033

31-
def init_twinkle_client(base_url: str | None = None, api_key: str | None = None, **kwargs) -> TwinkleClient:
34+
def init_twinkle_client(
35+
base_url: Optional[str] = None,
36+
api_key: Optional[str] = None,
37+
session_heartbeat_interval: int = 30,
38+
**kwargs,
39+
) -> 'TwinkleClient':
3240
"""
33-
Initialize a Twinkle client and setup context variables.
41+
Initialize a Twinkle client.
42+
43+
This function:
44+
45+
* Resolves ``base_url`` and ``api_key`` (env-vars as fallbacks).
46+
* Sets both values into the shared context so that all other client objects
47+
(``MultiLoraTransformersModel``, ``vLLMSampler``, processor clients) created
48+
afterwards automatically inherit the same server configuration.
49+
* Creates a server-side session and stores the ``session_id`` in context so
50+
every subsequent HTTP request carries it in ``X-Twinkle-Session-Id``.
51+
* Starts a background thread that touches the session every
52+
``session_heartbeat_interval`` seconds.
53+
54+
Args:
55+
base_url: Twinkle server base URL. Falls back to ``TWINKLE_SERVER_URL``.
56+
api_key: Authentication token. Falls back to ``TWINKLE_SERVER_TOKEN``.
57+
session_heartbeat_interval: Seconds between session touch calls (default: 30).
58+
**kwargs: Additional keyword arguments forwarded to :class:`TwinkleClient`.
59+
60+
Returns:
61+
An initialised :class:`~twinkle_client.manager.TwinkleClient` instance.
3462
"""
35-
from .http.utils import get_api_key, get_base_url, set_api_key, set_base_url
36-
from .manager import TwinkleClient, TwinkleClientError
37-
38-
if base_url is not None:
39-
set_base_url(base_url)
40-
else:
41-
base_url = get_base_url()
42-
43-
if api_key is not None:
44-
set_api_key(api_key)
45-
else:
46-
api_key = get_api_key()
47-
48-
return TwinkleClient(base_url=base_url, api_key=api_key, **kwargs)
63+
from .manager import TwinkleClient
64+
return TwinkleClient(
65+
base_url=base_url,
66+
api_key=api_key,
67+
session_heartbeat_interval=session_heartbeat_interval,
68+
**kwargs,
69+
)
4970

5071

5172
__all__ = ['init_tinker_client', 'init_twinkle_client']

src/twinkle_client/dataloader/dataloader.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
# ============================================================================
1111

1212
from typing import Callable, Type, Union
13-
from twinkle_client.http import http_post, heartbeat_manager
13+
from twinkle_client.http import http_post
1414
from twinkle.dataset import Dataset
1515
from twinkle.processor import InputProcessor
1616

@@ -31,13 +31,6 @@ def __init__(self, dataset: Union[Dataset, Callable], **kwargs):
3131
)
3232
response.raise_for_status()
3333
self.processor_id = response.json()['processor_id']
34-
heartbeat_manager.register_processor(self.processor_id)
35-
36-
def __del__(self):
37-
try:
38-
heartbeat_manager.unregister_processor(self.processor_id)
39-
except:
40-
pass
4134

4235

4336
def __len__(self):

src/twinkle_client/dataset/base.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
# ============================================================================
1111

1212
from typing import Any, Callable, Dict, Type, Union
13-
from twinkle_client.http import http_post, heartbeat_manager
13+
from twinkle_client.http import http_post
1414
from twinkle.dataset import Dataset
1515
from twinkle.dataset import DatasetMeta
1616
from twinkle.preprocessor import DataFilter
@@ -34,13 +34,6 @@ def __init__(self, dataset_meta: DatasetMeta, **kwargs):
3434
)
3535
response.raise_for_status()
3636
self.processor_id = response.json()['processor_id']
37-
heartbeat_manager.register_processor(self.processor_id)
38-
39-
def __del__(self):
40-
try:
41-
heartbeat_manager.unregister_processor(self.processor_id)
42-
except:
43-
pass
4437

4538

4639
def set_template(self, template_func: Union[Template, Type[Template], str], **kwargs):

src/twinkle_client/dataset/iterable_dataset.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
# 2. Run: python client_tools/client_generator.py
1010
# ============================================================================
1111

12-
from twinkle_client.http import http_post, heartbeat_manager
12+
from twinkle_client.http import http_post
1313
from twinkle.dataset import Dataset
1414
from twinkle.dataset import DatasetMeta
1515
from torch.utils.data import IterableDataset
@@ -31,13 +31,6 @@ def __init__(self, dataset_meta: DatasetMeta, **kwargs):
3131
)
3232
response.raise_for_status()
3333
self.processor_id = response.json()['processor_id']
34-
heartbeat_manager.register_processor(self.processor_id)
35-
36-
def __del__(self):
37-
try:
38-
heartbeat_manager.unregister_processor(self.processor_id)
39-
except:
40-
pass
4134

4235

4336
def add_dataset(self, dataset_meta: DatasetMeta, **kwargs):

src/twinkle_client/dataset/iterable_packing_dataset.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
# ============================================================================
1111

1212
from typing import Type, Union
13-
from twinkle_client.http import http_post, heartbeat_manager
13+
from twinkle_client.http import http_post
1414
from twinkle.dataset import Dataset
1515
from twinkle.dataset import DatasetMeta
1616
from twinkle.template import Template
@@ -33,13 +33,6 @@ def __init__(self, dataset_meta: DatasetMeta, packing_interval: int = 128, packi
3333
)
3434
response.raise_for_status()
3535
self.processor_id = response.json()['processor_id']
36-
heartbeat_manager.register_processor(self.processor_id)
37-
38-
def __del__(self):
39-
try:
40-
heartbeat_manager.unregister_processor(self.processor_id)
41-
except:
42-
pass
4336

4437

4538
def set_template(self, template_cls: Union[Type[Template], str, Template], **kwargs):

src/twinkle_client/dataset/lazy_dataset.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
# 2. Run: python client_tools/client_generator.py
1010
# ============================================================================
1111

12-
from twinkle_client.http import http_post, heartbeat_manager
12+
from twinkle_client.http import http_post
1313
from twinkle.dataset import Dataset
1414
from twinkle.dataset import DatasetMeta
1515
from .base import Dataset
@@ -31,13 +31,6 @@ def __init__(self, dataset_meta: DatasetMeta, **kwargs):
3131
)
3232
response.raise_for_status()
3333
self.processor_id = response.json()['processor_id']
34-
heartbeat_manager.register_processor(self.processor_id)
35-
36-
def __del__(self):
37-
try:
38-
heartbeat_manager.unregister_processor(self.processor_id)
39-
except:
40-
pass
4134

4235

4336
def encode(self, **kwargs):

src/twinkle_client/dataset/packing_dataset.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
# 2. Run: python client_tools/client_generator.py
1010
# ============================================================================
1111

12-
from twinkle_client.http import http_post, heartbeat_manager
12+
from twinkle_client.http import http_post
1313
from twinkle.dataset import Dataset
1414
from twinkle.dataset import DatasetMeta
1515
from .base import Dataset
@@ -31,13 +31,6 @@ def __init__(self, dataset_meta: DatasetMeta, packing_num_proc: int = 1, **kwarg
3131
)
3232
response.raise_for_status()
3333
self.processor_id = response.json()['processor_id']
34-
heartbeat_manager.register_processor(self.processor_id)
35-
36-
def __del__(self):
37-
try:
38-
heartbeat_manager.unregister_processor(self.processor_id)
39-
except:
40-
pass
4134

4235

4336
def pack_dataset(self):

0 commit comments

Comments
 (0)