Spaces:
Running
Running
hasune
commited on
Commit
·
94c3165
1
Parent(s):
21f5244
Initial commit: demo generator 구현
Browse files- README.md +207 -6
- app.py +914 -0
- equirements.txt +4 -0
README.md
CHANGED
@@ -1,14 +1,215 @@
|
|
1 |
---
|
2 |
title: Demo Generator
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
sdk: gradio
|
7 |
sdk_version: 5.31.0
|
8 |
app_file: app.py
|
9 |
pinned: false
|
10 |
-
license: apache-2.0
|
11 |
-
short_description: Auto-generate Gradio demos from HF model names
|
12 |
---
|
13 |
|
14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
---
|
2 |
title: Demo Generator
|
3 |
+
emoji: 🎮
|
4 |
+
colorFrom: blue
|
5 |
+
colorTo: purple
|
6 |
sdk: gradio
|
7 |
sdk_version: 5.31.0
|
8 |
app_file: app.py
|
9 |
pinned: false
|
|
|
|
|
10 |
---
|
11 |
|
12 |
+
# 🎮 Hugging Face Demo Generator
|
13 |
+
|
14 |
+
모델명만 입력하면 바로 작동하는 Gradio 데모 Space를 자동으로 생성해주는 도구입니다.
|
15 |
+
|
16 |
+
## ✨ 주요 기능
|
17 |
+
|
18 |
+
### 🔍 스마트 모델 분석
|
19 |
+
- Hugging Face Hub 모델 자동 분석
|
20 |
+
- 태스크 타입 및 호환성 자동 감지
|
21 |
+
- 지원 가능 여부 즉시 판별
|
22 |
+
- 모델 메타데이터 자동 추출
|
23 |
+
|
24 |
+
### 🎨 태스크별 최적화된 UI 생성
|
25 |
+
- **텍스트 분류**: 결과 시각화 + 예시 버튼
|
26 |
+
- **질의응답**: 컨텍스트/질문 분리 인터페이스
|
27 |
+
- **텍스트 생성**: 창의성 제어 슬라이더
|
28 |
+
- **요약**: 압축률 통계 포함
|
29 |
+
- **번역**: 깔끔한 입출력 UI
|
30 |
+
- **빈칸 채우기**: [MASK] 예시 제공
|
31 |
+
- **개체명 인식**: 위치 정보 포함 결과
|
32 |
+
|
33 |
+
### 📦 완전한 배포 패키지
|
34 |
+
- `app.py`: 완전 작동하는 Gradio 앱
|
35 |
+
- `requirements.txt`: 필요 라이브러리 목록
|
36 |
+
- `README.md`: Space 설정 및 문서
|
37 |
+
- ZIP 다운로드로 즉시 배포 가능
|
38 |
+
|
39 |
+
## 🚀 사용법
|
40 |
+
|
41 |
+
### 1️⃣ 모델 분석
|
42 |
+
원하는 허깅페이스 모델명을 입력하세요:
|
43 |
+
|
44 |
+
**예시 모델들:**
|
45 |
+
- `klue/bert-base` (한국어 텍스트 분류)
|
46 |
+
- `klue/roberta-large-ynat` (한국어 주제분류)
|
47 |
+
- `microsoft/DialoGPT-medium` (대화 생성)
|
48 |
+
- `facebook/bart-large-cnn` (요약)
|
49 |
+
- `Helsinki-NLP/opus-mt-ko-en` (한영 번역)
|
50 |
+
|
51 |
+
### 2️⃣ 데모 설정
|
52 |
+
- **제목**: Space에서 보여질 데모 이름
|
53 |
+
- **설명**: 데모의 용도와 기능 설명
|
54 |
+
|
55 |
+
### 3️⃣ 코드 생성 및 다운로드
|
56 |
+
1. **"데모 생성"** 버튼으로 코드 미리보기
|
57 |
+
2. **"완전한 패키지 생성"** 버튼으로 ZIP 파일 생성
|
58 |
+
3. 다운로드 후 바로 새 Space에 업로드
|
59 |
+
|
60 |
+
## 🎯 지원하는 AI 태스크
|
61 |
+
|
62 |
+
### 텍스트 분류 (Text Classification)
|
63 |
+
감정분석, 주제분류, 스팸 탐지 등의 분류 태스크를 위한 인터페이스
|
64 |
+
|
65 |
+
**생성되는 기능:**
|
66 |
+
- 텍스트 입력창
|
67 |
+
- 분류 결과 시각화
|
68 |
+
- 신뢰도 표시
|
69 |
+
- 예시 텍스트 버튼
|
70 |
+
|
71 |
+
### 질의응답 (Question Answering)
|
72 |
+
문서 기반 질의응답 시스템을 위한 인터페이스
|
73 |
+
|
74 |
+
**생성되는 기능:**
|
75 |
+
- 컨텍스트 입력창
|
76 |
+
- 질문 입력창
|
77 |
+
- 답변 추출 및 신뢰도 표시
|
78 |
+
- 답변 위치 정보
|
79 |
+
|
80 |
+
### 텍스트 생성 (Text Generation)
|
81 |
+
언어모델을 이용한 텍스트 생성 인터페이스
|
82 |
+
|
83 |
+
**생성되는 기능:**
|
84 |
+
- 프롬프트 입력창
|
85 |
+
- 생성 설정 (길이, 창의성, 다양성)
|
86 |
+
- 실시간 텍스트 생성
|
87 |
+
- 설정값 표시
|
88 |
+
|
89 |
+
### 요약 (Summarization)
|
90 |
+
긴 텍스트를 요약하는 인터페이스
|
91 |
+
|
92 |
+
**생성되는 기능:**
|
93 |
+
- 긴 텍스트 입력창
|
94 |
+
- 요약 길이 설정
|
95 |
+
- 요약 결과 표시
|
96 |
+
- 압축률 통계
|
97 |
+
|
98 |
+
### 번역 (Translation)
|
99 |
+
언어 간 번역을 위한 인터페이스
|
100 |
+
|
101 |
+
**생성되는 기능:**
|
102 |
+
- 원문 입력창
|
103 |
+
- 번역 결과 표시
|
104 |
+
- 문자 수 비교
|
105 |
+
- 간단명료한 UI
|
106 |
+
|
107 |
+
### 빈칸 채우기 (Fill Mask)
|
108 |
+
BERT 스타일 마스크 예측 인터페이스
|
109 |
+
|
110 |
+
**생성되는 기능:**
|
111 |
+
- [MASK] 토큰 입력창
|
112 |
+
- 다중 후보 예측 결과
|
113 |
+
- 신뢰도별 순위 표시
|
114 |
+
- 예시 문장 제공
|
115 |
+
|
116 |
+
### 개체명 인식 (Named Entity Recognition)
|
117 |
+
텍스트에서 개체를 인식하는 인터페이스
|
118 |
+
|
119 |
+
**생성되는 기능:**
|
120 |
+
- 텍스트 입력창
|
121 |
+
- 인식된 개체 리스트
|
122 |
+
- 개체 유형 및 위치 정보
|
123 |
+
- 신뢰도 표시
|
124 |
+
|
125 |
+
## 💡 사용 사례
|
126 |
+
|
127 |
+
### AI 연구자
|
128 |
+
- 논문 발표용 라이브 데모 준비
|
129 |
+
- 모델 성능 시연 및 검증
|
130 |
+
- 연구 결과 시각적 공유
|
131 |
+
|
132 |
+
### 개발자
|
133 |
+
- 클라이언트 데모 제작
|
134 |
+
- 프로토타입 빠른 검증
|
135 |
+
- API 테스트 인터페이스
|
136 |
+
|
137 |
+
### 교육자 & 학생
|
138 |
+
- 수업용 인터랙티브 도구
|
139 |
+
- AI 모델 학습 자료
|
140 |
+
- 과제 결과 시연
|
141 |
+
|
142 |
+
### 기업
|
143 |
+
- 내부 모델 검증 도구
|
144 |
+
- stakeholder 프레젠테이션
|
145 |
+
- POC (Proof of Concept) 제작
|
146 |
+
|
147 |
+
## 🔗 완벽한 AI 개발 워크플로우
|
148 |
+
|
149 |
+
이 도구는 다른 도구들과 연계하여 완전한 개발 경험을 제공합니다:
|
150 |
+
|
151 |
+
### 1️⃣ 모델 검색
|
152 |
+
**[Model Search Tool](https://huggingface.co/spaces/your-username/model-search-tool)**에서 최적의 사전 훈련 모델 탐색
|
153 |
+
|
154 |
+
### 2️⃣ 데이터 준비
|
155 |
+
**[Dataset Converter](https://huggingface.co/spaces/your-username/dataset-converter)**로 학습 데이터 허깅페이스 포맷 변환
|
156 |
+
|
157 |
+
### 3️⃣ 데모 생성
|
158 |
+
**Demo Generator**로 모델 시연용 인터랙티브 데모 자동 생성 ← *현재 도구*
|
159 |
+
|
160 |
+
### 4️⃣ 문서화
|
161 |
+
**[Model Card Generator](https://huggingface.co/spaces/your-username/model-card-generator)**로 전문적인 모델 문서 작성
|
162 |
+
|
163 |
+
## 🛠️ 기술적 특징
|
164 |
+
|
165 |
+
### 자동 코드 생성
|
166 |
+
- 태스크별 최적화된 Gradio 인터페이스
|
167 |
+
- 에러 처리 및 사용자 가이드 포함
|
168 |
+
- 최신 transformers 라이브러리 활용
|
169 |
+
- 반응형 UI 및 예쁜 디자인
|
170 |
+
|
171 |
+
### 배포 최적화
|
172 |
+
- 허깅페이스 Space 표준 준수
|
173 |
+
- 자동 requirements.txt 생성
|
174 |
+
- 완전한 README.md 템플릿
|
175 |
+
- 한 번의 다운로드로 배포 준비 완료
|
176 |
+
|
177 |
+
### 확장성
|
178 |
+
- 새로운 태스크 쉽게 추가 가능
|
179 |
+
- 커스터마이징 가능한 템플릿
|
180 |
+
- 모델 호환성 자동 체크
|
181 |
+
|
182 |
+
## 📊 생성 예시
|
183 |
+
|
184 |
+
### 입력
|
185 |
+
```
|
186 |
+
모델명: klue/bert-base
|
187 |
+
제목: Korean BERT Demo
|
188 |
+
설명: 한국어 텍스트 분류를 위한 BERT 모델
|
189 |
+
```
|
190 |
+
|
191 |
+
### 출력
|
192 |
+
- 완전히 작동하는 Gradio 앱
|
193 |
+
- 예시 텍스트 버튼 포함
|
194 |
+
- 한국어 최적화 인터페이스
|
195 |
+
- 바로 배포 가능한 패키지
|
196 |
+
|
197 |
+
## 🎨 UI/UX 최적화
|
198 |
+
|
199 |
+
- **직관적 인터페이스**: 비전문가도 쉽게 사용
|
200 |
+
- **실시간 피드백**: 즉시 결과 확인 가능
|
201 |
+
- **모바일 호환**: 반응형 디자인
|
202 |
+
- **접근성**: 명확한 라벨 및 설명
|
203 |
+
|
204 |
+
## 🔒 안정성 & 호환성
|
205 |
+
|
206 |
+
- **에러 처리**: 강건한 예외 처리
|
207 |
+
- **모델 호환성**: 자동 검증 시스템
|
208 |
+
- **버전 관리**: 최신 라이브러리 지원
|
209 |
+
- **보안**: 안전한 모델 로딩
|
210 |
+
|
211 |
+
---
|
212 |
+
|
213 |
+
Made with ❤️ for the AI community
|
214 |
+
|
215 |
+
*"복잡한 AI 모델을 누구나 쉽게 체험할 수 있는 세상을 만들어갑니다"*
|
app.py
ADDED
@@ -0,0 +1,914 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from huggingface_hub import HfApi, model_info
|
3 |
+
import tempfile
|
4 |
+
import zipfile
|
5 |
+
import os
|
6 |
+
from datetime import datetime
|
7 |
+
|
8 |
+
api = HfApi()
|
9 |
+
|
10 |
+
def analyze_model(model_name):
|
11 |
+
"""허깅페이스 모델 분석"""
|
12 |
+
if not model_name:
|
13 |
+
return "모델명을 입력해주세요.", None, None
|
14 |
+
|
15 |
+
try:
|
16 |
+
# 모델 정보 가져오기
|
17 |
+
info = model_info(model_name)
|
18 |
+
|
19 |
+
# 파이프라인 태스크 확인
|
20 |
+
pipeline_tag = getattr(info, 'pipeline_tag', None)
|
21 |
+
|
22 |
+
# 모델 타입 분석
|
23 |
+
model_type = "unknown"
|
24 |
+
if hasattr(info, 'config') and info.config:
|
25 |
+
model_type = info.config.get('model_type', 'unknown')
|
26 |
+
|
27 |
+
# 라이브러리 확인
|
28 |
+
library = getattr(info, 'library_name', 'transformers')
|
29 |
+
|
30 |
+
# 언어 확인
|
31 |
+
languages = getattr(info, 'language', ['en'])
|
32 |
+
if isinstance(languages, str):
|
33 |
+
languages = [languages]
|
34 |
+
|
35 |
+
analysis_result = f"""
|
36 |
+
## 🔍 모델 분석 결과
|
37 |
+
|
38 |
+
### 기본 정보
|
39 |
+
- **모델명**: {model_name}
|
40 |
+
- **태스크**: {pipeline_tag or 'Unknown'}
|
41 |
+
- **모델 타입**: {model_type}
|
42 |
+
- **라이브러리**: {library}
|
43 |
+
- **언어**: {', '.join(languages[:3])}
|
44 |
+
- **다운로드**: {getattr(info, 'downloads', 0):,}회
|
45 |
+
|
46 |
+
### 데모 생성 가능 여부
|
47 |
+
"""
|
48 |
+
|
49 |
+
# 지원 가능한 태스크인지 확인
|
50 |
+
supported_tasks = {
|
51 |
+
'text-classification': '✅ 텍스트 분류 데모 생성 가능',
|
52 |
+
'question-answering': '✅ 질의응답 데모 생성 가능',
|
53 |
+
'text-generation': '✅ 텍스트 생성 데모 생성 가능',
|
54 |
+
'summarization': '✅ 요약 데모 생성 가능',
|
55 |
+
'translation': '✅ 번역 데모 생성 가능',
|
56 |
+
'fill-mask': '✅ 빈칸 채우기 데모 생성 가능',
|
57 |
+
'token-classification': '✅ 개체명 인식 데모 생성 가능'
|
58 |
+
}
|
59 |
+
|
60 |
+
if pipeline_tag in supported_tasks:
|
61 |
+
analysis_result += supported_tasks[pipeline_tag]
|
62 |
+
demo_possible = True
|
63 |
+
else:
|
64 |
+
analysis_result += f"⚠️ '{pipeline_tag}' 태스크는 아직 지원되지 않습니다."
|
65 |
+
demo_possible = False
|
66 |
+
|
67 |
+
return analysis_result, info, demo_possible
|
68 |
+
|
69 |
+
except Exception as e:
|
70 |
+
return f"❌ 모델 분석 실패: {str(e)}\n\n모델명이 정확한지 확인해주세요.", None, False
|
71 |
+
|
72 |
+
def generate_demo_code(model_info, model_name, demo_title, demo_description):
|
73 |
+
"""태스크별 데모 코드 생성"""
|
74 |
+
|
75 |
+
if not model_info:
|
76 |
+
return "먼저 모델을 분석해주세요.", None
|
77 |
+
|
78 |
+
pipeline_tag = getattr(model_info, 'pipeline_tag', None)
|
79 |
+
|
80 |
+
if not demo_title:
|
81 |
+
demo_title = f"{model_name.split('/')[-1]} Demo"
|
82 |
+
if not demo_description:
|
83 |
+
demo_description = f"Demo for {model_name}"
|
84 |
+
|
85 |
+
# 태스크별 코드 생성
|
86 |
+
if pipeline_tag == 'text-classification':
|
87 |
+
app_code = generate_text_classification_demo(model_name, demo_title, demo_description)
|
88 |
+
elif pipeline_tag == 'question-answering':
|
89 |
+
app_code = generate_qa_demo(model_name, demo_title, demo_description)
|
90 |
+
elif pipeline_tag == 'text-generation':
|
91 |
+
app_code = generate_text_generation_demo(model_name, demo_title, demo_description)
|
92 |
+
elif pipeline_tag == 'summarization':
|
93 |
+
app_code = generate_summarization_demo(model_name, demo_title, demo_description)
|
94 |
+
elif pipeline_tag == 'translation':
|
95 |
+
app_code = generate_translation_demo(model_name, demo_title, demo_description)
|
96 |
+
elif pipeline_tag == 'fill-mask':
|
97 |
+
app_code = generate_fill_mask_demo(model_name, demo_title, demo_description)
|
98 |
+
elif pipeline_tag == 'token-classification':
|
99 |
+
app_code = generate_token_classification_demo(model_name, demo_title, demo_description)
|
100 |
+
else:
|
101 |
+
return f"❌ '{pipeline_tag}' 태스크는 아직 지원되지 않습니다.", None
|
102 |
+
|
103 |
+
return app_code, pipeline_tag
|
104 |
+
|
105 |
+
def generate_text_classification_demo(model_name, title, description):
|
106 |
+
"""텍스트 분류 데모 코드 생성"""
|
107 |
+
return f'''import gradio as gr
|
108 |
+
from transformers import pipeline
|
109 |
+
|
110 |
+
# 모델 로드
|
111 |
+
classifier = pipeline("text-classification", model="{model_name}")
|
112 |
+
|
113 |
+
def classify_text(text):
|
114 |
+
"""텍스트 분류 수행"""
|
115 |
+
if not text.strip():
|
116 |
+
return "텍스트를 입력해주세요."
|
117 |
+
|
118 |
+
try:
|
119 |
+
results = classifier(text)
|
120 |
+
|
121 |
+
# 결과 포맷팅
|
122 |
+
output = "## 🎯 분류 결과\\n\\n"
|
123 |
+
for i, result in enumerate(results):
|
124 |
+
label = result['label']
|
125 |
+
score = result['score']
|
126 |
+
confidence = f"{score:.1%}"
|
127 |
+
|
128 |
+
output += f"**{i+1}. {label}**: {confidence}\\n"
|
129 |
+
|
130 |
+
return output
|
131 |
+
except Exception as e:
|
132 |
+
return f"❌ 오류가 발생했습니다: {{str(e)}}"
|
133 |
+
|
134 |
+
# Gradio 인터페이스
|
135 |
+
with gr.Blocks(title="{title}", theme=gr.themes.Soft()) as demo:
|
136 |
+
gr.Markdown("# {title}")
|
137 |
+
gr.Markdown("{description}")
|
138 |
+
|
139 |
+
with gr.Row():
|
140 |
+
with gr.Column(scale=1):
|
141 |
+
text_input = gr.Textbox(
|
142 |
+
label="분석할 텍스트",
|
143 |
+
placeholder="여기에 텍스트를 입력하세요...",
|
144 |
+
lines=5
|
145 |
+
)
|
146 |
+
classify_btn = gr.Button("🎯 분류하기", variant="primary")
|
147 |
+
|
148 |
+
# 예시 버튼들
|
149 |
+
gr.Markdown("### 📝 예시 텍스트")
|
150 |
+
examples = [
|
151 |
+
["이 영화 정말 재미있어요! 강력 추천합니다."],
|
152 |
+
["서비스가 너무 별로네요. 실망스럽습니다."],
|
153 |
+
["그냥 평범한 제품인 것 같아요."]
|
154 |
+
]
|
155 |
+
|
156 |
+
example_btns = []
|
157 |
+
for example in examples:
|
158 |
+
btn = gr.Button(example[0][:30] + "...", size="sm")
|
159 |
+
btn.click(lambda x=example[0]: x, outputs=text_input)
|
160 |
+
|
161 |
+
with gr.Column(scale=1):
|
162 |
+
output = gr.Markdown("텍스트를 입력하고 분류 버튼을 클릭하세요.")
|
163 |
+
|
164 |
+
classify_btn.click(
|
165 |
+
fn=classify_text,
|
166 |
+
inputs=text_input,
|
167 |
+
outputs=output
|
168 |
+
)
|
169 |
+
|
170 |
+
gr.Markdown(f"""
|
171 |
+
### ℹ️ 모델 정보
|
172 |
+
- **모델**: [{model_name}](https://huggingface.co/{model_name})
|
173 |
+
- **태스크**: 텍스트 분류
|
174 |
+
- **설명**: {description}
|
175 |
+
""")
|
176 |
+
|
177 |
+
if __name__ == "__main__":
|
178 |
+
demo.launch()'''
|
179 |
+
|
180 |
+
def generate_qa_demo(model_name, title, description):
|
181 |
+
"""질의응답 데모 코드 생성"""
|
182 |
+
return f'''import gradio as gr
|
183 |
+
from transformers import pipeline
|
184 |
+
|
185 |
+
# 모델 로드
|
186 |
+
qa_pipeline = pipeline("question-answering", model="{model_name}")
|
187 |
+
|
188 |
+
def answer_question(context, question):
|
189 |
+
"""질의응답 수행"""
|
190 |
+
if not context.strip() or not question.strip():
|
191 |
+
return "컨텍스트와 질문을 모두 입력해주세요."
|
192 |
+
|
193 |
+
try:
|
194 |
+
result = qa_pipeline(question=question, context=context)
|
195 |
+
|
196 |
+
answer = result['answer']
|
197 |
+
score = result['score']
|
198 |
+
confidence = f"{score:.1%}"
|
199 |
+
|
200 |
+
output = f"""
|
201 |
+
## 💡 답변 결과
|
202 |
+
|
203 |
+
**답변**: {answer}
|
204 |
+
|
205 |
+
**신뢰도**: {confidence}
|
206 |
+
|
207 |
+
**시작 위치**: {result.get('start', 'N/A')}
|
208 |
+
**끝 위치**: {result.get('end', 'N/A')}
|
209 |
+
"""
|
210 |
+
return output
|
211 |
+
except Exception as e:
|
212 |
+
return f"❌ 오류가 발생했습니다: {{str(e)}}"
|
213 |
+
|
214 |
+
# Gradio 인터페이스
|
215 |
+
with gr.Blocks(title="{title}", theme=gr.themes.Soft()) as demo:
|
216 |
+
gr.Markdown("# {title}")
|
217 |
+
gr.Markdown("{description}")
|
218 |
+
|
219 |
+
with gr.Row():
|
220 |
+
with gr.Column():
|
221 |
+
context_input = gr.Textbox(
|
222 |
+
label="📄 컨텍스트 (배경 정보)",
|
223 |
+
placeholder="답변의 근거가 될 텍스트를 입력하세요...",
|
224 |
+
lines=8
|
225 |
+
)
|
226 |
+
question_input = gr.Textbox(
|
227 |
+
label="❓ 질문",
|
228 |
+
placeholder="질문을 입력하세요...",
|
229 |
+
lines=2
|
230 |
+
)
|
231 |
+
qa_btn = gr.Button("💡 답변 찾기", variant="primary")
|
232 |
+
|
233 |
+
with gr.Column():
|
234 |
+
output = gr.Markdown("컨텍스트와 질문을 입력하고 버튼을 클릭하세요.")
|
235 |
+
|
236 |
+
qa_btn.click(
|
237 |
+
fn=answer_question,
|
238 |
+
inputs=[context_input, question_input],
|
239 |
+
outputs=output
|
240 |
+
)
|
241 |
+
|
242 |
+
gr.Markdown(f"""
|
243 |
+
### ℹ️ 모델 정보
|
244 |
+
- **모델**: [{model_name}](https://huggingface.co/{model_name})
|
245 |
+
- **태스크**: 질의응답
|
246 |
+
- **설명**: {description}
|
247 |
+
""")
|
248 |
+
|
249 |
+
if __name__ == "__main__":
|
250 |
+
demo.launch()'''
|
251 |
+
|
252 |
+
def generate_text_generation_demo(model_name, title, description):
|
253 |
+
"""텍스트 생성 데모 코드 생성"""
|
254 |
+
return f'''import gradio as gr
|
255 |
+
from transformers import pipeline
|
256 |
+
|
257 |
+
# 모델 로드
|
258 |
+
generator = pipeline("text-generation", model="{model_name}")
|
259 |
+
|
260 |
+
def generate_text(prompt, max_length, temperature, top_p):
|
261 |
+
"""텍스트 생성 수행"""
|
262 |
+
if not prompt.strip():
|
263 |
+
return "프롬프트를 입력해주세요."
|
264 |
+
|
265 |
+
try:
|
266 |
+
results = generator(
|
267 |
+
prompt,
|
268 |
+
max_length=max_length,
|
269 |
+
temperature=temperature,
|
270 |
+
top_p=top_p,
|
271 |
+
num_return_sequences=1,
|
272 |
+
do_sample=True,
|
273 |
+
pad_token_id=generator.tokenizer.eos_token_id
|
274 |
+
)
|
275 |
+
|
276 |
+
generated_text = results[0]['generated_text']
|
277 |
+
|
278 |
+
# 원본 프롬프트 제거하고 생성된 부분만 표시
|
279 |
+
if generated_text.startswith(prompt):
|
280 |
+
generated_text = generated_text[len(prompt):]
|
281 |
+
|
282 |
+
output = f"""
|
283 |
+
## ✨ 생성된 텍스트
|
284 |
+
|
285 |
+
**입력**: {prompt}
|
286 |
+
|
287 |
+
**생성 결과**:
|
288 |
+
{generated_text}
|
289 |
+
|
290 |
+
---
|
291 |
+
*설정: 최대 길이={max_length}, 온도={temperature}, Top-p={top_p}*
|
292 |
+
"""
|
293 |
+
return output
|
294 |
+
except Exception as e:
|
295 |
+
return f"❌ 오류가 발생했습니다: {{str(e)}}"
|
296 |
+
|
297 |
+
# Gradio 인터페이스
|
298 |
+
with gr.Blocks(title="{title}", theme=gr.themes.Soft()) as demo:
|
299 |
+
gr.Markdown("# {title}")
|
300 |
+
gr.Markdown("{description}")
|
301 |
+
|
302 |
+
with gr.Row():
|
303 |
+
with gr.Column(scale=1):
|
304 |
+
prompt_input = gr.Textbox(
|
305 |
+
label="✍️ 프롬프트",
|
306 |
+
placeholder="텍스트 생성을 시작할 문장을 입력하세요...",
|
307 |
+
lines=4
|
308 |
+
)
|
309 |
+
|
310 |
+
gr.Markdown("### ⚙️ 생성 설정")
|
311 |
+
max_length = gr.Slider(
|
312 |
+
label="최대 길이",
|
313 |
+
minimum=10,
|
314 |
+
maximum=200,
|
315 |
+
value=50,
|
316 |
+
step=10
|
317 |
+
)
|
318 |
+
temperature = gr.Slider(
|
319 |
+
label="Temperature (창의성)",
|
320 |
+
minimum=0.1,
|
321 |
+
maximum=2.0,
|
322 |
+
value=0.7,
|
323 |
+
step=0.1
|
324 |
+
)
|
325 |
+
top_p = gr.Slider(
|
326 |
+
label="Top-p (다양성)",
|
327 |
+
minimum=0.1,
|
328 |
+
maximum=1.0,
|
329 |
+
value=0.9,
|
330 |
+
step=0.1
|
331 |
+
)
|
332 |
+
|
333 |
+
generate_btn = gr.Button("✨ 텍스트 생성", variant="primary")
|
334 |
+
|
335 |
+
with gr.Column(scale=2):
|
336 |
+
output = gr.Markdown("프롬프트를 입력하고 생성 버튼을 클릭하세요.")
|
337 |
+
|
338 |
+
generate_btn.click(
|
339 |
+
fn=generate_text,
|
340 |
+
inputs=[prompt_input, max_length, temperature, top_p],
|
341 |
+
outputs=output
|
342 |
+
)
|
343 |
+
|
344 |
+
gr.Markdown(f"""
|
345 |
+
### ℹ️ 모델 정보
|
346 |
+
- **모델**: [{model_name}](https://huggingface.co/{model_name})
|
347 |
+
- **태스크**: 텍스트 생성
|
348 |
+
- **설명**: {description}
|
349 |
+
""")
|
350 |
+
|
351 |
+
if __name__ == "__main__":
|
352 |
+
demo.launch()'''
|
353 |
+
|
354 |
+
def generate_summarization_demo(model_name, title, description):
|
355 |
+
"""요약 데모 코드 생성"""
|
356 |
+
return f'''import gradio as gr
|
357 |
+
from transformers import pipeline
|
358 |
+
|
359 |
+
# 모델 로드
|
360 |
+
summarizer = pipeline("summarization", model="{model_name}")
|
361 |
+
|
362 |
+
def summarize_text(text, max_length, min_length):
|
363 |
+
"""텍스트 요약 수행"""
|
364 |
+
if not text.strip():
|
365 |
+
return "요약할 텍스트를 입력해주세요."
|
366 |
+
|
367 |
+
if len(text.split()) < 10:
|
368 |
+
return "요약하기에는 텍스트가 너무 짧습니다. 더 긴 텍스트를 입력해주세요."
|
369 |
+
|
370 |
+
try:
|
371 |
+
results = summarizer(
|
372 |
+
text,
|
373 |
+
max_length=max_length,
|
374 |
+
min_length=min_length,
|
375 |
+
do_sample=False
|
376 |
+
)
|
377 |
+
|
378 |
+
summary = results[0]['summary_text']
|
379 |
+
|
380 |
+
# 통계 계산
|
381 |
+
original_words = len(text.split())
|
382 |
+
summary_words = len(summary.split())
|
383 |
+
compression_ratio = (1 - summary_words / original_words) * 100
|
384 |
+
|
385 |
+
output = f"""
|
386 |
+
## 📝 요약 결과
|
387 |
+
|
388 |
+
**요약문**:
|
389 |
+
{summary}
|
390 |
+
|
391 |
+
---
|
392 |
+
|
393 |
+
### 📊 통계
|
394 |
+
- **원문 단어 수**: {original_words:,}개
|
395 |
+
- **요약문 단어 수**: {summary_words:,}개
|
396 |
+
- **압축률**: {compression_ratio:.1f}%
|
397 |
+
"""
|
398 |
+
return output
|
399 |
+
except Exception as e:
|
400 |
+
return f"❌ 오류가 발생했습니다: {{str(e)}}"
|
401 |
+
|
402 |
+
# Gradio 인터페이스
|
403 |
+
with gr.Blocks(title="{title}", theme=gr.themes.Soft()) as demo:
|
404 |
+
gr.Markdown("# {title}")
|
405 |
+
gr.Markdown("{description}")
|
406 |
+
|
407 |
+
with gr.Row():
|
408 |
+
with gr.Column(scale=1):
|
409 |
+
text_input = gr.Textbox(
|
410 |
+
label="📄 요약할 텍스트",
|
411 |
+
placeholder="긴 텍스트를 입력하세요...",
|
412 |
+
lines=10
|
413 |
+
)
|
414 |
+
|
415 |
+
gr.Markdown("### ⚙️ 요약 설정")
|
416 |
+
max_length = gr.Slider(
|
417 |
+
label="최대 요약 길이",
|
418 |
+
minimum=20,
|
419 |
+
maximum=150,
|
420 |
+
value=50,
|
421 |
+
step=10
|
422 |
+
)
|
423 |
+
min_length = gr.Slider(
|
424 |
+
label="최소 요약 길이",
|
425 |
+
minimum=5,
|
426 |
+
maximum=50,
|
427 |
+
value=10,
|
428 |
+
step=5
|
429 |
+
)
|
430 |
+
|
431 |
+
summarize_btn = gr.Button("📝 요약하기", variant="primary")
|
432 |
+
|
433 |
+
with gr.Column(scale=1):
|
434 |
+
output = gr.Markdown("텍스트를 입력하고 요약 버튼을 클릭하세요.")
|
435 |
+
|
436 |
+
summarize_btn.click(
|
437 |
+
fn=summarize_text,
|
438 |
+
inputs=[text_input, max_length, min_length],
|
439 |
+
outputs=output
|
440 |
+
)
|
441 |
+
|
442 |
+
gr.Markdown(f"""
|
443 |
+
### ℹ️ 모델 정보
|
444 |
+
- **모델**: [{model_name}](https://huggingface.co/{model_name})
|
445 |
+
- **태스크**: 텍스트 요약
|
446 |
+
- **설명**: {description}
|
447 |
+
""")
|
448 |
+
|
449 |
+
if __name__ == "__main__":
|
450 |
+
demo.launch()'''
|
451 |
+
|
452 |
+
def generate_translation_demo(model_name, title, description):
|
453 |
+
"""번역 데모 코드 생성"""
|
454 |
+
return f'''import gradio as gr
|
455 |
+
from transformers import pipeline
|
456 |
+
|
457 |
+
# 모델 로드
|
458 |
+
translator = pipeline("translation", model="{model_name}")
|
459 |
+
|
460 |
+
def translate_text(text):
|
461 |
+
"""번역 수행"""
|
462 |
+
if not text.strip():
|
463 |
+
return "번역할 텍스트를 입력해주세요."
|
464 |
+
|
465 |
+
try:
|
466 |
+
results = translator(text)
|
467 |
+
translated = results[0]['translation_text']
|
468 |
+
|
469 |
+
output = f"""
|
470 |
+
## 🌍 번역 결과
|
471 |
+
|
472 |
+
**원문**: {text}
|
473 |
+
|
474 |
+
**번역문**: {translated}
|
475 |
+
|
476 |
+
---
|
477 |
+
*문자 수: {len(text)} → {len(translated)}*
|
478 |
+
"""
|
479 |
+
return output
|
480 |
+
except Exception as e:
|
481 |
+
return f"❌ 오류가 발생했습니다: {{str(e)}}"
|
482 |
+
|
483 |
+
# Gradio 인터페이스
|
484 |
+
with gr.Blocks(title="{title}", theme=gr.themes.Soft()) as demo:
|
485 |
+
gr.Markdown("# {title}")
|
486 |
+
gr.Markdown("{description}")
|
487 |
+
|
488 |
+
with gr.Row():
|
489 |
+
with gr.Column():
|
490 |
+
text_input = gr.Textbox(
|
491 |
+
label="🌍 번역할 텍스트",
|
492 |
+
placeholder="번역할 텍스트를 입력하세요...",
|
493 |
+
lines=6
|
494 |
+
)
|
495 |
+
translate_btn = gr.Button("🌍 번역하기", variant="primary")
|
496 |
+
|
497 |
+
with gr.Column():
|
498 |
+
output = gr.Markdown("텍스트를 입력하고 번역 버튼을 클릭하세요.")
|
499 |
+
|
500 |
+
translate_btn.click(
|
501 |
+
fn=translate_text,
|
502 |
+
inputs=text_input,
|
503 |
+
outputs=output
|
504 |
+
)
|
505 |
+
|
506 |
+
gr.Markdown(f"""
|
507 |
+
### ℹ️ 모델 정보
|
508 |
+
- **모델**: [{model_name}](https://huggingface.co/{model_name})
|
509 |
+
- **태스크**: 번역
|
510 |
+
- **설명**: {description}
|
511 |
+
""")
|
512 |
+
|
513 |
+
if __name__ == "__main__":
|
514 |
+
demo.launch()'''
|
515 |
+
|
516 |
+
def generate_fill_mask_demo(model_name, title, description):
|
517 |
+
"""빈칸 채우기 데모 코드 생성"""
|
518 |
+
return f'''import gradio as gr
|
519 |
+
from transformers import pipeline
|
520 |
+
|
521 |
+
# 모델 로드
|
522 |
+
fill_mask = pipeline("fill-mask", model="{model_name}")
|
523 |
+
|
524 |
+
def predict_mask(text):
|
525 |
+
"""마스크 예측 수행"""
|
526 |
+
if not text.strip():
|
527 |
+
return "텍스트를 입력해주세요."
|
528 |
+
|
529 |
+
if "[MASK]" not in text:
|
530 |
+
return "텍스트에 [MASK] 토큰을 포함해주세요."
|
531 |
+
|
532 |
+
try:
|
533 |
+
results = fill_mask(text)
|
534 |
+
|
535 |
+
output = f"## 🎯 예측 결과\\n\\n**원문**: {text}\\n\\n### 후보들:\\n"
|
536 |
+
|
537 |
+
for i, result in enumerate(results[:5]):
|
538 |
+
token = result['token_str']
|
539 |
+
score = result['score']
|
540 |
+
sequence = result['sequence']
|
541 |
+
confidence = f"{score:.1%}"
|
542 |
+
|
543 |
+
output += f"**{i+1}. {token}** ({confidence})\\n"
|
544 |
+
output += f" *{sequence}*\\n\\n"
|
545 |
+
|
546 |
+
return output
|
547 |
+
except Exception as e:
|
548 |
+
return f"❌ 오류가 발생했습니다: {{str(e)}}"
|
549 |
+
|
550 |
+
# Gradio 인터페이스
|
551 |
+
with gr.Blocks(title="{title}", theme=gr.themes.Soft()) as demo:
|
552 |
+
gr.Markdown("# {title}")
|
553 |
+
gr.Markdown("{description}")
|
554 |
+
|
555 |
+
with gr.Row():
|
556 |
+
with gr.Column():
|
557 |
+
text_input = gr.Textbox(
|
558 |
+
label="🎯 [MASK] 예측할 텍스트",
|
559 |
+
placeholder="[MASK] 토큰을 포함한 문장을 입력하세요...",
|
560 |
+
lines=4,
|
561 |
+
value="오늘 날씨가 정말 [MASK]네요."
|
562 |
+
)
|
563 |
+
predict_btn = gr.Button("🎯 예측하기", variant="primary")
|
564 |
+
|
565 |
+
gr.Markdown("### 📝 예시")
|
566 |
+
examples = [
|
567 |
+
"오늘 날씨가 정말 [MASK]네요.",
|
568 |
+
"이 영화는 [MASK] 재미있어요.",
|
569 |
+
"한국의 수도는 [MASK]입니다."
|
570 |
+
]
|
571 |
+
|
572 |
+
for example in examples:
|
573 |
+
btn = gr.Button(example, size="sm")
|
574 |
+
btn.click(lambda x=example: x, outputs=text_input)
|
575 |
+
|
576 |
+
with gr.Column():
|
577 |
+
output = gr.Markdown("[MASK] 토큰을 포함한 텍스트를 입력하고 예측 버튼을 클릭하세요.")
|
578 |
+
|
579 |
+
predict_btn.click(
|
580 |
+
fn=predict_mask,
|
581 |
+
inputs=text_input,
|
582 |
+
outputs=output
|
583 |
+
)
|
584 |
+
|
585 |
+
gr.Markdown(f"""
|
586 |
+
### ℹ️ 모델 정보
|
587 |
+
- **모델**: [{model_name}](https://huggingface.co/{model_name})
|
588 |
+
- **태스크**: 빈칸 채우기 (Fill Mask)
|
589 |
+
- **설명**: {description}
|
590 |
+
""")
|
591 |
+
|
592 |
+
if __name__ == "__main__":
|
593 |
+
demo.launch()'''
|
594 |
+
|
595 |
+
def generate_token_classification_demo(model_name, title, description):
|
596 |
+
"""개체명 인식 데모 코드 생성"""
|
597 |
+
return f'''import gradio as gr
|
598 |
+
from transformers import pipeline
|
599 |
+
|
600 |
+
# 모델 로드
|
601 |
+
ner_pipeline = pipeline("token-classification", model="{model_name}", aggregation_strategy="simple")
|
602 |
+
|
603 |
+
def recognize_entities(text):
|
604 |
+
"""개체명 인식 수행"""
|
605 |
+
if not text.strip():
|
606 |
+
return "텍스트를 입력해주세요."
|
607 |
+
|
608 |
+
try:
|
609 |
+
results = ner_pipeline(text)
|
610 |
+
|
611 |
+
if not results:
|
612 |
+
return "인식된 개체가 없습니다."
|
613 |
+
|
614 |
+
output = f"## 🏷️ 개체명 인식 결과\\n\\n**원문**: {text}\\n\\n### 인식된 개체들:\\n"
|
615 |
+
|
616 |
+
for i, entity in enumerate(results):
|
617 |
+
word = entity['word']
|
618 |
+
label = entity['entity_group']
|
619 |
+
score = entity['score']
|
620 |
+
start = entity['start']
|
621 |
+
end = entity['end']
|
622 |
+
confidence = f"{score:.1%}"
|
623 |
+
|
624 |
+
output += f"**{i+1}. {word}** → *{label}* ({confidence})\\n"
|
625 |
+
output += f" 위치: {start}-{end}\\n\\n"
|
626 |
+
|
627 |
+
return output
|
628 |
+
except Exception as e:
|
629 |
+
return f"❌ 오류가 발생했습니다: {{str(e)}}"
|
630 |
+
|
631 |
+
# Gradio 인터페이스
|
632 |
+
with gr.Blocks(title="{title}", theme=gr.themes.Soft()) as demo:
|
633 |
+
gr.Markdown("# {title}")
|
634 |
+
gr.Markdown("{description}")
|
635 |
+
|
636 |
+
with gr.Row():
|
637 |
+
with gr.Column():
|
638 |
+
text_input = gr.Textbox(
|
639 |
+
label="🏷️ 개체명 인식할 텍스트",
|
640 |
+
placeholder="사람명, 지명, 기관명 등이 포함된 텍스트를 입력하세요...",
|
641 |
+
lines=5,
|
642 |
+
value="삼성전자의 이재용 회장이 서울에서 기자회견을 열었다."
|
643 |
+
)
|
644 |
+
ner_btn = gr.Button("🏷️ 개체명 인식", variant="primary")
|
645 |
+
|
646 |
+
with gr.Column():
|
647 |
+
output = gr.Markdown("텍스트를 입력하고 인식 버튼을 클릭하세요.")
|
648 |
+
|
649 |
+
ner_btn.click(
|
650 |
+
fn=recognize_entities,
|
651 |
+
inputs=text_input,
|
652 |
+
outputs=output
|
653 |
+
)
|
654 |
+
|
655 |
+
gr.Markdown(f"""
|
656 |
+
### ℹ️ 모델 정보
|
657 |
+
- **모델**: [{model_name}](https://huggingface.co/{model_name})
|
658 |
+
- **태스크**: 개체명 인식 (Named Entity Recognition)
|
659 |
+
- **설명**: {description}
|
660 |
+
""")
|
661 |
+
|
662 |
+
if __name__ == "__main__":
|
663 |
+
demo.launch()'''
|
664 |
+
|
665 |
+
def create_demo_package(app_code, pipeline_tag, model_name, demo_title, demo_description):
|
666 |
+
"""완전한 데모 패키지 생성"""
|
667 |
+
|
668 |
+
if not app_code:
|
669 |
+
return "먼저 데모 코드를 생성해주세요.", None
|
670 |
+
|
671 |
+
try:
|
672 |
+
# 임시 디렉토리 생성
|
673 |
+
temp_dir = tempfile.mkdtemp()
|
674 |
+
demo_dir = os.path.join(temp_dir, demo_title.lower().replace(' ', '-'))
|
675 |
+
os.makedirs(demo_dir, exist_ok=True)
|
676 |
+
|
677 |
+
# 1. app.py 저장
|
678 |
+
with open(os.path.join(demo_dir, "app.py"), 'w', encoding='utf-8') as f:
|
679 |
+
f.write(app_code)
|
680 |
+
|
681 |
+
# 2. requirements.txt 생성
|
682 |
+
requirements = """gradio
|
683 |
+
transformers
|
684 |
+
torch
|
685 |
+
"""
|
686 |
+
with open(os.path.join(demo_dir, "requirements.txt"), 'w', encoding='utf-8') as f:
|
687 |
+
f.write(requirements)
|
688 |
+
|
689 |
+
# 3. README.md 생성
|
690 |
+
space_name = demo_title.lower().replace(' ', '-')
|
691 |
+
readme_content = f"""---
|
692 |
+
title: {demo_title}
|
693 |
+
emoji: 🤖
|
694 |
+
colorFrom: blue
|
695 |
+
colorTo: purple
|
696 |
+
sdk: gradio
|
697 |
+
sdk_version: 5.31.0
|
698 |
+
app_file: app.py
|
699 |
+
pinned: false
|
700 |
+
models:
|
701 |
+
- {model_name}
|
702 |
+
---
|
703 |
+
|
704 |
+
# {demo_title}
|
705 |
+
|
706 |
+
{demo_description}
|
707 |
+
|
708 |
+
## 🚀 사용법
|
709 |
+
|
710 |
+
이 데모는 [{model_name}](https://huggingface.co/{model_name}) 모델을 사용합니다.
|
711 |
+
|
712 |
+
### 태스크: {pipeline_tag}
|
713 |
+
|
714 |
+
{get_task_description(pipeline_tag)}
|
715 |
+
|
716 |
+
## 🛠️ 로컬 실행
|
717 |
+
|
718 |
+
```bash
|
719 |
+
pip install -r requirements.txt
|
720 |
+
python app.py
|
721 |
+
```
|
722 |
+
|
723 |
+
## 📝 모델 정보
|
724 |
+
|
725 |
+
- **모델**: [{model_name}](https://huggingface.co/{model_name})
|
726 |
+
- **태스크**: {pipeline_tag}
|
727 |
+
- **라이브러리**: transformers
|
728 |
+
|
729 |
+
---
|
730 |
+
|
731 |
+
*이 데모는 [Demo Generator](https://huggingface.co/spaces/your-username/demo-generator)로 자동 생성되었습니다.*
|
732 |
+
"""
|
733 |
+
|
734 |
+
with open(os.path.join(demo_dir, "README.md"), 'w', encoding='utf-8') as f:
|
735 |
+
f.write(readme_content)
|
736 |
+
|
737 |
+
# 4. ZIP 파일 생성
|
738 |
+
zip_path = os.path.join(temp_dir, f"{space_name}_demo.zip")
|
739 |
+
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
740 |
+
for root, dirs, files in os.walk(demo_dir):
|
741 |
+
for file in files:
|
742 |
+
file_path = os.path.join(root, file)
|
743 |
+
arcname = os.path.relpath(file_path, demo_dir)
|
744 |
+
zipf.write(file_path, arcname)
|
745 |
+
|
746 |
+
success_msg = f"""
|
747 |
+
## ✅ 데모 생성 완료!
|
748 |
+
|
749 |
+
**{demo_title}** 데모가 성공적으로 생성되었습니다!
|
750 |
+
|
751 |
+
### 📦 포함된 파일들:
|
752 |
+
- `app.py`: 메인 데모 애플리케이션
|
753 |
+
- `requirements.txt`: 필요한 라이브러리 목록
|
754 |
+
- `README.md`: Space 설명 및 설정
|
755 |
+
|
756 |
+
### 🚀 배포 방법:
|
757 |
+
1. 아래 ZIP 파일을 다운로드하세요
|
758 |
+
2. 허깅페이스에서 새 Space를 생성하세요
|
759 |
+
3. 파일들을 업로드하거나 Git으로 push하세요
|
760 |
+
4. 자동으로 빌드되고 배포됩니다!
|
761 |
+
|
762 |
+
### 🎯 태스크: {pipeline_tag}
|
763 |
+
### 🤖 모델: {model_name}
|
764 |
+
"""
|
765 |
+
|
766 |
+
return success_msg, zip_path
|
767 |
+
|
768 |
+
except Exception as e:
|
769 |
+
return f"❌ 패키지 생성 중 오류가 발생했습니다: {str(e)}", None
|
770 |
+
|
771 |
+
def get_task_description(pipeline_tag):
|
772 |
+
"""태스크별 설명 반환"""
|
773 |
+
descriptions = {
|
774 |
+
'text-classification': '텍스트를 입력하면 카테고리별로 분류합니다. 감정분석, 주제분류 등에 사용됩니다.',
|
775 |
+
'question-answering': '컨텍스트와 질문을 입력하면 답변을 찾아줍니다.',
|
776 |
+
'text-generation': '주어진 프롬프트를 이어서 텍스트를 생성합니다.',
|
777 |
+
'summarization': '긴 텍스트를 요약해줍니다.',
|
778 |
+
'translation': '텍스트를 다른 언어로 번역합니다.',
|
779 |
+
'fill-mask': '[MASK] 토큰이 포함된 문장에서 빈칸을 채워줍니다.',
|
780 |
+
'token-classification': '텍스트에서 사람명, 지명, 기관명 등의 개체를 인식합니다.'
|
781 |
+
}
|
782 |
+
return descriptions.get(pipeline_tag, '다양한 NLP 태스크를 수행합니다.')
|
783 |
+
|
784 |
+
# Gradio 인터페이스
|
785 |
+
with gr.Blocks(title="🎮 Demo Generator", theme=gr.themes.Soft()) as demo:
|
786 |
+
|
787 |
+
# 상태 저장용
|
788 |
+
model_info_state = gr.State()
|
789 |
+
demo_possible_state = gr.State()
|
790 |
+
|
791 |
+
gr.Markdown("# 🎮 Hugging Face Demo Generator")
|
792 |
+
gr.Markdown("모델명만 입력하면 바로 작동하는 데모 Space를 자동으로 생성해드립니다!")
|
793 |
+
|
794 |
+
with gr.Row():
|
795 |
+
with gr.Column(scale=1):
|
796 |
+
gr.Markdown("### 🔍 모델 분석")
|
797 |
+
|
798 |
+
model_name_input = gr.Textbox(
|
799 |
+
label="모델명",
|
800 |
+
placeholder="예: klue/bert-base",
|
801 |
+
info="Hugging Face Hub의 정확한 모델명을 입력하세요"
|
802 |
+
)
|
803 |
+
|
804 |
+
analyze_btn = gr.Button("🔍 모델 분석", variant="primary")
|
805 |
+
|
806 |
+
gr.Markdown("### ⚙️ 데모 설정")
|
807 |
+
|
808 |
+
demo_title = gr.Textbox(
|
809 |
+
label="데모 제목",
|
810 |
+
placeholder="예: Korean BERT Sentiment Demo",
|
811 |
+
value=""
|
812 |
+
)
|
813 |
+
|
814 |
+
demo_description = gr.Textbox(
|
815 |
+
label="데모 설명",
|
816 |
+
placeholder="예: 한국어 감정 분석을 위한 BERT 모델 데모",
|
817 |
+
lines=3
|
818 |
+
)
|
819 |
+
|
820 |
+
generate_btn = gr.Button("🎮 데모 생성", variant="secondary")
|
821 |
+
create_package_btn = gr.Button("📦 완전한 패키지 생성", variant="secondary")
|
822 |
+
|
823 |
+
with gr.Column(scale=2):
|
824 |
+
gr.Markdown("### 📊 분석 결과")
|
825 |
+
analysis_output = gr.Markdown("모델명을 입력하고 분석 버튼을 클릭하세요.")
|
826 |
+
|
827 |
+
gr.Markdown("### 💻 생성된 데모 코드")
|
828 |
+
code_output = gr.Code(language="python", label="app.py")
|
829 |
+
|
830 |
+
gr.Markdown("### 📦 다운로드")
|
831 |
+
download_file = gr.File(label="완전한 데모 패키지", visible=False)
|
832 |
+
|
833 |
+
# 이벤트 핸들러
|
834 |
+
def analyze_and_store(model_name):
|
835 |
+
analysis, info, possible = analyze_model(model_name)
|
836 |
+
return analysis, info, possible
|
837 |
+
|
838 |
+
def generate_and_show_code(info, model_name, title, description):
|
839 |
+
if not info:
|
840 |
+
return "먼저 모델을 분석해주세요."
|
841 |
+
|
842 |
+
code, task = generate_demo_code(info, model_name, title, description)
|
843 |
+
return code
|
844 |
+
|
845 |
+
def create_package_and_download(info, model_name, title, description, code):
|
846 |
+
if not info or not code:
|
847 |
+
return "먼저 데모 코드를 생성해주세요.", None
|
848 |
+
|
849 |
+
pipeline_tag = getattr(info, 'pipeline_tag', 'unknown')
|
850 |
+
result, zip_path = create_demo_package(code, pipeline_tag, model_name, title, description)
|
851 |
+
|
852 |
+
if zip_path:
|
853 |
+
return result, gr.File(value=zip_path, visible=True)
|
854 |
+
else:
|
855 |
+
return result, None
|
856 |
+
|
857 |
+
analyze_btn.click(
|
858 |
+
fn=analyze_and_store,
|
859 |
+
inputs=model_name_input,
|
860 |
+
outputs=[analysis_output, model_info_state, demo_possible_state]
|
861 |
+
)
|
862 |
+
|
863 |
+
generate_btn.click(
|
864 |
+
fn=generate_and_show_code,
|
865 |
+
inputs=[model_info_state, model_name_input, demo_title, demo_description],
|
866 |
+
outputs=code_output
|
867 |
+
)
|
868 |
+
|
869 |
+
create_package_btn.click(
|
870 |
+
fn=create_package_and_download,
|
871 |
+
inputs=[model_info_state, model_name_input, demo_title, demo_description, code_output],
|
872 |
+
outputs=[analysis_output, download_file]
|
873 |
+
)
|
874 |
+
|
875 |
+
gr.Markdown("""
|
876 |
+
### 💡 사용법 가이드
|
877 |
+
|
878 |
+
#### 1️⃣ 모델 분석
|
879 |
+
- Hugging Face Hub의 정확한 모델명 입력 (예: `klue/bert-base`)
|
880 |
+
- 모델의 태스크와 호환성 자동 확인
|
881 |
+
|
882 |
+
#### 2️⃣ 데모 설정
|
883 |
+
- **제목**: Space에서 보여질 데모 제목
|
884 |
+
- **설명**: 데모의 용도와 기능 설명
|
885 |
+
|
886 |
+
#### 3️⃣ 코드 생성
|
887 |
+
- 태스크에 맞는 최적화된 Gradio 인터페이스 자동 생성
|
888 |
+
- 바로 복사해서 사용 가능한 완전한 코드
|
889 |
+
|
890 |
+
#### 4️⃣ 패키지 다운로드
|
891 |
+
- `app.py`, `requirements.txt`, `README.md` 포함
|
892 |
+
- ZIP 다운로드 후 바로 Space에 업로드 가능
|
893 |
+
|
894 |
+
### 🎯 지원하는 태스크
|
895 |
+
|
896 |
+
- **텍스트 분류**: 감정분석, 주제분류, 언어감지 등
|
897 |
+
- **질의응답**: 문서 기반 QA 시스템
|
898 |
+
- **텍스트 생성**: 언어모델 기반 텍스트 완성
|
899 |
+
- **요약**: 긴 텍스트의 핵심 요약
|
900 |
+
- **번역**: 언어 간 번역
|
901 |
+
- **빈칸 채우기**: BERT 스타일 마스크 예측
|
902 |
+
- **개체명 인식**: 사람명, 지명, 기관명 등 추출
|
903 |
+
|
904 |
+
### 🔗 워크플로우 연계
|
905 |
+
|
906 |
+
이 도구는 다�� 도구들과 완벽하게 연계됩니다:
|
907 |
+
1. **[Model Search Tool](https://huggingface.co/spaces/your-username/model-search-tool)**: 최적 모델 검색
|
908 |
+
2. **[Dataset Converter](https://huggingface.co/spaces/your-username/dataset-converter)**: 데이터 준비
|
909 |
+
3. **Demo Generator**: 데모 생성 ← *현재 도구*
|
910 |
+
4. **[Model Card Generator](https://huggingface.co/spaces/your-username/model-card-generator)**: 문서화
|
911 |
+
""")
|
912 |
+
|
913 |
+
if __name__ == "__main__":
|
914 |
+
demo.launch()
|
equirements.txt
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
gradio
|
2 |
+
transformers
|
3 |
+
huggingface_hub
|
4 |
+
torch
|