seawolf2357 commited on
Commit
15378c4
·
verified ·
1 Parent(s): c713d4d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +360 -817
app.py CHANGED
@@ -455,7 +455,7 @@ def replace_attention_with_retention(model, use_hierarchical=True):
455
 
456
 
457
  # =====================================================
458
- # Custom Modeling Code 생성 (완전 개선!)
459
  # =====================================================
460
 
461
  def generate_modeling_phoenix_code():
@@ -868,187 +868,13 @@ class PhoenixModelForCausalLM(PhoenixPreTrainedModel):
868
 
869
  # Auto-registration
870
  AutoConfig.register("phoenix", PhoenixConfig)
871
-
872
-
873
- return modeling_code
874
-
875
-
876
- class PhoenixPreTrainedModel(PreTrainedModel):
877
- """
878
- Base PHOENIX PreTrainedModel
879
- Handles weight initialization and loading
880
- """
881
- config_class = PhoenixConfig
882
- base_model_prefix = "phoenix"
883
- supports_gradient_checkpointing = True
884
- _no_split_modules = ["MultiScaleRetention", "HierarchicalRetention"]
885
-
886
- def _init_weights(self, module):
887
- """Initialize weights"""
888
- if isinstance(module, nn.Linear):
889
- module.weight.data.normal_(mean=0.0, std=self.config.initializer_range if hasattr(self.config, 'initializer_range') else 0.02)
890
- if module.bias is not None:
891
- module.bias.data.zero_()
892
- elif isinstance(module, nn.Embedding):
893
- module.weight.data.normal_(mean=0.0, std=self.config.initializer_range if hasattr(self.config, 'initializer_range') else 0.02)
894
- if module.padding_idx is not None:
895
- module.weight.data[module.padding_idx].zero_()
896
- elif isinstance(module, nn.LayerNorm):
897
- module.bias.data.zero_()
898
- module.weight.data.fill_(1.0)
899
-
900
-
901
- class PhoenixModel(PhoenixPreTrainedModel):
902
- """
903
- PHOENIX Model with Retention layers
904
- This is the actual model class loaded by AutoModel
905
- """
906
-
907
- def __init__(self, config):
908
- super().__init__(config)
909
- self.config = config
910
-
911
- # Store original model for delegation
912
- self._original_model = None
913
-
914
- def set_original_model(self, model):
915
- """Set the original model with converted retention layers"""
916
- self._original_model = model
917
-
918
- def forward(self, *args, **kwargs):
919
- """Forward pass delegates to original model"""
920
- if self._original_model is None:
921
- raise ValueError("Original model not set. Use set_original_model() first.")
922
- return self._original_model(*args, **kwargs)
923
-
924
- def generate(self, *args, **kwargs):
925
- """Generate delegates to original model"""
926
- if self._original_model is None:
927
- raise ValueError("Original model not set. Use set_original_model() first.")
928
- return self._original_model.generate(*args, **kwargs)
929
-
930
-
931
-
932
-
933
-
934
- def load_phoenix_model(pretrained_model_name_or_path, **kwargs):
935
- """
936
- Load PHOENIX model with automatic Retention conversion
937
-
938
- This function is called by AutoModel/AutoModelForCausalLM when trust_remote_code=True
939
-
940
- Args:
941
- pretrained_model_name_or_path: Model path or Hub URL
942
- **kwargs: Additional arguments for model loading
943
-
944
- Returns:
945
- PhoenixModelForCausalLM: Model with Retention mechanism
946
- """
947
- import json
948
- from pathlib import Path
949
-
950
- print(f"🔥 Loading PHOENIX model from {pretrained_model_name_or_path}")
951
-
952
- # Load config
953
- config_path = Path(pretrained_model_name_or_path) / "config.json"
954
- if config_path.exists():
955
- with open(config_path, 'r') as f:
956
- config_dict = json.load(f)
957
- else:
958
- # Try to download from Hub
959
- from huggingface_hub import hf_hub_download
960
- config_path = hf_hub_download(
961
- repo_id=pretrained_model_name_or_path,
962
- filename="config.json"
963
- )
964
- with open(config_path, 'r') as f:
965
- config_dict = json.load(f)
966
-
967
- # Check PHOENIX markers
968
- use_phoenix = config_dict.get('use_phoenix_retention', False)
969
- original_model_url = config_dict.get('original_model', 'unknown')
970
-
971
- if not use_phoenix:
972
- print("⚠️ Warning: This doesn't appear to be a PHOENIX model")
973
-
974
- print(f" Original model: {original_model_url}")
975
- print(f" PHOENIX version: {config_dict.get('phoenix_version', 'unknown')}")
976
-
977
- # Load original model architecture
978
- from transformers import AutoModelForCausalLM, AutoConfig
979
-
980
- # Create base config
981
- base_config = AutoConfig.from_pretrained(
982
- pretrained_model_name_or_path,
983
- trust_remote_code=True
984
- )
985
-
986
- # Load base model structure with weights
987
- base_model = AutoModelForCausalLM.from_pretrained(
988
- pretrained_model_name_or_path,
989
- config=base_config,
990
- **kwargs
991
- )
992
-
993
- # Apply retention conversion
994
- print("🔄 Applying Retention conversion...")
995
- use_hierarchical = config_dict.get('use_hierarchical', True)
996
-
997
- if hasattr(base_model, 'model') and hasattr(base_model.model, 'layers'):
998
- layers = base_model.model.layers
999
- converted_count = 0
1000
-
1001
- for layer_idx, layer in enumerate(layers):
1002
- if hasattr(layer, 'self_attn'):
1003
- old_attn = layer.self_attn
1004
-
1005
- # Create new retention layer
1006
- if use_hierarchical:
1007
- new_retention = HierarchicalRetention(base_config, layer_idx)
1008
- else:
1009
- new_retention = MultiScaleRetention(base_config, layer_idx)
1010
-
1011
- # Copy weights if available
1012
- if hasattr(old_attn, 'q_proj'):
1013
- try:
1014
- target = new_retention.base_retention if use_hierarchical else new_retention
1015
-
1016
- # Copy Q, K, V, O projection weights
1017
- if old_attn.q_proj.weight.shape == target.q_proj.weight.shape:
1018
- target.q_proj.weight.data = old_attn.q_proj.weight.data.clone()
1019
-
1020
- if old_attn.k_proj.weight.shape == target.k_proj.weight.shape:
1021
- target.k_proj.weight.data = old_attn.k_proj.weight.data.clone()
1022
-
1023
- if old_attn.v_proj.weight.shape == target.v_proj.weight.shape:
1024
- target.v_proj.weight.data = old_attn.v_proj.weight.data.clone()
1025
-
1026
- if old_attn.o_proj.weight.shape == target.o_proj.weight.shape:
1027
- target.o_proj.weight.data = old_attn.o_proj.weight.data.clone()
1028
-
1029
- except Exception as e:
1030
- print(f" ⚠️ Layer {layer_idx}: Could not copy weights - {e}")
1031
-
1032
- # Replace attention with retention
1033
- layer.self_attn = new_retention
1034
- converted_count += 1
1035
-
1036
- print(f"✅ Converted {converted_count}/{len(layers)} layers to Retention")
1037
-
1038
- # Create PHOENIX wrapper
1039
- phoenix_model = PhoenixModelForCausalLM(base_config)
1040
- phoenix_model.set_original_model(base_model)
1041
-
1042
- print("✅ PHOENIX model loaded successfully!")
1043
-
1044
- return phoenix_model
1045
  '''
1046
 
1047
  return modeling_code
1048
 
1049
 
1050
  # =====================================================
1051
- # 향상된 저장 함수 (완전 수정!)
1052
  # =====================================================
1053
 
1054
  def save_phoenix_model_with_code(model, tokenizer, output_path, original_model_url, metadata):
@@ -1084,9 +910,8 @@ def save_phoenix_model_with_code(model, tokenizer, output_path, original_model_u
1084
  config_dict["original_model"] = original_model_url
1085
  config_dict["use_hierarchical"] = metadata.get('use_hierarchical', True)
1086
 
1087
- # auto_map 설정 (핵심!)
1088
  config_dict["auto_map"] = {
1089
- "AutoModel": "modeling_phoenix.PhoenixModel",
1090
  "AutoModelForCausalLM": "modeling_phoenix.PhoenixModelForCausalLM",
1091
  }
1092
 
@@ -1221,16 +1046,12 @@ Apache 2.0 (inherited from original model)
1221
 
1222
 
1223
  # =====================================================
1224
- # 업로드 전 검증 함수 (신규!)
1225
- # =====================================================
1226
-
1227
- # =====================================================
1228
- # 업로드 전 검증 함수 (완전 수정!)
1229
  # =====================================================
1230
 
1231
  def verify_phoenix_model_before_upload(model_path: str) -> Tuple[bool, str, Dict]:
1232
  """
1233
- Upload 전 PHOENIX 모델 검증 (구조 탐색 개선!)
1234
 
1235
  Returns:
1236
  (success, message, metrics)
@@ -1238,37 +1059,37 @@ def verify_phoenix_model_before_upload(model_path: str) -> Tuple[bool, str, Dict
1238
  print("\n🧪 Pre-upload Verification...")
1239
 
1240
  try:
1241
- # 1. 파일 존재 확인 (safetensors OR pytorch_model.bin)
1242
  model_path = Path(model_path)
1243
 
1244
- # 필수 파일 체크 (모델 가중치는 둘 중 하나만 있으면 됨)
1245
- config_exists = (model_path / 'config.json').exists()
1246
- modeling_exists = (model_path / 'modeling_phoenix.py').exists()
1247
- readme_exists = (model_path / 'README.md').exists()
 
 
 
 
1248
 
1249
- # 모델 가중치 파일 확인 (safetensors 우선)
1250
- safetensors_exists = (model_path / 'model.safetensors').exists()
1251
- pytorch_bin_exists = (model_path / 'pytorch_model.bin').exists()
1252
- model_weights_exist = safetensors_exists or pytorch_bin_exists
1253
 
1254
  print(f" 📄 File Check:")
1255
- print(f" config.json: {'✅' if config_exists else '❌'}")
1256
- print(f" modeling_phoenix.py: {'✅' if modeling_exists else '❌'}")
1257
- print(f" README.md: {'✅' if readme_exists else '❌'}")
1258
- print(f" model weights: {'✅ (safetensors)' if safetensors_exists else '✅ (pytorch_model.bin)' if pytorch_bin_exists else '❌'}")
1259
 
1260
- if not config_exists:
1261
  return False, "❌ Missing file: config.json", {}
1262
- if not modeling_exists:
1263
  return False, "❌ Missing file: modeling_phoenix.py", {}
1264
- if not readme_exists:
1265
  return False, "❌ Missing file: README.md", {}
1266
  if not model_weights_exist:
1267
- return False, "❌ Missing model weights (need model.safetensors or pytorch_model.bin)", {}
1268
 
1269
  print(" ✅ All required files present")
1270
 
1271
- # 2. Config 검증
1272
  with open(model_path / 'config.json', 'r') as f:
1273
  config = json.load(f)
1274
 
@@ -1280,7 +1101,7 @@ def verify_phoenix_model_before_upload(model_path: str) -> Tuple[bool, str, Dict
1280
 
1281
  print(" ✅ Config validated")
1282
 
1283
- # 3. 모델 로딩 테스트
1284
  print(" 🔄 Testing model loading...")
1285
 
1286
  try:
@@ -1299,20 +1120,19 @@ def verify_phoenix_model_before_upload(model_path: str) -> Tuple[bool, str, Dict
1299
  print(f" ⚠️ Model loading warning: {e}")
1300
  print(f" Continuing with basic checks...")
1301
 
1302
- # 로딩 실패해도 파일들이 있으면 통과
1303
  metrics = {
1304
  'retention_layers': -1,
1305
  'total_layers': -1,
1306
- 'retention_rate': 1.0, # 파일 검증만 통과
1307
- 'generation_quality': 0.8, # 기본값
1308
- 'model_format': 'safetensors' if safetensors_exists else 'pytorch_bin',
1309
  'verification_mode': 'file_only'
1310
  }
1311
 
1312
  print(" ✅ File-based verification passed")
1313
  return True, "✅ File checks passed (model loading skipped)", metrics
1314
 
1315
- # 4. Retention 검증 (여러 경로 시도)
1316
  print(" 🔍 Verifying Retention layers...")
1317
 
1318
  retention_count = 0
@@ -1321,18 +1141,14 @@ def verify_phoenix_model_before_upload(model_path: str) -> Tuple[bool, str, Dict
1321
 
1322
  # 여러 가능한 구조 탐색
1323
  if hasattr(model, '_original_model'):
1324
- # PhoenixModelForCausalLM의 _original_model
1325
  actual_model = model._original_model
1326
  if hasattr(actual_model, 'model') and hasattr(actual_model.model, 'layers'):
1327
  layers = actual_model.model.layers
1328
  elif hasattr(model, 'model') and hasattr(model.model, 'layers'):
1329
- # 일반적인 구조
1330
  layers = model.model.layers
1331
  elif hasattr(model, 'transformer') and hasattr(model.transformer, 'h'):
1332
- # GPT 스타일
1333
  layers = model.transformer.h
1334
  elif hasattr(model, 'layers'):
1335
- # 직접 layers
1336
  layers = model.layers
1337
 
1338
  if layers is not None:
@@ -1349,7 +1165,6 @@ def verify_phoenix_model_before_upload(model_path: str) -> Tuple[bool, str, Dict
1349
  retention_rate = retention_count / total_layers if total_layers > 0 else 0
1350
  print(f" ✅ Retention layers: {retention_count}/{total_layers} ({retention_rate*100:.1f}%)")
1351
  else:
1352
- # 레이어 구조를 못 찾았지만, 파일들이 정상이면 통과
1353
  print(f" ⚠️ Could not verify layer structure (custom architecture)")
1354
  print(f" ✅ Files are valid, proceeding...")
1355
 
@@ -1358,13 +1173,12 @@ def verify_phoenix_model_before_upload(model_path: str) -> Tuple[bool, str, Dict
1358
  'total_layers': -1,
1359
  'retention_rate': 1.0,
1360
  'generation_quality': 0.8,
1361
- 'model_format': 'safetensors' if safetensors_exists else 'pytorch_bin',
1362
  'verification_mode': 'file_only'
1363
  }
1364
 
1365
  return True, "✅ File checks passed (layer verification skipped)", metrics
1366
 
1367
- # Retention이 하나도 없으면 경고만 하고 통과 (파일은 정상)
1368
  if retention_count == 0:
1369
  print(f" ⚠️ No Retention layers detected in loaded model")
1370
  print(f" ⚠️ This may be normal if custom code hasn't loaded yet")
@@ -1375,13 +1189,13 @@ def verify_phoenix_model_before_upload(model_path: str) -> Tuple[bool, str, Dict
1375
  'total_layers': total_layers,
1376
  'retention_rate': 0.0,
1377
  'generation_quality': 0.7,
1378
- 'model_format': 'safetensors' if safetensors_exists else 'pytorch_bin',
1379
  'verification_mode': 'file_only'
1380
  }
1381
 
1382
  return True, "✅ File checks passed (Retention will load on Hub)", metrics
1383
 
1384
- # 5. 생성 테스트 (Retention이 있으면)
1385
  if retention_count > 0:
1386
  print(" 🚀 Testing generation...")
1387
 
@@ -1404,17 +1218,13 @@ def verify_phoenix_model_before_upload(model_path: str) -> Tuple[bool, str, Dict
1404
 
1405
  # 품질 점수
1406
  score = 0.0
1407
-
1408
- # 길이 체크
1409
  if len(generated) > len(prompt):
1410
  score += 0.3
1411
 
1412
- # 이상한 토큰 체크
1413
  weird_tokens = ['�', '[UNK]', 'priv', 'Brah', '__,__']
1414
  if not any(token in generated for token in weird_tokens):
1415
  score += 0.4
1416
 
1417
- # 의미있는 생성
1418
  if len(generated.split()) > len(prompt.split()) + 3:
1419
  score += 0.3
1420
 
@@ -1431,15 +1241,15 @@ def verify_phoenix_model_before_upload(model_path: str) -> Tuple[bool, str, Dict
1431
  avg_score = sum(generation_scores) / len(generation_scores) if generation_scores else 0.0
1432
  print(f" ✅ Generation quality: {avg_score:.2f}/1.00")
1433
  else:
1434
- avg_score = 0.7 # 기본값
1435
 
1436
- # 6. 최종 검증 통과
1437
  metrics = {
1438
  'retention_layers': retention_count,
1439
  'total_layers': total_layers,
1440
  'retention_rate': retention_rate if total_layers > 0 else 0.0,
1441
  'generation_quality': avg_score,
1442
- 'model_format': 'safetensors' if safetensors_exists else 'pytorch_bin',
1443
  'verification_mode': 'full' if retention_count > 0 else 'file_only'
1444
  }
1445
 
@@ -1451,18 +1261,18 @@ def verify_phoenix_model_before_upload(model_path: str) -> Tuple[bool, str, Dict
1451
  import traceback
1452
  error_msg = traceback.format_exc()
1453
 
1454
- # 예외 발생해도 파일만 체크하고 통과
1455
  print(f"\n⚠️ Verification exception: {str(e)}")
1456
  print(f" Checking files only...")
1457
 
1458
  model_path = Path(model_path)
1459
- config_exists = (model_path / 'config.json').exists()
1460
- modeling_exists = (model_path / 'modeling_phoenix.py').exists()
1461
- readme_exists = (model_path / 'README.md').exists()
1462
- safetensors_exists = (model_path / 'model.safetensors').exists()
1463
- pytorch_bin_exists = (model_path / 'pytorch_model.bin').exists()
 
1464
 
1465
- if config_exists and modeling_exists and (safetensors_exists or pytorch_bin_exists):
1466
  print(f" ✅ Essential files present, proceeding...")
1467
 
1468
  metrics = {
@@ -1470,7 +1280,7 @@ def verify_phoenix_model_before_upload(model_path: str) -> Tuple[bool, str, Dict
1470
  'total_layers': -1,
1471
  'retention_rate': 1.0,
1472
  'generation_quality': 0.7,
1473
- 'model_format': 'safetensors' if safetensors_exists else 'pytorch_bin',
1474
  'verification_mode': 'minimal'
1475
  }
1476
 
@@ -1480,7 +1290,7 @@ def verify_phoenix_model_before_upload(model_path: str) -> Tuple[bool, str, Dict
1480
 
1481
 
1482
  # =====================================================
1483
- # HuggingFace Hub Upload (수정!)
1484
  # =====================================================
1485
 
1486
  def upload_to_huggingface_hub(
@@ -1580,21 +1390,6 @@ def upload_to_huggingface_hub(
1580
  print(f"\n📤 Uploading files to HuggingFace Hub...")
1581
  print(f" This may take a few minutes depending on model size...")
1582
 
1583
- # 필수 파일 체크 (safetensors OR pytorch_model.bin)
1584
- config_exists = (model_path / 'config.json').exists()
1585
- modeling_exists = (model_path / 'modeling_phoenix.py').exists()
1586
- safetensors_exists = (model_path / 'model.safetensors').exists()
1587
- pytorch_bin_exists = (model_path / 'pytorch_model.bin').exists()
1588
-
1589
- if not config_exists:
1590
- return False, "", "❌ config.json not found"
1591
- if not modeling_exists:
1592
- return False, "", "❌ modeling_phoenix.py not found"
1593
- if not (safetensors_exists or pytorch_bin_exists):
1594
- return False, "", "❌ Model weights not found (need model.safetensors or pytorch_model.bin)"
1595
-
1596
- print(f"✅ All required files present")
1597
-
1598
  try:
1599
  api.upload_folder(
1600
  folder_path=str(model_path),
@@ -1757,420 +1552,96 @@ class ExperimentDatabase:
1757
  return [dict(row) for row in cursor.fetchall()]
1758
 
1759
 
1760
-
1761
-
1762
-
1763
  # =====================================================
1764
- # 모델 버닝 UI 함수 (개선!)
1765
  # =====================================================
1766
 
1767
- def burn_phoenix_model_ui(
1768
- model_url,
1769
- use_hierarchical,
1770
- dataset_path,
1771
- output_name,
1772
- use_finetuning,
1773
- num_epochs,
1774
- batch_size,
1775
- learning_rate,
1776
- max_steps,
1777
- upload_to_hub,
1778
- hub_repo_name,
1779
- hub_private,
1780
- ):
1781
- """Gradio UI용 모델 버닝 함수 (업로드 개선!)"""
1782
 
1783
- print("\n" + "="*80)
1784
- print("🔥 PHOENIX MODEL BURNING START")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1785
  print("="*80)
1786
 
 
 
 
1787
  try:
1788
- # 입력 검증
1789
- if not model_url.strip():
1790
- return "⚠️ Model URL is required", None
1791
 
1792
- if not output_name.strip():
1793
- output_name = f"phoenix_{model_url.split('/')[-1]}_{int(time.time())}"
 
 
 
 
1794
 
1795
- output_dir = f"{MODELS_PATH}/{output_name}"
 
 
1796
 
1797
- print(f"📋 Configuration:")
1798
- print(f" Model URL: {model_url}")
1799
- print(f" Output Name: {output_name}")
1800
- print(f" Output Dir: {output_dir}")
1801
- print(f" Hierarchical: {use_hierarchical}")
1802
- print(f" Upload to Hub: {upload_to_hub}")
1803
 
1804
- has_dataset = dataset_path and dataset_path.strip() and Path(dataset_path).exists()
 
 
1805
 
1806
- if use_finetuning and not has_dataset:
1807
- return "⚠️ Fine-tuning requires a valid dataset path", None
 
 
1808
 
1809
- # HF Token 확인 (업로드 예정인 경우)
1810
- if upload_to_hub and not HF_TOKEN:
1811
- warning_msg = """
1812
- ⚠️ **HuggingFace Token Not Found!**
1813
-
1814
- Model will be burned locally, but upload will fail.
1815
-
1816
- To enable upload:
1817
- 1. Set `HF_TOKEN` environment variable
1818
- 2. Restart the application
1819
-
1820
- Continuing with local burning only...
1821
- """
1822
- print(f"\n{warning_msg}")
1823
 
1824
- # Burning 실행
1825
- print(f"\n{'='*80}")
1826
- if use_finetuning and has_dataset:
1827
- print("🚀 Starting Fine-tuning Burning...")
1828
- result = burn_model_with_finetuning(
1829
- model_url=model_url,
1830
- output_dir=output_dir,
1831
- dataset_path=dataset_path,
1832
- use_hierarchical=use_hierarchical,
1833
- num_epochs=num_epochs,
1834
- batch_size=batch_size,
1835
- learning_rate=learning_rate,
1836
- max_steps=max_steps,
1837
- )
1838
- else:
1839
- print("🚀 Starting Zero-shot Burning...")
1840
- result = burn_model_zero_shot(
1841
- model_url=model_url,
1842
- output_dir=output_dir,
1843
- use_hierarchical=use_hierarchical,
1844
- )
1845
-
1846
- if result['status'] != 'success':
1847
- error_msg = f"""
1848
- ❌ **Burning Failed**
1849
- ```
1850
- {result.get('error', 'Unknown error')}
1851
- ```
1852
-
1853
- **Traceback:**
1854
- ```
1855
- {result.get('traceback', 'N/A')}
1856
- ```
1857
- """
1858
- return error_msg, None
1859
-
1860
- print(f"\n✅ Burning completed successfully!")
1861
-
1862
- # HuggingFace Hub 업로드
1863
- hub_url = None
1864
- verification_passed = False
1865
- upload_status = "Not attempted"
1866
-
1867
- if upload_to_hub:
1868
- if not HF_TOKEN:
1869
- upload_status = "❌ Failed - No HF_TOKEN"
1870
- print(f"\n{upload_status}")
1871
- else:
1872
- print(f"\n{'='*80}")
1873
- print("📤 Starting HuggingFace Hub Upload...")
1874
- print(f"{'='*80}")
1875
-
1876
- success, hub_url, upload_msg = upload_to_huggingface_hub(
1877
- model_path=result['model_path'],
1878
- original_model_url=model_url,
1879
- repo_name=hub_repo_name if hub_repo_name.strip() else None,
1880
- private=hub_private,
1881
- skip_verification=False
1882
- )
1883
-
1884
- verification_passed = success
1885
-
1886
- if success:
1887
- upload_status = f"✅ Uploaded successfully to {hub_url}"
1888
- print(f"\n{upload_status}")
1889
- else:
1890
- upload_status = f"❌ Upload failed\n\n{upload_msg}"
1891
- print(f"\n{upload_status}")
1892
- else:
1893
- upload_status = "⏭️ Skipped (not requested)"
1894
- print(f"\n📦 Hub upload: {upload_status}")
1895
-
1896
- # 데이터베이스 저장
1897
- burning_info = {
1898
- 'model_url': model_url,
1899
- 'output_path': result['model_path'],
1900
- 'hub_url': hub_url,
1901
- 'use_hierarchical': use_hierarchical,
1902
- 'dataset_used': has_dataset,
1903
- 'conversion_rate': result.get('conversion_rate', 0.0),
1904
- 'training_steps': result.get('training_steps', 0),
1905
- 'final_loss': result.get('final_loss'),
1906
- 'evaluation_score': result.get('quality_score', 0.0),
1907
- 'verification_passed': verification_passed,
1908
- }
1909
-
1910
- db.save_burning(burning_info)
1911
- print(f"✅ Saved to database")
1912
-
1913
- # 결과 포맷팅
1914
- output_md = f"""
1915
- # 🔥 Model Burning Complete!
1916
-
1917
- ## 📦 Model Information
1918
- - **Original Model**: {model_url}
1919
- - **Output Path**: `{result['model_path']}`
1920
- - **Burning Type**: {'Fine-tuning' if has_dataset else 'Zero-shot'}
1921
- - **Hierarchical**: {use_hierarchical}
1922
-
1923
- ## 📊 Metrics
1924
- - **Conversion Rate**: {result.get('conversion_rate', 0)*100:.1f}%
1925
- - **Quality Score**: {result.get('quality_score', 0):.2f}/1.00
1926
- """
1927
-
1928
- if 'training_steps' in result:
1929
- output_md += f"""
1930
- ## 🚀 Training
1931
- - **Steps**: {result['training_steps']}
1932
- - **Final Loss**: {result.get('final_loss', 0.0):.4f}
1933
- """
1934
-
1935
- output_md += f"""
1936
- ## ⏱️ Time Breakdown
1937
- - **Total**: {result.get('total_time', 0):.1f}s
1938
- """
1939
-
1940
- if 'load_time' in result:
1941
- output_md += f"- **Load**: {result['load_time']:.1f}s\n"
1942
- output_md += f"- **Convert**: {result['convert_time']:.1f}s\n"
1943
- output_md += f"- **Evaluate**: {result['eval_time']:.1f}s\n"
1944
- output_md += f"- **Save**: {result['save_time']:.1f}s\n"
1945
-
1946
- # Hub Upload 상태
1947
- output_md += f"""
1948
- ---
1949
-
1950
- ## 🌐 HuggingFace Hub Upload
1951
-
1952
- **Status**: {upload_status}
1953
- """
1954
-
1955
- if hub_url:
1956
- output_md += f"""
1957
- **Model URL**: [{hub_url}]({hub_url})
1958
- **Privacy**: {'🔒 Private' if hub_private else '🌍 Public'}
1959
- **Verification**: {'✅ Passed' if verification_passed else '⚠️ Not verified'}
1960
-
1961
- ### 🚀 Load from Hub
1962
- ```python
1963
- from transformers import AutoModelForCausalLM, AutoTokenizer
1964
-
1965
- # ⚠️ MUST use trust_remote_code=True
1966
- model = AutoModelForCausalLM.from_pretrained(
1967
- "{hub_url.replace('https://huggingface.co/', '')}",
1968
- trust_remote_code=True, # Required!
1969
- torch_dtype="auto",
1970
- device_map="auto"
1971
- )
1972
- tokenizer = AutoTokenizer.from_pretrained(
1973
- "{hub_url.replace('https://huggingface.co/', '')}"
1974
- )
1975
-
1976
- # Generate
1977
- inputs = tokenizer("Your prompt here", return_tensors="pt")
1978
- outputs = model.generate(**inputs, max_new_tokens=50)
1979
- print(tokenizer.decode(outputs[0], skip_special_tokens=True))
1980
- ```
1981
- """
1982
- elif upload_to_hub:
1983
- output_md += f"""
1984
- **Upload failed!** Check logs for details.
1985
-
1986
- 💡 **Troubleshooting:**
1987
- 1. Ensure `HF_TOKEN` environment variable is set
1988
- 2. Check token permissions (write access required)
1989
- 3. Verify network connectivity
1990
- 4. Review error messages above
1991
- """
1992
-
1993
- output_md += f"""
1994
- ---
1995
-
1996
- ## 🎯 Local Usage
1997
- ```python
1998
- from transformers import AutoModelForCausalLM, AutoTokenizer
1999
-
2000
- # Load from local path
2001
- model = AutoModelForCausalLM.from_pretrained(
2002
- "{result['model_path']}",
2003
- trust_remote_code=True # Important!
2004
- )
2005
- tokenizer = AutoTokenizer.from_pretrained("{result['model_path']}")
2006
-
2007
- # Generate
2008
- inputs = tokenizer("Your prompt", return_tensors="pt")
2009
- outputs = model.generate(**inputs, max_new_tokens=50)
2010
- print(tokenizer.decode(outputs[0], skip_special_tokens=True))
2011
- ```
2012
-
2013
- ---
2014
-
2015
- ✅ **PHOENIX Model Ready!**
2016
-
2017
- {'📤 Model uploaded to HuggingFace Hub' if hub_url else '💾 Model saved locally'}
2018
- """
2019
-
2020
- # 플롯 생성
2021
- fig = go.Figure()
2022
-
2023
- metrics_names = ['Conversion', 'Quality']
2024
- metrics_values = [result.get('conversion_rate', 0), result.get('quality_score', 0)]
2025
- metrics_text = [
2026
- f"{result.get('conversion_rate', 0)*100:.1f}%",
2027
- f"{result.get('quality_score', 0):.2f}"
2028
- ]
2029
-
2030
- if verification_passed:
2031
- metrics_names.append('Upload')
2032
- metrics_values.append(1.0)
2033
- metrics_text.append('✅')
2034
-
2035
- fig.add_trace(go.Bar(
2036
- x=metrics_names,
2037
- y=metrics_values,
2038
- text=metrics_text,
2039
- textposition='auto',
2040
- marker_color=['#3b82f6', '#10b981', '#8b5cf6'][:len(metrics_names)]
2041
- ))
2042
-
2043
- fig.update_layout(
2044
- title="🔥 Burning Metrics",
2045
- yaxis_range=[0, 1],
2046
- template='plotly_white',
2047
- height=400
2048
- )
2049
-
2050
- print(f"\n{'='*80}")
2051
- print(f"✅ PHOENIX MODEL BURNING COMPLETE!")
2052
- print(f"{'='*80}\n")
2053
-
2054
- return output_md, fig
2055
-
2056
- except Exception as e:
2057
- import traceback
2058
- error_msg = traceback.format_exc()
2059
-
2060
- print(f"\n{'='*80}")
2061
- print(f"❌ BURNING FAILED")
2062
- print(f"{'='*80}")
2063
- print(f"{error_msg}")
2064
- print(f"{'='*80}\n")
2065
-
2066
- return f"""
2067
- ❌ **Burning Failed**
2068
-
2069
- **Error:** {str(e)}
2070
-
2071
- **Full Traceback:**
2072
- ```
2073
- {error_msg}
2074
- ```
2075
-
2076
- **Troubleshooting:**
2077
- 1. Check model URL is valid
2078
- 2. Ensure sufficient disk space
2079
- 3. Verify GPU availability
2080
- 4. Check logs above for details
2081
- """, None
2082
-
2083
-
2084
- # =====================================================
2085
- # 모델 버닝 (Zero-shot + Optional Fine-tuning)
2086
- # =====================================================
2087
-
2088
- def evaluate_model_quality(model, tokenizer, test_prompts=None):
2089
- """간단한 모델 품질 평가"""
2090
- if test_prompts is None:
2091
- test_prompts = [
2092
- "The capital of France is",
2093
- "In machine learning, overfitting means",
2094
- "2 + 2 =",
2095
- ]
2096
-
2097
- model.eval()
2098
- scores = []
2099
-
2100
- with torch.no_grad():
2101
- for prompt in test_prompts:
2102
- try:
2103
- inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
2104
- outputs = model.generate(
2105
- **inputs,
2106
- max_new_tokens=20,
2107
- do_sample=False,
2108
- pad_token_id=tokenizer.eos_token_id,
2109
- )
2110
- generated = tokenizer.decode(outputs[0], skip_special_tokens=True)
2111
-
2112
- score = 0.0
2113
- if len(generated) > len(prompt):
2114
- score += 0.3
2115
- if not any(char in generated[len(prompt):] for char in ['�', '[UNK]']):
2116
- score += 0.3
2117
- if len(generated.split()) > len(prompt.split()) + 2:
2118
- score += 0.4
2119
-
2120
- scores.append(score)
2121
- except Exception as e:
2122
- print(f" ⚠️ Evaluation error for '{prompt}': {e}")
2123
- scores.append(0.0)
2124
-
2125
- return sum(scores) / len(scores) if scores else 0.0
2126
-
2127
-
2128
- def burn_model_zero_shot(
2129
- model_url: str,
2130
- output_dir: str,
2131
- use_hierarchical: bool = True,
2132
- test_prompts: List[str] = None,
2133
- ):
2134
- """Zero-shot Model Burning with Custom Code"""
2135
- print("="*80)
2136
- print("🔥 PHOENIX Zero-shot Model Burning")
2137
- print("="*80)
2138
-
2139
- output_path = Path(output_dir)
2140
- output_path.mkdir(parents=True, exist_ok=True)
2141
-
2142
- try:
2143
- # 1. Load model
2144
- print(f"\n📥 Loading model: {model_url}")
2145
- start_time = time.time()
2146
-
2147
- config = AutoConfig.from_pretrained(model_url, trust_remote_code=True)
2148
- model = AutoModelForCausalLM.from_pretrained(
2149
- model_url,
2150
- trust_remote_code=True,
2151
- torch_dtype=torch.float16,
2152
- ).to(DEVICE)
2153
-
2154
- tokenizer = AutoTokenizer.from_pretrained(model_url, trust_remote_code=True)
2155
- if tokenizer.pad_token is None:
2156
- tokenizer.pad_token = tokenizer.eos_token
2157
-
2158
- load_time = time.time() - start_time
2159
- print(f"✅ Loaded in {load_time:.1f}s")
2160
-
2161
- # 2. Convert
2162
- print(f"\n🔄 Converting Attention → Retention...")
2163
- convert_start = time.time()
2164
-
2165
- model.model, converted, total = replace_attention_with_retention(
2166
- model.model,
2167
- use_hierarchical=use_hierarchical
2168
- )
2169
-
2170
- convert_time = time.time() - convert_start
2171
- conversion_rate = converted / total if total > 0 else 0
2172
-
2173
- print(f"✅ Converted {converted}/{total} layers ({conversion_rate*100:.1f}%) in {convert_time:.1f}s")
2174
 
2175
  # 3. Evaluate
2176
  print(f"\n📊 Evaluating model quality...")
@@ -2508,22 +1979,52 @@ def burn_phoenix_model_ui(
2508
  hub_private,
2509
  ):
2510
  """Gradio UI용 모델 버닝 함수"""
 
 
 
 
 
2511
  try:
 
2512
  if not model_url.strip():
2513
- return "⚠️ Model URL required", None
2514
 
2515
  if not output_name.strip():
2516
  output_name = f"phoenix_{model_url.split('/')[-1]}_{int(time.time())}"
2517
 
2518
  output_dir = f"{MODELS_PATH}/{output_name}"
2519
 
 
 
 
 
 
 
 
2520
  has_dataset = dataset_path and dataset_path.strip() and Path(dataset_path).exists()
2521
 
2522
  if use_finetuning and not has_dataset:
2523
- return "⚠️ Fine-tuning requires dataset path", None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2524
 
2525
- # Burning
 
2526
  if use_finetuning and has_dataset:
 
2527
  result = burn_model_with_finetuning(
2528
  model_url=model_url,
2529
  output_dir=output_dir,
@@ -2535,155 +2036,249 @@ def burn_phoenix_model_ui(
2535
  max_steps=max_steps,
2536
  )
2537
  else:
 
2538
  result = burn_model_zero_shot(
2539
  model_url=model_url,
2540
  output_dir=output_dir,
2541
  use_hierarchical=use_hierarchical,
2542
  )
2543
 
2544
- if result['status'] == 'success':
2545
- hub_url = None
2546
- verification_passed = False
2547
-
2548
- # Upload to Hub with verification
2549
- if upload_to_hub:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2550
  success, hub_url, upload_msg = upload_to_huggingface_hub(
2551
  model_path=result['model_path'],
2552
  original_model_url=model_url,
2553
  repo_name=hub_repo_name if hub_repo_name.strip() else None,
2554
  private=hub_private,
2555
- skip_verification=False # 검증 활성화!
2556
  )
2557
 
2558
  verification_passed = success
2559
 
2560
- if not success:
2561
- print(f"\n{upload_msg}")
2562
-
2563
- # Save to DB
2564
- burning_info = {
2565
- 'model_url': model_url,
2566
- 'output_path': result['model_path'],
2567
- 'hub_url': hub_url,
2568
- 'use_hierarchical': use_hierarchical,
2569
- 'dataset_used': has_dataset,
2570
- 'conversion_rate': result.get('conversion_rate', 0.0),
2571
- 'training_steps': result.get('training_steps', 0),
2572
- 'final_loss': result.get('final_loss'),
2573
- 'evaluation_score': result.get('quality_score', 0.0),
2574
- 'verification_passed': verification_passed,
2575
- }
2576
-
2577
- db.save_burning(burning_info)
2578
-
2579
- # Format output
2580
- output_md = f"""
 
 
 
 
 
 
 
 
2581
  # 🔥 Model Burning Complete!
2582
 
2583
  ## 📦 Model Information
2584
- - **Original**: {model_url}
2585
- - **Output**: `{result['model_path']}`
2586
- - **Type**: {'Fine-tuning' if has_dataset else 'Zero-shot'}
 
 
 
 
 
2587
  """
2588
-
2589
- if hub_url:
2590
- output_md += f"""
2591
- ## 🌐 HuggingFace Hub
2592
- - **URL**: [{hub_url}]({hub_url})
2593
- - **Private**: {hub_private}
2594
- - **Status**: ✅ Uploaded & Verified
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2595
 
2596
  ### 🚀 Load from Hub
2597
  ```python
2598
  from transformers import AutoModelForCausalLM, AutoTokenizer
2599
 
2600
- # ⚠️ CRITICAL: Must use trust_remote_code=True
2601
  model = AutoModelForCausalLM.from_pretrained(
2602
  "{hub_url.replace('https://huggingface.co/', '')}",
2603
  trust_remote_code=True, # Required!
2604
  torch_dtype="auto",
2605
  device_map="auto"
2606
  )
2607
- tokenizer = AutoTokenizer.from_pretrained("{hub_url.replace('https://huggingface.co/', '')}")
 
 
2608
 
2609
  # Generate
2610
- inputs = tokenizer("Your prompt", return_tensors="pt")
2611
  outputs = model.generate(**inputs, max_new_tokens=50)
2612
- print(tokenizer.decode(outputs[0]))
2613
  ```
2614
  """
2615
- elif upload_to_hub:
2616
- output_md += f"""
2617
- ## 🌐 HuggingFace Hub
2618
- - **Status**: ❌ Upload/Verification failed (check logs)
2619
- """
2620
-
2621
- output_md += f"""
2622
- ## 📊 Metrics
2623
- - **Conversion Rate**: {result['conversion_rate']*100:.1f}%
2624
- - **Quality Score**: {result.get('quality_score', 0.0):.2f}/1.00
2625
- - **Verification**: {'✅ Passed' if verification_passed else '⚠️ Not verified'}
2626
- """
2627
-
2628
- if 'training_steps' in result:
2629
- output_md += f"""
2630
- ## 🚀 Training
2631
- - **Steps**: {result['training_steps']}
2632
- - **Final Loss**: {result.get('final_loss', 0.0):.4f}
2633
- """
2634
-
2635
  output_md += f"""
2636
- ## ⏱️ Time Breakdown
2637
- - **Total**: {result.get('total_time', 0):.1f}s
 
 
 
 
 
2638
  """
2639
-
2640
- if 'load_time' in result:
2641
- output_md += f"- **Load**: {result['load_time']:.1f}s\n"
2642
- output_md += f"- **Convert**: {result['convert_time']:.1f}s\n"
2643
- output_md += f"- **Evaluate**: {result['eval_time']:.1f}s\n"
2644
- output_md += f"- **Save**: {result['save_time']:.1f}s\n"
2645
-
2646
- output_md += f"""
2647
  ## 🎯 Local Usage
2648
  ```python
2649
  from transformers import AutoModelForCausalLM, AutoTokenizer
2650
 
 
2651
  model = AutoModelForCausalLM.from_pretrained(
2652
  "{result['model_path']}",
2653
  trust_remote_code=True # Important!
2654
  )
2655
  tokenizer = AutoTokenizer.from_pretrained("{result['model_path']}")
2656
 
 
2657
  inputs = tokenizer("Your prompt", return_tensors="pt")
2658
  outputs = model.generate(**inputs, max_new_tokens=50)
2659
- print(tokenizer.decode(outputs[0]))
2660
  ```
2661
 
2662
- ✅ **PHOENIX Model Ready with Custom Code & Verification!**
 
 
 
 
2663
  """
2664
-
2665
- # Plot
2666
- fig = go.Figure()
2667
- fig.add_trace(go.Bar(
2668
- x=['Conversion', 'Quality', 'Verification'],
2669
- y=[result['conversion_rate'], result.get('quality_score', 0.0), 1.0 if verification_passed else 0.0],
2670
- text=[f"{result['conversion_rate']*100:.1f}%", f"{result.get('quality_score', 0.0):.2f}", '✅' if verification_passed else '❌'],
2671
- textposition='auto',
2672
- ))
2673
- fig.update_layout(
2674
- title="Burning Metrics",
2675
- yaxis_range=[0, 1],
2676
- template='plotly_white'
2677
- )
2678
-
2679
- return output_md, fig
2680
-
2681
- else:
2682
- return f"❌ Burning failed:\n```\n{result.get('error', 'Unknown error')}\n```", None
2683
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2684
  except Exception as e:
2685
  import traceback
2686
- return f"❌ Error:\n```\n{traceback.format_exc()}\n```", None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2687
 
2688
 
2689
  def view_burning_history():
@@ -2971,7 +2566,7 @@ with gr.Blocks(
2971
  ✅ O(n) Complexity
2972
  ✅ Auto Upload to HuggingFace Hub
2973
  ✅ Custom Code for Proper Loading
2974
- ✅ Pre-upload Verification (NEW!)
2975
 
2976
  ---
2977
  """)
@@ -3012,8 +2607,8 @@ with gr.Blocks(
3012
  - **Zero-shot**: 데이터셋 없이 변환만 수행 (빠름!)
3013
  - **Fine-tuning**: 데이터셋으로 추가 학습 (성능 향상)
3014
  - **HuggingFace Hub**: 자동으로 Hub에 업로드 (Private 기본)
3015
- - **Custom Code**: modeling_phoenix.py 자동 생성 (trust_remote_code=True)
3016
- - **Pre-upload Verification**: 업로드 전 Retention 동작 확인 (NEW!)
3017
  """)
3018
 
3019
  with gr.Row():
@@ -3040,7 +2635,7 @@ with gr.Blocks(
3040
 
3041
  burn_hub_repo = gr.Textbox(
3042
  label="📦 Hub Repository Name (optional)",
3043
- placeholder="phoenix-granite-350m (auto-generated if empty)"
3044
  )
3045
 
3046
  burn_hub_private = gr.Checkbox(
@@ -3053,7 +2648,7 @@ with gr.Blocks(
3053
 
3054
  burn_dataset = gr.Textbox(
3055
  label="📁 Dataset Path (Optional)",
3056
- placeholder="/path/to/dataset.txt (leave empty for zero-shot)",
3057
  value=""
3058
  )
3059
 
@@ -3148,13 +2743,6 @@ with gr.Blocks(
3148
  ### 🧪 PHOENIX 모델 검증
3149
 
3150
  배포된 PHOENIX 모델을 로드하고 품질을 검증합니다.
3151
-
3152
- - **HuggingFace Hub**: 공개/비공개 모델 로드
3153
- - **Local Path**: 로컬 저장 모델 로드
3154
- - **Generation Test**: 실제 텍스트 생성 테스트
3155
- - **Retention Verification**: PHOENIX 메커니즘 확인
3156
-
3157
- ⚠️ **Important**: Use `trust_remote_code=True` when loading PHOENIX models!
3158
  """)
3159
 
3160
  with gr.Row():
@@ -3168,38 +2756,25 @@ with gr.Blocks(
3168
  val_path = gr.Textbox(
3169
  label="🔗 Model Path/URL",
3170
  value="seawolf2357/phoenix-granite-4.0-h-350m",
3171
- placeholder="seawolf2357/phoenix-granite-4.0-h-350m or /data/phoenix_models/..."
3172
  )
3173
 
3174
  val_prompts = gr.Textbox(
3175
  label="📝 Test Prompts (one per line)",
3176
  lines=5,
3177
  value="The future of AI is\nOnce upon a time\nIn machine learning,",
3178
- placeholder="Enter test prompts..."
3179
  )
3180
 
3181
  with gr.Row():
3182
- val_max_tokens = gr.Slider(
3183
- 16, 256, 64,
3184
- step=16,
3185
- label="Max Tokens"
3186
- )
3187
- val_temp = gr.Slider(
3188
- 0.1, 2.0, 0.7,
3189
- step=0.1,
3190
- label="Temperature"
3191
- )
3192
 
3193
  val_verify_retention = gr.Checkbox(
3194
  value=True,
3195
  label="🔍 Verify Retention Mechanism"
3196
  )
3197
 
3198
- val_btn = gr.Button(
3199
- "🧪 Validate Model",
3200
- variant="primary",
3201
- size="lg"
3202
- )
3203
 
3204
  with gr.Column(scale=2):
3205
  val_output = gr.Markdown()
@@ -3211,54 +2786,22 @@ with gr.Blocks(
3211
  val_temp, val_verify_retention],
3212
  [val_output, val_plot]
3213
  )
3214
-
3215
- gr.Markdown("""
3216
- ---
3217
-
3218
- ### 💡 Quick Validation
3219
-
3220
- 1. Select **"hub"** as source
3221
- 2. Enter model URL (e.g., `seawolf2357/phoenix-granite-4.0-h-350m`)
3222
- 3. Click **"Validate Model"**
3223
- 4. Check generation quality and Retention verification!
3224
-
3225
- **Example prompts:**
3226
- - `The future of AI is`
3227
- - `Once upon a time`
3228
- - `In machine learning,`
3229
- - `Explain quantum computing`
3230
- """)
3231
 
3232
  gr.Markdown(f"""
3233
  ---
3234
 
3235
- ## 🔥 PHOENIX Model Burning v1.1
3236
 
3237
- ### What's New in v1.1
3238
- - ✅ auto_map configuration (proper model loading)
3239
- - ✅ PreTrainedModel base classes
3240
- - ✅ Pre-upload verification (Retention + Generation quality)
3241
- - ✅ Enhanced error handling
3242
-
3243
- ### Zero-shot (데이터셋 불필요!)
3244
- 1. 모델 URL 입력
3245
- 2. "Upload to HuggingFace Hub" 체크 (기본 Private)
3246
- 3. "Burn Model" 클릭
3247
- 4. 자동 검증 → 통과 시 Hub 업로드!
3248
-
3249
- ### Loading PHOENIX Models
3250
- ```python
3251
- from transformers import AutoModelForCausalLM
3252
-
3253
- # ⚠️ trust_remote_code=True 필수!
3254
- model = AutoModelForCausalLM.from_pretrained(
3255
- "your-username/phoenix-model",
3256
- trust_remote_code=True, # Required!
3257
- torch_dtype="auto"
3258
- )
3259
- ```
3260
 
3261
- **HuggingFace Token Status**: {'✅ Connected' if HF_TOKEN else '❌ Not Found (set HF_TOKEN env)'}
3262
 
3263
  **VIDraft AI Research Lab** | PHOENIX v1.1
3264
  """)
 
455
 
456
 
457
  # =====================================================
458
+ # Custom Modeling Code 생성
459
  # =====================================================
460
 
461
  def generate_modeling_phoenix_code():
 
868
 
869
  # Auto-registration
870
  AutoConfig.register("phoenix", PhoenixConfig)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
871
  '''
