chargen / app.py
openfree's picture
Update app.py
acadfc3 verified
from datasets import load_dataset
import gradio as gr
from gradio_client import Client
import json
import torch
from diffusers import FluxPipeline, AutoencoderKL
from live_preview_helpers import flux_pipe_call_that_returns_an_iterable_of_images
import spaces
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
pipe = FluxPipeline.from_pretrained("black-forest-labs/FLUX.1-dev", torch_dtype=torch.bfloat16).to(device)
good_vae = AutoencoderKL.from_pretrained("black-forest-labs/FLUX.1-dev", subfolder="vae", torch_dtype=torch.bfloat16).to(device)
pipe.flux_pipe_call_that_returns_an_iterable_of_images = flux_pipe_call_that_returns_an_iterable_of_images.__get__(pipe)
llm_client = Client("Qwen/Qwen2.5-72B-Instruct")
ds = load_dataset("MohamedRashad/FinePersonas-Lite", split="train")
prompt_template = """λ‹€μŒ 페λ₯΄μ†Œλ‚˜ μ„€λͺ…을 가진 캐릭터λ₯Ό μƒμ„±ν•˜μ„Έμš”: {persona_description}
λ‹€μŒ μ„€λͺ…μ˜ μ„Έκ³„μ—μ„œ: {world_description}
λ‹€μŒ ν•„λ“œλ₯Ό ν¬ν•¨ν•˜λŠ” JSON ν˜•μ‹μœΌλ‘œ 캐릭터λ₯Ό μž‘μ„±ν•˜μ„Έμš”:
- name: μΊλ¦­ν„°μ˜ 이름
- background: μΊλ¦­ν„°μ˜ λ°°κ²½
- appearance: μΊλ¦­ν„°μ˜ μ™Έλͺ¨
- personality: μΊλ¦­ν„°μ˜ 성격
- skills_and_abilities: μΊλ¦­ν„°μ˜ 기술과 λŠ₯λ ₯
- goals: μΊλ¦­ν„°μ˜ λͺ©ν‘œ
- conflicts: μΊλ¦­ν„°μ˜ κ°ˆλ“±
- backstory: μΊλ¦­ν„°μ˜ κ³Όκ±° 이야기
- current_situation: μΊλ¦­ν„°μ˜ ν˜„μž¬ 상황
- spoken_lines: μΊλ¦­ν„°μ˜ λŒ€μ‚¬ (λ¬Έμžμ—΄ 리슀트)
JSON ν˜•μ‹μ˜ 캐릭터 μ„€λͺ…λ§Œ μž‘μ„±ν•˜κ³  λ‹€λ₯Έ λ‚΄μš©μ€ ν¬ν•¨ν•˜μ§€ λ§ˆμ„Έμš”. '```'도 ν¬ν•¨ν•˜μ§€ λ§ˆμ„Έμš”.
"""
world_description_prompt = "λ…νŠΉν•˜κ³  λ¬΄μž‘μœ„ν•œ 세계 μ„€λͺ…을 μƒμ„±ν•˜μ„Έμš” (세계 μ„€λͺ…λ§Œ μž‘μ„±ν•˜κ³  λ‹€λ₯Έ λ‚΄μš©μ€ ν¬ν•¨ν•˜μ§€ λ§ˆμ„Έμš”)."
def get_random_world_description():
result = llm_client.predict(
query=world_description_prompt,
history=[],
system="λ°˜λ“œμ‹œ ν•œκΈ€λ‘œ 좜λ ₯ν•˜λΌ. 당신은 도움이 λ˜λŠ” μ–΄μ‹œμŠ€ν„΄νŠΈμž…λ‹ˆλ‹€.",
api_name="/model_chat",
)
return result[1][0][-1]
def get_random_persona_description():
return ds.shuffle().select([100])[0]["persona"]
@spaces.GPU(duration=75)
def infer_flux(character_json):
for image in pipe.flux_pipe_call_that_returns_an_iterable_of_images(
prompt=character_json["appearance"],
guidance_scale=3.5,
num_inference_steps=28,
width=1024,
height=1024,
generator=torch.Generator("cpu").manual_seed(0),
output_type="pil",
good_vae=good_vae,
):
yield image
def generate_character(world_description, persona_description, progress=gr.Progress(track_tqdm=True)):
result = llm_client.predict(
query=prompt_template.format(
persona_description=persona_description, world_description=world_description
),
history=[],
system="λ°˜λ“œμ‹œ ν•œκΈ€λ‘œ 좜λ ₯ν•˜λΌ. 당신은 도움이 λ˜λŠ” μ–΄μ‹œμŠ€ν„΄νŠΈμž…λ‹ˆλ‹€.",
api_name="/model_chat",
)
output = json.loads(result[1][0][-1])
return output
with gr.Blocks(title="캐릭터 μžλ™ 생성", theme="Nymbo/Nymbo_Theme") as app:
with gr.Column():
gr.HTML("<center><h1>캐릭터 생성기</h1></center>")
with gr.Column():
with gr.Row():
world_description = gr.Textbox(lines=10, label="세계 μ„€λͺ…", scale=4)
persona_description = gr.Textbox(lines=10, label="페λ₯΄μ†Œλ‚˜ μ„€λͺ…", value=get_random_persona_description(), scale=1)
with gr.Row():
random_world_button = gr.Button(value="λ¬΄μž‘μœ„ 세계 μ„€λͺ… κ°€μ Έμ˜€κΈ°", variant="secondary", scale=1)
submit_button = gr.Button(value="ν₯미둜운 캐릭터 μƒμ„±ν•˜κΈ°!", variant="primary", scale=5)
random_persona_button = gr.Button(value="λ¬΄μž‘μœ„ 페λ₯΄μ†Œλ‚˜ μ„€λͺ… κ°€μ Έμ˜€κΈ°", variant="secondary", scale=1)
with gr.Row():
character_image = gr.Image(label="캐릭터 이미지")
character_json = gr.JSON(label="캐릭터 μ„€λͺ…")
examples = gr.Examples(
[
"λ§ˆλ²•μ΄ μ‹€μ‘΄ν•˜κ³  μš©λ“€μ΄ ν•˜λŠ˜μ„ λ‚ μ•„λ‹€λ‹ˆλŠ” μ„Έκ³„μ—μ„œ, λͺ¨ν—˜κ°€λ“€μ˜ 일행이 전섀적인 μš©μ™•μ˜ 검을 μ°Ύμ•„ λ‚˜μ„­λ‹ˆλ‹€.",
"에토리아에 μ˜€μ‹  것을 ν™˜μ˜ν•©λ‹ˆλ‹€. 이곳은 물리 법칙이 κ³ λŒ€ λ§ˆλ²•μ˜ μ˜μ§€μ— 따라 νœ˜μ–΄μ§€λŠ” κ΄‘ν™œν•˜κ³  μ‹ λΉ„λ‘œμš΄ μ˜μ—­μž…λ‹ˆλ‹€. 이 μ„Έκ³„λŠ” λμ—†λŠ” ν•˜λŠ˜μ— λ–  μžˆλŠ” μˆ˜λ§Žμ€ λΆ€μœ  μ„¬μœΌλ‘œ κ΅¬μ„±λ˜μ–΄ 있으며, 각 섬은 생λͺ…κ³Ό λΉ„λ°€λ‘œ 가득 μ°¬ λ…νŠΉν•œ μƒνƒœκ³„μž…λ‹ˆλ‹€. μ—ν† λ¦¬μ•„μ˜ 섬듀은 μšΈμ°½ν•œ μ •κΈ€λΆ€ν„° ν™©λŸ‰ν•œ μˆ˜μ • μ‚¬λ§‰κΉŒμ§€ λ‹€μ–‘ν•©λ‹ˆλ‹€. μ–΄λ–€ 섬은 λ„μ‹œ λΈ”λ‘λ§ŒνΌ μž‘κ³ , μ–΄λ–€ 섬은 수백 λ§ˆμΌμ— 걸쳐 μžˆμŠ΅λ‹ˆλ‹€. 이 λΆ„λ¦¬λœ 땅덩어리듀을 μ—°κ²°ν•˜λŠ” 것은 μˆœμˆ˜ν•œ μ—λ„ˆμ§€λ‘œ λ§Œλ“€μ–΄μ§„ λ°˜μ§μ΄λŠ” 닀리이며, beaten pathλ₯Ό λ²—μ–΄λ‚  만큼 μš©κ°ν•œ μ‚¬λžŒλ“€μ€ λ¨Ό 거리λ₯Ό μˆœκ°„μ μœΌλ‘œ 이동할 수 μžˆλŠ” μˆ¨κ²¨μ§„ 포털을 찾을 수 μžˆμŠ΅λ‹ˆλ‹€. μ—ν† λ¦¬μ•„μ˜ 주민듀은 κ·Έ ν’κ²½λ§ŒνΌμ΄λ‚˜ λ‹€μ–‘ν•©λ‹ˆλ‹€. 인간듀은 λΉ›μ˜ μ—ν…Œλ₯΄ 쑴재, λ°”μœ„ ν”ΌλΆ€λ₯Ό 가진 거인, λΆ„λ₯˜ν•˜κΈ° μ–΄λ €μš΄ λ³€ν˜• 생물듀과 κ³΅μ‘΄ν•©λ‹ˆλ‹€. κ³ λŒ€ μœ μ λ“€μ΄ 섬듀을 점점이 μž₯μ‹ν•˜κ³  μžˆμ–΄, κ³Όν•™κ³Ό λ§ˆλ²•μ˜ 경계λ₯Ό νλ¦¬λŠ” μžŠν˜€μ§„ λ¬Έλͺ…κ³Ό κΈ°μˆ μ„ μ•”μ‹œν•©λ‹ˆλ‹€. μ„Έκ³„λŠ” μ—ν…Œλ₯΄λΌλŠ” μ‹ λΉ„ν•œ 물질둜 움직이며, 이것은 λͺ¨λ“  것을 톡해 νλ¦…λ‹ˆλ‹€. μ—ν…Œλ₯΄μ˜ νž˜μ„ λ‹€λ£° 수 μžˆλŠ” μ‚¬λžŒλ“€μ€ ν˜„μ‹€ 자체λ₯Ό μ‘°μž‘ν•  수 μžˆλŠ” κ°•λ ₯ν•œ λ§ˆλ²•μ‚¬κ°€ λ©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ μ—ν…Œλ₯΄λŠ” ν•œμ •λœ μžμ›μ΄λ©°, κ·Έ ν¬μ†Œμ„±μœΌλ‘œ 인해 ν†΅μ œκΆŒμ„ 놓고 λ‹€νˆ¬λŠ” λ‹€μ–‘ν•œ μ„Έλ ₯ 사이에 κ°ˆλ“±μ΄ μƒκ²ΌμŠ΅λ‹ˆλ‹€. 섬듀 μ‚¬μ΄μ˜ ν•˜λŠ˜μ—μ„œλŠ” μ›…μž₯ν•œ 비행선듀이 λ§ˆλ²•μ˜ κΈ°λ₯˜λ₯Ό 타고 ν•­ν•΄ν•˜λ©° 무역과 νƒν—˜μ„ μ΄‰μ§„ν•©λ‹ˆλ‹€. 해적듀과 ν•˜λŠ˜ μŠ΅κ²©μžλ“€μ΄ ꡬ름 κΉŠμˆ™ν•œ 곳에 μˆ¨μ–΄ λ°©μ‹¬ν•œ λ¨Ήμž‡κ°μ„ 항상 노리고 μžˆμŠ΅λ‹ˆλ‹€. λΆ€μœ ν•˜λŠ” λ•… κΉŠμˆ™νžˆ μ•„λž˜μ—λŠ” μ–Έλ”λ³΄μ΄λ“œλΌλŠ” μ–΄λ‘‘κ³  μœ„ν—˜ν•œ μ˜μ—­μ΄ 있으며, μ•…λͺ½ 같은 생물듀과 말둜 ν‘œν˜„ν•  수 μ—†λŠ” λΆ€κ°€ κ°€λ“ν•©λ‹ˆλ‹€. 였직 κ°€μž₯ μš©κ°ν•œ λͺ¨ν—˜κ°€λ“€λ§Œμ΄ κ·Έ 깊이λ₯Ό νƒν—˜ν•˜λ € ν•˜κ³ , 더 적은 수만이 κ·Έ 이야기λ₯Ό λ“€λ €μ£ΌκΈ° μœ„ν•΄ λŒμ•„μ˜΅λ‹ˆλ‹€. 항상 μ‘΄μž¬ν•˜λŠ” μœ„ν˜‘μœΌλ‘œ, 혼돈의 폭풍이 μ•Œλ €μ§„ μ„Έκ³„μ˜ κ°€μž₯μžλ¦¬μ—μ„œ λ§Ήμœ„λ₯Ό λ–¨μΉ˜λ©° κ·Έ 길에 μžˆλŠ” λͺ¨λ“  것을 μ‚ΌμΌœλ²„λ¦΄ μœ„ν˜‘μ„ κ°€ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μ—ν† λ¦¬μ•„μ˜ μ˜μ›…λ“€μ—κ²Œ μ„Έκ³„μ˜ 비밀을 밝히고 λ„ˆλ¬΄ 늦기 전에 λ‹€κ°€μ˜€λŠ” 어둠을 물리칠 방법을 μ°ΎλŠ” μž„λ¬΄κ°€ μ£Όμ–΄μ‘ŒμŠ΅λ‹ˆλ‹€. μ—ν† λ¦¬μ•„μ—μ„œλŠ” λͺ¨λ“  섬이 이야기λ₯Ό ν’ˆκ³  있고, λͺ¨λ“  생물이 비밀을 가지고 있으며, λͺ¨λ“  λͺ¨ν—˜μ΄ 이 경이둭고 μœ„ν—˜μ— μ²˜ν•œ μ„Έκ³„μ˜ 운λͺ…을 λ°”κΏ€ 수 μžˆμŠ΅λ‹ˆλ‹€.",
"제 상상 속 μ„Έκ³„μ—λŠ” 'μ˜€λΌν‚€μŠ€'λΌλŠ” λ„μ‹œκ°€ μžˆμŠ΅λ‹ˆλ‹€. 이 λ„μ‹œλŠ” μˆœμˆ˜ν•œ λΉ›μ˜ κΈ°λ‘₯ μœ„μ— λ–  μžˆμŠ΅λ‹ˆλ‹€. λ„μ‹œμ˜ 벽은 μˆ˜μ • 유리둜 λ§Œλ“€μ–΄μ Έ μžˆμ–΄ 항상 μƒˆλ²½κ³Ό ν™©ν˜Όμ˜ 색을 λ°˜μ‚¬ν•˜λ©° μ˜μ›ν•œ μ²œμƒμ˜ 광채λ₯Ό λ°œν•©λ‹ˆλ‹€. 건물듀은 κ³„μ ˆμ— 따라 μˆ¨μ„ 쉬며 ν˜•νƒœλ₯Ό λ°”κΏ‰λ‹ˆλ‹€ - λ΄„μ—λŠ” μ„±μž₯ν•˜κ³ , μ—¬λ¦„μ—λŠ” 강해지며, κ°€μ„μ—λŠ” ν‡΄μƒ‰ν•˜κΈ° μ‹œμž‘ν•΄ 겨울이 되면 μ•ˆκ°œκ°€ λ©λ‹ˆλ‹€.",
],
world_description,
)
submit_button.click(
generate_character, [world_description, persona_description], outputs=[character_json]
).then(fn=infer_flux, inputs=[character_json], outputs=[character_image])
random_world_button.click(
get_random_world_description, outputs=[world_description]
)
random_persona_button.click(
get_random_persona_description, outputs=[persona_description]
)
app.queue().launch(share=False)