├── .idea
├── .gitignore
├── ToDoFlask.iml
├── dataSources.xml
├── inspectionProfiles
│ ├── Project_Default.xml
│ └── profiles_settings.xml
├── misc.xml
├── modules.xml
├── ppt-api.iml
└── vcs.xml
├── README.md
├── __pycache__
├── app.cpython-310.pyc
├── chat.cpython-310.pyc
└── ppt.cpython-310.pyc
├── app.py
├── chat.py
├── instance
└── database.db
├── ppt.py
├── requirements.txt
└── templates
├── base.html
├── dashboard.html
├── home.html
├── login.html
└── register.html
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/ToDoFlask.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/dataSources.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | sqlite.xerial
6 | true
7 | org.sqlite.JDBC
8 | jdbc:sqlite:$PROJECT_DIR$/database.db
9 | $ProjectFileDir$
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/ppt-api.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PPT maker using ChatGPT
2 |
3 | ### EDIT:
4 | My free Open AI API token expired the first of this month when I had just started working on the app. As a result, I will not be working on this anymore for quite some time.
5 |
6 | ## Goal
7 |
8 | 1) To be able to generate a powerpoint presentation just from the prompt given.
9 | 2) Make a web application for easy access
10 |
11 | ## Current Status
12 |
13 | Lots of bugs to fix but made a start. Made a web application where you can give a prompt and generate (and download) a pptx file prepared from chat gpt's response.
14 |
15 | ## USAGE
16 |
17 | 1) Register
18 | 2) Login
19 | 3) navigate to /dashboard
20 | 4) Write your prompt. Don't forget to mention: `Write a ppt` in the starting.
21 | 5) Generate your ppt. Download starts automatically!
22 |
23 | ## Setup Instructions:
24 |
25 | 1) `git clone https://github.com/MSSRPRAD/ppt-api.git`
26 | 2) `cd ppt-api`
27 | 3) `virtualenv venv`
28 | 4) (from bash terminal) `source venv/bin/activate`
29 | 5) `pip install -r requirements.txt`
30 | 6) `python app.py`
31 |
32 | NOTE: You have to set your own OPENAI API KEY. Go to https://platform.openai.com/account/api-keys to generate one if you don't have one.
33 |
34 |
35 |
--------------------------------------------------------------------------------
/__pycache__/app.cpython-310.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MSSRPRAD/ppt-api/02ae2b7323de05a1472b518a09033981a9b87c64/__pycache__/app.cpython-310.pyc
--------------------------------------------------------------------------------
/__pycache__/chat.cpython-310.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MSSRPRAD/ppt-api/02ae2b7323de05a1472b518a09033981a9b87c64/__pycache__/chat.cpython-310.pyc
--------------------------------------------------------------------------------
/__pycache__/ppt.cpython-310.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MSSRPRAD/ppt-api/02ae2b7323de05a1472b518a09033981a9b87c64/__pycache__/ppt.cpython-310.pyc
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
1 | import string
2 | import sys
3 |
4 | from flask import Flask, render_template, redirect, url_for, flash, session, request, send_file
5 | from flask_sqlalchemy import SQLAlchemy
6 | from flask_login import UserMixin, login_required, login_user, LoginManager, current_user, logout_user
7 | import os
8 | from flask_bcrypt import Bcrypt
9 |
10 | import chat
11 | import ppt
12 |
13 | app = Flask(__name__)
14 |
15 | bcrypt = Bcrypt(app)
16 |
17 | basedir = os.path.abspath(os.path.dirname(__file__))
18 |
19 | # app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db'
20 | app.config['SQLALCHEMY_DATABASE_URI'] =\
21 | 'sqlite:///' + os.path.join(basedir, 'database.db')
22 |
23 | app.config['SECRET_KEY'] = "secretkey"
24 |
25 | db = SQLAlchemy(app)
26 |
27 | login_manager = LoginManager()
28 | login_manager.init_app(app)
29 | login_manager.login_view = 'login'
30 |
31 | class Error:
32 | message = string
33 |
34 | @login_manager.user_loader
35 | def load_user(user_id):
36 | return User.query.get(int(user_id))
37 |
38 | class User(db.Model, UserMixin):
39 | id = db.Column(db.Integer, primary_key=True)
40 | username = db.Column(db.String(20), nullable = False)
41 | password = db.Column(db.String(100), nullable = False)
42 | requests = db.relationship('Request', backref = 'user')
43 |
44 | class Request(db.Model):
45 | id = db.Column(db.Integer, primary_key=True)
46 | userId = db.Column(db.Integer, db.ForeignKey('user.id'))
47 | content = db.Column(db.String(5000), nullable = True)
48 |
49 | @app.route('/')
50 | def home():
51 | return render_template('home.html')
52 |
53 | @app.route('/login', methods = ['GET', 'POST'])
54 | def login():
55 | if current_user:
56 | session.clear()
57 | flash("If you try to open this page after logging in you will be logged out automatically!")
58 | logout_user()
59 | redirect(url_for('login'))
60 | if request.method == 'POST':
61 | username = request.form['username']
62 | password = request.form['password']
63 | user = User.query.filter_by(username=username).first()
64 | if user:
65 | if bcrypt.check_password_hash(user.password, password):
66 | login_user(user)
67 | flash("")
68 | return redirect(url_for('dashboard'))
69 | else:
70 | flash("Wrong Password. Please Try Again!")
71 | else:
72 | flash("Invalid Credentials. Please Try Again!")
73 | return render_template('login.html')
74 |
75 | @app.route('/logout', methods = ['GET', 'POST'])
76 | def logout():
77 | logout_user()
78 | return redirect(url_for('login'))
79 |
80 | @app.route('/dashboard', methods = ['GET', 'POST'])
81 | @login_required
82 | def dashboard():
83 | return render_template('dashboard.html')
84 |
85 | @app.route('/register', methods = ['GET', 'POST'])
86 | def register():
87 | if request.method == 'POST':
88 | username = request.form['username']
89 | password = request.form['password']
90 | hashed_password = bcrypt.generate_password_hash(password)
91 | new_user = User(username=username, password = hashed_password)
92 | existing_user = User.query.filter_by(username=username).first()
93 | if (existing_user):
94 | # print('\nAlready Exists Error!\n', file=sys.stderr)
95 | flash("That name is already taken, please choose another")
96 | return render_template('register.html')
97 | else:
98 | db.session.add(new_user)
99 | db.session.commit()
100 | flash("")
101 | return redirect(url_for('login'))
102 | return render_template('register.html')
103 |
104 | @app.route('/delete/user')
105 | @login_required
106 | def deleteUser():
107 | user = current_user
108 | if user:
109 | User.query.filter_by(id=user.id).delete()
110 | logout_user()
111 | db.session.commit()
112 | return redirect(url_for('home'))
113 |
114 | @app.route('/dashboard/create', methods=['POST','GET'])
115 | @login_required
116 | def create():
117 | if request.method == 'POST':
118 | req = Request()
119 | req.user=current_user
120 | content=request.form['content']
121 | content = chat.chat(content, current_user.username)
122 | req.content=content
123 | db.session.add(req)
124 | db.session.commit()
125 | ppt.ppt(current_user.username)
126 | path = current_user.username+".pptx"
127 | return send_file(path, as_attachment=True)
128 | return "THERE WAS AN ERROR WHILE ADDING THE TASK!"
129 |
130 | if __name__ == '__main__':
131 | with app.app_context():
132 | db.create_all()
133 | app.run(debug=True)
134 |
--------------------------------------------------------------------------------
/chat.py:
--------------------------------------------------------------------------------
1 | import openai
2 | import os
3 | import json
4 | import re
5 |
6 | # set your OpenAI API key
7 | openai.api_key = ""
8 | def chat(req, username):
9 | # define the prompt for the text generation
10 | s2 = " Answer should be as a valid json object with this structure: 1) 'title' field representing title of ppt 2) 'slides' field representing array of slides 3) Each 'slide' having: 'title', 'content' fields. Also, 'content' is a list of strings representing points each not having more than 20 words. Double Check that output is a valid json and that the number of slides is correct."
11 | # req = "Make a powerpoint presentation with five slides for a programmer audience on technical and ethical advantages of linux vs windows with each slide having around 200 words. It should be technical and complex."
12 | prompt = req + s2
13 |
14 |
15 | # define the model and parameters
16 | model_engine = "text-davinci-002"
17 | parameters = {
18 | "temperature": 0.5,
19 | "max_tokens": 3000,
20 | "top_p": 1,
21 | "frequency_penalty": 0,
22 | "presence_penalty": 0
23 | }
24 |
25 | # generate text using the model and prompt
26 | response = openai.Completion.create(
27 | engine=model_engine,
28 | prompt=prompt,
29 | max_tokens=parameters["max_tokens"],
30 | temperature=parameters["temperature"],
31 | top_p=parameters["top_p"],
32 | frequency_penalty=parameters["frequency_penalty"],
33 | presence_penalty=parameters["presence_penalty"]
34 | )
35 |
36 | result = response["choices"][0]["text"]
37 |
38 | output = re.sub(r'^.*?{', '{', result)
39 |
40 | # Save the JSON data string to a file
41 | with open("ppt-api/"+username+"ppt.json", "w") as json_file:
42 | json_file.write(output)
43 |
44 |
45 | with open("ppt-api/"+username+"ppt.json", "r") as f:
46 | # Read the lines of the file into a list
47 | lines = f.readlines()
48 |
49 | delimiter = "{"
50 | for i in range(len(lines)):
51 | # Find the index of the delimiter in the current line
52 | index = lines[i].find(delimiter)
53 | # If found....
54 | if index != -1:
55 | # Remove characters before the delimiter and update the line
56 | lines[i] = lines[i][index:]
57 | break
58 | else:
59 | lines[i]=""
60 |
61 | # Write the updated lines to a new file
62 | with open("ppt-api/"+username+"ppt1.json", "w") as f:
63 | f.writelines(lines)
64 |
65 | return output
--------------------------------------------------------------------------------
/instance/database.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MSSRPRAD/ppt-api/02ae2b7323de05a1472b518a09033981a9b87c64/instance/database.db
--------------------------------------------------------------------------------
/ppt.py:
--------------------------------------------------------------------------------
1 | import collections
2 | import collections.abc
3 | import json
4 | from pptx import Presentation
5 |
6 | def ppt(username):
7 | prs = Presentation()
8 |
9 | # Read the JSON object from a file
10 | with open("ppt-api/"+username+"ppt1.json", 'r') as f:
11 | ppt = json.load(f)
12 |
13 | # Extract the title and slides fields from the JSON object
14 | title = ppt['title']
15 | slides = ppt['slides']
16 |
17 | # Add a title slide
18 | title_slide_layout = prs.slide_layouts[0]
19 | slide1 = prs.slides.add_slide(title_slide_layout)
20 | title1 = slide1.shapes.title
21 | subtitle = slide1.placeholders[1]
22 | title1.text = title
23 | subtitle.text = "By ChatGPT"
24 |
25 | # Loop through each slide and extract the title and content fields
26 | for slide in slides:
27 | slide_title = slide['title']
28 | slide_content = slide['content']
29 | print(f"Slide title: {slide_title}")
30 | print("Slide content:")
31 |
32 | # Add a bullet slide
33 | bullet_slide_layout = prs.slide_layouts[3]
34 | slide2 = prs.slides.add_slide(bullet_slide_layout)
35 | title2 = slide2.shapes.title
36 | body2 = slide2.shapes.placeholders[1]
37 | title2.text = slide_title
38 | tf = body2.text_frame
39 |
40 | for content_string in slide_content:
41 | p = tf.add_paragraph()
42 | p.text = content_string
43 | p.level = 1
44 |
45 | print("\n\n")
46 |
47 |
48 |
49 | prs.save("ppt-api/"+username+str('.pptx'))
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | aiohttp==3.8.4
2 | aiosignal==1.3.1
3 | async-timeout==4.0.2
4 | attrs==22.2.0
5 | bcrypt==4.0.1
6 | certifi==2022.12.7
7 | charset-normalizer==3.1.0
8 | click==8.1.3
9 | Flask==2.2.3
10 | Flask-Bcrypt==1.0.1
11 | Flask-Login==0.6.2
12 | Flask-SQLAlchemy==3.0.3
13 | frozenlist==1.3.3
14 | greenlet==2.0.2
15 | idna==3.4
16 | itsdangerous==2.1.2
17 | Jinja2==3.1.2
18 | lxml==4.9.2
19 | MarkupSafe==2.1.2
20 | multidict==6.0.4
21 | openai==0.27.2
22 | Pillow==9.4.0
23 | python-pptx==0.6.21
24 | requests==2.28.2
25 | SQLAlchemy==2.0.7
26 | tqdm==4.65.0
27 | typing_extensions==4.5.0
28 | urllib3==1.26.15
29 | Werkzeug==2.2.3
30 | XlsxWriter==3.0.9
31 | yarl==1.8.2
32 |
--------------------------------------------------------------------------------
/templates/base.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {% block head %}
10 |
11 | {% block title %}
12 | {% endblock %}
13 |
14 | {% endblock %}
15 |
49 |
50 |
51 |
52 | {% block body %}
53 |
54 | {% endblock %}
55 |
58 |
59 | {% block content %}
60 |
61 | {% endblock %}
62 |
63 |
68 |
--------------------------------------------------------------------------------
/templates/dashboard.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block head %}
4 |
5 | {% endblock %}
6 |
7 | {% block body %}
8 |
9 |
30 |
31 |
32 |
33 | {% endblock %}
34 |
--------------------------------------------------------------------------------
/templates/home.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {% extends 'base.html' %}
4 |
5 | {% block head %}
6 | {% endblock %}
7 |
8 | {% block content %}
9 |
10 |
11 |
12 | This is a site created for learning purposes using the Flask Microframework and Tailwind CSS
13 |
14 |
15 | Created By:
Pradyumna Malladi
16 |
17 |
18 |
21 |
22 |
23 | {% endblock %}
24 |
--------------------------------------------------------------------------------
/templates/login.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block body %}
4 |
5 |
6 |
7 |
38 |
39 |
40 |
41 | {% endblock %}
--------------------------------------------------------------------------------
/templates/register.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block body %}
4 |
5 |
6 |
7 |
45 |
46 |
47 |
48 | {% endblock %}
49 |
--------------------------------------------------------------------------------