File size: 6,748 Bytes
dfb775d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | """External-API clients — register with mindx.pythai.net + list on AgenticPlace.
Real httpx POSTs against configurable base URLs (env-overridable).
These endpoints are part of the mindX cognitive ecosystem; if your `*.pythai.net`
endpoints aren't deployed yet, set `MINDXTRAIN_API_BASE_URL` /
`MINDXTRAIN_AGENTICPLACE_URL` to your own service.
"""
from __future__ import annotations
import json
import os
import httpx
from pydantic import BaseModel, ConfigDict, Field
class MindXAgentRegistration(BaseModel):
model_config = ConfigDict(extra="forbid")
run_id: str
hf_url: str
cid: str
capability: str = "chat"
class MindXFallbackSwap(BaseModel):
"""Payload for the mindX runtime fallback-swap endpoint."""
model_config = ConfigDict(extra="forbid")
provider: str = Field(default="vllm", description="LLM provider in mindX (vllm, ollama, ...).")
model: str = Field(..., min_length=1, description="HF Hub repo or provider-local model name.")
class AgenticPlaceListing(BaseModel):
model_config = ConfigDict(extra="forbid")
run_id: str
hf_url: str
title: str = ""
price_usdc_per_million_tokens: float = 1.0
def register_with_mindx(
*,
run_id: str,
hf_url: str,
cid: str,
api_url: str | None = None,
timeout_s: float = 30.0,
) -> dict[str, str]:
"""POST /v1/agents on the mindX cognitive API; return the registration receipt."""
api_url = (api_url or os.environ.get("MINDXTRAIN_API_BASE_URL", "https://mindx.pythai.net")).rstrip("/")
body = MindXAgentRegistration(run_id=run_id, hf_url=hf_url, cid=cid).model_dump()
with httpx.Client(timeout=timeout_s) as client:
resp = client.post(f"{api_url}/v1/agents", json=body)
resp.raise_for_status()
data: dict[str, str] = resp.json()
return data
def swap_mindx_fallback_model(
*,
provider: str = "vllm",
model: str,
api_url: str | None = None,
api_key: str | None = None,
timeout_s: float = 30.0,
) -> dict[str, str]:
"""PATCH /v1/config/fallback-model on mindX; return {previous, current, ...}.
Called by the `publish` step after the trained checkpoint lands on HF Hub
so subsequent LLM handler creations in mindX resolve the new default.
`api_url` defaults to `MINDXTRAIN_API_BASE_URL` env (or `https://mindx.pythai.net`).
`api_key`, if provided or read from `MINDXTRAIN_API_KEY`, is sent as
`Authorization: Bearer <key>` — required when the mindX deployment has
its bearer-auth secret set.
"""
api_url = (api_url or os.environ.get("MINDXTRAIN_API_BASE_URL", "https://mindx.pythai.net")).rstrip("/")
api_key = api_key if api_key is not None else os.environ.get("MINDXTRAIN_API_KEY", "")
body = MindXFallbackSwap(provider=provider, model=model).model_dump()
headers: dict[str, str] = {}
if api_key:
headers["Authorization"] = f"Bearer {api_key}"
with httpx.Client(timeout=timeout_s) as client:
resp = client.patch(f"{api_url}/v1/config/fallback-model", json=body, headers=headers)
resp.raise_for_status()
data: dict[str, str] = resp.json()
return data
def list_on_agenticplace(
*,
run_id: str,
hf_url: str,
title: str = "",
price_usdc_per_million_tokens: float = 1.0,
api_url: str | None = None,
timeout_s: float = 30.0,
) -> str:
"""POST /v1/listings on AgenticPlace; return the listing slug/url."""
api_url = (
api_url
or os.environ.get("MINDXTRAIN_AGENTICPLACE_URL", "https://agenticplace.pythai.net")
).rstrip("/")
body = AgenticPlaceListing(
run_id=run_id,
hf_url=hf_url,
title=title or run_id,
price_usdc_per_million_tokens=price_usdc_per_million_tokens,
).model_dump()
with httpx.Client(timeout=timeout_s) as client:
resp = client.post(f"{api_url}/v1/listings", json=body)
resp.raise_for_status()
data = resp.json()
return str(data.get("listing_url", data))
def trigger_dream_ingestion(
*,
run_id: str,
adapter_dir: str,
base_model: str,
persona_name: str = "",
imprint_delta: float | None = None,
api_url: str | None = None,
timeout_s: float = 10.0,
) -> dict[str, str]:
"""Hand a freshly-imprinted actor to mindX's `machine.dream` 8hr cycle.
Clean-room boundary: we never import or run mindX code — we hand off an
artifact *pointer* (run id + adapter path + base model + imprint delta) so the
mindX dream cycle (`agents/machine_dreaming.py`) can ingest the trained actor
on its next pass. Best-effort, with two delivery modes:
1. HTTP — POST `/v1/dream/ingest` on the mindX API when `MINDXTRAIN_API_BASE_URL`
is set and reachable.
2. Inbox drop — write a pointer JSON into
`$MINDXTRAIN_MINDX_HOME/data/incoming/<run_id>.dream.json` so a filesystem-
watching dream cycle picks it up.
Returns `{"mode": ..., "target": ...}`; never raises — a failed trigger reports
via the return dict rather than failing the training run.
"""
payload = {
"run_id": run_id,
"adapter_dir": adapter_dir,
"base_model": base_model,
"persona": persona_name,
"imprint_delta": "" if imprint_delta is None else f"{imprint_delta:.4f}",
"source": "mindxtrain.imprint",
}
api = (api_url or os.environ.get("MINDXTRAIN_API_BASE_URL", "")).rstrip("/")
if api:
try:
with httpx.Client(timeout=timeout_s) as client:
resp = client.post(f"{api}/v1/dream/ingest", json=payload)
resp.raise_for_status()
return {"mode": "http", "target": f"{api}/v1/dream/ingest"}
except (httpx.HTTPError, OSError) as exc:
payload["http_error"] = str(exc)
# Filesystem inbox fallback — the 8hr dream cycle watches data/incoming.
home = os.environ.get("MINDXTRAIN_MINDX_HOME", "")
if home:
from pathlib import Path
inbox = Path(home).expanduser() / "data" / "incoming"
try:
inbox.mkdir(parents=True, exist_ok=True)
ptr = inbox / f"{run_id}.dream.json"
ptr.write_text(json.dumps(payload, indent=2))
return {"mode": "inbox", "target": str(ptr)}
except OSError as exc:
return {"mode": "failed", "target": str(inbox), "error": str(exc)}
return {
"mode": "skipped",
"target": "",
"note": "set MINDXTRAIN_API_BASE_URL or MINDXTRAIN_MINDX_HOME to deliver",
}
__all__ = [
"AgenticPlaceListing",
"MindXAgentRegistration",
"MindXFallbackSwap",
"list_on_agenticplace",
"register_with_mindx",
"swap_mindx_fallback_model",
"trigger_dream_ingestion",
]
|