diff --git a/app/oobabooga - webui.py b/app/oobabooga - webui.py index a7c2196..5c44ede 100644 --- a/app/oobabooga - webui.py +++ b/app/oobabooga - webui.py @@ -14,12 +14,41 @@ folder_path = "models" global_url = "" + + def process_url(url): global global_url global_url = url.rstrip("/") + "/v1/completions" # Append '/v1/completions' to the URL return f"URL Set: {global_url}" # Return the modified URL +# Function to process the uploaded image +from PIL import Image +import numpy as np + + +def process_uploaded_image(uploaded_img): + global processed_image_path # Access the global variable + + # Convert the NumPy array to a PIL image + pil_image = Image.fromarray(np.uint8(uploaded_img)).convert('RGB') + + # Define the path for the uploaded image + character_name = "uploaded_character" + os.makedirs(f"characters/{character_name}", exist_ok=True) + image_path = f"characters/{character_name}/{character_name}.png" + + # Save the image + pil_image.save(image_path) + + # Update the global variable with the image path + processed_image_path = image_path + + print("Uploaded image saved at:", image_path) + return pil_image + + + def send_message(prompt): global global_url if not global_url: @@ -72,6 +101,7 @@ def send_message(prompt): except requests.RequestException as e: return f"Error sending request: {e}" + def load_models(): global sd sd = DiffusionPipeline.from_pretrained( @@ -93,8 +123,10 @@ def load_models(): else: print("Loading LLM to CPU...") + load_models() + # Function to scrape character data from Fandom def scrape_fandom_character(url): response = requests.get(url) @@ -102,10 +134,14 @@ def scrape_fandom_character(url): title = soup.find('h1', {'class': 'page-header__title'}).get_text(strip=True) content = soup.find('div', {'id': 'mw-content-text'}).get_text("\n", strip=True) return title, content + print(title) + # Function to set the character data based on scraped information def set_character_data(url): name, content = scrape_fandom_character(url) + print(name) + print(content) summary = generate_character_summary(name, "", "") personality = generate_character_personality(name, summary, "") scenario = generate_character_scenario(summary, personality, "") @@ -113,6 +149,7 @@ def set_character_data(url): example_messages = generate_example_messages(name, summary, personality, "") return name, summary, personality, scenario, greeting_message, example_messages + def generate_character_name(topic, gender): example_dialogue = """ <|system|> @@ -133,7 +170,7 @@ def generate_character_name(topic, gender): example_dialogue + "\n<|user|> Generate a random character name. " + f"Topic: {topic}. " - + f"{'Character gender: '+gender+'.' if gender else ''} " + + f"{'Character gender: ' + gender + '.' if gender else ''} " + "\n<|assistant|> " ) output = re.sub(r"[^a-zA-Z0-9_ -]", "", output).strip() @@ -141,7 +178,9 @@ def generate_character_name(topic, gender): return output -def generate_character_summary(character_name, topic, gender): +def generate_character_summary(character_name, topic, gender, content=None): + content_clause = f"using {content}" if content else "" + example_dialogue = """ <|system|> You are a text generation tool. Describe the character in a very simple and understandable way, you can just list some characteristics, you do not need to write a professional characterization of the character. Describe: age, height, personality traits, appearance, clothing, what the character likes, what the character does not like. @@ -174,7 +213,8 @@ def generate_character_summary(character_name, topic, gender): example_dialogue + "\n<|user|> Create a longer description for a character named " + f"{character_name}. " - + f"{'Character gender: '+gender+'.' if gender else ''} " + + f"{'Character gender: ' + gender + '.' if gender else ''} " + + f"use {content_clause}" + "Describe their appearance, distinctive features, and looks. " + f"Tailor the character to the theme of {topic} but don't " + "specify what topic it is, and don't describe the topic itself. " @@ -188,9 +228,9 @@ def generate_character_summary(character_name, topic, gender): def generate_character_personality( - character_name, - character_summary, - topic + character_name, + character_summary, + topic ): example_dialogue = """ <|system|> @@ -224,9 +264,9 @@ def generate_character_personality( def generate_character_scenario( - character_summary, - character_personality, - topic + character_summary, + character_personality, + topic ): example_dialogue = """ <|system|> @@ -262,7 +302,7 @@ def generate_character_scenario( def generate_character_greeting_message( - character_name, character_summary, character_personality, topic + character_name, character_summary, character_personality, topic ): example_dialogue = """ <|system|> @@ -300,7 +340,7 @@ def generate_character_greeting_message( def generate_example_messages( - character_name, character_summary, character_personality, topic + character_name, character_summary, character_personality, topic ): example_dialogue = """ <|system|> @@ -343,12 +383,12 @@ def generate_example_messages( def generate_character_avatar( - character_name, - character_summary, - topic, - negative_prompt, - avatar_prompt, - nsfw_filter, + character_name, + character_summary, + topic, + negative_prompt, + avatar_prompt, + nsfw_filter, ): example_dialogue = """ <|system|> @@ -365,14 +405,14 @@ def generate_character_avatar( <|assistant|> 1girl, improvised tag, """ # nopep8 sd_prompt = ( - input_none(avatar_prompt) - or send_message( - example_dialogue - + "\n<|user|> create a prompt that lists the appearance " - + "characteristics of a character whose summary is " - + "if lack of info, generate something based on available info." - + f"{character_summary}. Topic: {topic}\n<|assistant|> " - ).strip() + input_none(avatar_prompt) + or send_message( + example_dialogue + + "\n<|user|> create a prompt that lists the appearance " + + "characteristics of a character whose summary is " + + "if lack of info, generate something based on available info." + + f"{character_summary}. Topic: {topic}\n<|assistant|> " + ).strip() ) print(sd_prompt) sd_filter(nsfw_filter) @@ -383,22 +423,21 @@ def generate_character_avatar( def image_generate(character_name, prompt, negative_prompt): - prompt = "absurdres, full hd, 8k, high quality, " + prompt default_negative_prompt = ( - "worst quality, normal quality, low quality, low res, blurry, " - + "text, watermark, logo, banner, extra digits, cropped, " - + "jpeg artifacts, signature, username, error, sketch, " - + "duplicate, ugly, monochrome, horror, geometry, " - + "mutation, disgusting, " - + "bad anatomy, bad hands, three hands, three legs, " - + "bad arms, missing legs, missing arms, poorly drawn face, " - + " bad face, fused face, cloned face, worst face, " - + "three crus, extra crus, fused crus, worst feet, " - + "three feet, fused feet, fused thigh, three thigh, " - + "fused thigh, extra thigh, worst thigh, missing fingers, " - + "extra fingers, ugly fingers, long fingers, horn, " - + "extra eyes, huge eyes, 2girl, amputation, disconnected limbs" + "worst quality, normal quality, low quality, low res, blurry, " + + "text, watermark, logo, banner, extra digits, cropped, " + + "jpeg artifacts, signature, username, error, sketch, " + + "duplicate, ugly, monochrome, horror, geometry, " + + "mutation, disgusting, " + + "bad anatomy, bad hands, three hands, three legs, " + + "bad arms, missing legs, missing arms, poorly drawn face, " + + " bad face, fused face, cloned face, worst face, " + + "three crus, extra crus, fused crus, worst feet, " + + "three feet, fused feet, fused thigh, three thigh, " + + "fused thigh, extra thigh, worst thigh, missing fingers, " + + "extra fingers, ugly fingers, long fingers, horn, " + + "extra eyes, huge eyes, 2girl, amputation, disconnected limbs" ) negative_prompt = default_negative_prompt + (negative_prompt or "") @@ -448,7 +487,8 @@ def import_character_json(json_path): character.greeting_message, character.example_messages, ) - raise ValueError("Error when importing character data from a JSON file. Validate the file. Check the file for correctness and try again") # nopep8 + raise ValueError( + "Error when importing character data from a JSON file. Validate the file. Check the file for correctness and try again") # nopep8 def import_character_card(card_path): @@ -465,11 +505,12 @@ def import_character_card(card_path): character.greeting_message, character.example_messages, ) - raise ValueError("Error when importing character data from a character card file. Check the file for correctness and try again") # nopep8 + raise ValueError( + "Error when importing character data from a character card file. Check the file for correctness and try again") # nopep8 def export_as_json( - name, summary, personality, scenario, greeting_message, example_messages + name, summary, personality, scenario, greeting_message, example_messages ): character = aichar.create_character( name=name, @@ -483,11 +524,29 @@ def export_as_json( return character.export_neutral_json() -def export_character_card( - name, summary, personality, scenario, greeting_message, example_messages -): +# Global variable to store the path of the processed image +processed_image_path = None + + +def export_character_card(name, summary, personality, scenario, greeting_message, example_messages): + global processed_image_path # Access the global variable + + # Prepare the character's name and base path character_name = name.replace(" ", "_") base_path = f"characters/{character_name}/" + + # Ensure the directory exists + os.makedirs(base_path, exist_ok=True) + + if processed_image_path is not None: + # If an image has been processed, use it + image_path = processed_image_path + else: + # If no image has been processed, use a default or placeholder image + # e.g., image_path = "path/to/default/image.png" + image_path = None # Or set a default image path + + # Create the character with the appropriate image character = aichar.create_character( name=name, summary=summary, @@ -495,9 +554,10 @@ def export_character_card( scenario=scenario, greeting_message=greeting_message, example_messages=example_messages, - image_path=f"{base_path}{character_name}.png", + image_path=image_path # Use the processed or default image ) - character_name = character.name.replace(" ", "_") + + # Export the character card card_path = f"{base_path}{character_name}.card.png" character.export_neutral_card_file(card_path) return Image.open(card_path) @@ -507,7 +567,7 @@ def export_character_card( gr.Markdown("# Character Factory WebUI") gr.Markdown("## Model: Zephyr 7b Beta") with gr.Row(): - url_input = gr.Textbox(label="Enter URL") + url_input = gr.Textbox(label="Enter URL", value="http://127.0.0.1:5000") submit_button = gr.Button("Set URL") output = gr.Textbox(label="URL Status") @@ -516,7 +576,8 @@ def export_character_card( ) with gr.Tab("Edit character"): gr.Markdown( - "## Protip: If you want to generate the entire character using LLM and Stable Diffusion, start from the top to bottom" # nopep8 + "## Protip: If you want to generate the entire character using LLM and Stable Diffusion, start from the top to bottom" + # nopep8 ) topic = gr.Textbox( placeholder="Topic: The topic for character generation (e.g., Fantasy, Anime, etc.)", # nopep8 @@ -596,21 +657,32 @@ def export_character_card( ) with gr.Row(): with gr.Column(): - image_input = gr.Image(width=512, height=512) + image_input = gr.Image(interactive=True, label="Character Image", width=512, height=512) + # Button to process the uploaded image + process_image_button = gr.Button("Process Uploaded Image") + + # Function to handle the uploaded image + process_image_button.click( + process_uploaded_image, # Your function to handle the image + inputs=[image_input], + outputs=[image_input] # You can update the same image display with the processed image + ) with gr.Column(): negative_prompt = gr.Textbox( placeholder="negative prompt for stable diffusion (optional)", # nopep8 label="negative prompt", ) avatar_prompt = gr.Textbox( - placeholder="prompt for generating character avatar (If not provided, LLM will generate prompt from character description)", # nopep8 + placeholder="prompt for generating character avatar (If not provided, LLM will generate prompt from character description)", + # nopep8 label="stable diffusion prompt", ) avatar_button = gr.Button( "Generate avatar with stable diffusion (set character name first)" # nopep8 ) potential_nsfw_checkbox = gr.Checkbox( - label="Block potential NSFW image (Upon detection of this content, a black image will be returned)", # nopep8 + label="Block potential NSFW image (Upon detection of this content, a black image will be returned)", + # nopep8 value=True, interactive=True, )