5 Commits

45 changed files with 199 additions and 479 deletions

View File

@ -1 +1 @@
FLASK_APP=apicalls.py FLASK_APP=run.py

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1 +0,0 @@
from application import app

View File

@ -1,7 +0,0 @@
from flask import Flask
from config import Config
app = Flask(__name__)
app.config.from_object(Config)
import application.routes

View File

@ -1,106 +0,0 @@
"""
Flask app that uses gpt4all to generate random song writing prompt.
"""
import os
import string
import random
import requests
from flask import (
render_template,
session,
request,
)
from gpt4all import GPT4All
from datetime import datetime, timezone, timedelta
from pathlib import Path
from application import app
from werkzeug.middleware.profiler import ProfilerMiddleware
app.wsgi_app = ProfilerMiddleware(app.wsgi_app, profile_dir="/root/flask-profiler/")
app.config.update(SECRET_KEY=os.urandom(24))
app.permanent_session_lifetime = timedelta(minutes=30)
MODEL = GPT4All(
model_name="gpt4all-falcon-q4_0.gguf",
# model_path=(Path.home() / ".cache" / "gpt4all"),
allow_download=False,
)
TIME_SIGNATURES = ["2/4", "3/4", "4/4", "2/2", "6/8", "9/8", "12/8"]
# Need to decide between manually entering this list or using ascii_letters, below
KEYS = ["A", "B", "C", "D", "E", "F", "G"]
SIGN = ["b", "#"]
# Option 2
MINOR = string.ascii_letters[0:7]
MAJOR = string.ascii_letters[26:33]
# and then use this:
# output = random.choice(KEYS)+random.choice(SIGN)
@app.route("/")
def main_prompt():
"""
Main function that loads the prompt
"""
return render_template("index.html", title="Home")
@app.route("/all", methods=["GET", "POST"])
def prompt_all():
print("Running Prompt_all func")
WORD_PROMPT = str(requests.get("https://random-word-api.herokuapp.com/word").text)[
2:-2
]
SYSTEM_TEMPLATE = 'A single sentence based on a word.'
PROMPT_TEMPLATE = '### Instruction: {0} \n### Response: '
if request.method == "POST":
message = "Results are here"
session["output_key"] = random.choice(KEYS) + random.choice(SIGN)
session["output_signature"] = random.choice(TIME_SIGNATURES)
session["word_prompt"] = WORD_PROMPT
# with MODEL.chat_session(SYSTEM_TEMPLATE, PROMPT_TEMPLATE):
# response = MODEL.generate(f"A single sentence about {WORD_PROMPT}.", temp=0.7)
# session["output_theme"] = str(response.splitlines()[0])
response = MODEL.generate(f"Tell me about {WORD_PROMPT}.", temp=0.7, callback=stop_on_token_callback)
session["output_theme"] = response
# numresp = len(response)- 1
# if numresp <= 1:
# session["output_theme"] = str(response)
# randresp = random.randrange(0, numresp)
# session["output_theme"] = response
return render_template("single-button.html", title="Results", message=message)
return render_template("single-button.html", title="Single Option")
def stop_on_token_callback(token_id, token_string):
if '.' in token_string:
return False
else:
return True
@app.route("/")
def prompt_instrument():
pass
@app.route("/")
def prompt_key():
pass
@app.route("/")
def prompt_timesig():
pass
@app.route("/")
def prompt_influence():
pass
response = MODEL.generate("The writing prompt is about the weather:", temp=0)
session["list_response"] = response.splitlines()
if __name__ == "__main__":
app.run(debug=True)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

View File

