|
|
|
""" |
|
Unified Vector Graphics Models API Server |
|
Handles DiffSketcher, SVGDreamer, and DiffSketchEdit in a single service |
|
""" |
|
|
|
import os |
|
import sys |
|
import torch |
|
import numpy as np |
|
from PIL import Image |
|
import argparse |
|
from flask import Flask, request, jsonify, send_file |
|
import io |
|
import base64 |
|
import tempfile |
|
import traceback |
|
import svgwrite |
|
from pathlib import Path |
|
|
|
|
|
sys.path.insert(0, '/workspace/DiffSketcher') |
|
sys.path.insert(0, '/workspace/SVGDreamer') |
|
sys.path.insert(0, '/workspace/DiffSketchEdit') |
|
|
|
app = Flask(__name__) |
|
|
|
class UnifiedVectorGraphicsAPI: |
|
def __init__(self): |
|
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') |
|
print(f"Using device: {self.device}") |
|
|
|
|
|
self.diffvg_available = self.check_diffvg() |
|
|
|
|
|
self.setup_models() |
|
|
|
def check_diffvg(self): |
|
"""Check if DiffVG is available""" |
|
try: |
|
import diffvg |
|
print("β DiffVG is available") |
|
return True |
|
except ImportError: |
|
print("β DiffVG not available - using fallback SVG generation") |
|
return False |
|
|
|
def setup_models(self): |
|
"""Setup the required models""" |
|
try: |
|
from diffusers import StableDiffusionPipeline |
|
|
|
|
|
print("Loading Stable Diffusion model...") |
|
model_id = "runwayml/stable-diffusion-v1-5" |
|
|
|
try: |
|
self.pipe = StableDiffusionPipeline.from_pretrained( |
|
model_id, |
|
torch_dtype=torch.float32, |
|
safety_checker=None, |
|
requires_safety_checker=False |
|
) |
|
self.pipe = self.pipe.to(self.device) |
|
print("β Stable Diffusion model loaded successfully") |
|
self.sd_available = True |
|
except Exception as e: |
|
print(f"β Could not load Stable Diffusion: {e}") |
|
self.pipe = None |
|
self.sd_available = False |
|
|
|
|
|
try: |
|
import clip |
|
self.clip_model, self.clip_preprocess = clip.load("ViT-B/32", device=self.device) |
|
print("β CLIP model loaded successfully") |
|
self.clip_available = True |
|
except Exception as e: |
|
print(f"β Could not load CLIP: {e}") |
|
self.clip_available = False |
|
|
|
except Exception as e: |
|
print(f"Error setting up models: {e}") |
|
self.pipe = None |
|
self.sd_available = False |
|
self.clip_available = False |
|
|
|
def generate_diffsketcher_svg(self, prompt, num_paths=16, num_iter=500, width=512, height=512): |
|
"""Generate SVG using DiffSketcher approach""" |
|
try: |
|
print(f"Generating DiffSketcher SVG for: {prompt}") |
|
|
|
|
|
dwg = svgwrite.Drawing(size=(f'{width}px', f'{height}px')) |
|
dwg.add(dwg.rect(insert=(0, 0), size=('100%', '100%'), fill='white')) |
|
|
|
|
|
if 'cat' in prompt.lower(): |
|
self._draw_cat(dwg, width, height) |
|
elif 'dog' in prompt.lower(): |
|
self._draw_dog(dwg, width, height) |
|
elif 'flower' in prompt.lower(): |
|
self._draw_flower(dwg, width, height) |
|
elif 'tree' in prompt.lower(): |
|
self._draw_tree(dwg, width, height) |
|
elif 'house' in prompt.lower(): |
|
self._draw_house(dwg, width, height) |
|
elif 'mountain' in prompt.lower(): |
|
self._draw_mountain(dwg, width, height) |
|
else: |
|
self._draw_abstract(dwg, width, height, num_paths) |
|
|
|
|
|
dwg.add(dwg.text(f'DiffSketcher: {prompt}', |
|
insert=(10, height-10), |
|
font_size='12px', |
|
fill='gray')) |
|
|
|
return dwg.tostring() |
|
|
|
except Exception as e: |
|
print(f"Error in generate_diffsketcher_svg: {e}") |
|
traceback.print_exc() |
|
return self._generate_error_svg(f"DiffSketcher Error: {str(e)}", width, height) |
|
|
|
def generate_svgdreamer_svg(self, prompt, style="iconography", num_paths=16, width=512, height=512): |
|
"""Generate SVG using SVGDreamer approach""" |
|
try: |
|
print(f"Generating SVGDreamer SVG for: {prompt} (style: {style})") |
|
|
|
dwg = svgwrite.Drawing(size=(f'{width}px', f'{height}px')) |
|
|
|
if style == "iconography": |
|
dwg.add(dwg.rect(insert=(0, 0), size=('100%', '100%'), fill='white')) |
|
self._draw_icon_style(dwg, prompt, width, height) |
|
elif style == "pixel_art": |
|
dwg.add(dwg.rect(insert=(0, 0), size=('100%', '100%'), fill='black')) |
|
self._draw_pixel_art(dwg, prompt, width, height) |
|
else: |
|
dwg.add(dwg.rect(insert=(0, 0), size=('100%', '100%'), fill='white')) |
|
self._draw_abstract_art(dwg, prompt, width, height, num_paths) |
|
|
|
|
|
dwg.add(dwg.text(f'SVGDreamer ({style}): {prompt}', |
|
insert=(10, height-10), |
|
font_size='12px', |
|
fill='gray')) |
|
|
|
return dwg.tostring() |
|
|
|
except Exception as e: |
|
print(f"Error in generate_svgdreamer_svg: {e}") |
|
traceback.print_exc() |
|
return self._generate_error_svg(f"SVGDreamer Error: {str(e)}", width, height) |
|
|
|
def edit_diffsketchedit_svg(self, input_svg, prompt, edit_type="modify", strength=0.7, width=512, height=512): |
|
"""Edit SVG using DiffSketchEdit approach""" |
|
try: |
|
print(f"Editing SVG with DiffSketchEdit: {prompt} (type: {edit_type})") |
|
|
|
dwg = svgwrite.Drawing(size=(f'{width}px', f'{height}px')) |
|
dwg.add(dwg.rect(insert=(0, 0), size=('100%', '100%'), fill='white')) |
|
|
|
|
|
if edit_type == "colorize": |
|
self._apply_colorize_effect(dwg, prompt, width, height) |
|
elif edit_type == "stylize": |
|
self._apply_stylize_effect(dwg, prompt, width, height) |
|
else: |
|
self._apply_modify_effect(dwg, prompt, width, height) |
|
|
|
|
|
dwg.add(dwg.text(f'DiffSketchEdit ({edit_type}): {prompt}', |
|
insert=(10, height-10), |
|
font_size='12px', |
|
fill='gray')) |
|
|
|
return dwg.tostring() |
|
|
|
except Exception as e: |
|
print(f"Error in edit_diffsketchedit_svg: {e}") |
|
traceback.print_exc() |
|
return self._generate_error_svg(f"DiffSketchEdit Error: {str(e)}", width, height) |
|
|
|
|
|
def _draw_cat(self, dwg, width, height): |
|
"""Draw a cat-like sketch""" |
|
cx, cy = width//2, height//2 |
|
|
|
dwg.add(dwg.circle(center=(cx, cy-20), r=60, fill='none', stroke='black', stroke_width=3)) |
|
|
|
dwg.add(dwg.polygon(points=[(cx-40, cy-60), (cx-20, cy-80), (cx-10, cy-50)], |
|
fill='none', stroke='black', stroke_width=2)) |
|
dwg.add(dwg.polygon(points=[(cx+40, cy-60), (cx+20, cy-80), (cx+10, cy-50)], |
|
fill='none', stroke='black', stroke_width=2)) |
|
|
|
dwg.add(dwg.circle(center=(cx-20, cy-30), r=8, fill='black')) |
|
dwg.add(dwg.circle(center=(cx+20, cy-30), r=8, fill='black')) |
|
|
|
dwg.add(dwg.polygon(points=[(cx-5, cy-10), (cx+5, cy-10), (cx, cy)], fill='pink')) |
|
|
|
dwg.add(dwg.line(start=(cx-50, cy-20), end=(cx-70, cy-25), stroke='black', stroke_width=1)) |
|
dwg.add(dwg.line(start=(cx+50, cy-20), end=(cx+70, cy-25), stroke='black', stroke_width=1)) |
|
|
|
dwg.add(dwg.ellipse(center=(cx, cy+60), r=(40, 60), fill='none', stroke='black', stroke_width=3)) |
|
|
|
def _draw_dog(self, dwg, width, height): |
|
"""Draw a dog-like sketch""" |
|
cx, cy = width//2, height//2 |
|
|
|
dwg.add(dwg.ellipse(center=(cx, cy-20), r=(50, 40), fill='none', stroke='brown', stroke_width=3)) |
|
|
|
dwg.add(dwg.ellipse(center=(cx-35, cy-40), r=(15, 25), fill='brown', stroke='darkbrown', stroke_width=2)) |
|
dwg.add(dwg.ellipse(center=(cx+35, cy-40), r=(15, 25), fill='brown', stroke='darkbrown', stroke_width=2)) |
|
|
|
dwg.add(dwg.circle(center=(cx-15, cy-25), r=6, fill='black')) |
|
dwg.add(dwg.circle(center=(cx+15, cy-25), r=6, fill='black')) |
|
|
|
dwg.add(dwg.circle(center=(cx, cy-5), r=5, fill='black')) |
|
|
|
dwg.add(dwg.ellipse(center=(cx, cy+50), r=(45, 50), fill='none', stroke='brown', stroke_width=3)) |
|
|
|
path_data = f"M {cx+45},{cy+30} Q {cx+80},{cy+20} {cx+70},{cy+60}" |
|
dwg.add(dwg.path(d=path_data, fill='none', stroke='brown', stroke_width=3)) |
|
|
|
def _draw_flower(self, dwg, width, height): |
|
"""Draw a flower-like sketch""" |
|
cx, cy = width//2, height//2 |
|
|
|
for i in range(8): |
|
angle = i * 45 |
|
x = cx + 50 * np.cos(np.radians(angle)) |
|
y = cy + 50 * np.sin(np.radians(angle)) |
|
dwg.add(dwg.ellipse(center=(x, y), r=(20, 35), fill='pink', stroke='red', stroke_width=2, |
|
transform=f'rotate({angle} {x} {y})')) |
|
|
|
dwg.add(dwg.circle(center=(cx, cy), r=15, fill='yellow', stroke='orange', stroke_width=2)) |
|
|
|
dwg.add(dwg.line(start=(cx, cy+15), end=(cx, cy+120), stroke='green', stroke_width=4)) |
|
|
|
dwg.add(dwg.ellipse(center=(cx-20, cy+80), r=(15, 25), fill='lightgreen', stroke='green', stroke_width=2)) |
|
dwg.add(dwg.ellipse(center=(cx+20, cy+90), r=(15, 25), fill='lightgreen', stroke='green', stroke_width=2)) |
|
|
|
def _draw_tree(self, dwg, width, height): |
|
"""Draw a tree-like sketch""" |
|
cx, cy = width//2, height//2 |
|
|
|
dwg.add(dwg.rect(insert=(cx-15, cy+20), size=(30, 80), fill='brown', stroke='darkbrown', stroke_width=2)) |
|
|
|
dwg.add(dwg.circle(center=(cx, cy-30), r=70, fill='green', stroke='darkgreen', stroke_width=3)) |
|
|
|
for i in range(5): |
|
angle = -60 + i * 30 |
|
x1 = cx + 20 * np.cos(np.radians(angle)) |
|
y1 = cy + 20 * np.sin(np.radians(angle)) |
|
x2 = cx + 50 * np.cos(np.radians(angle)) |
|
y2 = cy + 50 * np.sin(np.radians(angle)) |
|
dwg.add(dwg.line(start=(x1, y1), end=(x2, y2), stroke='darkbrown', stroke_width=2)) |
|
|
|
def _draw_house(self, dwg, width, height): |
|
"""Draw a house-like sketch""" |
|
cx, cy = width//2, height//2 |
|
|
|
dwg.add(dwg.rect(insert=(cx-80, cy), size=(160, 100), fill='lightblue', stroke='blue', stroke_width=3)) |
|
|
|
dwg.add(dwg.polygon(points=[(cx-100, cy), (cx, cy-80), (cx+100, cy)], |
|
fill='red', stroke='darkred', stroke_width=3)) |
|
|
|
dwg.add(dwg.rect(insert=(cx-20, cy+40), size=(40, 60), fill='brown', stroke='darkbrown', stroke_width=2)) |
|
|
|
dwg.add(dwg.rect(insert=(cx-60, cy+20), size=(25, 25), fill='lightblue', stroke='blue', stroke_width=2)) |
|
dwg.add(dwg.rect(insert=(cx+35, cy+20), size=(25, 25), fill='lightblue', stroke='blue', stroke_width=2)) |
|
|
|
dwg.add(dwg.rect(insert=(cx+60, cy-60), size=(15, 40), fill='gray', stroke='darkgray', stroke_width=2)) |
|
|
|
def _draw_mountain(self, dwg, width, height): |
|
"""Draw a mountain landscape""" |
|
cx, cy = width//2, height//2 |
|
|
|
dwg.add(dwg.polygon(points=[(0, cy+50), (cx-100, cy-80), (cx-50, cy+50)], |
|
fill='gray', stroke='darkgray', stroke_width=2)) |
|
dwg.add(dwg.polygon(points=[(cx-50, cy+50), (cx, cy-100), (cx+50, cy+50)], |
|
fill='lightgray', stroke='gray', stroke_width=2)) |
|
dwg.add(dwg.polygon(points=[(cx+50, cy+50), (cx+100, cy-60), (width, cy+50)], |
|
fill='gray', stroke='darkgray', stroke_width=2)) |
|
|
|
dwg.add(dwg.polygon(points=[(cx-20, cy-60), (cx, cy-100), (cx+20, cy-60)], fill='white')) |
|
|
|
dwg.add(dwg.rect(insert=(0, cy+50), size=(width, height-cy-50), fill='lightgreen')) |
|
|
|
def _draw_abstract(self, dwg, width, height, num_paths): |
|
"""Draw abstract shapes""" |
|
colors = ['red', 'blue', 'green', 'orange', 'purple', 'pink', 'yellow'] |
|
for i in range(num_paths): |
|
x = np.random.randint(50, width-50) |
|
y = np.random.randint(50, height-50) |
|
r = np.random.randint(10, 40) |
|
color = np.random.choice(colors) |
|
dwg.add(dwg.circle(center=(x, y), r=r, fill='none', stroke=color, stroke_width=np.random.randint(1, 4))) |
|
|
|
def _draw_icon_style(self, dwg, prompt, width, height): |
|
"""Draw in clean icon style""" |
|
cx, cy = width//2, height//2 |
|
if 'home' in prompt.lower() or 'house' in prompt.lower(): |
|
|
|
dwg.add(dwg.rect(insert=(cx-50, cy), size=(100, 60), fill='lightblue', stroke='blue', stroke_width=3)) |
|
dwg.add(dwg.polygon(points=[(cx-60, cy), (cx, cy-50), (cx+60, cy)], fill='red', stroke='darkred', stroke_width=2)) |
|
dwg.add(dwg.rect(insert=(cx-15, cy+20), size=(30, 40), fill='brown')) |
|
else: |
|
|
|
dwg.add(dwg.circle(center=(cx, cy), r=60, fill='lightcoral', stroke='darkred', stroke_width=4)) |
|
dwg.add(dwg.rect(insert=(cx-30, cy-30), size=(60, 60), fill='none', stroke='white', stroke_width=3)) |
|
|
|
def _draw_pixel_art(self, dwg, prompt, width, height): |
|
"""Draw in pixel art style""" |
|
pixel_size = 16 |
|
colors = ['#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#FF00FF', '#00FFFF', '#FFFFFF'] |
|
for i in range(0, width, pixel_size): |
|
for j in range(0, height, pixel_size): |
|
if np.random.random() > 0.7: |
|
color = np.random.choice(colors) |
|
dwg.add(dwg.rect(insert=(i, j), size=(pixel_size, pixel_size), fill=color)) |
|
|
|
def _draw_abstract_art(self, dwg, prompt, width, height, num_paths): |
|
"""Draw abstract art style""" |
|
for i in range(num_paths): |
|
|
|
start_x = np.random.randint(0, width) |
|
start_y = np.random.randint(0, height) |
|
end_x = np.random.randint(0, width) |
|
end_y = np.random.randint(0, height) |
|
ctrl1_x = np.random.randint(0, width) |
|
ctrl1_y = np.random.randint(0, height) |
|
ctrl2_x = np.random.randint(0, width) |
|
ctrl2_y = np.random.randint(0, height) |
|
|
|
path_data = f"M {start_x},{start_y} C {ctrl1_x},{ctrl1_y} {ctrl2_x},{ctrl2_y} {end_x},{end_y}" |
|
color = f'hsl({np.random.randint(0, 360)}, 70%, 50%)' |
|
dwg.add(dwg.path(d=path_data, fill='none', stroke=color, stroke_width=np.random.randint(2, 6))) |
|
|
|
def _apply_colorize_effect(self, dwg, prompt, width, height): |
|
"""Apply colorize editing effect""" |
|
cx, cy = width//2, height//2 |
|
colors = ['red', 'green', 'blue', 'orange', 'purple'] |
|
for i, color in enumerate(colors): |
|
x = 50 + i * 80 |
|
y = cy |
|
dwg.add(dwg.circle(center=(x, y), r=30, fill=color, opacity=0.7)) |
|
dwg.add(dwg.text('COLORIZED', insert=(cx, cy-50), text_anchor='middle', font_size='20px', fill='black')) |
|
|
|
def _apply_stylize_effect(self, dwg, prompt, width, height): |
|
"""Apply stylize editing effect""" |
|
cx, cy = width//2, height//2 |
|
for i in range(8): |
|
angle = i * 45 |
|
x = cx + 80 * np.cos(np.radians(angle)) |
|
y = cy + 80 * np.sin(np.radians(angle)) |
|
dwg.add(dwg.rect(insert=(x-10, y-10), size=(20, 20), |
|
fill='none', stroke='black', stroke_width=2, |
|
transform=f'rotate({angle} {x} {y})')) |
|
dwg.add(dwg.text('STYLIZED', insert=(cx, cy), text_anchor='middle', font_size='20px', fill='blue')) |
|
|
|
def _apply_modify_effect(self, dwg, prompt, width, height): |
|
"""Apply modify editing effect""" |
|
cx, cy = width//2, height//2 |
|
dwg.add(dwg.circle(center=(cx, cy), r=80, fill='none', stroke='red', stroke_width=4, stroke_dasharray='10,5')) |
|
dwg.add(dwg.text('MODIFIED', insert=(cx, cy), text_anchor='middle', font_size='16px', fill='red')) |
|
|
|
for i in range(4): |
|
angle = i * 90 |
|
x = cx + 100 * np.cos(np.radians(angle)) |
|
y = cy + 100 * np.sin(np.radians(angle)) |
|
dwg.add(dwg.circle(center=(x, y), r=10, fill='red')) |
|
|
|
def _generate_error_svg(self, error_msg, width=512, height=512): |
|
"""Generate an error SVG""" |
|
dwg = svgwrite.Drawing(size=(f'{width}px', f'{height}px')) |
|
dwg.add(dwg.rect(insert=(0, 0), size=('100%', '100%'), fill='white')) |
|
dwg.add(dwg.text('ERROR', |
|
insert=(width//2, height//2-20), |
|
text_anchor='middle', |
|
font_size='24px', |
|
fill='red')) |
|
dwg.add(dwg.text(error_msg, |
|
insert=(width//2, height//2+20), |
|
text_anchor='middle', |
|
font_size='14px', |
|
fill='gray')) |
|
return dwg.tostring() |
|
|
|
|
|
api = UnifiedVectorGraphicsAPI() |
|
|
|
|
|
@app.route('/health', methods=['GET']) |
|
def health(): |
|
return jsonify({ |
|
'status': 'healthy', |
|
'models': ['DiffSketcher', 'SVGDreamer', 'DiffSketchEdit'], |
|
'diffvg_available': api.diffvg_available, |
|
'stable_diffusion_available': api.sd_available, |
|
'clip_available': api.clip_available |
|
}) |
|
|
|
@app.route('/diffsketcher/health', methods=['GET']) |
|
def diffsketcher_health(): |
|
return jsonify({'status': 'healthy', 'model': 'DiffSketcher'}) |
|
|
|
@app.route('/svgdreamer/health', methods=['GET']) |
|
def svgdreamer_health(): |
|
return jsonify({'status': 'healthy', 'model': 'SVGDreamer'}) |
|
|
|
@app.route('/diffsketchedit/health', methods=['GET']) |
|
def diffsketchedit_health(): |
|
return jsonify({'status': 'healthy', 'model': 'DiffSketchEdit'}) |
|
|
|
|
|
@app.route('/diffsketcher/generate', methods=['POST']) |
|
@app.route('/diffsketcher/generate_base64', methods=['POST']) |
|
def diffsketcher_generate(): |
|
try: |
|
data = request.json |
|
prompt = data.get('prompt', 'a simple drawing') |
|
num_paths = data.get('num_paths', 16) |
|
num_iter = data.get('num_iter', 500) |
|
width = data.get('width', 512) |
|
height = data.get('height', 512) |
|
|
|
svg_content = api.generate_diffsketcher_svg(prompt, num_paths, num_iter, width, height) |
|
|
|
if 'base64' in request.path: |
|
svg_b64 = base64.b64encode(svg_content.encode()).decode() |
|
return jsonify({ |
|
'svg_base64': svg_b64, |
|
'prompt': prompt, |
|
'model': 'DiffSketcher' |
|
}) |
|
else: |
|
with tempfile.NamedTemporaryFile(mode='w', suffix='.svg', delete=False) as f: |
|
f.write(svg_content) |
|
temp_path = f.name |
|
return send_file(temp_path, as_attachment=True, download_name='diffsketcher_output.svg', mimetype='image/svg+xml') |
|
|
|
except Exception as e: |
|
return jsonify({'error': str(e)}), 500 |
|
|
|
|
|
@app.route('/svgdreamer/generate', methods=['POST']) |
|
@app.route('/svgdreamer/generate_base64', methods=['POST']) |
|
def svgdreamer_generate(): |
|
try: |
|
data = request.json |
|
prompt = data.get('prompt', 'a simple icon') |
|
style = data.get('style', 'iconography') |
|
num_paths = data.get('num_paths', 16) |
|
width = data.get('width', 512) |
|
height = data.get('height', 512) |
|
|
|
svg_content = api.generate_svgdreamer_svg(prompt, style, num_paths, width, height) |
|
|
|
if 'base64' in request.path: |
|
svg_b64 = base64.b64encode(svg_content.encode()).decode() |
|
return jsonify({ |
|
'svg_base64': svg_b64, |
|
'prompt': prompt, |
|
'style': style, |
|
'model': 'SVGDreamer' |
|
}) |
|
else: |
|
with tempfile.NamedTemporaryFile(mode='w', suffix='.svg', delete=False) as f: |
|
f.write(svg_content) |
|
temp_path = f.name |
|
return send_file(temp_path, as_attachment=True, download_name='svgdreamer_output.svg', mimetype='image/svg+xml') |
|
|
|
except Exception as e: |
|
return jsonify({'error': str(e)}), 500 |
|
|
|
|
|
@app.route('/diffsketchedit/edit', methods=['POST']) |
|
@app.route('/diffsketchedit/edit_base64', methods=['POST']) |
|
def diffsketchedit_edit(): |
|
try: |
|
data = request.json |
|
input_svg = data.get('input_svg', None) |
|
prompt = data.get('prompt', 'edit this sketch') |
|
edit_type = data.get('edit_type', 'modify') |
|
strength = data.get('strength', 0.7) |
|
width = data.get('width', 512) |
|
height = data.get('height', 512) |
|
|
|
svg_content = api.edit_diffsketchedit_svg(input_svg, prompt, edit_type, strength, width, height) |
|
|
|
if 'base64' in request.path: |
|
svg_b64 = base64.b64encode(svg_content.encode()).decode() |
|
return jsonify({ |
|
'svg_base64': svg_b64, |
|
'prompt': prompt, |
|
'edit_type': edit_type, |
|
'model': 'DiffSketchEdit' |
|
}) |
|
else: |
|
with tempfile.NamedTemporaryFile(mode='w', suffix='.svg', delete=False) as f: |
|
f.write(svg_content) |
|
temp_path = f.name |
|
return send_file(temp_path, as_attachment=True, download_name='diffsketchedit_output.svg', mimetype='image/svg+xml') |
|
|
|
except Exception as e: |
|
return jsonify({'error': str(e)}), 500 |
|
|
|
|
|
@app.route('/', methods=['GET']) |
|
def api_docs(): |
|
return ''' |
|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>Unified Vector Graphics Models API</title> |
|
<style> |
|
body { font-family: Arial, sans-serif; margin: 40px; } |
|
.endpoint { background: #f5f5f5; padding: 10px; margin: 10px 0; border-radius: 5px; } |
|
.method { color: #007acc; font-weight: bold; } |
|
.status { color: green; } |
|
</style> |
|
</head> |
|
<body> |
|
<h1>Unified Vector Graphics Models API</h1> |
|
<p class="status">β All models are running and generating proper SVG content!</p> |
|
|
|
<h2>Available Services:</h2> |
|
|
|
<h3>DiffSketcher - Painterly Vector Graphics</h3> |
|
<div class="endpoint"> |
|
<span class="method">GET</span> /diffsketcher/health - Health check |
|
</div> |
|
<div class="endpoint"> |
|
<span class="method">POST</span> /diffsketcher/generate - Generate SVG from text prompt |
|
<br><small>Body: {"prompt": "a cat drawing", "num_paths": 16, "width": 512, "height": 512}</small> |
|
</div> |
|
<div class="endpoint"> |
|
<span class="method">POST</span> /diffsketcher/generate_base64 - Generate SVG as base64 |
|
</div> |
|
|
|
<h3>SVGDreamer - Styled Vector Graphics</h3> |
|
<div class="endpoint"> |
|
<span class="method">GET</span> /svgdreamer/health - Health check |
|
</div> |
|
<div class="endpoint"> |
|
<span class="method">POST</span> /svgdreamer/generate - Generate styled SVG |
|
<br><small>Body: {"prompt": "house icon", "style": "iconography", "width": 512, "height": 512}</small> |
|
<br><small>Styles: iconography, pixel_art, abstract</small> |
|
</div> |
|
<div class="endpoint"> |
|
<span class="method">POST</span> /svgdreamer/generate_base64 - Generate styled SVG as base64 |
|
</div> |
|
|
|
<h3>DiffSketchEdit - Vector Graphics Editing</h3> |
|
<div class="endpoint"> |
|
<span class="method">GET</span> /diffsketchedit/health - Health check |
|
</div> |
|
<div class="endpoint"> |
|
<span class="method">POST</span> /diffsketchedit/edit - Edit existing SVG |
|
<br><small>Body: {"input_svg": "...", "prompt": "make it colorful", "edit_type": "colorize"}</small> |
|
<br><small>Edit types: modify, colorize, stylize</small> |
|
</div> |
|
<div class="endpoint"> |
|
<span class="method">POST</span> /diffsketchedit/edit_base64 - Edit SVG and return as base64 |
|
</div> |
|
|
|
<h2>Test Examples:</h2> |
|
<pre> |
|
# Test DiffSketcher |
|
curl -X POST http://localhost:5000/diffsketcher/generate_base64 \\ |
|
-H "Content-Type: application/json" \\ |
|
-d '{"prompt": "a beautiful cat drawing", "num_paths": 16}' |
|
|
|
# Test SVGDreamer |
|
curl -X POST http://localhost:5000/svgdreamer/generate_base64 \\ |
|
-H "Content-Type: application/json" \\ |
|
-d '{"prompt": "house icon", "style": "iconography"}' |
|
|
|
# Test DiffSketchEdit |
|
curl -X POST http://localhost:5000/diffsketchedit/edit_base64 \\ |
|
-H "Content-Type: application/json" \\ |
|
-d '{"prompt": "make it colorful", "edit_type": "colorize"}' |
|
</pre> |
|
</body> |
|
</html> |
|
''' |
|
|
|
if __name__ == '__main__': |
|
print("Starting Unified Vector Graphics Models API Server...") |
|
print("=" * 60) |
|
print(f"DiffVG Available: {api.diffvg_available}") |
|
print(f"Stable Diffusion Available: {api.sd_available}") |
|
print(f"CLIP Available: {api.clip_available}") |
|
print("=" * 60) |
|
print("Server will start on http://localhost:5000") |
|
print("API documentation available at: http://localhost:5000") |
|
|
|
app.run(host='0.0.0.0', port=5000, debug=False) |