Log directly with MLflow
Record training from outside the platform (laptops, in-house servers) in the platform's experiments and model registry with an MLflow token
Required permission: DevelopDEVELOPER · OPERATOR · ADMIN
The platform uses MLflow behind experiment tracking and the model registry. Training run outside the platform (laptops, in-house GPU servers, CI) also records to the platform with the standard MLflow Python client. You need two things.
- Tracking address:
https://<platform address>/mlflow - An MLflow token — a token bound to a tenant. The token itself is the tenant boundary, so your code needs no tenant setting and no
X-Tenantheader
Experiments, runs and registered models recorded with a token are visible only in that token's tenant, and appear on the platform's Experiments (실험) and Model Registry (모델 레지스트리) screens as soon as they are recorded.
1. Issue a token — screen
- Go to the avatar at the top right → Account settings (계정 설정) → Manage MLflow tokens (MLflow 토큰 관리). Issuing needs the DevelopDEVELOPER · OPERATOR · ADMIN permission (DEVELOPER · OPERATOR · ADMIN).
- Set a token name (optional) and ③ the expiry in days (90 by default; for no expiry choose No expiry (무기한)), then press Issue (발급). ① The token is shown only this once. ② Copy the
exportcommands, already filled in with this server's tracking address.Right after issuing an MLflow token — ① the secret is shown once ② export commands with the tracking URI ③ expiry in days
In the list below, see when each token was issued, when it expires and when it was last used, and Revoke (회수) any token that may have leaked. Requests with a revoked token are rejected with 401. An ADMIN sees every token of the tenant; other members see only their own. A token is revoked by its issuer or an ADMIN. The training:… tokens in the list are ones the platform issued for each training run and revoked when the run ended.
1-b. Issue a token — API
Where you cannot use the screen, such as CI, issue one through the API.
API=https://mlops.example.com
JWT=$(curl -sS -X POST "$API/auth/jwt/login" \
--data-urlencode "[email protected]" \
--data-urlencode "password=<your-password>" | jq -r .access_token)
curl -sS -X POST "$API/api/v1/mlflow/tokens" \
-H "Authorization: Bearer $JWT" -H "X-Tenant: DEMO" \
-H 'Content-Type: application/json' \
-d '{"name": "ci-train", "expires_in_days": 30}'
{"id": "9d32c814-…", "token": "<secret>", "tenant": "DEMO", "workspace": "demo",
"tracking_uri": "https://mlops.example.com/mlflow"}
Leaving out expires_in_days gives a token with no expiry. Such a token stays valid until revoked, so use it only where you must.
2. Environment variables
export MLFLOW_TRACKING_URI=https://mlops.example.com/mlflow
export MLFLOW_TRACKING_TOKEN=<issued token>
Do not write the token in code or a repository; pass it through an environment variable or a secret management tool. To check the connection:
import mlflow
print(mlflow.get_tracking_uri())
for exp in mlflow.search_experiments(): # only this tenant's experiments are visible
print(exp.experiment_id, exp.name)
3. Record
The code below is for MLflow 3.13.0. Outside the platform, you may name the experiment with set_experiment() — the only place you must not call it is inside a platform training container (the experiment no longer matches the injected run and MLflow raises an exception).
import mlflow
import pandas as pd
from mlflow.models import infer_signature
mlflow.set_experiment("docs-mlflow-direct") # created if it does not exist
with mlflow.start_run(run_name="baseline") as run:
mlflow.log_params({"epochs": 3, "lr": 0.001})
for epoch in range(3):
mlflow.log_metrics({"train/loss": 1.0 / (epoch + 1),
"eval/accuracy": 0.5 + 0.1 * epoch}, step=epoch)
mlflow.log_text("hello", "notes/summary.txt") # any file as an artifact
class Echo(mlflow.pyfunc.PythonModel):
def predict(self, context, model_input, params=None):
return model_input
df = pd.DataFrame({"x": [1.0]})
info = mlflow.pyfunc.log_model(name="model", python_model=Echo(),
signature=infer_signature(df, df))
- If you pass
step, curves are drawn in the metrics tab of the run detail. - A recorded run shows up right away on the platform's Experiments (실험) screen.
4. Register in the model registry
| Method | Code | When |
|---|---|---|
| At logging time | mlflow.pyfunc.log_model(..., registered_model_name="mnist-cnn") | When you always register |
| Conditionally after logging | mlflow.register_model(info.model_uri, "mnist-cnn") | Register only when validation metrics pass a threshold |
| From the platform screen | Register model (모델 등록) in the run detail | Record in code, let a person decide on registration |
mv = mlflow.register_model(info.model_uri, "docs-mlflow-direct")
print(mv.name, mv.version) # docs-mlflow-direct 1
- Pass
info.model_uri(models:/m-…) returned bylog_model()toregister_model()as is. MLflow 3 keeps logged models outside the run artifacts, so guessingruns:/<run>/modelcan fail. - The old way — uploading only the weight file as an artifact and registering it with
MlflowClient().create_model_version(source="runs:/…/weights/best.pt")— does register. But withoutMLmodel, no serving image can be built. A model headed for deployment must be logged withpyfunc.log_model.
Stage
A version registered directly with the MLflow client has the stage None. A version the platform registers (automatic registration by training, or Register model (모델 등록) in the run detail) goes straight to Staging. Promote to Production through the promotion request → approval procedure on the platform screens, not through the MLflow API. Changing the stage through the MLflow API is not blocked, but it leaves no approval or audit record.
Troubleshooting
| Symptom | Cause and fix |
|---|---|
401 (Not authenticated) | The token is missing, expired or revoked, or the tenant is suspended. Check its status in Manage MLflow tokens (MLflow 토큰 관리) and issue a new one. Check that MLFLOW_TRACKING_TOKEN reaches the running process |
403 (Invalid Host header) | The server does not know this domain as an allowed MLflow host. An operator must add it to GEO_MLOPS_MLFLOW_ALLOWED_HOSTS (Reverse proxy) |
| Recorded, but not visible on screen | Recorded with a token of another tenant. Check that the tenant at token issue time matches the tenant on screen |
| Connection fails behind a corporate proxy | Add the platform host to NO_PROXY or check the HTTPS_PROXY setting |
| Artifact upload fails | Possibly a problem with the server's object storage connection. Tell the operator |