@ -1,180 +0,0 @@
/* 1.0 - Foundational Styling */
:root {
--primary: #66C92D;
--text-light: #FFFFFF;
--text-dark: #101314;
--background: #667E8A;
--background-light: #E5E9EB;
height: 100%;
}
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: inherit;
}
body {
background: linear-gradient(
15deg, #ff97c0, #ffa964, #ffff8e, #00ffc8, #d26aff
);
background-size: 700% 550%;
animation: gradient 7s ease-in-out infinite;
color: var(--text-dark);
font-family: 'Space Grotesk', sans-serif;
background-color: var(--background-light);
box-sizing: border-box;
text-align: center;
width: 100%;
}
@keyframes gradient {
0% {
background-position: 0% 79%;
}
50% {
background-position: 100% 22%;
}
100% {
background-position: 0% 79%;
}
}
html {
display: flex;
justify-content: center;
}
header {
height: 10%;
}
.prompt-button {
background-color: rgba(255, 255, 255, 0.5);
border-radius: 4px;
margin-right: 4px;
border: 1px solid black;
white-space: nowrap;
cursor: pointer;
font-size: 14px;
line-height: 16px;
padding: 8px 16px 8px 12px;
width: 300px
}
.prompt {
padding: 5px;
}
.results-container {
display: inline-block;
width: 60%;
text-align: center;
}
/* MODAL POPUP */
.first-time-user-popup {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1000;
display: flex;
padding: 1em;
background-color: rgba(0, 0, 0, 0.75);
transition: 0.25s ease-out;
}
.first-time-user-popup.is-active {
visibility: visible;
opacity: 1;
pointer-events: auto;
}
.first-time-user-popup-container {
width: 100%;
max-width: 600px;
margin: auto;
transform: translateY(-1em) scale(0.95);
background-color: white;
transition: transform 0.25s ease-out;
border-radius: 8px;
}
.first-time-user-popup.is-active .first-time-user-popup-container {
transform: translateY(0) scale(1);
}
.modal-headline {
font-size: 20px;
line-height: normal;
font-weight: 500;
margin-bottom: 32px;
text-align: center;
color: #F7492D;
}
.modal-links {
display: block;
}
.modal-x-out {
float: left;
border: none;
background: transparent;
}
.modal-links a {
border: 2px solid #3c228a;
background: #F7492D;
padding: 8px 16px;
text-align: center;
width: calc(50% - 8px);
margin: 0 8px;
border-radius: 30px;
color: #fff;
text-decoration: none;
font-weight: 700;
transition: all 0.2s;
}
.modal-links a.secondary {
background: transparent;
color: #3c228a;
}
.modal-links a:hover {
border: 2px solid #13014a;
background: #13014a;
}
.modal-links a.secondary:hover {
border: 2px solid #13014a;
background: #ebe8f3;
color: #13014a;
}
.first-time-user-popup-content {
padding: 32px 16px;
}
@media (min-width: 768px) {
.first-time-user-popup-content {
padding: 32px;
}
.modal-headline {
font-size: 24px;
}
.modal-links a {
min-height: 40px;
line-height: 40px;
}
}
.loading {
url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"><radialGradient id="a12" cx=".66" fx=".66" cy=".3125" fy=".3125" gradientTransform="scale(1.5)"><stop offset="0" stop-color="%23FF156D"></stop><stop offset=".3" stop-color="%23FF156D" stop-opacity=".9"></stop><stop offset=".6" stop-color="%23FF156D" stop-opacity=".6"></stop><stop offset=".8" stop-color="%23FF156D" stop-opacity=".3"></stop><stop offset="1" stop-color="%23FF156D" stop-opacity="0"></stop></radialGradient><circle transform-origin="center" fill="none" stroke="url(%23a12)" stroke-width="15" stroke-linecap="round" stroke-dasharray="200 1000" stroke-dashoffset="0" cx="100" cy="100" r="70"><animateTransform type="rotate" attributeName="transform" calcMode="spline" dur="2" values="360;0" keyTimes="0;1" keySplines="0 0 1 1" repeatCount="indefinite"></animateTransform></circle><circle transform-origin="center" fill="none" opacity=".2" stroke="%23FF156D" stroke-width="15" stroke-linecap="round" cx="100" cy="100" r="70"></circle></svg>')
}

View File

