Spaces:
Sleeping
Sleeping
File size: 5,971 Bytes
71b378e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
"""
Character Portrait Tab for D'n'D Campaign Manager
"""
import gradio as gr
from typing import Optional, Tuple
from src.agents.character_agent import CharacterAgent
from src.ui.components.dropdown_manager import DropdownManager
class CharacterPortraitTab:
"""Generate Portrait tab for AI character portrait generation"""
def __init__(self, character_agent: CharacterAgent, dropdown_manager: DropdownManager):
self.character_agent = character_agent
self.dropdown_manager = dropdown_manager
def generate_portrait_ui(
self,
character_id: str,
style: str = "fantasy art",
quality: str = "standard",
provider: str = "auto"
) -> Tuple[Optional[str], str]:
"""
Generate character portrait
Returns:
Tuple of (image_path, status_message)
"""
try:
if not character_id.strip():
return None, "β Error: Please provide a character ID"
# Load character
character = self.character_agent.load_character(character_id)
if not character:
return None, f"β Character not found: {character_id}"
# Generate portrait
file_path, status = self.character_agent.generate_portrait(
character=character,
style=style,
quality=quality,
provider=provider
)
return file_path, status
except Exception as e:
import traceback
error_msg = f"β Error generating portrait:\n\n{str(e)}\n\n{traceback.format_exc()}"
return None, error_msg
def create(self) -> gr.Dropdown:
"""Create and return the Generate Portrait tab component"""
with gr.Tab("Generate Portrait"):
gr.Markdown("""
### π¨ AI Character Portrait Generator
Generate stunning character portraits using DALL-E 3 or HuggingFace!
""")
with gr.Row():
with gr.Column():
portrait_refresh_btn = gr.Button("π Refresh Character List", variant="secondary")
portrait_character_dropdown = gr.Dropdown(
choices=[],
label="Select Character",
info="Choose a character to generate portrait for (type to search)",
allow_custom_value=False,
interactive=True
)
portrait_provider = gr.Radio(
choices=["auto", "openai", "huggingface"],
label="Image Provider",
value="auto",
info="Auto: Try OpenAI first, fallback to HuggingFace if needed"
)
portrait_style = gr.Dropdown(
choices=[
"fantasy art",
"digital painting",
"anime style",
"oil painting",
"watercolor",
"comic book art",
"concept art"
],
label="Art Style",
value="fantasy art",
info="Choose the artistic style"
)
portrait_quality = gr.Radio(
choices=["standard", "hd"],
label="Image Quality (OpenAI only)",
value="standard",
info="HD costs more tokens (OpenAI only)"
)
generate_portrait_btn = gr.Button(
"π¨ Generate Portrait",
variant="primary",
size="lg"
)
portrait_status = gr.Textbox(
label="Status",
lines=4
)
with gr.Column():
portrait_output = gr.Image(
label="Generated Portrait",
type="filepath",
height=512
)
gr.Markdown("""
**Providers:**
- **OpenAI DALL-E 3**: High quality, costs $0.04/image (standard) or $0.08/image (HD)
- **HuggingFace (Free!)**: Stable Diffusion XL, ~100 requests/day on free tier
- **Auto**: Tries OpenAI first, automatically falls back to HuggingFace if billing issues
Portraits are automatically saved to `data/portraits/` directory.
**Tips:**
- Use "auto" mode for seamless fallback
- OpenAI HD quality produces better results but costs 2x
- HuggingFace is free but may have a 30-60s warm-up time
- Different styles work better for different races/classes
""")
# Refresh portrait character dropdown
portrait_refresh_btn.click(
fn=self.dropdown_manager.refresh_character_dropdown,
inputs=[],
outputs=[portrait_character_dropdown]
)
# Generate portrait action - convert dropdown label to ID
def generate_portrait_from_dropdown(label, style, quality, provider):
char_id = self.dropdown_manager.get_character_id_from_label(label)
return self.generate_portrait_ui(char_id, style, quality, provider)
generate_portrait_btn.click(
fn=generate_portrait_from_dropdown,
inputs=[portrait_character_dropdown, portrait_style, portrait_quality, portrait_provider],
outputs=[portrait_output, portrait_status]
)
# Return the dropdown for auto-population
return portrait_character_dropdown
|