ShubhamSetia commited on
Commit
7fdbbb5
·
1 Parent(s): 9543536

feat: add optional OpenBMB actor backend

Browse files
app.py CHANGED
@@ -1,9 +1,11 @@
1
  from html import escape
 
2
  from time import sleep
3
 
4
  import gradio as gr
5
 
6
  from puppet_theater import (
 
7
  TheaterSession,
8
  create_show_from_premise,
9
  request_finale,
@@ -28,6 +30,8 @@ EMPTY_TRANSCRIPT = "No show yet. The transcript will appear here."
28
  EMPTY_DIRECTOR_LOG = "No director notes yet."
29
  EMPTY_TRACE = "No trace events yet."
30
  EMPTY_BACKEND = "Active backend: deterministic\nFallback: deterministic safety path enabled"
 
 
31
  PLAYBACK_DELAY_SECONDS = 0.75
32
  PROP_EMOJI = {
33
  "rubber duck": "🐤",
@@ -912,12 +916,28 @@ def render_trace(session: TheaterSession | None) -> str:
912
  return "\n".join(f"- {entry}" for entry in session.trace_events)
913
 
914
 
915
- def render_backend_settings(session: TheaterSession | None) -> str:
916
- backend_name = session.backend_name if session is not None else "deterministic"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
917
  return (
918
- f"Active backend: {backend_name}\n"
919
- "Available backends: deterministic\n"
920
- "LLM backends: not configured\n"
921
  "Fallback behavior: invalid model output falls back to deterministic actor lines"
922
  )
923
 
@@ -932,8 +952,9 @@ def render_outputs(session: TheaterSession | None):
932
  )
933
 
934
 
935
- def create_show(premise: str, session: TheaterSession | None):
936
  premise = premise.strip()
 
937
  if not premise:
938
  return (
939
  None,
@@ -941,10 +962,14 @@ def create_show(premise: str, session: TheaterSession | None):
941
  "No premise yet. Add a premise to raise the curtain.",
942
  EMPTY_DIRECTOR_LOG,
943
  EMPTY_TRACE,
944
- EMPTY_BACKEND,
945
  )
946
 
947
- session = create_show_from_premise(premise)
 
 
 
 
948
  return session, *render_outputs(session)
949
 
950
 
@@ -958,23 +983,40 @@ def reset_show():
958
  EMPTY_TRANSCRIPT,
959
  EMPTY_DIRECTOR_LOG,
960
  EMPTY_TRACE,
 
961
  EMPTY_BACKEND,
962
  )
963
 
964
 
965
- def advance_one_beat(session: TheaterSession | None):
966
  if session is None:
967
- return None, EMPTY_STAGE, "Create a show before running a beat.", EMPTY_DIRECTOR_LOG, EMPTY_TRACE, EMPTY_BACKEND
 
 
 
 
 
 
 
968
 
 
969
  session = run_one_beat(session)
970
  return session, *render_outputs(session)
971
 
972
 
973
- def advance_full_act(session: TheaterSession | None):
974
  if session is None:
975
- yield None, EMPTY_STAGE, "Create a show before running the full act.", EMPTY_DIRECTOR_LOG, EMPTY_TRACE, EMPTY_BACKEND
 
 
 
 
 
 
 
976
  return
977
 
 
978
  if session.beat_index >= session.max_beats:
979
  session = run_one_beat(session)
980
  yield session, *render_outputs(session)
@@ -987,26 +1029,50 @@ def advance_full_act(session: TheaterSession | None):
987
  sleep(PLAYBACK_DELAY_SECONDS)
988
 
989
 
990
- def throw_audience_prop(session: TheaterSession | None, prop_name: str):
991
  if session is None:
992
- return None, EMPTY_STAGE, "Create a show before throwing a prop.", EMPTY_DIRECTOR_LOG, EMPTY_TRACE, EMPTY_BACKEND
 
 
 
 
 
 
 
993
 
 
994
  session = throw_prop(session, prop_name)
995
  return session, *render_outputs(session)
996
 
997
 
998
- def summon_audience_actor(session: TheaterSession | None, actor_name: str):
999
  if session is None:
1000
- return None, EMPTY_STAGE, "Create a show before summoning an actor.", EMPTY_DIRECTOR_LOG, EMPTY_TRACE, EMPTY_BACKEND
 
 
 
 
 
 
 
1001
 
 
1002
  session = summon_actor(session, actor_name)
1003
  return session, *render_outputs(session)
1004
 
1005
 
1006
- def request_audience_finale(session: TheaterSession | None):
1007
  if session is None:
1008
- return None, EMPTY_STAGE, "Create a show before requesting a finale.", EMPTY_DIRECTOR_LOG, EMPTY_TRACE, EMPTY_BACKEND
 
 
 
 
 
 
 
1009
 
 
1010
  session = request_finale(session)
1011
  return session, *render_outputs(session)
1012
 
@@ -1091,6 +1157,12 @@ with gr.Blocks(title="AI Puppet Theater") as app:
1091
  interactive=False,
1092
  )
1093
  with gr.Accordion("Backend", open=False):
 
 
 
 
 
 
1094
  backend_output = gr.Textbox(
1095
  value=EMPTY_BACKEND,
1096
  label="Model Settings",
@@ -1100,32 +1172,32 @@ with gr.Blocks(title="AI Puppet Theater") as app:
1100
 
1101
  create_button.click(
1102
  create_show,
1103
- inputs=[premise_input, session_state],
1104
  outputs=[session_state, stage_output, transcript_output, director_output, trace_output, backend_output],
1105
  )
1106
  run_one_button.click(
1107
  advance_one_beat,
1108
- inputs=[session_state],
1109
  outputs=[session_state, stage_output, transcript_output, director_output, trace_output, backend_output],
1110
  )
1111
  run_full_button.click(
1112
  advance_full_act,
1113
- inputs=[session_state],
1114
  outputs=[session_state, stage_output, transcript_output, director_output, trace_output, backend_output],
1115
  )
1116
  throw_prop_button.click(
1117
  throw_audience_prop,
1118
- inputs=[session_state, prop_input],
1119
  outputs=[session_state, stage_output, transcript_output, director_output, trace_output, backend_output],
1120
  )
1121
  summon_actor_button.click(
1122
  summon_audience_actor,
1123
- inputs=[session_state, actor_input],
1124
  outputs=[session_state, stage_output, transcript_output, director_output, trace_output, backend_output],
1125
  )
1126
  request_finale_button.click(
1127
  request_audience_finale,
1128
- inputs=[session_state],
1129
  outputs=[session_state, stage_output, transcript_output, director_output, trace_output, backend_output],
1130
  )
1131
  reset_button.click(
@@ -1139,6 +1211,7 @@ with gr.Blocks(title="AI Puppet Theater") as app:
1139
  transcript_output,
1140
  director_output,
1141
  trace_output,
 
1142
  backend_output,
1143
  ],
1144
  )
 
1
  from html import escape
2
+ import os
3
  from time import sleep
4
 
5
  import gradio as gr
6
 
7
  from puppet_theater import (
8
+ DEFAULT_OPENBMB_MODEL_ID,
9
  TheaterSession,
10
  create_show_from_premise,
11
  request_finale,
 
30
  EMPTY_DIRECTOR_LOG = "No director notes yet."
31
  EMPTY_TRACE = "No trace events yet."
32
  EMPTY_BACKEND = "Active backend: deterministic\nFallback: deterministic safety path enabled"
33
+ BACKEND_CHOICES = ["deterministic", "openbmb"]
34
+ OPENBMB_MODEL_ID = os.getenv("OPENBMB_MODEL_ID", DEFAULT_OPENBMB_MODEL_ID)
35
  PLAYBACK_DELAY_SECONDS = 0.75
36
  PROP_EMOJI = {
37
  "rubber duck": "🐤",
 
916
  return "\n".join(f"- {entry}" for entry in session.trace_events)
917
 
918
 
919
+ def normalize_backend_name(backend_name: str | None) -> str:
920
+ return backend_name if backend_name in BACKEND_CHOICES else "deterministic"
921
+
922
+
923
+ def apply_backend_selection(session: TheaterSession | None, backend_name: str | None) -> TheaterSession | None:
924
+ if session is None:
925
+ return None
926
+ session.backend_name = normalize_backend_name(backend_name)
927
+ session.backend_model_id = OPENBMB_MODEL_ID if session.backend_name == "openbmb" else None
928
+ return session
929
+
930
+
931
+ def render_backend_settings(session: TheaterSession | None, backend_name: str | None = None) -> str:
932
+ selected_backend = normalize_backend_name(backend_name)
933
+ active_backend = session.backend_name if session is not None else selected_backend
934
+ model_id = session.backend_model_id if session is not None else None
935
+ if active_backend == "openbmb":
936
+ model_id = model_id or OPENBMB_MODEL_ID
937
  return (
938
+ f"Active backend: {active_backend}\n"
939
+ "Available backends: deterministic, openbmb\n"
940
+ f"OpenBMB model id: {model_id or 'not selected'}\n"
941
  "Fallback behavior: invalid model output falls back to deterministic actor lines"
942
  )
943
 
 
952
  )
953
 
954
 
955
+ def create_show(premise: str, session: TheaterSession | None, backend_name: str):
956
  premise = premise.strip()
957
+ selected_backend = normalize_backend_name(backend_name)
958
  if not premise:
959
  return (
960
  None,
 
962
  "No premise yet. Add a premise to raise the curtain.",
963
  EMPTY_DIRECTOR_LOG,
964
  EMPTY_TRACE,
965
+ render_backend_settings(None, selected_backend),
966
  )
967
 
968
+ session = create_show_from_premise(
969
+ premise,
970
+ backend_name=selected_backend,
971
+ backend_model_id=OPENBMB_MODEL_ID if selected_backend == "openbmb" else None,
972
+ )
973
  return session, *render_outputs(session)
974
 
975
 
 
983
  EMPTY_TRANSCRIPT,
984
  EMPTY_DIRECTOR_LOG,
985
  EMPTY_TRACE,
986
+ "deterministic",
987
  EMPTY_BACKEND,
988
  )
989
 
990
 
991
+ def advance_one_beat(session: TheaterSession | None, backend_name: str):
992
  if session is None:
993
+ return (
994
+ None,
995
+ EMPTY_STAGE,
996
+ "Create a show before running a beat.",
997
+ EMPTY_DIRECTOR_LOG,
998
+ EMPTY_TRACE,
999
+ render_backend_settings(None, backend_name),
1000
+ )
1001
 
1002
+ session = apply_backend_selection(session, backend_name)
1003
  session = run_one_beat(session)
1004
  return session, *render_outputs(session)
1005
 
1006
 
1007
+ def advance_full_act(session: TheaterSession | None, backend_name: str):
1008
  if session is None:
1009
+ yield (
1010
+ None,
1011
+ EMPTY_STAGE,
1012
+ "Create a show before running the full act.",
1013
+ EMPTY_DIRECTOR_LOG,
1014
+ EMPTY_TRACE,
1015
+ render_backend_settings(None, backend_name),
1016
+ )
1017
  return
1018
 
1019
+ session = apply_backend_selection(session, backend_name)
1020
  if session.beat_index >= session.max_beats:
1021
  session = run_one_beat(session)
1022
  yield session, *render_outputs(session)
 
1029
  sleep(PLAYBACK_DELAY_SECONDS)
1030
 
1031
 
1032
+ def throw_audience_prop(session: TheaterSession | None, prop_name: str, backend_name: str):
1033
  if session is None:
1034
+ return (
1035
+ None,
1036
+ EMPTY_STAGE,
1037
+ "Create a show before throwing a prop.",
1038
+ EMPTY_DIRECTOR_LOG,
1039
+ EMPTY_TRACE,
1040
+ render_backend_settings(None, backend_name),
1041
+ )
1042
 
1043
+ session = apply_backend_selection(session, backend_name)
1044
  session = throw_prop(session, prop_name)
1045
  return session, *render_outputs(session)
1046
 
1047
 
1048
+ def summon_audience_actor(session: TheaterSession | None, actor_name: str, backend_name: str):
1049
  if session is None:
1050
+ return (
1051
+ None,
1052
+ EMPTY_STAGE,
1053
+ "Create a show before summoning an actor.",
1054
+ EMPTY_DIRECTOR_LOG,
1055
+ EMPTY_TRACE,
1056
+ render_backend_settings(None, backend_name),
1057
+ )
1058
 
1059
+ session = apply_backend_selection(session, backend_name)
1060
  session = summon_actor(session, actor_name)
1061
  return session, *render_outputs(session)
1062
 
1063
 
1064
+ def request_audience_finale(session: TheaterSession | None, backend_name: str):
1065
  if session is None:
1066
+ return (
1067
+ None,
1068
+ EMPTY_STAGE,
1069
+ "Create a show before requesting a finale.",
1070
+ EMPTY_DIRECTOR_LOG,
1071
+ EMPTY_TRACE,
1072
+ render_backend_settings(None, backend_name),
1073
+ )
1074
 