@ -1 +0,0 @@
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'><radialGradient id='a12' cx='.66' fx='.66' cy='.3125' fy='.3125' gradientTransform='scale(1.5)'><stop offset='0' stop-color='#FF156D'></stop><stop offset='.3' stop-color='#FF156D' stop-opacity='.9'></stop><stop offset='.6' stop-color='#FF156D' stop-opacity='.6'></stop><stop offset='.8' stop-color='#FF156D' stop-opacity='.3'></stop><stop offset='1' stop-color='#FF156D' stop-opacity='0'></stop></radialGradient><circle transform-origin='center' fill='none' stroke='url(#a12)' stroke-width='15' stroke-linecap='round' stroke-dasharray='200 1000' stroke-dashoffset='0' cx='100' cy='100' r='70'><animateTransform type='rotate' attributeName='transform' calcMode='spline' dur='2' values='360;0' keyTimes='0;1' keySplines='0 0 1 1' repeatCount='indefinite'></animateTransform></circle><circle transform-origin='center' fill='none' opacity='.2' stroke='#FF156D' stroke-width='15' stroke-linecap='round' cx='100' cy='100' r='70'></circle></svg>

View File

@ -1,20 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="shortcut icon" href="{{ url_for('static', filename='np-favicon.png') }}">
<title>Song Writing Prompt Machine</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap"
rel="stylesheet">
<link rel="stylesheet" href="{{ url_for('static', filename="styles.css") }}" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
</head>
<body>
{% block content %} {% endblock %}
</body>
</html>

View File

@ -1,3 +0,0 @@
<!DOCTYPE html>
<header class="header">
</header>

View File

@ -1,44 +0,0 @@
<!DOCTYPE html>
{% include 'head.html' %}
{% include 'header.html' %}
{% block content %}
<div class="main-container">
<h1> Get Inspired with a Song Writing Prompt! </h1>
<h3> Please select from below </h3>
<h2> {{ session.list_response }} </strong></h4>
<div class="prompt-questions">
<form class="prompt"
action="{{ url_for("prompt_influence")}}"
method="post">
<input id="fields" type="keywords" name="keyword-influence">
<input class="prompt-button"
id="fields" type="submit" value="Submit Prompt Only">
</form>
<form class="prompt"
action="{{ url_for("prompt_key")}}"
method="post">
<input class="prompt-button"
id="fields" type="submit" value="Submit Prompt Key Only">
</form>
<form class="prompt"
action="{{ url_for("prompt_timesig")}}"
method="post">
<input class="prompt-button"
id="fields" type="submit" value="Submit Prompt Time Signature Only">
</form>
<form class="prompt"
action="{{ url_for("prompt_instrument")}}"
method="post">
<input class="prompt-button"
id="fields" type="submit" value="Submit Prompt instrument Only">
</form>
<form class="prompt"
action="{{ url_for("prompt_all")}}"
method="post">
<input class="prompt-button"
id="fields" type="submit" value="Submit Prompt all Only">
</form>
</div>
</div>
{% endblock %}

View File

@ -1,36 +0,0 @@
<div
class="first-time-user-popup"
id="firstTimeUsers"
role="dialog"
aria-labelledby="dialogTitle"
aria-describedby="dialogContent"
aria-hidden="true">
<section class="first-time-user-popup-container">
<div id="dialogContent" class="first-time-user-popup-content">
<input
type="button"
class="modal-x-out"
value=&#10006
onclick="document.getElementById('firstTimeUsers').remove();">
<div class="modal-headline">Here you go! Now go write a song!</div>
<div class="modal-links">
<h2> Key: </h2>
<h3> {{ session.output_key }} </h3>
<p></p>
<h2> Time Signature: </h2>
<h3> {{ session.output_signature }} </h3>
<p></p>
<h2> Theme: </h2>
<h3> {{ session.output_theme }} </h3>
<p></p>
</div>
</div>
</section>
</div>
<script>
var elements = $('#firstTimeUsers');
if (elements.length === 1) {
$('#loading').hide();
}
</script>

View File

@ -1,18 +0,0 @@
<!DOCTYPE html>
{% include 'head.html' %}
{% include 'header.html' %}
{% block content %}
<div class="main-container" style="padding-bottom:10px;">
<h1> Here are your results! </h1>
<p></p>
<div class="results-container">
<h2> Key: </h2>
<h3> {{ session.output_key }} </h3>
<h2> Time Signature: </h2>
<h3> {{ session.output_signature }} </h3>
<h2> Theme: </h2>
<h3> {{ session.output_theme }} </h3>
</div>
</div>
{% endblock %}

View File

