Skip to content

Commit 4df6522

Browse files
authored
feat: add mlflow 3 support (#6)
* feat: add MLflow 3.x LoggedModel ID import support MLflow 3.x uses LoggedModel IDs (format: m-<32 hex chars>) in model version source fields instead of the original artifact_path. This causes import failures because the exported artifacts use the original path while the source field references the LoggedModel ID. Changes: - Add _is_logged_model_id() to detect MLflow 3.x LoggedModel IDs - Add _resolve_logged_model_path() to resolve IDs to actual artifact paths using mlflow.log-model.history tag or directory scanning - Update _extract_model_path() in both import modules to handle LoggedModel IDs and pass input_dir for resolution - Fix bug in import_model.py where "artifacts" pattern incorrectly matched "mlflow-artifacts:" URL scheme (changed to "/artifacts/") * fix: formatting for the unit testing script * fix: black formatting for prompts changes not related to the changes made in this PR * fix: fixed pre-commit issues
1 parent a9f57e7 commit 4df6522

File tree

13 files changed

+1170
-374
lines changed

13 files changed

+1170
-374
lines changed

docs/bulk.md

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -388,26 +388,26 @@ cat experiment-names.csv
388388
/Users/me@mycompany.com,/Users/you@mycompany.com
389389
/Users/foo@mycompany.com,/Users/bar@mycompany.com
390390
```
391-
391+
392392
## Prompts
393-
393+
394394
Export/import prompts from the MLflow Prompt Registry (MLflow 2.21.0+).
395-
396-
**Notes:**
395+
396+
**Notes:**
397397
* Prompt Registry support requires MLflow 2.21.0 or higher. The export/import will be skipped with a warning message if the MLflow version doesn't support prompts.
398398
* **Version handling**: MLflow 3.0+ uses efficient pagination to export all prompt versions. MLflow 2.21-2.x uses iterative discovery with early stopping (stops after 3 consecutive missing versions).
399-
399+
400400
### Export prompts
401-
401+
402402
Export prompts from the MLflow Prompt Registry to a directory.
403-
403+
404404
Source: [export_prompts.py](mlflow_migration/bulk/export_prompts.py).
405-
405+
406406
#### Usage
407-
407+
408408
```
409409
export-prompts --help
410-
410+
411411
Options:
412412
--output-dir TEXT Output directory. [required]
413413
--prompts TEXT Prompt names: 'all' for all prompts, comma-delimited
@@ -416,16 +416,16 @@ Options:
416416
[required]
417417
--use-threads BOOLEAN Use multithreading for export. [default: False]
418418
```
419-
419+
420420
#### Examples
421-
421+
422422
##### Export all prompts
423423
```
424424
export-prompts \
425425
--output-dir out/prompts \
426426
--prompts all
427427
```
428-
428+
429429
##### Export specific prompts
430430
```
431431
export-prompts \
@@ -445,30 +445,30 @@ where `my-prompts.txt` is:
445445
my-prompt-1
446446
my-prompt-2
447447
```
448-
448+
449449
### Import prompts
450-
450+
451451
Import prompts to the MLflow Prompt Registry from a directory.
452-
452+
453453
Source: [import_prompts.py](mlflow_migration/bulk/import_prompts.py).
454-
454+
455455
#### Usage
456-
456+
457457
```
458458
import-prompts --help
459-
459+
460460
Options:
461461
--input-dir TEXT Input directory containing exported prompts. [required]
462462
--delete-prompt BOOLEAN Delete existing prompt before importing. [default: False]
463463
--use-threads BOOLEAN Use multithreading for import. [default: False]
464464
```
465-
465+
466466
#### Examples
467-
467+
468468
```
469469
import-prompts --input-dir out/prompts
470470
```
471-
472-
**Notes:**
471+
472+
**Notes:**
473473
* Prompts are imported with their original names and version numbers are preserved.
474474
* All versions of each prompt are exported and imported to maintain complete version history.

mlflow_migration/bulk/export_all.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,17 +83,19 @@ def export_all(
8383
output_dir=os.path.join(output_dir, "prompts"),
8484
prompt_names=None, # Export all prompts
8585
use_threads=use_threads,
86-
mlflow_client=mlflow_client
86+
mlflow_client=mlflow_client,
8787
)
8888
# Log if unsupported but don't fail
8989
if res_prompts and "unsupported" in res_prompts:
90-
_logger.warning(f"Prompts not supported in MLflow {res_prompts.get('mlflow_version')}")
90+
_logger.warning(
91+
f"Prompts not supported in MLflow {res_prompts.get('mlflow_version')}"
92+
)
9193
elif res_prompts and "error" in res_prompts:
9294
_logger.warning(f"Failed to export prompts: {res_prompts['error']}")
9395
except Exception as e:
9496
_logger.warning(f"Failed to export prompts: {e}")
9597
res_prompts = {"error": str(e)}
96-
98+
9799
duration = round(time.time() - start_time, 1)
98100
info_attr = {
99101
"options": {
@@ -108,8 +110,8 @@ def export_all(
108110
"duration": duration,
109111
"models": res_models,
110112
"experiments": res_exps,
111-
"prompts": res_prompts
112-
}
113+
"prompts": res_prompts,
114+
},
113115
}
114116
io_utils.write_export_file(output_dir, "manifest.json", __file__, {}, info_attr)
115117
_logger.info(f"Duration for entire tracking server export: {duration} seconds")

0 commit comments

Comments
 (0)