1075
+ session = apply_backend_selection(session, backend_name)
1076
  session = request_finale(session)
1077
  return session, *render_outputs(session)
1078
 
 
1157
  interactive=False,
1158
  )
1159
  with gr.Accordion("Backend", open=False):
1160
+ backend_select = gr.Dropdown(
1161
+ choices=BACKEND_CHOICES,
1162
+ value="deterministic",
1163
+ label="Actor Line Backend",
1164
+ interactive=True,
1165
+ )
1166
  backend_output = gr.Textbox(
1167
  value=EMPTY_BACKEND,
1168
  label="Model Settings",
 
1172
 
1173
  create_button.click(
1174
  create_show,
1175
+ inputs=[premise_input, session_state, backend_select],
1176
  outputs=[session_state, stage_output, transcript_output, director_output, trace_output, backend_output],
1177
  )
1178
  run_one_button.click(
1179
  advance_one_beat,
1180
+ inputs=[session_state, backend_select],
1181
  outputs=[session_state, stage_output, transcript_output, director_output, trace_output, backend_output],
1182
  )
1183
  run_full_button.click(
1184
  advance_full_act,
1185
+ inputs=[session_state, backend_select],
1186
  outputs=[session_state, stage_output, transcript_output, director_output, trace_output, backend_output],
1187
  )
1188
  throw_prop_button.click(
1189
  throw_audience_prop,
1190
+ inputs=[session_state, prop_input, backend_select],
1191
  outputs=[session_state, stage_output, transcript_output, director_output, trace_output, backend_output],
1192
  )
1193
  summon_actor_button.click(
1194
  summon_audience_actor,
1195
+ inputs=[session_state, actor_input, backend_select],
1196
  outputs=[session_state, stage_output, transcript_output, director_output, trace_output, backend_output],
1197
  )
1198
  request_finale_button.click(
1199
  request_audience_finale,
1200
+ inputs=[session_state, backend_select],
1201
  outputs=[session_state, stage_output, transcript_output, director_output, trace_output, backend_output],
1202
  )
1203
  reset_button.click(
 
1211
  transcript_output,
1212
  director_output,
1213
  trace_output,
1214
+ backend_select,
1215
  backend_output,
1216
  ],
1217
  )
puppet_theater/__init__.py CHANGED
@@ -1,5 +1,12 @@
1
  from puppet_theater.actions import request_finale, summon_actor, throw_prop
2
- from puppet_theater.backends import DeterministicBackend, ModelBackend, generate_actor_response, parse_actor_output
 
 
 
 
 
 
 
3
  from puppet_theater.director import BEAT_ARC, run_full_act, run_one_beat
4
  from puppet_theater.models import Actor, ActorResponse, Beat, TheaterSession
5
  from puppet_theater.session import create_show_from_premise
@@ -9,8 +16,10 @@ __all__ = [
9
  "ActorResponse",
10
  "BEAT_ARC",
11
  "Beat",
 
12
  "DeterministicBackend",
13
  "ModelBackend",
 
14
  "TheaterSession",
15
  "create_show_from_premise",
16
  "generate_actor_response",
 
1
  from puppet_theater.actions import request_finale, summon_actor, throw_prop
2
+ from puppet_theater.backends import (
3
+ DEFAULT_OPENBMB_MODEL_ID,
4
+ DeterministicBackend,
5
+ ModelBackend,
6
+ OpenBMBTransformersBackend,
7
+ generate_actor_response,
8
+ parse_actor_output,
9
+ )
10
  from puppet_theater.director import BEAT_ARC, run_full_act, run_one_beat
11
  from puppet_theater.models import Actor, ActorResponse, Beat, TheaterSession
12
  from puppet_theater.session import create_show_from_premise
 
16
  "ActorResponse",
17
  "BEAT_ARC",
18
  "Beat",
19
+ "DEFAULT_OPENBMB_MODEL_ID",
20
  "DeterministicBackend",
21
  "ModelBackend",
22
+ "OpenBMBTransformersBackend",
23
  "TheaterSession",
24
  "create_show_from_premise",
25
  "generate_actor_response",
puppet_theater/backends.py CHANGED
@@ -1,26 +1,35 @@
1
  from abc import ABC, abstractmethod
2
  from dataclasses import dataclass
3
  import json
 
 
4
  from typing import Any
5
 
6
  from pydantic import ValidationError
7
 
8
  from puppet_theater.models import Actor, ActorResponse, TheaterSession
 
9
 
10
 
11
  MAX_ACTOR_LINE_CHARS = 220
 
 
12
 
13
 
14
  @dataclass(frozen=True)
15
  class BackendGeneration:
16
  response: ActorResponse
17
  backend_name: str
 
18
  fallback_used: bool
19
  validation_status: str
 
 
20
 
21
 
22
  class ModelBackend(ABC):
23
  name: str = "base"
 
24
 
25
  @abstractmethod
26
  def generate_actor_response(
@@ -32,6 +41,17 @@ class ModelBackend(ABC):
32
  ) -> ActorResponse | dict[str, Any] | str:
33
  """Return raw or structured actor output for one beat."""
34
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
  class DeterministicBackend(ModelBackend):
37
  name = "deterministic"
@@ -46,6 +66,101 @@ class DeterministicBackend(ModelBackend):
46
  return deterministic_actor_response(session, beat_type, speaker, prop)
47
 
48
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  def deterministic_actor_response(
50
  session: TheaterSession,
51
  beat_type: str,
@@ -68,23 +183,135 @@ def generate_actor_response(
68
  prop: str | None,
69
  backend: ModelBackend | None = None,
70
  ) -> BackendGeneration:
71
- active_backend = backend or DeterministicBackend()
72
- raw_output = active_backend.generate_actor_response(session, beat_type, speaker, prop)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  response, validation_status = parse_actor_output(raw_output)
74
  if response is not None:
75
  return BackendGeneration(
76
  response=response,
77
  backend_name=active_backend.name,
 
78
  fallback_used=False,
79
  validation_status=validation_status,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  fallback_response = deterministic_actor_response(session, beat_type, speaker, prop)
83
  return BackendGeneration(
84
  response=fallback_response,
85
- backend_name=active_backend.name,
 
86
  fallback_used=True,
87
  validation_status=validation_status,
 
 
88
  )
89
 
90
 
@@ -126,6 +353,17 @@ def _coerce_actor_output(raw_output: ActorResponse | dict[str, Any] | str) -> Ac
126
  return None
127
 
128
 
 
 
 
 
 
 
 
 
 
 
 
129
  def _line_for_beat(
130
  session: TheaterSession,
131
  beat_type: str,
@@ -178,3 +416,8 @@ def _effect_for_beat(beat_type: str) -> str:
178
  "chaos_or_intervention": "confetti_rustle",
179
  "finale": "curtain_fall",
180
  }[beat_type]
 
 
 
 
 
 
1
  from abc import ABC, abstractmethod
2
  from dataclasses import dataclass
3
  import json
4
+ import os
5
+ import time
6
  from typing import Any
7
 
8
  from pydantic import ValidationError
9
 
10
  from puppet_theater.models import Actor, ActorResponse, TheaterSession
11
+ from puppet_theater.prompts import ACTOR_LINE_PROMPT
12
 
13
 
14
  MAX_ACTOR_LINE_CHARS = 220
15
+ DEFAULT_OPENBMB_MODEL_ID = "openbmb/MiniCPM5-1B"
16
+ OPENBMB_MAX_NEW_TOKENS = 112
17
 
18
 
19
  @dataclass(frozen=True)
20
  class BackendGeneration:
21
  response: ActorResponse
22
  backend_name: str
23
+ model_id: str | None
24
  fallback_used: bool
25
  validation_status: str
26
+ latency_ms: int | None = None
27
+ error: str | None = None
28
 
29
 
30
  class ModelBackend(ABC):
31
  name: str = "base"
32
+ model_id: str | None = None
33
 
34
  @abstractmethod
35
  def generate_actor_response(
 
41
  ) -> ActorResponse | dict[str, Any] | str:
42
  """Return raw or structured actor output for one beat."""
43
 
44
+ def repair_actor_response(
45
+ self,
46
+ session: TheaterSession,
47
+ beat_type: str,
48
+ speaker: Actor,
49
+ prop: str | None,
50
+ invalid_output: ActorResponse | dict[str, Any] | str,
51
+ validation_status: str,
52
+ ) -> ActorResponse | dict[str, Any] | str | None:
53
+ return None
54
+
55
 
56
  class DeterministicBackend(ModelBackend):
57
  name = "deterministic"
 
66
  return deterministic_actor_response(session, beat_type, speaker, prop)
67
 
68
 
69
+ class OpenBMBTransformersBackend(ModelBackend):
70
+ name = "openbmb"
71
+
72
+ def __init__(self, model_id: str | None = None, max_new_tokens: int = OPENBMB_MAX_NEW_TOKENS) -> None:
73
+ self.model_id = model_id or os.getenv("OPENBMB_MODEL_ID", DEFAULT_OPENBMB_MODEL_ID)
74
+ self.max_new_tokens = max_new_tokens
75
+ self._tokenizer = None
76
+ self._model = None
77
+ self._torch = None
78
+
79
+ def generate_actor_response(
80
+ self,
81
+ session: TheaterSession,
82
+ beat_type: str,
83
+ speaker: Actor,
84
+ prop: str | None,
85
+ ) -> str:
86
+ prompt = build_actor_line_prompt(session, beat_type, speaker, prop)
87
+ return self._generate_text(prompt)
88
+
89
+ def repair_actor_response(
90
+ self,
91
+ session: TheaterSession,
92
+ beat_type: str,
93
+ speaker: Actor,
94
+ prop: str | None,
95
+ invalid_output: ActorResponse | dict[str, Any] | str,
96
+ validation_status: str,
97
+ ) -> str | None:
98
+ prompt = build_actor_line_prompt(session, beat_type, speaker, prop)
99
+ repair_prompt = (
100
+ f"{prompt}\n\nThe previous output failed validation with status {validation_status}.\n"
101
+ "Return only valid compact JSON. Do not include markdown, commentary, or extra keys.\n"
102
+ f"Previous output: {invalid_output}"
103
+ )
104
+ return self._generate_text(repair_prompt)
105
+
106
+ def _load(self) -> None:
107
+ if self._tokenizer is not None and self._model is not None:
108
+ return
109
+
110
+ try:
111
+ import torch
112
+ from transformers import AutoModelForCausalLM, AutoTokenizer
113
+ except ImportError as exc:
114
+ raise RuntimeError("OpenBMB backend dependencies are not installed") from exc
115
+
116
+ self._torch = torch
117
+ self._tokenizer = AutoTokenizer.from_pretrained(self.model_id)
118
+ self._model = AutoModelForCausalLM.from_pretrained(
119
+ self.model_id,
120
+ torch_dtype="auto",
121
+ device_map="auto",
122
+ )
123
+ self._model.eval()
124
+
125
+ def _generate_text(self, prompt: str) -> str:
126
+ self._load()
127
+ messages = [{"role": "user", "content": prompt}]
128
+ tokenizer = self._tokenizer
129
+ model = self._model
130
+
131
+ try:
132
+ inputs = tokenizer.apply_chat_template(
133
+ messages,
134
+ tokenize=True,
135
+ add_generation_prompt=True,
136
+ enable_thinking=False,
137
+ return_dict=True,
138
+ return_tensors="pt",
139
+ )
140
+ except TypeError:
141
+ inputs = tokenizer.apply_chat_template(
142
+ messages,
143
+ tokenize=True,
144
+ add_generation_prompt=True,
145
+ return_dict=True,
146
+ return_tensors="pt",
147
+ )
148
+
149
+ inputs = inputs.to(model.device)
150
+ eos_token_id = tokenizer.eos_token_id
151
+ pad_token_id = tokenizer.pad_token_id or eos_token_id
152
+ with self._torch.inference_mode():
153
+ outputs = model.generate(
154
+ **inputs,
155
+ max_new_tokens=self.max_new_tokens,
156
+ do_sample=False,
157
+ pad_token_id=pad_token_id,
158
+ eos_token_id=eos_token_id,
159
+ )
160
+ new_tokens = outputs[0][inputs["input_ids"].shape[-1] :]
161
+ return tokenizer.decode(new_tokens, skip_special_tokens=True).strip()
162
+
163
+
164
  def deterministic_actor_response(
165
  session: TheaterSession,
166
  beat_type: str,
 
183
  prop: str | None,
184
  backend: ModelBackend | None = None,
185
  ) -> BackendGeneration:
186
+ active_backend = backend or get_backend(session.backend_name)
187
+ start_time = time.perf_counter()
188
+ raw_output: ActorResponse | dict[str, Any] | str | None = None
189
+ try:
190
+ raw_output = active_backend.generate_actor_response(session, beat_type, speaker, prop)
191
+ except Exception as exc:
192
+ latency_ms = _elapsed_ms(start_time)
193
+ return _fallback_generation(
194
+ session=session,
195
+ beat_type=beat_type,
196
+ speaker=speaker,
197
+ prop=prop,
198
+ backend=active_backend,
199
+ validation_status="backend_error",
200
+ latency_ms=latency_ms,
201
+ error=_summarize_error(exc),
202
+ )
203
+
204
  response, validation_status = parse_actor_output(raw_output)
205
  if response is not None:
206
  return BackendGeneration(
207
  response=response,
208
  backend_name=active_backend.name,
209
+ model_id=active_backend.model_id,
210
  fallback_used=False,
211
  validation_status=validation_status,
212
+ latency_ms=_elapsed_ms(start_time),
213
+ )
214
+
215
+ try:
216
+ repair_output = active_backend.repair_actor_response(
217
+ session=session,
218
+ beat_type=beat_type,
219
+ speaker=speaker,
220
+ prop=prop,
221
+ invalid_output=raw_output,
222
+ validation_status=validation_status,
223
+ )
224
+ except Exception as exc:
225
+ return _fallback_generation(
226
+ session=session,
227
+ beat_type=beat_type,
228
+ speaker=speaker,
229
+ prop=prop,
230
+ backend=active_backend,
231
+ validation_status=f"{validation_status};repair_backend_error",
232
+ latency_ms=_elapsed_ms(start_time),
233
+ error=_summarize_error(exc),
234
  )
235
+ if repair_output is not None:
236
+ response, repair_status = parse_actor_output(repair_output)
237
+ if response is not None:
238
+ return BackendGeneration(
239
+ response=response,
240
+ backend_name=active_backend.name,
241
+ model_id=active_backend.model_id,
242
+ fallback_used=False,
243
+ validation_status=f"repair_{repair_status}",
244
+ latency_ms=_elapsed_ms(start_time),
245
+ )
246
+ validation_status = f"{validation_status};repair_{repair_status}"
247
+
248
+ return _fallback_generation(
249
+ session=session,
250
+ beat_type=beat_type,
251
+ speaker=speaker,
252
+ prop=prop,
253
+ backend=active_backend,
254
+ validation_status=validation_status,
255
+ latency_ms=_elapsed_ms(start_time),
256
+ )
257
 
258
+
259
+ def get_backend(backend_name: str | None) -> ModelBackend:
260
+ normalized_name = (backend_name or "deterministic").strip().lower()
261
+ if normalized_name == "openbmb":
262
+ model_id = os.getenv("OPENBMB_MODEL_ID", DEFAULT_OPENBMB_MODEL_ID)
263
+ cache_key = f"openbmb:{model_id}"
264
+ if cache_key not in _BACKEND_CACHE:
265
+ _BACKEND_CACHE[cache_key] = OpenBMBTransformersBackend(model_id=model_id)
266
+ return _BACKEND_CACHE[cache_key]
267
+ return _BACKEND_CACHE["deterministic"]
268
+
269
+
270
+ def build_actor_line_prompt(
271
+ session: TheaterSession,
272
+ beat_type: str,
273
+ speaker: Actor,
274
+ prop: str | None,
275
+ ) -> str:
276
+ recent_transcript = "\n".join(
277
+ f"{beat.speaker}: {beat.line}" for beat in session.transcript[-3:]
278
+ ) or "No lines yet."
279
+ prompt = ACTOR_LINE_PROMPT.format(
280
+ show_title=session.show_title,
281
+ premise=session.premise,
282
+ setting=session.setting,
283
+ beat_type=beat_type,
284
+ speaker_name=speaker.name,
285
+ speaker_goal=speaker.goal,
286
+ speaker_style=speaker.speaking_style,
287
+ audience_action=session.latest_audience_action or "None",
288
+ latest_prop=prop or session.latest_prop or "None",
289
+ )
290
+ return (
291
+ f"{prompt}\nRecent transcript:\n{recent_transcript}\n\n"
292
+ "Keep the line under 220 characters. Return JSON only."
293
+ )
294
+
295
+
296
+ def _fallback_generation(
297
+ session: TheaterSession,
298
+ beat_type: str,
299
+ speaker: Actor,
300
+ prop: str | None,
301
+ backend: ModelBackend,
302
+ validation_status: str,
303
+ latency_ms: int | None,
304
+ error: str | None = None,
305
+ ) -> BackendGeneration:
306
  fallback_response = deterministic_actor_response(session, beat_type, speaker, prop)
307
  return BackendGeneration(
308
  response=fallback_response,
309
+ backend_name=backend.name,
310
+ model_id=backend.model_id,
311
  fallback_used=True,
312
  validation_status=validation_status,
313
+ latency_ms=latency_ms,
314
+ error=error,
315
  )
316
 
317
 
 
353
  return None
354
 
355
 
356
+ def _elapsed_ms(start_time: float) -> int:
357
+ return round((time.perf_counter() - start_time) * 1000)
358
+
359
+
360
+ def _summarize_error(exc: Exception) -> str:
361
+ message = " ".join(str(exc).split())
362
+ if not message:
363
+ message = exc.__class__.__name__
364
+ return message[:180]
365
+
366
+
367
  def _line_for_beat(
368
  session: TheaterSession,
369
  beat_type: str,
 
416
  "chaos_or_intervention": "confetti_rustle",
417
  "finale": "curtain_fall",
418
  }[beat_type]
419
+
420
+
421
+ _BACKEND_CACHE: dict[str, ModelBackend] = {
422
+ "deterministic": DeterministicBackend(),
423
+ }
puppet_theater/director.py CHANGED
@@ -49,14 +49,21 @@ def run_one_beat(session: TheaterSession | None) -> TheaterSession | None:
49
  session.director_log.append(
50
  "Backend "
51
  f"{backend_generation.backend_name} returned actor output "
52
- f"({backend_generation.validation_status}, fallback={backend_generation.fallback_used})."
 
53
  )
 
 
 
 
54
  session.trace_events.append(f"beat_added:{session.beat_index}:{beat_type}")
55
  session.trace_events.append(
56
  "backend_result:"
57
  f"{backend_generation.backend_name}:"
 
58
  f"fallback={backend_generation.fallback_used}:"
59
- f"validation={backend_generation.validation_status}"
 
60
  )
61
 
62
  if beat_type == "finale":
 
49
  session.director_log.append(
50
  "Backend "
51
  f"{backend_generation.backend_name} returned actor output "
52
+ f"({backend_generation.validation_status}, fallback={backend_generation.fallback_used}"
53
+ f", latency={backend_generation.latency_ms}ms)."
54
  )
55
+ if backend_generation.model_id:
56
+ session.director_log.append(f"Model id: {backend_generation.model_id}.")
57
+ if backend_generation.error:
58
+ session.director_log.append(f"Backend fallback reason: {backend_generation.error}.")
59
  session.trace_events.append(f"beat_added:{session.beat_index}:{beat_type}")
60
  session.trace_events.append(
61
  "backend_result:"
62
  f"{backend_generation.backend_name}:"
63
+ f"model={backend_generation.model_id or 'none'}:"
64
  f"fallback={backend_generation.fallback_used}:"
65
+ f"validation={backend_generation.validation_status}:"
66
+ f"latency_ms={backend_generation.latency_ms}"
67
  )
68
 
69
  if beat_type == "finale":
puppet_theater/models.py CHANGED
@@ -64,3 +64,4 @@ class TheaterSession:
64
  trace_events: list[str] = field(default_factory=list)
65
  finale_requested: bool = False
66
  backend_name: str = "deterministic"
 
 
64
  trace_events: list[str] = field(default_factory=list)
65
  finale_requested: bool = False
66
  backend_name: str = "deterministic"
67
+ backend_model_id: str | None = None
puppet_theater/session.py CHANGED
@@ -27,7 +27,7 @@ def _setting_from_premise(premise: str) -> str:
27
  return "a pocket-sized improv stage with painted flats and a wobbly spotlight"
28
 
29
 
30
- def create_show_from_premise(premise: str) -> TheaterSession:
31
  cleaned_premise = _clean_premise(premise)
32
  show_title = _title_from_premise(cleaned_premise)
33
  setting = _setting_from_premise(cleaned_premise)
@@ -59,9 +59,11 @@ def create_show_from_premise(premise: str) -> TheaterSession:
59
  ),
60
  ]
61
 
 
 
62
  director_log = [
63
  "Director created a deterministic six-beat show plan.",
64
- "Active backend: deterministic.",
65
  f"Setting selected: {setting}.",
66
  "Three puppet actors are waiting for the first beat.",
67
  ]
@@ -69,7 +71,7 @@ def create_show_from_premise(premise: str) -> TheaterSession:
69
  "show_created",
70
  "actors_created:3",
71
  "director_plan_created",
72
- "backend_active:deterministic",
73
  ]
