fantos commited on
Commit
6659834
Β·
verified Β·
1 Parent(s): 9d6ae27

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +47 -36
app.py CHANGED
@@ -1,23 +1,25 @@
1
  # img_bot.py
2
- import discord, os, io, re, asyncio, logging, requests, replicate, subprocess
3
- from transformers import pipeline as transformers_pipeline # λ²ˆμ—­ νŒŒμ΄ν”„λΌμΈ
 
4
 
5
  # ── ν™˜κ²½ λ³€μˆ˜ ────────────────────────────────────────────────
6
- TOKEN = os.getenv("DISCORD_TOKEN") # Discord 봇 토큰
7
- CHANNEL_ID = int(os.getenv("DISCORD_CHANNEL_ID")) # κ°μ‹œν•  채널 ID
8
- REPL_TOKEN = (os.getenv("OPENAI_API_KEY") or "").strip() # Replicate 토큰 μž¬μ‚¬μš©
9
- HF_TOKEN = (os.getenv("HF_TOKEN") or "").strip() # Hugging Face 토큰
10
- USE_MSG_INTENT = os.getenv("MESSAGE_CONTENT_INTENT", "1") != "0" # 1=ON(κΈ°λ³Έ), 0=OFF
11
 
12
  if not TOKEN or not CHANNEL_ID:
13
  raise RuntimeError("DISCORD_TOKEN κ³Ό DISCORD_CHANNEL_ID ν™˜κ²½ λ³€μˆ˜λ₯Ό λͺ¨λ‘ μ§€μ •ν•˜μ„Έμš”.")
14
  if not REPL_TOKEN:
15
  raise RuntimeError("OPENAI_API_KEY ν™˜κ²½ λ³€μˆ˜μ— Replicate Personal Access Token 값을 λ„£μ–΄μ£Όμ„Έμš”.")
16
 
17
- os.environ["REPLICATE_API_TOKEN"] = REPL_TOKEN # Replicate κ°€ μ°Έμ‘°ν•  토큰
 
18
 
19
- # ── 이미지 생성 λͺ¨λΈ (Flux Schnell) ─────────────────────────
20
- MODEL = "black-forest-labs/flux-schnell"
 
21
 
22
  # ── λ²ˆμ—­ νŒŒμ΄ν”„λΌμΈ (CPU) ───────────────────────────────────
23
  translator_kwargs = {"device": -1}
@@ -28,7 +30,7 @@ translator = transformers_pipeline(
28
  )
29
 
30
  def ko2en(text: str) -> str:
31
- """ν”„λ‘¬ν”„νŠΈμ— ν•œκΈ€ 포함 μ‹œ μ˜μ–΄ λ²ˆμ—­."""
32
  if re.search(r"[κ°€-힣]", text):
33
  try:
34
  return translator(text, max_length=512)[0]["translation_text"].strip()
@@ -40,14 +42,9 @@ def ko2en(text: str) -> str:
40
  logging.basicConfig(level=logging.INFO,
41
  format="%(asctime)s [%(levelname)s] %(message)s")
42
 
43
- # ── Discord μΈν…νŠΈ μ„€μ • ────────────────────────────────────
44
  intents = discord.Intents.default()
45
- if USE_MSG_INTENT:
46
- intents.message_content = True
47
- logging.info("Message Content Intent = ON "
48
- "(Developer Portal β†’ Bot β†’ Privileged Intents μ—μ„œ ON ν•„μš”)")
49
- else:
50
- logging.info("Message Content Intent = OFF (MESSAGE_CONTENT_INTENT=0)")
51
 
52
  class ImageBot(discord.Client):
53
  async def on_ready(self):
@@ -60,43 +57,57 @@ class ImageBot(discord.Client):
60
  logging.warning(f"web.py μ‹€ν–‰ μ‹€νŒ¨: {e}")
61
 
62
  async def on_message(self, message: discord.Message):
63
- # λ©”μ‹œμ§€ λ‚΄μš© 읽을 κΆŒν•œμ΄ μ—†μœΌλ©΄ λ°”λ‘œ λ°˜ν™˜
64
- if not USE_MSG_INTENT:
65
- return
66
  if message.author.id == self.user.id or message.channel.id != CHANNEL_ID:
