Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -5,45 +5,73 @@ from transformers import (
|
|
5 |
)
|
6 |
from PIL import Image
|
7 |
|
8 |
-
#
|
|
|
|
|
9 |
os.environ["HF_FORCE_SAFE_SERIALIZATION"] = "1"
|
10 |
os.environ["XFORMERS_FORCE_DISABLE"] = "1" # audiocraft 내부 플래그
|
11 |
|
12 |
-
#
|
|
|
|
|
13 |
dummy = types.ModuleType("xformers")
|
14 |
dummy.__version__ = "0.0.0"
|
15 |
ops = types.ModuleType("xformers.ops")
|
16 |
|
17 |
-
def
|
|
|
18 |
return torch.nn.functional.scaled_dot_product_attention(
|
19 |
q, k, v, dropout_p=dropout_p, is_causal=False
|
20 |
)
|
21 |
-
class _FakeLowerTriangularMask: pass
|
22 |
|
23 |
-
|
|
|
|
|
|
|
|
|
24 |
ops.LowerTriangularMask = _FakeLowerTriangularMask
|
25 |
dummy.ops = ops
|
26 |
sys.modules["xformers"] = dummy
|
27 |
sys.modules["xformers.ops"] = ops
|
28 |
-
# ────────────────────────────────────────────────────────────
|
29 |
|
30 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
try:
|
32 |
from audiocraft.models import MusicGen
|
33 |
from audiocraft.data.audio import audio_write
|
34 |
-
except ModuleNotFoundError:
|
|
|
35 |
subprocess.check_call([
|
36 |
sys.executable, "-m", "pip", "install",
|
37 |
"git+https://github.com/facebookresearch/audiocraft@main",
|
38 |
"--no-deps", "--use-pep517"
|
39 |
])
|
|
|
|
|
|
|
|
|
40 |
from audiocraft.models import MusicGen
|
41 |
from audiocraft.data.audio import audio_write
|
42 |
|
43 |
-
#
|
|
|
|
|
44 |
caption_model = VisionEncoderDecoderModel.from_pretrained(
|
45 |
"nlpconnect/vit-gpt2-image-captioning",
|
46 |
-
use_safetensors=True,
|
|
|
47 |
)
|
48 |
feature_extractor = ViTImageProcessor.from_pretrained(
|
49 |
"nlpconnect/vit-gpt2-image-captioning"
|
@@ -52,18 +80,22 @@ tokenizer = AutoTokenizer.from_pretrained(
|
|
52 |
"nlpconnect/vit-gpt2-image-captioning"
|
53 |
)
|
54 |
|
55 |
-
#
|
|
|
|
|
56 |
musicgen = MusicGen.get_pretrained("facebook/musicgen-small")
|
57 |
-
musicgen.set_generation_params(duration=10)
|
58 |
|
59 |
-
#
|
|
|
|
|
60 |
def generate_caption(image: Image.Image) -> str:
|
61 |
pixel_values = feature_extractor(images=image, return_tensors="pt").pixel_values
|
62 |
ids = caption_model.generate(pixel_values, max_length=50)
|
63 |
return tokenizer.decode(ids[0], skip_special_tokens=True)
|
64 |
|
65 |
def generate_music(prompt: str) -> str:
|
66 |
-
wav = musicgen.generate([prompt])
|
67 |
tmpdir = tempfile.mkdtemp()
|
68 |
path = os.path.join(tmpdir, "musicgen.wav")
|
69 |
audio_write(path, wav[0], musicgen.sample_rate, strategy="loudness")
|
@@ -71,10 +103,12 @@ def generate_music(prompt: str) -> str:
|
|
71 |
|
72 |
def process(image: Image.Image):
|
73 |
caption = generate_caption(image)
|
74 |
-
path
|
75 |
return caption, path
|
76 |
|
77 |
-
#
|
|
|
|
|
78 |
demo = gr.Interface(
|
79 |
fn=process,
|
80 |
inputs=gr.Image(type="pil"),
|
@@ -82,8 +116,8 @@ demo = gr.Interface(
|
|
82 |
gr.Text(label="AI가 생성한 그림 설명"),
|
83 |
gr.Audio(label="생성된 AI 음악 (MusicGen)")
|
84 |
],
|
85 |
-
title="🎨 AI
|
86 |
-
description="그림을 업로드하면 AI가 설명을 만들고, 설명을 바탕으로 음악을
|
87 |
)
|
88 |
|
89 |
if __name__ == "__main__":
|
|
|
5 |
)
|
6 |
from PIL import Image
|
7 |
|
8 |
+
# ─────────────────────────────────────────────────────────────
|
9 |
+
# 0. 환경 변수
|
10 |
+
# ─────────────────────────────────────────────────────────────
|
11 |
os.environ["HF_FORCE_SAFE_SERIALIZATION"] = "1"
|
12 |
os.environ["XFORMERS_FORCE_DISABLE"] = "1" # audiocraft 내부 플래그
|
13 |
|
14 |
+
# ─────────────────────────────────────────────────────────────
|
15 |
+
# 1. xformers 더미 모듈 주입 (GPU 종속 제거)
|
16 |
+
# ─────────────────────────────────────────────────────────────
|
17 |
dummy = types.ModuleType("xformers")
|
18 |
dummy.__version__ = "0.0.0"
|
19 |
ops = types.ModuleType("xformers.ops")
|
20 |
|
21 |
+
def _fake_mea(q, k, v, *_, dropout_p: float = 0.0, **__):
|
22 |
+
# PyTorch 2.x 표준 S-DPA로 대체 (CPU에서도 동작)
|
23 |
return torch.nn.functional.scaled_dot_product_attention(
|
24 |
q, k, v, dropout_p=dropout_p, is_causal=False
|
25 |
)
|
|
|
26 |
|
27 |
+
class _FakeLowerTriangularMask:
|
28 |
+
"""audiocraft가 타입 존재만 확인하므로 빈 클래스로 대체"""
|
29 |
+
pass
|
30 |
+
|
31 |
+
ops.memory_efficient_attention = _fake_mea
|
32 |
ops.LowerTriangularMask = _FakeLowerTriangularMask
|
33 |
dummy.ops = ops
|
34 |
sys.modules["xformers"] = dummy
|
35 |
sys.modules["xformers.ops"] = ops
|
|
|
36 |
|
37 |
+
# ─────────────────────────────────────────────────────────────
|
38 |
+
# 2. 기타 누락 모듈에 대한 더미(stub) 안전망
|
39 |
+
# (requirements.txt 에 이미 설치하지만, 혹시 빠져도 런타임 통과)
|
40 |
+
# ─────────────────────────────────────────────────────────────
|
41 |
+
for name in (
|
42 |
+
"av", "librosa", "torchdiffeq", "torchmetrics",
|
43 |
+
"pesq", "pystoi", "soxr"
|
44 |
+
):
|
45 |
+
if name not in sys.modules:
|
46 |
+
sys.modules[name] = types.ModuleType(name)
|
47 |
+
|
48 |
+
# ─────────────────────────────────────────────────────────────
|
49 |
+
# 3. audiocraft (MusicGen) 불러오기
|
50 |
+
# ─────────────────────────────────────────────────────────────
|
51 |
try:
|
52 |
from audiocraft.models import MusicGen
|
53 |
from audiocraft.data.audio import audio_write
|
54 |
+
except ModuleNotFoundError:
|
55 |
+
# 로컬 실행 등으로 미설치 시: 의존성 없는 형태로 설치
|
56 |
subprocess.check_call([
|
57 |
sys.executable, "-m", "pip", "install",
|
58 |
"git+https://github.com/facebookresearch/audiocraft@main",
|
59 |
"--no-deps", "--use-pep517"
|
60 |
])
|
61 |
+
# 필요 최소 의존성만 즉석 설치 (stub로도 대부분 통과하지만 안전하게)
|
62 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install",
|
63 |
+
"encodec", "torchdiffeq", "torchmetrics",
|
64 |
+
"librosa", "soxr", "av"])
|
65 |
from audiocraft.models import MusicGen
|
66 |
from audiocraft.data.audio import audio_write
|
67 |
|
68 |
+
# ─────────────────────────────────────────────────────────────
|
69 |
+
# 4. 이미지 캡셔닝 모델
|
70 |
+
# ─────────────────────────────────────────────────────────────
|
71 |
caption_model = VisionEncoderDecoderModel.from_pretrained(
|
72 |
"nlpconnect/vit-gpt2-image-captioning",
|
73 |
+
use_safetensors=True,
|
74 |
+
low_cpu_mem_usage=True
|
75 |
)
|
76 |
feature_extractor = ViTImageProcessor.from_pretrained(
|
77 |
"nlpconnect/vit-gpt2-image-captioning"
|
|
|
80 |
"nlpconnect/vit-gpt2-image-captioning"
|
81 |
)
|
82 |
|
83 |
+
# ─────────────────────────────────────────────────────────────
|
84 |
+
# 5. MusicGen 모델 (CPU 전용)
|
85 |
+
# ─────────────────────────────────────────────────────────────
|
86 |
musicgen = MusicGen.get_pretrained("facebook/musicgen-small")
|
87 |
+
musicgen.set_generation_params(duration=10) # 10초 길이
|
88 |
|
89 |
+
# ─────────────────────────────────────────────────────────────
|
90 |
+
# 6. 파이프라인 함수
|
91 |
+
# ─────────────────────────────────────────────────────────────
|
92 |
def generate_caption(image: Image.Image) -> str:
|
93 |
pixel_values = feature_extractor(images=image, return_tensors="pt").pixel_values
|
94 |
ids = caption_model.generate(pixel_values, max_length=50)
|
95 |
return tokenizer.decode(ids[0], skip_special_tokens=True)
|
96 |
|
97 |
def generate_music(prompt: str) -> str:
|
98 |
+
wav = musicgen.generate([prompt]) # batch size = 1
|
99 |
tmpdir = tempfile.mkdtemp()
|
100 |
path = os.path.join(tmpdir, "musicgen.wav")
|
101 |
audio_write(path, wav[0], musicgen.sample_rate, strategy="loudness")
|
|
|
103 |
|
104 |
def process(image: Image.Image):
|
105 |
caption = generate_caption(image)
|
106 |
+
path = generate_music(f"A cheerful melody inspired by: {caption}")
|
107 |
return caption, path
|
108 |
|
109 |
+
# ─────────────────────────────────────────────────────────────
|
110 |
+
# 7. Gradio UI
|
111 |
+
# ─────────────────────────────────────────────────────────────
|
112 |
demo = gr.Interface(
|
113 |
fn=process,
|
114 |
inputs=gr.Image(type="pil"),
|
|
|
116 |
gr.Text(label="AI가 생성한 그림 설명"),
|
117 |
gr.Audio(label="생성된 AI 음악 (MusicGen)")
|
118 |
],
|
119 |
+
title="🎨 AI 그림-음악 생성기",
|
120 |
+
description="그림을 업로드하면 AI가 설명을 만들고, 설명을 바탕으로 10초 길이의 음악을 생성해 들려줍니다."
|
121 |
)
|
122 |
|
123 |
if __name__ == "__main__":
|