├── README.md
├── LICENSE
├── templates
└── home.html
└── GPT-Journey.py
/README.md:
--------------------------------------------------------------------------------
1 | # GPT-Journey
2 | Building a text and image-based journey game powered by, and with, GPT 3.5
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Harrison
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/templates/home.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ title }}
5 |
6 |
7 |
8 |
9 |
10 |
{{ title }}
11 |
12 |
{{ text }}
13 | {% for button_name, message in button_messages.items() %}
14 |
19 | {% if button_states[button_name] %}
20 |
{{ message }}
21 | {% endif %}
22 | {% endfor %}
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/GPT-Journey.py:
--------------------------------------------------------------------------------
1 | # For the UI
2 | from flask import Flask, render_template, request, session
3 | # OpenAI API
4 | import openai
5 | # Regular expressions:
6 | import re
7 |
8 | # Set the OpenAI API key
9 | openai.api_key = open("key.txt", "r").read().strip("\n")
10 |
11 | # Create a new Flask app and set the secret key
12 | app = Flask(__name__)
13 | app.secret_key = "mysecretkey"
14 |
15 | # Define a function to generate an image using the OpenAI API
16 | def get_img(prompt):
17 | try:
18 | response = openai.Image.create(
19 | prompt=prompt,
20 | n=1,
21 | size="512x512"
22 | )
23 | img_url = response.data[0].url
24 | except Exception as e:
25 | # if it fails (e.g. if the API detects an unsafe image), use a default image
26 | img_url = "https://pythonprogramming.net/static/images/imgfailure.png"
27 | return img_url
28 |
29 |
30 | # Define a function to generate a chat response using the OpenAI API
31 | def chat(inp, message_history, role="user"):
32 |
33 | # Append the input message to the message history
34 | message_history.append({"role": role, "content": f"{inp}"})
35 |
36 | # Generate a chat response using the OpenAI API
37 | completion = openai.ChatCompletion.create(
38 | model="gpt-3.5-turbo",
39 | messages=message_history
40 | )
41 |
42 | # Grab just the text from the API completion response
43 | reply_content = completion.choices[0].message.content
44 |
45 | # Append the generated response to the message history
46 | message_history.append({"role": "assistant", "content": f"{reply_content}"})
47 |
48 | # Return the generated response and the updated message history
49 | return reply_content, message_history
50 |
51 |
52 | # Define the homepage route for the Flask app
53 | @app.route('/', methods=['GET', 'POST'])
54 | def home():
55 | # Page's title:
56 | title = "GPT-Journey"
57 |
58 | # Initialize the button messages and button states dictionaries
59 | button_messages = {}
60 | button_states = {}
61 |
62 | # If the request method is GET (i.e., the page has just been loaded), set up the initial chat
63 | if request.method == 'GET':
64 |
65 | # Initialize the message history
66 | session['message_history'] = [{"role": "user", "content": """You are an interactive story game bot that proposes some hypothetical fantastical situation where the user needs to pick from 2-4 options that you provide. Once the user picks one of those options, you will then state what happens next and present new options, and this then repeats. If you understand, say, OK, and begin when I say "begin." When you present the story and options, present just the story and start immediately with the story, no further commentary, and then options like "Option 1:" "Option 2:" ...etc."""},
67 | {"role": "assistant", "content": f"""OK, I understand. Begin when you're ready."""}]
68 |
69 | # Retrieve the message history from the session
70 | message_history = session['message_history']
71 |
72 | # Generate a chat response with an initial message ("Begin")
73 | reply_content, message_history = chat("Begin", message_history)
74 |
75 | # Extract the text from the response
76 | text = reply_content.split("Option 1")[0]
77 |
78 | # Using regex, grab the natural language options from the response
79 | options = re.findall(r"Option \d:.*", reply_content)
80 |
81 | # Create a dictionary of button messages
82 | for i, option in enumerate(options):
83 | button_messages[f"button{i+1}"] = option
84 |
85 | # Initialize the button states
86 | for button_name in button_messages.keys():
87 | button_states[button_name] = False
88 |
89 |
90 | # If the request method is POST (i.e., a button has been clicked), update the chat
91 | message = None
92 | button_name = None
93 | if request.method == 'POST':
94 |
95 | # Retrieve the message history and button messages from the session
96 | message_history = session['message_history']
97 | button_messages = session['button_messages']
98 |
99 | # Get the name of the button that was clicked ***
100 | button_name = request.form.get('button_name')
101 |
102 | # Set the state of the button to "True"
103 | button_states[button_name] = True
104 |
105 | # Get the message associated with the clicked button
106 | message = button_messages.get(button_name)
107 |
108 | # Generate a chat response with the clicked message
109 | reply_content, message_history = chat(message, message_history)
110 |
111 | # Extract the text and options from the response
112 | text = reply_content.split("Option 1")[0]
113 | options = re.findall(r"Option \d:.*", reply_content)
114 |
115 | # Update the button messages and states
116 | button_messages = {}
117 | for i, option in enumerate(options):
118 | button_messages[f"button{i+1}"] = option
119 | for button_name in button_messages.keys():
120 | button_states[button_name] = False
121 |
122 | # Store the updated message history and button messages in the session
123 | session['message_history'] = message_history
124 | session['button_messages'] = button_messages
125 |
126 | # Generate an image based on the chat response text
127 | image_url = get_img(text)
128 |
129 | # Render the template with the updated information
130 | return render_template('home.html', title=title, text=text, image_url=image_url, button_messages=button_messages, button_states=button_states, message=message)
131 |
132 | # Run the Flask app
133 | if __name__ == '__main__':
134 | app.run(debug=True, port=5001)
135 |
--------------------------------------------------------------------------------