local branc

This commit is contained in:
Nick Walton
2019-09-09 15:35:21 -06:00
parent 10ca1a84dc
commit 64dbdf1e84
16 changed files with 1192 additions and 38 deletions
Executable
+468
View File
@@ -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
View File
@@ -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()
+17
View File
@@ -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).**
+85
View File
@@ -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
```
+21
View File
@@ -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.
+61
View File
@@ -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 youre doing interesting research with or working on applications of GPT-2-117M! Were 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)
View File
+28
View File
@@ -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)
+1
View File
@@ -0,0 +1 @@
model*
+2
View File
@@ -0,0 +1,2 @@
model_checkpoint_path: "model.ckpt"
all_model_checkpoint_paths: "model.ckpt"
+7
View File
@@ -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.
+176
View File
@@ -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
+79
View File
@@ -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
+67 -38
View File
@@ -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)