Google Colab์์
demo.launch(share=True)
ํ ์ค๋ก ์ ์ธ๊ณ ๋๊ตฌ๋ ์ ์ ๊ฐ๋ฅํ ์น ์ฑ์ ๋ง๋ค ์ ์์ต๋๋ค. ๋๋์ฒด ์ด๋ป๊ฒ ๊ฐ๋ฅํ ๊ฑธ๊น์? ๋คํธ์ํฌ์ ์๋ฆฌ๋ถํฐ ์ค์ ๊ตฌํ๊น์ง ์๋ฒฝํ ํํค์ณ๋ด ๋๋ค.
Google Colab์ ๊ฒฉ๋ฆฌ๋ ๊ฐ์ ๋จธ์ (VM)์์ ์คํ๋ฉ๋๋ค.
[๋น์ ์ ์ปดํจํฐ]
โ ๋ธ๋ผ์ฐ์ ๋ก Colab ์ ์ โ
[Google ์๋ฒ - Colab VM]
โ ???
[๋ค๋ฅธ ์ฌ๋์ ์ปดํจํฐ] โ ์ ๊ทผ ๋ถ๊ฐ!
1. Public IP๊ฐ ์์
# Colab ์
์์ ์คํ
import socket
import requests
# ์ธ๋ถ์์ ๋ณด์ด๋ IP (Public IP)
public_ip = requests.get('https://api.ipify.org').text
print(f"Public IP: {public_ip}") # ์: 142.250.x.x
# Colab VM์ ๋ด๋ถ IP (Private IP)
hostname = socket.gethostname()
internal_ip = socket.gethostbyname(hostname)
print(f"Internal IP: {internal_ip}") # ์: 172.28.0.x
๊ฒฐ๊ณผ:
2. ์ธ๋ฐ์ด๋ ๋ฐฉํ๋ฒฝ ์ฐจ๋จ
Colab VM์ ๋ฐฉํ๋ฒฝ ์ ์ฑ :
# ๋ค์ด์ค๋ ์ฐ๊ฒฐ (Inbound) - ๋ชจ๋ ์ฐจ๋จ โ
์ธ๋ถ โ Colab VM (ํฌํธ 80, 8080, 7860 ๋ฑ ๋ชจ๋ ์ฐจ๋จ)
# ๋๊ฐ๋ ์ฐ๊ฒฐ (Outbound) - ํ์ฉ โ
Colab VM โ ์ธ๋ถ (์น์ฌ์ดํธ, API ๋ฑ ์ ์ ๊ฐ๋ฅ)
# Colab ์
1: ๊ฐ๋จํ ์น ์๋ฒ ์คํ
from flask import Flask
import threading
app = Flask(__name__)
@app.route('/')
def home():
return "Hello from Colab!"
def run():
app.run(host='0.0.0.0', port=5000)
thread = threading.Thread(target=run)
thread.daemon = True
thread.start()
print("์๋ฒ ์คํ ์ค: http://127.0.0.1:5000")
# Colab ์
2: ๋ก์ปฌ์์๋ ์ ๊ทผ ๊ฐ๋ฅ
import requests
response = requests.get('http://127.0.0.1:5000')
print(response.text) # โ
"Hello from Colab!" ์ถ๋ ฅ
# ์ธ๋ถ ์ปดํจํฐ์์ ์๋ (์คํจ)
# Colab์ Public IP๋ฅผ ์์๋...
import requests
response = requests.get('http://142.250.x.x:5000', timeout=5)
# โ requests.exceptions.ConnectTimeout: ์ฐ๊ฒฐ ์๊ฐ ์ด๊ณผ
๊ฒฐ๋ก : Colab VM ๋ด๋ถ์์๋ ์๋ํ์ง๋ง, ์ธ๋ถ์์๋ ์ ๊ทผ ๋ถ๊ฐ๋ฅ!
"๋ค์ด์ฌ ์ ์๋ค๋ฉด, ๋ด๊ฐ ๋จผ์ ๋๊ฐ์ ๋ฌธ์ ์ด์ด๋์!"
[์ธ๋ถ ์ฌ์ฉ์]
โ ์์ฒญ (Inbound)
โ ๋ฐฉํ๋ฒฝ ์ฐจ๋จ
[Colab VM]
[์ธ๋ถ ์ฌ์ฉ์]
โ ์์ฒญ
[์ค๊ณ ์๋ฒ] (gradio.live)
โ ์ด๋ฏธ ์ด๋ฆฐ ํฐ๋๋ก ์ ๋ฌ
โ (Colab์ด ๋จผ์ ์ฐ๊ฒฐํด๋ )
[Colab VM] โ ์์๋ฐ์ด๋ ์ฐ๊ฒฐ โ
๋น์ ์ ์ง์ ํน๋ณํ ์ ํ๊ธฐ๊ฐ ์์ต๋๋ค:
์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ (๋ถ๊ฐ๋ฅ):
์น๊ตฌ๊ฐ ๋น์ ์๊ฒ ์ ํํ๋ ค๊ณ ์๋
โ ๋ฒํธ๋ ์์ง๋ง ์ฐ๊ฒฐ ์ ๋จ โ
๋ฆฌ๋ฒ์ค ํฐ๋ ๋ฐฉ๋ฒ (๊ฐ๋ฅ):
1. ๋น์ ์ด ๊ตํ์(Gradio)์๊ฒ ๋จผ์ ์ ํ ๊ฑธ๊ธฐ
2. "๊ณ์ ์ฐ๊ฒฐ ์ ์งํด์ฃผ์ธ์"๋ผ๊ณ ์์ฒญ
3. ์น๊ตฌ๊ฐ ๊ตํ์์๊ฒ ์ ํ
4. ๊ตํ์์ด ๋น์ ์ ์ด๋ฏธ ์ฐ๊ฒฐ๋ ํ์ ์ผ๋ก ์ค๊ณ
5. ์๋ฐฉํฅ ๋ํ ๊ฐ๋ฅ! โ
TCP ์ฐ๊ฒฐ์ ํน์ฑ:
# ์ฐ๊ฒฐ์ด ํ ๋ฒ ์ฑ๋ฆฝ(ESTABLISHED)๋๋ฉด
# ์๋ฐฉํฅ ํต์ ์ด ๊ฐ๋ฅํฉ๋๋ค
[Colab] --SYNโ [์๋ฒ] # Colab์ด ๋จผ์ ์์ฒญ
[Colab] โSYN-ACK-- [์๋ฒ] # ์๋ฒ๊ฐ ์๋ฝ
[Colab] --ACKโ [์๋ฒ] # ์ฐ๊ฒฐ ์๋ฃ
# ์ด์ ์๋ฐฉํฅ ํต์ ๊ฐ๋ฅ
[Colab] โ [์๋ฒ]
๋ฐฉํ๋ฒฝ์ ํ์ฉ ๊ท์น:
# iptables ๊ท์น (Colab VM)
# ์๋ก์ด ์ธ๋ฐ์ด๋ ์ฐ๊ฒฐ ์ฐจ๋จ
-A INPUT -m state --state NEW -j DROP
# ํ์ง๋ง! ์ด๋ฏธ ์ฐ๊ฒฐ๋(ESTABLISHED) ํธ๋ํฝ์ ํ์ฉ
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# ์์๋ฐ์ด๋๋ ๋ชจ๋ ํ์ฉ
-A OUTPUT -j ACCEPT
๋ฐ๋ผ์:
1. Colab์์ ์ธ๋ถ๋ก ์ฐ๊ฒฐ (NEW ์์๋ฐ์ด๋) โ โ
ํ์ฉ
2. ์ฐ๊ฒฐ ์ฑ๊ณต โ ์ํ๊ฐ ESTABLISHED๋ก ๋ณ๊ฒฝ
3. ์ด์ ์๋ฐฉํฅ ํต์ ๊ฐ๋ฅ โ โ
ํ์ฉ
๋ค, ๋ง์ต๋๋ค! Gradio๋ gradio.live
๋๋ฉ์ธ์ ์ค์ ์ค๊ณ ์๋ฒ๋ฅผ ์ด์ํ๊ณ ์์ต๋๋ค.
[Cloudflare CDN]
โ
[gradio.live ์๋ฒ๋ค] (์ฌ๋ฌ ๋)
โ
[๋ก๋ ๋ฐธ๋ฐ์]
โ
[ํฐ๋ ๊ด๋ฆฌ ์๋ฒ ํด๋ฌ์คํฐ]
โโ ํฐ๋ 1: abc123.gradio.live โ Colab VM #1
โโ ํฐ๋ 2: xyz789.gradio.live โ Colab VM #2
โโ ํฐ๋ 3: def456.gradio.live โ Colab VM #3
โโ ...
1. ํฐ๋ ๋ฑ๋ก ๊ด๋ฆฌ
# Colab์ด share=True๋ก ์คํํ๋ฉด
# Gradio ์๋ฒ์ ํฐ๋ ์์ฒญ์ ๋ณด๋
๋๋ค
{
"action": "create_tunnel",
"local_port": 7860,
"auth": "optional_credentials"
}
# Gradio ์๋ฒ ์๋ต
{
"tunnel_id": "abc123xyz",
"public_url": "https://abc123xyz.gradio.live",
"websocket_url": "wss://api.gradio.app/tunnel/abc123xyz",
"expires_at": "2025-10-07T00:00:00Z" # 72์๊ฐ ํ
}
2. ์ค์๊ฐ ํ๋ก์ (์ค๊ณ)
# ์ฌ์ฉ์๊ฐ gradio.live์ ์์ฒญํ๋ฉด
# Gradio ์๋ฒ๊ฐ ์ค์๊ฐ์ผ๋ก ์ค๊ณํฉ๋๋ค
# ์์ฌ ์ฝ๋ (Gradio ์๋ฒ ์ธก)
@app.route('/<tunnel_id>/*')
async def proxy_request(tunnel_id, path):
# 1. ํด๋น ํฐ๋ ์ฐพ๊ธฐ
tunnel = get_tunnel(tunnel_id)
if not tunnel or not tunnel.is_connected():
return "Tunnel not found", 404
# 2. Colab์ผ๋ก ์์ฒญ ์ ๋ฌ (WebSocket)
response = await tunnel.send_request({
'method': request.method,
'path': path,
'headers': dict(request.headers),
'body': request.data
})
# 3. Colab์ ์๋ต์ ์ฌ์ฉ์์๊ฒ ๋ฐํ
return response['body'], response['status']
3. ์ฐ๊ฒฐ ์ ์ง (Keep-Alive)
# Gradio ์๋ฒ๋ ์ฃผ๊ธฐ์ ์ผ๋ก ping์ ๋ณด๋
๋๋ค
while tunnel.is_active():
tunnel.send_ping()
await asyncio.sleep(30) # 30์ด๋ง๋ค ํ์ธ
if tunnel.last_pong > 60: # 60์ด ์๋ต ์์ผ๋ฉด
tunnel.close() # ํฐ๋ ์ข
๋ฃ
[์ฌ์ฉ์ ๋ธ๋ผ์ฐ์ ]
โ โ HTTP GET https://abc123.gradio.live/
[Cloudflare CDN]
โ โก ์บ์ ํ์ธ (๋์ ์ฝํ
์ธ ๋ผ Miss)
[gradio.live ๋ก๋ ๋ฐธ๋ฐ์]
โ โข ํฐ๋ ID๋ก ๋ผ์ฐํ
[ํฐ๋ ๊ด๋ฆฌ ์๋ฒ]
โ โฃ WebSocket์ผ๋ก ์์ฒญ ์ ์ก
{
"type": "http_request",
"method": "GET",
"path": "/",
"headers": {...}
}
[Colab VM]
โ โค WebSocket์์ ๋ฉ์์ง ์์
โ โฅ localhost:7860์ผ๋ก HTTP ์์ฒญ
[Gradio ์ฑ]
โ โฆ ์์ฒญ ์ฒ๋ฆฌ (HTML ์์ฑ)
[Colab VM]
โ โง ์๋ต์ WebSocket์ผ๋ก ์ ์ก
{
"type": "http_response",
"status": 200,
"body": "<html>..."
}
[ํฐ๋ ๊ด๋ฆฌ ์๋ฒ]
โ โจ HTTP ์๋ต์ผ๋ก ๋ณํ
[Cloudflare CDN]
โ โฉ ์ ์ ๋ฆฌ์์ค ์บ์ฑ
[์ฌ์ฉ์ ๋ธ๋ผ์ฐ์ ]
โโ โช ํ์ด์ง ๋ ๋๋ง
์ฒ๋ฆฌ ์๊ฐ:
import gradio as gr
def greet(name):
return f"Hello {name}!"
demo = gr.Interface(fn=greet, inputs="text", outputs="text")
# share=False (๊ธฐ๋ณธ๊ฐ)
demo.launch()
๋ด๋ถ ๋์:
# gradio/blocks.py (simplified)
class Blocks:
def launch(self, share=False, server_port=None):
# 1. Flask ์๋ฒ ์์ฑ
self.server = create_flask_app(self)
# 2. ๋ก์ปฌ ํฌํธ์์ ์์
if server_port is None:
server_port = 7860
self.server.run(host='127.0.0.1', port=server_port)
print(f"Running on local URL: http://127.0.0.1:{server_port}")
ํ์ฌ ์ํ:
[Colab VM]
โโ Flask ์๋ฒ (127.0.0.1:7860)
โโ Gradio UI
โโ ์ธ๋ถ ์ ๊ทผ ๋ถ๊ฐ โ
demo.launch(share=True) # ์ด ํ ์ค์ด ๋ง๋ฒ์ ์ผ์ผํต๋๋ค!
๋ด๋ถ ๋์ (์ค์ Gradio ์ฝ๋ ๊ธฐ๋ฐ):
# gradio/networking.py
import websocket
import threading
import requests
import json
class Tunnel:
GRADIO_API = "https://api.gradio.app"
def __init__(self, local_port):
self.local_port = local_port
self.ws = None
self.public_url = None
def start(self):
# 1. Gradio API์ ํฐ๋ ์์ฑ ์์ฒญ (HTTP POST)
response = requests.post(
f"{self.GRADIO_API}/v2/tunnel-request",
json={
'local_port': self.local_port,
'gradio_version': '4.x.x'
},
timeout=10
)
data = response.json()
self.tunnel_id = data['tunnel_id']
self.public_url = f"https://{self.tunnel_id}.gradio.live"
print(f"๐ Public URL: {self.public_url}")
print(f"โณ This share link expires in 72 hours.")
# 2. WebSocket ์ฐ๊ฒฐ ์์ฑ
ws_url = f"wss://api.gradio.app/v2/tunnel/{self.tunnel_id}"
self.ws = websocket.WebSocketApp(
ws_url,
on_open=self.on_open,
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close
)
# 3. ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋์์ WebSocket ์คํ
self.ws_thread = threading.Thread(
target=self.ws.run_forever,
kwargs={'ping_interval': 30, 'ping_timeout': 10}
)
self.ws_thread.daemon = True
self.ws_thread.start()
return self.public_url
def on_open(self, ws):
"""WebSocket ์ฐ๊ฒฐ์ด ์ด๋ ธ์ ๋"""
print(f"โ
Tunnel connected: {self.tunnel_id}")
# ํฐ๋ ๋ฑ๋ก ๋ฉ์์ง ์ ์ก
ws.send(json.dumps({
'type': 'register',
'local_port': self.local_port,
'tunnel_id': self.tunnel_id
}))
def on_message(self, ws, message):
"""Gradio ์๋ฒ๋ก๋ถํฐ ๋ฉ์์ง(์์ฒญ) ์์ """
try:
data = json.loads(message)
if data['type'] == 'http_request':
# Gradio ์๋ฒ๊ฐ ์ฌ์ฉ์ ์์ฒญ์ ์ค๊ณ
self.handle_request(data)
elif data['type'] == 'ping':
# Keep-alive
ws.send(json.dumps({'type': 'pong'}))
except Exception as e:
print(f"Error handling message: {e}")
def handle_request(self, request_data):
"""์ฌ์ฉ์ ์์ฒญ์ ๋ก์ปฌ ์๋ฒ๋ก ํ๋ก์"""
import requests
# ๋ก์ปฌ Gradio ์ฑ์ ์์ฒญ
try:
local_url = f"http://127.0.0.1:{self.local_port}{request_data['path']}"
response = requests.request(
method=request_data['method'],
url=local_url,
headers=request_data['headers'],
data=request_data.get('body'),
timeout=30
)
# ์๋ต์ WebSocket์ผ๋ก ์ ์ก
self.ws.send(json.dumps({
'type': 'http_response',
'request_id': request_data['request_id'],
'status': response.status_code,
'headers': dict(response.headers),
'body': response.content.decode('utf-8', errors='ignore')
}))
except Exception as e:
# ์๋ฌ ์๋ต
self.ws.send(json.dumps({
'type': 'http_response',
'request_id': request_data['request_id'],
'status': 500,
'body': str(e)
}))
def on_error(self, ws, error):
print(f"โ Tunnel error: {error}")
def on_close(self, ws, close_status_code, close_msg):
print(f"๐ Tunnel closed")
# Colab ์
์์ ํ์ธ
import requests
# ๋ก์ปฌ ์ ์ (ํญ์ ์๋)
response = requests.get('http://127.0.0.1:7860')
print("Local:", response.status_code) # 200
# Public URL ์ ์ (ํฐ๋์ ํตํด)
public_response = requests.get('https://abc123.gradio.live')
print("Public:", public_response.status_code) # 200
# ์ฌ์ฉ์๊ฐ ๋ธ๋ผ์ฐ์ ์์ ๋ฒํผ ํด๋ฆญ
"""
1. ์ฌ์ฉ์ ๋ธ๋ผ์ฐ์
โ POST https://abc123.gradio.live/api/predict
{
"data": ["Alice"]
}
2. Cloudflare CDN
โ SSL ์ข
๋ฃ ๋ฐ ์ ๋ฌ
3. gradio.live ์๋ฒ
โ ํฐ๋ ID ํ์ธ
โ WebSocket ๋ฉ์์ง ์ ์ก
{
"type": "http_request",
"request_id": "req_123",
"method": "POST",
"path": "/api/predict",
"body": "{\"data\": [\"Alice\"]}"
}
4. Colab VM (WebSocket ์์ )
โ ๋ฉ์์ง ํ์ฑ
โ HTTP ์์ฒญ ์์ฑ
POST http://127.0.0.1:7860/api/predict
5. Gradio ์ฑ
โ greet("Alice") ์คํ
โ ๊ฒฐ๊ณผ: "Hello Alice!"
6. Colab VM
โ ์๋ต์ WebSocket์ผ๋ก ์ ์ก
{
"type": "http_response",
"request_id": "req_123",
"status": 200,
"body": "{\"data\": [\"Hello Alice!\"]}"
}
7. gradio.live ์๋ฒ
โ HTTP ์๋ต์ผ๋ก ๋ณํ
โ 200 OK
8. Cloudflare CDN
โ ์๋ต ์ ๋ฌ
9. ์ฌ์ฉ์ ๋ธ๋ผ์ฐ์
โโ "Hello Alice!" ํ๋ฉด์ ํ์
"""
๊ฐ์ฅ ์ ๋ช ํ ํฐ๋๋ง ์๋น์ค
# Colab ์ค์น
!pip install pyngrok
from pyngrok import ngrok
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return "Hello from ngrok!"
# ngrok ํฐ๋ ์์ฑ
ngrok.set_auth_token("YOUR_NGROK_TOKEN") # ngrok.com์์ ๋ฌด๋ฃ ๊ฐ์
public_url = ngrok.connect(5000)
print(f"Public URL: {public_url}")
# Flask ์๋ฒ ์์
app.run(port=5000)
์ฅ์ :
๋จ์ :
๋ด๋ถ ๊ตฌ์กฐ:
[Colab] --ngrok ํด๋ผ์ด์ธํธ--> [ngrok.io ์๋ฒ]
โ โ
๋ฐ์ด๋๋ฆฌ ์คํ ์ค๊ณ ์๋ฒ ํด๋ฌ์คํฐ
์์ ๋ฌด๋ฃ ์คํ์์ค
# Colab ์ค์น
!npm install -g localtunnel
# Python ์๋ฒ ์์ (๋ฐฑ๊ทธ๋ผ์ด๋)
from flask import Flask
import subprocess
import threading
app = Flask(__name__)
@app.route('/')
def home():
return "Hello from Localtunnel!"
def run_server():
app.run(port=8000)
# ์๋ฒ ์์
thread = threading.Thread(target=run_server)
thread.daemon = True
thread.start()
# ํฐ๋ ์์
!lt --port 8000
# ์ถ๋ ฅ: your url is: https://random-name.loca.lt
์ฅ์ :
๋จ์ :
ํน์ฑ | Gradio | ngrok | Localtunnel |
---|---|---|---|
์ค์น | ๋ด์ฅ | ๋ณ๋ | npm ํ์ |
๊ฐ๊ฒฉ | ๋ฌด๋ฃ | ๋ฌด๋ฃ/์ ๋ฃ | ๋ฌด๋ฃ |
์๋ | ๋น ๋ฆ | ๋งค์ฐ ๋น ๋ฆ | ๋ณดํต |
์์ ์ฑ | ์ข์ | ๋งค์ฐ ์ข์ | ๋ณดํต |
๋ง๋ฃ | 72์๊ฐ | 2์๊ฐ (๋ฌด๋ฃ) | ์์ |
์ปค์คํ URL | โ | โ (์ ๋ฃ) | โ |
ํ๋กํ ์ฝ | HTTP๋ง | ๋ชจ๋ ํ๋กํ ์ฝ | HTTP๋ง |
UI ํนํ | โ Gradio๋ง | โ | โ |
์ธ์ฆ ๊ธฐ๋ฅ | โ ๋ด์ฅ | โ | โ |
Gradio ์ ํ:
ngrok ์ ํ:
Localtunnel ์ ํ:
๊ฐ์ฅ ์ธ๊ธฐ ์๋ ์ฌ์ฉ ์ฌ๋ก
# Colab ์
1: ์ค์น
!git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui
%cd stable-diffusion-webui
# ๋ชจ๋ธ ๋ค์ด๋ก๋ (์ ํ)
!wget https://huggingface.co/stabilityai/stable-diffusion-2-1/resolve/main/v2-1_768-ema-pruned.safetensors \
-O models/Stable-diffusion/sd-v2-1.safetensors
# Colab ์
2: ์คํ
import subprocess
import threading
import time
def run_webui():
subprocess.run([
'python', 'launch.py',
'--share', # Gradio ๊ณต์ ๋งํฌ
'--xformers', # ๋ฉ๋ชจ๋ฆฌ ์ต์ ํ
'--enable-insecure-extension-access',
'--gradio-auth', 'admin:your_password_here', # ๋ณด์!
'--theme', 'dark',
'--no-half-vae'
])
# ๋ฐฑ๊ทธ๋ผ์ด๋ ์คํ
thread = threading.Thread(target=run_webui)
thread.start()
print("โณ WebUI ์์ ์ค... 1-2๋ถ ์ ๋ ๊ฑธ๋ฆฝ๋๋ค")
time.sleep(120) # ์ด๊ธฐํ ๋๊ธฐ
print("โ
์์์ gradio.live ๋งํฌ๋ฅผ ์ฐพ์ ํด๋ฆญํ์ธ์!")
์ค์ ํ๋๊ทธ:
--share
: Gradio ๊ณต์ ํ์ฑํ--gradio-auth username:password
: ๋น๋ฐ๋ฒํธ ๋ณดํธ (ํ์!)--xformers
: GPU ๋ฉ๋ชจ๋ฆฌ ํจ์จ ๊ฐ์ --theme dark
: ๋คํฌ ๋ชจ๋import gradio as gr
from transformers import pipeline
# ๋ชจ๋ธ ๋ก๋ (Colab GPU ํ์ฉ)
chatbot = pipeline("text-generation", model="microsoft/DialoGPT-medium")
def chat(message, history):
"""์ฑํ
ํจ์"""
# ์ด์ ๋ํ ์ปจํ
์คํธ ํฌํจ
context = "\n".join([f"User: {h[0]}\nBot: {h[1]}" for h in history])
full_message = f"{context}\nUser: {message}\nBot:"
response = chatbot(full_message, max_length=200)[0]['generated_text']
bot_response = response.split("Bot:")[-1].strip()
return bot_response
# Gradio ChatInterface
demo = gr.ChatInterface(
fn=chat,
title="๐ค My AI Chatbot",
description="Powered by DialoGPT",
theme=gr.themes.Soft(),
examples=[
"Hello! How are you?",
"Tell me a joke",
"What's the weather like?"
]
)
# ๊ณต์ ๋งํฌ๋ก ์์
demo.launch(
share=True,
auth=("user", "pass123"), # ์ธ์ฆ ์ถ๊ฐ
show_error=True
)
import gradio as gr
import pandas as pd
import plotly.express as px
def analyze_csv(file):
"""CSV ํ์ผ ๋ถ์ ๋ฐ ์๊ฐํ"""
# ํ์ผ ์ฝ๊ธฐ
df = pd.read_csv(file.name)
# ํต๊ณ ์์ฝ
summary = df.describe().to_html()
# ์๊ฐํ
if len(df.columns) >= 2:
fig = px.scatter(df, x=df.columns[0], y=df.columns[1],
title="Scatter Plot")
plot = fig
else:
plot = None
return summary, plot
# UI ๊ตฌ์ฑ
with gr.Blocks() as demo:
gr.Markdown("# ๐ CSV ๋ถ์ ๋๊ตฌ")
with gr.Row():
with gr.Column():
file_input = gr.File(label="CSV ํ์ผ ์
๋ก๋")
analyze_btn = gr.Button("๋ถ์ ์์")
with gr.Column():
summary_output = gr.HTML(label="ํต๊ณ ์์ฝ")
plot_output = gr.Plot(label="์๊ฐํ")
analyze_btn.click(
fn=analyze_csv,
inputs=file_input,
outputs=[summary_output, plot_output]
)
demo.launch(share=True, auth=("analyst", "data2024"))
import gradio as gr
import numpy as np
from scipy.io import wavfile
def process_audio(audio_file, effect):
"""์ค๋์ค ํจ๊ณผ ์ ์ฉ"""
# ์ค๋์ค ๋ก๋
sample_rate, audio_data = wavfile.read(audio_file)
# ํจ๊ณผ ์ ์ฉ
if effect == "Echo":
delay = int(0.3 * sample_rate) # 0.3์ด ๋๋ ์ด
echo = np.zeros_like(audio_data)
echo[delay:] = audio_data[:-delay] * 0.5
processed = audio_data + echo
elif effect == "Speed Up":
processed = audio_data[::2] # 2๋ฐฐ์
sample_rate = sample_rate * 2
elif effect == "Reverse":
processed = audio_data[::-1]
else:
processed = audio_data
# ์ ๊ทํ
processed = np.clip(processed, -32768, 32767).astype(np.int16)
return (sample_rate, processed)
demo = gr.Interface(
fn=process_audio,
inputs=[
gr.Audio(type="filepath", label="์
๋ ฅ ์ค๋์ค"),
gr.Dropdown(["Echo", "Speed Up", "Reverse"], label="ํจ๊ณผ")
],
outputs=gr.Audio(label="์ถ๋ ฅ ์ค๋์ค"),
title="๐ต ์ค๋์ค ํจ๊ณผ ๋๊ตฌ"
)
demo.launch(share=True)
# โ ๋์ ์ - ๋๊ตฌ๋ ์ ๊ทผ ๊ฐ๋ฅ
demo.launch(share=True)
# โ
์ข์ ์ - ๋น๋ฐ๋ฒํธ ๋ณดํธ
demo.launch(
share=True,
auth=("username", "strong_password_123!")
)
# โ
๋ ์ข์ ์ - ์ฌ๋ฌ ์ฌ์ฉ์
demo.launch(
share=True,
auth=[
("admin", "admin_password"),
("user1", "user1_password"),
("user2", "user2_password")
]
)
from functools import wraps
import time
# ๊ฐ๋จํ Rate Limiter
request_times = {}
def rate_limit(calls=10, period=60):
"""์ด๋น ํธ์ถ ์ ํ"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
now = time.time()
# ํด๋ผ์ด์ธํธ ์๋ณ (์ค์ ๋ก๋ IP ์ฌ์ฉ)
client = "default"
if client not in request_times:
request_times[client] = []
# ์ค๋๋ ์์ฒญ ์ ๊ฑฐ
request_times[client] = [
t for t in request_times[client]
if now - t < period
]
if len(request_times[client]) >= calls:
return "โ ๏ธ Too many requests. Please wait."
request_times[client].append(now)
return func(*args, **kwargs)
return wrapper
return decorator
@rate_limit(calls=5, period=60)
def protected_function(text):
return f"Processed: {text}"
demo = gr.Interface(fn=protected_function, inputs="text", outputs="text")
demo.launch(share=True, auth=("user", "pass"))
def safe_process(user_input):
"""์ํํ ์
๋ ฅ ์ฐจ๋จ"""
# ๊ธธ์ด ์ ํ
if len(user_input) > 1000:
return "โ Input too long (max 1000 characters)"
# ์
์ฑ ํจํด ์ฐจ๋จ
dangerous_patterns = ['<script>', 'DROP TABLE', 'rm -rf']
for pattern in dangerous_patterns:
if pattern.lower() in user_input.lower():
return "โ Invalid input detected"
# ์ ์ ์ฒ๋ฆฌ
return process(user_input)
demo = gr.Interface(fn=safe_process, inputs="text", outputs="text")
demo.launch(share=True, auth=("user", "pass"))
# Colab ์ธ์
์ idle ์ํ์์ 90๋ถ ํ ์ข
๋ฃ
# ํฐ๋๋ ํจ๊ป ๋๊น
# ํด๊ฒฐ์ฑ
: Keep-alive
import time
import threading
def keep_alive():
while True:
print(".", end="", flush=True)
time.sleep(60) # 1๋ถ๋ง๋ค ์ถ๋ ฅ
thread = threading.Thread(target=keep_alive)
thread.daemon = True
thread.start()
demo.launch(share=True)
# Gradio ๊ณต์ ๋งํฌ๋ 72์๊ฐ ํ ๋ง๋ฃ
# ์ฅ๊ธฐ ์ฌ์ฉ ์ ๋์:
# ๋ฐฉ๋ฒ 1: ngrok ์ ๋ฃ ํ๋
from pyngrok import ngrok
ngrok.set_auth_token("YOUR_PAID_TOKEN")
public_url = ngrok.connect(7860)
# ๋ฐฉ๋ฒ 2: ์์ฒด ์๋ฒ ๋ฐฐํฌ (AWS, GCP ๋ฑ)
# ๋ฐฉ๋ฒ 3: Hugging Face Spaces (๋ฌด๋ฃ ํธ์คํ
)
# Colab ๋ฌด๋ฃ ํ๋ ์ ์ฝ:
# - GPU: Tesla T4 (์ ํ์ )
# - RAM: 12GB
# - ๋์คํฌ: 100GB
# - ๋คํธ์ํฌ: ์ ํ์ ๋์ญํญ
# ์ต์ ํ ์ ๋ต:
def optimized_inference(input_data):
# 1. ๋ฐฐ์น ์ฒ๋ฆฌ
# 2. ๋ชจ๋ธ ์์ํ
# 3. ์บ์ฑ
pass
# ๋ฌด๊ฑฐ์ด ์์
์ ํ์
import queue
work_queue = queue.Queue(maxsize=10)
def queue_processor():
while True:
task = work_queue.get()
process(task)
work_queue.task_done()
# ๋ฐฑ๊ทธ๋ผ์ด๋ ์์ปค
threading.Thread(target=queue_processor, daemon=True).start()
auth
ํ๋ผ๋ฏธํฐ)[Colab VM]
โ 1. share=True ์คํ
โ 2. gradio.live๋ก ์์๋ฐ์ด๋ ์ฐ๊ฒฐ (WebSocket)
โ 3. ํฐ๋ ๋ฑ๋ก ์๋ฃ
โ
[gradio.live ์ค๊ณ ์๋ฒ] โ Gradio๊ฐ ์ค์ ๋ก ์ด์ํ๋ ์๋ฒ
โ 4. ๊ณต๊ฐ URL ์ ๊ณต (abc123.gradio.live)
โ 5. ์ฌ์ฉ์ ์์ฒญ์ WebSocket์ผ๋ก ์ค๊ณ
โ
[์ฌ์ฉ์ ๋ธ๋ผ์ฐ์ ]
โโ 6. ์ ์ธ๊ณ ์ด๋์๋ ์ ์ ๊ฐ๋ฅ!
โ ์ ํฉํ ๊ฒฝ์ฐ:
โ ๋ถ์ ํฉํ ๊ฒฝ์ฐ: