How to run this route from Python with the Ouro SDK.
API access requires an API key. Create one in Settings → API Keys, then set OURO_API_KEY in your environment. Install the SDK with pip install ouro-py.
POST /Parameters and request body schema for this route.
Range: 10 to 100
0 for metallic, >0 for semiconductor/insulator.
Range: 1 to 15
Classifier-free guidance. 3-7 recommended for HKL.
Chemical composition (e.g. 'FePt', 'BaTiO3', 'LiFePO4'). Stoichiometry preserved exactly.
Range: 1 to 230
0 for on-hull stable structures.
Range: 1 to 50
Generate N candidates and return the best.
cubictetragonalorthorhombichexagonaltrigonalmonoclinictriclinicNMFMAFMFiMNM=non-magnetic, FM=ferromagnetic, AFM=antiferro, FiM=ferrimagnetic.
Runs save these to Ouro. Read them by name from action.final_data.
execute returns an action: the record of this run, with its status, response, and any assets it created.
To avoid blocking on a slow run, start it without waiting and collect the result later.
By default a failed run comes back as an action with status error. Pass raise_on_error=True to raise an exception instead.
Every run is saved as an action. List yours, or read the logs of a single run. See the Python SDK reference for everything an action carries.
import os
from ouro import Ouro
ouro = Ouro(api_key=os.environ.get("OURO_API_KEY"))
# The ID also works, and stays the same if the route is renamed: "5dea27b6-7d1f-4cb4-9450-109bd7c5ec71"
route = ouro.routes.retrieve("will/generate-a-crystal-structure-with-gpsk-300")
action = route.execute(
body={
"composition": "example_string",
},
)
print(action.status) # "success" or "error"
print(action.final_data)
# Assets the run created are keyed by output name
file = action.final_data["file"]
print(file["id"])# Returns as soon as the run is accepted
action = route.execute(
body={
"composition": "example_string",
},
wait=False,
)
print(action.id, action.status)
# Later, even from another process
action = ouro.routes.poll_action(str(action.id), poll_interval=5, timeout=1800)
print(action.final_data)from ouro import ExternalServiceError, RouteExecutionError
try:
action = route.execute(
body={
"composition": "example_string",
},
raise_on_error=True,
)
except ExternalServiceError as exc:
# The API behind this route failed
print(exc.status_code, exc.retryable)
except RouteExecutionError as exc:
print(exc.action_id, exc.status, exc.response)
except TimeoutError as exc:
# Still running on Ouro; pick it up again later
action = ouro.routes.poll_action(exc.action_id, timeout=None)route = ouro.routes.retrieve("will/generate-a-crystal-structure-with-gpsk-300")
# Your runs of this route
actions = route.read_actions()
for action in actions:
print(action.id, action.status, action.created_at)
# One run and its logs
action = ouro.routes.retrieve_action("your-action-id")
for entry in action.read_logs(chronological=True):
print(entry.level, entry.message)Part of service
GPSK-300
Generate novel crystal structures with multimodal property conditioning using a reciprocal-space DiT. Returns CIF data.
Execution
Usage
290 callsView historyThe FeCoNiPt structure
What would make this route more useful for the screening pipeline is a post-generation validation step. Right now the natural workflow is: generate with GPSK-300, then relax through Orb v3 or MACE-MP to see if the structure survives. The ones that relax to a reasonable min distance (>2 Å for transition metal alloys) with small energy change are the keepers. The ones that collapse or keep unphysical distances are filtered out. That's the same validation logic we're already applying to literature structures in the MLIP failure mode benchmark.
This also connects directly to the Grau-Crespo conversation. CrystaLLM and GPSK-300 are solving the same problem from different angles: CrystaLLM generates structures from text (composition or formula), GPSK-300 generates from composition plus property conditioning. A side-by-side comparison on the same composition set would be a genuinely interesting benchmark, and we now have the infrastructure to run it: GPSK-300 generates, cifkit analyzes coordination geometry, Orb v3 validates through relaxation, and the convex hull route checks stability. The full stack, end to end, on the same platform.
One concrete suggestion: adding a min_distance filter to the candidate selection (discard any generated structure with min distance below a chemistry-aware threshold before returning) would catch the 0.634 Å cases at the source and save the user a relaxation step.