mirror of
https://github.com/wassname/Clover-Edition.git
synced 2026-09-09 11:13:26 +08:00
local branc
This commit is contained in:
@@ -0,0 +1,468 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright 2019 Cortex Labs, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set -e
|
||||
|
||||
####################
|
||||
### FLAG PARSING ###
|
||||
####################
|
||||
|
||||
flag_help=false
|
||||
positional_args=()
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
key="$1"
|
||||
case $key in
|
||||
-c|--config)
|
||||
export CORTEX_CONFIG="$2"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
flag_help="true"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
positional_args+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
set -- "${positional_args[@]}"
|
||||
positional_args=()
|
||||
for i in "$@"; do
|
||||
case $i in
|
||||
-c=*|--config=*)
|
||||
export CORTEX_CONFIG="${i#*=}"
|
||||
shift
|
||||
;;
|
||||
-h=*|--help=*)
|
||||
flag_help="true"
|
||||
;;
|
||||
*)
|
||||
positional_args+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
set -- "${positional_args[@]}"
|
||||
if [ "$flag_help" == "true" ]; then
|
||||
show_help
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for arg in "$@"; do
|
||||
if [[ "$arg" == -* ]]; then
|
||||
echo "unknown flag: $arg"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
#####################
|
||||
### CONFIGURATION ###
|
||||
#####################
|
||||
|
||||
if [ "$CORTEX_CONFIG" != "" ]; then
|
||||
if [ ! -f "$CORTEX_CONFIG" ]; then
|
||||
echo "Cortex config file does not exist: $CORTEX_CONFIG"
|
||||
exit 1
|
||||
fi
|
||||
source $CORTEX_CONFIG
|
||||
fi
|
||||
|
||||
set -u
|
||||
|
||||
export CORTEX_VERSION_STABLE=0.7.3
|
||||
|
||||
# Defaults
|
||||
export AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID:-""}"
|
||||
|
||||
if [ "$AWS_ACCESS_KEY_ID" = "" ]; then
|
||||
echo -e "\nPlease set AWS_ACCESS_KEY_ID"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY:-""}"
|
||||
|
||||
if [ "$AWS_SECRET_ACCESS_KEY" = "" ]; then
|
||||
echo -e "\nPlease set AWS_SECRET_ACCESS_KEY"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export CORTEX_LOG_GROUP="${CORTEX_LOG_GROUP:-cortex}"
|
||||
export CORTEX_BUCKET="${CORTEX_BUCKET:-""}"
|
||||
export CORTEX_REGION="${CORTEX_REGION:-us-west-2}"
|
||||
export CORTEX_ZONES="${CORTEX_ZONES:-""}"
|
||||
|
||||
export CORTEX_CLUSTER="${CORTEX_CLUSTER:-cortex}"
|
||||
export CORTEX_NODE_TYPE="${CORTEX_NODE_TYPE:-t3.large}"
|
||||
export CORTEX_NODES_MIN="${CORTEX_NODES_MIN:-2}"
|
||||
export CORTEX_NODES_MAX="${CORTEX_NODES_MAX:-5}"
|
||||
export CORTEX_NAMESPACE="${CORTEX_NAMESPACE:-cortex}"
|
||||
|
||||
export CORTEX_IMAGE_MANAGER="${CORTEX_IMAGE_MANAGER:-cortexlabs/manager:$CORTEX_VERSION_STABLE}"
|
||||
export CORTEX_IMAGE_FLUENTD="${CORTEX_IMAGE_FLUENTD:-cortexlabs/fluentd:$CORTEX_VERSION_STABLE}"
|
||||
export CORTEX_IMAGE_NGINX_BACKEND="${CORTEX_IMAGE_NGINX_BACKEND:-cortexlabs/nginx-backend:$CORTEX_VERSION_STABLE}"
|
||||
export CORTEX_IMAGE_NGINX_CONTROLLER="${CORTEX_IMAGE_NGINX_CONTROLLER:-cortexlabs/nginx-controller:$CORTEX_VERSION_STABLE}"
|
||||
export CORTEX_IMAGE_OPERATOR="${CORTEX_IMAGE_OPERATOR:-cortexlabs/operator:$CORTEX_VERSION_STABLE}"
|
||||
export CORTEX_IMAGE_SPARK="${CORTEX_IMAGE_SPARK:-cortexlabs/spark:$CORTEX_VERSION_STABLE}"
|
||||
export CORTEX_IMAGE_SPARK_OPERATOR="${CORTEX_IMAGE_SPARK_OPERATOR:-cortexlabs/spark-operator:$CORTEX_VERSION_STABLE}"
|
||||
export CORTEX_IMAGE_TF_SERVE="${CORTEX_IMAGE_TF_SERVE:-cortexlabs/tf-serve:$CORTEX_VERSION_STABLE}"
|
||||
export CORTEX_IMAGE_TF_TRAIN="${CORTEX_IMAGE_TF_TRAIN:-cortexlabs/tf-train:$CORTEX_VERSION_STABLE}"
|
||||
export CORTEX_IMAGE_TF_API="${CORTEX_IMAGE_TF_API:-cortexlabs/tf-api:$CORTEX_VERSION_STABLE}"
|
||||
export CORTEX_IMAGE_PYTHON_PACKAGER="${CORTEX_IMAGE_PYTHON_PACKAGER:-cortexlabs/python-packager:$CORTEX_VERSION_STABLE}"
|
||||
export CORTEX_IMAGE_TF_SERVE_GPU="${CORTEX_IMAGE_TF_SERVE_GPU:-cortexlabs/tf-serve-gpu:$CORTEX_VERSION_STABLE}"
|
||||
export CORTEX_IMAGE_TF_TRAIN_GPU="${CORTEX_IMAGE_TF_TRAIN_GPU:-cortexlabs/tf-train-gpu:$CORTEX_VERSION_STABLE}"
|
||||
export CORTEX_IMAGE_ONNX_SERVE="${CORTEX_IMAGE_ONNX_SERVE:-cortexlabs/onnx-serve:$CORTEX_VERSION_STABLE}"
|
||||
export CORTEX_IMAGE_ONNX_SERVE_GPU="${CORTEX_IMAGE_ONNX_SERVE_GPU:-cortexlabs/onnx-serve-gpu:$CORTEX_VERSION_STABLE}"
|
||||
export CORTEX_IMAGE_CLUSTER_AUTOSCALER="${CORTEX_IMAGE_CLUSTER_AUTOSCALER:-cortexlabs/cluster-autoscaler:$CORTEX_VERSION_STABLE}"
|
||||
export CORTEX_IMAGE_NVIDIA="${CORTEX_IMAGE_NVIDIA:-cortexlabs/nvidia:$CORTEX_VERSION_STABLE}"
|
||||
export CORTEX_IMAGE_METRICS_SERVER="${CORTEX_IMAGE_METRICS_SERVER:-cortexlabs/metrics-server:$CORTEX_VERSION_STABLE}"
|
||||
|
||||
export CORTEX_ENABLE_TELEMETRY="${CORTEX_ENABLE_TELEMETRY:-""}"
|
||||
|
||||
##########################
|
||||
### TOP-LEVEL COMMANDS ###
|
||||
##########################
|
||||
|
||||
function install_eks() {
|
||||
echo
|
||||
docker run -it --entrypoint /root/install_eks.sh \
|
||||
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
|
||||
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
|
||||
-e CORTEX_CLUSTER=$CORTEX_CLUSTER \
|
||||
-e CORTEX_REGION=$CORTEX_REGION \
|
||||
-e CORTEX_NODE_TYPE=$CORTEX_NODE_TYPE \
|
||||
-e CORTEX_NODES_MIN=$CORTEX_NODES_MIN \
|
||||
-e CORTEX_NODES_MAX=$CORTEX_NODES_MAX \
|
||||
$CORTEX_IMAGE_MANAGER
|
||||
}
|
||||
|
||||
function uninstall_eks() {
|
||||
echo
|
||||
docker run -it --entrypoint /root/uninstall_eks.sh \
|
||||
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
|
||||
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
|
||||
-e CORTEX_CLUSTER=$CORTEX_CLUSTER \
|
||||
-e CORTEX_REGION=$CORTEX_REGION \
|
||||
$CORTEX_IMAGE_MANAGER
|
||||
}
|
||||
|
||||
function install_cortex() {
|
||||
echo
|
||||
docker run -it --entrypoint /root/install_cortex.sh \
|
||||
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
|
||||
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
|
||||
-e CORTEX_CLUSTER=$CORTEX_CLUSTER \
|
||||
-e CORTEX_REGION=$CORTEX_REGION \
|
||||
-e CORTEX_NAMESPACE=$CORTEX_NAMESPACE \
|
||||
-e CORTEX_NODE_TYPE=$CORTEX_NODE_TYPE \
|
||||
-e CORTEX_LOG_GROUP=$CORTEX_LOG_GROUP \
|
||||
-e CORTEX_BUCKET=$CORTEX_BUCKET \
|
||||
-e CORTEX_IMAGE_FLUENTD=$CORTEX_IMAGE_FLUENTD \
|
||||
-e CORTEX_IMAGE_NGINX_BACKEND=$CORTEX_IMAGE_NGINX_BACKEND \
|
||||
-e CORTEX_IMAGE_NGINX_CONTROLLER=$CORTEX_IMAGE_NGINX_CONTROLLER \
|
||||
-e CORTEX_IMAGE_OPERATOR=$CORTEX_IMAGE_OPERATOR \
|
||||
-e CORTEX_IMAGE_SPARK=$CORTEX_IMAGE_SPARK \
|
||||
-e CORTEX_IMAGE_SPARK_OPERATOR=$CORTEX_IMAGE_SPARK_OPERATOR \
|
||||
-e CORTEX_IMAGE_TF_SERVE=$CORTEX_IMAGE_TF_SERVE \
|
||||
-e CORTEX_IMAGE_TF_TRAIN=$CORTEX_IMAGE_TF_TRAIN \
|
||||
-e CORTEX_IMAGE_TF_API=$CORTEX_IMAGE_TF_API \
|
||||
-e CORTEX_IMAGE_PYTHON_PACKAGER=$CORTEX_IMAGE_PYTHON_PACKAGER \
|
||||
-e CORTEX_IMAGE_TF_SERVE_GPU=$CORTEX_IMAGE_TF_SERVE_GPU \
|
||||
-e CORTEX_IMAGE_TF_TRAIN_GPU=$CORTEX_IMAGE_TF_TRAIN_GPU \
|
||||
-e CORTEX_IMAGE_ONNX_SERVE=$CORTEX_IMAGE_ONNX_SERVE \
|
||||
-e CORTEX_IMAGE_ONNX_SERVE_GPU=$CORTEX_IMAGE_ONNX_SERVE_GPU \
|
||||
-e CORTEX_IMAGE_CLUSTER_AUTOSCALER=$CORTEX_IMAGE_CLUSTER_AUTOSCALER \
|
||||
-e CORTEX_IMAGE_NVIDIA=$CORTEX_IMAGE_NVIDIA \
|
||||
-e CORTEX_IMAGE_METRICS_SERVER=$CORTEX_IMAGE_METRICS_SERVER \
|
||||
-e CORTEX_ENABLE_TELEMETRY=$CORTEX_ENABLE_TELEMETRY \
|
||||
$CORTEX_IMAGE_MANAGER
|
||||
}
|
||||
|
||||
function uninstall_operator() {
|
||||
echo
|
||||
docker run -it --entrypoint /root/uninstall_operator.sh \
|
||||
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
|
||||
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
|
||||
-e CORTEX_CLUSTER=$CORTEX_CLUSTER \
|
||||
-e CORTEX_REGION=$CORTEX_REGION \
|
||||
-e CORTEX_NAMESPACE=$CORTEX_NAMESPACE \
|
||||
$CORTEX_IMAGE_MANAGER
|
||||
}
|
||||
|
||||
function info() {
|
||||
echo
|
||||
docker run -it --entrypoint /root/info.sh \
|
||||
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
|
||||
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
|
||||
-e CORTEX_CLUSTER=$CORTEX_CLUSTER \
|
||||
-e CORTEX_REGION=$CORTEX_REGION \
|
||||
-e CORTEX_NAMESPACE=$CORTEX_NAMESPACE \
|
||||
$CORTEX_IMAGE_MANAGER
|
||||
}
|
||||
|
||||
################
|
||||
### CHECK OS ###
|
||||
################
|
||||
|
||||
case "$OSTYPE" in
|
||||
darwin*) PARSED_OS="darwin" ;;
|
||||
linux*) PARSED_OS="linux" ;;
|
||||
*) echo -e "\nerror: only mac and linux are supported"; exit 1 ;;
|
||||
esac
|
||||
|
||||
#############################
|
||||
### DEPENDENCY MANAGEMENT ###
|
||||
#############################
|
||||
|
||||
function check_dep_curl() {
|
||||
if ! command -v curl >/dev/null; then
|
||||
echo -e "\nerror: please install \`curl\`"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function install_cli() {
|
||||
set -e
|
||||
|
||||
check_dep_curl
|
||||
|
||||
echo -e "\nInstalling the Cortex CLI (/usr/local/bin/cortex) ..."
|
||||
|
||||
CORTEX_SH_TMP_DIR="$HOME/.cortex-sh-tmp"
|
||||
rm -rf $CORTEX_SH_TMP_DIR && mkdir -p $CORTEX_SH_TMP_DIR
|
||||
curl -s -o $CORTEX_SH_TMP_DIR/cortex https://s3-us-west-2.amazonaws.com/get-cortex/$CORTEX_VERSION_STABLE/cli/$PARSED_OS/cortex
|
||||
chmod +x $CORTEX_SH_TMP_DIR/cortex
|
||||
|
||||
if [ $(id -u) = 0 ]; then
|
||||
mv -f $CORTEX_SH_TMP_DIR/cortex /usr/local/bin/cortex
|
||||
else
|
||||
ask_sudo
|
||||
sudo mv -f $CORTEX_SH_TMP_DIR/cortex /usr/local/bin/cortex
|
||||
fi
|
||||
|
||||
rm -rf $CORTEX_SH_TMP_DIR
|
||||
echo "✓ Installed the Cortex CLI"
|
||||
|
||||
bash_profile_path=$(get_bash_profile)
|
||||
if [ ! "$bash_profile_path" = "" ]; then
|
||||
if ! grep -Fxq "source <(cortex completion)" "$bash_profile_path"; then
|
||||
echo
|
||||
read -p "Would you like to modify your bash profile ($bash_profile_path) to enable cortex command completion and the cx alias? [Y/n] " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo -e "\nsource <(cortex completion)" >> $bash_profile_path
|
||||
echo "✓ Your bash profile ($bash_profile_path) has been updated"
|
||||
echo
|
||||
echo "Note: \`bash_completion\` must be installed on your system for cortex command completion to function properly"
|
||||
echo
|
||||
echo "Command to update your current terminal session:"
|
||||
echo " source $bash_profile_path"
|
||||
else
|
||||
echo "Your bash profile has not been modified. If you would like to modify it manually, add this line to your bash profile:"
|
||||
echo " source <(cortex completion)"
|
||||
echo "Note: \`bash_completion\` must be installed on your system for cortex command completion to function properly"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo -e "\nIf your would like to enable cortex command completion and the cx alias, add this line to your bash profile:"
|
||||
echo " source <(cortex completion)"
|
||||
echo "Note: \`bash_completion\` must be installed on your system for cortex command completion to function properly"
|
||||
fi
|
||||
}
|
||||
|
||||
function uninstall_cli() {
|
||||
set -e
|
||||
|
||||
rm -rf $HOME/.cortex
|
||||
|
||||
if ! command -v cortex >/dev/null; then
|
||||
echo -e "\nThe Cortex CLI is not installed"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ ! -f /usr/local/bin/cortex ]]; then
|
||||
echo -e "\nThe Cortex CLI was not found at /usr/local/bin/cortex, please uninstall it manually"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ $(id -u) = 0 ]; then
|
||||
rm /usr/local/bin/cortex
|
||||
else
|
||||
ask_sudo
|
||||
sudo rm /usr/local/bin/cortex
|
||||
fi
|
||||
echo -e "\n✓ Uninstalled the Cortex CLI"
|
||||
|
||||
bash_profile_path=$(get_bash_profile)
|
||||
if [ ! "$bash_profile_path" = "" ]; then
|
||||
if grep -Fxq "source <(cortex completion)" "$bash_profile_path"; then
|
||||
echo
|
||||
read -p "Would you like to remove \"source <(cortex completion)\" from your bash profile ($bash_profile_path)? [Y/n] " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
sed '/^source <(cortex completion)$/d' "$bash_profile_path" > "${bash_profile_path}_cortex_modified" && mv -f "${bash_profile_path}_cortex_modified" "$bash_profile_path"
|
||||
echo "✓ Your bash profile ($bash_profile_path) has been updated"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function get_bash_profile() {
|
||||
if [ "$PARSED_OS" = "darwin" ]; then
|
||||
if [ -f $HOME/.bash_profile ]; then
|
||||
echo $HOME/.bash_profile
|
||||
return
|
||||
elif [ -f $HOME/.bashrc ]; then
|
||||
echo $HOME/.bashrc
|
||||
return
|
||||
fi
|
||||
else
|
||||
if [ -f $HOME/.bashrc ]; then
|
||||
echo $HOME/.bashrc
|
||||
return
|
||||
elif [ -f $HOME/.bash_profile ]; then
|
||||
echo $HOME/.bash_profile
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
function ask_sudo() {
|
||||
if ! sudo -n true 2>/dev/null; then
|
||||
echo -e "\nPlease enter your sudo password"
|
||||
fi
|
||||
}
|
||||
|
||||
function prompt_for_telemetry() {
|
||||
if [ "$CORTEX_ENABLE_TELEMETRY" != "true" ] && [ "$CORTEX_ENABLE_TELEMETRY" != "false" ]; then
|
||||
while true
|
||||
do
|
||||
echo
|
||||
read -p "Would you like to help improve Cortex by anonymously sending error reports and usage stats to the dev team? [Y/n] " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
export CORTEX_ENABLE_TELEMETRY=true
|
||||
break
|
||||
elif [[ $REPLY =~ ^[Nn]$ ]]; then
|
||||
export CORTEX_ENABLE_TELEMETRY=false
|
||||
break
|
||||
fi
|
||||
echo "Unexpected value, please enter \"Y\" or \"n\""
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
############
|
||||
### HELP ###
|
||||
############
|
||||
|
||||
function show_help() {
|
||||
echo "
|
||||
Usage:
|
||||
./cortex.sh command [sub-command] [flags]
|
||||
|
||||
Available Commands:
|
||||
install install Cortex
|
||||
uninstall uninstall Cortex
|
||||
update update Cortex
|
||||
info information about Cortex
|
||||
|
||||
install cli install the Cortex CLI
|
||||
uninstall cli uninstall the Cortex CLI
|
||||
|
||||
Flags:
|
||||
-c, --config path to a Cortex config file
|
||||
-h, --help
|
||||
"
|
||||
}
|
||||
|
||||
######################
|
||||
### ARG PROCESSING ###
|
||||
######################
|
||||
|
||||
arg1=${1:-""}
|
||||
arg2=${2:-""}
|
||||
arg3=${3:-""}
|
||||
|
||||
if [ -z "$arg1" ]; then
|
||||
show_help
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$arg1" = "install" ]; then
|
||||
if [ ! "$arg3" = "" ]; then
|
||||
echo -e "\nerror: too many arguments for install command"
|
||||
show_help
|
||||
exit 1
|
||||
elif [ "$arg2" = "" ]; then
|
||||
prompt_for_telemetry && install_eks && install_cortex && info
|
||||
elif [ "$arg2" = "cli" ]; then
|
||||
install_cli
|
||||
elif [ "$arg2" = "" ]; then
|
||||
echo -e "\nerror: missing subcommand for install"
|
||||
show_help
|
||||
exit 1
|
||||
else
|
||||
echo -e "\nerror: invalid subcommand for install: $arg2"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
elif [ "$arg1" = "uninstall" ]; then
|
||||
if [ ! "$arg3" = "" ]; then
|
||||
echo -e "\nerror: too many arguments for uninstall command"
|
||||
show_help
|
||||
exit 1
|
||||
elif [ "$arg2" = "" ]; then
|
||||
uninstall_eks
|
||||
elif [ "$arg2" = "cli" ]; then
|
||||
uninstall_cli
|
||||
elif [ "$arg2" = "" ]; then
|
||||
echo -e "\nerror: missing subcommand for uninstall"
|
||||
show_help
|
||||
exit 1
|
||||
else
|
||||
echo -e "\nerror: invalid subcommand for uninstall: $arg2"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
elif [ "$arg1" = "update" ]; then
|
||||
if [ ! "$arg2" = "" ]; then
|
||||
echo -e "\nerror: too many arguments for get command"
|
||||
show_help
|
||||
exit 1
|
||||
else
|
||||
uninstall_operator && install_cortex
|
||||
fi
|
||||
elif [ "$arg1" = "info" ]; then
|
||||
if [ ! "$arg2" = "" ]; then
|
||||
echo -e "\nerror: too many arguments for get command"
|
||||
show_help
|
||||
exit 1
|
||||
else
|
||||
info
|
||||
fi
|
||||
else
|
||||
echo -e "\nerror: unknown command: $arg1"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
import json
|
||||
import os
|
||||
import numpy as np
|
||||
import tensorflow as tf
|
||||
|
||||
import gpt2.src.model as model
|
||||
from tensorflow.contrib import predictor
|
||||
import gpt2.src.sample as sample
|
||||
import gpt2.src.encoder as encoder
|
||||
from utils import *
|
||||
|
||||
pos_action_starts = ["You attack", "You tell", "You use", "You go"]
|
||||
|
||||
|
||||
class StoryGenerator():
|
||||
|
||||
def __init__(self, sess, length=75, temperature=0.9, top_k=40):
|
||||
|
||||
seed = None
|
||||
batch_size=1
|
||||
model_path='gpt2/models/117M'
|
||||
self.sess = sess
|
||||
|
||||
self.enc = encoder.get_encoder(model_path)
|
||||
hparams = model.default_hparams()
|
||||
with open(os.path.join(model_path, 'hparams.json')) as f:
|
||||
hparams.override_from_dict(json.load(f))
|
||||
|
||||
self.context = tf.placeholder(tf.int32, [batch_size, None])
|
||||
np.random.seed(seed)
|
||||
tf.set_random_seed(seed)
|
||||
self.output = sample.sample_sequence(
|
||||
hparams=hparams, length=length,
|
||||
context=self.context,
|
||||
batch_size=batch_size,
|
||||
)
|
||||
|
||||
saver = tf.train.Saver()
|
||||
ckpt = tf.train.latest_checkpoint(model_path)
|
||||
saver.restore(self.sess, ckpt)
|
||||
|
||||
|
||||
def generate(self, prompt):
|
||||
context_tokens = self.enc.encode(prompt)
|
||||
out = self.sess.run(self.output, feed_dict={
|
||||
self.context: [context_tokens for _ in range(1)]
|
||||
})[:, len(context_tokens):]
|
||||
|
||||
text = self.enc.decode(out[0])
|
||||
return text
|
||||
|
||||
def generate_story_block(self, prompt):
|
||||
block = self.generate(prompt)
|
||||
block = cut_trailing_sentence(block)
|
||||
block = story_replace(block)
|
||||
|
||||
return block
|
||||
|
||||
def generate_action_options(self, prompt, action_starts=pos_action_starts):
|
||||
|
||||
possible_actions = []
|
||||
for phrase in action_starts:
|
||||
action = phrase + self.generate(prompt + phrase)
|
||||
action = first_sentence(action)
|
||||
possible_actions.append(action)
|
||||
|
||||
return possible_actions
|
||||
|
||||
def generate_action_result(self, prompt, phrase):
|
||||
action = phrase + self.generate(prompt + phrase)
|
||||
action_result = cut_trailing_sentence(action)
|
||||
action_result = story_replace(action_result)
|
||||
|
||||
action = first_sentence(action)
|
||||
|
||||
|
||||
return action, action_result
|
||||
|
||||
|
||||
def save_model():
|
||||
length=75
|
||||
temperature=0.9
|
||||
top_k=40
|
||||
|
||||
with tf.Session() as sess:
|
||||
seed = None
|
||||
batch_size=None
|
||||
model_path='gpt2/models/117M'
|
||||
|
||||
hparams = model.default_hparams()
|
||||
with open(os.path.join(model_path, 'hparams.json')) as f:
|
||||
hparams.override_from_dict(json.load(f))
|
||||
|
||||
context = tf.placeholder(tf.int32, [batch_size, None])
|
||||
np.random.seed(seed)
|
||||
tf.set_random_seed(seed)
|
||||
output = sample.sample_sequence(
|
||||
hparams=hparams, length=length,
|
||||
context=context,
|
||||
batch_size=batch_size,
|
||||
)
|
||||
print("***********************",type(output))
|
||||
|
||||
saver = tf.train.Saver()
|
||||
ckpt = tf.train.latest_checkpoint(model_path)
|
||||
saver.restore(sess, ckpt)
|
||||
|
||||
tf.saved_model.simple_save(sess, "./saved2", inputs={"context": context}, outputs={"output": output})
|
||||
|
||||
|
||||
def generate_gpu_config(memory_fraction):
|
||||
config = tf.ConfigProto()
|
||||
config.gpu_options.allow_growth = True
|
||||
config.gpu_options.per_process_gpu_memory_fraction = memory_fraction
|
||||
return config
|
||||
|
||||
def run_interactive():
|
||||
pass
|
||||
|
||||
|
||||
def load_model():
|
||||
# Set your memory fraction equal to a value less than 1, 0.6 is a good starting point.
|
||||
# If no fraction is defined, the tensorflow algorithm may run into gpu out of memory problems.
|
||||
fraction = 0.6
|
||||
config = config=generate_gpu_config(fraction)
|
||||
path_to_graph = "./saved"
|
||||
|
||||
#tf.saved_model.loader.load(
|
||||
# session,
|
||||
# [tf.saved_model.tag_constants.SERVING],
|
||||
# path_to_graph)
|
||||
|
||||
#output = session.graph.get_tensor_by_name('output:0')
|
||||
#context = session.graph.get_tensor_by_name('context:0')
|
||||
model_path = 'gpt2/models/117M'
|
||||
enc = encoder.get_encoder(model_path)
|
||||
|
||||
predict_fn = predictor.from_saved_model(path_to_graph, config=config)
|
||||
context_tokens = [enc.encode("hello")]
|
||||
predictions = predict_fn({"context": context_tokens})
|
||||
output = enc.decode(predictions["output"][0])
|
||||
print(output)
|
||||
|
||||
return (output, session)
|
||||
|
||||
if __name__ == '__main__':
|
||||
save_model()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# Contributors (alphabetically)
|
||||
|
||||
* **[madisonmay](https://github.com/madisonmay)**
|
||||
|
||||
Added Dockerfiles
|
||||
|
||||
* **[Margaret Mitchell et al](https://arxiv.org/abs/1810.03993)**
|
||||
|
||||
Our [usage](./README.md#usage) writeup was loosely inspired by the paper
|
||||
[Model Cards for Model Reporting](https://arxiv.org/abs/1810.03993)
|
||||
and related conversations with some of the authors.
|
||||
|
||||
* **[webproduktion01](https://github.com/webproduktion01)**
|
||||
|
||||
Ported download script to python.
|
||||
|
||||
**[Full code contributors list](https://github.com/openai/gpt-2/contributors).**
|
||||
@@ -0,0 +1,85 @@
|
||||
# Installation
|
||||
|
||||
Git clone this repository, and `cd` into directory for remaining commands
|
||||
```
|
||||
git clone https://github.com/openai/gpt-2.git && cd gpt-2
|
||||
```
|
||||
|
||||
Then, follow instructions for either native or Docker installation.
|
||||
|
||||
## Native Installation
|
||||
|
||||
All steps can optionally be done in a virtual environment using tools such as `virtualenv` or `conda`.
|
||||
|
||||
Install tensorflow 1.12 (with GPU support, if you have a GPU and want everything to run faster)
|
||||
```
|
||||
pip3 install tensorflow==1.12.0
|
||||
```
|
||||
or
|
||||
```
|
||||
pip3 install tensorflow-gpu==1.12.0
|
||||
```
|
||||
|
||||
Install other python packages:
|
||||
```
|
||||
pip3 install -r requirements.txt
|
||||
```
|
||||
|
||||
Download the model data
|
||||
```
|
||||
python3 download_model.py 117M
|
||||
```
|
||||
|
||||
## Docker Installation
|
||||
|
||||
Build the Dockerfile and tag the created image as `gpt-2`:
|
||||
```
|
||||
docker build --tag gpt-2 -f Dockerfile.gpu . # or Dockerfile.cpu
|
||||
```
|
||||
|
||||
Start an interactive bash session from the `gpt-2` docker image.
|
||||
|
||||
You can opt to use the `--runtime=nvidia` flag if you have access to a NVIDIA GPU
|
||||
and a valid install of [nvidia-docker 2.0](https://github.com/nvidia/nvidia-docker/wiki/Installation-(version-2.0)).
|
||||
```
|
||||
docker run --runtime=nvidia -it gpt-2 bash
|
||||
```
|
||||
|
||||
# Running
|
||||
|
||||
| WARNING: Samples are unfiltered and may contain offensive content. |
|
||||
| --- |
|
||||
|
||||
Some of the examples below may include Unicode text characters. Set the environment variable:
|
||||
```
|
||||
export PYTHONIOENCODING=UTF-8
|
||||
```
|
||||
to override the standard stream settings in UTF-8 mode.
|
||||
|
||||
## Unconditional sample generation
|
||||
|
||||
To generate unconditional samples from the small model:
|
||||
```
|
||||
python3 src/generate_unconditional_samples.py | tee /tmp/samples
|
||||
```
|
||||
There are various flags for controlling the samples:
|
||||
```
|
||||
python3 src/generate_unconditional_samples.py --top_k 40 --temperature 0.7 | tee /tmp/samples
|
||||
```
|
||||
|
||||
To check flag descriptions, use:
|
||||
```
|
||||
python3 src/generate_unconditional_samples.py -- --help
|
||||
```
|
||||
|
||||
## Conditional sample generation
|
||||
|
||||
To give the model custom prompts, you can use:
|
||||
```
|
||||
python3 src/interactive_conditional_samples.py --top_k 40
|
||||
```
|
||||
|
||||
To check flag descriptions, use:
|
||||
```
|
||||
python3 src/interactive_conditional_samples.py -- --help
|
||||
```
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 OpenAI
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,61 @@
|
||||
# gpt-2
|
||||
|
||||
Code and samples from the paper ["Language Models are Unsupervised Multitask Learners"](https://d4mucfpksywv.cloudfront.net/better-language-models/language-models.pdf).
|
||||
|
||||
For now, we have only released a smaller (117M parameter) version of GPT-2.
|
||||
|
||||
See more details in our [blog post](https://blog.openai.com/better-language-models/).
|
||||
|
||||
## Usage
|
||||
|
||||
This repository is meant to be a starting point for researchers and engineers to experiment with GPT-2-117M. While GPT-2-117M is less proficient than GPT-2-1.5B, it is useful for a wide range of research and applications which could also apply to larger models.
|
||||
|
||||
### Some caveats
|
||||
|
||||
- GPT-2-117M robustness and worst case behaviors are not well-understood. As with any machine-learned model, carefully evaluate GPT-2-117M for your use case, especially if used without fine-tuning or in safety-critical applications where reliability is important.
|
||||
- The dataset our GPT-2-117M was trained on contains many texts with [biases](https://twitter.com/TomerUllman/status/1101485289720242177) and factual inaccuracies, and thus GPT-2-117M is likely to be biased and inaccurate as well.
|
||||
- To avoid having samples mistaken as human-written, we recommend clearly labeling samples as synthetic before wide dissemination. Our models are often incoherent or inaccurate in subtle ways, which takes more than a quick read for a human to notice.
|
||||
|
||||
### Work with us
|
||||
|
||||
Please [let us know](mailto:languagequestions@openai.com) if you’re doing interesting research with or working on applications of GPT-2-117M! We’re especially interested in hearing from and potentially working with those who are studying
|
||||
- Potential malicious use cases and defenses against them (e.g. the detectability of synthetic text)
|
||||
- The extent of problematic content (e.g. bias) being baked into the models and effective mitigations
|
||||
|
||||
## Development
|
||||
|
||||
See [DEVELOPERS.md](./DEVELOPERS.md)
|
||||
|
||||
## Contributors
|
||||
|
||||
See [CONTRIBUTORS.md](./CONTRIBUTORS.md)
|
||||
|
||||
## GPT-2 samples
|
||||
|
||||
| WARNING: Samples are unfiltered and may contain offensive content. |
|
||||
| --- |
|
||||
|
||||
While we have not yet released GPT-2 itself, you can see some samples from it in the `gpt-2-samples` folder.
|
||||
We show unconditional samples with default settings (temperature 1 and no truncation), with temperature 0.7, and with truncation with top_k 40.
|
||||
We show conditional samples, with contexts drawn from `WebText`'s test set, with default settings (temperature 1 and no truncation), with temperature 0.7, and with truncation with top_k 40.
|
||||
|
||||
## Citation
|
||||
|
||||
Please use the following bibtex entry:
|
||||
```
|
||||
@article{radford2019language,
|
||||
title={Language Models are Unsupervised Multitask Learners},
|
||||
author={Radford, Alec and Wu, Jeff and Child, Rewon and Luan, David and Amodei, Dario and Sutskever, Ilya},
|
||||
year={2019}
|
||||
}
|
||||
```
|
||||
|
||||
## Future work
|
||||
|
||||
We may release code for evaluating the models on various benchmarks.
|
||||
|
||||
We are still considering release of the larger models.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](./LICENSE)
|
||||
@@ -0,0 +1,28 @@
|
||||
import os
|
||||
import sys
|
||||
import requests
|
||||
from tqdm import tqdm
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
print('You must enter the model name as a parameter, e.g.: download_model.py 117M')
|
||||
sys.exit(1)
|
||||
|
||||
model = sys.argv[1]
|
||||
|
||||
subdir = os.path.join('models', model)
|
||||
if not os.path.exists(subdir):
|
||||
os.makedirs(subdir)
|
||||
subdir = subdir.replace('\\','/') # needed for Windows
|
||||
|
||||
for filename in ['checkpoint','encoder.json','hparams.json','model.ckpt.data-00000-of-00001', 'model.ckpt.index', 'model.ckpt.meta', 'vocab.bpe']:
|
||||
|
||||
r = requests.get("https://storage.googleapis.com/gpt-2/" + subdir + "/" + filename, stream=True)
|
||||
|
||||
with open(os.path.join(subdir, filename), 'wb') as f:
|
||||
file_size = int(r.headers["content-length"])
|
||||
chunk_size = 1000
|
||||
with tqdm(ncols=100, desc="Fetching " + filename, total=file_size, unit_scale=True) as pbar:
|
||||
# 1k for chunk_size, since Ethernet packet size is around 1500 bytes
|
||||
for chunk in r.iter_content(chunk_size=chunk_size):
|
||||
f.write(chunk)
|
||||
pbar.update(chunk_size)
|
||||
@@ -0,0 +1 @@
|
||||
model*
|
||||
@@ -0,0 +1,2 @@
|
||||
model_checkpoint_path: "model.ckpt"
|
||||
all_model_checkpoint_paths: "model.ckpt"
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"n_vocab": 50257,
|
||||
"n_ctx": 1024,
|
||||
"n_embd": 768,
|
||||
"n_head": 12,
|
||||
"n_layer": 12
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,176 @@
|
||||
import numpy as np
|
||||
import tensorflow as tf
|
||||
from tensorflow.contrib.training import HParams
|
||||
|
||||
def default_hparams():
|
||||
return HParams(
|
||||
n_vocab=0,
|
||||
n_ctx=1024,
|
||||
n_embd=768,
|
||||
n_head=12,
|
||||
n_layer=12,
|
||||
)
|
||||
|
||||
def shape_list(x):
|
||||
"""Deal with dynamic shape in tensorflow cleanly."""
|
||||
static = x.shape.as_list()
|
||||
dynamic = tf.shape(x)
|
||||
return [dynamic[i] if s is None else s for i, s in enumerate(static)]
|
||||
|
||||
def softmax(x, axis=-1):
|
||||
x = x - tf.reduce_max(x, axis=axis, keepdims=True)
|
||||
ex = tf.exp(x)
|
||||
return ex / tf.reduce_sum(ex, axis=axis, keepdims=True)
|
||||
|
||||
def gelu(x):
|
||||
return 0.5*x*(1+tf.tanh(np.sqrt(2/np.pi)*(x+0.044715*tf.pow(x, 3))))
|
||||
|
||||
def norm(x, scope, *, axis=-1, epsilon=1e-5):
|
||||
"""Normalize to mean = 0, std = 1, then do a diagonal affine transform."""
|
||||
with tf.variable_scope(scope):
|
||||
n_state = x.shape[-1].value
|
||||
g = tf.get_variable('g', [n_state], initializer=tf.constant_initializer(1))
|
||||
b = tf.get_variable('b', [n_state], initializer=tf.constant_initializer(0))
|
||||
u = tf.reduce_mean(x, axis=axis, keepdims=True)
|
||||
s = tf.reduce_mean(tf.square(x-u), axis=axis, keepdims=True)
|
||||
x = (x - u) * tf.rsqrt(s + epsilon)
|
||||
x = x*g + b
|
||||
return x
|
||||
|
||||
def split_states(x, n):
|
||||
"""Reshape the last dimension of x into [n, x.shape[-1]/n]."""
|
||||
*start, m = shape_list(x)
|
||||
return tf.reshape(x, start + [n, m//n])
|
||||
|
||||
def merge_states(x):
|
||||
"""Smash the last two dimensions of x into a single dimension."""
|
||||
*start, a, b = shape_list(x)
|
||||
return tf.reshape(x, start + [a*b])
|
||||
|
||||
def conv1d(x, scope, nf, *, w_init_stdev=0.02):
|
||||
with tf.variable_scope(scope):
|
||||
*start, nx = shape_list(x)
|
||||
w = tf.get_variable('w', [1, nx, nf], initializer=tf.random_normal_initializer(stddev=w_init_stdev))
|
||||
b = tf.get_variable('b', [nf], initializer=tf.constant_initializer(0))
|
||||
c = tf.reshape(tf.matmul(tf.reshape(x, [-1, nx]), tf.reshape(w, [-1, nf]))+b, start+[nf])
|
||||
return c
|
||||
|
||||
def attention_mask(nd, ns, *, dtype):
|
||||
"""1's in the lower triangle, counting from the lower right corner.
|
||||
|
||||
Same as tf.matrix_band_part(tf.ones([nd, ns]), -1, ns-nd), but doesn't produce garbage on TPUs.
|
||||
"""
|
||||
i = tf.range(nd)[:,None]
|
||||
j = tf.range(ns)
|
||||
m = i >= j - ns + nd
|
||||
return tf.cast(m, dtype)
|
||||
|
||||
|
||||
def attn(x, scope, n_state, *, past, hparams):
|
||||
assert x.shape.ndims == 3 # Should be [batch, sequence, features]
|
||||
assert n_state % hparams.n_head == 0
|
||||
if past is not None:
|
||||
assert past.shape.ndims == 5 # Should be [batch, 2, heads, sequence, features], where 2 is [k, v]
|
||||
|
||||
def split_heads(x):
|
||||
# From [batch, sequence, features] to [batch, heads, sequence, features]
|
||||
return tf.transpose(split_states(x, hparams.n_head), [0, 2, 1, 3])
|
||||
|
||||
def merge_heads(x):
|
||||
# Reverse of split_heads
|
||||
return merge_states(tf.transpose(x, [0, 2, 1, 3]))
|
||||
|
||||
def mask_attn_weights(w):
|
||||
# w has shape [batch, heads, dst_sequence, src_sequence], where information flows from src to dst.
|
||||
_, _, nd, ns = shape_list(w)
|
||||
b = attention_mask(nd, ns, dtype=w.dtype)
|
||||
b = tf.reshape(b, [1, 1, nd, ns])
|
||||
w = w*b - tf.cast(1e10, w.dtype)*(1-b)
|
||||
return w
|
||||
|
||||
def multihead_attn(q, k, v):
|
||||
# q, k, v have shape [batch, heads, sequence, features]
|
||||
w = tf.matmul(q, k, transpose_b=True)
|
||||
w = w * tf.rsqrt(tf.cast(v.shape[-1].value, w.dtype))
|
||||
|
||||
w = mask_attn_weights(w)
|
||||
w = softmax(w)
|
||||
a = tf.matmul(w, v)
|
||||
return a
|
||||
|
||||
with tf.variable_scope(scope):
|
||||
c = conv1d(x, 'c_attn', n_state*3)
|
||||
q, k, v = map(split_heads, tf.split(c, 3, axis=2))
|
||||
present = tf.stack([k, v], axis=1)
|
||||
if past is not None:
|
||||
pk, pv = tf.unstack(past, axis=1)
|
||||
k = tf.concat([pk, k], axis=-2)
|
||||
v = tf.concat([pv, v], axis=-2)
|
||||
a = multihead_attn(q, k, v)
|
||||
a = merge_heads(a)
|
||||
a = conv1d(a, 'c_proj', n_state)
|
||||
return a, present
|
||||
|
||||
|
||||
def mlp(x, scope, n_state, *, hparams):
|
||||
with tf.variable_scope(scope):
|
||||
nx = x.shape[-1].value
|
||||
h = gelu(conv1d(x, 'c_fc', n_state))
|
||||
h2 = conv1d(h, 'c_proj', nx)
|
||||
return h2
|
||||
|
||||
|
||||
def block(x, scope, *, past, hparams):
|
||||
with tf.variable_scope(scope):
|
||||
nx = x.shape[-1].value
|
||||
a, present = attn(norm(x, 'ln_1'), 'attn', nx, past=past, hparams=hparams)
|
||||
x = x + a
|
||||
m = mlp(norm(x, 'ln_2'), 'mlp', nx*4, hparams=hparams)
|
||||
x = x + m
|
||||
return x, present
|
||||
|
||||
def past_shape(*, hparams, batch_size=None, sequence=None):
|
||||
return [batch_size, hparams.n_layer, 2, hparams.n_head, sequence, hparams.n_embd // hparams.n_head]
|
||||
|
||||
def expand_tile(value, size):
|
||||
"""Add a new axis of given size."""
|
||||
value = tf.convert_to_tensor(value, name='value')
|
||||
ndims = value.shape.ndims
|
||||
return tf.tile(tf.expand_dims(value, axis=0), [size] + [1]*ndims)
|
||||
|
||||
def positions_for(tokens, past_length):
|
||||
batch_size = tf.shape(tokens)[0]
|
||||
nsteps = tf.shape(tokens)[1]
|
||||
return expand_tile(past_length + tf.range(nsteps), batch_size)
|
||||
|
||||
|
||||
def model(hparams, X, past=None, scope='model', reuse=False):
|
||||
with tf.variable_scope(scope, reuse=reuse):
|
||||
results = {}
|
||||
batch, sequence = shape_list(X)
|
||||
|
||||
wpe = tf.get_variable('wpe', [hparams.n_ctx, hparams.n_embd],
|
||||
initializer=tf.random_normal_initializer(stddev=0.01))
|
||||
wte = tf.get_variable('wte', [hparams.n_vocab, hparams.n_embd],
|
||||
initializer=tf.random_normal_initializer(stddev=0.02))
|
||||
past_length = 0 if past is None else tf.shape(past)[-2]
|
||||
h = tf.gather(wte, X) + tf.gather(wpe, positions_for(X, past_length))
|
||||
|
||||
# Transformer
|
||||
presents = []
|
||||
pasts = tf.unstack(past, axis=1) if past is not None else [None] * hparams.n_layer
|
||||
assert len(pasts) == hparams.n_layer
|
||||
for layer, past in enumerate(pasts):
|
||||
h, present = block(h, 'h%d' % layer, past=past, hparams=hparams)
|
||||
presents.append(present)
|
||||
results['present'] = tf.stack(presents, axis=1)
|
||||
h = norm(h, 'ln_f')
|
||||
|
||||
# Language model loss. Do tokens <n predict token n?
|
||||
h_flat = tf.reshape(h, [batch*sequence, hparams.n_embd])
|
||||
logits = tf.matmul(h_flat, wte, transpose_b=True)
|
||||
logits = tf.reshape(logits, [batch, sequence, hparams.n_vocab])
|
||||
results['logits'] = logits
|
||||
return results
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import tensorflow as tf
|
||||
|
||||
import gpt2.src.model as model
|
||||
|
||||
def top_k_logits(logits, k):
|
||||
if k == 0:
|
||||
# no truncation
|
||||
return logits
|
||||
|
||||
def _top_k():
|
||||
values, _ = tf.nn.top_k(logits, k=k)
|
||||
min_values = values[:, -1, tf.newaxis]
|
||||
return tf.where(
|
||||
logits < min_values,
|
||||
tf.ones_like(logits, dtype=logits.dtype) * -1e10,
|
||||
logits,
|
||||
)
|
||||
return tf.cond(
|
||||
tf.equal(k, 0),
|
||||
lambda: logits,
|
||||
lambda: _top_k(),
|
||||
)
|
||||
|
||||
|
||||
def sample_sequence(*, hparams, length, start_token=None, batch_size=None, context=None, temperature=1, top_k=0):
|
||||
if start_token is None:
|
||||
assert context is not None, 'Specify exactly one of start_token and context!'
|
||||
else:
|
||||
assert context is None, 'Specify exactly one of start_token and context!'
|
||||
context = tf.fill([batch_size, 1], start_token)
|
||||
|
||||
def step(hparams, tokens, past=None):
|
||||
lm_output = model.model(hparams=hparams, X=tokens, past=past, reuse=tf.AUTO_REUSE)
|
||||
|
||||
logits = lm_output['logits'][:, :, :hparams.n_vocab]
|
||||
presents = lm_output['present']
|
||||
presents.set_shape(model.past_shape(hparams=hparams, batch_size=batch_size))
|
||||
return {
|
||||
'logits': logits,
|
||||
'presents': presents,
|
||||
}
|
||||
|
||||
with tf.name_scope('sample_sequence'):
|
||||
# Don't feed the last context token -- leave that to the loop below
|
||||
# TODO: Would be slightly faster if we called step on the entire context,
|
||||
# rather than leaving the last token transformer calculation to the while loop.
|
||||
context_output = step(hparams, context[:, :-1])
|
||||
|
||||
def body(past, prev, output):
|
||||
next_outputs = step(hparams, prev[:, tf.newaxis], past=past)
|
||||
logits = next_outputs['logits'][:, -1, :] / tf.to_float(temperature)
|
||||
logits = top_k_logits(logits, k=top_k)
|
||||
samples = tf.multinomial(logits, num_samples=1, output_dtype=tf.int32)
|
||||
return [
|
||||
tf.concat([past, next_outputs['presents']], axis=-2),
|
||||
tf.squeeze(samples, axis=[1]),
|
||||
tf.concat([output, samples], axis=1),
|
||||
]
|
||||
|
||||
def cond(*args):
|
||||
return True
|
||||
|
||||
_, _, tokens = tf.while_loop(
|
||||
cond=cond, body=body,
|
||||
maximum_iterations=length,
|
||||
loop_vars=[
|
||||
context_output['presents'],
|
||||
context[:, -1],
|
||||
context,
|
||||
],
|
||||
shape_invariants=[
|
||||
tf.TensorShape(model.past_shape(hparams=hparams, batch_size=batch_size)),
|
||||
tf.TensorShape([batch_size]),
|
||||
tf.TensorShape([batch_size, None]),
|
||||
],
|
||||
back_prop=False, name="EndWhile"
|
||||
)
|
||||
|
||||
return tokens
|
||||
@@ -26,6 +26,7 @@ from flask import Response
|
||||
import requests
|
||||
import pdb
|
||||
import sys
|
||||
from generator import StoryGenerator
|
||||
import gpt2.src.encoder as encoder
|
||||
|
||||
|
||||
@@ -47,6 +48,25 @@ os.environ['GOOGLE_APPLICATION_CREDENTIALS']="./AI-Adventure-2bb65e3a4e2f.json"
|
||||
storage_client = storage.Client()
|
||||
bucket = storage_client.get_bucket("dungeon-cache")
|
||||
|
||||
# Local generator functionality
|
||||
RUN_LOCAL = True
|
||||
session = None
|
||||
local_generator = None
|
||||
def get_local_generator():
|
||||
if "gen" not in g:
|
||||
if "sess" not in g:
|
||||
g.sess = tf.Session()
|
||||
g.gen = StoryGenerator(g.sess)
|
||||
|
||||
return g.gen
|
||||
|
||||
|
||||
@app.teardown_appcontext
|
||||
def teardown_sess(_):
|
||||
sess = g.pop("sess", None)
|
||||
|
||||
if sess is not None:
|
||||
sess.close()
|
||||
|
||||
def predict(context_tokens):
|
||||
service = googleapiclient.discovery.build('ml', 'v1')
|
||||
@@ -80,20 +100,31 @@ def generate(prompt):
|
||||
print("generate request failed, trying again")
|
||||
continue
|
||||
|
||||
def generate_story_block(prompt):
|
||||
block = generate(prompt)
|
||||
|
||||
def generate_story_block(prompt, local=False):
|
||||
|
||||
if local:
|
||||
generator = get_local_generator()
|
||||
block = generator.generate(prompt)
|
||||
else:
|
||||
block = generate(prompt)
|
||||
|
||||
block = cut_trailing_sentence(block)
|
||||
block = story_replace(block)
|
||||
|
||||
return block
|
||||
|
||||
def generate_action_result(prompt, phrase):
|
||||
action = phrase + generate(prompt + phrase)
|
||||
|
||||
|
||||
def generate_action_result(prompt, phrase, local=False):
|
||||
|
||||
if local:
|
||||
generator = get_local_generator()
|
||||
action = phrase + generator.generate(prompt + phrase)
|
||||
else:
|
||||
action = phrase + generate(prompt + phrase)
|
||||
|
||||
action_result = cut_trailing_sentence(action)
|
||||
action_result = story_replace(action_result)
|
||||
|
||||
action = first_sentence(action)
|
||||
|
||||
|
||||
return action, action_result
|
||||
|
||||
@@ -124,33 +155,34 @@ def about():
|
||||
|
||||
|
||||
def cache_file(seed, prompt_num, choices, response, tag):
|
||||
|
||||
blob_file_name = "prompt" + 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")
|
||||
return
|
||||
# blob_file_name = "prompt" + 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 = "prompt" + 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
|
||||
return None
|
||||
# blob_file_name = "prompt" + 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'])
|
||||
@@ -178,7 +210,7 @@ def story_request():
|
||||
last_action_result = request.form["last_action_result"]
|
||||
prompt = continuing_prompts[prompt_num] + last_action_result
|
||||
print("\n\nAction prompt is \n ", prompt)
|
||||
action_results = [generate_action_result(prompt, phrase) for phrase in phrases]
|
||||
action_results = [generate_action_result(prompt, phrase, local=RUN_LOCAL) for phrase in phrases]
|
||||
response = json.dumps(action_results)
|
||||
cache_file(seed, prompt_num, choices, response, "choices")
|
||||
else:
|
||||
@@ -190,7 +222,7 @@ def story_request():
|
||||
response = result
|
||||
else:
|
||||
prompt = prompts[prompt_num]
|
||||
response = generate_story_block(prompt)
|
||||
response = generate_story_block(prompt, local=RUN_LOCAL)
|
||||
cache_file(seed, prompt_num, [], response, "story")
|
||||
|
||||
print("\nGenerated response is: \n", response)
|
||||
@@ -253,10 +285,7 @@ def generate_cache():
|
||||
action_queue.append([seed, 0, new_choices, un_jsoned[j][1]])
|
||||
|
||||
if __name__ == '__main__':
|
||||
if(len(sys.argv) > 1):
|
||||
generate_cache()
|
||||
else:
|
||||
app.run(host='0.0.0.0', port=8080)
|
||||
app.run(host='0.0.0.0', port=8080)
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user