872
 
873
  return modeling_code
874
 
875
 
876
  # =====================================================
877
+ # 저장 함수
878
  # =====================================================
879
 
880
  def save_phoenix_model_with_code(model, tokenizer, output_path, original_model_url, metadata):
 
910
  config_dict["original_model"] = original_model_url
911
  config_dict["use_hierarchical"] = metadata.get('use_hierarchical', True)
912
 
913
+ # auto_map 설정
914
  config_dict["auto_map"] = {
 
915
  "AutoModelForCausalLM": "modeling_phoenix.PhoenixModelForCausalLM",
916
  }
917
 
 
1046
 
1047
 
1048
  # =====================================================
1049
+ # 업로드 전 검증 함수
 
 
 
 
1050
  # =====================================================
1051
 
1052
  def verify_phoenix_model_before_upload(model_path: str) -> Tuple[bool, str, Dict]:
1053
  """
1054
+ Upload 전 PHOENIX 모델 검증
1055
 
1056
  Returns:
1057
  (success, message, metrics)
 
1059
  print("\n🧪 Pre-upload Verification...")
1060
 
1061
  try:
 
1062
  model_path = Path(model_path)
1063
 
1064
+ # 파일 존재 확인 ( 번만)
1065
+ file_checks = {
1066
+ 'config': (model_path / 'config.json').exists(),
1067
+ 'modeling': (model_path / 'modeling_phoenix.py').exists(),
1068
+ 'readme': (model_path / 'README.md').exists(),
1069
+ 'safetensors': (model_path / 'model.safetensors').exists(),
1070
+ 'pytorch_bin': (model_path / 'pytorch_model.bin').exists(),
1071
+ }
1072
 
1073
+ model_weights_exist = file_checks['safetensors'] or file_checks['pytorch_bin']
 
 
 
1074
 
1075
  print(f" 📄 File Check:")
1076
+ print(f" config.json: {'✅' if file_checks['config'] else '❌'}")
1077
+ print(f" modeling_phoenix.py: {'✅' if file_checks['modeling'] else '❌'}")
1078
+ print(f" README.md: {'✅' if file_checks['readme'] else '❌'}")
1079
+ print(f" model weights: {'✅ (safetensors)' if file_checks['safetensors'] else '✅ (pytorch_model.bin)' if file_checks['pytorch_bin'] else '❌'}")
1080
 
1081
+ if not file_checks['config']:
1082
  return False, "❌ Missing file: config.json", {}
1083
+ if not file_checks['modeling']:
1084
  return False, "❌ Missing file: modeling_phoenix.py", {}
1085
+ if not file_checks['readme']:
1086
  return False, "❌ Missing file: README.md", {}
1087
  if not model_weights_exist:
1088
+ return False, "❌ Missing model weights", {}
1089
 
1090
  print(" ✅ All required files present")
1091
 
1092
+ # Config 검증
1093
  with open(model_path / 'config.json', 'r') as f:
1094
  config = json.load(f)
1095
 
 
1101
 
1102
  print(" ✅ Config validated")
1103
 
1104
+ # 모델 로딩 테스트
1105
  print(" 🔄 Testing model loading...")
1106
 
1107
  try:
 
1120
  print(f" ⚠️ Model loading warning: {e}")
1121
  print(f" Continuing with basic checks...")
1122
 
 
1123
  metrics = {
1124
  'retention_layers': -1,
1125
  'total_layers': -1,
1126
+ 'retention_rate': 1.0,
1127
+ 'generation_quality': 0.8,
1128
+ 'model_format': 'safetensors' if file_checks['safetensors'] else 'pytorch_bin',
1129
  'verification_mode': 'file_only'
1130
  }
1131
 
1132
  print(" ✅ File-based verification passed")
1133
  return True, "✅ File checks passed (model loading skipped)", metrics
1134
 
1135
+ # Retention 검증
1136
  print(" 🔍 Verifying Retention layers...")
1137
 
1138
  retention_count = 0
 
1141
 
1142
  # 여러 가능한 구조 탐색
1143
  if hasattr(model, '_original_model'):
 
1144
  actual_model = model._original_model
1145
  if hasattr(actual_model, 'model') and hasattr(actual_model.model, 'layers'):
1146
  layers = actual_model.model.layers
1147
  elif hasattr(model, 'model') and hasattr(model.model, 'layers'):
 
1148
  layers = model.model.layers
1149
  elif hasattr(model, 'transformer') and hasattr(model.transformer, 'h'):
 
1150
  layers = model.transformer.h
1151
  elif hasattr(model, 'layers'):
 
1152
  layers = model.layers
1153
 
1154
  if layers is not None:
 
1165
  retention_rate = retention_count / total_layers if total_layers > 0 else 0
1166
  print(f" ✅ Retention layers: {retention_count}/{total_layers} ({retention_rate*100:.1f}%)")
1167
  else:
 
1168
  print(f" ⚠️ Could not verify layer structure (custom architecture)")
1169
  print(f" ✅ Files are valid, proceeding...")
1170
 
 
1173
  'total_layers': -1,
1174
  'retention_rate': 1.0,
1175
  'generation_quality': 0.8,
1176
+ 'model_format': 'safetensors' if file_checks['safetensors'] else 'pytorch_bin',
1177
  'verification_mode': 'file_only'
1178
  }
1179
 
1180
  return True, "✅ File checks passed (layer verification skipped)", metrics
1181
 
 
1182
  if retention_count == 0:
1183
  print(f" ⚠️ No Retention layers detected in loaded model")
1184
  print(f" ⚠️ This may be normal if custom code hasn't loaded yet")
 
1189
  'total_layers': total_layers,
1190
  'retention_rate': 0.0,
1191
  'generation_quality': 0.7,
1192
+ 'model_format': 'safetensors' if file_checks['safetensors'] else 'pytorch_bin',
1193
  'verification_mode': 'file_only'
1194
  }
1195
 
1196
  return True, "✅ File checks passed (Retention will load on Hub)", metrics
1197
 
1198
+ # 생성 테스트
1199
  if retention_count > 0:
1200
  print(" 🚀 Testing generation...")
1201
 
 
1218
 
1219
  # 품질 점수
1220
  score = 0.0
 
 
1221
  if len(generated) > len(prompt):
1222
  score += 0.3
1223
 
 
1224
  weird_tokens = ['�', '[UNK]', 'priv', 'Brah', '__,__']
1225
  if not any(token in generated for token in weird_tokens):
1226
  score += 0.4
1227
 
 
1228
  if len(generated.split()) > len(prompt.split()) + 3:
1229
  score += 0.3
1230
 
 
1241
  avg_score = sum(generation_scores) / len(generation_scores) if generation_scores else 0.0
1242
  print(f" ✅ Generation quality: {avg_score:.2f}/1.00")
1243
  else:
1244
+ avg_score = 0.7
1245
 
1246
+ # 최종 검증 통과
1247
  metrics = {
1248
  'retention_layers': retention_count,
1249
  'total_layers': total_layers,
1250
  'retention_rate': retention_rate if total_layers > 0 else 0.0,
1251
  'generation_quality': avg_score,
1252
+ 'model_format': 'safetensors' if file_checks['safetensors'] else 'pytorch_bin',
1253
  'verification_mode': 'full' if retention_count > 0 else 'file_only'
1254
  }
1255
 
 
1261
  import traceback
1262
  error_msg = traceback.format_exc()
1263
 
 
1264
  print(f"\n⚠️ Verification exception: {str(e)}")
1265
  print(f" Checking files only...")
1266
 
1267
  model_path = Path(model_path)
1268
+ file_checks = {
1269
+ 'config': (model_path / 'config.json').exists(),
1270
+ 'modeling': (model_path / 'modeling_phoenix.py').exists(),
1271
+ 'safetensors': (model_path / 'model.safetensors').exists(),
1272
+ 'pytorch_bin': (model_path / 'pytorch_model.bin').exists(),
1273
+ }
1274
 
1275
+ if file_checks['config'] and file_checks['modeling'] and (file_checks['safetensors'] or file_checks['pytorch_bin']):
1276
  print(f" ✅ Essential files present, proceeding...")
1277
 
1278
  metrics = {
 
1280
  'total_layers': -1,
1281
  'retention_rate': 1.0,
1282
  'generation_quality': 0.7,
1283
+ 'model_format': 'safetensors' if file_checks['safetensors'] else 'pytorch_bin',
1284
  'verification_mode': 'minimal'
1285
  }
1286
 
 
1290
 
1291
 
1292
  # =====================================================
1293
+ # HuggingFace Hub Upload
1294
  # =====================================================
1295
 
1296
  def upload_to_huggingface_hub(
 
1390
  print(f"\n📤 Uploading files to HuggingFace Hub...")
1391
  print(f" This may take a few minutes depending on model size...")
1392
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1393
  try:
1394
  api.upload_folder(
1395
  folder_path=str(model_path),
 
1552
  return [dict(row) for row in cursor.fetchall()]
1553
 
1554
 
 
 
 
1555
  # =====================================================
1556
+ # 모델 버닝 함수
1557
  # =====================================================
1558
 
1559
+ def evaluate_model_quality(model, tokenizer, test_prompts=None):
1560
+ """간단한 모델 품질 평가"""
1561
+ if test_prompts is None:
1562
+ test_prompts = [
1563
+ "The capital of France is",
1564
+ "In machine learning, overfitting means",
1565
+ "2 + 2 =",
1566
+ ]
 
 
 
 
 
 
 
1567
 
1568
+ model.eval()
1569
+ scores = []
1570
+
1571
+ with torch.no_grad():
1572
+ for prompt in test_prompts:
1573
+ try:
1574
+ inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
1575
+ outputs = model.generate(
1576
+ **inputs,
1577
+ max_new_tokens=20,
1578
+ do_sample=False,
1579
+ pad_token_id=tokenizer.eos_token_id,
1580
+ )
1581
+ generated = tokenizer.decode(outputs[0], skip_special_tokens=True)
1582
+
1583
+ score = 0.0
1584
+ if len(generated) > len(prompt):
1585
+ score += 0.3
1586
+ if not any(char in generated[len(prompt):] for char in ['�', '[UNK]']):
1587
+ score += 0.3
1588
+ if len(generated.split()) > len(prompt.split()) + 2:
1589
+ score += 0.4
1590
+
1591
+ scores.append(score)
1592
+ except Exception as e:
1593
+ print(f" ⚠️ Evaluation error for '{prompt}': {e}")
1594
+ scores.append(0.0)
1595
+
1596
+ return sum(scores) / len(scores) if scores else 0.0
1597
+
1598
+
1599
+ def burn_model_zero_shot(
1600
+ model_url: str,
1601
+ output_dir: str,
1602
+ use_hierarchical: bool = True,
1603
+ test_prompts: List[str] = None,
1604
+ ):
1605
+ """Zero-shot Model Burning with Custom Code"""
1606
+ print("="*80)
1607
+ print("🔥 PHOENIX Zero-shot Model Burning")
1608
  print("="*80)
1609
 
1610
+ output_path = Path(output_dir)
1611
+ output_path.mkdir(parents=True, exist_ok=True)
1612
+
1613
  try:
1614
+ # 1. Load model
1615
+ print(f"\n📥 Loading model: {model_url}")
1616
+ start_time = time.time()
1617
 
1618
+ config = AutoConfig.from_pretrained(model_url, trust_remote_code=True)
1619
+ model = AutoModelForCausalLM.from_pretrained(
1620
+ model_url,
1621
+ trust_remote_code=True,
1622
+ torch_dtype=torch.float16,
1623
+ ).to(DEVICE)
1624
 
1625
+ tokenizer = AutoTokenizer.from_pretrained(model_url, trust_remote_code=True)
1626
+ if tokenizer.pad_token is None:
1627
+ tokenizer.pad_token = tokenizer.eos_token
1628
 
1629
+ load_time = time.time() - start_time
1630
+ print(f" Loaded in {load_time:.1f}s")
 
 
 
 
1631
 
1632
+ # 2. Convert
1633
+ print(f"\n🔄 Converting Attention → Retention...")
1634
+ convert_start = time.time()
1635
 
1636
+ model.model, converted, total = replace_attention_with_retention(
1637
+ model.model,
1638
+ use_hierarchical=use_hierarchical
1639
+ )
1640
 
1641
+ convert_time = time.time() - convert_start
1642
+ conversion_rate = converted / total if total > 0 else 0
 
 
 
 
 
 
 
 
 
 
 
 
1643
 
1644
+ print(f"✅ Converted {converted}/{total} layers ({conversion_rate*100:.1f}%) in {convert_time:.1f}s")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1645
 
1646
  # 3. Evaluate
1647
  print(f"\n📊 Evaluating model quality...")
 
1979
  hub_private,
1980
  ):
1981
  """Gradio UI용 모델 버닝 함수"""
1982
+
1983
+ print("\n" + "="*80)
1984
+ print("🔥 PHOENIX MODEL BURNING START")
1985
+ print("="*80)
1986
+
1987
  try:
1988
+ # 입력 검증
1989
  if not model_url.strip():
1990
+ return "⚠️ Model URL is required", None
1991
 
1992
  if not output_name.strip():
1993
  output_name = f"phoenix_{model_url.split('/')[-1]}_{int(time.time())}"
1994
 
1995
  output_dir = f"{MODELS_PATH}/{output_name}"
1996
 
1997
+ print(f"📋 Configuration:")
1998
+ print(f" Model URL: {model_url}")
1999
+ print(f" Output Name: {output_name}")
2000
+ print(f" Output Dir: {output_dir}")
2001
+ print(f" Hierarchical: {use_hierarchical}")
2002
+ print(f" Upload to Hub: {upload_to_hub}")
2003
+
2004
  has_dataset = dataset_path and dataset_path.strip() and Path(dataset_path).exists()
2005
 
2006
  if use_finetuning and not has_dataset:
2007
+ return "⚠️ Fine-tuning requires a valid dataset path", None
2008
+
2009
+ # HF Token 확인
2010
+ if upload_to_hub and not HF_TOKEN:
2011
+ warning_msg = """
2012
+ ⚠️ **HuggingFace Token Not Found!**
2013
+
2014
+ Model will be burned locally, but upload will fail.
2015
+
2016
+ To enable upload:
2017
+ 1. Set `HF_TOKEN` environment variable
2018
+ 2. Restart the application
2019
+
2020
+ Continuing with local burning only...
2021
+ """
2022
+ print(f"\n{warning_msg}")
2023
 
2024
+ # Burning 실행
2025
+ print(f"\n{'='*80}")
2026
  if use_finetuning and has_dataset:
2027
+ print("🚀 Starting Fine-tuning Burning...")
2028
  result = burn_model_with_finetuning(
2029
  model_url=model_url,
2030
  output_dir=output_dir,
 
2036
  max_steps=max_steps,
2037
  )
2038
  else:
2039
+ print("🚀 Starting Zero-shot Burning...")
2040
  result = burn_model_zero_shot(
2041
  model_url=model_url,
2042
  output_dir=output_dir,
2043
  use_hierarchical=use_hierarchical,
2044
  )
2045
 
2046
+ if result['status'] != 'success':
2047
+ error_msg = f"""
2048
+ **Burning Failed**
2049
+ ```
2050
+ {result.get('error', 'Unknown error')}
2051
+ ```
2052
+
2053
+ **Traceback:**
2054
+ ```
2055
+ {result.get('traceback', 'N/A')}
2056
+ ```
2057
+ """
2058
+ return error_msg, None
2059
+
2060
+ print(f"\n✅ Burning completed successfully!")
2061
+
2062
+ # HuggingFace Hub 업로드
2063
+ hub_url = None
2064
+ verification_passed = False
2065
+ upload_status = "Not attempted"
2066
+
2067
+ if upload_to_hub:
2068
+ if not HF_TOKEN:
2069
+ upload_status = "❌ Failed - No HF_TOKEN"
2070
+ print(f"\n{upload_status}")
2071
+ else:
2072
+ print(f"\n{'='*80}")
2073
+ print("📤 Starting HuggingFace Hub Upload...")
2074
+ print(f"{'='*80}")
2075
+
2076
  success, hub_url, upload_msg = upload_to_huggingface_hub(
2077
  model_path=result['model_path'],
2078
  original_model_url=model_url,
2079
  repo_name=hub_repo_name if hub_repo_name.strip() else None,
2080
  private=hub_private,
2081
+ skip_verification=False
2082
  )
2083
 
2084
  verification_passed = success
2085
 
2086
+ if success:
2087
+ upload_status = f"✅ Uploaded successfully to {hub_url}"
2088
+ print(f"\n{upload_status}")
2089
+ else:
2090
+ upload_status = f"❌ Upload failed\n\n{upload_msg}"
2091
+ print(f"\n{upload_status}")
2092
+ else:
2093
+ upload_status = "⏭️ Skipped (not requested)"
2094
+ print(f"\n📦 Hub upload: {upload_status}")
2095
+
2096
+ # 데이터베이스 저장
2097
+ burning_info = {
2098
+ 'model_url': model_url,
2099
+ 'output_path': result['model_path'],
2100
+ 'hub_url': hub_url,
2101
+ 'use_hierarchical': use_hierarchical,
2102
+ 'dataset_used': has_dataset,
2103
+ 'conversion_rate': result.get('conversion_rate', 0.0),
2104
+ 'training_steps': result.get('training_steps', 0),
2105
+ 'final_loss': result.get('final_loss'),
2106
+ 'evaluation_score': result.get('quality_score', 0.0),
2107
+ 'verification_passed': verification_passed,
2108
+ }
2109
+
2110
+ db.save_burning(burning_info)
2111
+ print(f"✅ Saved to database")
2112
+
2113
+ # 결과 포맷팅
2114
+ output_md = f"""
2115
  # 🔥 Model Burning Complete!
