import gradio as gr import json import pandas as pd from typing import List import tempfile import os from pathlib import Path import re import shutil def clean_json_content(content: str) -> str: """JSON 문자열에서 주석을 제거하고 JSON 형식을 정리합니다.""" # 한 줄 주석 제거 (#으로 시작하는 줄) content = re.sub(r'^\s*#.*$', '', content, flags=re.MULTILINE) # 여러 줄의 연속된 콤마 정리 content = re.sub(r'},\s*,\s*{', '},{', content) # 시작과 끝에 대괄호가 없는 경우 추가 content = content.strip() if not content.startswith('['): content = '[' + content if not content.endswith(']'): content = content + ']' # 마지막 객체 뒤의 콤마 제거 content = re.sub(r'},\s*]', '}]', content) return content def process_json_files(files: List[tempfile._TemporaryFileWrapper]) -> tuple[str, str]: try: # 모든 JSON 데이터를 저장할 리스트 all_data = [] # 업로드된 각 파일 처리 for file in files: try: # 파일 내용 읽기 if hasattr(file, 'name'): # 실제 파일 객체인 경우 with open(file.name, 'r', encoding='utf-8') as f: content = f.read() else: # 문자열이나 다른 형태의 입력인 경우 content = file # JSON 내용 정리 cleaned_content = clean_json_content(content) try: json_data = json.loads(cleaned_content) except json.JSONDecodeError as e: return None, f"JSON 파싱 오류: {str(e)}\n정리된 내용:\n{cleaned_content}" # 단일 객체인 경우 리스트로 변환 if isinstance(json_data, dict): json_data = [json_data] all_data.extend(json_data) except Exception as e: return None, f"파일 처리 중 오류 발생: {str(e)}" if not all_data: return None, "처리할 데이터가 없습니다." # DataFrame으로 변환하여 중복 제거 df = pd.DataFrame(all_data) df_deduplicated = df.drop_duplicates(subset=['repo']) # 결과를 loras.json 파일로 저장 output_path = "loras.json" result_json = df_deduplicated.to_dict('records') with open(output_path, 'w', encoding='utf-8') as f: json.dump(result_json, f, ensure_ascii=False, indent=2) return output_path, f"성공적으로 처리되었습니다. 중복 제거 전 {len(all_data)}개, 중복 제거 후 {len(df_deduplicated)}개의 항목이 있습니다." except Exception as e: return None, f"처리 중 오류가 발생했습니다: {str(e)}" def create_example_file(): example_data = [ { "image": "https://huggingface.co/strangerzonehf/Flux-Super-Realism-LoRA/resolve/main/images/1.png", "title": "Super Realism", "repo": "strangerzonehf/Flux-Super-Realism-LoRA", "weights": "super-realism.safetensors", "trigger_word": "Super Realism" }, { "image": "https://huggingface.co/prithivMLmods/Flux-Dalle-Mix-LoRA/resolve/main/images/D3.png", "title": "Dalle Mix", "repo": "prithivMLmods/Flux-Dalle-Mix-LoRA", "weights": "dalle-mix.safetensors", "trigger_word": "dalle-mix" } ] example_path = "example_loras.json" with open(example_path, 'w', encoding='utf-8') as f: json.dump(example_data, f, ensure_ascii=False, indent=2) return example_path # Gradio 인터페이스 생성 iface = gr.Interface( fn=process_json_files, inputs=gr.File(file_count="multiple", label="JSON 파일 업로드 (여러 개 가능)"), outputs=[ gr.File(label="loras.json 다운로드"), gr.Textbox(label="처리 결과") ], title="JSON 파일 중복 제거 도구", description="repo 값을 기준으로 중복을 제거한 loras.json 파일을 생성합니다.\n주석이나 불완전한 JSON 형식도 처리 가능합니다.", examples=[[create_example_file()]] ) # 앱 실행 if __name__ == "__main__": iface.launch(share=True)