File size: 6,124 Bytes
fdd1fae
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9d6e2ac
 
 
 
 
 
 
 
 
 
1b5d224
 
9d6e2ac
 
fdd1fae
 
9d6e2ac
 
 
 
 
 
efe308e
 
 
 
1b5d224
 
9d6e2ac
efe308e
fdd1fae
 
9d6e2ac
efe308e
fdd1fae
 
 
1b5d224
 
9d6e2ac
fdd1fae
 
 
 
 
 
 
1b5d224
 
 
 
 
fdd1fae
 
 
 
 
 
 
9d6e2ac
1b5d224
fdd1fae
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
658b140
fdd1fae
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
import gradio as gr
import random
from helper import load_world, save_world
from together import Together
from helper import get_together_api_key

# Initialize Together client
client = Together(api_key=get_together_api_key())

# Load the world data from the JSON file
world_data = load_world('./YourWorld_L1.json')

# Function to randomly select a world, kingdom, town, and character
def randomly_select_from_json(world_data):
    # World level
    world_name = world_data["name"]
    world_description = world_data["description"]

    # Filter valid kingdoms (those with towns containing NPCs)
    valid_kingdoms = {
        k_name: k_data
        for k_name, k_data in world_data["kingdoms"].items()
        if any("npcs" in town_data and town_data["npcs"] for town_data in k_data["towns"].values())
    }

    if not valid_kingdoms:
        raise ValueError("No kingdoms with valid towns and NPCs found.")

    print(f"Valid Kingdoms: {list(valid_kingdoms.keys())}")  # Debug

    # Randomly select a kingdom
    kingdom_name, kingdom_data = random.choice(list(valid_kingdoms.items()))
    kingdom_description = kingdom_data["description"]

    # Filter towns with NPCs in the selected kingdom
    valid_towns = {
        t_name: t_data
        for t_name, t_data in kingdom_data["towns"].items()
        if "npcs" in t_data and t_data["npcs"]
    }

    if not valid_towns:
        raise ValueError(f"No towns with NPCs found in kingdom: {kingdom_name}")

    print(f"Valid Towns in {kingdom_name}: {list(valid_towns.keys())}")  # Debug

    # Randomly select a town
    town_name, town_data = random.choice(list(valid_towns.items()))
    town_description = town_data["description"]

    # Randomly select an NPC
    npcs = town_data["npcs"]
    character_name, character_data = random.choice(list(npcs.items()))
    character_description = character_data["description"]

    print(f"Selected NPC in {town_name}: {character_name}")  # Debug

    # Return the selected elements
    return {
        "world": {"name": world_name, "description": world_description},
        "kingdom": {"name": kingdom_name, "description": kingdom_description},
        "town": {"name": town_name, "description": town_description},
        "character": {"name": character_name, "description": character_description},
    }

# Reload JSON data each run to ensure randomness
random.seed(None)  # Remove seed to ensure true randomness

# Get random world state
random_state = randomly_select_from_json(world_data)

# Use random selections in the game state
world = random_state["world"]
kingdom = random_state["kingdom"]
town = random_state["town"]
character = random_state["character"]



# Create the system prompt
system_prompt = """You are an AI Game master. Your job is to create a 
start to an adventure based on the world, kingdom, town, and character 
a player is playing as. 
Instructions:
- You must use only 2-4 sentences.
- Write in second person, e.g., "You are Jack."
- Write in present tense, e.g., "You stand at..."
- First describe the character and their backstory.
- Then describe where they start and what they see around them."""

# Format the world info for the model
world_info = f"""
World: {world['description']}
Kingdom: {kingdom['description']}
Town: {town['description']}
Your Character: {character['description']}
"""

# Generate the starting prompt using Together AI
model_output = client.chat.completions.create(
    model="meta-llama/Llama-3-70b-chat-hf",
    temperature=1.0,
    messages=[
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": world_info + '\nYour Start:'}
    ],
)

# Extract the start response
start = model_output.choices[0].message.content

# Save the starting point back to the JSON file (optional)
world_data["start"] = start
save_world(world_data, './YourWorld_L1.json')

# Game state for the main loop
game_state = {
    "world": world["description"],
    "kingdom": kingdom["description"],
    "town": town["description"],
    "character": character["description"],
    "start": start,
}

# Function to process actions
def run_action(message, history, game_state):
    if message.lower() == "start game":
        return game_state["start"]

    system_prompt = """You are an AI Game master. Your job is to write what \
happens next in a player's adventure game.\
Instructions: \
- Write only 1-3 sentences. \
- Always write in second person, e.g., "You look north and see..." \
- Write in present tense."""

    world_info = f"""
World: {game_state['world']}
Kingdom: {game_state['kingdom']}
Town: {game_state['town']}
Your Character: {game_state['character']}"""

    # Build the context for the conversation
    messages = [
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": world_info},
    ]

    for action in history:
        if isinstance(action, tuple) and len(action) == 2:
            messages.append({"role": "assistant", "content": action[0]})
            messages.append({"role": "user", "content": action[1]})

    # Add the user's current action
    messages.append({"role": "user", "content": message})

    # Get the model's response
    model_output = client.chat.completions.create(
        model="meta-llama/Llama-3-70b-chat-hf",
        messages=messages,
    )

    return model_output.choices[0].message.content


def main_loop(message, history):
    return run_action(message, history, game_state)

demo = None

def start_game(main_loop, share=False):
    global demo
    if demo is not None:
        demo.close()

    demo = gr.ChatInterface(
        main_loop,
        chatbot=gr.Chatbot(
            height=250,
            placeholder="Type 'start game' to begin",
            type="messages",
        ),
        textbox=gr.Textbox(
            placeholder="What do you do next?",
            container=False,
            scale=7,
        ),
        title="AI RPG",
        theme="soft",
        examples=["Look around", "Continue the story"],
        cache_examples=False,
    )
    demo.launch(share=share, server_name="0.0.0.0")

# Launch the game
start_game(main_loop, True)