2116
 
2117
  ## 📦 Model Information
2118
+ - **Original Model**: {model_url}
2119
+ - **Output Path**: `{result['model_path']}`
2120
+ - **Burning Type**: {'Fine-tuning' if has_dataset else 'Zero-shot'}
2121
+ - **Hierarchical**: {use_hierarchical}
2122
+
2123
+ ## 📊 Metrics
2124
+ - **Conversion Rate**: {result.get('conversion_rate', 0)*100:.1f}%
2125
+ - **Quality Score**: {result.get('quality_score', 0):.2f}/1.00
2126
  """
2127
+
2128
+ if 'training_steps' in result:
2129
+ output_md += f"""
2130
+ ## 🚀 Training
2131
+ - **Steps**: {result['training_steps']}
2132
+ - **Final Loss**: {result.get('final_loss', 0.0):.4f}
2133
+ """
2134
+
2135
+ output_md += f"""
2136
+ ## ⏱️ Time Breakdown
2137
+ - **Total**: {result.get('total_time', 0):.1f}s
2138
+ """
2139
+
2140
+ if 'load_time' in result:
2141
+ output_md += f"- **Load**: {result['load_time']:.1f}s\n"
2142
+ output_md += f"- **Convert**: {result['convert_time']:.1f}s\n"
2143
+ output_md += f"- **Evaluate**: {result['eval_time']:.1f}s\n"
2144
+ output_md += f"- **Save**: {result['save_time']:.1f}s\n"
2145
+
2146
+ # Hub Upload 상태
2147
+ output_md += f"""
2148
+ ---
2149
+
2150
+ ## 🌐 HuggingFace Hub Upload
2151
+
2152
+ **Status**: {upload_status}
2153
+ """
2154
+
2155
+ if hub_url:
2156
+ output_md += f"""
2157
+ **Model URL**: [{hub_url}]({hub_url})
2158
+ **Privacy**: {'🔒 Private' if hub_private else '🌍 Public'}
2159
+ **Verification**: {'✅ Passed' if verification_passed else '⚠️ Not verified'}
2160
 