74
 
75
  return TheaterSession(
@@ -86,5 +88,6 @@ def create_show_from_premise(premise: str) -> TheaterSession:
86
  director_log=director_log,
87
  trace_events=trace_events,
88
  finale_requested=False,
89
- backend_name="deterministic",
 
90
  )
 
27
  return "a pocket-sized improv stage with painted flats and a wobbly spotlight"
28
 
29
 
30
+ def create_show_from_premise(premise: str, backend_name: str = "deterministic", backend_model_id: str | None = None) -> TheaterSession:
31
  cleaned_premise = _clean_premise(premise)
32
  show_title = _title_from_premise(cleaned_premise)
33
  setting = _setting_from_premise(cleaned_premise)
 
59
  ),
60
  ]
61
 
62
+ active_backend = backend_name if backend_name in {"deterministic", "openbmb"} else "deterministic"
63
+ model_note = f" ({backend_model_id})" if backend_model_id else ""
64
  director_log = [
65
  "Director created a deterministic six-beat show plan.",
66
+ f"Active backend: {active_backend}{model_note}.",
67
  f"Setting selected: {setting}.",
68
  "Three puppet actors are waiting for the first beat.",
69
  ]
 
71
  "show_created",
72
  "actors_created:3",
73
  "director_plan_created",
74
+ f"backend_active:{active_backend}",
75
  ]
76
 
77
  return TheaterSession(
 
88
  director_log=director_log,
89
  trace_events=trace_events,
90
  finale_requested=False,
91
+ backend_name=active_backend,
92
+ backend_model_id=backend_model_id,
93
  )
pyproject.toml CHANGED
@@ -5,8 +5,11 @@ description = "A Hugging Face Gradio Space for AI Puppet Theater."
5
  readme = "README.md"
6
  requires-python = "==3.11.*"
7
  dependencies = [
 
8
  "gradio==6.5.1",
9
  "pydantic<=2.12.5",
 
 
10
  ]
11
 
12
  [dependency-groups]
 
5
  readme = "README.md"
6
  requires-python = "==3.11.*"
7
  dependencies = [
8
+ "accelerate",
9
  "gradio==6.5.1",
10
  "pydantic<=2.12.5",
11
+ "torch",
12
+ "transformers",
13
  ]
14
 
15
  [dependency-groups]
requirements.txt CHANGED
@@ -1,5 +1,7 @@
1
  # This file was autogenerated by uv via the following command:
2
  # uv pip compile pyproject.toml -o requirements.txt
 
 
3
  aiofiles==24.1.0
4
  # via gradio
5
  annotated-doc==0.0.4
@@ -29,11 +31,14 @@ fastapi==0.136.3
29
  ffmpy==1.0.0
30
  # via gradio
31
  filelock==3.29.1
32
- # via huggingface-hub
 
 
33
  fsspec==2026.4.0
34
  # via
35
  # gradio-client
36
  # huggingface-hub
 
37
  gradio==6.5.1
38
  # via ai-puppet-theater (pyproject.toml)
39
  gradio-client==2.0.3
@@ -56,14 +61,19 @@ httpx==0.28.1
56
  # safehttpx
57
  huggingface-hub==1.18.0
58
  # via
 
59
  # gradio
60
  # gradio-client
 
 
61
  idna==3.18
62
  # via
63
  # anyio
64
  # httpx
65
  jinja2==3.1.6
66
- # via gradio
 
 
67
  markdown-it-py==4.2.0
68
  # via rich
69
  markupsafe==3.0.3
@@ -72,21 +82,31 @@ markupsafe==3.0.3
72
  # jinja2
73
  mdurl==0.1.2
74
  # via markdown-it-py
 
 
 
 
75
  numpy==2.4.6
76
  # via
 
77
  # gradio
78
  # pandas
 
79
  orjson==3.11.9
80
  # via gradio
81
  packaging==26.2
82
  # via
 
83
  # gradio
84
  # gradio-client
85
  # huggingface-hub
 
86
  pandas==3.0.3
87
  # via gradio
88
  pillow==12.2.0
89
  # via gradio
 
 
90
  pydantic==2.12.5
91
  # via
92
  # ai-puppet-theater (pyproject.toml)
@@ -106,14 +126,24 @@ pytz==2026.2
106
  # via gradio
107
  pyyaml==6.0.3
108
  # via
 
109
  # gradio
110
  # huggingface-hub
 
 
 
111
  rich==15.0.0
112
  # via typer
113
  safehttpx==0.1.7
114
  # via gradio
 
 
 
 
115
  semantic-version==2.10.0
116
  # via gradio
 
 
117
  shellingham==1.5.4
118
  # via typer
119
  six==1.17.0
@@ -122,14 +152,27 @@ starlette==0.52.1
122
  # via
123
  # fastapi
124
  # gradio
 
 
 
 
125
  tomlkit==0.13.3
126
  # via gradio
 
 
 
 
127
  tqdm==4.68.1
128
- # via huggingface-hub
 
 
 
 
129
  typer==0.25.1
130
  # via
131
  # gradio
132
  # huggingface-hub
 
133
  typing-extensions==4.15.0
134
  # via
135
  # anyio
@@ -140,6 +183,7 @@ typing-extensions==4.15.0
140
  # pydantic
141
  # pydantic-core
142
  # starlette
 
143
  # typing-inspection
144
  typing-inspection==0.4.2
145
  # via
 
1
  # This file was autogenerated by uv via the following command:
2
  # uv pip compile pyproject.toml -o requirements.txt
3
+ accelerate==1.13.0
4
+ # via ai-puppet-theater (pyproject.toml)
5
  aiofiles==24.1.0
6
  # via gradio
7
  annotated-doc==0.0.4
 
31
  ffmpy==1.0.0
32
  # via gradio
33
  filelock==3.29.1
34
+ # via
35
+ # huggingface-hub
36
+ # torch
37
  fsspec==2026.4.0
38
  # via
39
  # gradio-client
40
  # huggingface-hub
41
+ # torch
42
  gradio==6.5.1
43
  # via ai-puppet-theater (pyproject.toml)
44
  gradio-client==2.0.3
 
61
  # safehttpx
62
  huggingface-hub==1.18.0
63
  # via
64
+ # accelerate
65
  # gradio
66
  # gradio-client
67
+ # tokenizers
68
+ # transformers
69
  idna==3.18
70
  # via
71
  # anyio
72
  # httpx
73
  jinja2==3.1.6
74
+ # via
75
+ # gradio
76
+ # torch
77
  markdown-it-py==4.2.0
78
  # via rich
79
  markupsafe==3.0.3
 
82
  # jinja2
83
  mdurl==0.1.2
84
  # via markdown-it-py
85
+ mpmath==1.3.0
86
+ # via sympy
87
+ networkx==3.6.1
88
+ # via torch
89
  numpy==2.4.6
90
  # via
91
+ # accelerate
92
  # gradio
93
  # pandas
94
+ # transformers
95
  orjson==3.11.9
96
  # via gradio
97
  packaging==26.2
98
  # via
99
+ # accelerate
100
  # gradio
101
  # gradio-client
102
  # huggingface-hub
103
+ # transformers
104
  pandas==3.0.3
105
  # via gradio
106
  pillow==12.2.0
107
  # via gradio
108
+ psutil==7.2.2
109
+ # via accelerate
110
  pydantic==2.12.5
111
  # via
112
  # ai-puppet-theater (pyproject.toml)
 
126
  # via gradio
127
  pyyaml==6.0.3
128
  # via
129
+ # accelerate
130
  # gradio
131
  # huggingface-hub
132
+ # transformers
133
+ regex==2026.5.9
134
+ # via transformers
135
  rich==15.0.0
136
  # via typer
137
  safehttpx==0.1.7
138
  # via gradio
139
+ safetensors==0.7.0
140
+ # via
141
+ # accelerate
142
+ # transformers
143
  semantic-version==2.10.0
144
  # via gradio
145
+ setuptools==81.0.0
146
+ # via torch
147
  shellingham==1.5.4
148
  # via typer
149
  six==1.17.0
 
152
  # via
153
  # fastapi
154
  # gradio
155
+ sympy==1.14.0
156
+ # via torch
157
+ tokenizers==0.22.2
158
+ # via transformers
159
  tomlkit==0.13.3
160
  # via gradio
161
+ torch==2.12.0
162
+ # via
163
+ # ai-puppet-theater (pyproject.toml)
164
+ # accelerate
165
  tqdm==4.68.1
166
+ # via
167
+ # huggingface-hub
168
+ # transformers
169
+ transformers==5.10.2
170
+ # via ai-puppet-theater (pyproject.toml)
171
  typer==0.25.1
172
  # via
173
  # gradio
174
  # huggingface-hub
175
+ # transformers
176
  typing-extensions==4.15.0
177
  # via
178
  # anyio
 
183
  # pydantic
184
  # pydantic-core
185
  # starlette
186
+ # torch
187
  # typing-inspection
188
  typing-inspection==0.4.2
189
  # via
uv.lock CHANGED
@@ -7,13 +7,34 @@ resolution-markers = [
7
  "sys_platform != 'emscripten' and sys_platform != 'win32'",
8
  ]
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  [[package]]
11
  name = "ai-puppet-theater"
12
  version = "0.1.0"
13
  source = { virtual = "." }
14
  dependencies = [
 
15
  { name = "gradio" },
16
  { name = "pydantic" },
 
 
17
  ]
18
 
19
  [package.dev-dependencies]
