This commit is contained in:
Nick Walton
2019-04-11 19:08:19 -06:00
4 changed files with 64 additions and 41 deletions
+29 -25
View File
@@ -22,7 +22,7 @@ os.environ['GOOGLE_APPLICATION_CREDENTIALS']="./AI-Adventure-2bb65e3a4e2f.json"
from google.cloud import storage
from google import cloud
import json
from flask import Flask, render_template, request
from flask import Flask, render_template, request, abort
storage_client = storage.Client()
bucket = storage_client.get_bucket("dungeon-cache")
from flask import Response
@@ -84,61 +84,65 @@ def generate(prompt):
@app.route('/')
def root():
return render_template('index.html')
@app.route('/index.html')
def index():
return render_template('index.html')
@app.route('/about.html')
def about():
return render_template('about.html')
def cache_file(seed, prompt_num, choices, response, tag):
blob_file_name = "p" + str(prompt_num) + "/seed" + str(seed) + "/" + tag
for action in choices:
blob_file_name = blob_file_name + str(action)
blob = bucket.blob(blob_file_name)
blob.upload_from_string(response)
print("File ", blob_file_name, " cached")
def retrieve_from_cache(seed, prompt_num, choices, tag):
blob_file_name = "p" + str(prompt_num) + "/seed" + str(seed) + "/" + tag
for action in choices:
blob_file_name = blob_file_name + str(action)
blob = bucket.blob(blob_file_name)
if blob.exists(storage_client):
result = blob.download_as_string().decode("utf-8")
print(blob_file_name, " found in cache")
else:
result = None
print(blob_file_name, " not found in cache")
return result
@app.route('/generate', methods=['POST'])
def story_request():
print("****Generating Story****")
seed = request.form["seed"]
prompt_num = int(request.form["prompt_num"])
gen_actions = request.form["actions"]
gen_actions = request.form["actions"]
if int(seed) < 0 or int(seed) > 1000:
print("Invalid seed: " + seed)
abort(404)
if gen_actions == "true":
prompt = request.form["prompt"]
prompt = request.form["prompt"]
choices = json.loads(request.form["choices"])
print("Getting response for seed ", seed, " prompt_num ", prompt_num, " and choices ", choices)
action_results = retrieve_from_cache(seed, prompt_num, choices, "choices")
if action_results is not None:
response = action_results
else:
@@ -147,25 +151,25 @@ def story_request():
response = response.text
cache_file(seed, prompt_num, choices, response, "choices")
else:
print("Getting response for seed ", seed, " prompt_num ", prompt_num)
result = retrieve_from_cache(seed, prompt_num, [], "story")
if result is not None:
response = result
else:
response = requests.post(gen_ip + "/generate", data={"actions":"false","seed":seed, "prompt_num":prompt_num})
response=response.text
cache_file(seed, prompt_num, [], response, "story")
print("\nGenerated response is: \n", response)
print("")
return response
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
# [START gae_python37_render_template]
+22 -10
View File
@@ -13,7 +13,7 @@ var should_blink = false
var blinkCounter = 0
var action_list = ["You attack", "You tell", "You use", "You go"]
var prompt_num = 0
var seed_max = 100
var seed_max = 1000
var seed_min = 0
var seed = Math.floor(Math.random() * (+seed_max - +seed_min)) + +seed_min;
//var seed = 108
@@ -33,6 +33,7 @@ function checkButtonDisplay()
setTimeout(checkButtonDisplay, 1000);
console.log("Not mobile device");
document.getElementById('buttons').style.visibility='hidden';
}
}
@@ -65,11 +66,14 @@ var StoryTracker = {
},
actionWait:function(){
if(action_waiting == true || typing){
setTimeout(StoryTracker.actionWait, 2000);
}
else{
Typer.appendToText(" Generating...")
if(action_waiting == true){
if(typing == true || acceptInput == true){
setTimeout(StoryTracker.actionWait, 5000);
}
else{
Typer.appendToText(" Generating...")
}
}
},
@@ -98,8 +102,10 @@ var StoryTracker = {
Typer.appendToText("\nWhich action do you choose? ")
StoryTracker.action_int = 0
acceptInput = true
if(isMobileDevice(){
setTimeout(checkButtonDisplay, 1000);
}
}
}
@@ -136,7 +142,7 @@ var StoryTracker = {
StoryTracker.lastStory = StoryTracker.results[choice_int]
StoryTracker.makeActionRequests(StoryTracker.firstStory + StoryTracker.lastStory)
action_waiting = true
setTimeout(StoryTracker.actionWait, 2000);
setTimeout(StoryTracker.actionWait, 4000);
Typer.appendToText("\n")
Typer.appendToText(StoryTracker.lastStory)
Typer.appendToText("\n\nOptions:")
@@ -147,6 +153,11 @@ var StoryTracker = {
Typer.appendToText("\nWhich action do you choose? ")
acceptInput = true
if(isMobileDevice()){
setTimeout(buttonCheck, 500);
}
}
@@ -191,7 +202,6 @@ var Typer={
var rtn= new RegExp("\n", "g")
A solution would be to add position: relative for the button. This will move it above the label.
$("#console").html(text.replace(rtn,"<br/>"))
window.scrollBy(0,50)
}
else{
typing = false
@@ -239,7 +249,7 @@ function typeWords() {
document.onkeypress = function(evt) {
if(acceptInput){
if(acceptInput && !isMobileDevice()){
evt = evt || window.event
var charCode = evt.keyCode || evt.which
@@ -260,6 +270,8 @@ document.onkeypress = function(evt) {
function onButtonClick(num){
document.getElementById('buttons').style.visibility='hidden';
if (acceptInput == true){
acceptInput = false
num = String(num)
@@ -280,7 +292,7 @@ function start(){
startTyping()
Typer.startBlinker()
}
+12 -5
View File
@@ -9,7 +9,7 @@ body {
width:80%;
margin-left:auto;
margin-right:auto;
margin-top:100px;
margin-top:calc(30px + 4.0vh);
font-size:14px;
background-color: #000;
}
@@ -79,11 +79,13 @@ a {
}
button {
border-color: #000
border-color: #fff;
bottom: 40px;
color: #fff;
margin-top: 40px;
margin-left: 4%;
margin-right: 4%;
margin-bottom: 20px;
background-color: #111;
width: 18%;
height: 100px;
@@ -93,10 +95,14 @@ button {
}
button:focus{
background-color: #0bc;
}
/* Add a black background color to the top navigation */
.topnav {
background-color: #000;
overflow: hidden;
max-width: 800px;
width:80%;
margin-left:auto;
@@ -106,13 +112,14 @@ button {
/* Style the links inside the navigation bar */
.topnav a {
font-family: courier, monospace;
font-family: courier, monospace;
display: inline-block;
color: #0bc;
text-align: center;
padding: 10px 5px;
text-decoration: none;
font-size: 16px;
font-size:calc(12px + 1.0vh );
min-font-size:
}
/* Change the color of links on hover */
+1 -1
View File
@@ -10,7 +10,7 @@
<div class="about">
<h2> About AI Dungeon </h2>
<text>
AIDungeon is an AI generated text adventure that uses deep learning to create each adventure. It uses OpenAI's new <a href="https://openai.com/blog/better-language-models/">GPT-2 model</a>, which has 117 million parameters, to generate each story block and possible action.
AI Dungeon is an AI generated text adventure that uses deep learning to create each adventure. It uses OpenAI's new <a href="https://openai.com/blog/better-language-models/">GPT-2 model</a>, which has 117 million parameters, to generate each story block and possible action.
<br><br> The first couple sentences of AIDungeon and the action verbs are handcrafted, but everything else is not. Each time an option is chosen, the initial prompt, the last story block, and the last action are fed into the neural network. The resulting story and action options are then output by the model.