- Mongle RunPod Test Package
- ์ ์ฒด ๊ตฌ์กฐ
- ๋ถ๊ธฐ ๊ธฐ์ค
- ํฌํจ๋ LoRA
- ์คํ ์ค ์๋ ๋ค์ด๋ก๋๋๋ ๋ฒ ์ด์ค ๋ชจ๋ธ
- ํฌํจ๋ ์ฝ๋
- ํฌํจํ์ง ์์ ๊ฒ
- RunPod์์ ๋ฐ๊ธฐ
- ํจํค์ง ์ค์น
- ํ
์คํธ 1: ํ
์คํธ์์ ์บ๋ฆญํฐ์ ํผ๋ ์์ฑ
- Handler 1: ์บ๋ฆญํฐ ์์ฑ
- ํ
์คํธ 2: ์ด๋ฏธ์ง์์ ์บ๋ฆญํฐ์ ํผ๋ ์์ฑ
- Handler 2: ํผ๋ ์์ฑ
- ์๋น์ค ์ฝ๋๋ก ๋ถ๋ฆฌํ ๋
- ์ ์ฒด ๊ตฌ์กฐ
Mongle RunPod Test Package
RunPod์์ Mongle ์บ๋ฆญํฐ ์์ฑ๊ณผ ํผ๋ ์ด๋ฏธ์ง ์์ฑ์ ํ ์คํธํ๊ธฐ ์ํ ํจํค์ง์ ๋๋ค.
์ด repo๋ ํ์ฌ ๋ก์ง์ RunPod์์ ๋ฐ๋ก ๊ฒ์ฆํ๊ธฐ ์ํ ํ ์คํธ ํจํค์ง์ ๋๋ค.
์๋ ๋ ๊ฐ์ง ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
1. end-to-end ํ
์คํธ ํ์ผ๋ก ์ ์ฒด ํ๋ฆ ๊ฒ์ฆ
- test_text2feed_pipeline.py
- test_image2feed_pipeline.py
2. RunPod serverless handler๋ก ์บ๋ฆญํฐ/ํผ๋ ๋ถ๋ฆฌ ์คํ
- handler_character.py
- handler_feed.py
์ ์ฒด ๊ตฌ์กฐ
ํ์ฌ ๋ก์ง์ ํฌ๊ฒ ๋ ๋จ๊ณ๋ก ๋๋ฉ๋๋ค.
1. ์บ๋ฆญํฐ ์์ฑ
- ํ
์คํธ๋ก ์บ๋ฆญํฐ๋ฅผ ๋ง๋ค๊ฑฐ๋
- ์ด๋ฏธ์ง๋ก ์บ๋ฆญํฐ๋ฅผ ๋ง๋ค ์ ์์
- ๊ฒฐ๊ณผ๋ก character.png์ appearance.json์ ๋ง๋ฆ
2. ํผ๋ ์์ฑ
- 1๋จ๊ณ์์ ๋์จ appearance.json
- ์ฌ์ฉ์์ quest text
- ์ ๋ ๊ฐ๋ฅผ ์ฌ์ฉํด์ feed.png๋ฅผ ๋ง๋ฆ
์๋น์ค ๊ด์ ์์๋ ์๋์ฒ๋ผ ๋ถ๋ฆฌํด์ ์ฌ์ฉํฉ๋๋ค.
handler_character
์
๋ ฅ:
- character_ko ๋๋ character_image
์ถ๋ ฅ:
- character.png
- appearance.json
handler_feed
์
๋ ฅ:
- appearance.json
- quest_ko
์ถ๋ ฅ:
- feed.png
- quest_en
์ด repo์๋ ์ ๊ตฌ์กฐ๋ฅผ ์ค์ ๋ก ๋๋ handler ํ์ผ๋ ๋ค์ด ์์ต๋๋ค.
handler_character.py
ํ
์คํธ branch์ ์ด๋ฏธ์ง branch๋ฅผ ๋ชจ๋ ์ฒ๋ฆฌ
character.png์ appearance.json์ ๋ฐํ
handler_feed.py
appearance.json๊ณผ quest_ko๋ฅผ ๋ฐ์ feed.png๋ฅผ ๋ฐํ
๊ทธ๋ฆฌ๊ณ ์๋ ๋ ํ ์คํธ ํ์ผ์ ๋ ๋จ๊ณ๋ฅผ ํ ๋ฒ์ ์ด์ด์ ๋๋ ค๋ณด๊ธฐ ์ํ end-to-end ํ ์คํธ ํ์ผ์ ๋๋ค.
test_text2feed_pipeline.py
ํ
์คํธ ์บ๋ฆญํฐ ์ค๋ช
์์ ์์ํด์ character.png, appearance.json, feed.png๊น์ง ์์ฑ
test_image2feed_pipeline.py
์
๋ ฅ ์บ๋ฆญํฐ ์ด๋ฏธ์ง์์ ์์ํด์ character.png, appearance.json, feed.png๊น์ง ์์ฑ
๋ถ๊ธฐ ๊ธฐ์ค
์บ๋ฆญํฐ ์์ฑ ์ ๋ ฅ์ด ํ ์คํธ์ธ์ง ์ด๋ฏธ์ง์ธ์ง์ ๋ฐ๋ผ ํ์ผ์ ๋ค๋ฅด๊ฒ ์ฌ์ฉํฉ๋๋ค.
ํ
์คํธ๋ก ์บ๋ฆญํฐ ์์ฑ ํ
์คํธ
-> test_text2feed_pipeline.py
์ด๋ฏธ์ง๋ก ์บ๋ฆญํฐ ์์ฑ ํ
์คํธ
-> test_image2feed_pipeline.py
๋ ํ์ผ ๋ชจ๋ ๋ง์ง๋ง์๋ ํผ๋ ์์ฑ๊น์ง ์คํํฉ๋๋ค.
appearance.json + quest_ko
-> Qwen2.5-7B๋ก quest_en ์์ฑ
-> SDXL + lora_v3_32bit + lora_bg_v1๋ก feed.png ์์ฑ
ํฌํจ๋ LoRA
์๋ ๋ LoRA๋ ์ด repo์ ํฌํจ๋์ด ์์ต๋๋ค. ๋ฐ๋ก ์ ๋ก๋ํ๊ฑฐ๋ ๋ณ๋๋ก ๋ฐ์ ํ์๊ฐ ์์ต๋๋ค.
models/lora_v3_32bit/pytorch_lora_weights.safetensors
models/lora_bg_v1/pytorch_lora_weights.safetensors
์ฝ๋๋ ์ ๊ฒฝ๋ก๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํฉ๋๋ค.
์บ๋ฆญํฐ ์์ฑ:
models/lora_v3_32bit
ํผ๋ ์์ฑ:
models/lora_v3_32bit/pytorch_lora_weights.safetensors
models/lora_bg_v1/pytorch_lora_weights.safetensors
์คํ ์ค ์๋ ๋ค์ด๋ก๋๋๋ ๋ฒ ์ด์ค ๋ชจ๋ธ
์๋ ๋ชจ๋ธ๋ค์ ์ด repo์ ํฌํจํ์ง ์์ต๋๋ค. RunPod์์ ์ฒ์ ์คํํ ๋ Hugging Face์์ ์๋์ผ๋ก ๋ค์ด๋ก๋๋ฉ๋๋ค.
stabilityai/stable-diffusion-xl-base-1.0
Qwen/Qwen2.5-7B-Instruct
Qwen/Qwen2.5-VL-7B-Instruct
์ฉ๋๋ ์๋์ ๊ฐ์ต๋๋ค.
stabilityai/stable-diffusion-xl-base-1.0
- character.png ์์ฑ
- feed.png ์์ฑ
Qwen/Qwen2.5-7B-Instruct
- ํ๊ตญ์ด ์บ๋ฆญํฐ ์ค๋ช
-> ์์ด ์บ๋ฆญํฐ ํ๋กฌํํธ
- ํ๊ตญ์ด ํ์คํธ -> ์์ด ์ฅ๋ฉด ํ๋กฌํํธ
Qwen/Qwen2.5-VL-7B-Instruct
- ์บ๋ฆญํฐ ์ด๋ฏธ์ง -> appearance.json ์ถ์ถ
rembg๋ ์ฒซ ์คํ ์ ๋ฐฐ๊ฒฝ ์ ๊ฑฐ์ฉ ๋ชจ๋ธ์ ์บ์์ ๋ค์ด๋ก๋ํ ์ ์์ต๋๋ค.
ํฌํจ๋ ์ฝ๋
test_text2feed_pipeline.py
test_image2feed_pipeline.py
handler_character.py
handler_feed.py
test_qwen25_vl_extract.py
src/pipeline/persona2prompt.py
src/feed/feed_generator_1.py
src/feed/feed_generator_2.py
requirements.txt
ํฌํจํ์ง ์์ ๊ฒ
.env
HF_TOKEN
outputs/
data/
image/
grid/
logs
caches
RunPod์์ ๋ฐ๊ธฐ
LoRA๊ฐ Git LFS๋ก ์ฌ๋ผ๊ฐ ์์ผ๋ฏ๋ก ๋ฐ๋์ git lfs๋ฅผ ๋จผ์ ์ผญ๋๋ค.
git lfs install
git clone https://huggingface.co/Hadimeeee/mongle-hf-package
cd mongle-hf-package
git lfs pull
LoRA๊ฐ ์ค์ ํ์ผ๋ก ๋ฐ์์ก๋์ง ํ์ธํฉ๋๋ค.
du -sh models/lora_v3_32bit/pytorch_lora_weights.safetensors
du -sh models/lora_bg_v1/pytorch_lora_weights.safetensors
๊ฐ๊ฐ ์ฝ 177M ์ ๋๋ก ๋ณด์ฌ์ผ ์ ์์
๋๋ค. ๋ช KB๋ก ๋ณด์ด๋ฉด LFS pointer๋ง ๋ฐ์ ์ํ์
๋๋ค.
ํจํค์ง ์ค์น
pip install -r requirements.txt
RunPod CUDA ์ด๋ฏธ์ง์ ๋ฐ๋ผ torch, torchvision, xformers, bitsandbytes ๋ฒ์ ์ถฉ๋์ด ๋ ์ ์์ต๋๋ค. ๊ทธ ๊ฒฝ์ฐ RunPod ์ด๋ฏธ์ง์ CUDA/PyTorch ๋ฒ์ ์ ๋ง์ถฐ ๋จผ์ ์ค์นํ ๋ค requirements.txt๋ฅผ ์กฐ์ ํ์ธ์.
ํ ์คํธ 1: ํ ์คํธ์์ ์บ๋ฆญํฐ์ ํผ๋ ์์ฑ
ํ ์คํธ ์บ๋ฆญํฐ ์ค๋ช ๋ง์ผ๋ก ์บ๋ฆญํฐ๋ฅผ ๋ง๋ค๊ณ , ์ด์ด์ ํผ๋ ์ด๋ฏธ์ง๊น์ง ์์ฑํฉ๋๋ค.
python test_text2feed_pipeline.py \
--name runpod_text_test \
--character-ko "์ด ์น๊ตฌ๋ ๋ถ๋๋ฌ์ด ์ฒด๋ฆฌํํฌ์ ๊ณฐ ์ธํ์ด์์. ํฌ๋ฆผ์ ๋ฐฐ๋ฅผ ๊ฐ์ง๊ณ ์๊ณ ์์ ๋ฅ๊ทผ ๊ท์ ๋ถํ์ ์ฝ๊ฐ ์์ด์." \
--quest-ko "๊ณต์์์ 30๋ถ ๋ฌ๋ฆฌ๊ธฐ๋ฅผ ์๋ฃํ์ด์!" \
--force
์คํ ํ๋ฆ:
character_ko
-> Qwen2.5-7B
-> English character prompt
-> SDXL + lora_v3_32bit
-> character.png
-> Qwen2.5-VL
-> appearance.json
-> quest_ko๋ฅผ Qwen2.5-7B๋ก quest_en ๋ณํ
-> SDXL + lora_v3_32bit + lora_bg_v1
-> feed.png
์ถ๋ ฅ:
outputs/text2feed/runpod_text_test/
character.png
appearance_raw.txt
appearance.json
character_prompt.json
quest.json
feed.png
results.json
์ด๋ฏธ ์์ด ์บ๋ฆญํฐ ํ๋กฌํํธ๊ฐ ์์ผ๋ฉด Qwen ์บ๋ฆญํฐ ๋ฒ์ญ ๋จ๊ณ๋ฅผ ๊ฑด๋๋ธ ์ ์์ต๋๋ค.
python test_text2feed_pipeline.py \
--name runpod_text_fast \
--character-text "soft cherry pink bear plush mascot with a cream belly, tiny pink nose, rounded ears" \
--quest-ko "๊ณต์์์ 30๋ถ ๋ฌ๋ฆฌ๊ธฐ๋ฅผ ์๋ฃํ์ด์!" \
--force
์ด๋ฏธ ์์ด ํ์คํธ ์ฅ๋ฉด์ด ์์ผ๋ฉด Qwen ํ์คํธ ๋ฒ์ญ ๋จ๊ณ๋ ๊ฑด๋๋ธ ์ ์์ต๋๋ค.
python test_text2feed_pipeline.py \
--name runpod_text_fastest \
--character-text "soft cherry pink bear plush mascot with a cream belly, tiny pink nose, rounded ears" \
--quest-en "running with arms swinging along a fluffy cloud meadow path" \
--force
Handler 1: ์บ๋ฆญํฐ ์์ฑ
RunPod serverless์์ ์บ๋ฆญํฐ ์์ฑ ์ ์ฉ worker๋ก ์ธ ํ์ผ์ ๋๋ค.
handler_character.py
์ด handler๋ ์ ๋ ฅ์ ๋ฐ๋ผ ๋ด๋ถ์์ ๋ branch๋ก ๋๋ฉ๋๋ค.
mode = "text"
character_ko ๋๋ character_text ์ฌ์ฉ
-> character.png
-> appearance.json
mode = "image"
character_image base64 ์ฌ์ฉ
-> rembg
-> appearance.json
-> character.png
ํ ์คํธ branch ์ ๋ ฅ ์์:
{
"input": {
"mode": "text",
"name": "char_text_01",
"character_ko": "์ด ์น๊ตฌ๋ ๋ถ๋๋ฌ์ด ์ฒด๋ฆฌํํฌ์ ๊ณฐ ์ธํ์ด์์. ํฌ๋ฆผ์ ๋ฐฐ์ ์์ ๋ฅ๊ทผ ๊ท๊ฐ ์์ด์.",
"seed": 42,
"character_steps": 30
}
}
์ด๋ฏธ์ง branch ์ ๋ ฅ ์์:
{
"input": {
"mode": "image",
"name": "char_image_01",
"character_image": "<base64 png or jpg>",
"seed": 42,
"character_steps": 30
}
}
์ถ๋ ฅ ์์:
{
"name": "char_text_01",
"mode": "text",
"character_image": "<base64 png>",
"appearance": {
"animal_type": "bear",
"body_color": "soft cherry pink"
},
"appearance_raw": "..."
}
RunPod serverless entrypoint ์์:
python handler_character.py
ํ ์คํธ 2: ์ด๋ฏธ์ง์์ ์บ๋ฆญํฐ์ ํผ๋ ์์ฑ
์ ๋ ฅ ์บ๋ฆญํฐ ์ด๋ฏธ์ง๋ฅผ ์ฌ์ฉํด์ appearance๋ฅผ ์ถ์ถํ๊ณ , ํฝ์ ์บ๋ฆญํฐ์ ํผ๋ ์ด๋ฏธ์ง๋ฅผ ์์ฑํฉ๋๋ค.
๋จผ์ ํ ์คํธ ์ด๋ฏธ์ง๋ฅผ ์ค๋นํฉ๋๋ค.
mkdir -p image
# image/01.jpg ์์น์ ์บ๋ฆญํฐ ์ด๋ฏธ์ง๋ฅผ ์
๋ก๋
์คํ:
python test_image2feed_pipeline.py \
--name runpod_image_test \
--character-image image/01.jpg \
--quest-ko "๊ณต์์์ 30๋ถ ๋ฌ๋ฆฌ๊ธฐ๋ฅผ ์๋ฃํ์ด์!" \
--force
์คํ ํ๋ฆ:
character_image
-> rembg
-> input_nobg.png
-> Qwen2.5-VL
-> appearance.json
-> SDXL + lora_v3_32bit
-> character.png
-> quest_ko๋ฅผ Qwen2.5-7B๋ก quest_en ๋ณํ
-> SDXL + lora_v3_32bit + lora_bg_v1
-> feed.png
์ถ๋ ฅ:
outputs/image2feed/runpod_image_test/
input_nobg.png
appearance_raw.txt
appearance.json
character.png
quest.json
feed.png
results.json
์ด๋ฏธ ์์ด ํ์คํธ ์ฅ๋ฉด์ด ์์ผ๋ฉด ๋ฒ์ญ ๋จ๊ณ๋ฅผ ๊ฑด๋๋ธ ์ ์์ต๋๋ค.
python test_image2feed_pipeline.py \
--name runpod_image_fast \
--character-image image/01.jpg \
--quest-en "running with arms swinging along a fluffy cloud meadow path" \
--force
Handler 2: ํผ๋ ์์ฑ
RunPod serverless์์ ํผ๋ ์์ฑ ์ ์ฉ worker๋ก ์ธ ํ์ผ์ ๋๋ค.
handler_feed.py
์ด handler๋ ์บ๋ฆญํฐ ์์ฑ handler์์ ๋์จ appearance์ ํ์คํธ ํ
์คํธ๋ฅผ ๋ฐ์์ ํผ๋ ์ด๋ฏธ์ง๋ฅผ ๋ง๋ญ๋๋ค.
์ ๋ ฅ ์์:
{
"input": {
"name": "feed_01",
"appearance": {
"animal_type": "bear",
"body_color": "soft cherry pink",
"body_shape": "round plush body",
"eye_style": "small black bead eyes"
},
"quest_ko": "๊ณต์์์ 30๋ถ ๋ฌ๋ฆฌ๊ธฐ๋ฅผ ์๋ฃํ์ด์!",
"feed_seed": 123
}
}
์ด๋ฏธ ์์ด ์ฅ๋ฉด ํ๋กฌํํธ๊ฐ ์์ผ๋ฉด quest_en์ ๋ฃ์ด์ Qwen ๋ฒ์ญ ๋จ๊ณ๋ฅผ ๊ฑด๋๋ธ ์ ์์ต๋๋ค.
{
"input": {
"name": "feed_fast_01",
"appearance": {
"animal_type": "bear",
"body_color": "soft cherry pink"
},
"quest_en": "running with arms swinging along a fluffy cloud meadow path",
"feed_seed": 123
}
}
์ถ๋ ฅ ์์:
{
"name": "feed_01",
"quest": {
"quest_ko": "๊ณต์์์ 30๋ถ ๋ฌ๋ฆฌ๊ธฐ๋ฅผ ์๋ฃํ์ด์!",
"quest_en": "running with arms swinging along a fluffy cloud meadow path"
},
"feed_image": "<base64 png>"
}
RunPod serverless entrypoint ์์:
python handler_feed.py
์๋น์ค ์ฝ๋๋ก ๋ถ๋ฆฌํ ๋
ํ์ฌ ํ
์คํธ ํ์ผ์ end-to-end ๊ฒ์ฆ์ฉ์ด๊ณ , ์ค์ ์๋น์ค์์๋ handler_character.py์ handler_feed.py๋ฅผ ๋๋์ด ์ฌ์ฉํ๋ ๊ฒ์ด ์์ฐ์ค๋ฝ์ต๋๋ค.
handler_character.py
- ์ฑ์์ ์บ๋ฆญํฐ ์์ฑ ์์ฒญ์ ๋ฐ์
- ํ
์คํธ ์
๋ ฅ์ด๋ฉด text branch ์ฌ์ฉ
- ์ด๋ฏธ์ง ์
๋ ฅ์ด๋ฉด image branch ์ฌ์ฉ
- character.png์ appearance.json ๋ฐํ
- ์๋ฒ๋ character.png๋ฅผ S3์ ์
๋ก๋ํ๊ณ appearance๋ฅผ DB์ ์ ์ฅ
handler_feed.py
- ์ฑ์์ quest ์๋ฃ ์์ฒญ์ ๋ฐ์
- ์๋ฒ๊ฐ DB์์ character_id๋ก appearance๋ฅผ ์กฐํ
- appearance + quest_ko๋ฅผ RunPod์ ์ ๋ฌ
- feed.png์ quest_en ๋ฐํ
- ์๋ฒ๋ feed.png๋ฅผ S3์ ์
๋ก๋ํ๊ณ feed record๋ฅผ DB์ ์ ์ฅ
์๋น์ค ํ๋ฆ:
์บ๋ฆญํฐ ์์ฑ ์์ฒญ
-> handler_character
-> character.png + appearance.json
-> S3 + DB ์ ์ฅ
ํ์คํธ ์๋ฃ ์์ฒญ
-> DB์์ appearance ์กฐํ
-> handler_feed
-> feed.png + quest_en
-> S3 + DB ์ ์ฅ
์ฆ, appearance.json์ด ์บ๋ฆญํฐ ์์ฑ๊ณผ ํผ๋ ์์ฑ์ ์ด์ด์ฃผ๋ ์ค๊ฐ ์ฐ์ถ๋ฌผ์
๋๋ค.