Skip to content

Commit

Permalink
First
Browse files Browse the repository at this point in the history
  • Loading branch information
gptix committed Feb 2, 2020
1 parent b4eac0f commit 4208bef
Show file tree
Hide file tree
Showing 13 changed files with 920 additions and 0 deletions.
18 changes: 18 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]
flask = "*"
flask-sqlalchemy = "*"
python-decouple = "*"
scikit-learn = "*"
gunicorn = "*"
psycopg2-binary = "*"
psycopg2 = "*"

[requires]
python_version = "3.7"
373 changes: 373 additions & 0 deletions Pipfile.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: gunicorn -w 4 twittoff:APP -t 120
136 changes: 136 additions & 0 deletions tester-app/Untitled.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.datasets import load_iris"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.linear_model import LogisticRegression"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"X,y = load_iris(return_X_y=True)"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"# clf = LogisticRegression(random_state=0, solver='lbfgs', multi_class='multinomial').fit(X,y)"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"# dir(clf)"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([0, 0])"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"clf.predict(X[:2, :])"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"\n",
"def create_app():\n",
" \"\"\"Create and configure an instance of the Flask app..\"\"\"\n",
"\n",
" app = Flask(__name__)\n",
" app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite3'\n",
" DB.init.app(app) \n",
"\n",
" @app.route('/')\n",
" def index():\n",
" return 'Index Page'\n",
"\n",
" @app.route('/hello')\n",
" def hello():\n",
" return render_template('base.html', title='Eels for Hovercrafts', users=User.query.all())\n",
" \n",
" return app\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
3 changes: 3 additions & 0 deletions tester-app/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .app import create_app

APP = create_app()
61 changes: 61 additions & 0 deletions tester-app/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from decouple import config
from flask import Flask, render_template, request

from .models import DB, User
from .predict import predict_user
from .twitter import add_or_update_user, update_all_users


def create_app():
"""Create and configure an instance of the Flask application"""
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = config('DATABASE_URL')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
DB.init_app(app)

@app.route('/')
def root():
DB.create_all()
return render_template('base.html', title='Home', users=User.query.all())

@app.route('/user', methods=['POST'])
@app.route('/user/<name>', methods=['GET'])
def user(name=None, message=''):
name = name or request.values['user_name']
try:
if request.method == 'POST':
add_or_update_user(name)
message = "User {} successfully added!".format(name)
tweets = User.query.filter(User.name == name).one().tweets
except Exception as e:
message = "Error adding {}: {}".format(name, e)
tweets = []
return render_template('user.html', title=name, tweets=tweets, message=message)

@app.route('/compare', methods=['POST'])
def compare(message=''):
user1 = request.values['user1']
user2 = request.values['user2']
tweet_text = request.values['tweet_text']

if user1 == user2:
message = 'Cannot compare a user to themselves!'
else:
prediction = predict_user(user1, user2, tweet_text)
message = '"{}" is more likely to be said by {} than {}'.format(
request.values['tweet_text'], user1 if prediction else user2,
user2 if prediction else user1)
return render_template('prediction.html', title='Prediction', message=message)

@app.route('/reset')
def reset():
DB.drop_all()
DB.create_all()
return render_template('base.html', title='Reset database!')

@app.route('/update')
def update():
update_all_users()
return render_template('base.html', users=User.query.all(), title='All Tweets updated!')

return app
24 changes: 24 additions & 0 deletions tester-app/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from flask_sqlalchemy import SQLAlchemy

DB = SQLAlchemy()


class User(DB.Model):
id = DB.Column(DB.BigInteger, primary_key=True)
# id = DB.Column(DB.Integer, primary_key=True)
name = DB.Column(DB.String(20), nullable=False)
newest_tweet_id = DB.Column(DB.BigInteger)

def __repr__(self):
return '<User {}>'.format(self.name)


class Tweet(DB.Model):
id = DB.Column(DB.BigInteger, primary_key=True)
text = DB.Column(DB.Unicode(500), nullable=False)
embedding = DB.Column(DB.PickleType, nullable=False)
user_id = DB.Column(DB.BigInteger, DB.ForeignKey('user.id'), nullable=False)
user = DB.relationship("User", backref=DB.backref('tweets', lazy=True))

def __repr__(self):
return '<Tweet {}>'.format(self.text)
22 changes: 22 additions & 0 deletions tester-app/predict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Prediction of Users based on Tweet embeddings."""
import numpy as np
#from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from .models import User
from .twitter import BASILICA


def predict_user(user1_name, user2_name, tweet_text):
"""Determine and return which user is more likely to say a given Tweet."""

user1 = User.query.filter(User.name == user1_name).one()
user2 = User.query.filter(User.name == user2_name).one()
user1_embeddings = np.array([tweet.embedding for tweet in user1.tweets])
user2_embeddings = np.array([tweet.embedding for tweet in user2.tweets])
embeddings = np.vstack([user1_embeddings, user2_embeddings])
labels = np.concatenate([np.ones(len(user1.tweets)),
np.zeros(len(user2.tweets))])

knnc = KNeighborsClassifier(weights='distance', metric='cosine').fit(embeddings, labels)
tweet_embedding = BASILICA.embed_sentence(tweet_text, model='twitter')
return knnc.predict(np.array(tweet_embedding).reshape(1, -1))
58 changes: 58 additions & 0 deletions tester-app/templates/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<!DOCTYPE html>
<html>
<head>
<title>TwitOff - {{ title }}</title>
<link rel="stylesheet" href="https://unpkg.com/picnic"/>
</head>
<body>
<nav>
<a href="/" class="brand"><span>TwitOff!</span></a>

<div class="menu">
<a href="/update" class="button warning">Update Tweets</a>
</div>
</nav>

<article class="flex two" style="padding: 3em 1em;">
{% block content %}
<div>
<h1>{{ title }}</h1>

<p>Select two users to compare:</p>

<form action="/compare" method="post">

<select name="user1">
{% for user in users %}
<option value="{{ user.name }}">{{ user.name }}</option>
{% endfor %}
</select>

<select name="user2">
{% for user in users %}
<option value="{{ user.name }}">{{ user.name }}</option>
{% endfor %}
</select>

<input type="text" name="tweet_text" placeholder="Tweet text to predict">
<input type="submit" value="Compare Users">

</form>
</div>

<div>
<h2>Twitter Users</h2>
{% for user in users %}
<a href="/user/{{ user.name }}"><span class="stack">{{ user.name }}</span></a>
{% endfor %}
<form action="/user" method="post">
<input type="text" name="user_name" placeholder="User to add">
<input type="submit" value="Add User">
</form>
</div>

{% endblock %}
</article>

</body>
</html>
7 changes: 7 additions & 0 deletions tester-app/templates/prediction.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{% extends "base.html" %}
{% block content %}
<div id="prediction">
<h2>{{ title }}</h2>
<p>{{ message }}</p>
</div>
{% endblock %}
10 changes: 10 additions & 0 deletions tester-app/templates/user.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{% extends "base.html" %}
{% block content %}
<div id="user-info">
<h2>User: {{ title }}</h2>
<p>{{ message }}</p>
{% for tweet in tweets %}
<span class="stack"><li>{{ tweet.id }} - {{ tweet.text }}</li></span>
{% endfor %}
</div>
{% endblock %}
Loading

0 comments on commit 4208bef

Please sign in to comment.