-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathchatbot.py
More file actions
130 lines (99 loc) · 4.02 KB
/
chatbot.py
File metadata and controls
130 lines (99 loc) · 4.02 KB
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
# chatbot_vanilla.py
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
GOAL = """You are the narrator as the user creates a story.
In this story, the user attempts to escape the dungeon without being eaten.
The goal is complete if the user 'escapes' or is 'eaten'.
"""
RULES = """
RULE #1 Include the keyword 'game over' in your result to signal the goal has been met.
RULE #2 The user must play for at least 3 turns.
RULE #3 You must attempt to advance the story towards an entertaining conclusion.
RULE #4 Naration must be short, 1 or 2 sentences.
"""
BACKSTORY = """The user is trapped in a dungeon.
There are monsters roaming.
One looks like an owl, the other like a cat.
Players can explore the dungeon and you will allow them to lead that exploration.
The cat-like creature will help you escape, the owl will take you to its nest to feed you to its babies.
"""
# The Observe Function
def observe():
"""Gather input from the player."""
print("\n👁️ OBSERVE:")
player_input = input("What do you do? > ")
return player_input
# The Reason Function
def reason(client, history):
"""LLM plans what to do next."""
messages = [
{"role": "system", "content": f"""Goal: {GOAL}
Backstory: {BACKSTORY}
Rules: {RULES}
You are in the REASON step. Output EXACTLY this format and nothing else:
THOUGHT: [a meta analysis of player intent, the current situation, narrative arc, and very brief plan for how the game world might react to the player.]
GAMEOVER: [TRUE or FALSE]"""},
{"role": "user", "content": f"History:\n{history}"}
]
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages
)
thought = response.choices[0].message.content
print("\n🧠 REASON:")
print(thought)
return thought
# The Act Function
def act(client, thought, history):
"""LLM takes an action - narrates the next part of the story."""
messages = [
{"role": "system", "content": f"Based on your reasoning, narrate 1-2 sentences to advance the story. If GAMEOVER: true the user must escape or is eaten; end the story. if GAMEOVER: false ensure the story continues another round."},
{"role": "user", "content": f"History:\n{history}\n\nYour reasoning:\n{thought}\n\nNarrate what happens:"}
]
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages
)
action = response.choices[0].message.content
print("\n\n🗣️ ACT:")
print(action)
return action
# Utility Function to end the story
def is_goal_complete(thought):
"""Check if the LLM signaled game over in its reasoning."""
thought_lower = thought.lower()
return "gameover: true" in thought_lower or "game over: true" in thought_lower
# Start the program
def run():
# Create the Open AI Client
client = OpenAI()
# Seed the initial history
initial_narration = """You wake up in a dark dungeon.
You hear strange cat-like sounds to the east.
You also hear what sounds like an owl to the west."""
history = [f"Narrator: {initial_narration}"]
print("\n🏰 DUNGEON ESCAPE 🏰")
print("(type 'quit' to exit)\n")
print(initial_narration)
# Loop until the goal is met
while True:
# OBSERVE - gather input from the player
player_input = observe()
# Allow the player to quit
if player_input.lower() in ["quit", "exit", "q"]:
break
history.append(f"Player: {player_input}")
# REASON - consider the history and plan an action
history_text = "\n".join(history[-10:])
thought = reason(client, history_text)
input("\n\n(press enter to continue)")
# ACT - act according to your reasoning
narration = act(client, thought, history_text)
history.append(f"Narrator: {narration}")
# END - exit the ReAct loop if the agent triggers completion
if is_goal_complete(thought):
print("\n🎮 GAME OVER 🎮\n")
break
if __name__ == "__main__":
run()