synth-ai 0.2.6.dev3__py3-none-any.whl → 0.2.6.dev5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of synth-ai might be problematic. Click here for more details.
- synth_ai/__init__.py +1 -1
- synth_ai/demos/core/cli.py +108 -141
- {synth_ai-0.2.6.dev3.dist-info → synth_ai-0.2.6.dev5.dist-info}/METADATA +1 -1
- {synth_ai-0.2.6.dev3.dist-info → synth_ai-0.2.6.dev5.dist-info}/RECORD +8 -8
- {synth_ai-0.2.6.dev3.dist-info → synth_ai-0.2.6.dev5.dist-info}/WHEEL +0 -0
- {synth_ai-0.2.6.dev3.dist-info → synth_ai-0.2.6.dev5.dist-info}/entry_points.txt +0 -0
- {synth_ai-0.2.6.dev3.dist-info → synth_ai-0.2.6.dev5.dist-info}/licenses/LICENSE +0 -0
- {synth_ai-0.2.6.dev3.dist-info → synth_ai-0.2.6.dev5.dist-info}/top_level.txt +0 -0
synth_ai/__init__.py
CHANGED
|
@@ -25,7 +25,7 @@ tracing = None # type: ignore
|
|
|
25
25
|
EventPartitionElement = RewardSignal = SystemTrace = TrainingQuestion = None # type: ignore
|
|
26
26
|
trace_event_async = trace_event_sync = upload = None # type: ignore
|
|
27
27
|
|
|
28
|
-
__version__ = "0.2.6.
|
|
28
|
+
__version__ = "0.2.6.dev4"
|
|
29
29
|
__all__ = [
|
|
30
30
|
"LM",
|
|
31
31
|
"OpenAI",
|
synth_ai/demos/core/cli.py
CHANGED
|
@@ -224,8 +224,59 @@ def _popen_stream_capture(cmd: list[str], cwd: str | None = None, env: dict | No
|
|
|
224
224
|
return int(proc.returncode or 0), "\n".join(buf_lines)
|
|
225
225
|
|
|
226
226
|
|
|
227
|
+
def _mask_secret_args(args: list[str]) -> list[str]:
|
|
228
|
+
masked: list[str] = []
|
|
229
|
+
for a in args:
|
|
230
|
+
if "=" in a and any(a.startswith(prefix) for prefix in ("ENVIRONMENT_API_KEY=", "OPENAI_API_KEY=", "SYNTH_API_KEY=")):
|
|
231
|
+
try:
|
|
232
|
+
key, value = a.split("=", 1)
|
|
233
|
+
tail = value[-5:] if len(value) >= 5 else value
|
|
234
|
+
masked.append(f"{key}=***{tail}")
|
|
235
|
+
except Exception:
|
|
236
|
+
masked.append("<masked>")
|
|
237
|
+
else:
|
|
238
|
+
masked.append(a)
|
|
239
|
+
return masked
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def _ensure_modal_secret(
|
|
243
|
+
secret_name: str,
|
|
244
|
+
*,
|
|
245
|
+
values: dict[str, str],
|
|
246
|
+
label: str = "deploy",
|
|
247
|
+
replace: bool = False,
|
|
248
|
+
) -> bool:
|
|
249
|
+
prefix = f"[{label}]"
|
|
250
|
+
if not secret_name.strip():
|
|
251
|
+
raise RuntimeError("Secret name is required")
|
|
252
|
+
|
|
253
|
+
if not values:
|
|
254
|
+
raise RuntimeError("No values provided to create Modal secret")
|
|
255
|
+
|
|
256
|
+
create_args = [f"{k}={v}" for k, v in values.items()]
|
|
257
|
+
create_cmd = ["uv", "run", "modal", "secret", "create", secret_name, *create_args]
|
|
258
|
+
|
|
259
|
+
if replace:
|
|
260
|
+
print(f"{prefix} Removing Modal secret '{secret_name}' (if present)…")
|
|
261
|
+
delete_cmd = ["bash", "-lc", f"printf 'y\\n' | uv run modal secret delete {secret_name}"]
|
|
262
|
+
print(f"{prefix} Command:", " ".join(delete_cmd))
|
|
263
|
+
delete_code = _popen_stream(delete_cmd)
|
|
264
|
+
if delete_code != 0:
|
|
265
|
+
print(f"{prefix} Warning: delete command exited with {delete_code}; continuing to create")
|
|
266
|
+
|
|
267
|
+
print(f"\n{prefix} Creating Modal secret '{secret_name}'…")
|
|
268
|
+
print(f"{prefix} Command:", " ".join(_mask_secret_args(create_cmd)))
|
|
269
|
+
code = _popen_stream(create_cmd)
|
|
270
|
+
if code != 0:
|
|
271
|
+
raise RuntimeError("Failed to provision Modal secret (see logs above)")
|
|
272
|
+
|
|
273
|
+
return True
|
|
274
|
+
|
|
275
|
+
|
|
227
276
|
def cmd_deploy(args: argparse.Namespace) -> int:
|
|
228
277
|
env = demo_core.load_env()
|
|
278
|
+
cwd_env_path = os.path.join(os.getcwd(), ".env")
|
|
279
|
+
local_env = demo_core.load_dotenv_file(cwd_env_path)
|
|
229
280
|
url = ""
|
|
230
281
|
app_name = env.task_app_name or ""
|
|
231
282
|
try:
|
|
@@ -279,6 +330,51 @@ def cmd_deploy(args: argparse.Namespace) -> int:
|
|
|
279
330
|
if not proceed:
|
|
280
331
|
print("Aborted by user.")
|
|
281
332
|
return 1
|
|
333
|
+
|
|
334
|
+
secret_name = (env.task_app_secret_name or "").strip() or f"{name_in}-secret"
|
|
335
|
+
env_key = (env.env_api_key or "").strip() or None
|
|
336
|
+
if env_key is None:
|
|
337
|
+
from synth_ai.rl.secrets import mint_environment_api_key
|
|
338
|
+
|
|
339
|
+
env_key = mint_environment_api_key()
|
|
340
|
+
demo_core.persist_env_api_key(env_key)
|
|
341
|
+
demo_core.persist_dotenv_values({"ENVIRONMENT_API_KEY": env_key})
|
|
342
|
+
os.environ["ENVIRONMENT_API_KEY"] = env_key
|
|
343
|
+
env.env_api_key = env_key
|
|
344
|
+
local_env["ENVIRONMENT_API_KEY"] = env_key
|
|
345
|
+
print("[deploy] Minted new ENVIRONMENT_API_KEY")
|
|
346
|
+
|
|
347
|
+
synth_key = (env.synth_api_key or os.environ.get("SYNTH_API_KEY") or local_env.get("SYNTH_API_KEY") or "").strip()
|
|
348
|
+
if not synth_key:
|
|
349
|
+
synth_key = input("Enter SYNTH_API_KEY for Modal secret (required): ").strip()
|
|
350
|
+
if not synth_key:
|
|
351
|
+
print("SYNTH_API_KEY is required to create the Modal secret.")
|
|
352
|
+
return 1
|
|
353
|
+
demo_core.persist_api_key(synth_key)
|
|
354
|
+
demo_core.persist_dotenv_values({"SYNTH_API_KEY": synth_key})
|
|
355
|
+
env.synth_api_key = synth_key
|
|
356
|
+
|
|
357
|
+
openai_key = (os.environ.get("OPENAI_API_KEY") or local_env.get("OPENAI_API_KEY") or "").strip()
|
|
358
|
+
if not openai_key:
|
|
359
|
+
openai_key = input("Enter OPENAI_API_KEY for Modal secret (required): ").strip()
|
|
360
|
+
if not openai_key:
|
|
361
|
+
print("OPENAI_API_KEY is required to create the Modal secret.")
|
|
362
|
+
return 1
|
|
363
|
+
demo_core.persist_dotenv_values({"OPENAI_API_KEY": openai_key})
|
|
364
|
+
local_env["OPENAI_API_KEY"] = openai_key
|
|
365
|
+
|
|
366
|
+
values = {"SYNTH_API_KEY": synth_key, "OPENAI_API_KEY": openai_key}
|
|
367
|
+
if env_key:
|
|
368
|
+
values["ENVIRONMENT_API_KEY"] = env_key
|
|
369
|
+
|
|
370
|
+
try:
|
|
371
|
+
created = _ensure_modal_secret(secret_name, values=values, label="deploy", replace=True)
|
|
372
|
+
except RuntimeError as secret_err:
|
|
373
|
+
print(f"Failed to prepare Modal secret '{secret_name}': {secret_err}")
|
|
374
|
+
return 2
|
|
375
|
+
if created:
|
|
376
|
+
print(f"[deploy] Modal secret '{secret_name}' provisioned.")
|
|
377
|
+
|
|
282
378
|
deploy_cmd = ["uv", "run", "python", "-m", "modal", "deploy", "--name", name_in, app_path]
|
|
283
379
|
print("\nStreaming Modal build/deploy logs (this can take several minutes on first run)…\n")
|
|
284
380
|
code, deploy_logs = _popen_stream_capture(deploy_cmd)
|
|
@@ -346,8 +442,6 @@ def cmd_deploy(args: argparse.Namespace) -> int:
|
|
|
346
442
|
|
|
347
443
|
|
|
348
444
|
def cmd_configure(args: argparse.Namespace) -> int:
|
|
349
|
-
from synth_ai.rl.secrets import mint_environment_api_key
|
|
350
|
-
|
|
351
445
|
env = demo_core.load_env()
|
|
352
446
|
cwd_env_path = os.path.join(os.getcwd(), ".env")
|
|
353
447
|
local_env = demo_core.load_dotenv_file(cwd_env_path)
|
|
@@ -362,13 +456,9 @@ def cmd_configure(args: argparse.Namespace) -> int:
|
|
|
362
456
|
demo_core.persist_dotenv_values({"SYNTH_API_KEY": synth_key})
|
|
363
457
|
|
|
364
458
|
env_key = env.env_api_key.strip()
|
|
365
|
-
minted_env_key = False
|
|
366
459
|
if not env_key:
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
print("Minted new ENVIRONMENT_API_KEY")
|
|
370
|
-
demo_core.persist_env_api_key(env_key)
|
|
371
|
-
demo_core.persist_dotenv_values({"ENVIRONMENT_API_KEY": env_key})
|
|
460
|
+
print("ENVIRONMENT_API_KEY missing; run `uvx synth-ai rl_demo deploy` to mint and store one.")
|
|
461
|
+
return 1
|
|
372
462
|
|
|
373
463
|
task_url = env.task_app_base_url
|
|
374
464
|
if not task_url or not _is_modal_public_url(task_url):
|
|
@@ -418,43 +508,20 @@ def cmd_configure(args: argparse.Namespace) -> int:
|
|
|
418
508
|
})
|
|
419
509
|
|
|
420
510
|
# Ensure Modal secret has the environment API key (and optional extras).
|
|
421
|
-
secret_args = [f"ENVIRONMENT_API_KEY={env_key}"]
|
|
422
511
|
openai_key = (os.environ.get("OPENAI_API_KEY") or local_env.get("OPENAI_API_KEY") or "").strip()
|
|
423
|
-
if openai_key:
|
|
424
|
-
secret_args.append(f"OPENAI_API_KEY={openai_key}")
|
|
425
512
|
synth_for_secret = synth_key
|
|
426
|
-
if synth_for_secret:
|
|
427
|
-
secret_args.append(f"SYNTH_API_KEY={synth_for_secret}")
|
|
428
513
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
try:
|
|
435
|
-
k, v = a.split("=", 1)
|
|
436
|
-
suf = v[-5:] if len(v) >= 5 else ""
|
|
437
|
-
masked.append(f"{k}=***{suf}")
|
|
438
|
-
except Exception:
|
|
439
|
-
masked.append("<masked>")
|
|
440
|
-
else:
|
|
441
|
-
masked.append(a)
|
|
442
|
-
return masked
|
|
514
|
+
secret_values: dict[str, str] = {"ENVIRONMENT_API_KEY": env_key}
|
|
515
|
+
if openai_key:
|
|
516
|
+
secret_values["OPENAI_API_KEY"] = openai_key
|
|
517
|
+
if synth_for_secret:
|
|
518
|
+
secret_values["SYNTH_API_KEY"] = synth_for_secret
|
|
443
519
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
delete_cmd = ["bash", "-lc", f"printf 'y\\n' | uv run modal secret delete {secret_name}"]
|
|
450
|
-
print("[configure] Command:", " ".join(delete_cmd))
|
|
451
|
-
_popen_stream(delete_cmd)
|
|
452
|
-
print("[configure] Retrying secret create…")
|
|
453
|
-
print("[configure] Command:", " ".join(_mask_args(create_cmd)))
|
|
454
|
-
code = _popen_stream(create_cmd)
|
|
455
|
-
if code != 0:
|
|
456
|
-
print("[configure] Failed to provision Modal secret.")
|
|
457
|
-
return 2
|
|
520
|
+
try:
|
|
521
|
+
_ensure_modal_secret(secret_name, values=secret_values, label="configure", replace=True)
|
|
522
|
+
except RuntimeError as err:
|
|
523
|
+
print(f"[configure] Failed to provision Modal secret: {err}")
|
|
524
|
+
return 2
|
|
458
525
|
|
|
459
526
|
# Verify task app can read the secret by hitting rollout health with X-API-Key.
|
|
460
527
|
rollout_url = task_url.rstrip("/") + "/health/rollout"
|
|
@@ -557,8 +624,6 @@ def cmd_configure(args: argparse.Namespace) -> int:
|
|
|
557
624
|
"TASK_APP_NAME": app_name,
|
|
558
625
|
"TASK_APP_SECRET_NAME": secret_name,
|
|
559
626
|
}, indent=2))
|
|
560
|
-
if minted_env_key:
|
|
561
|
-
print(f"Stored minted ENVIRONMENT_API_KEY in {cwd_env_path}")
|
|
562
627
|
print("Next: uvx synth-ai rl_demo run")
|
|
563
628
|
return 0
|
|
564
629
|
|
|
@@ -938,96 +1003,6 @@ def cmd_run(args: argparse.Namespace) -> int:
|
|
|
938
1003
|
return 0
|
|
939
1004
|
|
|
940
1005
|
|
|
941
|
-
def cmd_eval(args: argparse.Namespace) -> int:
|
|
942
|
-
env = demo_core.load_env()
|
|
943
|
-
# Ensure required env
|
|
944
|
-
if not env.task_app_base_url:
|
|
945
|
-
print("Task app URL missing. Run: uvx synth-ai rl_demo deploy")
|
|
946
|
-
return 1
|
|
947
|
-
# Load config: prefer CWD demo_config.toml; else packaged default
|
|
948
|
-
cfg_path: str | None = None
|
|
949
|
-
if getattr(args, "config", None):
|
|
950
|
-
p = os.path.abspath(args.config)
|
|
951
|
-
if not os.path.isfile(p):
|
|
952
|
-
print(f"Config not found: {p}")
|
|
953
|
-
return 1
|
|
954
|
-
cfg_path = p
|
|
955
|
-
else:
|
|
956
|
-
cwd_prepared = os.path.abspath(os.path.join(os.getcwd(), "demo_config.toml"))
|
|
957
|
-
if os.path.isfile(cwd_prepared):
|
|
958
|
-
cfg_path = cwd_prepared
|
|
959
|
-
else:
|
|
960
|
-
packaged = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "demo_task_apps", "math", "config.toml"))
|
|
961
|
-
cfg_path = packaged if os.path.isfile(packaged) else None
|
|
962
|
-
if not cfg_path:
|
|
963
|
-
print("No config TOML found.")
|
|
964
|
-
return 1
|
|
965
|
-
|
|
966
|
-
import tomllib
|
|
967
|
-
with open(cfg_path, "rb") as fh:
|
|
968
|
-
inline_cfg = tomllib.load(fh)
|
|
969
|
-
|
|
970
|
-
# Model selection prompt
|
|
971
|
-
default_model = (args.model or (inline_cfg.get("model", {}) or {}).get("name") or "Qwen/Qwen3-0.6B")
|
|
972
|
-
entered = input(f"Model to evaluate [{default_model}]: ").strip()
|
|
973
|
-
model = entered or default_model
|
|
974
|
-
confirm = (input(f"Use model '{model}'? [Y/n]: ").strip().lower() or "y").startswith("y")
|
|
975
|
-
if not confirm:
|
|
976
|
-
print("Aborted by user.")
|
|
977
|
-
return 1
|
|
978
|
-
|
|
979
|
-
# Build on-board rollout request to the Task App (no backend RL job)
|
|
980
|
-
# Use Synth backend chat-completions proxy as inference URL (derive from DEV_BACKEND_URL)
|
|
981
|
-
# Ensure /api suffix for backend, then use proxy prefix for chat completions
|
|
982
|
-
backend_api = (env.dev_backend_url or "https://agent-learning.onrender.com/api").rstrip("/")
|
|
983
|
-
if not backend_api.endswith("/api"):
|
|
984
|
-
backend_api = f"{backend_api}/api"
|
|
985
|
-
inference_url = f"{backend_api}/proxy"
|
|
986
|
-
# ops: alternate agent/env for a small number of decisions (from config max_steps_per_episode if present)
|
|
987
|
-
try:
|
|
988
|
-
steps = int((inline_cfg.get("rollout", {}) or {}).get("max_steps_per_episode", 4))
|
|
989
|
-
except Exception:
|
|
990
|
-
steps = 4
|
|
991
|
-
ops: list[str] = []
|
|
992
|
-
for _ in range(max(1, steps // 2)):
|
|
993
|
-
ops.extend(["agent", "env"])
|
|
994
|
-
env_name = (inline_cfg.get("rollout", {}) or {}).get("env_name") or "math"
|
|
995
|
-
policy_name = (inline_cfg.get("rollout", {}) or {}).get("policy_name") or "math-react"
|
|
996
|
-
run_id = f"eval-{int(time.time())}"
|
|
997
|
-
body: Dict[str, Any] = {
|
|
998
|
-
"run_id": run_id,
|
|
999
|
-
"env": {
|
|
1000
|
-
"env_name": env_name,
|
|
1001
|
-
"config": inline_cfg.get("rollout", {}) or {},
|
|
1002
|
-
},
|
|
1003
|
-
"policy": {
|
|
1004
|
-
"policy_name": policy_name,
|
|
1005
|
-
"config": {"model": model, "inference_url": inference_url},
|
|
1006
|
-
},
|
|
1007
|
-
"ops": ops,
|
|
1008
|
-
"on_done": "terminate",
|
|
1009
|
-
}
|
|
1010
|
-
# POST to task app rollout endpoint
|
|
1011
|
-
headers = {"Content-Type": "application/json"}
|
|
1012
|
-
if env.env_api_key:
|
|
1013
|
-
headers["X-API-Key"] = env.env_api_key
|
|
1014
|
-
rc, resp = _http("POST", env.task_app_base_url.rstrip("/") + "/rollout", headers=headers, body=body)
|
|
1015
|
-
if rc not in (200, 201) or not isinstance(resp, dict):
|
|
1016
|
-
print("Eval rollout failed:", rc)
|
|
1017
|
-
try:
|
|
1018
|
-
print(json.dumps(resp, indent=2) if isinstance(resp, dict) else str(resp))
|
|
1019
|
-
except Exception:
|
|
1020
|
-
print(str(resp))
|
|
1021
|
-
print("Request body was:\n" + json.dumps(body, indent=2))
|
|
1022
|
-
return 2
|
|
1023
|
-
metrics = (resp.get("metrics") if isinstance(resp, dict) else None) or {}
|
|
1024
|
-
mean = metrics.get("mean_return")
|
|
1025
|
-
if mean is not None:
|
|
1026
|
-
print(f"eval.reward_mean={mean}")
|
|
1027
|
-
else:
|
|
1028
|
-
print(json.dumps(resp, indent=2))
|
|
1029
|
-
return 0
|
|
1030
|
-
|
|
1031
1006
|
def main(argv: list[str] | None = None) -> int:
|
|
1032
1007
|
p = argparse.ArgumentParser(prog="synth-ai")
|
|
1033
1008
|
sub = p.add_subparsers(dest="cmd")
|
|
@@ -1069,14 +1044,6 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
1069
1044
|
|
|
1070
1045
|
_add_parser(["rl_demo.run", "demo.run"], configure=_run_opts)
|
|
1071
1046
|
|
|
1072
|
-
def _eval_opts(parser):
|
|
1073
|
-
parser.add_argument("--config", type=str, default=None, help="Path to TOML config (optional)")
|
|
1074
|
-
parser.add_argument("--model", type=str, default=None, help="Model to evaluate (default Qwen/Qwen3-0.6B)")
|
|
1075
|
-
parser.add_argument("--timeout", type=int, default=300, help="Seconds to wait for metrics")
|
|
1076
|
-
parser.set_defaults(func=cmd_eval)
|
|
1077
|
-
|
|
1078
|
-
_add_parser(["rl_demo.eval", "demo.eval"], configure=_eval_opts)
|
|
1079
|
-
|
|
1080
1047
|
args = p.parse_args(argv)
|
|
1081
1048
|
if not hasattr(args, "func"):
|
|
1082
1049
|
p.print_help()
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
synth_ai/__init__.py,sha256=
|
|
1
|
+
synth_ai/__init__.py,sha256=NixuXddy4lS2Wmj0F8eMt0HS_oYCTnq3iVVq5VYwWIc,1341
|
|
2
2
|
synth_ai/__main__.py,sha256=Kh1xBKkTE5Vs2qNMtDuuOXerHUptMcOiF3YziOpC6DA,146
|
|
3
3
|
synth_ai/http.py,sha256=lqjFXDmAP_xgfywK_rDSOVxuMy4rDH9S3Rtu9k1tLmk,1028
|
|
4
4
|
synth_ai/http_client.py,sha256=_9J8rUGoItUMnJLGZw7r0uXiJeLWR939kByRkvtP1XM,4429
|
|
@@ -20,7 +20,7 @@ synth_ai/config/base_url.py,sha256=Bk7Bd9jKJP-LF0SW--WE01JhMfvOB6NUkFMRgPMnJuQ,3
|
|
|
20
20
|
synth_ai/core/experiment.py,sha256=hLkPtzUFA7iY3-QpeJ5K8YjvQeyfqnjab5P2CFaojys,236
|
|
21
21
|
synth_ai/core/system.py,sha256=s-Z7np2ISYmYc1r9YN-y2yb3cgRlOalrh0iaqnxeo84,206
|
|
22
22
|
synth_ai/demos/core/__init__.py,sha256=A2FjhY7KXGtyzdQXqeTPCkEhHfrH-eQg6bvP8HaYhZM,36
|
|
23
|
-
synth_ai/demos/core/cli.py,sha256=
|
|
23
|
+
synth_ai/demos/core/cli.py,sha256=MuJELXFRxtyucek9b05Oo54pmJs5QGo45SV3hDZTFO0,44729
|
|
24
24
|
synth_ai/demos/demo_task_apps/__init__.py,sha256=8aUGEGpWUw11GRb3wQXRAmQ99yjAt5qd5FCTDJpXWjI,44
|
|
25
25
|
synth_ai/demos/demo_task_apps/core.py,sha256=3-C2dGdaqVqrVjnsxU2n6kGcuaprwuszBcTHePBypwo,13580
|
|
26
26
|
synth_ai/demos/demo_task_apps/math/__init__.py,sha256=WBzpZwSn7pRarBmhopQi34i9bEm05-71eM3siboOavY,43
|
|
@@ -411,9 +411,9 @@ synth_ai/v0/tracing_v1/events/manage.py,sha256=ZDXXP-ZwLH9LCsmw7Ru9o55d7bl_diPtJ
|
|
|
411
411
|
synth_ai/v0/tracing_v1/events/scope.py,sha256=BuBkhSpVHUJt8iGT9HJZF82rbb88mQcd2vM2shg-w2I,2550
|
|
412
412
|
synth_ai/v0/tracing_v1/events/store.py,sha256=0342lvAcalyJbVEIzQFaPuMQGgwiFm7M5rE6gr-G0E8,9041
|
|
413
413
|
synth_ai/zyk/__init__.py,sha256=htVLnzTYQ5rxzYpzSYBm7_o6uNKZ3pB_PrqkBrgTRS4,771
|
|
414
|
-
synth_ai-0.2.6.
|
|
415
|
-
synth_ai-0.2.6.
|
|
416
|
-
synth_ai-0.2.6.
|
|
417
|
-
synth_ai-0.2.6.
|
|
418
|
-
synth_ai-0.2.6.
|
|
419
|
-
synth_ai-0.2.6.
|
|
414
|
+
synth_ai-0.2.6.dev5.dist-info/licenses/LICENSE,sha256=ynhjRQUfqA_RdGRATApfFA_fBAy9cno04sLtLUqxVFM,1069
|
|
415
|
+
synth_ai-0.2.6.dev5.dist-info/METADATA,sha256=zOL3OaxOqOJIBabHtKPJqdEvEoAEYalzrOFHTxHu3N8,3980
|
|
416
|
+
synth_ai-0.2.6.dev5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
417
|
+
synth_ai-0.2.6.dev5.dist-info/entry_points.txt,sha256=Neq-3bT7TAijjgOIR77pKL-WYg6TWBDeO8pp_nL4vGY,91
|
|
418
|
+
synth_ai-0.2.6.dev5.dist-info/top_level.txt,sha256=fBmtZyVHuKaGa29oHBaaUkrUIWTqSpoVMPiVdCDP3k8,9
|
|
419
|
+
synth_ai-0.2.6.dev5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|