2161
  ### 🚀 Load from Hub
2162
  ```python
2163
  from transformers import AutoModelForCausalLM, AutoTokenizer
2164
 
2165
+ # ⚠️ MUST use trust_remote_code=True
2166
  model = AutoModelForCausalLM.from_pretrained(
2167
  "{hub_url.replace('https://huggingface.co/', '')}",
2168
  trust_remote_code=True, # Required!
2169
  torch_dtype="auto",
2170
  device_map="auto"
2171
  )
2172
+ tokenizer = AutoTokenizer.from_pretrained(
2173
+ "{hub_url.replace('https://huggingface.co/', '')}"
2174
+ )
2175
 
2176
  # Generate
2177
+ inputs = tokenizer("Your prompt here", return_tensors="pt")
2178
  outputs = model.generate(**inputs, max_new_tokens=50)
2179
+ print(tokenizer.decode(outputs[0], skip_special_tokens=True))
2180
  ```
2181
  """
2182
+ elif upload_to_hub:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2183
  output_md += f"""
2184
+ **Upload failed!** Check logs for details.
2185
+
2186
+ 💡 **Troubleshooting:**
2187
+ 1. Ensure `HF_TOKEN` environment variable is set
2188
+ 2. Check token permissions (write access required)
2189
+ 3. Verify network connectivity
2190
+ 4. Review error messages above
2191
  """
2192
+
2193
+ output_md += f"""
2194
+ ---
2195
+
 
 
 
 
2196
  ## 🎯 Local Usage
