File size: 2,007 Bytes
9d5790d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
"""Reference adapter contract (documentation — adapters are duck-typed).

An adapter owns everything model-specific: weights resolution (the /repository
mount vs its Hub fallback), preprocessing, the inference call, and its CHUNK
SEMANTICS. The server owns HTTP, auth, image decode, locking, and timing.

    class Adapter:
        def __init__(self, model_path: str): ...
            # model_path = the /repository probe location (may not exist)

        def load(self) -> None: ...
            # Heavy imports (torch/lerobot/transformers) happen HERE, not at
            # module import — the server must import light for tests.

        def act(self, *, images, state, instruction, num_steps, extras)
                -> tuple[np.ndarray, dict]: ...
            # images: list[np.ndarray HxWx3 uint8] in the order of meta()['cameras']
            # state:  np.float32 vector, robot scale (adapter normalizes)
            # returns (chunk [horizon x DOF] robot scale, extra dict e.g. {'rtc': ...})
            # Raise fastapi.HTTPException for contract errors (422/507-style).

        def meta(self) -> dict: ...
            # MUST include: kind, chunk_hz, horizon, dof, cameras (list of the
            # camera roles/keys this policy expects, in /act image order),
            # max_images, source (resolved weights location).
            # The client reads this instead of assuming another model's constants.

        def point(self, *, image, query, max_new_tokens) -> dict: ...   # OPTIONAL

Weights resolution helper shared by all adapters lives here."""

from __future__ import annotations

from pathlib import Path


def resolve_source(model_path: str, hub_fallback: str) -> str:
    """Prefer the platform-mounted weights dir (Inference Endpoints mount the
    endpoint's model repo at /repository); fall back to a Hub repo id."""
    p = Path(model_path)
    try:
        if p.is_dir() and any(p.iterdir()):
            return str(p)
    except OSError:
        pass
    return hub_fallback