Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -584,158 +584,206 @@ demo.launch()'''
|
|
| 584 |
|
| 585 |
|
| 586 |
|
| 587 |
-
|
| 588 |
-
|
| 589 |
-
|
| 590 |
-
|
| 591 |
import gradio as gr
|
| 592 |
from transformers import AutoTokenizer, AutoModelForCausalLM
|
| 593 |
import torch
|
|
|
|
| 594 |
|
| 595 |
# Load TinyLlama model and tokenizer
|
| 596 |
model_name = "TinyLlama/TinyLlama-1.1B-Chat"
|
| 597 |
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
| 598 |
-
model = AutoModelForCausalLM.from_pretrained(
|
| 599 |
-
|
| 600 |
-
|
| 601 |
-
|
|
|
|
| 602 |
|
| 603 |
-
|
| 604 |
-
|
| 605 |
-
|
| 606 |
-
|
| 607 |
-
|
| 608 |
-
|
| 609 |
-
|
| 610 |
-
|
| 611 |
-
|
| 612 |
-
|
| 613 |
-
|
| 614 |
-
inputs.input_ids,
|
| 615 |
-
max_new_tokens=max_length,
|
| 616 |
-
do_sample=True,
|
| 617 |
-
temperature=0.7,
|
| 618 |
-
top_p=0.9,
|
| 619 |
-
num_return_sequences=1,
|
| 620 |
-
pad_token_id=tokenizer.eos_token_id
|
| 621 |
-
)
|
| 622 |
-
|
| 623 |
-
# Decode and clean up response
|
| 624 |
-
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 625 |
-
response = response.replace(formatted_prompt, "").strip()
|
| 626 |
-
return response
|
| 627 |
|
| 628 |
-
|
| 629 |
-
|
| 630 |
-
story_prompt = (
|
| 631 |
-
f"Write a short, engaging paragraph (40-50 words) for a story starting with: '{prompt}'. "
|
| 632 |
-
"Make it descriptive and ensure it relates directly to the prompt."
|
| 633 |
-
)
|
| 634 |
-
story_output = generate_text(story_prompt, max_length=75)
|
| 635 |
-
|
| 636 |
-
# Ensure the story starts with the prompt theme
|
| 637 |
-
if not any(word in story_output.lower() for word in prompt.lower().split()):
|
| 638 |
-
story_output = f"{prompt}. {story_output}"
|
| 639 |
-
|
| 640 |
-
return story_output
|
| 641 |
|
| 642 |
-
def
|
| 643 |
-
"""Generate
|
| 644 |
-
option_prompt = (
|
| 645 |
-
f"Based on this story: '{story_so_far}'\n"
|
| 646 |
-
"Generate 3 distinct, exciting options for what happens next. "
|
| 647 |
-
"Each option should be a single sentence and directly relate to the story's context. "
|
| 648 |
-
"Format: 1. [Option 1] 2. [Option 2] 3. [Option 3]"
|
| 649 |
-
)
|
| 650 |
-
|
| 651 |
-
options_text = generate_text(option_prompt, max_length=100)
|
| 652 |
-
|
| 653 |
-
# Parse options or provide fallback options if generation fails
|
| 654 |
try:
|
| 655 |
-
|
| 656 |
-
|
| 657 |
-
|
| 658 |
-
|
| 659 |
-
|
| 660 |
-
|
| 661 |
-
|
| 662 |
-
|
| 663 |
-
|
| 664 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 665 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 666 |
|
| 667 |
-
|
| 668 |
-
|
| 669 |
-
def start_story(initial_prompt):
|
| 670 |
-
"""Start the story with the user's initial prompt."""
|
| 671 |
-
global story_history
|
| 672 |
-
story_history = [initial_prompt]
|
| 673 |
-
|
| 674 |
-
# Generate initial segment
|
| 675 |
-
segment = generate_initial_story(initial_prompt)
|
| 676 |
-
story_history.append(segment)
|
| 677 |
|
| 678 |
-
# Generate
|
| 679 |
-
|
| 680 |
|
| 681 |
-
return
|
| 682 |
|
| 683 |
def continue_story(choice):
|
| 684 |
-
"""Continue the story based on
|
| 685 |
-
|
| 686 |
-
|
| 687 |
-
|
| 688 |
-
|
| 689 |
-
|
| 690 |
-
|
| 691 |
-
|
| 692 |
-
"
|
|
|
|
|
|
|
| 693 |
)
|
| 694 |
|
| 695 |
-
new_segment =
|
| 696 |
-
|
| 697 |
|
| 698 |
-
# Generate new
|
| 699 |
-
|
| 700 |
|
| 701 |
-
return
|
| 702 |
|
| 703 |
-
def
|
| 704 |
-
"""Format the
|
| 705 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 706 |
|
| 707 |
-
def
|
| 708 |
-
"""Reset the
|
| 709 |
-
|
| 710 |
-
|
| 711 |
-
return "Story reset. Enter a new prompt to begin!", "", "", ""
|
| 712 |
|
| 713 |
# Gradio interface
|
| 714 |
-
with gr.Blocks(title="Story
|
| 715 |
-
gr.Markdown("#
|
| 716 |
-
gr.Markdown("
|
| 717 |
|
|
|
|
| 718 |
with gr.Row():
|
| 719 |
-
|
| 720 |
-
|
| 721 |
-
|
| 722 |
-
|
| 723 |
-
|
| 724 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 725 |
|
| 726 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 727 |
|
| 728 |
with gr.Row():
|
| 729 |
-
choice_button_1 = gr.Button(
|
| 730 |
-
choice_button_2 = gr.Button(
|
| 731 |
-
choice_button_3 = gr.Button(
|
| 732 |
|
| 733 |
-
reset_button = gr.Button("🔄 Reset
|
| 734 |
|
| 735 |
# Event handlers
|
| 736 |
start_button.click(
|
| 737 |
-
fn=
|
| 738 |
-
inputs=
|
| 739 |
outputs=[story_output, choice_button_1, choice_button_2, choice_button_3]
|
| 740 |
).then(
|
| 741 |
fn=lambda story, c1, c2, c3: (
|
|
@@ -751,7 +799,7 @@ with gr.Blocks(title="Story Adventure") as demo:
|
|
| 751 |
for button in [choice_button_1, choice_button_2, choice_button_3]:
|
| 752 |
button.click(
|
| 753 |
fn=continue_story,
|
| 754 |
-
inputs=button,
|
| 755 |
outputs=[story_output, choice_button_1, choice_button_2, choice_button_3]
|
| 756 |
).then(
|
| 757 |
fn=lambda story, c1, c2, c3: (
|
|
@@ -765,9 +813,23 @@ with gr.Blocks(title="Story Adventure") as demo:
|
|
| 765 |
)
|
| 766 |
|
| 767 |
reset_button.click(
|
| 768 |
-
fn=
|
| 769 |
-
outputs=[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 770 |
)
|
| 771 |
|
|
|
|
| 772 |
if __name__ == "__main__":
|
| 773 |
-
demo.launch()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 584 |
|
| 585 |
|
| 586 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 587 |
import gradio as gr
|
| 588 |
from transformers import AutoTokenizer, AutoModelForCausalLM
|
| 589 |
import torch
|
| 590 |
+
import random
|
| 591 |
|
| 592 |
# Load TinyLlama model and tokenizer
|
| 593 |
model_name = "TinyLlama/TinyLlama-1.1B-Chat"
|
| 594 |
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
| 595 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 596 |
+
model_name,
|
| 597 |
+
torch_dtype=torch.float16,
|
| 598 |
+
device_map="auto"
|
| 599 |
+
)
|
| 600 |
|
| 601 |
+
class StoryState:
|
| 602 |
+
def __init__(self):
|
| 603 |
+
self.history = []
|
| 604 |
+
self.player_name = ""
|
| 605 |
+
self.character_class = ""
|
| 606 |
+
self.current_location = ""
|
| 607 |
+
self.inventory = []
|
| 608 |
+
self.health = 100
|
| 609 |
+
|
| 610 |
+
def reset(self):
|
| 611 |
+
self.__init__()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 612 |
|
| 613 |
+
# Initialize game state
|
| 614 |
+
game_state = StoryState()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 615 |
|
| 616 |
+
def generate_story_segment(prompt, max_length=150):
|
| 617 |
+
"""Generate story text using TinyLlama."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 618 |
try:
|
| 619 |
+
# Format prompt for chat
|
| 620 |
+
formatted_prompt = f"<|im_start|>user\n{prompt}<|im_end|>\n<|im_start|>assistant\n"
|
| 621 |
+
|
| 622 |
+
# Tokenize
|
| 623 |
+
inputs = tokenizer(formatted_prompt, return_tensors="pt").to(model.device)
|
| 624 |
+
|
| 625 |
+
# Generate with optimized parameters
|
| 626 |
+
with torch.no_grad():
|
| 627 |
+
outputs = model.generate(
|
| 628 |
+
inputs.input_ids,
|
| 629 |
+
max_new_tokens=max_length,
|
| 630 |
+
do_sample=True,
|
| 631 |
+
temperature=0.8,
|
| 632 |
+
top_p=0.9,
|
| 633 |
+
num_return_sequences=1,
|
| 634 |
+
pad_token_id=tokenizer.eos_token_id
|
| 635 |
+
)
|
| 636 |
+
|
| 637 |
+
# Decode and clean response
|
| 638 |
+
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 639 |
+
return response.replace(formatted_prompt, "").strip()
|
| 640 |
+
except Exception as e:
|
| 641 |
+
return get_fallback_segment()
|
| 642 |
+
|
| 643 |
+
def get_fallback_segment():
|
| 644 |
+
"""Provide fallback story segments if generation fails."""
|
| 645 |
+
fallbacks = [
|
| 646 |
+
"As you proceed cautiously, the path ahead seems to hold both promise and peril.",
|
| 647 |
+
"The atmosphere grows tense as you consider your next move.",
|
| 648 |
+
"Your instincts tell you that this decision could change everything.",
|
| 649 |
+
"The consequences of your choices begin to unfold around you."
|
| 650 |
+
]
|
| 651 |
+
return random.choice(fallbacks)
|
| 652 |
+
|
| 653 |
+
def generate_choices(context):
|
| 654 |
+
"""Generate contextual choices based on the current story state."""
|
| 655 |
+
try:
|
| 656 |
+
prompt = (
|
| 657 |
+
f"Based on this story context: '{context}'\n"
|
| 658 |
+
"Generate 3 distinct, interesting choices for what the player could do next. "
|
| 659 |
+
"Each choice should be a single sentence and affect the story differently. "
|
| 660 |
+
"Format: 1. [Choice 1] 2. [Choice 2] 3. [Choice 3]"
|
| 661 |
+
)
|
| 662 |
+
|
| 663 |
+
choices_text = generate_story_segment(prompt, max_length=100)
|
| 664 |
+
choices = [
|
| 665 |
+
choice.split(". ")[1].strip()
|
| 666 |
+
for choice in choices_text.split("\n")
|
| 667 |
+
if choice.strip().startswith(("1.", "2.", "3."))
|
| 668 |
]
|
| 669 |
+
|
| 670 |
+
if len(choices) != 3:
|
| 671 |
+
raise ValueError("Invalid choices generated")
|
| 672 |
+
|
| 673 |
+
return choices
|
| 674 |
+
except:
|
| 675 |
+
return get_fallback_choices()
|
| 676 |
+
|
| 677 |
+
def get_fallback_choices():
|
| 678 |
+
"""Provide fallback choices if generation fails."""
|
| 679 |
+
return [
|
| 680 |
+
"Proceed carefully and gather more information",
|
| 681 |
+
"Take bold action and face the consequences",
|
| 682 |
+
"Seek an alternative path forward"
|
| 683 |
+
]
|
| 684 |
+
|
| 685 |
+
def initialize_character(name, character_class):
|
| 686 |
+
"""Initialize the player character."""
|
| 687 |
+
if not name or not character_class:
|
| 688 |
+
return "Please enter both name and class!", None, None, None
|
| 689 |
+
|
| 690 |
+
game_state.reset()
|
| 691 |
+
game_state.player_name = name
|
| 692 |
+
game_state.character_class = character_class
|
| 693 |
+
|
| 694 |
+
# Generate initial story setup
|
| 695 |
+
prompt = (
|
| 696 |
+
f"Write an engaging opening paragraph for a fantasy adventure story where {name}, "
|
| 697 |
+
f"a brave {character_class}, begins their journey. Make it exciting and descriptive."
|
| 698 |
+
)
|
| 699 |
|
| 700 |
+
story_start = generate_story_segment(prompt)
|
| 701 |
+
game_state.history.append(story_start)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 702 |
|
| 703 |
+
# Generate initial choices
|
| 704 |
+
choices = generate_choices(story_start)
|
| 705 |
|
| 706 |
+
return format_game_output(story_start, choices), *choices
|
| 707 |
|
| 708 |
def continue_story(choice):
|
| 709 |
+
"""Continue the story based on player's choice."""
|
| 710 |
+
if not choice or not game_state.history:
|
| 711 |
+
return "Please start a new game!", None, None, None
|
| 712 |
+
|
| 713 |
+
game_state.history.append(f"You chose to: {choice}")
|
| 714 |
+
|
| 715 |
+
# Generate new story segment
|
| 716 |
+
prompt = (
|
| 717 |
+
f"Continue this story naturally:\n{game_state.history[-2]}\n"
|
| 718 |
+
f"The player ({game_state.player_name} the {game_state.character_class}) chose to: {choice}\n"
|
| 719 |
+
"Write an exciting 50-75 word continuation that builds on this choice."
|
| 720 |
)
|
| 721 |
|
| 722 |
+
new_segment = generate_story_segment(prompt)
|
| 723 |
+
game_state.history.append(new_segment)
|
| 724 |
|
| 725 |
+
# Generate new choices
|
| 726 |
+
choices = generate_choices(new_segment)
|
| 727 |
|
| 728 |
+
return format_game_output("\n\n".join(game_state.history), choices), *choices
|
| 729 |
|
| 730 |
+
def format_game_output(story, choices):
|
| 731 |
+
"""Format the game output with story and choices."""
|
| 732 |
+
status_line = (
|
| 733 |
+
f"📜 Adventure of {game_state.player_name} the {game_state.character_class}\n"
|
| 734 |
+
f"❤️ Health: {game_state.health}% | 🎒 Items: {', '.join(game_state.inventory) or 'None'}\n"
|
| 735 |
+
f"{'─' * 50}\n\n"
|
| 736 |
+
)
|
| 737 |
+
|
| 738 |
+
return (
|
| 739 |
+
f"{status_line}{story}\n\n"
|
| 740 |
+
f"What will you do?\n"
|
| 741 |
+
f"1️⃣ {choices[0]}\n"
|
| 742 |
+
f"2️⃣ {choices[1]}\n"
|
| 743 |
+
f"3️⃣ {choices[2]}"
|
| 744 |
+
)
|
| 745 |
|
| 746 |
+
def reset_game():
|
| 747 |
+
"""Reset the game state."""
|
| 748 |
+
game_state.reset()
|
| 749 |
+
return "Start a new adventure!", "", "", "", None, None, None
|
|
|
|
| 750 |
|
| 751 |
# Gradio interface
|
| 752 |
+
with gr.Blocks(title="Story Quest") as demo:
|
| 753 |
+
gr.Markdown("# 🎮 Story Quest")
|
| 754 |
+
gr.Markdown("Embark on an AI-powered interactive adventure! Create your character and shape the story through your choices.")
|
| 755 |
|
| 756 |
+
# Character Creation
|
| 757 |
with gr.Row():
|
| 758 |
+
with gr.Column():
|
| 759 |
+
name_input = gr.Textbox(
|
| 760 |
+
label="Character Name",
|
| 761 |
+
placeholder="Enter your character's name"
|
| 762 |
+
)
|
| 763 |
+
class_input = gr.Dropdown(
|
| 764 |
+
choices=["Warrior", "Mage", "Rogue", "Paladin", "Ranger"],
|
| 765 |
+
label="Character Class"
|
| 766 |
+
)
|
| 767 |
+
start_button = gr.Button("⚔️ Begin Adventure", variant="primary")
|
| 768 |
|
| 769 |
+
# Story Display and Choices
|
| 770 |
+
story_output = gr.Textbox(
|
| 771 |
+
label="Your Adventure",
|
| 772 |
+
lines=12,
|
| 773 |
+
interactive=False
|
| 774 |
+
)
|
| 775 |
|
| 776 |
with gr.Row():
|
| 777 |
+
choice_button_1 = gr.Button(visible=False, variant="secondary")
|
| 778 |
+
choice_button_2 = gr.Button(visible=False, variant="secondary")
|
| 779 |
+
choice_button_3 = gr.Button(visible=False, variant="secondary")
|
| 780 |
|
| 781 |
+
reset_button = gr.Button("🔄 Reset Adventure", variant="stop")
|
| 782 |
|
| 783 |
# Event handlers
|
| 784 |
start_button.click(
|
| 785 |
+
fn=initialize_character,
|
| 786 |
+
inputs=[name_input, class_input],
|
| 787 |
outputs=[story_output, choice_button_1, choice_button_2, choice_button_3]
|
| 788 |
).then(
|
| 789 |
fn=lambda story, c1, c2, c3: (
|
|
|
|
| 799 |
for button in [choice_button_1, choice_button_2, choice_button_3]:
|
| 800 |
button.click(
|
| 801 |
fn=continue_story,
|
| 802 |
+
inputs=[button],
|
| 803 |
outputs=[story_output, choice_button_1, choice_button_2, choice_button_3]
|
| 804 |
).then(
|
| 805 |
fn=lambda story, c1, c2, c3: (
|
|
|
|
| 813 |
)
|
| 814 |
|
| 815 |
reset_button.click(
|
| 816 |
+
fn=reset_game,
|
| 817 |
+
outputs=[
|
| 818 |
+
story_output,
|
| 819 |
+
name_input,
|
| 820 |
+
class_input,
|
| 821 |
+
story_output,
|
| 822 |
+
choice_button_1,
|
| 823 |
+
choice_button_2,
|
| 824 |
+
choice_button_3
|
| 825 |
+
]
|
| 826 |
)
|
| 827 |
|
| 828 |
+
# Launch the app
|
| 829 |
if __name__ == "__main__":
|
| 830 |
+
demo.launch()
|
| 831 |
+
|
| 832 |
+
|
| 833 |
+
|
| 834 |
+
|
| 835 |
+
|