2197
  ```python
2198
  from transformers import AutoModelForCausalLM, AutoTokenizer
2199
 
2200
+ # Load from local path
2201
  model = AutoModelForCausalLM.from_pretrained(
2202
  "{result['model_path']}",
2203
  trust_remote_code=True # Important!
2204
  )
2205
  tokenizer = AutoTokenizer.from_pretrained("{result['model_path']}")
2206
 
2207
+ # Generate
2208
  inputs = tokenizer("Your prompt", return_tensors="pt")
2209
  outputs = model.generate(**inputs, max_new_tokens=50)
2210
+ print(tokenizer.decode(outputs[0], skip_special_tokens=True))
2211
  ```
2212
 
2213
+ ---
2214
+
2215
+ ✅ **PHOENIX Model Ready!**
2216
+
2217
+ {'📤 Model uploaded to HuggingFace Hub' if hub_url else '💾 Model saved locally'}
2218
  """
2219
+
2220
+ # 플롯 생성
2221
+ fig = go.Figure()
2222
+
2223
+ metrics_names = ['Conversion', 'Quality']
2224
+ metrics_values = [result.get('conversion_rate', 0), result.get('quality_score', 0)]
2225
+ metrics_text = [
2226
+ f"{result.get('conversion_rate', 0)*100:.1f}%",
2227
+ f"{result.get('quality_score', 0):.2f}"
2228
+ ]
2229
+
2230
+ if verification_passed:
2231
+ metrics_names.append('Upload')
2232
+ metrics_values.append(1.0)
2233
+ metrics_text.append('✅')
2234
+
2235
+ fig.add_trace(go.Bar(
2236
+ x=metrics_names,
2237
+ y=metrics_values,
2238
+ text=metrics_text,
2239
+ textposition='auto',
2240
+ marker_color=['#3b82f6', '#10b981', '#8b5cf6'][:len(metrics_names)]
2241
+ ))
2242
+
2243
+ fig.update_layout(
2244
+ title="🔥 Burning Metrics",
2245
+ yaxis_range=[0, 1],
2246
+ template='plotly_white',
2247
+ height=400
2248
+ )
2249
+
2250
+ print(f"\n{'='*80}")
2251
+ print(f"✅ PHOENIX MODEL BURNING COMPLETE!")
2252
+ print(f"{'='*80}\n")
2253
+
2254
+ return output_md, fig
2255
+
2256
  except Exception as e:
2257
  import traceback
2258
+ error_msg = traceback.format_exc()
2259
+
2260
+ print(f"\n{'='*80}")
2261
+ print(f"❌ BURNING FAILED")
2262
+ print(f"{'='*80}")
2263
+ print(f"{error_msg}")
2264
+ print(f"{'='*80}\n")
2265
+
2266
+ return f"""
2267
+ ❌ **Burning Failed**
2268
+
2269
+ **Error:** {str(e)}
2270
+
2271
+ **Full Traceback:**
2272
+ ```
2273
+ {error_msg}
2274
+ ```
2275
+
2276
+ **Troubleshooting:**
2277
+ 1. Check model URL is valid
2278
+ 2. Ensure sufficient disk space
2279
+ 3. Verify GPU availability
2280
+ 4. Check logs above for details
2281
+ """, None
2282
 
2283
 
2284
  def view_burning_history():
 
2566
  ✅ O(n) Complexity
2567
  ✅ Auto Upload to HuggingFace Hub
2568
  ✅ Custom Code for Proper Loading
2569
+ ✅ Pre-upload Verification
2570
 
2571
  ---
2572
  """)
 
