From a6ecf2e85595750b2102b3d648c7bef27c3d29d4 Mon Sep 17 00:00:00 2001 From: Nick Walton Date: Fri, 5 Apr 2019 01:30:03 -0600 Subject: [PATCH] made a lot of progress --- .gitignore | 4 + README.md | 31 +++- __pycache__/dungeon_master.cpython-37.pyc | Bin 0 -> 1788 bytes __pycache__/generator.cpython-37.pyc | Bin 0 -> 2288 bytes __pycache__/utils.cpython-37.pyc | Bin 0 -> 1783 bytes download_model.py | 28 +++ generator.py | 65 +++++++ generator.pyc | Bin 0 -> 2688 bytes gpt2/CONTRIBUTORS.md | 17 ++ gpt2/DEVELOPERS.md | 85 +++++++++ gpt2/LICENSE | 21 +++ gpt2/README.md | 61 +++++++ gpt2/__init__.py | 0 gpt2/download_model.py | 28 +++ gpt2/src/__init__.py | 0 gpt2/src/__pycache__/__init__.cpython-37.pyc | Bin 0 -> 153 bytes gpt2/src/__pycache__/encoder.cpython-37.pyc | Bin 0 -> 4961 bytes gpt2/src/__pycache__/model.cpython-37.pyc | Bin 0 -> 6723 bytes gpt2/src/__pycache__/sample.cpython-37.pyc | Bin 0 -> 2618 bytes gpt2/src/encoder.py | 117 +++++++++++++ gpt2/src/model.py | 174 +++++++++++++++++++ gpt2/src/sample.py | 79 +++++++++ main.py | 43 ++++- requirements.txt | 6 +- static/script.js | 26 +-- static/style.css | 4 + story_prompts.yaml | 7 + utils.py | 79 +++++++++ 28 files changed, 857 insertions(+), 18 deletions(-) create mode 100644 .gitignore create mode 100644 __pycache__/dungeon_master.cpython-37.pyc create mode 100644 __pycache__/generator.cpython-37.pyc create mode 100644 __pycache__/utils.cpython-37.pyc create mode 100644 download_model.py create mode 100644 generator.py create mode 100644 generator.pyc create mode 100644 gpt2/CONTRIBUTORS.md create mode 100644 gpt2/DEVELOPERS.md create mode 100644 gpt2/LICENSE create mode 100644 gpt2/README.md create mode 100644 gpt2/__init__.py create mode 100644 gpt2/download_model.py create mode 100644 gpt2/src/__init__.py create mode 100644 gpt2/src/__pycache__/__init__.cpython-37.pyc create mode 100644 gpt2/src/__pycache__/encoder.cpython-37.pyc create mode 100644 gpt2/src/__pycache__/model.cpython-37.pyc create mode 100644 gpt2/src/__pycache__/sample.cpython-37.pyc create mode 100644 gpt2/src/encoder.py create mode 100644 gpt2/src/model.py create mode 100644 gpt2/src/sample.py create mode 100644 story_prompts.yaml create mode 100644 utils.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9661db6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +__pychache__/* +gpt2/__pycache__/* +gpt2/models/* +regex diff --git a/README.md b/README.md index 92d7d3b..66b722e 100644 --- a/README.md +++ b/README.md @@ -1 +1,30 @@ -# DM-Server \ No newline at end of file +# AI-DungeonMaster + +### AI Dungeon Master is an automatically generated text adventure that uses the GPT-2 model (smaller version) to generate completely AI made text adventures. + +## Installation +``` +git clone http://github.com/nickwalton/AI-DungeonMaster +pip install regex +pip install numpy +pip install tensorflow +pip install tqdm +``` + +## (Optional) tensorflow-gpu +For faster performance you can instead install tensorflow-gpu, but you'll also need up to date nvidia graphics drivers and cuda. +``` +pip install tensorflow-gpu==1.12 +``` + +## Download the GPT-2 Model +``` +cd AI-DungeonMaster/gpt2 +python download_model.py 117M +``` + +## Run the Game +``` +cd .. +python dungeon_master.py +``` diff --git a/__pycache__/dungeon_master.cpython-37.pyc b/__pycache__/dungeon_master.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..81fbde03aa9d346fa597b8548cc7521ac0e20510 GIT binary patch literal 1788 zcma)6Pj4GV6rb7kI<{jwv6IwElQz>*AO;$zE#iPE&JZv`r1p_`Mxh@z39+|9}tPsrd!%olSbPZcU>hLOxyz~C;Gtc#7A^>UTpgq!oXu;yE5#B_@+_P69a@;!mK zXM~cV2%GQ@RAzL8aE8^gc$Vk9*8E*y*!504rJZy}aZQ6io0r&xy-(^_Uzt6rQ(fLy zp`1K|0Hli&T8gpdK)UTN$gj~r-@})4EZu(R)ec5!GTkrSf5V5dHw50F{?r7&9rl2! zkUeHrgPU+C z!5>epI@5Gd(>t2p)%2dG(RBNNqj&ZicN%va_v&m~eH@&)z9-V|vGZM?Z4V0&Cp?qZp&z!ph*7S@95U?n zm0nCbNL&?@JXx32&rAPStCtZS>0%SSd=5$V+C|#b5hnM^7g9mzAsF_|HwQeM*tCs} z@KStpt)!WVmr#fxNGsBrunz&xD;TSm*-!0^q=ytsrlwIROy@Px85ny?+h&~0#+S61 zG;G>8SC(kM5_tpfEPnmH*XZB}*a*CKcjWpi3>wFtYKY$L2;>RKM!KM_o*Utw@AfA; z_en1lLmxh+ND>|4t4ND9M|0IxD@U_dnHFu-tekBbYwXM5nZ;khF4D41I-42{;cP9--D4BSHM{CLEg5wANg40@X z+CjVGu(b0fxl6dk?IXhNLl$&7-6lQf1gw&+9yRps7|G>0b*m2?LC}?e@ea4Sb40-* zmp6_`U~`W*VRyLCTd=#l4NAMFyRCD%e^+EeMnIi>21@?=<98f?e{^yMzG7!#sSSG* z=53hjH&{5CIh@X1&Ss60mLw#a&RN+wM%vQ$+&LyQPrJG?_U6s9!L4I9jID%HrXjKz zl*ynq5;|Ob7z+sFR91o&E{4%G)!|aFofjfAELX-ZBG7M-^CSz_@^6Kd2^Zl|=97>o zv4#_H$=GQgal`a5XccJ`i=8}0gHDp^_iji8uwhvdxH8IkK0&_(4^|YoQ*%OO7*|D; zA{B5@?ZDidf|tU$`BWEE9XMJ>;D@svfg{10G}1!pFy0aIZUGMJpdo>gOVMkijdUmx zArc`Hw6vHM2&t(QpeQfGU3mddTX^bMi3l-R=>fygVc@9Bj19{5uSC8I>?cYNtWm^?7~%b85Y89ia(dNsYlo8CR?X% z>Q_9Q`j!u02OG~9K!2$vW~c#%4bz2*b*8?71%WiDB>?vaq}kYl6~H%kz9&Pp9Owd?JquH< z!ZHGb_q`c?Onzp2_I917Dpx&bSpS-#AvB2Y0-vGIcSWYEbNL!vf8yUv6Q$#PQrxs&Zrlap5emkV(@bsx zRfEz2_>F|Ipp1;m1(r$AmY1q)1z^0;fd$wzHWpVM6_sz`b#&f%OSiBqDKtQ;=e$f; z+3J5Eaw&cKkeErFw_z&OSduxxXPhxjOXy6nvwANXJOth9SrXF}oQtPA#A-;BYy^b@ z)enUdbP)afp%hgWf-r_6dw9cn0GZpZGmlWNBUoSh6xKH@q3dw0unGu3)1w|cc=ILC z@$9V_Bf){t#92l4ArK=nvmRY5*&TBK%FHeSm>6YgZvezLpkqU<4#et|7WC?>r|$Xp zNCmy85qF1)gkoQYYTT%R9>sg^Gck6eSSNV~UPV%?V717VN*<<obT%iyav$Xec$~ z#cXVxW@Di!FHoQQ0D`EW7wXriYmk&KJ9z75NqPPnL#s zmcYrTlVV?P0BwALi^}CN%^%A1c-Y1NoW7EAziNcW0#dHv$;#n$wMs(%2yDu}H?Rw1v}zwORXd;kCd literal 0 HcmV?d00001 diff --git a/__pycache__/utils.cpython-37.pyc b/__pycache__/utils.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..66d02d02d487a02d24384935e852c30167e64e3e GIT binary patch literal 1783 zcmb_cPmkL~6rUMS60hT=>58gwGrLk(DeC4%r3xY1LIoTmq#g=^%2*!nt`)~l$CKSn zl$=_=2Nfqi1z&(qkSnMC3OOKtZ@kHdg+)j(*1Y#--t)Zqy+8A$)$$m|>F+;%_iLT8 z-)ONO0>USlB@x92OmQXNumM+&lHfwsR2|$=4dsGMwWB=nnrbQ^yslcR4c<_(iA#P%Am-z=_9*CyL;1O5}c)3wg+lX?0WA?dt3yj*ir@6 zMs?!jEW5HCPx9DIB9j(*by8jgts}%CP9=>gMCmHJg_u8C_OLc zhyx7=vxfN;v%CjFfjJfne*W&9f688V7GlnRWOJdMw_?FwwO_C~LkMJlAde>Ta3G(7 z&g6ZJE?+h-!_sw@(j@0*;8(W@&kC)|r6l$<(-MwW2fdSGl=Sj69-c*+De~TNYIqI(mQX64~{y6jw@G1kRVl&5Ceq071;jJw?99ifqLw!uW$$b-f7IRrvLxCnuj zoh@0a+GfA58XMVFJ0u%EXRkT^2h?7FCcX$}l2STz&JvIpAo3ep*Md=+C$oA0tu9x5 zf62N+(`D@Sx?EEgTI>~}xG$SgmW7v5yNivo4Z^s;{)8*^4tD;8jt;WuC z-iHsey}?yGim7YV?rP;{98>SUh$WRDW&p;(E3#DYuq2euA~}eVv|OjPEEPp zgxSGj6NT@wsG{(eFHmwQSOH1Q#heeB{*W4QD8ZR>Aj`Y#2k{9T}Zx}RRSqYNu%BIr zZTqy=*SBz@rX=XwM0P=dv!=I!HnZpoXU8u70p^`}VnU;%G)wd2aEco2G`a^=R7d;NA#YJYXxkN^Jd`+%0e8vehF*ZhJd z#G@!78m?$XLsjt|8rCYhPQ$f|Zcw~Vag&D4iqjHKn}+R*vmu-g4LibdDCyESA=E)j zot_b05`8zk!uAKf27HPB!SAG}Kw4hjv{$eWY*t)+p;KM>pjJ`TA^Hrjc^`|0|CP_7 zLoo8JMne!{heKFngTp$74I$RZ9rV_5GJ1ez{KxP7`}32ihh4CSrGvMP_j9~v3*I16 z3plQ5(IA*utkYc4oXAsT9g1r-U#H8GQzyGdaf9PqG|8@$ZBmT+tv2^GMvQ*&D#{;kh6$xgY7GLGUzpt znUjd?WVW!3b9>yMW}!|@|LEw0`-U?($^F8gn#0&+De|ylST1*>)3KchJAha}wU#q} z>f2!AndnE|yNRu>V>!uEErij=$O)YWuvOR%NXOcG)xL&3XcT}*ys?|0LOt?liS?HL zh^j2tDJn;l8QJGPoMB^e7Ntlo1dnx5M4|RZMK<-qD6plRgW(U8%nwC_9f==#;s<(? zCF~d5hnjbfUH($ON^=Rj@Y67xiUOl`DE=8lQ1U(Dae9nD%@bXUg@ovQhS;>I$!0d6 zS+QdaAEwyiz=z9r8&u+3ZLAkeba0k)K$5irysXeYuFcYeWaM&TTuz)sVf8fUUYixV z)Sl(unR~$BunDP=WY*)1xtu}i){%T|!~>2Qb}hFP$zqN{^(Wa>_tPjid*UZHOZ(%< z_CNjd?R&Fyth4mKZ>%o*ZRT+;Tf|=wN}?D{VDt4z)EpfE*J9-8$&i;mV0^VI2Vi z0xjvJ2psA$-{n@2LYK&vB3Uj{F-u)(46X)1Gu9=GX;@rwi zUG|%2vooCe~#9*rM z#J5hJ_5r4Spow!MO7yD8NFoKr5}gFIEGx(#RNTC3Gs zFLm<;1>)`xE!B&2!NWb7$w;gmysha%J=D^DT2fD7Gs=X=kk3gcfv|u y-V^S17E~9p94rS%;Wk;q_?p=$G2-dV30hM9ahcpZt3Lz)Yk~F-`g}*VYySdTr#vD6 literal 0 HcmV?d00001 diff --git a/gpt2/CONTRIBUTORS.md b/gpt2/CONTRIBUTORS.md new file mode 100644 index 0000000..eab7132 --- /dev/null +++ b/gpt2/CONTRIBUTORS.md @@ -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).** diff --git a/gpt2/DEVELOPERS.md b/gpt2/DEVELOPERS.md new file mode 100644 index 0000000..078999b --- /dev/null +++ b/gpt2/DEVELOPERS.md @@ -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 +``` diff --git a/gpt2/LICENSE b/gpt2/LICENSE new file mode 100644 index 0000000..cb36e12 --- /dev/null +++ b/gpt2/LICENSE @@ -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. diff --git a/gpt2/README.md b/gpt2/README.md new file mode 100644 index 0000000..c1be039 --- /dev/null +++ b/gpt2/README.md @@ -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) diff --git a/gpt2/__init__.py b/gpt2/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gpt2/download_model.py b/gpt2/download_model.py new file mode 100644 index 0000000..30ba84a --- /dev/null +++ b/gpt2/download_model.py @@ -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) diff --git a/gpt2/src/__init__.py b/gpt2/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gpt2/src/__pycache__/__init__.cpython-37.pyc b/gpt2/src/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..11790e43a3e6740b5b9c8e20d3722eea84b95a21 GIT binary patch literal 153 zcmZ?b<>g`kg0g>$V?gv{5CH>>K!yVl7qb9~6oz01O-8?!3`HPe1o6vBKO;XkRX;B? zIlDYDrzAg5KRvTVKP6YUIJKxOwMajuG%r0hKQBHvvA6`tO)n@h(l0Jb){l?R%*!l^ ZkJl@xyv1RYo1apelWGSt`!f(T004r+Cer`_ literal 0 HcmV?d00001 diff --git a/gpt2/src/__pycache__/encoder.cpython-37.pyc b/gpt2/src/__pycache__/encoder.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee9bc1c84c59d2e2f7eb59bbcaf065b671ba29e5 GIT binary patch literal 4961 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%0DBOJY-1VQU%G7$FYE6Gg zTlo=4I#^d)p{j{J*54xmRkPkEau)+PT;tMh3DP;*6A`lO9}^*OrBSQyVd1SfdPn{g zlW1*23@#i*Z-Z}$VSf-l5}W-b2yt%<5hJ2uu!(DED29Qi$@m57S$_!R;h8`4!H|9i pcJMQ>= 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 Typer.text.length) { clearInterval(addTextTimer); + var choice = prompt("What's your choice?"); + requestStory(prompt); // Here we probably want to call the request story function with the choice they made } } +function start(){ + Typer.speed=2; + + Typer.init(); + startTyping("Adventurer@DungeonDream:~$ Hello Adventurer and welcome to my dungeon!"); +} + addTextTimer = null; - -Typer.speed=2; - -Typer.init(); -startTyping(Typer, "Adventurer@DungeonDream:~$ Hello Adventurer and welcome to my dungeon!"); +start(); diff --git a/static/style.css b/static/style.css index 3501ede..e0e61f9 100644 --- a/static/style.css +++ b/static/style.css @@ -37,6 +37,10 @@ a { color: #888888 } +#SI{ + background-color:transparent; +} + @keyframes change { 0% { color: #0f0; } 50% { color: #0f0; } diff --git a/story_prompts.yaml b/story_prompts.yaml new file mode 100644 index 0000000..c2c0493 --- /dev/null +++ b/story_prompts.yaml @@ -0,0 +1,7 @@ +dungeon: "You enter a dungeon with your trusty sword and shield. You are searching for the evil necromancer who killed your family. You believe he is at the lowest level of the dungeon. You know you will encounter undead zombies and skeletons. You enter the first door and see" + +starship: "You're the captain of the Magnetar, a giant starship and the last hope of defending earth from the swarms of alien spaceships that are now hurtling towards the planet. You only have a small amount of laser charges left. You must defend earth at all costs." + +bees: "Your entire life, you've been told you're deathly allergic to bees. You've always had people protecting you from them, be it your mother or a hired hand. Today, one slips through and lands on your shoulder. You hear a tiny voice say 'Your Majesty, what are your orders?'" + +drug: "When you’re 28, science discovers a drug that stops all effects of aging, creating immortality. Your government decides to give the drug to all citizens under 26, but you and the rest of the “Lost Generations” are deemed too high-risk. When you’re 85, the side effects are finally discovered." diff --git a/utils.py b/utils.py new file mode 100644 index 0000000..aeb731c --- /dev/null +++ b/utils.py @@ -0,0 +1,79 @@ + +""" +replacements: + + stories only: + "you will" with "you" + "go to" with "you go to" + + All + "punctuation with no space. add a space + "remove any # and - and _'s + +""" + + +def remove_profanity(text): + remove_words = ["fuck", "Fuck"] + for word in remove_words: + text = text.replace(word, "****") + + return text + +def all_replace(text): + text = text.replace("I ","you ") + text = text.replace("we ","you ") + text = text.replace("We ","You ") + text = text.replace(" mine"," yours") + text = text.replace("#","") + + text = remove_profanity(text) + + return text + + +def action_replace(text): + return all_replace(text) + + +def story_replace(text): + return all_replace(text) + + +def text_replace(text): +# Replace certain words + text = text.replace("I ","you ") + text = text.replace("we ","you ") + text = text.replace("We ","You ") + text = text.replace(" mine"," yours") + text = text.replace("kill you", "hurt you") + text = text.replace("[","") + text = text.replace("]","") + return text + + +def first_sentence(text): + first_period = text.find('.') + first_exclamation = text.find('!') + + if first_exclamation < first_period and first_exclamation > 0: + text = text[0:first_exclamation+1] + elif first_period > 0: + text = text[0:first_period+1] + else: + return text[0:20] + + return text + + +def cut_trailing_sentence(text): + last_period = text.rfind('.') + last_exclamation = text.rfind('!') + + if last_exclamation > last_period: + text = text[0:last_exclamation+1] + elif last_period > 0: + text = text[0:last_period+1] + + return text +