@ -1,26 +0,0 @@
<!DOCTYPE html>
{% include 'head.html' %}
{% include 'header.html' %}
{% block content %}
<div class="main-container">
{% if message %}
{% include 'modal_results.html' %}
{% endif %}
<h1> Get Inspired with a Song Writing Prompt! </h1>
<h2> {{ session.list_response }} </strong></h4>
<div class="prompt-questions">
<form class="prompt"
action="{{ url_for("prompt_all")}}"
method="post">
<input class="prompt-button"
id="fields" type="submit" value="Click for Inspiration"
onclick="$('#loading').show();">
</form>
<div id="loading" style="display:none;">
<img src={{ url_for('static', filename='tube-spinner.svg') }} width="200px">
Please be patient as we load up on inspiration!
</div>
</div>
</div>
{% endblock %}

View File

@ -1,4 +0,0 @@
import os
class Config(object):
SECRET_KEY = os.environ.get("SONGPROMPT") or "song-prompt"

BIN
dump.rdb Normal file

Binary file not shown.

View File

@ -1,18 +0,0 @@
from gpt4all import GPT4All
import requests
from pathlib import Path
MODEL = GPT4All(
model_name="gpt4all-falcon-q4_0.gguf",
# model_path=(Path.home() / ".cache" / "gpt4all"),
# /root/.pyenv/versions/gpt-song-prompt/lib/python3.10/site-packages/gpt4all
allow_download=True,
)
WORD_PROMPT = str(requests.get("https://random-word-api.herokuapp.com/word").text)[2:-2]
SYSTEM_TEMPLATE = 'A single sentence based on a word.'
PROMPT_TEMPLATE = '### Instruction: {0} \n### Response: '
with MODEL.chat_session(SYSTEM_TEMPLATE, PROMPT_TEMPLATE):
response = MODEL.generate(f"A single sentence about {WORD_PROMPT}.", temp=0.7)
print(WORD_PROMPT)
resp = str(response.splitlines()[0])
print(resp)

32
gpt_test_loader.py Normal file
View File

@ -0,0 +1,32 @@
from gpt4all import GPT4All
import requests
from pathlib import Path
def prompt():
MODEL = GPT4All(
model_name="gpt4all-falcon-q4_0.gguf",
# model_path=(Path.home() / ".cache" / "gpt4all"),
# /root/.pyenv/versions/gpt-song-prompt/lib/python3.10/site-packages/gpt4all
allow_download=False,
)
WORD_PROMPT = str(requests.get("https://random-word-api.herokuapp.com/word").text)[
2:-2
]
SYSTEM_TEMPLATE = "A creative response about a word."
PROMPT_TEMPLATE = "### Instruction: {0} \n### Response: "
response = MODEL.generate(
f"Tell me something interesting about {WORD_PROMPT}.",
temp=0.7,
callback=stop_on_token_callback,
)
print(response)
def stop_on_token_callback(token_id, token_string):
if "." in token_string:
return False
return True
if __name__ == "__main__":
prompt()

0
instance/db.sqlite3 Normal file
View File

20
project/__init__.py Normal file
View File

@ -0,0 +1,20 @@
from flask import Flask
from .extensions import db
from .views import main
from .utils import make_celery
def create_app():
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///db.sqlite3"
app.config["SECRET_KEY"] = "super-secret-key"
app.config["CELERY_CONFIG"] = {"broker_url": "redis://localhost"}
db.init_app(app)
app.register_blueprint(main)
celery = make_celery(app)
celery.set_default()
return app, celery

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

3
project/extensions.py Normal file
View File

@ -0,0 +1,3 @@
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()

8
project/models.py Normal file
View File

@ -0,0 +1,8 @@
from datetime import datetime
from .extensions import db
class Result(db.Model):
id = db.Column(db.Integer, primary_key=True)
text = db.Column(db.String(100), nullable=False)
date_created = db.Column(db.DateTime, default=datetime.utcnow)

64
project/tasks.py Normal file
View File