2607
  - **Zero-shot**: 데이터셋 없이 변환만 수행 (빠름!)
2608
  - **Fine-tuning**: 데이터셋으로 추가 학습 (성능 향상)
2609
  - **HuggingFace Hub**: 자동으로 Hub에 업로드 (Private 기본)
2610
+ - **Custom Code**: modeling_phoenix.py 자동 생성
2611
+ - **Pre-upload Verification**: 업로드 전 검증
2612
  """)
2613
 
2614
  with gr.Row():
 
2635
 
2636
  burn_hub_repo = gr.Textbox(
2637
  label="📦 Hub Repository Name (optional)",
2638
+ placeholder="phoenix-granite-350m"
2639
  )
2640
 
2641
  burn_hub_private = gr.Checkbox(
 
2648
 
2649
  burn_dataset = gr.Textbox(
2650
  label="📁 Dataset Path (Optional)",
2651
+ placeholder="/path/to/dataset.txt",
2652
  value=""
2653
  )
2654
 
 
2743
  ### 🧪 PHOENIX 모델 검증
2744
 
2745
  배포된 PHOENIX 모델을 로드하고 품질을 검증합니다.
 
 
 
 
 
 
 
2746
  """)
2747
 
2748
  with gr.Row():
 
2756
  val_path = gr.Textbox(
2757
  label="🔗 Model Path/URL",
2758
  value="seawolf2357/phoenix-granite-4.0-h-350m",
2759
+ placeholder="seawolf2357/phoenix-model"
2760
  )
