Download code/models/autoports/cloudflare_clef/tt/server.py from tt-hous/clef: direct link, hf CLI and curl.
- Browser
- Download file 29.4 kB
-
https://huggingface.co/tt-hous/clef/resolve/main/code/models/autoports/cloudflare_clef/tt/server.py
- Command line
-
hf download hf://tt-hous/clef/code/models/autoports/cloudflare_clef/tt/server.py
-
curl -L -o server.py https://huggingface.co/tt-hous/clef/resolve/main/code/models/autoports/cloudflare_clef/tt/server.py
29.4 kB
| import asyncio | |
| import hashlib | |
| import hmac | |
| import inspect | |
| import logging | |
| import os | |
| import queue | |
| import threading | |
| import time | |
| import uuid | |
| from collections import OrderedDict | |
| from concurrent.futures import Future | |
| from contextlib import asynccontextmanager | |
| from dataclasses import dataclass, field | |
| from pathlib import Path | |
| import torch | |
| from fastapi import FastAPI, HTTPException, Request | |
| from fastapi.exceptions import RequestValidationError | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import JSONResponse | |
| from models.autoports.cloudflare_clef.tt import encode as clef_encode | |
| from models.autoports.cloudflare_clef.tt import head as clef_head | |
| from models.autoports.cloudflare_clef.tt import precision_defaults | |
| from models.autoports.cloudflare_clef.tt.api import SystemOneRequest, api_request, decode_media, to_record | |
| DEFAULT_REPO = "Cloudflare/clef" | |
| DEFAULT_REVISION = "2f3de3dd85f379784083b0814d997ab627200f0c" | |
| DEFAULT_MODEL_NAMES = "clef" | |
| HIDDEN = 5120 | |
| ALIGN = 128 | |
| TP = 2 | |
| L1_SMALL_SIZE = 24576 | |
| COMMAND_QUEUES = 2 | |
| TRACE_REGION = 1 << 30 | |
| ENCODE_MAX_LENGTH = 1 << 31 | |
| API_KEY = os.environ.get("CLEF_API_KEY") | |
| OPEN_PATHS = ("/health", "/v1/health") | |
| PARENTS = {"1x4": ("FABRIC_1D", (1, 4)), "2x2": ("FABRIC_2D", (2, 2))} | |
| MESH_DEVICE_SHAPES = {"P150X2": (1, 2), "P300": (1, 2), "P150X4": (1, 4), "P300X2": (1, 4), "QB2": (2, 2)} | |
| log = logging.getLogger("clef.tt.server") | |
| if not log.handlers: | |
| handler = logging.StreamHandler() | |
| handler.setFormatter(logging.Formatter("%(asctime)s %(name)s %(levelname)s %(message)s")) | |
| log.addHandler(handler) | |
| log.setLevel(logging.INFO) | |
| WARMUP = { | |
| "model": "clef", | |
| "state": "Checkout has been failing for every customer for the last hour.", | |
| "questions": { | |
| "urgent": {"type": "noul", "instructions": "Is this support request urgent?"}, | |
| "team": { | |
| "type": "choice", | |
| "instructions": "Which team should handle this request?", | |
| "criteria": { | |
| "billing": "Payments, invoices, and refunds", | |
| "technical": "Outages, errors, and configuration", | |
| "sales": "Plans and upgrades", | |
| }, | |
| }, | |
| "severity": { | |
| "type": "score", | |
| "instructions": "How severe is the customer impact?", | |
| "criteria": ["No impact", "Minor", "Major", "Critical"], | |
| }, | |
| }, | |
| } | |
| def flag(name, default="0"): | |
| return os.environ.get(name, default) == "1" | |
| def parse_mesh_shape(shape, mesh_device): | |
| if shape: | |
| r, c = shape.lower().split("x") | |
| return int(r), int(c) | |
| return MESH_DEVICE_SHAPES.get((mesh_device or "").upper(), (1, 2)) | |
| def parse_offset(text): | |
| r, c = (text or "0,0").split(",") | |
| return int(r), int(c) | |
| def resolve_model(value, revision=None): | |
| if os.path.isdir(value): | |
| return str(Path(value).resolve()) | |
| from huggingface_hub import snapshot_download | |
| repo, _, at_revision = value.partition("@") | |
| offline = os.environ.get("HF_HUB_OFFLINE") == "1" | |
| return snapshot_download(repo, revision=at_revision or revision or None, local_files_only=offline) | |
| class Settings: | |
| model: str | |
| revision: str | |
| snapshot: str | |
| model_names: tuple | |
| mesh_shape: tuple | |
| parent_mesh: str | |
| submesh_offset: tuple | |
| fake: bool | |
| fake_workers: int | |
| trace_region: int | |
| prefix_cache: int | |
| max_state: int | |
| max_tail: int | |
| truncate: bool | |
| traced: bool | |
| planner: bool = True | |
| allow_remote_images: bool = True | |
| warmup: bool = True | |
| extra: dict = field(default_factory=dict) | |
| def from_env(cls): | |
| model = os.environ.get("CLEF_MODEL") or os.environ.get("HF_MODEL") or DEFAULT_REPO | |
| revision = os.environ.get("CLEF_REVISION", DEFAULT_REVISION) | |
| snapshot = resolve_model(model, revision) | |
| os.environ["CLEF_MODEL"] = snapshot | |
| traced = flag("CLEF_TRACED", "0") | |
| return cls( | |
| model=model, | |
| revision=revision, | |
| snapshot=snapshot, | |
| model_names=tuple( | |
| n.strip() for n in os.environ.get("CLEF_MODEL_NAMES", DEFAULT_MODEL_NAMES).split(",") if n.strip() | |
| ), | |
| mesh_shape=parse_mesh_shape(os.environ.get("CLEF_MESH_SHAPE"), os.environ.get("MESH_DEVICE")), | |
| parent_mesh=os.environ.get("CLEF_PARENT_MESH", ""), | |
| submesh_offset=parse_offset(os.environ.get("CLEF_SUBMESH_OFFSET")), | |
| fake=flag("CLEF_FAKE_ENGINE"), | |
| fake_workers=int(os.environ.get("CLEF_FAKE_WORKERS", "1")), | |
| trace_region=int(os.environ.get("CLEF_TRACE_REGION", str(TRACE_REGION if traced else 0))), | |
| prefix_cache=int(os.environ.get("CLEF_PREFIX_CACHE", "4")), | |
| max_state=int(os.environ.get("CLEF_MAX_STATE", "16384")), | |
| max_tail=int(os.environ.get("CLEF_MAX_TAIL", "4096")), | |
| truncate=flag("CLEF_TRUNCATE_STATES"), | |
| traced=traced, | |
| planner=flag("CLEF_PLANNER", "1"), | |
| allow_remote_images=flag("CLEF_ALLOW_REMOTE_IMAGES", "1"), | |
| warmup=flag("CLEF_WARMUP", "1"), | |
| ) | |
| def mesh_plan(mesh_shape, visible, parent="", offset=(0, 0)): | |
| r, c = mesh_shape | |
| if (r, c) == (1, 2): | |
| if parent or visible > 2: | |
| name = parent or "1x4" | |
| if name not in PARENTS: | |
| raise ValueError(f"CLEF_PARENT_MESH={name!r}; expected one of {sorted(PARENTS)}") | |
| fabric, shape = PARENTS[name] | |
| return {"fabric": fabric, "open": shape, "submeshes": [((1, 2), tuple(offset))], "parent": name} | |
| return {"fabric": "FABRIC_1D", "open": (1, 2), "submeshes": [], "parent": None} | |
| if (r, c) == (1, 4): | |
| if parent: | |
| raise ValueError("CLEF_PARENT_MESH is only supported for CLEF_MESH_SHAPE=1x2") | |
| return { | |
| "fabric": "FABRIC_1D", | |
| "open": (1, 4), | |
| "submeshes": [((1, 2), (0, 0)), ((1, 2), (0, 2))], | |
| "parent": None, | |
| } | |
| if (r, c) == (2, 2): | |
| if parent: | |
| raise ValueError("CLEF_PARENT_MESH is only supported for CLEF_MESH_SHAPE=1x2") | |
| return { | |
| "fabric": "FABRIC_2D", | |
| "open": (2, 2), | |
| "submeshes": [((1, 2), (0, 0)), ((1, 2), (1, 0))], | |
| "parent": None, | |
| } | |
| raise ValueError(f"unsupported mesh shape {r}x{c}; Clef runs TP={TP} groups on 1x2, 1x4 or 2x2") | |
| def visible_chips(): | |
| import ttnn | |
| return len(ttnn.get_device_ids()) | |
| def open_devices(settings): | |
| import ttnn | |
| visible = visible_chips() | |
| plan = mesh_plan(settings.mesh_shape, visible, settings.parent_mesh, settings.submesh_offset) | |
| ttnn.set_fabric_config(getattr(ttnn.FabricConfig, plan["fabric"])) | |
| parent = ttnn.open_mesh_device( | |
| mesh_shape=ttnn.MeshShape(*plan["open"]), | |
| l1_small_size=L1_SMALL_SIZE, | |
| num_command_queues=COMMAND_QUEUES, | |
| trace_region_size=settings.trace_region, | |
| ) | |
| groups = [] | |
| for shape, offset in plan["submeshes"]: | |
| groups.append(parent.create_submesh(ttnn.MeshShape(*shape), offset=ttnn.MeshCoordinate(*offset))) | |
| if not groups: | |
| groups = [parent] | |
| for group in groups: | |
| group.enable_program_cache() | |
| log.info( | |
| "mesh: %d chip(s) visible, %s parent %s chips %s, %d TP group(s) %s", | |
| visible, | |
| plan["fabric"], | |
| list(parent.shape), | |
| list(parent.get_device_ids()), | |
| len(groups), | |
| [list(g.get_device_ids()) for g in groups], | |
| ) | |
| def close(): | |
| for group in groups: | |
| ttnn.synchronize_device(group) | |
| for child in parent.get_submeshes(): | |
| ttnn.close_mesh_device(child) | |
| ttnn.close_mesh_device(parent) | |
| ttnn.set_fabric_config(ttnn.FabricConfig.DISABLED) | |
| return parent, groups, close, plan | |
| def accepted_kwargs(fn, candidates): | |
| params = inspect.signature(fn).parameters | |
| if any(p.kind == inspect.Parameter.VAR_KEYWORD for p in params.values()): | |
| return dict(candidates) | |
| return {k: v for k, v in candidates.items() if k in params} | |
| def build_engine(mesh, settings): | |
| from models.autoports.cloudflare_clef.tt.engine import ClefEngine | |
| candidates = dict( | |
| max_state_len=settings.max_state, | |
| max_tail_len=settings.max_tail, | |
| snapshot_slots=max(1, settings.prefix_cache), | |
| traced=settings.traced, | |
| planner=settings.planner, | |
| ) | |
| return ClefEngine(mesh, **accepted_kwargs(ClefEngine.__init__, candidates)) | |
| def build_fake_engine(settings): | |
| from models.autoports.cloudflare_clef.tt.fake_engine import FakeEngine | |
| return FakeEngine( | |
| max_state_len=settings.max_state, max_tail_len=settings.max_tail, snapshot_slots=max(1, settings.prefix_cache) | |
| ) | |
| def media_key(ids, media_digest): | |
| key = clef_encode.cache_key(ids) | |
| if media_digest is None: | |
| return key | |
| return hashlib.sha1(f"{key}:{media_digest}".encode()).hexdigest() | |
| class Job: | |
| ids: list | |
| state_ids: list | |
| tail_ids: list | |
| encoded: object | |
| media: dict | |
| key: str | |
| questions: dict | |
| def supports_media(engine): | |
| try: | |
| return "media" in inspect.signature(engine.prefill_state).parameters | |
| except (TypeError, ValueError): | |
| return bool(getattr(engine, "supports_media", False)) | |
| def supports_tail_len(engine): | |
| try: | |
| return "tail_len" in inspect.signature(engine.prefill_state).parameters | |
| except (TypeError, ValueError): | |
| return False | |
| class Worker: | |
| def __init__(self, wid, build, head, lm_rows, cache_size): | |
| self.id = wid | |
| self.build = build | |
| self.head = head | |
| self.lm_rows = lm_rows | |
| self.cache_size = cache_size | |
| self.queue = queue.Queue() | |
| self.cache = OrderedDict() | |
| self.free_slots = [] | |
| self.hits = self.misses = self.requests = 0 | |
| self.inflight = 0 | |
| self.counter = threading.Lock() | |
| self.ready = threading.Event() | |
| self.error = None | |
| self.engine = None | |
| self.media_ok = False | |
| self.tail_len_ok = False | |
| self.traced = False | |
| self.warm_grids = None | |
| self.gdn_conv = None | |
| self.planner = None | |
| self.thread = threading.Thread(target=self._run, name=f"clef-worker-{wid}", daemon=True) | |
| self.thread.start() | |
| def load(self): | |
| return self.queue.qsize() + self.inflight | |
| def submit(self, job): | |
| done = Future() | |
| with self.counter: | |
| self.inflight += 1 | |
| self.queue.put((job, done)) | |
| return done | |
| def stop(self): | |
| self.queue.put(None) | |
| self.thread.join() | |
| def _run(self): | |
| try: | |
| self.engine = self.build() | |
| slots = getattr(self.engine, "snapshot_slots", 1) | |
| self.cache_size = min(self.cache_size, slots) | |
| self.free_slots = list(range(self.cache_size)) | |
| self.media_ok = supports_media(self.engine) | |
| self.tail_len_ok = supports_tail_len(self.engine) | |
| self.traced = bool(getattr(self.engine, "traced", False)) | |
| self.gdn_conv = getattr(self.engine, "gdn_conv_impl", None) | |
| self.planner = getattr(self.engine, "planner", None) | |
| if self.traced: | |
| self.warm_grids = sorted(tuple(g) for g, _ in getattr(self.engine, "vision_warmed_grids", [])) | |
| except Exception as error: | |
| self.error = error | |
| self.ready.set() | |
| return | |
| self.ready.set() | |
| while True: | |
| item = self.queue.get() | |
| if item is None: | |
| return | |
| job, done = item | |
| try: | |
| done.set_result(self._serve(job)) | |
| except Exception as error: | |
| done.set_exception(error) | |
| finally: | |
| with self.counter: | |
| self.inflight -= 1 | |
| def _media_kwargs(self, job): | |
| if job.media is None: | |
| return {} | |
| if not self.media_ok: | |
| raise HTTPException(422, "this server build does not accept images or videos") | |
| return {"media": job.media} | |
| def _serve(self, job): | |
| t0 = time.perf_counter() | |
| ids = torch.tensor([job.ids], dtype=torch.long) | |
| hit = False | |
| if self.cache_size == 0: | |
| hidden = self.engine.prefill_hidden(ids, slot=0, **self._media_kwargs(job)) | |
| else: | |
| entry = self.cache.get(job.key) | |
| hit = entry is not None | |
| if hit: | |
| self.cache.move_to_end(job.key) | |
| self.hits += 1 | |
| handle, slot = entry | |
| else: | |
| self.misses += 1 | |
| slot = self.free_slots.pop() if self.free_slots else self.cache.popitem(last=False)[1][1] | |
| hint = {"tail_len": len(job.tail_ids)} if self.tail_len_ok else {} | |
| try: | |
| handle = self.engine.prefill_state( | |
| torch.tensor([job.state_ids], dtype=torch.long), | |
| slot=slot, | |
| key=job.key, | |
| **self._media_kwargs(job), | |
| **hint, | |
| ) | |
| except ValueError as error: | |
| self.free_slots.append(slot) | |
| raise HTTPException(422, str(error)) | |
| except Exception: | |
| self.free_slots.append(slot) | |
| raise | |
| self.cache[job.key] = (handle, slot) | |
| tail = self.engine.schema_hidden(handle, torch.tensor([job.tail_ids], dtype=torch.long)) | |
| hidden = torch.cat([self.engine.prefix_hidden[slot], tail], dim=0) | |
| probs = clef_head.probs_for_record(self.head, hidden, ids[0], job.encoded, self.lm_rows) | |
| self.requests += 1 | |
| return probs, hit, round((time.perf_counter() - t0) * 1000, 1) | |
| class Server: | |
| def __init__(self, settings): | |
| self.settings = settings | |
| self.snapshot = settings.snapshot | |
| self.release = clef_encode.release_module(self.snapshot) | |
| self.tok = clef_encode.load_tokenizer(self.snapshot) | |
| self.processor = None | |
| self.head = clef_head.load_head(self.snapshot) | |
| self.parent = None | |
| self.close_devices = lambda: None | |
| self.plan = None | |
| self.lock = threading.Lock() | |
| self.workers = [] | |
| self.stopping = threading.Event() | |
| self.device_name = "none" | |
| self.started = time.time() | |
| def start(cls, settings): | |
| server = cls(settings) | |
| server.open() | |
| if settings.warmup: | |
| server.warmup() | |
| return server | |
| def processor_for_media(self): | |
| if self.processor is None: | |
| with self.lock: | |
| if self.processor is None: | |
| self.processor = clef_encode.load_processor(self.snapshot) | |
| return self.processor | |
| def _lm_rows(self): | |
| from models.autoports.cloudflare_clef.tt.loader import LmHeadRows | |
| return LmHeadRows(self.snapshot) | |
| def open(self): | |
| s = self.settings | |
| if s.fake: | |
| builds = [(f"fake{i}", lambda: build_fake_engine(s)) for i in range(max(1, s.fake_workers))] | |
| self.device_name = f"fake x{len(builds)}" | |
| else: | |
| self.parent, groups, self.close_devices, self.plan = open_devices(s) | |
| builds = [(str(list(g.get_device_ids())), lambda g=g: build_engine(g, s)) for g in groups] | |
| self.device_name = f"ttnn {s.mesh_shape[0]}x{s.mesh_shape[1]}: {len(groups)} TP={TP} worker(s)" | |
| self.workers = [ | |
| Worker(i, build, self.head, self._lm_rows(), s.prefix_cache) for i, (_, build) in enumerate(builds) | |
| ] | |
| for w, (name, _) in zip(self.workers, builds): | |
| w.ready.wait() | |
| if w.error is not None: | |
| self.close() | |
| raise RuntimeError(f"worker {w.id} ({name}) failed to load") from w.error | |
| log.info( | |
| "worker %d ready on %s, prefix cache %d state(s), media=%s, mode=%s, gdn_conv=%s, planner=%s, " | |
| "warm_grids=%s", | |
| w.id, | |
| name, | |
| w.cache_size, | |
| w.media_ok, | |
| "traced" if w.traced else "eager", | |
| w.gdn_conv, | |
| w.planner, | |
| w.warm_grids, | |
| ) | |
| def warmup(self): | |
| req = SystemOneRequest.model_validate(WARMUP) | |
| job, _ = self.encode(req) | |
| for w in self.workers: | |
| probs, _, ms = w.submit(job).result() | |
| log.info("warmup worker=%d questions=%d latency_ms=%.1f", w.id, len(probs), ms) | |
| def close(self): | |
| if self.stopping.is_set(): | |
| return | |
| self.stopping.set() | |
| for w in self.workers: | |
| if w.ready.is_set() and w.error is None: | |
| w.stop() | |
| self.close_devices() | |
| def _encode_record(self, record, processor, max_state_tokens=None): | |
| try: | |
| encoded = clef_encode.encode( | |
| self.tok, record, processor=processor, max_length=ENCODE_MAX_LENGTH, max_state_tokens=max_state_tokens | |
| ) | |
| except ValueError as error: | |
| raise HTTPException(422, str(error)) | |
| try: | |
| state_ids, tail_ids, _ = clef_encode.split_for_cache(encoded, self.tok, record) | |
| except ValueError as error: | |
| raise HTTPException(500, f"prefix split failed: {error}") | |
| return encoded, state_ids, tail_ids | |
| def encode(self, req): | |
| s = self.settings | |
| try: | |
| images, videos, media_digest = decode_media(req) | |
| except ValueError as error: | |
| raise HTTPException(422, str(error)) | |
| record = to_record(req, images, videos) | |
| processor = self.processor_for_media() if (images or videos) else None | |
| encoded, state_ids, tail_ids = self._encode_record(record, processor) | |
| if encoded.media: | |
| self.check_warm_grids(encoded.media) | |
| S = len(state_ids) | |
| stats = {"state_tokens": S, "state_tokens_used": S} | |
| if S > s.max_state: | |
| n_state = len(self.release._tokens(self.tok, self.release.render(req.state))) | |
| fixed = S - n_state | |
| keep = s.max_state - fixed | |
| if not s.truncate or keep < 0: | |
| raise HTTPException(422, overflow_message(S, fixed, s.max_state)) | |
| encoded, state_ids, tail_ids = self._encode_record(record, processor, max_state_tokens=keep) | |
| stats["state_tokens_used"] = len(state_ids) | |
| if len(tail_ids) > s.max_tail: | |
| raise HTTPException( | |
| 422, | |
| f"schema is {len(tail_ids):,} tokens, over the {s.max_tail:,}-token limit: " | |
| "use fewer questions or shorter criteria, or split them across requests", | |
| ) | |
| key = media_key(state_ids, media_digest) | |
| job = Job(list(encoded.input_ids), state_ids, tail_ids, encoded, encoded.media, key, req.question_dicts()) | |
| stats["tokens"] = len(encoded.input_ids) | |
| stats["images"] = len(images) | |
| stats["videos"] = len(videos) | |
| return job, stats | |
| def warm_grids(self): | |
| lists = [w.warm_grids for w in self.workers if w.warm_grids is not None] | |
| if not lists: | |
| return None | |
| return sorted({grid for grids in lists for grid in grids}) | |
| def check_warm_grids(self, media): | |
| warm = self.warm_grids() | |
| if warm is None: | |
| return | |
| rows = [] | |
| for name in ("image_grid_thw", "video_grid_thw"): | |
| grids = media.get(name) | |
| if grids is not None: | |
| rows.extend(torch.as_tensor(grids).reshape(-1, 3).tolist()) | |
| if len(rows) > 1: | |
| raise HTTPException(422, single_grid_message(len(rows))) | |
| for grid in rows: | |
| if tuple(grid) not in warm: | |
| raise HTTPException(422, warm_grid_message(tuple(grid), warm)) | |
| def pick_worker(self, key): | |
| with self.lock: | |
| for w in self.workers: | |
| if key in w.cache: | |
| return w | |
| return min(self.workers, key=lambda w: (w.load(), w.id)) | |
| def submit(self, req): | |
| if self.stopping.is_set(): | |
| raise HTTPException(503, "the server is stopping") | |
| job, stats = self.encode(req) | |
| worker = self.pick_worker(job.key) | |
| done = Future() | |
| inner = worker.submit(job) | |
| def finish(f): | |
| if f.exception() is not None: | |
| done.set_exception(f.exception()) | |
| return | |
| probs, hit, ms = f.result() | |
| stats.update(worker=worker.id, latency_ms=ms, prefix_cache_hit=hit) | |
| log.info( | |
| "worker=%d S=%d tail=%d questions=%d images=%d videos=%d latency_ms=%.1f cache_hit=%s", | |
| worker.id, | |
| stats["state_tokens_used"], | |
| len(job.tail_ids), | |
| len(probs), | |
| stats["images"], | |
| stats["videos"], | |
| ms, | |
| hit, | |
| ) | |
| done.set_result((probs, stats, job)) | |
| inner.add_done_callback(finish) | |
| return done | |
| def as_request(self, rec): | |
| return rec if isinstance(rec, SystemOneRequest) else SystemOneRequest.model_validate(api_request(rec)) | |
| def predict(self, rec): | |
| probs, stats, _ = self.submit(self.as_request(rec)).result() | |
| return probs, stats | |
| def answer(self, req): | |
| return self.body(req, *self.submit(req).result()) | |
| async def answer_async(self, req): | |
| return self.body(req, *await asyncio.wrap_future(self.submit(req))) | |
| def body(self, req, probs, stats, job): | |
| answers = {qid: self.release.systemone_answer(job.questions[qid], dist) for qid, dist in probs.items()} | |
| body = { | |
| "model": req.model, | |
| "answers": answers, | |
| "usage": {"input_tokens": stats["tokens"], "output_tokens": 0}, | |
| "latency_ms": stats["latency_ms"], | |
| } | |
| if self.settings.truncate: | |
| body["usage"].update(state_tokens=stats["state_tokens"], state_tokens_used=stats["state_tokens_used"]) | |
| body["truncated"] = stats["state_tokens"] > stats["state_tokens_used"] | |
| return body | |
| def card(self): | |
| s = self.settings | |
| workers = [ | |
| { | |
| "id": w.id, | |
| "queued": w.load(), | |
| "cached_states": len(w.cache), | |
| "cache_size": w.cache_size, | |
| "hits": w.hits, | |
| "misses": w.misses, | |
| "requests": w.requests, | |
| "media": w.media_ok, | |
| } | |
| for w in self.workers | |
| ] | |
| backend = "fake engine" if s.fake else "ttnn, TP=2" | |
| warm = self.warm_grids() | |
| traced_media = None | |
| if warm is not None: | |
| traced_media = { | |
| "warm_grids": [list(grid) for grid in warm], | |
| "rule": "one image or video grid per request, and a grid (t, h, w) outside this list is refused " | |
| "with 422; eager (CLEF_TRACED=0) accepts any grid and several images or videos per request", | |
| } | |
| return { | |
| "description": f"Cloudflare/clef joint schema decisions on Tenstorrent ({backend})", | |
| "weights": {"repo": DEFAULT_REPO, "revision": s.revision, "snapshot": self.snapshot}, | |
| "device": self.device_name, | |
| "mesh_shape": f"{s.mesh_shape[0]}x{s.mesh_shape[1]}", | |
| "mesh_plan": self.plan, | |
| "backend": "fake" if s.fake else "ttnn", | |
| "precision": precision_defaults.active(), | |
| "traced": s.traced, | |
| "mode": "traced" if s.traced else "eager", | |
| "gdn_conv": next((w.gdn_conv for w in self.workers if w.gdn_conv), None), | |
| "prefix_planner": s.planner, | |
| "traced_media": traced_media, | |
| "max_state_tokens": s.max_state, | |
| "max_schema_tokens": s.max_tail, | |
| "truncate_states": s.truncate, | |
| "remote_images": s.allow_remote_images, | |
| "prefix_cache": { | |
| "size": s.prefix_cache, | |
| "hits": sum(w.hits for w in self.workers), | |
| "misses": sum(w.misses for w in self.workers), | |
| "cached_states": sum(len(w.cache) for w in self.workers), | |
| }, | |
| "workers": workers, | |
| "requests": sum(w.requests for w in self.workers), | |
| "uptime_s": round(time.time() - self.started, 1), | |
| } | |
| def overflow_message(S, fixed, max_state): | |
| return ( | |
| f"state is {S:,} tokens ({fixed} of them the system prompt and media placeholders), " | |
| f"over the {max_state:,}-token limit: shorten the state or split it across requests; " | |
| f"or start the server with CLEF_TRUNCATE_STATES=1 to read only its first {max_state:,} tokens " | |
| "(responses then say truncated: true)" | |
| ) | |
| def warm_grid_message(grid, warm): | |
| grids = "; ".join(",".join(str(x) for x in g) for g in warm) | |
| return ( | |
| f"image grid {grid} (t, h, w patches) is not in this traced server's warm list [{grids}]: " | |
| "resize the image to a warmed grid, add the grid to CLEF_VISION_WARM_GRID at startup, " | |
| "or serve with CLEF_TRACED=0 (the default), which accepts any grid" | |
| ) | |
| def single_grid_message(n_grids): | |
| return ( | |
| f"this request carries {n_grids} image or video grids; a traced server (CLEF_TRACED=1) takes one grid " | |
| "per request, because the tower joins several images with a concat program compiled per image count " | |
| "and no vision program may compile while traces are live: send one image (or one video) per request, " | |
| "or serve with CLEF_TRACED=0 (the default), which accepts several" | |
| ) | |
| async def lifespan(app): | |
| settings = Settings.from_env() | |
| log.info( | |
| "starting: model=%s snapshot=%s fake=%s mesh=%s parent=%s offset=%s prefix_cache=%d max_state=%d " | |
| "max_tail=%d truncate=%s traced=%s planner=%s trace_region=%d", | |
| settings.model, | |
| settings.snapshot, | |
| settings.fake, | |
| settings.mesh_shape, | |
| settings.parent_mesh or "auto", | |
| settings.submesh_offset, | |
| settings.prefix_cache, | |
| settings.max_state, | |
| settings.max_tail, | |
| settings.truncate, | |
| settings.traced, | |
| settings.planner, | |
| settings.trace_region, | |
| ) | |
| app.state.server = await asyncio.to_thread(Server.start, settings) | |
| server_ = app.state.server | |
| log.info( | |
| "ready: %d worker(s) on %s, mode=%s, gdn_conv=%s, planner=%s, warm_grids=%s", | |
| len(server_.workers), | |
| server_.device_name, | |
| "traced" if settings.traced else "eager", | |
| next((w.gdn_conv for w in server_.workers if w.gdn_conv), None), | |
| settings.planner, | |
| server_.warm_grids(), | |
| ) | |
| try: | |
| yield | |
| finally: | |
| app.state.server.close() | |
| app = FastAPI(title="clef-tt", lifespan=lifespan) | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| expose_headers=["x-typesafe-request-id", "server-timing"], | |
| ) | |
| def validation_detail(error): | |
| errors = error.errors() | |
| if not errors: | |
| return "invalid request" | |
| first = errors[0] | |
| msg = str(first.get("msg", "invalid request")) | |
| if msg.startswith("Value error, "): | |
| return msg[len("Value error, ") :] | |
| loc = ".".join(str(p) for p in first.get("loc", ()) if p != "body") | |
| return f"{loc}: {msg}" if loc else msg | |
| async def on_validation_error(request: Request, error: RequestValidationError): | |
| return JSONResponse({"detail": validation_detail(error)}, 422) | |
| async def typesafe(request, call_next): | |
| started = time.perf_counter() | |
| path = request.url.path | |
| if ( | |
| API_KEY | |
| and path.startswith("/v1") | |
| and path not in OPEN_PATHS | |
| and not hmac.compare_digest(request.headers.get("authorization", ""), f"Bearer {API_KEY}") | |
| ): | |
| resp = JSONResponse( | |
| {"detail": "missing or invalid API key; send Authorization: Bearer <CLEF_API_KEY>"}, | |
| 401, | |
| {"www-authenticate": "Bearer"}, | |
| ) | |
| else: | |
| resp = await call_next(request) | |
| resp.headers["x-typesafe-request-id"] = request.headers.get("x-typesafe-request-id") or uuid.uuid4().hex | |
| resp.headers["server-timing"] = f"app;dur={(time.perf_counter() - started) * 1000:.1f}" | |
| return resp | |
| def server() -> Server: | |
| return app.state.server | |
| async def systemone(req: SystemOneRequest): | |
| return await server().answer_async(req) | |
| def models(): | |
| card = server().card() | |
| return {"models": [{"name": name, **card} for name in server().settings.model_names]} | |
| def health(): | |
| s = server() | |
| return {"status": "ok", "workers": len(s.workers), "queued": sum(w.load() for w in s.workers)} | |
| def main(): | |
| import argparse | |
| import uvicorn | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--host", default="127.0.0.1") | |
| ap.add_argument("--port", type=int, default=8008) | |
| a = ap.parse_args() | |
| uvicorn.run(app, host=a.host, port=a.port, lifespan="on") | |
| if __name__ == "__main__": | |
| main() | |