@ -0,0 +1,64 @@
from celery import shared_task
from time import sleep
from redbeat import RedBeatSchedulerEntry
from sqlalchemy import create_engine
from sqlalchemy.sql.expression import func, select, insert
from sqlalchemy.ext.automap import automap_base
from gpt4all import GPT4All
from sqlalchemy.orm import Session
from celery import current_app as celery_app
from .extensions import db
from .models import Result
engine = create_engine("sqlite:///words_prompts.db", pool_pre_ping=True)
Base = automap_base()
Base.prepare(engine, reflect=True)
Words = Base.classes.words
Themes = Base.classes.themes
MODEL = GPT4All(
model_name="gpt4all-falcon-q4_0.gguf",
# model_path=(Path.home() / ".cache" / "gpt4all"),
allow_download=False,
)
@shared_task
def my_task(text, schedule_name):
while True:
with Session(engine) as word_session:
random_word = word_session.query(Words.words)
random_word = random_word.order_by(func.random()).first()
random_word = str(random_word)[4:-4]
# SYSTEM_TEMPLATE = "A single sentence based on a word."
# PROMPT_TEMPLATE = "### Instruction: {0} \n### Response: "
response = MODEL.generate(
f"Give me a writing prompt about {random_word}.",
temp=0.7,
callback=stop_on_token_callback,
)
word_session.execute(insert(Themes).values(themes=response))
word_session.commit()
try:
entry = RedBeatSchedulerEntry.from_key(
"redbeat:" + schedule_name, app=celery_app
)
except KeyError:
entry = None
if entry:
entry.delete()
def stop_on_token_callback(token_id, token_string):
"""
Function to limit return length of the
gpt4all response. Period indicates a sentence.
"""
if "." in token_string:
return False
return True

13
project/utils.py Normal file
View File

@ -0,0 +1,13 @@
from celery import Celery
def make_celery(app):
celery = Celery(app.import_name)
celery.conf.update(app.config["CELERY_CONFIG"])
class ContextTask(celery.Task):
def __call__(self, *args, **kwargs):
with app.app_context():
return self.run(*args, **kwargs)
celery.Task = ContextTask
return celery

29
project/views.py Normal file
View File

@ -0,0 +1,29 @@
from flask import Blueprint
from redbeat import RedBeatSchedulerEntry
from redbeat.schedules import rrule
from datetime import datetime
from celery import current_app as celery_app
from uuid import uuid4
from .tasks import my_task
main = Blueprint("main", __name__)
@main.route("/", methods=["GET"])
def index():
# my_task.delay("Hello World!")
schedule_name = str(uuid4())
dt = datetime.utcnow()
interval = rrule(freq="MINUTELY", dtstart=dt)
entry = RedBeatSchedulerEntry(
schedule_name,
"project.tasks.my_task",
interval,
args=["From the scheduler"],
kwargs={"schedule_name": schedule_name},
app=celery_app,
)
entry.save()
return "Created the schedule!"

View File

@ -1,18 +1,29 @@
blinker==1.7.0 amqp==5.1.1
certifi==2023.11.17 async-timeout==4.0.3
charset-normalizer==3.3.2 billiard==4.1.0
blinker==1.6.2
celery==5.3.4
celery-redbeat==2.1.1
click==8.1.7 click==8.1.7
Flask==3.0.0 click-didyoumean==0.3.0
gevent==23.9.1 click-plugins==1.1.1
gpt4all==2.0.2 click-repl==0.3.0
greenlet==3.0.1 Flask==2.3.3
idna==3.6 Flask-SQLAlchemy==3.1.1
greenlet==2.0.2
itsdangerous==2.1.2 itsdangerous==2.1.2
Jinja2==3.1.2 Jinja2==3.1.2
kombu==5.3.2
MarkupSafe==2.1.3 MarkupSafe==2.1.3
requests==2.31.0 prompt-toolkit==3.0.39
tqdm==4.66.1 python-dateutil==2.8.2
urllib3==2.1.0 redis==5.0.0
Werkzeug==3.0.1 six==1.16.0
zope.event==5.0 SQLAlchemy==2.0.21
zope.interface==6.1 tenacity==8.2.3
typing_extensions==4.8.0
tzdata==2023.3
vine==5.0.0
wcwidth==0.2.6
Werkzeug==2.3.7
gpt4all==2.0.2

4
run.py Normal file
View File

@ -0,0 +1,4 @@
from project import create_app
app, celery = create_app()
app.app_context().push()

BIN
words_prompts.db Normal file

Binary file not shown.