2761
 
2762
  val_prompts = gr.Textbox(
2763
  label="📝 Test Prompts (one per line)",
2764
  lines=5,
2765
  value="The future of AI is\nOnce upon a time\nIn machine learning,",
 
2766
  )
2767
 
2768
  with gr.Row():
2769
+ val_max_tokens = gr.Slider(16, 256, 64, step=16, label="Max Tokens")
2770
+ val_temp = gr.Slider(0.1, 2.0, 0.7, step=0.1, label="Temperature")
 
 
 
 
 
 
 
 
2771
 
2772
  val_verify_retention = gr.Checkbox(
2773
  value=True,
2774
  label="🔍 Verify Retention Mechanism"
2775
  )
2776
 
2777
+ val_btn = gr.Button("🧪 Validate Model", variant="primary", size="lg")
 
 
 
 
2778
 
2779
  with gr.Column(scale=2):
2780
  val_output = gr.Markdown()
 
2786
  val_temp, val_verify_retention],
2787
  [val_output, val_plot]
2788
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2789
 
2790
  gr.Markdown(f"""
2791
  ---
2792
 
2793
+ ## 🔥 PHOENIX Model Burning Platform v1.1
2794
 
2795
+ ### Features
2796
+ - ✅ Zero-shot Conversion (No Dataset Required)
2797
+ - ✅ Optional Fine-tuning
2798
+ - ✅ GQA Support (Grouped Query Attention)
2799
+ - ✅ O(n) Complexity
2800
+ - ✅ HuggingFace Hub Auto-Upload
2801
+ - Custom Code Generation
2802
+ - Pre-upload Verification
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2803
 
2804
+ **HuggingFace Token**: {'✅ Connected' if HF_TOKEN else '❌ Not Found'}
2805
 
2806
  **VIDraft AI Research Lab** | PHOENIX v1.1
2807
  """)