67
  return
68
-
69
  prompt_raw = message.content.strip()
70
  if not prompt_raw:
71
  return
72
 
73
- prompt_en = ko2en(prompt_raw)
74
  await message.channel.typing()
75
 
76
- # ── Replicate μš”μ²­ ─────────────────────────────────
77
- def run_replicate():
78
- return list(replicate.run(MODEL, input={"prompt": prompt_en}))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
  try:
81
- images = await asyncio.get_running_loop().run_in_executor(None, run_replicate)
82
  except Exception as e:
83
- logging.error(f"Replicate error: {e}")
84
  await message.reply("⚠️ 이미지 생성 μ‹€νŒ¨!")
85
  return
86
 
87
- # ── Discord 전솑 ──────────────────────────────────
88
  files = []
89
- for idx, item in enumerate(images):
90
- try:
91
- data = item.read() if hasattr(item, "read") else requests.get(item).content
92
- files.append(discord.File(io.BytesIO(data), filename=f"img_{idx}.webp"))
93
- except Exception as e:
94
- logging.warning(f"[IMG {idx}] 처리 μ‹€νŒ¨: {e}")
 
 
 
95
 
96
  await message.reply(files=files if files else None,
97
  content=None if files else "⚠️ 이미지λ₯Ό 전솑할 수 μ—†μŠ΅λ‹ˆλ‹€.")
98
 
99
  # ── μ‹€ν–‰ ────────────────────────────────────────────────────
100
  if __name__ == "__main__":
101
- replicate.Client(api_token=REPL_TOKEN) # Replicate 인증
102
  ImageBot(intents=intents).run(TOKEN)
 
1
  # img_bot.py
2
+ import discord, os, io, re, random, asyncio, logging, requests, replicate, subprocess
3
+ from transformers import pipeline as transformers_pipeline # λ²ˆμ—­ νŒŒμ΄ν”„λΌμΈ
4
+ from gradio_client import Client, handle_file # NEW ─ Gradio API
5
 
6
  # ── ν™˜κ²½ λ³€μˆ˜ ────────────────────────────────────────────────
7
+ TOKEN = os.getenv("DISCORD_TOKEN") # Discord 봇 토큰
8
+ CHANNEL_ID = int(os.getenv("DISCORD_CHANNEL_ID")) # κ°μ‹œν•  채널 ID
9
+ REPL_TOKEN = (os.getenv("OPENAI_API_KEY") or "").strip() # κ·ΈλŒ€λ‘œ μœ μ§€(Replicate 토큰)
10
+ HF_TOKEN = (os.getenv("HF_TOKEN") or "").strip() # Hugging Face Personal Access Token
 
11
 
12
  if not TOKEN or not CHANNEL_ID:
13
  raise RuntimeError("DISCORD_TOKEN κ³Ό DISCORD_CHANNEL_ID ν™˜κ²½ λ³€μˆ˜λ₯Ό λͺ¨λ‘ μ§€μ •ν•˜μ„Έμš”.")
14
  if not REPL_TOKEN:
15
  raise RuntimeError("OPENAI_API_KEY ν™˜κ²½ λ³€μˆ˜μ— Replicate Personal Access Token 값을 λ„£μ–΄μ£Όμ„Έμš”.")
16
 
17
+ # Replicate λΌμ΄λΈŒλŸ¬λ¦¬κ°€ μ°Έμ‘°ν•˜λ„λ‘ 토큰 μ£Όμž… (비둝 μ‚¬μš© μ•ˆ ν•˜μ§€λ§Œ ꡬ쑰 μœ μ§€)
18
+ os.environ["REPLICATE_API_TOKEN"] = REPL_TOKEN
19
 
20
+ # ── Gradio μ„œλ²„ μ—”λ“œν¬μΈνŠΈ ──────────────────────────────────
21
+ GRADIO_URL = "http://211.233.58.201:7896" # μ„œλ²„ μ£Όμ†Œ
22
+ GRADIO_API = "/generate_image" # μ‚¬μš©ν•  ν•¨μˆ˜ 이름
23
 
