@aws/ml-container-creator 0.13.5 → 0.15.1
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.
- package/config/parameter-schema-v2.json +33 -5
- package/infra/ci-harness/lib/ci-harness-stack.ts +13 -5
- package/infra/ci-harness/package-lock.json +121 -111
- package/infra/ci-harness/package.json +1 -1
- package/package.json +2 -2
- package/servers/endpoint-picker/index.js +23 -14
- package/servers/instance-sizer/index.js +72 -4
- package/servers/instance-sizer/lib/model-resolver.js +28 -2
- package/src/app.js +15 -0
- package/src/lib/config-loader.js +18 -0
- package/src/lib/config-manager.js +6 -1
- package/src/lib/dataset-slug.js +152 -0
- package/src/lib/generated/cli-options.js +9 -3
- package/src/lib/generated/parameter-matrix.js +15 -4
- package/src/lib/generated/validation-rules.js +1 -1
- package/src/lib/mcp-client.js +15 -1
- package/src/lib/mcp-query-runner.js +11 -1
- package/src/lib/prompt-runner.js +40 -20
- package/src/lib/prompts/feature-prompts.js +1 -1
- package/src/lib/template-manager.js +0 -7
- package/src/lib/template-variable-resolver.js +51 -1
- package/src/lib/tune-config-state.js +14 -1
- package/templates/do/.benchmark_writer.py +43 -0
- package/templates/do/.register_helper.py +1185 -0
- package/templates/do/.tune_helper.py +168 -2
- package/templates/do/__pycache__/.adapter_helper.cpython-312.pyc +0 -0
- package/templates/do/__pycache__/.benchmark_writer.cpython-312.pyc +0 -0
- package/templates/do/__pycache__/.register_helper.cpython-312.pyc +0 -0
- package/templates/do/__pycache__/.tune_helper.cpython-312.pyc +0 -0
- package/templates/do/adapter +319 -27
- package/templates/do/add-ic +85 -3
- package/templates/do/benchmark +28 -8
- package/templates/do/config +20 -0
- package/templates/do/lib/inference-component.sh +56 -3
- package/templates/do/register +557 -6
- package/templates/do/test +12 -2
- package/templates/do/tune +219 -6
package/templates/do/adapter
CHANGED
|
@@ -35,6 +35,7 @@ _usage() {
|
|
|
35
35
|
echo " add <name> --weights <s3-uri> Add a new LoRA adapter from S3"
|
|
36
36
|
echo " add <name> --from-hub <hf-repo-id> Add a new LoRA adapter from HuggingFace Hub"
|
|
37
37
|
echo " add <name> --from-tune [technique] Add adapter from do/tune output"
|
|
38
|
+
echo " add <name> --from-registry [arn] Add adapter from model registry"
|
|
38
39
|
echo " list List all adapters on the endpoint"
|
|
39
40
|
echo " remove <name> Remove an adapter"
|
|
40
41
|
echo " update <name> --weights <new-s3-uri> Update adapter weights from S3"
|
|
@@ -53,6 +54,8 @@ _usage() {
|
|
|
53
54
|
echo " ./do/adapter add tuned-sft --from-tune sft"
|
|
54
55
|
echo " ./do/adapter add tuned-sft --from-tune --local"
|
|
55
56
|
echo " ./do/adapter add tuned-sft --from-tune --no-wait"
|
|
57
|
+
echo " ./do/adapter add my-adapter --from-registry"
|
|
58
|
+
echo " ./do/adapter add my-adapter --from-registry arn:aws:sagemaker:...:model-package/proj/2"
|
|
56
59
|
echo " ./do/adapter list"
|
|
57
60
|
echo " ./do/adapter remove ectsum"
|
|
58
61
|
echo " ./do/adapter update ectsum --weights s3://my-bucket/adapters/ectsum-v2/adapter.tar.gz"
|
|
@@ -60,7 +63,7 @@ _usage() {
|
|
|
60
63
|
echo ""
|
|
61
64
|
echo "Adapter metadata is stored in do/adapters/<name>.conf"
|
|
62
65
|
echo ""
|
|
63
|
-
echo "Note: --weights, --from-hub, and --from-
|
|
66
|
+
echo "Note: --weights, --from-hub, --from-tune, and --from-registry are mutually exclusive."
|
|
64
67
|
}
|
|
65
68
|
|
|
66
69
|
# ── Validate LoRA is enabled ──────────────────────────────────────────────────
|
|
@@ -371,6 +374,8 @@ _adapter_add() {
|
|
|
371
374
|
local from_hub=""
|
|
372
375
|
local from_tune=""
|
|
373
376
|
local from_tune_technique=""
|
|
377
|
+
local from_registry=""
|
|
378
|
+
local registry_arn=""
|
|
374
379
|
local use_local=""
|
|
375
380
|
local no_wait=""
|
|
376
381
|
|
|
@@ -406,6 +411,16 @@ _adapter_add() {
|
|
|
406
411
|
shift
|
|
407
412
|
fi
|
|
408
413
|
;;
|
|
414
|
+
--from-registry)
|
|
415
|
+
from_registry="true"
|
|
416
|
+
# Check if next argument is an ARN (starts with arn:)
|
|
417
|
+
if [ -n "${2:-}" ] && [[ "${2}" == arn:* ]]; then
|
|
418
|
+
registry_arn="$2"
|
|
419
|
+
shift 2
|
|
420
|
+
else
|
|
421
|
+
shift
|
|
422
|
+
fi
|
|
423
|
+
;;
|
|
409
424
|
--local)
|
|
410
425
|
use_local="true"
|
|
411
426
|
shift
|
|
@@ -418,6 +433,7 @@ _adapter_add() {
|
|
|
418
433
|
echo "Usage: ./do/adapter add <name> --weights <s3-uri>"
|
|
419
434
|
echo " ./do/adapter add <name> --from-hub <hf-repo-id>"
|
|
420
435
|
echo " ./do/adapter add <name> --from-tune [technique]"
|
|
436
|
+
echo " ./do/adapter add <name> --from-registry [version-arn]"
|
|
421
437
|
echo ""
|
|
422
438
|
echo "Add a new LoRA adapter to the endpoint."
|
|
423
439
|
echo ""
|
|
@@ -428,10 +444,13 @@ _adapter_add() {
|
|
|
428
444
|
echo " --from-tune [technique] Use adapter output from do/tune"
|
|
429
445
|
echo " Without technique: uses latest tune output"
|
|
430
446
|
echo " With technique (e.g., sft, dpo): uses technique-specific output"
|
|
447
|
+
echo " --from-registry [arn] Add adapter from model registry"
|
|
448
|
+
echo " Without ARN: presents interactive selection"
|
|
449
|
+
echo " With ARN: adds directly using specified version ARN"
|
|
431
450
|
echo " --local Use local aws s3 cp instead of Processing Job (--from-tune only)"
|
|
432
451
|
echo " --no-wait Submit Processing Job and return immediately (--from-tune only)"
|
|
433
452
|
echo ""
|
|
434
|
-
echo "Note: --weights, --from-hub, and --from-
|
|
453
|
+
echo "Note: --weights, --from-hub, --from-tune, and --from-registry are mutually exclusive."
|
|
435
454
|
echo ""
|
|
436
455
|
echo "Examples:"
|
|
437
456
|
echo " ./do/adapter add ectsum --weights s3://bucket/adapters/ectsum/adapter.tar.gz"
|
|
@@ -440,6 +459,8 @@ _adapter_add() {
|
|
|
440
459
|
echo " ./do/adapter add tuned-sft --from-tune sft"
|
|
441
460
|
echo " ./do/adapter add tuned-sft --from-tune --local"
|
|
442
461
|
echo " ./do/adapter add tuned-sft --from-tune --no-wait"
|
|
462
|
+
echo " ./do/adapter add my-adapter --from-registry"
|
|
463
|
+
echo " ./do/adapter add my-adapter --from-registry arn:aws:sagemaker:...:model-package/proj/2"
|
|
443
464
|
exit 0
|
|
444
465
|
;;
|
|
445
466
|
-*)
|
|
@@ -447,6 +468,7 @@ _adapter_add() {
|
|
|
447
468
|
echo " Usage: ./do/adapter add <name> --weights <s3-uri>"
|
|
448
469
|
echo " ./do/adapter add <name> --from-hub <hf-repo-id>"
|
|
449
470
|
echo " ./do/adapter add <name> --from-tune [technique]"
|
|
471
|
+
echo " ./do/adapter add <name> --from-registry [version-arn]"
|
|
450
472
|
exit 1
|
|
451
473
|
;;
|
|
452
474
|
*)
|
|
@@ -457,6 +479,7 @@ _adapter_add() {
|
|
|
457
479
|
echo " Usage: ./do/adapter add <name> --weights <s3-uri>"
|
|
458
480
|
echo " ./do/adapter add <name> --from-hub <hf-repo-id>"
|
|
459
481
|
echo " ./do/adapter add <name> --from-tune [technique]"
|
|
482
|
+
echo " ./do/adapter add <name> --from-registry [version-arn]"
|
|
460
483
|
exit 1
|
|
461
484
|
fi
|
|
462
485
|
shift
|
|
@@ -478,46 +501,97 @@ _adapter_add() {
|
|
|
478
501
|
[ -n "${weights_uri}" ] && source_count=$((source_count + 1))
|
|
479
502
|
[ -n "${from_hub}" ] && source_count=$((source_count + 1))
|
|
480
503
|
[ -n "${from_tune}" ] && source_count=$((source_count + 1))
|
|
504
|
+
[ -n "${from_registry}" ] && source_count=$((source_count + 1))
|
|
481
505
|
|
|
482
506
|
if [ "${source_count}" -gt 1 ]; then
|
|
483
|
-
echo "❌ --weights, --from-hub, and --from-
|
|
507
|
+
echo "❌ --weights, --from-hub, --from-tune, and --from-registry are mutually exclusive"
|
|
484
508
|
echo ""
|
|
485
509
|
echo " Use one of:"
|
|
486
510
|
echo " ./do/adapter add ${adapter_name} --weights <s3-uri>"
|
|
487
511
|
echo " ./do/adapter add ${adapter_name} --from-hub <hf-repo-id>"
|
|
488
512
|
echo " ./do/adapter add ${adapter_name} --from-tune [technique]"
|
|
513
|
+
echo " ./do/adapter add ${adapter_name} --from-registry [version-arn]"
|
|
489
514
|
exit 1
|
|
490
515
|
fi
|
|
491
516
|
|
|
492
517
|
if [ "${source_count}" -eq 0 ]; then
|
|
493
|
-
echo "❌ One of --weights, --from-hub, or --from-
|
|
518
|
+
echo "❌ One of --weights, --from-hub, --from-tune, or --from-registry is required"
|
|
494
519
|
echo " Usage: ./do/adapter add <name> --weights <s3-uri>"
|
|
495
520
|
echo " ./do/adapter add <name> --from-hub <hf-repo-id>"
|
|
496
521
|
echo " ./do/adapter add <name> --from-tune [technique]"
|
|
522
|
+
echo " ./do/adapter add <name> --from-registry [version-arn]"
|
|
497
523
|
exit 1
|
|
498
524
|
fi
|
|
499
525
|
|
|
500
526
|
# ── Resolve --from-tune to weights_uri ────────────────────────────────
|
|
501
527
|
if [ -n "${from_tune}" ]; then
|
|
502
528
|
if [ -n "${from_tune_technique}" ]; then
|
|
503
|
-
#
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
echo ""
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
529
|
+
# Check if technique contains a hyphen — may be technique-dataset compound
|
|
530
|
+
if [[ "${from_tune_technique}" == *-* ]]; then
|
|
531
|
+
# Try compound key: TUNE_ADAPTER_PATH_<TECHNIQUE>_<SLUG>
|
|
532
|
+
local compound_technique="${from_tune_technique%%-*}"
|
|
533
|
+
local compound_slug="${from_tune_technique#*-}"
|
|
534
|
+
local compound_technique_upper
|
|
535
|
+
compound_technique_upper=$(echo "${compound_technique}" | tr '[:lower:]' '[:upper:]')
|
|
536
|
+
local compound_slug_upper
|
|
537
|
+
compound_slug_upper=$(echo "${compound_slug}" | tr '[:lower:]' '[:upper:]' | sed 's/-/_/g')
|
|
538
|
+
local compound_var="TUNE_ADAPTER_PATH_${compound_technique_upper}_${compound_slug_upper}"
|
|
539
|
+
local compound_path="${!compound_var:-}"
|
|
540
|
+
|
|
541
|
+
if [ -n "${compound_path}" ]; then
|
|
542
|
+
weights_uri="${compound_path}"
|
|
543
|
+
echo "📦 Using tune adapter output for technique '${compound_technique}' dataset '${compound_slug}': ${weights_uri}"
|
|
544
|
+
else
|
|
545
|
+
# Fallback: try as technique-only
|
|
546
|
+
local technique_upper
|
|
547
|
+
technique_upper=$(echo "${from_tune_technique}" | tr '[:lower:]' '[:upper:]' | sed 's/-/_/g')
|
|
548
|
+
local tune_var="TUNE_ADAPTER_PATH_${technique_upper}"
|
|
549
|
+
local tune_path="${!tune_var:-}"
|
|
550
|
+
|
|
551
|
+
if [ -n "${tune_path}" ]; then
|
|
552
|
+
echo "⚠️ ${compound_var} not found, falling back to ${tune_var}"
|
|
553
|
+
weights_uri="${tune_path}"
|
|
554
|
+
echo "📦 Using tune adapter output for technique '${from_tune_technique}': ${weights_uri}"
|
|
555
|
+
else
|
|
556
|
+
# Try the technique part alone as final fallback
|
|
557
|
+
local fallback_var="TUNE_ADAPTER_PATH_${compound_technique_upper}"
|
|
558
|
+
local fallback_path="${!fallback_var:-}"
|
|
559
|
+
|
|
560
|
+
if [ -n "${fallback_path}" ]; then
|
|
561
|
+
echo "⚠️ ${compound_var} not found, falling back to ${fallback_var}"
|
|
562
|
+
weights_uri="${fallback_path}"
|
|
563
|
+
echo "📦 Using tune adapter output for technique '${compound_technique}': ${weights_uri}"
|
|
564
|
+
else
|
|
565
|
+
echo "❌ No adapter output found for: ${from_tune_technique}"
|
|
566
|
+
echo ""
|
|
567
|
+
echo " Tried: ${compound_var}, ${fallback_var}"
|
|
568
|
+
echo ""
|
|
569
|
+
echo " Run a tune job first:"
|
|
570
|
+
echo " ./do/tune --technique ${compound_technique} --dataset <source>"
|
|
571
|
+
exit 1
|
|
572
|
+
fi
|
|
573
|
+
fi
|
|
574
|
+
fi
|
|
575
|
+
else
|
|
576
|
+
# Technique-only: read TUNE_ADAPTER_PATH_<TECHNIQUE>
|
|
577
|
+
local technique_upper
|
|
578
|
+
technique_upper=$(echo "${from_tune_technique}" | tr '[:lower:]' '[:upper:]')
|
|
579
|
+
local tune_var="TUNE_ADAPTER_PATH_${technique_upper}"
|
|
580
|
+
local tune_path="${!tune_var:-}"
|
|
581
|
+
|
|
582
|
+
if [ -z "${tune_path}" ]; then
|
|
583
|
+
echo "❌ No adapter output found for technique: ${from_tune_technique}"
|
|
584
|
+
echo ""
|
|
585
|
+
echo " ${tune_var} is not set in do/config."
|
|
586
|
+
echo ""
|
|
587
|
+
echo " Run a tune job first:"
|
|
588
|
+
echo " ./do/tune --technique ${from_tune_technique} --dataset <source>"
|
|
589
|
+
exit 1
|
|
590
|
+
fi
|
|
518
591
|
|
|
519
|
-
|
|
520
|
-
|
|
592
|
+
weights_uri="${tune_path}"
|
|
593
|
+
echo "📦 Using tune adapter output for technique '${from_tune_technique}': ${weights_uri}"
|
|
594
|
+
fi
|
|
521
595
|
else
|
|
522
596
|
# No technique: read TUNE_OUTPUT_PATH_LATEST and verify type
|
|
523
597
|
if [ -z "${TUNE_OUTPUT_PATH_LATEST:-}" ]; then
|
|
@@ -787,6 +861,136 @@ _adapter_add() {
|
|
|
787
861
|
fi # end --local else branch
|
|
788
862
|
fi
|
|
789
863
|
|
|
864
|
+
# ── Resolve --from-registry to weights_uri ────────────────────────────
|
|
865
|
+
if [ -n "${from_registry}" ]; then
|
|
866
|
+
if [ -z "${registry_arn}" ]; then
|
|
867
|
+
# Interactive mode: query registry and present selection (AC-4.2)
|
|
868
|
+
# Check if stdin is a TTY (AC-4.4)
|
|
869
|
+
if [ ! -t 0 ]; then
|
|
870
|
+
echo "Error: --from-registry requires an explicit version ARN in non-interactive mode."
|
|
871
|
+
echo "Usage: ./do/adapter add <name> --from-registry <version-arn>"
|
|
872
|
+
exit 1
|
|
873
|
+
fi
|
|
874
|
+
|
|
875
|
+
echo "📦 Querying model registry for available adapters..."
|
|
876
|
+
echo ""
|
|
877
|
+
|
|
878
|
+
local adapters_json
|
|
879
|
+
adapters_json=$(python3 "${SCRIPT_DIR}/.register_helper.py" list-adapters \
|
|
880
|
+
--project-name "${PROJECT_NAME}" \
|
|
881
|
+
--region "${AWS_REGION}" 2>/dev/null)
|
|
882
|
+
|
|
883
|
+
# Extract JSON line (filter out any non-JSON noise)
|
|
884
|
+
local json_line
|
|
885
|
+
json_line=$(echo "${adapters_json}" | grep -E '^\{' | tail -1)
|
|
886
|
+
|
|
887
|
+
if [ -z "${json_line}" ]; then
|
|
888
|
+
echo "❌ Failed to query model registry."
|
|
889
|
+
echo " Check that your AWS credentials are configured and the project has registered adapters."
|
|
890
|
+
exit 1
|
|
891
|
+
fi
|
|
892
|
+
|
|
893
|
+
# Parse adapter count
|
|
894
|
+
local adapter_count
|
|
895
|
+
adapter_count=$(echo "${json_line}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); print(len(data.get('adapters',[])))" 2>/dev/null || echo "0")
|
|
896
|
+
|
|
897
|
+
if [ "${adapter_count}" -eq 0 ]; then
|
|
898
|
+
echo "❌ No adapters found in the model registry for project: ${PROJECT_NAME}"
|
|
899
|
+
echo ""
|
|
900
|
+
echo " Register an adapter first with: ./do/register (after do/tune)"
|
|
901
|
+
echo " Or use --weights or --from-hub to add an adapter manually."
|
|
902
|
+
exit 1
|
|
903
|
+
fi
|
|
904
|
+
|
|
905
|
+
# Display selection menu
|
|
906
|
+
echo "Available adapters in registry (${adapter_count} found):"
|
|
907
|
+
echo ""
|
|
908
|
+
printf ' %-4s%-10s%-12s%-20s%s\n' "#" "VERSION" "TECHNIQUE" "CREATED" "PARENT MODEL"
|
|
909
|
+
|
|
910
|
+
local i=0
|
|
911
|
+
while [ "${i}" -lt "${adapter_count}" ]; do
|
|
912
|
+
local version technique created_at parent_arn
|
|
913
|
+
version=$(echo "${json_line}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); print(data['adapters'][${i}].get('version','?'))" 2>/dev/null)
|
|
914
|
+
technique=$(echo "${json_line}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); print(data['adapters'][${i}].get('tuneTechnique','?'))" 2>/dev/null)
|
|
915
|
+
created_at=$(echo "${json_line}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); t=data['adapters'][${i}].get('createdAt',''); print(t[:10] if t else '?')" 2>/dev/null)
|
|
916
|
+
parent_arn=$(echo "${json_line}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); a=data['adapters'][${i}].get('parentModelVersionArn',''); print(a.split('/')[-2]+'/'+a.split('/')[-1] if '/' in a else a[:40])" 2>/dev/null)
|
|
917
|
+
|
|
918
|
+
local num=$((i + 1))
|
|
919
|
+
printf ' %-4s%-10s%-12s%-20s%s\n' "${num}" "v${version}" "${technique}" "${created_at}" "${parent_arn}"
|
|
920
|
+
i=$((i + 1))
|
|
921
|
+
done
|
|
922
|
+
|
|
923
|
+
echo ""
|
|
924
|
+
echo -n "Select adapter (1-${adapter_count}): "
|
|
925
|
+
read -r selection
|
|
926
|
+
|
|
927
|
+
# Validate selection
|
|
928
|
+
if ! echo "${selection}" | grep -qE '^[0-9]+$'; then
|
|
929
|
+
echo "❌ Invalid selection: ${selection}"
|
|
930
|
+
exit 1
|
|
931
|
+
fi
|
|
932
|
+
if [ "${selection}" -lt 1 ] || [ "${selection}" -gt "${adapter_count}" ]; then
|
|
933
|
+
echo "❌ Selection out of range. Choose 1-${adapter_count}."
|
|
934
|
+
exit 1
|
|
935
|
+
fi
|
|
936
|
+
|
|
937
|
+
# Get the ARN of the selected adapter
|
|
938
|
+
local sel_idx=$((selection - 1))
|
|
939
|
+
registry_arn=$(echo "${json_line}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); print(data['adapters'][${sel_idx}]['arn'])" 2>/dev/null)
|
|
940
|
+
|
|
941
|
+
if [ -z "${registry_arn}" ]; then
|
|
942
|
+
echo "❌ Failed to retrieve ARN for selected adapter."
|
|
943
|
+
exit 1
|
|
944
|
+
fi
|
|
945
|
+
|
|
946
|
+
echo ""
|
|
947
|
+
echo "✅ Selected: ${registry_arn}"
|
|
948
|
+
echo ""
|
|
949
|
+
fi
|
|
950
|
+
|
|
951
|
+
# Direct mode (AC-4.3): use the provided or selected ARN to get version details
|
|
952
|
+
echo "📦 Retrieving adapter details from registry: ${registry_arn}"
|
|
953
|
+
echo ""
|
|
954
|
+
|
|
955
|
+
local version_json
|
|
956
|
+
version_json=$(python3 "${SCRIPT_DIR}/.register_helper.py" get-version \
|
|
957
|
+
--arn "${registry_arn}" \
|
|
958
|
+
--region "${AWS_REGION}" 2>/dev/null)
|
|
959
|
+
|
|
960
|
+
local version_line
|
|
961
|
+
version_line=$(echo "${version_json}" | grep -E '^\{' | tail -1)
|
|
962
|
+
|
|
963
|
+
if [ -z "${version_line}" ]; then
|
|
964
|
+
echo "❌ Failed to get version details for: ${registry_arn}"
|
|
965
|
+
echo ""
|
|
966
|
+
echo " Check that the ARN is correct and you have sagemaker:DescribeModelPackage permission."
|
|
967
|
+
echo " Run ./do/adapter list to see available registry adapters."
|
|
968
|
+
exit 1
|
|
969
|
+
fi
|
|
970
|
+
|
|
971
|
+
# Check for error in response
|
|
972
|
+
local version_error
|
|
973
|
+
version_error=$(echo "${version_line}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); print(data.get('error',''))" 2>/dev/null || echo "")
|
|
974
|
+
if [ -n "${version_error}" ]; then
|
|
975
|
+
echo "❌ Registry error: ${version_error}"
|
|
976
|
+
exit 1
|
|
977
|
+
fi
|
|
978
|
+
|
|
979
|
+
# Extract model data URL (weights path)
|
|
980
|
+
weights_uri=$(echo "${version_line}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); print(data.get('modelDataUrl',''))" 2>/dev/null || echo "")
|
|
981
|
+
|
|
982
|
+
if [ -z "${weights_uri}" ]; then
|
|
983
|
+
echo "❌ No model data URL found for registry version: ${registry_arn}"
|
|
984
|
+
echo ""
|
|
985
|
+
echo " The registered adapter does not have a model data URL."
|
|
986
|
+
echo " Use --weights with an explicit S3 URI instead."
|
|
987
|
+
exit 1
|
|
988
|
+
fi
|
|
989
|
+
|
|
990
|
+
echo "✅ Resolved adapter weights from registry: ${weights_uri}"
|
|
991
|
+
echo ""
|
|
992
|
+
fi
|
|
993
|
+
|
|
790
994
|
# ── Validate HF repo ID format (if --from-hub) ───────────────────────
|
|
791
995
|
if [ -n "${from_hub}" ]; then
|
|
792
996
|
# Valid formats: "org/name" or "name" (alphanumeric, hyphens, underscores, dots)
|
|
@@ -813,7 +1017,7 @@ _adapter_add() {
|
|
|
813
1017
|
fi
|
|
814
1018
|
|
|
815
1019
|
# ── Validate S3 URI format (only when --weights is explicitly used) ──
|
|
816
|
-
if [ -n "${weights_uri}" ] && [ -z "${from_hub}" ] && [ -z "${from_tune}" ]; then
|
|
1020
|
+
if [ -n "${weights_uri}" ] && [ -z "${from_hub}" ] && [ -z "${from_tune}" ] && [ -z "${from_registry}" ]; then
|
|
817
1021
|
if ! echo "${weights_uri}" | grep -qE '^s3://.*\.tar\.gz$'; then
|
|
818
1022
|
echo "❌ Invalid S3 URI: ${weights_uri}"
|
|
819
1023
|
echo ""
|
|
@@ -842,6 +1046,9 @@ _adapter_add() {
|
|
|
842
1046
|
elif [ -n "${from_tune}" ]; then
|
|
843
1047
|
echo " Source: do/tune output"
|
|
844
1048
|
echo " Weights: ${weights_uri}"
|
|
1049
|
+
elif [ -n "${from_registry}" ]; then
|
|
1050
|
+
echo " Source: Model Registry (${registry_arn})"
|
|
1051
|
+
echo " Weights: ${weights_uri}"
|
|
845
1052
|
else
|
|
846
1053
|
echo " Weights: ${weights_uri}"
|
|
847
1054
|
fi
|
|
@@ -942,9 +1149,24 @@ EOF
|
|
|
942
1149
|
|
|
943
1150
|
# Add tune-specific metadata if --from-tune was used
|
|
944
1151
|
if [ -n "${from_tune}" ]; then
|
|
1152
|
+
local tune_technique_meta="${from_tune_technique:-latest}"
|
|
1153
|
+
local tune_dataset_meta=""
|
|
1154
|
+
if [ -n "${from_tune_technique}" ] && [[ "${from_tune_technique}" == *-* ]]; then
|
|
1155
|
+
tune_technique_meta="${from_tune_technique%%-*}"
|
|
1156
|
+
tune_dataset_meta="${from_tune_technique#*-}"
|
|
1157
|
+
fi
|
|
945
1158
|
cat >> "${SCRIPT_DIR}/adapters/${adapter_name}.conf" <<EOF
|
|
946
1159
|
export ADAPTER_SOURCE="tune"
|
|
947
|
-
export ADAPTER_TUNE_TECHNIQUE="${
|
|
1160
|
+
export ADAPTER_TUNE_TECHNIQUE="${tune_technique_meta}"
|
|
1161
|
+
export ADAPTER_TUNE_DATASET="${tune_dataset_meta}"
|
|
1162
|
+
EOF
|
|
1163
|
+
fi
|
|
1164
|
+
|
|
1165
|
+
# Add registry-specific metadata if --from-registry was used
|
|
1166
|
+
if [ -n "${from_registry}" ]; then
|
|
1167
|
+
cat >> "${SCRIPT_DIR}/adapters/${adapter_name}.conf" <<EOF
|
|
1168
|
+
export ADAPTER_SOURCE="registry"
|
|
1169
|
+
export ADAPTER_REGISTRY_ARN="${registry_arn}"
|
|
948
1170
|
EOF
|
|
949
1171
|
fi
|
|
950
1172
|
|
|
@@ -959,6 +1181,8 @@ EOF
|
|
|
959
1181
|
echo " Source: HuggingFace Hub (${from_hub})"
|
|
960
1182
|
elif [ -n "${from_tune}" ]; then
|
|
961
1183
|
echo " Source: do/tune (${from_tune_technique:-latest})"
|
|
1184
|
+
elif [ -n "${from_registry}" ]; then
|
|
1185
|
+
echo " Source: Model Registry (${registry_arn})"
|
|
962
1186
|
fi
|
|
963
1187
|
echo " Created: ${created_at}"
|
|
964
1188
|
echo ""
|
|
@@ -1053,7 +1277,31 @@ _adapter_list() {
|
|
|
1053
1277
|
ownership=" (external)"
|
|
1054
1278
|
fi
|
|
1055
1279
|
|
|
1056
|
-
|
|
1280
|
+
# Check for tuning metadata in conf file
|
|
1281
|
+
local tune_info=""
|
|
1282
|
+
if [ -d "${SCRIPT_DIR}/adapters" ]; then
|
|
1283
|
+
for conf_file in "${SCRIPT_DIR}"/adapters/*.conf; do
|
|
1284
|
+
[ -f "${conf_file}" ] || continue
|
|
1285
|
+
local conf_ic
|
|
1286
|
+
conf_ic=$(grep "^export ADAPTER_IC_NAME=" "${conf_file}" 2>/dev/null | sed 's/^export ADAPTER_IC_NAME="//' | sed 's/"$//' || echo "")
|
|
1287
|
+
if [ "${conf_ic}" = "${ic_name}" ]; then
|
|
1288
|
+
local conf_technique
|
|
1289
|
+
conf_technique=$(grep "^export ADAPTER_TUNE_TECHNIQUE=" "${conf_file}" 2>/dev/null | sed 's/^export ADAPTER_TUNE_TECHNIQUE="//' | sed 's/"$//' || echo "")
|
|
1290
|
+
local conf_dataset
|
|
1291
|
+
conf_dataset=$(grep "^export ADAPTER_TUNE_DATASET=" "${conf_file}" 2>/dev/null | sed 's/^export ADAPTER_TUNE_DATASET="//' | sed 's/"$//' || echo "")
|
|
1292
|
+
if [ -n "${conf_technique}" ]; then
|
|
1293
|
+
if [ -n "${conf_dataset}" ]; then
|
|
1294
|
+
tune_info=" (from tune: ${conf_technique} / ${conf_dataset})"
|
|
1295
|
+
else
|
|
1296
|
+
tune_info=" (from tune: ${conf_technique})"
|
|
1297
|
+
fi
|
|
1298
|
+
fi
|
|
1299
|
+
break
|
|
1300
|
+
fi
|
|
1301
|
+
done
|
|
1302
|
+
fi
|
|
1303
|
+
|
|
1304
|
+
output_lines="${output_lines}$(printf '%-14s%-12s%s%s%s' "${display_name}" "${status}" "${weights_url}" "${ownership}" "${tune_info}")\n"
|
|
1057
1305
|
found_adapters=$((found_adapters + 1))
|
|
1058
1306
|
done
|
|
1059
1307
|
|
|
@@ -1061,12 +1309,56 @@ _adapter_list() {
|
|
|
1061
1309
|
echo "No adapters found on this endpoint."
|
|
1062
1310
|
echo ""
|
|
1063
1311
|
echo "Add one with: ./do/adapter add <name> --weights <s3-uri>"
|
|
1312
|
+
fi
|
|
1313
|
+
|
|
1314
|
+
if [ "${found_adapters}" -gt 0 ]; then
|
|
1315
|
+
# ── Print table ───────────────────────────────────────────────────────
|
|
1316
|
+
printf '%-14s%-12s%s\n' "NAME" "STATUS" "WEIGHTS"
|
|
1317
|
+
echo -e "${output_lines}" | sed '$ { /^$/d; }'
|
|
1318
|
+
fi
|
|
1319
|
+
|
|
1320
|
+
# ── Show registry adapters (isAdapter=true) alongside local ones ──────
|
|
1321
|
+
echo ""
|
|
1322
|
+
echo "📦 Registry adapters:"
|
|
1323
|
+
echo ""
|
|
1324
|
+
|
|
1325
|
+
local registry_json
|
|
1326
|
+
registry_json=$(python3 "${SCRIPT_DIR}/.register_helper.py" list-adapters \
|
|
1327
|
+
--project-name "${PROJECT_NAME}" \
|
|
1328
|
+
--region "${AWS_REGION}" 2>/dev/null || echo "")
|
|
1329
|
+
|
|
1330
|
+
local registry_line
|
|
1331
|
+
registry_line=$(echo "${registry_json}" | grep -E '^\{' | tail -1)
|
|
1332
|
+
|
|
1333
|
+
if [ -z "${registry_line}" ]; then
|
|
1334
|
+
echo " (could not query registry — check AWS credentials)"
|
|
1335
|
+
return 0
|
|
1336
|
+
fi
|
|
1337
|
+
|
|
1338
|
+
local registry_count
|
|
1339
|
+
registry_count=$(echo "${registry_line}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); print(len(data.get('adapters',[])))" 2>/dev/null || echo "0")
|
|
1340
|
+
|
|
1341
|
+
if [ "${registry_count}" -eq 0 ]; then
|
|
1342
|
+
echo " (none found)"
|
|
1064
1343
|
return 0
|
|
1065
1344
|
fi
|
|
1066
1345
|
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1346
|
+
printf ' %-10s%-12s%-14s%s\n' "VERSION" "TECHNIQUE" "CREATED" "PARENT MODEL"
|
|
1347
|
+
|
|
1348
|
+
local ri=0
|
|
1349
|
+
while [ "${ri}" -lt "${registry_count}" ]; do
|
|
1350
|
+
local rv rt rc rp
|
|
1351
|
+
rv=$(echo "${registry_line}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); print(data['adapters'][${ri}].get('version','?'))" 2>/dev/null)
|
|
1352
|
+
rt=$(echo "${registry_line}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); print(data['adapters'][${ri}].get('tuneTechnique','?'))" 2>/dev/null)
|
|
1353
|
+
rc=$(echo "${registry_line}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); t=data['adapters'][${ri}].get('createdAt',''); print(t[:10] if t else '?')" 2>/dev/null)
|
|
1354
|
+
rp=$(echo "${registry_line}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); a=data['adapters'][${ri}].get('parentModelVersionArn',''); print(a.split('/')[-2]+'/'+a.split('/')[-1] if '/' in a else a[:40])" 2>/dev/null)
|
|
1355
|
+
|
|
1356
|
+
printf ' %-10s%-12s%-14s%s\n' "v${rv}" "${rt}" "${rc}" "${rp}"
|
|
1357
|
+
ri=$((ri + 1))
|
|
1358
|
+
done
|
|
1359
|
+
|
|
1360
|
+
echo ""
|
|
1361
|
+
echo "Add from registry: ./do/adapter add <name> --from-registry [version-arn]"
|
|
1070
1362
|
}
|
|
1071
1363
|
|
|
1072
1364
|
_adapter_remove() {
|
package/templates/do/add-ic
CHANGED
|
@@ -123,6 +123,71 @@ if [ -n "${MODEL_DATA}" ]; then
|
|
|
123
123
|
fi
|
|
124
124
|
echo ""
|
|
125
125
|
|
|
126
|
+
# ============================================================
|
|
127
|
+
# Query model registry for available versions (AC-5.1)
|
|
128
|
+
# Non-intrusive: if registry query fails, skip silently
|
|
129
|
+
# ============================================================
|
|
130
|
+
REGISTRY_MODELS_JSON=""
|
|
131
|
+
REGISTRY_MODEL_COUNT=0
|
|
132
|
+
REGISTRY_SELECTED_MODEL_DATA=""
|
|
133
|
+
REGISTRY_SELECTED_IMAGE=""
|
|
134
|
+
|
|
135
|
+
if [ -z "${MODEL_DATA}" ]; then
|
|
136
|
+
# Only query registry if MODEL_DATA was not already provided via --from-tune or --model-data
|
|
137
|
+
if [ -t 0 ]; then
|
|
138
|
+
# Interactive mode: query registry for available models
|
|
139
|
+
_registry_json=$(python3 "${SCRIPT_DIR}/.register_helper.py" list-models \
|
|
140
|
+
--project-name "${PROJECT_NAME}" \
|
|
141
|
+
--region "${AWS_REGION:-us-east-1}" 2>/dev/null || echo "")
|
|
142
|
+
|
|
143
|
+
_registry_line=$(echo "${_registry_json}" | grep -E '^\{' | tail -1)
|
|
144
|
+
|
|
145
|
+
if [ -n "${_registry_line}" ]; then
|
|
146
|
+
REGISTRY_MODEL_COUNT=$(echo "${_registry_line}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); print(len(data.get('models',[])))" 2>/dev/null || echo "0")
|
|
147
|
+
|
|
148
|
+
if [ "${REGISTRY_MODEL_COUNT}" -gt 0 ]; then
|
|
149
|
+
REGISTRY_MODELS_JSON="${_registry_line}"
|
|
150
|
+
|
|
151
|
+
echo "📦 Available registered models:"
|
|
152
|
+
echo ""
|
|
153
|
+
printf ' %-4s%-10s%-12s%-38s%s\n' "#" "VERSION" "CONFIG" "MODEL" "INSTANCE"
|
|
154
|
+
|
|
155
|
+
_i=0
|
|
156
|
+
while [ "${_i}" -lt "${REGISTRY_MODEL_COUNT}" ]; do
|
|
157
|
+
_v=$(echo "${REGISTRY_MODELS_JSON}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); print(data['models'][${_i}].get('version','?'))" 2>/dev/null)
|
|
158
|
+
_c=$(echo "${REGISTRY_MODELS_JSON}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); print(data['models'][${_i}].get('deploymentConfig','?'))" 2>/dev/null)
|
|
159
|
+
_m=$(echo "${REGISTRY_MODELS_JSON}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); m=data['models'][${_i}].get('modelName','?'); print(m[:36]+'…' if len(m)>36 else m)" 2>/dev/null)
|
|
160
|
+
_inst=$(echo "${REGISTRY_MODELS_JSON}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); print(data['models'][${_i}].get('instanceType','?'))" 2>/dev/null)
|
|
161
|
+
|
|
162
|
+
_num=$((_i + 1))
|
|
163
|
+
printf ' %-4s%-10s%-12s%-38s%s\n' "${_num}" "v${_v}" "${_c}" "${_m}" "${_inst}"
|
|
164
|
+
_i=$((_i + 1))
|
|
165
|
+
done
|
|
166
|
+
|
|
167
|
+
echo ""
|
|
168
|
+
read -p "Select a model (1-${REGISTRY_MODEL_COUNT}) or press Enter to specify manually: " _selection
|
|
169
|
+
|
|
170
|
+
if [ -n "${_selection}" ]; then
|
|
171
|
+
# Validate selection
|
|
172
|
+
if echo "${_selection}" | grep -qE '^[0-9]+$' && [ "${_selection}" -ge 1 ] && [ "${_selection}" -le "${REGISTRY_MODEL_COUNT}" ]; then
|
|
173
|
+
_sel_idx=$((_selection - 1))
|
|
174
|
+
REGISTRY_SELECTED_MODEL_DATA=$(echo "${REGISTRY_MODELS_JSON}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); print(data['models'][${_sel_idx}].get('modelDataUrl',''))" 2>/dev/null || echo "")
|
|
175
|
+
REGISTRY_SELECTED_IMAGE=$(echo "${REGISTRY_MODELS_JSON}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); img=data['models'][${_sel_idx}].get('containerImage',''); print(img.split('/')[-1] if '/' in img else img)" 2>/dev/null || echo "")
|
|
176
|
+
|
|
177
|
+
echo ""
|
|
178
|
+
echo "✅ Selected registry model v$(echo "${REGISTRY_MODELS_JSON}" | python3 -c "import sys,json; data=json.loads(sys.stdin.read()); print(data['models'][${_sel_idx}].get('version','?'))" 2>/dev/null)"
|
|
179
|
+
echo ""
|
|
180
|
+
else
|
|
181
|
+
echo " ⚠️ Invalid selection, proceeding with manual entry."
|
|
182
|
+
echo ""
|
|
183
|
+
fi
|
|
184
|
+
fi
|
|
185
|
+
# If user pressed Enter without selection, proceed with manual entry
|
|
186
|
+
fi
|
|
187
|
+
fi
|
|
188
|
+
fi
|
|
189
|
+
fi
|
|
190
|
+
|
|
126
191
|
# ============================================================
|
|
127
192
|
# Prompt for IC name (if not provided as argument)
|
|
128
193
|
# ============================================================
|
|
@@ -169,12 +234,29 @@ else
|
|
|
169
234
|
fi
|
|
170
235
|
|
|
171
236
|
# ============================================================
|
|
172
|
-
# Prompt for image tag
|
|
237
|
+
# Prompt for image tag (AC-5.2, AC-5.3: pre-fill from registry, user can override)
|
|
173
238
|
# ============================================================
|
|
174
|
-
|
|
239
|
+
if [ -n "${REGISTRY_SELECTED_IMAGE}" ]; then
|
|
240
|
+
DEFAULT_IMAGE_TAG="${REGISTRY_SELECTED_IMAGE}"
|
|
241
|
+
else
|
|
242
|
+
DEFAULT_IMAGE_TAG="${PROJECT_NAME}-latest"
|
|
243
|
+
fi
|
|
175
244
|
read -p "Image tag [${DEFAULT_IMAGE_TAG}]: " IC_IMAGE_TAG
|
|
176
245
|
IC_IMAGE_TAG="${IC_IMAGE_TAG:-${DEFAULT_IMAGE_TAG}}"
|
|
177
246
|
|
|
247
|
+
# ============================================================
|
|
248
|
+
# Prompt for model data URL (AC-5.2, AC-5.3: pre-fill from registry, user can override)
|
|
249
|
+
# ============================================================
|
|
250
|
+
if [ -z "${MODEL_DATA}" ] && [ -n "${REGISTRY_SELECTED_MODEL_DATA}" ]; then
|
|
251
|
+
# Pre-fill from registry selection — user can override (AC-5.3)
|
|
252
|
+
read -p "Model data URL [${REGISTRY_SELECTED_MODEL_DATA}]: " _model_data_input
|
|
253
|
+
MODEL_DATA="${_model_data_input:-${REGISTRY_SELECTED_MODEL_DATA}}"
|
|
254
|
+
elif [ -z "${MODEL_DATA}" ]; then
|
|
255
|
+
# No registry selection — offer manual entry (optional)
|
|
256
|
+
read -p "Model data URL (S3 URI, optional — press Enter to skip): " _model_data_input
|
|
257
|
+
MODEL_DATA="${_model_data_input:-}"
|
|
258
|
+
fi
|
|
259
|
+
|
|
178
260
|
# ============================================================
|
|
179
261
|
# Prompt for GPU count
|
|
180
262
|
# ============================================================
|
|
@@ -232,7 +314,7 @@ export IC_MIN_MEMORY_MB=${IC_MIN_MEMORY_MB}
|
|
|
232
314
|
export IC_STARTUP_TIMEOUT=900
|
|
233
315
|
EOF
|
|
234
316
|
|
|
235
|
-
# Add model data if provided (from --from-tune
|
|
317
|
+
# Add model data if provided (from --from-tune, --model-data, or registry selection)
|
|
236
318
|
if [ -n "${MODEL_DATA}" ]; then
|
|
237
319
|
cat >> "${IC_CONF_PATH}" <<EOF
|
|
238
320
|
export IC_MODEL_DATA="${MODEL_DATA}"
|