@@ -24,8 +45,11 @@ dev = [
24
 
25
  [package.metadata]
26
  requires-dist = [
 
27
  { name = "gradio", specifier = "==6.5.1" },
28
  { name = "pydantic", specifier = "<=2.12.5" },
 
 
29
  ]
30
 
31
  [package.metadata.requires-dev]
@@ -122,6 +146,66 @@ wheels = [
122
  { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
123
  ]
124
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  [[package]]
126
  name = "fastapi"
127
  version = "0.136.3"
@@ -373,6 +457,24 @@ wheels = [
373
  { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
374
  ]
375
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
376
  [[package]]
377
  name = "numpy"
378
  version = "2.4.6"
@@ -399,6 +501,158 @@ wheels = [
399
  { url = "https://files.pythonhosted.org/packages/15/ce/e5ec180bc41812edcd8daeb8639d205622c0e8c02259d8ab25a0201b3c2a/numpy-2.4.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:2803abfebfc990042cd494d8ce2d5f82e9d847af6d35ec486923aa19dbad5e73", size = 12504263, upload-time = "2026-05-18T23:37:09.715Z" },
400
  ]
401
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
402
  [[package]]
403
  name = "orjson"
404
  version = "3.11.9"
@@ -487,6 +741,22 @@ wheels = [
487
  { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
488
  ]
489
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
490
  [[package]]
491
  name = "pydantic"
492
  version = "2.12.5"
@@ -620,6 +890,30 @@ wheels = [
620
  { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" },
621
  ]
622
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
623
  [[package]]
624
  name = "rich"
625
  version = "15.0.0"
@@ -670,6 +964,28 @@ wheels = [
670
  { url = "https://files.pythonhosted.org/packages/2e/a3/0f0b7d78e2f1eb9e8e1afbff1d2bff8d60144aee17aca51c065b516743dd/safehttpx-0.1.7-py3-none-any.whl", hash = "sha256:c4f4a162db6993464d7ca3d7cc4af0ffc6515a606dfd220b9f82c6945d869cde", size = 8959, upload-time = "2025-10-24T18:30:08.733Z" },
671
  ]
672
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
673
  [[package]]
674
  name = "semantic-version"
675
  version = "2.10.0"
@@ -679,6 +995,15 @@ wheels = [
679
  { url = "https://files.pythonhosted.org/packages/6a/23/8146aad7d88f4fcb3a6218f41a60f6c2d4e3a72de72da1825dc7c8f7877c/semantic_version-2.10.0-py2.py3-none-any.whl", hash = "sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177", size = 15552, upload-time = "2022-05-26T13:35:21.206Z" },
680
  ]
681
 
 
 
 
 
 
 
 
 
 
682
  [[package]]
683
  name = "shellingham"
684
  version = "1.5.4"
@@ -710,6 +1035,44 @@ wheels = [
710
  { url = "https://files.pythonhosted.org/packages/81/0d/13d1d239a25cbfb19e740db83143e95c772a1fe10202dda4b76792b114dd/starlette-0.52.1-py3-none-any.whl", hash = "sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74", size = 74272, upload-time = "2026-01-18T13:34:09.188Z" },
711
  ]
712
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
713
  [[package]]
714
  name = "tomlkit"
715
  version = "0.13.3"
@@ -719,6 +1082,34 @@ wheels = [
719
  { url = "https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl", hash = "sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0", size = 38901, upload-time = "2025-06-05T07:13:43.546Z" },
720
  ]
721
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
722
  [[package]]
723
  name = "tqdm"
724
  version = "4.68.1"
@@ -731,6 +1122,35 @@ wheels = [
731
  { url = "https://files.pythonhosted.org/packages/47/aa/218a0eb34de1f753c83e4d0d1c8e7c4cef27f20dcb8342e024f63a80dc86/tqdm-4.68.1-py3-none-any.whl", hash = "sha256:fea4a90e4023f764914569f7802a297277c5ab1a66be5144143e142e1a4031d8", size = 78354, upload-time = "2026-06-05T17:23:13.654Z" },
732
  ]
733
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
734
  [[package]]
735
  name = "typer"
736
  version = "0.25.1"
 
7
  "sys_platform != 'emscripten' and sys_platform != 'win32'",
8
  ]
9
 
10
+ [[package]]
11
+ name = "accelerate"
12
+ version = "1.13.0"
13
+ source = { registry = "https://pypi.org/simple" }
14
+ dependencies = [
15
+ { name = "huggingface-hub" },
16
+ { name = "numpy" },
17
+ { name = "packaging" },
18
+ { name = "psutil" },
19
+ { name = "pyyaml" },
20
+ { name = "safetensors" },
21
+ { name = "torch" },
22
+ ]
23
+ sdist = { url = "https://files.pythonhosted.org/packages/ca/14/787e5498cd062640f0f3d92ef4ae4063174f76f9afd29d13fc52a319daae/accelerate-1.13.0.tar.gz", hash = "sha256:d631b4e0f5b3de4aff2d7e9e6857d164810dfc3237d54d017f075122d057b236", size = 402835, upload-time = "2026-03-04T19:34:12.359Z" }
24
+ wheels = [
25
+ { url = "https://files.pythonhosted.org/packages/7e/46/02ac5e262d4af18054b3e922b2baedbb2a03289ee792162de60a865defc5/accelerate-1.13.0-py3-none-any.whl", hash = "sha256:cf1a3efb96c18f7b152eb0fa7490f3710b19c3f395699358f08decca2b8b62e0", size = 383744, upload-time = "2026-03-04T19:34:10.313Z" },
26
+ ]
27
+
28
  [[package]]
29
  name = "ai-puppet-theater"
30
  version = "0.1.0"
31
  source = { virtual = "." }
32
  dependencies = [
33
+ { name = "accelerate" },
34
  { name = "gradio" },
35
  { name = "pydantic" },
36
+ { name = "torch" },
37
+ { name = "transformers" },
38
  ]
39
 
40
  [package.dev-dependencies]
 
45
 
46
  [package.metadata]
47
  requires-dist = [
48
+ { name = "accelerate" },
49
  { name = "gradio", specifier = "==6.5.1" },
50
  { name = "pydantic", specifier = "<=2.12.5" },
51
+ { name = "torch" },
52
+ { name = "transformers" },
53
  ]
54
 
55
  [package.metadata.requires-dev]
 
146
  { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
147
  ]
148
 
149
+ [[package]]
150
+ name = "cuda-bindings"
151
+ version = "13.3.1"
152
+ source = { registry = "https://pypi.org/simple" }
153
+ dependencies = [
154
+ { name = "cuda-pathfinder", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
155
+ ]
156
+ wheels = [
157
+ { url = "https://files.pythonhosted.org/packages/51/6b/457ca12dad3ee9bfcc9a545cfd6b64b359ba49de40f776f6e028e678f262/cuda_bindings-13.3.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c5879712accf6e14bb01aa5e67440eb84998b8d104b509cc7a6dc0b8f656a474", size = 6053539, upload-time = "2026-05-29T23:11:43.19Z" },
158
+ { url = "https://files.pythonhosted.org/packages/95/7a/c5e3c34a409b148f5c0f5a4ea374158f95d488862c1dffedf9aa5c639df9/cuda_bindings-13.3.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:04436a9364059c84b8f9636f359eccda1cf814341f5b670c71d80d2f79dbc708", size = 6674166, upload-time = "2026-05-29T23:11:45.478Z" },
159
+ ]
160
+
161
+ [[package]]
162
+ name = "cuda-pathfinder"
163
+ version = "1.5.5"
164
+ source = { registry = "https://pypi.org/simple" }
165
+ wheels = [
166
+ { url = "https://files.pythonhosted.org/packages/11/c8/26f2e4aae92f11522a96043892ba39a90eac610d5242523aa863212bc1c7/cuda_pathfinder-1.5.5-py3-none-any.whl", hash = "sha256:0228c023f95d1480f143ef5c8922d27a2ab052087a942e81dc289c9eb8f91689", size = 51671, upload-time = "2026-05-27T01:21:25.413Z" },
167
+ ]
168
+
169
+ [[package]]
170
+ name = "cuda-toolkit"
171
+ version = "13.0.2"
172
+ source = { registry = "https://pypi.org/simple" }
173
+ wheels = [
174
+ { url = "https://files.pythonhosted.org/packages/57/b2/453099f5f3b698d7d0eab38916aac44c7f76229f451709e2eb9db6615dcd/cuda_toolkit-13.0.2-py2.py3-none-any.whl", hash = "sha256:b198824cf2f54003f50d64ada3a0f184b42ca0846c1c94192fa269ecd97a66eb", size = 2364, upload-time = "2025-12-19T23:24:07.328Z" },
175
+ ]
176
+
177
+ [package.optional-dependencies]
178
+ cudart = [
179
+ { name = "nvidia-cuda-runtime", marker = "sys_platform == 'linux'" },
180
+ ]
181
+ cufft = [
182
+ { name = "nvidia-cufft", marker = "sys_platform == 'linux'" },
183
+ ]
184
+ cufile = [
185
+ { name = "nvidia-cufile", marker = "sys_platform == 'linux'" },
186
+ ]
187
+ cupti = [
188
+ { name = "nvidia-cuda-cupti", marker = "sys_platform == 'linux'" },
189
+ ]
190
+ curand = [
191
+ { name = "nvidia-curand", marker = "sys_platform == 'linux'" },
192
+ ]
193
+ cusolver = [
194
+ { name = "nvidia-cusolver", marker = "sys_platform == 'linux'" },
195
+ ]
196
+ cusparse = [
197
+ { name = "nvidia-cusparse", marker = "sys_platform == 'linux'" },
198
+ ]
199
+ nvjitlink = [
200
+ { name = "nvidia-nvjitlink", marker = "sys_platform == 'linux'" },
201
+ ]
202
+ nvrtc = [
203
+ { name = "nvidia-cuda-nvrtc", marker = "sys_platform == 'linux'" },
204
+ ]
205
+ nvtx = [
206
+ { name = "nvidia-nvtx", marker = "sys_platform == 'linux'" },
207
+ ]
208
+
209
  [[package]]
210
  name = "fastapi"
211
  version = "0.136.3"
 
457
  { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
458
  ]
459
 
460
+ [[package]]
461
+ name = "mpmath"
462
+ version = "1.3.0"
463
+ source = { registry = "https://pypi.org/simple" }
464
+ sdist = { url = "https://files.pythonhosted.org/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106, upload-time = "2023-03-07T16:47:11.061Z" }
465
+ wheels = [
466
+ { url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198, upload-time = "2023-03-07T16:47:09.197Z" },
467
+ ]
468
+
469
+ [[package]]
470
+ name = "networkx"
471
+ version = "3.6.1"
472
+ source = { registry = "https://pypi.org/simple" }
473
+ sdist = { url = "https://files.pythonhosted.org/packages/6a/51/63fe664f3908c97be9d2e4f1158eb633317598cfa6e1fc14af5383f17512/networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509", size = 2517025, upload-time = "2025-12-08T17:02:39.908Z" }
474
+ wheels = [
475
+ { url = "https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762", size = 2068504, upload-time = "2025-12-08T17:02:38.159Z" },
476
+ ]
477
+
478
  [[package]]
479
  name = "numpy"
480
  version = "2.4.6"
 
501
  { url = "https://files.pythonhosted.org/packages/15/ce/e5ec180bc41812edcd8daeb8639d205622c0e8c02259d8ab25a0201b3c2a/numpy-2.4.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:2803abfebfc990042cd494d8ce2d5f82e9d847af6d35ec486923aa19dbad5e73", size = 12504263, upload-time = "2026-05-18T23:37:09.715Z" },
502
  ]
503
 
504
+ [[package]]
505
+ name = "nvidia-cublas"
506
+ version = "13.1.1.3"
507
+ source = { registry = "https://pypi.org/simple" }
508
+ dependencies = [
509
+ { name = "nvidia-cuda-nvrtc", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
510
+ ]
511
+ wheels = [
512
+ { url = "https://files.pythonhosted.org/packages/a7/a1/0bd24ee8c8d03adac032fd2909426a00c88f8c57961b1277ded97f91119f/nvidia_cublas-13.1.1.3-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:b7a210458267ac818974c53038fbec2e969d5c99f305ab15c72522fa9f001dd5", size = 542848918, upload-time = "2026-04-08T18:46:22.985Z" },
513
+ { url = "https://files.pythonhosted.org/packages/3b/cd/154ca20c38269e05eff77c1464e6c1da89f50a6390b565e9d82e06bc11e1/nvidia_cublas-13.1.1.3-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:37936a16db8fe4ac1f065c2139360608a543a09275cb1a1af612e08cfa065436", size = 423138758, upload-time = "2026-04-08T18:46:58.655Z" },
514
+ ]
515
+
516
+ [[package]]
517
+ name = "nvidia-cuda-cupti"
518
+ version = "13.0.85"
519
+ source = { registry = "https://pypi.org/simple" }
520
+ wheels = [
521
+ { url = "https://files.pythonhosted.org/packages/2a/2a/80353b103fc20ce05ef51e928daed4b6015db4aaa9162ed0997090fe2250/nvidia_cuda_cupti-13.0.85-py3-none-manylinux_2_25_aarch64.whl", hash = "sha256:796bd679890ee55fb14a94629b698b6db54bcfd833d391d5e94017dd9d7d3151", size = 10310827, upload-time = "2025-09-04T08:26:42.012Z" },
522
+ { url = "https://files.pythonhosted.org/packages/33/6d/737d164b4837a9bbd202f5ae3078975f0525a55730fe871d8ed4e3b952b0/nvidia_cuda_cupti-13.0.85-py3-none-manylinux_2_25_x86_64.whl", hash = "sha256:4eb01c08e859bf924d222250d2e8f8b8ff6d3db4721288cf35d14252a4d933c8", size = 10715597, upload-time = "2025-09-04T08:26:51.312Z" },
523
+ ]
524
+
525
+ [[package]]
526
+ name = "nvidia-cuda-nvrtc"
527
+ version = "13.0.88"
528
+ source = { registry = "https://pypi.org/simple" }
529
+ wheels = [
530
+ { url = "https://files.pythonhosted.org/packages/c3/68/483a78f5e8f31b08fb1bb671559968c0ca3a065ac7acabfc7cee55214fd6/nvidia_cuda_nvrtc-13.0.88-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:ad9b6d2ead2435f11cbb6868809d2adeeee302e9bb94bcf0539c7a40d80e8575", size = 90215200, upload-time = "2025-09-04T08:28:44.204Z" },
531
+ { url = "https://files.pythonhosted.org/packages/b7/dc/6bb80850e0b7edd6588d560758f17e0550893a1feaf436807d64d2da040f/nvidia_cuda_nvrtc-13.0.88-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d27f20a0ca67a4bb34268a5e951033496c5b74870b868bacd046b1b8e0c3267b", size = 43015449, upload-time = "2025-09-04T08:28:20.239Z" },
532
+ ]
533
+
534
+ [[package]]
535
+ name = "nvidia-cuda-runtime"
536
+ version = "13.0.96"
537
+ source = { registry = "https://pypi.org/simple" }
538
+ wheels = [
539
+ { url = "https://files.pythonhosted.org/packages/87/4f/17d7b9b8e285199c58ce28e31b5c5bbaa4d8271af06a89b6405258245de2/nvidia_cuda_runtime-13.0.96-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ef9bcbe90493a2b9d810e43d249adb3d02e98dd30200d86607d8d02687c43f55", size = 2261060, upload-time = "2025-10-09T08:55:15.78Z" },
540
+ { url = "https://files.pythonhosted.org/packages/2e/24/d1558f3b68b1d26e706813b1d10aa1d785e4698c425af8db8edc3dced472/nvidia_cuda_runtime-13.0.96-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7f82250d7782aa23b6cfe765ecc7db554bd3c2870c43f3d1821f1d18aebf0548", size = 2243632, upload-time = "2025-10-09T08:55:36.117Z" },
541
+ ]
542
+
543
+ [[package]]
544
+ name = "nvidia-cudnn-cu13"
545
+ version = "9.20.0.48"
546
+ source = { registry = "https://pypi.org/simple" }
547
+ dependencies = [
548
+ { name = "nvidia-cublas", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
549
+ ]
550
+ wheels = [
551
+ { url = "https://files.pythonhosted.org/packages/56/c5/83384d846b2fd17c44bd499b36c75a45ed4f095fbbb2252294e89cea5c5c/nvidia_cudnn_cu13-9.20.0.48-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:e31454ae00094b0c55319d9d15b6fa2fc50a9e1c0f5c8c80fb75258234e731e1", size = 444574296, upload-time = "2026-03-09T19:28:27.751Z" },
552
+ { url = "https://files.pythonhosted.org/packages/6e/5e/edb9c0ae051602c3ccaffe424256463636d639e27d7f302dde9975ef9e7a/nvidia_cudnn_cu13-9.20.0.48-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:0c45dd8eeb50b603f07995b1b300c62ffe6a1980482b82b3bcf94a4ca9d49304", size = 366173588, upload-time = "2026-03-09T19:29:34.474Z" },
553
+ ]
554
+
555
+ [[package]]
556
+ name = "nvidia-cufft"
557
+ version = "12.0.0.61"
558
+ source = { registry = "https://pypi.org/simple" }
559
+ dependencies = [
560
+ { name = "nvidia-nvjitlink", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
561
+ ]
562
+ wheels = [
563
+ { url = "https://files.pythonhosted.org/packages/8b/ae/f417a75c0259e85c1d2f83ca4e960289a5f814ed0cea74d18c353d3e989d/nvidia_cufft-12.0.0.61-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2708c852ef8cd89d1d2068bdbece0aa188813a0c934db3779b9b1faa8442e5f5", size = 214053554, upload-time = "2025-09-04T08:31:38.196Z" },
564
+ { url = "https://files.pythonhosted.org/packages/a8/2f/7b57e29836ea8714f81e9898409196f47d772d5ddedddf1592eadb8ab743/nvidia_cufft-12.0.0.61-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6c44f692dce8fd5ffd3e3df134b6cdb9c2f72d99cf40b62c32dde45eea9ddad3", size = 214085489, upload-time = "2025-09-04T08:31:56.044Z" },
565
+ ]
566
+
567
+ [[package]]
568
+ name = "nvidia-cufile"
569
+ version = "1.15.1.6"
570
+ source = { registry = "https://pypi.org/simple" }
571
+ wheels = [
572
+ { url = "https://files.pythonhosted.org/packages/3f/70/4f193de89a48b71714e74602ee14d04e4019ad36a5a9f20c425776e72cd6/nvidia_cufile-1.15.1.6-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:08a3ecefae5a01c7f5117351c64f17c7c62efa5fffdbe24fc7d298da19cd0b44", size = 1223672, upload-time = "2025-09-04T08:32:22.779Z" },
573
+ { url = "https://files.pythonhosted.org/packages/ab/73/cc4a14c9813a8a0d509417cf5f4bdaba76e924d58beb9864f5a7baceefbf/nvidia_cufile-1.15.1.6-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:bdc0deedc61f548bddf7733bdc216456c2fdb101d020e1ab4b88d232d5e2f6d1", size = 1136992, upload-time = "2025-09-04T08:32:14.119Z" },
574
+ ]
575
+
576
+ [[package]]
577
+ name = "nvidia-curand"
578
+ version = "10.4.0.35"
579
+ source = { registry = "https://pypi.org/simple" }
580
+ wheels = [
581
+ { url = "https://files.pythonhosted.org/packages/1e/72/7c2ae24fb6b63a32e6ae5d241cc65263ea18d08802aaae087d9f013335a2/nvidia_curand-10.4.0.35-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:133df5a7509c3e292aaa2b477afd0194f06ce4ea24d714d616ff36439cee349a", size = 61962106, upload-time = "2025-08-04T10:21:41.128Z" },
582
+ { url = "https://files.pythonhosted.org/packages/a5/9f/be0a41ca4a4917abf5cb9ae0daff1a6060cc5de950aec0396de9f3b52bc5/nvidia_curand-10.4.0.35-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:1aee33a5da6e1db083fe2b90082def8915f30f3248d5896bcec36a579d941bfc", size = 59544258, upload-time = "2025-08-04T10:22:03.992Z" },
583
+ ]
584
+
585
+ [[package]]
586
+ name = "nvidia-cusolver"
587
+ version = "12.0.4.66"
588
+ source = { registry = "https://pypi.org/simple" }
589
+ dependencies = [
590
+ { name = "nvidia-cublas", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
591
+ { name = "nvidia-cusparse", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
592
+ { name = "nvidia-nvjitlink", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
593
+ ]
594
+ wheels = [
595
+ { url = "https://files.pythonhosted.org/packages/c8/c3/b30c9e935fc01e3da443ec0116ed1b2a009bb867f5324d3f2d7e533e776b/nvidia_cusolver-12.0.4.66-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:02c2457eaa9e39de20f880f4bd8820e6a1cfb9f9a34f820eb12a155aa5bc92d2", size = 223467760, upload-time = "2025-09-04T08:33:04.222Z" },
596
+ { url = "https://files.pythonhosted.org/packages/5f/67/cba3777620cdacb99102da4042883709c41c709f4b6323c10781a9c3aa34/nvidia_cusolver-12.0.4.66-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:0a759da5dea5c0ea10fd307de75cdeb59e7ea4fcb8add0924859b944babf1112", size = 200941980, upload-time = "2025-09-04T08:33:22.767Z" },
597
+ ]
598
+
599
+ [[package]]
600
+ name = "nvidia-cusparse"
601
+ version = "12.6.3.3"
602
+ source = { registry = "https://pypi.org/simple" }
603
+ dependencies = [
604
+ { name = "nvidia-nvjitlink", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
605
+ ]
606
+ wheels = [
607
+ { url = "https://files.pythonhosted.org/packages/f8/94/5c26f33738ae35276672f12615a64bd008ed5be6d1ebcb23579285d960a9/nvidia_cusparse-12.6.3.3-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:80bcc4662f23f1054ee334a15c72b8940402975e0eab63178fc7e670aa59472c", size = 162155568, upload-time = "2025-09-04T08:33:42.864Z" },
608
+ { url = "https://files.pythonhosted.org/packages/fa/18/623c77619c31d62efd55302939756966f3ecc8d724a14dab2b75f1508850/nvidia_cusparse-12.6.3.3-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2b3c89c88d01ee0e477cb7f82ef60a11a4bcd57b6b87c33f789350b59759360b", size = 145942937, upload-time = "2025-09-04T08:33:58.029Z" },
609
+ ]
610
+
611
+ [[package]]
612
+ name = "nvidia-cusparselt-cu13"
613
+ version = "0.8.1"
614
+ source = { registry = "https://pypi.org/simple" }
615
+ wheels = [
616
+ { url = "https://files.pythonhosted.org/packages/46/e1/cdc1797eadf82d3a9a575a19b33fdc871a97edbec42c00b5b5e914f4aff4/nvidia_cusparselt_cu13-0.8.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:4dca476c50bf4780d46cd0bfbd82e2bc10a08e4fef7950917ce8d7578d22a23f", size = 221051344, upload-time = "2025-09-05T18:49:51.289Z" },
617
+ { url = "https://files.pythonhosted.org/packages/34/7d/2661f2fb3ac4302f3a246f5fc030213ac60c1fe0bce84f9783dbd831dbb7/nvidia_cusparselt_cu13-0.8.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:786ce87568c303fadb5afcc7102d454cd3040d75f6f8626f5db460d1871f4dd0", size = 170148586, upload-time = "2025-09-05T18:50:50.248Z" },
618
+ ]
619
+
620
+ [[package]]
621
+ name = "nvidia-nccl-cu13"
622
+ version = "2.29.7"
623
+ source = { registry = "https://pypi.org/simple" }
624
+ wheels = [
625
+ { url = "https://files.pythonhosted.org/packages/72/0d/daf50d44177ee0cbc7ff0a0c91eb5ff676c82be42f9a970bc7597f440c3a/nvidia_nccl_cu13-2.29.7-py3-none-manylinux_2_18_aarch64.whl", hash = "sha256:674a12383e3c38a1bcccae7d4f3633b37852230b6047883cb2f4c2d1b36d9bf5", size = 206014712, upload-time = "2026-03-03T05:34:20.843Z" },
626
+ { url = "https://files.pythonhosted.org/packages/67/f4/58e4e91b6919367c7aafb8e36fce9aad1a3047e536bf7e2fd560927d3a4c/nvidia_nccl_cu13-2.29.7-py3-none-manylinux_2_18_x86_64.whl", hash = "sha256:edd81538446786ec3b73972543e53bb43bcaf0bfc8ef76cb679fcc390ffe136d", size = 205976000, upload-time = "2026-03-03T05:36:24.472Z" },
627
+ ]
628
+
629
+ [[package]]
630
+ name = "nvidia-nvjitlink"
631
+ version = "13.0.88"
632
+ source = { registry = "https://pypi.org/simple" }
633
+ wheels = [
634
+ { url = "https://files.pythonhosted.org/packages/56/7a/123e033aaff487c77107195fa5a2b8686795ca537935a24efae476c41f05/nvidia_nvjitlink-13.0.88-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:13a74f429e23b921c1109976abefacc69835f2f433ebd323d3946e11d804e47b", size = 40713933, upload-time = "2025-09-04T08:35:43.553Z" },
635
+ { url = "https://files.pythonhosted.org/packages/ab/2c/93c5250e64df4f894f1cbb397c6fd71f79813f9fd79d7cd61de3f97b3c2d/nvidia_nvjitlink-13.0.88-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e931536ccc7d467a98ba1d8b89ff7fa7f1fa3b13f2b0069118cd7f47bff07d0c", size = 38768748, upload-time = "2025-09-04T08:35:20.008Z" },
636
+ ]
637
+
638
+ [[package]]
639
+ name = "nvidia-nvshmem-cu13"
640
+ version = "3.4.5"
641
+ source = { registry = "https://pypi.org/simple" }
642
+ wheels = [
643
+ { url = "https://files.pythonhosted.org/packages/dc/0f/05cc9c720236dcd2db9c1ab97fff629e96821be2e63103569da0c9b72f19/nvidia_nvshmem_cu13-3.4.5-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6dc2a197f38e5d0376ad52cd1a2a3617d3cdc150fd5966f4aee9bcebb1d68fe9", size = 60215947, upload-time = "2025-09-06T00:32:20.022Z" },
644
+ { url = "https://files.pythonhosted.org/packages/3c/35/a9bf80a609e74e3b000fef598933235c908fcefcef9026042b8e6dfde2a9/nvidia_nvshmem_cu13-3.4.5-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:290f0a2ee94c9f3687a02502f3b9299a9f9fe826e6d0287ee18482e78d495b80", size = 60412546, upload-time = "2025-09-06T00:32:41.564Z" },
645
+ ]
646
+
647
+ [[package]]
648
+ name = "nvidia-nvtx"
649
+ version = "13.0.85"
650
+ source = { registry = "https://pypi.org/simple" }
651
+ wheels = [
652
+ { url = "https://files.pythonhosted.org/packages/c2/f3/d86c845465a2723ad7e1e5c36dcd75ddb82898b3f53be47ebd429fb2fa5d/nvidia_nvtx-13.0.85-py3-none-manylinux1_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4936d1d6780fbe68db454f5e72a42ff64d1fd6397df9f363ae786930fd5c1cd4", size = 148047, upload-time = "2025-09-04T08:29:01.761Z" },
653
+ { url = "https://files.pythonhosted.org/packages/a8/64/3708a90d1ebe202ffdeb7185f878a3c84d15c2b2c31858da2ce0583e2def/nvidia_nvtx-13.0.85-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cb7780edb6b14107373c835bf8b72e7a178bac7367e23da7acb108f973f157a6", size = 148878, upload-time = "2025-09-04T08:28:53.627Z" },
654
+ ]
655
+
656
  [[package]]
657
  name = "orjson"
658
  version = "3.11.9"
 
741
  { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
742
  ]
743
 
744
+ [[package]]
745
+ name = "psutil"
746
+ version = "7.2.2"
747
+ source = { registry = "https://pypi.org/simple" }
748
+ sdist = { url = "https://files.pythonhosted.org/packages/aa/c6/d1ddf4abb55e93cebc4f2ed8b5d6dbad109ecb8d63748dd2b20ab5e57ebe/psutil-7.2.2.tar.gz", hash = "sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372", size = 493740, upload-time = "2026-01-28T18:14:54.428Z" }
749
+ wheels = [
750
+ { url = "https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486", size = 129090, upload-time = "2026-01-28T18:15:22.168Z" },
751
+ { url = "https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979", size = 129859, upload-time = "2026-01-28T18:15:23.795Z" },
752
+ { url = "https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9", size = 155560, upload-time = "2026-01-28T18:15:25.976Z" },
753
+ { url = "https://files.pythonhosted.org/packages/63/65/37648c0c158dc222aba51c089eb3bdfa238e621674dc42d48706e639204f/psutil-7.2.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e", size = 156997, upload-time = "2026-01-28T18:15:27.794Z" },
754
+ { url = "https://files.pythonhosted.org/packages/8e/13/125093eadae863ce03c6ffdbae9929430d116a246ef69866dad94da3bfbc/psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8", size = 148972, upload-time = "2026-01-28T18:15:29.342Z" },
755
+ { url = "https://files.pythonhosted.org/packages/04/78/0acd37ca84ce3ddffaa92ef0f571e073faa6d8ff1f0559ab1272188ea2be/psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc", size = 148266, upload-time = "2026-01-28T18:15:31.597Z" },
756
+ { url = "https://files.pythonhosted.org/packages/b4/90/e2159492b5426be0c1fef7acba807a03511f97c5f86b3caeda6ad92351a7/psutil-7.2.2-cp37-abi3-win_amd64.whl", hash = "sha256:eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988", size = 137737, upload-time = "2026-01-28T18:15:33.849Z" },
757
+ { url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee", size = 134617, upload-time = "2026-01-28T18:15:36.514Z" },
758
+ ]
759
+
760
  [[package]]
761
  name = "pydantic"
762
  version = "2.12.5"
 
890
  { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" },
891
  ]
892
 
893
+ [[package]]
894
+ name = "regex"
895
+ version = "2026.5.9"
896
+ source = { registry = "https://pypi.org/simple" }
897
+ sdist = { url = "https://files.pythonhosted.org/packages/dc/0e/49aee608ad09480e7fd276898c99ec6192985fa331abe4eb3a986094490b/regex-2026.5.9.tar.gz", hash = "sha256:a8234aa23ec39894bfe4a3f1b85616a7032481964a13ac6fc9f10de4f6fca270", size = 416074, upload-time = "2026-05-09T23:15:19.37Z" }
898
+ wheels = [
899
+ { url = "https://files.pythonhosted.org/packages/c2/dc/c1f2df4027e82fc54b5a473e4b250f5139faca49a0fbe29a48668d228f34/regex-2026.5.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ccf5249114cc3e772ecdd88a98a86eca0fd74c61ce32a94743758c083fc05d48", size = 489445, upload-time = "2026-05-09T23:12:06.111Z" },
900
+ { url = "https://files.pythonhosted.org/packages/03/d2/59f01110660081cce9c0bc30ebd0b5ee250dacf658e3248ed92f01e0e8ee/regex-2026.5.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46f1326ca6e65b0879d23ca302c0f2415aad42ff0309b9c818e7949fe19a41d8", size = 291271, upload-time = "2026-05-09T23:12:07.731Z" },
901
+ { url = "https://files.pythonhosted.org/packages/58/b6/14b2c84ff90ddb370c81d27503f4a0fcf071496416f4855f6cc8c5d81c35/regex-2026.5.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ef31cbfe458e21c6122ba8150ff060e0c7789ed0d26eb423f25472584920b555", size = 289212, upload-time = "2026-05-09T23:12:09.266Z" },
902
+ { url = "https://files.pythonhosted.org/packages/03/d0/4db86529117320de0c84afd90e70bb47434625875e34fcef9d8c127c5b16/regex-2026.5.9-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:992604d02e6d9c6d786c24a706a71ecffe1020fc1ef264044474cd81fa2c3919", size = 792310, upload-time = "2026-05-09T23:12:11.416Z" },
903
+ { url = "https://files.pythonhosted.org/packages/07/78/fe4800cd322f862ecffd2d553409b20d80650e5ed71b9d178f853d020b82/regex-2026.5.9-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9411dd64ca95477225734a93dfc8583b51916b8d5942f99d6cac21e09965451", size = 861721, upload-time = "2026-05-09T23:12:13.681Z" },
904
+ { url = "https://files.pythonhosted.org/packages/b5/d0/b3618a895dd8feb897c61bb2954edd265e1767d82a01d53065d5871127a3/regex-2026.5.9-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3dd4a3ff360dfb836fecdb93a4598f9d6e2ac81e3e397125145c6221bf58cf4c", size = 906460, upload-time = "2026-05-09T23:12:15.443Z" },
905
+ { url = "https://files.pythonhosted.org/packages/33/6f/1481597e859ef19508b345eec4afd1416ed6e6b459c75a64026ef193aecf/regex-2026.5.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2a661a7d270a61f7cf460caee8b9fa2d5ef9e5c681234bcb9e0fe14f488e7dfc", size = 799843, upload-time = "2026-05-09T23:12:16.892Z" },
906
+ { url = "https://files.pythonhosted.org/packages/73/59/955734c803f59108deccba3597ae440c76b62a652733c0006e6243758420/regex-2026.5.9-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f079e50a0d3cc3cd5091fa9ff45869a2e6b2cd35895731edafb0327901a8d86d", size = 773610, upload-time = "2026-05-09T23:12:19.127Z" },
907
+ { url = "https://files.pythonhosted.org/packages/68/8f/70c04a236d651c81881dac42ef8538bddda6121434509d0a22d9e601503b/regex-2026.5.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4ebe8f0b5ec5a5024dc4a4c59f444c4e9afc5f2abdbb8962065b75d27fb971f9", size = 781645, upload-time = "2026-05-09T23:12:20.806Z" },
908
+ { url = "https://files.pythonhosted.org/packages/1d/96/05c7434d88185e5d27fe54aeb74df86bd77cd79f52f0b4eae54faa8fea70/regex-2026.5.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:97cf3bc1b7d7d2306772ec07366c80d9df00ff79e79cea32898883a646d2fae2", size = 854473, upload-time = "2026-05-09T23:12:22.465Z" },
909
+ { url = "https://files.pythonhosted.org/packages/4e/c1/6e3d8202d981f3117004bf341ee74893ba4ba8a9fbaf4b94615846550a08/regex-2026.5.9-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0f9eede6a5cbdc02d4978090186390936e1776a7d1359b21e41014c609880bcf", size = 763311, upload-time = "2026-05-09T23:12:24.351Z" },
910
+ { url = "https://files.pythonhosted.org/packages/93/c7/e7737f1526b3fb32bd4c337fd6c71c3ebb5c8296fc34d11197e0955d2e35/regex-2026.5.9-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:01f0f5f55f4b64dacec85dc116d3c05fd23ad3ff037bbc73a2085775953c2611", size = 844593, upload-time = "2026-05-09T23:12:26.341Z" },
911
+ { url = "https://files.pythonhosted.org/packages/a5/27/0daffb1a535bb39f422c3d200f4ab023c71110ad66a32b366bee708baba0/regex-2026.5.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1268eddd8486dc561d08eee1156e40aa3a8fe10f4bdec8fa653b455fcbffd12c", size = 789167, upload-time = "2026-05-09T23:12:27.975Z" },
912
+ { url = "https://files.pythonhosted.org/packages/ce/fc/294fe4fac4f2ed67207b17471815870c1c45b3a489e08e0ac96daea16ef6/regex-2026.5.9-cp311-cp311-win32.whl", hash = "sha256:8676474c07469d6f33dd1085ca2cd45f65785f32518f2b20e36d9953ca07f994", size = 266249, upload-time = "2026-05-09T23:12:30.141Z" },
913
+ { url = "https://files.pythonhosted.org/packages/d0/b0/8dce459f6245bcf8f6e9f23ac9569f1a0f15c131cc0745e82b43226204cf/regex-2026.5.9-cp311-cp311-win_amd64.whl", hash = "sha256:246de9d60aa3f8538b519834dd95cbf276ea263d6a7bd5a3666dc3fa0230505b", size = 278423, upload-time = "2026-05-09T23:12:31.676Z" },
914
+ { url = "https://files.pythonhosted.org/packages/db/8d/f9aeff6ad63a3ef720386f2907e6d34a35a510a6e498ebad28b0fb3f6ab6/regex-2026.5.9-cp311-cp311-win_arm64.whl", hash = "sha256:d726ca3f0d76969bf1e8e477d160d3d666bbf999f6860bd314889e5345782046", size = 270420, upload-time = "2026-05-09T23:12:33.194Z" },
915
+ ]
916
+
917
  [[package]]
918
  name = "rich"
919
  version = "15.0.0"
 
964
  { url = "https://files.pythonhosted.org/packages/2e/a3/0f0b7d78e2f1eb9e8e1afbff1d2bff8d60144aee17aca51c065b516743dd/safehttpx-0.1.7-py3-none-any.whl", hash = "sha256:c4f4a162db6993464d7ca3d7cc4af0ffc6515a606dfd220b9f82c6945d869cde", size = 8959, upload-time = "2025-10-24T18:30:08.733Z" },
965
  ]
966
 
967
+ [[package]]
968
+ name = "safetensors"
969
+ version = "0.7.0"
970
+ source = { registry = "https://pypi.org/simple" }
971
+ sdist = { url = "https://files.pythonhosted.org/packages/29/9c/6e74567782559a63bd040a236edca26fd71bc7ba88de2ef35d75df3bca5e/safetensors-0.7.0.tar.gz", hash = "sha256:07663963b67e8bd9f0b8ad15bb9163606cd27cc5a1b96235a50d8369803b96b0", size = 200878, upload-time = "2025-11-19T15:18:43.199Z" }
972
+ wheels = [
973
+ { url = "https://files.pythonhosted.org/packages/fa/47/aef6c06649039accf914afef490268e1067ed82be62bcfa5b7e886ad15e8/safetensors-0.7.0-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:c82f4d474cf725255d9e6acf17252991c3c8aac038d6ef363a4bf8be2f6db517", size = 467781, upload-time = "2025-11-19T15:18:35.84Z" },
974
+ { url = "https://files.pythonhosted.org/packages/e8/00/374c0c068e30cd31f1e1b46b4b5738168ec79e7689ca82ee93ddfea05109/safetensors-0.7.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:94fd4858284736bb67a897a41608b5b0c2496c9bdb3bf2af1fa3409127f20d57", size = 447058, upload-time = "2025-11-19T15:18:34.416Z" },
975
+ { url = "https://files.pythonhosted.org/packages/f1/06/578ffed52c2296f93d7fd2d844cabfa92be51a587c38c8afbb8ae449ca89/safetensors-0.7.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e07d91d0c92a31200f25351f4acb2bc6aff7f48094e13ebb1d0fb995b54b6542", size = 491748, upload-time = "2025-11-19T15:18:09.79Z" },
976
+ { url = "https://files.pythonhosted.org/packages/ae/33/1debbbb70e4791dde185edb9413d1fe01619255abb64b300157d7f15dddd/safetensors-0.7.0-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8469155f4cb518bafb4acf4865e8bb9d6804110d2d9bdcaa78564b9fd841e104", size = 503881, upload-time = "2025-11-19T15:18:16.145Z" },
977
+ { url = "https://files.pythonhosted.org/packages/8e/1c/40c2ca924d60792c3be509833df711b553c60effbd91da6f5284a83f7122/safetensors-0.7.0-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:54bef08bf00a2bff599982f6b08e8770e09cc012d7bba00783fc7ea38f1fb37d", size = 623463, upload-time = "2025-11-19T15:18:21.11Z" },
978
+ { url = "https://files.pythonhosted.org/packages/9b/3a/13784a9364bd43b0d61eef4bea2845039bc2030458b16594a1bd787ae26e/safetensors-0.7.0-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:42cb091236206bb2016d245c377ed383aa7f78691748f3bb6ee1bfa51ae2ce6a", size = 532855, upload-time = "2025-11-19T15:18:25.719Z" },
979
+ { url = "https://files.pythonhosted.org/packages/a0/60/429e9b1cb3fc651937727befe258ea24122d9663e4d5709a48c9cbfceecb/safetensors-0.7.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac7252938f0696ddea46f5e855dd3138444e82236e3be475f54929f0c510d48", size = 507152, upload-time = "2025-11-19T15:18:33.023Z" },
980
+ { url = "https://files.pythonhosted.org/packages/3c/a8/4b45e4e059270d17af60359713ffd83f97900d45a6afa73aaa0d737d48b6/safetensors-0.7.0-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1d060c70284127fa805085d8f10fbd0962792aed71879d00864acda69dbab981", size = 541856, upload-time = "2025-11-19T15:18:31.075Z" },
981
+ { url = "https://files.pythonhosted.org/packages/06/87/d26d8407c44175d8ae164a95b5a62707fcc445f3c0c56108e37d98070a3d/safetensors-0.7.0-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:cdab83a366799fa730f90a4ebb563e494f28e9e92c4819e556152ad55e43591b", size = 674060, upload-time = "2025-11-19T15:18:37.211Z" },
982
+ { url = "https://files.pythonhosted.org/packages/11/f5/57644a2ff08dc6325816ba7217e5095f17269dada2554b658442c66aed51/safetensors-0.7.0-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:672132907fcad9f2aedcb705b2d7b3b93354a2aec1b2f706c4db852abe338f85", size = 771715, upload-time = "2025-11-19T15:18:38.689Z" },
983
+ { url = "https://files.pythonhosted.org/packages/86/31/17883e13a814bd278ae6e266b13282a01049b0c81341da7fd0e3e71a80a3/safetensors-0.7.0-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:5d72abdb8a4d56d4020713724ba81dac065fedb7f3667151c4a637f1d3fb26c0", size = 714377, upload-time = "2025-11-19T15:18:40.162Z" },
984
+ { url = "https://files.pythonhosted.org/packages/4a/d8/0c8a7dc9b41dcac53c4cbf9df2b9c83e0e0097203de8b37a712b345c0be5/safetensors-0.7.0-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b0f6d66c1c538d5a94a73aa9ddca8ccc4227e6c9ff555322ea40bdd142391dd4", size = 677368, upload-time = "2025-11-19T15:18:41.627Z" },
985
+ { url = "https://files.pythonhosted.org/packages/05/e5/cb4b713c8a93469e3c5be7c3f8d77d307e65fe89673e731f5c2bfd0a9237/safetensors-0.7.0-cp38-abi3-win32.whl", hash = "sha256:c74af94bf3ac15ac4d0f2a7c7b4663a15f8c2ab15ed0fc7531ca61d0835eccba", size = 326423, upload-time = "2025-11-19T15:18:45.74Z" },
986
+ { url = "https://files.pythonhosted.org/packages/5d/e6/ec8471c8072382cb91233ba7267fd931219753bb43814cbc71757bfd4dab/safetensors-0.7.0-cp38-abi3-win_amd64.whl", hash = "sha256:d1239932053f56f3456f32eb9625590cc7582e905021f94636202a864d470755", size = 341380, upload-time = "2025-11-19T15:18:44.427Z" },
987
+ ]
988
+
989
  [[package]]
990
  name = "semantic-version"
991
  version = "2.10.0"
 
995
  { url = "https://files.pythonhosted.org/packages/6a/23/8146aad7d88f4fcb3a6218f41a60f6c2d4e3a72de72da1825dc7c8f7877c/semantic_version-2.10.0-py2.py3-none-any.whl", hash = "sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177", size = 15552, upload-time = "2022-05-26T13:35:21.206Z" },
996
  ]
997
 
998
+ [[package]]
999
+ name = "setuptools"
1000
+ version = "81.0.0"
1001
+ source = { registry = "https://pypi.org/simple" }
1002
+ sdist = { url = "https://files.pythonhosted.org/packages/0d/1c/73e719955c59b8e424d015ab450f51c0af856ae46ea2da83eba51cc88de1/setuptools-81.0.0.tar.gz", hash = "sha256:487b53915f52501f0a79ccfd0c02c165ffe06631443a886740b91af4b7a5845a", size = 1198299, upload-time = "2026-02-06T21:10:39.601Z" }
1003
+ wheels = [
1004
+ { url = "https://files.pythonhosted.org/packages/e1/e3/c164c88b2e5ce7b24d667b9bd83589cf4f3520d97cad01534cd3c4f55fdb/setuptools-81.0.0-py3-none-any.whl", hash = "sha256:fdd925d5c5d9f62e4b74b30d6dd7828ce236fd6ed998a08d81de62ce5a6310d6", size = 1062021, upload-time = "2026-02-06T21:10:37.175Z" },
1005
+ ]
1006
+
1007
  [[package]]
1008
  name = "shellingham"
1009
  version = "1.5.4"
 
1035
  { url = "https://files.pythonhosted.org/packages/81/0d/13d1d239a25cbfb19e740db83143e95c772a1fe10202dda4b76792b114dd/starlette-0.52.1-py3-none-any.whl", hash = "sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74", size = 74272, upload-time = "2026-01-18T13:34:09.188Z" },
1036
  ]
1037
 
1038
+ [[package]]
1039
+ name = "sympy"
1040
+ version = "1.14.0"
1041
+ source = { registry = "https://pypi.org/simple" }
1042
+ dependencies = [
1043
+ { name = "mpmath" },
1044
+ ]
1045
+ sdist = { url = "https://files.pythonhosted.org/packages/83/d3/803453b36afefb7c2bb238361cd4ae6125a569b4db67cd9e79846ba2d68c/sympy-1.14.0.tar.gz", hash = "sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517", size = 7793921, upload-time = "2025-04-27T18:05:01.611Z" }
1046
+ wheels = [
1047
+ { url = "https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl", hash = "sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5", size = 6299353, upload-time = "2025-04-27T18:04:59.103Z" },
1048
+ ]
1049
+
1050
+ [[package]]
1051
+ name = "tokenizers"
1052
+ version = "0.22.2"
1053
+ source = { registry = "https://pypi.org/simple" }
1054
+ dependencies = [
1055
+ { name = "huggingface-hub" },
1056
+ ]
1057
+ sdist = { url = "https://files.pythonhosted.org/packages/73/6f/f80cfef4a312e1fb34baf7d85c72d4411afde10978d4657f8cdd811d3ccc/tokenizers-0.22.2.tar.gz", hash = "sha256:473b83b915e547aa366d1eee11806deaf419e17be16310ac0a14077f1e28f917", size = 372115, upload-time = "2026-01-05T10:45:15.988Z" }
1058
+ wheels = [
1059
+ { url = "https://files.pythonhosted.org/packages/92/97/5dbfabf04c7e348e655e907ed27913e03db0923abb5dfdd120d7b25630e1/tokenizers-0.22.2-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:544dd704ae7238755d790de45ba8da072e9af3eea688f698b137915ae959281c", size = 3100275, upload-time = "2026-01-05T10:41:02.158Z" },
1060
+ { url = "https://files.pythonhosted.org/packages/2e/47/174dca0502ef88b28f1c9e06b73ce33500eedfac7a7692108aec220464e7/tokenizers-0.22.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:1e418a55456beedca4621dbab65a318981467a2b188e982a23e117f115ce5001", size = 2981472, upload-time = "2026-01-05T10:41:00.276Z" },
1061
+ { url = "https://files.pythonhosted.org/packages/d6/84/7990e799f1309a8b87af6b948f31edaa12a3ed22d11b352eaf4f4b2e5753/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2249487018adec45d6e3554c71d46eb39fa8ea67156c640f7513eb26f318cec7", size = 3290736, upload-time = "2026-01-05T10:40:32.165Z" },
1062
+ { url = "https://files.pythonhosted.org/packages/78/59/09d0d9ba94dcd5f4f1368d4858d24546b4bdc0231c2354aa31d6199f0399/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25b85325d0815e86e0bac263506dd114578953b7b53d7de09a6485e4a160a7dd", size = 3168835, upload-time = "2026-01-05T10:40:38.847Z" },
1063
+ { url = "https://files.pythonhosted.org/packages/47/50/b3ebb4243e7160bda8d34b731e54dd8ab8b133e50775872e7a434e524c28/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfb88f22a209ff7b40a576d5324bf8286b519d7358663db21d6246fb17eea2d5", size = 3521673, upload-time = "2026-01-05T10:40:56.614Z" },
1064
+ { url = "https://files.pythonhosted.org/packages/e0/fa/89f4cb9e08df770b57adb96f8cbb7e22695a4cb6c2bd5f0c4f0ebcf33b66/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c774b1276f71e1ef716e5486f21e76333464f47bece56bbd554485982a9e03e", size = 3724818, upload-time = "2026-01-05T10:40:44.507Z" },
1065
+ { url = "https://files.pythonhosted.org/packages/64/04/ca2363f0bfbe3b3d36e95bf67e56a4c88c8e3362b658e616d1ac185d47f2/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df6c4265b289083bf710dff49bc51ef252f9d5be33a45ee2bed151114a56207b", size = 3379195, upload-time = "2026-01-05T10:40:51.139Z" },
1066
+ { url = "https://files.pythonhosted.org/packages/2e/76/932be4b50ef6ccedf9d3c6639b056a967a86258c6d9200643f01269211ca/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:369cc9fc8cc10cb24143873a0d95438bb8ee257bb80c71989e3ee290e8d72c67", size = 3274982, upload-time = "2026-01-05T10:40:58.331Z" },
1067
+ { url = "https://files.pythonhosted.org/packages/1d/28/5f9f5a4cc211b69e89420980e483831bcc29dade307955cc9dc858a40f01/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:29c30b83d8dcd061078b05ae0cb94d3c710555fbb44861139f9f83dcca3dc3e4", size = 9478245, upload-time = "2026-01-05T10:41:04.053Z" },
1068
+ { url = "https://files.pythonhosted.org/packages/6c/fb/66e2da4704d6aadebf8cb39f1d6d1957df667ab24cff2326b77cda0dcb85/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:37ae80a28c1d3265bb1f22464c856bd23c02a05bb211e56d0c5301a435be6c1a", size = 9560069, upload-time = "2026-01-05T10:45:10.673Z" },
1069
+ { url = "https://files.pythonhosted.org/packages/16/04/fed398b05caa87ce9b1a1bb5166645e38196081b225059a6edaff6440fac/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:791135ee325f2336f498590eb2f11dc5c295232f288e75c99a36c5dbce63088a", size = 9899263, upload-time = "2026-01-05T10:45:12.559Z" },
1070
+ { url = "https://files.pythonhosted.org/packages/05/a1/d62dfe7376beaaf1394917e0f8e93ee5f67fea8fcf4107501db35996586b/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:38337540fbbddff8e999d59970f3c6f35a82de10053206a7562f1ea02d046fa5", size = 10033429, upload-time = "2026-01-05T10:45:14.333Z" },
1071
+ { url = "https://files.pythonhosted.org/packages/fd/18/a545c4ea42af3df6effd7d13d250ba77a0a86fb20393143bbb9a92e434d4/tokenizers-0.22.2-cp39-abi3-win32.whl", hash = "sha256:a6bf3f88c554a2b653af81f3204491c818ae2ac6fbc09e76ef4773351292bc92", size = 2502363, upload-time = "2026-01-05T10:45:20.593Z" },
1072
+ { url = "https://files.pythonhosted.org/packages/65/71/0670843133a43d43070abeb1949abfdef12a86d490bea9cd9e18e37c5ff7/tokenizers-0.22.2-cp39-abi3-win_amd64.whl", hash = "sha256:c9ea31edff2968b44a88f97d784c2f16dc0729b8b143ed004699ebca91f05c48", size = 2747786, upload-time = "2026-01-05T10:45:18.411Z" },
1073
+ { url = "https://files.pythonhosted.org/packages/72/f4/0de46cfa12cdcbcd464cc59fde36912af405696f687e53a091fb432f694c/tokenizers-0.22.2-cp39-abi3-win_arm64.whl", hash = "sha256:9ce725d22864a1e965217204946f830c37876eee3b2ba6fc6255e8e903d5fcbc", size = 2612133, upload-time = "2026-01-05T10:45:17.232Z" },
1074
+ ]
1075
+
1076
  [[package]]
1077
  name = "tomlkit"
1078
  version = "0.13.3"
 
1082
  { url = "https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl", hash = "sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0", size = 38901, upload-time = "2025-06-05T07:13:43.546Z" },
1083
  ]
1084
 
1085
+ [[package]]
1086
+ name = "torch"
1087
+ version = "2.12.0"
1088
+ source = { registry = "https://pypi.org/simple" }
1089
+ dependencies = [
1090
+ { name = "cuda-bindings", marker = "sys_platform == 'linux'" },
1091
+ { name = "cuda-toolkit", extra = ["cudart", "cufft", "cufile", "cupti", "curand", "cusolver", "cusparse", "nvjitlink", "nvrtc", "nvtx"], marker = "sys_platform == 'linux'" },
1092
+ { name = "filelock" },
1093
+ { name = "fsspec" },
1094
+ { name = "jinja2" },
1095
+ { name = "networkx" },
1096
+ { name = "nvidia-cublas", marker = "sys_platform == 'linux'" },
1097
+ { name = "nvidia-cudnn-cu13", marker = "sys_platform == 'linux'" },
1098
+ { name = "nvidia-cusparselt-cu13", marker = "sys_platform == 'linux'" },
1099
+ { name = "nvidia-nccl-cu13", marker = "sys_platform == 'linux'" },
1100
+ { name = "nvidia-nvshmem-cu13", marker = "sys_platform == 'linux'" },
1101
+ { name = "setuptools" },
1102
+ { name = "sympy" },
1103
+ { name = "triton", marker = "sys_platform == 'linux'" },
1104
+ { name = "typing-extensions" },
1105
+ ]
1106
+ wheels = [
1107
+ { url = "https://files.pythonhosted.org/packages/18/62/131124fb95df03811b8260d1d43dcc5ee85ea1a344b964613d7efe77fb08/torch-2.12.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:10802fd383bbfed646212e765a72c37d2185205d4f26eb197a254e8ac7ddcb25", size = 87990344, upload-time = "2026-05-13T14:55:42.154Z" },
1108
+ { url = "https://files.pythonhosted.org/packages/12/9c/dda0dbd547dc549839824135f223792fd0e725f28ed0715dda366b7acaa2/torch-2.12.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:c12592630aef72feaf18bd3f197ef587bbfa21131b31c38b23ab2e55fce92e36", size = 426362932, upload-time = "2026-05-13T14:54:15.295Z" },
1109
+ { url = "https://files.pythonhosted.org/packages/e2/d2/a7dd5a3f9bdaa7842124e8e2359202b317c48d47d2fc5816fafdf2049adb/torch-2.12.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:415c1b8d0412f67551c8e89a2daca0fb3e56694af0281ba155eaa9da481f58b4", size = 532170085, upload-time = "2026-05-13T14:55:20.788Z" },
1110
+ { url = "https://files.pythonhosted.org/packages/12/1b/a61ce2004f9ab0ea8964a6e6168133a127795667639e2ff4f8f2bdb16a65/torch-2.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:dd37188ea325042cb1f6cafa56822b11ada2520c04791a52629b0af25bdfbfd9", size = 122953128, upload-time = "2026-05-13T14:54:52.744Z" },
1111
+ ]
1112
+
1113
  [[package]]
1114
  name = "tqdm"
1115
  version = "4.68.1"
 
1122
  { url = "https://files.pythonhosted.org/packages/47/aa/218a0eb34de1f753c83e4d0d1c8e7c4cef27f20dcb8342e024f63a80dc86/tqdm-4.68.1-py3-none-any.whl", hash = "sha256:fea4a90e4023f764914569f7802a297277c5ab1a66be5144143e142e1a4031d8", size = 78354, upload-time = "2026-06-05T17:23:13.654Z" },
1123
  ]
1124
 
1125
+ [[package]]
1126
+ name = "transformers"
1127
+ version = "5.10.2"
1128
+ source = { registry = "https://pypi.org/simple" }
1129
+ dependencies = [
1130
+ { name = "huggingface-hub" },
1131
+ { name = "numpy" },
1132
+ { name = "packaging" },
1133
+ { name = "pyyaml" },
1134
+ { name = "regex" },
1135
+ { name = "safetensors" },
1136
+ { name = "tokenizers" },
1137
+ { name = "tqdm" },
1138
+ { name = "typer" },
1139
+ ]
1140
+ sdist = { url = "https://files.pythonhosted.org/packages/8d/38/d5f978bd5091019e89aef29b9a831f5cd70f2598963a3ead8b9570cab592/transformers-5.10.2.tar.gz", hash = "sha256:f9a44b9c8ca9ab1156b467f574d832ea066284299c2fd0ed84641ccb592751fc", size = 8799687, upload-time = "2026-06-04T18:43:49.119Z" }
1141
+ wheels = [
1142
+ { url = "https://files.pythonhosted.org/packages/73/6f/e1564b0cc182afa05e219a8e09a8e770ffaab879b6b824b56c819bd221da/transformers-5.10.2-py3-none-any.whl", hash = "sha256:8a669db546f82c7c3618cb46ceb0f0afd89292bc70f319c058f8332ec63e268d", size = 11003830, upload-time = "2026-06-04T18:43:45.303Z" },
1143
+ ]
1144
+
1145
+ [[package]]
1146
+ name = "triton"
1147
+ version = "3.7.0"
1148
+ source = { registry = "https://pypi.org/simple" }
1149
+ wheels = [
1150
+ { url = "https://files.pythonhosted.org/packages/b8/c1/5d842314bb6c78442cc60437928781701c6050b8d479bc2a1aed691d37ca/triton-3.7.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a9e71fc392675fac364e0ecf4ef3f76f85b7f5433a16f4c3c5fe5f05a52c85fe", size = 188480277, upload-time = "2026-05-07T19:05:03.231Z" },
1151
+ { url = "https://files.pythonhosted.org/packages/13/31/8315ea5f8dd18e60970b3022e3a8b93fd37e0b784fbbef86e10c8e6e5ca1/triton-3.7.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22bacffce443f54593dd20f05294d5a40622e0ea9ab632816f87154504356221", size = 201415942, upload-time = "2026-05-07T18:46:06.479Z" },
1152
+ ]
1153
+
1154
  [[package]]
1155
  name = "typer"
1156
  version = "0.25.1"