Spaces:
Running
Running
import os | |
from crewai import Agent, Task, Crew, Process, LLM | |
import gradio as gr | |
from markdown import markdown | |
import warnings | |
warnings.filterwarnings('ignore') | |
api_key = os.getenv("api_key") | |
llm = LLM( | |
model='gemini/gemini-1.5-flash', | |
api_key=api_key | |
) | |
# Agents | |
def generate_fantasy_outline(user_idea:str): | |
idea_extractor = Agent( | |
role="Idea Extractor", | |
goal=f"Extract and refine a raw fantasy story idea into structured elements from {user_idea}.", | |
backstory="You are a creative consultant helping fantasy writers refine their initial story ideas. " | |
"You specialize in identifying characters, setting, tone, conflict, and themes. " | |
"You guide the entire outlining process by establishing a clear vision.", | |
llm=llm, | |
allow_delegation=False, | |
verbose=True, | |
) | |
worldbuilder = Agent( | |
role="Worldbuilding Expert", | |
goal="Design an ULTRA-DETAILED fantasy world with comprehensive systems.", | |
backstory="You are a seasoned worldbuilder who constructs vivid and believable fantasy realms. " | |
"You define geography, cultures, magic systems, political structures, and mythologies " | |
"that serve as the foundation for storytelling.", | |
llm=llm, | |
allow_delegation=False, | |
verbose=True, | |
) | |
character_architect = Agent( | |
role="Character Architect", | |
goal="Create detailed, multi-dimensional characters who drive the story forward.", | |
backstory="You are a character development expert who crafts heroes, villains, and side characters. " | |
"You define their backstories, motivations, arcs, relationships, and emotional journeys.", | |
llm=llm, | |
allow_delegation=False, | |
verbose=True, | |
) | |
plot_strategist = Agent( | |
role="Plot Structure Strategist", | |
goal="Generate a structured fantasy plot using traditional narrative frameworks.", | |
backstory="You are a master storyteller who weaves plots using the Hero’s Journey, Three Act Structure, and other frameworks. " | |
"You ensure that the plot flows logically and engages readers from start to finish.", | |
llm=llm, | |
allow_delegation=False, | |
verbose=True, | |
) | |
scene_director = Agent( | |
role="Scene Breakdown Specialist", | |
goal="Translate the structured plot into detailed scene-by-scene or chapter-wise outlines.", | |
backstory="You specialize in breaking stories into vivid scenes. " | |
"You provide clear settings, goals, conflicts, and turning points for each scene " | |
"to help the writer visualize and write the novel more easily.", | |
llm=llm, | |
allow_delegation=False, | |
verbose=True, | |
) | |
theme_advisor = Agent( | |
role="Theme & Tone Advisor", | |
goal="Ensure thematic consistency and emotional depth across the outline align with {user_idea}.", | |
backstory="You are a literary expert who analyzes and suggests core themes, tones, and motifs. " | |
"You help the story feel emotionally resonant and stylistically consistent throughout.", | |
llm=llm, | |
allow_delegation=False, | |
verbose=True, | |
) | |
consistency_checker = Agent( | |
role="Continuity & Logic Checker", | |
goal="Identify logical gaps, plot holes, and inconsistencies in the full outline.", | |
backstory="You are an editorial specialist who reviews the full outline for quality control. " | |
"You ensure that the plot, characters, and world are coherent and nothing is left underdeveloped.", | |
llm=llm, | |
allow_delegation=False, | |
verbose=True, | |
) | |
#tasks | |
idea_extraction_task = Task( | |
description=( | |
f"1. Analyze the user's raw fantasy novel idea: {user_idea}.\n" | |
"2. Identify the main characters, potential setting, central conflict, and themes.\n" | |
"3. Clarify vague elements and structure the idea into a coherent story seed.\n" | |
"4. Prepare the refined concept for use in worldbuilding and plotting.\n" | |
"5. Generate 1000+ words with exhaustive commentary" | |
), | |
expected_output="A structured 1000+ word summary of the story idea including protagonist, world hints, tone, conflict, and themes.", | |
agent=idea_extractor | |
) | |
worldbuilding_task = Task( | |
description=( | |
"1. Use the refined idea to design a vivid and immersive fantasy world.\n" | |
"2. Define the geography, magic systems, political structures, and cultural norms.\n" | |
"3. Include religion, history, economic systems, and mythologies where relevant.\n" | |
"4. Ensure internal consistency and creative depth across the world design.\n" | |
"5.Write at least 1000 words." | |
), | |
expected_output="A detailed 2000+ word world document covering terrain, magic, politics, culture, and unique lore.", | |
agent=worldbuilder | |
) | |
character_task = Task( | |
description=( | |
"1. Create detailed character profiles for at least one protagonist, one antagonist, and two key supporting characters.\n" | |
"2. Define names, roles, traits, motivations, arcs, and relationships.\n" | |
"3. Ensure each character supports the core theme and plot direction.\n" | |
"4. Highlight how their evolution affects the story.\n" | |
"5. Write at least 800+ words." | |
), | |
expected_output="Four or more character bios totaling 800+ words with backstory, arc, and inter-character dynamics.", | |
agent=character_architect | |
) | |
plot_task = Task( | |
description=( | |
"1. Develop a plot outline using the Hero’s Journey or Three-Act Structure.\n" | |
"2. Include exposition, inciting incident, rising action, climax, and resolution.\n" | |
"3. Integrate major turning points, conflicts, and internal dilemmas.\n" | |
"4. Align plot beats with character and theme development.\n" | |
"5. Write at least 800 words." | |
), | |
expected_output="A structured plot outline with 800+ words covering 8–12 major beats linked to characters and world.", | |
agent=plot_strategist | |
) | |
scene_task = Task( | |
description=( | |
"1. Break the structured plot into a detailed scene-by-scene or chapter-wise outline.\n" | |
"2. For each scene, define the setting, involved characters, scene goal, and conflict.\n" | |
"3. Include pacing considerations and emotional flow.\n" | |
"4. Ensure each scene advances the plot and develops theme or character.\n" | |
"5. Write at least 1000+ words." | |
), | |
expected_output="A comprehensive 1000+ word scene-by-scene breakdown to guide novel structure.", | |
agent=scene_director | |
) | |
theme_task = Task( | |
description=( | |
"1. Analyze the story concept and outline to extract central themes and motifs.\n" | |
"2. Identify emotional tone (e.g., epic, tragic, whimsical) and stylistic cues.\n" | |
"3. Suggest recurring symbols or metaphors that unify the narrative.\n" | |
"4. Ensure tonal consistency from beginning to end.\n" | |
"5. Write at least 400+ words." | |
), | |
expected_output="A 400+ word theme and tone guideline covering core message, style, and motifs.", | |
agent=theme_advisor | |
) | |
consistency_task = Task( | |
description=( | |
"1. Review the complete outline for logic gaps, inconsistencies, or contradictions.\n" | |
"2. Identify undeveloped or repetitive sections.\n" | |
"3. Ensure character motivations, world rules, and plot developments align.\n" | |
"4. Suggest direct edits or improvements for cohesion.\n" | |
"5. Write at least 2000+ words." | |
), | |
expected_output="A 2000+ word edited and annotated version of the full outline with feedback and fixes.", | |
agent=consistency_checker | |
) | |
from crewai import Crew | |
# Assemble all the tasks | |
tasks = [ | |
idea_extraction_task, | |
worldbuilding_task, | |
character_task, | |
plot_task, | |
scene_task, | |
theme_task, | |
consistency_task | |
] | |
# Define the crew with all agents and tasks | |
fantasy_outline_crew = Crew( | |
agents=[ | |
idea_extractor, | |
worldbuilder, | |
character_architect, | |
plot_strategist, | |
scene_director, | |
theme_advisor, | |
consistency_checker | |
], | |
tasks=tasks, | |
verbose=True | |
) | |
results=fantasy_outline_crew.kickoff(inputs={'user_idea':user_idea}) | |
return results.raw | |
def format_output(plan_text): | |
# Convert plain text or Markdown to styled HTML | |
html_content = markdown(plan_text) | |
styled_html = f""" | |
<div style=' | |
font-family: "Segoe UI", sans-serif; | |
line-height: 1.6; | |
padding: 20px; | |
background-color: #ffffff; | |
border-radius: 10px; | |
border: 1px solid #ccc; | |
box-shadow: 0 2px 10px rgba(0,0,0,0.05); | |
color: #333; | |
'> | |
{html_content} | |
</div> | |
""" | |
return styled_html | |
# def create_gradio_app(): | |
# with gr.Blocks(css=""" | |
# .gradio-container { | |
# background: linear-gradient(to right, #fdfbfb, #ebedee); | |
# font-family: 'Segoe UI', sans-serif; | |
# padding: 30px; | |
# } | |
# .main-title { | |
# text-align: center; | |
# font-size: 40px; | |
# font-weight: bold; | |
# color: #2c3e50; | |
# margin-bottom: 10px; | |
# } | |
# .sub-title { | |
# text-align: center; | |
# font-size: 18px; | |
# color: #555; | |
# margin-bottom: 30px; | |
# } | |
# .gradio-button { | |
# background-color: #4CAF50; | |
# color: white; | |
# font-size: 18px; | |
# padding: 14px; | |
# border-radius: 8px; | |
# margin-top: 20px; | |
# } | |
# .gradio-button:hover { | |
# background-color: #45a049; | |
# } | |
# #output-box { | |
# height: 600px; | |
# overflow-y: scroll; | |
# padding: 20px; | |
# background-color: white; | |
# border: 1px solid #ccc; | |
# border-radius: 12px; | |
# box-shadow: 0 2px 10px rgba(0,0,0,0.05); | |
# } | |
# """) as demo: | |
# gr.Markdown("<div class='main-title'>Fantasy Novel Outline Generator</div>") | |
# gr.Markdown("<div class='sub-title'>Turn your novel idea into a rich, detailed outline with AI-powered agents.</div>") | |
# with gr.Row(): | |
# with gr.Column(scale=1): | |
# user_idea = gr.Textbox( | |
# label="Enter Your Fantasy Novel Idea", | |
# placeholder="e.g., A young orphan discovers they're heir to a ruined magical kingdom...", | |
# lines=5, | |
# interactive=True | |
# ) | |
# generate_btn = gr.Button("Generate Outline", elem_classes="gradio-button") | |
# with gr.Column(scale=2): | |
# output_html = gr.HTML(label="AI-Generated Outline", elem_id="output-box") | |
# # Button logic | |
# generate_btn.click( | |
# fn=lambda idea: format_output(generate_fantasy_outline(idea)), | |
# inputs=[user_idea], | |
# outputs=output_html | |
# ) | |
# demo.launch() | |
# def create_gradio_app(): | |
# with gr.Blocks(css=""" | |
# .gradio-container { | |
# background: linear-gradient(to right, #3c3b6e, #121062); | |
# font-family: 'Cinzel', serif; | |
# padding: 40px; | |
# } | |
# .main-title { | |
# text-align: center; | |
# font-size: 48px; | |
# font-weight: bold; | |
# color: #f1c40f; | |
# margin-bottom: 20px; | |
# } | |
# .sub-title { | |
# text-align: center; | |
# font-size: 20px; | |
# color: #ecf0f1; | |
# margin-bottom: 40px; | |
# } | |
# .gradio-button { | |
# background-color: #8e44ad; | |
# color: white; | |
# font-size: 20px; | |
# padding: 16px; | |
# border-radius: 10px; | |
# margin-top: 30px; | |
# width: 100%; | |
# } | |
# .gradio-button:hover { | |
# background-color: #9b59b6; | |
# } | |
# #output-box { | |
# height: 600px; | |
# overflow-y: scroll; | |
# padding: 20px; | |
# background-color: #ecf0f1; | |
# border: 1px solid #dcdde1; | |
# border-radius: 12px; | |
# box-shadow: 0 4px 15px rgba(0,0,0,0.1); | |
# margin-top: 20px; | |
# } | |
# .gradio-input { | |
# background-color: #ecf0f1; | |
# border-radius: 8px; | |
# padding: 10px; | |
# border: 1px solid #dcdde1; | |
# font-size: 16px; | |
# } | |
# .gradio-input:focus { | |
# outline: none; | |
# border-color: #8e44ad; | |
# } | |
# .gradio-column { | |
# display: flex; | |
# justify-content: center; | |
# } | |
# .loading { | |
# color: #f39c12; | |
# font-size: 18px; | |
# text-align: center; | |
# } | |
# """) as demo: | |
# gr.Markdown("<div class='main-title'>Fantasy Novel Outline Generator</div>") | |
# gr.Markdown("<div class='sub-title'>Turn your novel idea into a rich, detailed outline with AI-powered agents.</div>") | |
# with gr.Row(): | |
# with gr.Column(scale=1): | |
# user_idea = gr.Textbox( | |
# label="Enter Your Fantasy Novel Idea", | |
# placeholder="e.g., A young orphan discovers they're heir to a ruined magical kingdom...", | |
# lines=5, | |
# interactive=True, | |
# elem_classes="gradio-input" | |
# ) | |
# generate_btn = gr.Button("Generate Outline", elem_classes="gradio-button") | |
# with gr.Column(scale=2): | |
# output_html = gr.HTML(label="AI-Generated Outline", elem_id="output-box") | |
# # Add a loading message for user feedback | |
# loading_message = gr.Markdown("<div class='loading'>Generating outline, please wait...</div>", visible=False) | |
# # Button logic | |
# def generate_and_format_output(idea): | |
# loading_message.visible = True | |
# result = generate_fantasy_outline(idea) | |
# formatted_result = format_output(result) | |
# loading_message.visible = False | |
# return formatted_result | |
# generate_btn.click( | |
# fn=generate_and_format_output, | |
# inputs=[user_idea], | |
# outputs=output_html | |
# ) | |
# demo.launch() | |
def create_gradio_app(): | |
with gr.Blocks(css=""" | |
.gradio-container { | |
background: url('https://img.freepik.com/free-ai-image/fantasy-landscape-floating-islands-illustration_355026699.htm#fromView=keyword&page=1&position=3&uuid=c5b6d86a-b71a-47da-9593-ce6dc72d2fbd&query=Fantasy+Background') no-repeat center center fixed; | |
background-size: cover; | |
font-family: 'Segoe UI', sans-serif; | |
padding: 30px; | |
} | |
.main-title { | |
text-align: center; | |
font-size: 60px; | |
font-weight: bold; | |
font-style: italic; | |
color: #FAF3E0; | |
margin-bottom: 20px; | |
} | |
.sub-title { | |
text-align: center; | |
font-size: 28px; | |
font-weight: bold; | |
font-style: italic; | |
color: #D1C6E1; | |
margin-bottom: 30px; | |
} | |
.gradio-button { | |
background-color: #A2C2E1; | |
color: white; | |
font-size: 18px; | |
padding: 14px; | |
border-radius: 8px; | |
margin-top: 20px; | |
} | |
.gradio-button:hover { | |
background-color: #A8E6CF; | |
} | |
#output-box { | |
height: 600px; | |
overflow-y: scroll; | |
padding: 20px; | |
background-color: white; | |
border: 1px solid #ccc; | |
border-radius: 12px; | |
box-shadow: 0 2px 10px rgba(0,0,0,0.05); | |
} | |
""") as demo: | |
gr.Markdown("<div class='main-title'>Fantasy Novel Outline Generator</div>") | |
gr.Markdown("<div class='sub-title'>Turn your novel idea into a rich, detailed outline with AI-powered agents.</div>") | |
with gr.Row(): | |
with gr.Column(scale=1): | |
user_idea = gr.Textbox( | |
label="Enter Your Fantasy Novel Idea", | |
placeholder="e.g., A young orphan discovers they're heir to a ruined magical kingdom...", | |
lines=5, | |
interactive=True | |
) | |
generate_btn = gr.Button("Generate Outline", elem_classes="gradio-button") | |
with gr.Column(scale=2): | |
output_html = gr.HTML(label="AI-Generated Outline", elem_id="output-box") | |
# Button logic | |
generate_btn.click( | |
fn=lambda idea: format_output(generate_fantasy_outline(idea)), | |
inputs=[user_idea], | |
outputs=output_html | |
) | |
demo.launch() | |
create_gradio_app() | |