24
  # ── λ²ˆμ—­ νŒŒμ΄ν”„λΌμΈ (CPU) ───────────────────────────────────
25
  translator_kwargs = {"device": -1}
 
30
  )
31
 
32
  def ko2en(text: str) -> str:
33
+ """ν”„λ‘¬ν”„νŠΈμ— ν•œκΈ€μ΄ 있으면 μ˜μ–΄λ‘œ λ²ˆμ—­."""
34
  if re.search(r"[κ°€-힣]", text):
35
  try:
36
  return translator(text, max_length=512)[0]["translation_text"].strip()
 
42
  logging.basicConfig(level=logging.INFO,
43
  format="%(asctime)s [%(levelname)s] %(message)s")
44
 
45
+ # ── Discord μΈν…νŠΈ ──────────────────────────────────────────
46
  intents = discord.Intents.default()
47
+ intents.message_content = True # λ©”μ‹œμ§€ 읽기 (Portalμ—μ„œ ON ν•„μš”)
 
 
 
 
 
48
 
49
  class ImageBot(discord.Client):
50
  async def on_ready(self):
 
57
  logging.warning(f"web.py μ‹€ν–‰ μ‹€νŒ¨: {e}")
58
 
59
  async def on_message(self, message: discord.Message):
 
 
 
60
  if message.author.id == self.user.id or message.channel.id != CHANNEL_ID:
61
  return
 
62
  prompt_raw = message.content.strip()
63
  if not prompt_raw:
64
  return
65
 
66
+ prompt_en = ko2en(prompt_raw) # ν•œκΈ€ β†’ μ˜μ–΄
67
  await message.channel.typing()
68
 
69
+ # ── Gradio 호좜 ────────────────────────────────────
70
+ def generate_image():
71
+ client = Client(GRADIO_URL)
72
+ seed = random.randint(0, 2**32 - 1)
73
+ result = client.predict(
74
+ prompt=prompt_en,
75
+ width=768,
76
+ height=768,
77
+ guidance=3.5,
78
+ inference_steps=30,
79
+ seed=seed,
80
+ do_img2img=False,
81
+ init_image=None, # img2img μ‚¬μš© μ•ˆ 함
82
+ image2image_strength=0.8,
83
+ resize_img=True,
84
+ api_name=GRADIO_API
85
+ )
86
+ return result[0] # dict (path / url)
87
 
88
  try:
89
+ img_info = await asyncio.get_running_loop().run_in_executor(None, generate_image)
90
  except Exception as e:
91
+ logging.error(f"Gradio API error: {e}")
92
  await message.reply("⚠️ 이미지 생성 μ‹€νŒ¨!")
93
  return
94
 
95
+ # ── 이미지 Discord 전솑 ─────────────────────────────
96
  files = []
97
+ try:
98
+ if img_info.get("path"): # μ„œλ²„κ°€ 파일 경둜둜 λ°˜ν™˜
99
+ with open(img_info["path"], "rb") as f:
100
+ files.append(discord.File(io.BytesIO(f.read()), filename="generated.webp"))
101
+ elif img_info.get("url"): # URL λ˜λŠ” base64
102
+ data = requests.get(img_info["url"]).content
103
+ files.append(discord.File(io.BytesIO(data), filename="generated.webp"))
104
+ except Exception as e:
105
+ logging.warning(f"이미지 처리 μ‹€νŒ¨: {e}")
106
 
107
  await message.reply(files=files if files else None,
108
  content=None if files else "⚠️ 이미지λ₯Ό 전솑할 수 μ—†μŠ΅λ‹ˆλ‹€.")
109
 
110
  # ── μ‹€ν–‰ ────────────────────────────────────────────────────
111
  if __name__ == "__main__":
112
+ replicate.Client(api_token=REPL_TOKEN) # ꡬ쑰 μœ μ§€: Replicate 인증(λ―Έμ‚¬μš©)
113
  ImageBot(intents=intents).run(TOKEN)