I’ve been playing with AI (Artificial Intelligence) writing tools since I was a kid. I’ve always been fascinated by the ways machines can generate text that sounds human, from chatbots to predictive text.
A few days ago, I decided to create my own AI writing tool. I wanted something that would help me write more efficiently and allow me to experiment with different writing styles.
This article gives you a clear view of how to create your own AI content writing tool.
Download the complete code from here.
What’s AI Content Writing Tool?
AI content writing tool is a computer program that uses AI to generate text according to the text and keywords you enter. Businesses and individuals who need to create content regularly can save time and money with these tools.
AI content writing tools have the potential to save time and money for businesses and individuals who need to create content regularly.
How Does Our AI Writing Tool Work?
This AI writing tool is made using Flask. It has four functionalties
- Topic Generator
- Outline Generator
- Article Writer
- Passive Voice to Active Voice Convertor
Every tool takes an input like a keyword or a sentence, then the flask server sends a request to the OpenAI server using its API; then the server returns some response in JSON format. The Python script extracts the required data from the JSON format and renders it on the web page.
This tool uses GPT-3 models to generate text.
How To Create Your Own AI Content Writing Tool?
Prerequisites:
- OpenAI API Key
- Python and Flask installed
- Flask or Django IDE
- This blog post 🙂
Get OpenAI API Key
To get an OpenAI API key go to https://beta.openai.com/login and log in or sign up. After login click on the profile picture on the left-> click view API keys-> then copy the key displayed under the section “Secret Key“.
![How I Created My Own AI Content Writing Tool? [Complete Guide] 2 Open AI API Key](https://techtrim.tech/wp-content/uploads/2022/07/Openai-API-key-edited-1.png)
Install Python
To install and set up Django first you’ll need to install Python on your system. On Linux, you can easily install Python by running this command.
$ sudo apt install python3
On Windows, you can download and install Python from this link https://python.org/downloads/.
Install Flask
To install and setup Flask, open the terminal and enter the following commands
$ pip install flask
Setting Up Flask Project
Now you have installed Python and Flask on your computer so we can go on to set up the Flask project. Follow the following steps:
Create a new folder with the name “ai-writer” -> Create three files named “app.py, blog.py, and config.py” -> Create two folders named “templates and static” -> Inside of static folder create two folders named “images and style” -> Inside of templates folder create two files named “index.html and 404.html”
![How I Created My Own AI Content Writing Tool? [Complete Guide] 3 Image showing the file structure of AI Writing Tool](https://techtrim.tech/wp-content/uploads/2022/07/file-structure-of-ai-writer-tool-2-1024x536.png)
After setting up the Flask project, open the terminal and install the Python module of OpenAI using the following command.
$ pip install openai
Files in Root Directory
Code For app.py File:
Open the app.py file which is in the root directory and paste the following code in there.
from unittest import result
from flask import Flask, render_template, request
import config
import blog
def page_not_found(e):
return render_template('404.html'), 404
app = Flask(__name__)
app.config.from_object(config.config['development'])
app.register_error_handler(404, page_not_found)
@app.route('/', methods=["GET", "POST"])
def index():
if request.method == 'POST':
if 'generateTopics' in request.form:
prompt = request.form['blogTopic']
result = blog.generateBlogTopics(prompt)
Topics = result.replace('\n', '<br>')
if 'generateOutline' in request.form:
prompt = request.form['blogSection']
result = blog.generateOutline(prompt)
Outline = result.replace('\n', '<br>')
if 'write' in request.form:
prompt = request.form['blogExpander']
result = blog.write(prompt)
Write = result.replace('\n', '<br>')
if 'passiveVoice' in request.form:
prompt = request.form['passiveVoice']
result = blog.passiveToActive(prompt)
activeVoice = result.replace('\n', '<br>')
return render_template('index.html', **locals())
if __name__ == '__main__':
app.run(host='0.0.0.0', port='8888', debug=True)
This file is responsible for the whole routing and rendering of the website.
Code For blog.py File:
Open the blog.py file in the root directory and paste the following code in there.
import os
import openai
import config
openai.api_key = config.OPENAI_API_KEY
def generateBlogTopics(prompt1):
response = openai.Completion.create(
engine="text-davinci-002",
prompt="Generate blog topics on: {}. \n \n 1. ".format(prompt1),
temperature=0.7,
max_tokens=100,
top_p=1,
frequency_penalty=0,
presence_penalty=0
)
return response['choices'][0]['text']
def generateOutline(prompt1):
response = openai.Completion.create(
engine="text-davinci-002",
prompt="Generate a complete outline on: {} \n\n- Introduction: ".format(prompt1),
temperature=0.6,
max_tokens=100,
top_p=1,
frequency_penalty=0,
presence_penalty=0
)
return response['choices'][0]['text']
def write(prompt1):
response = openai.Completion.create(
engine="text-davinci-002",
prompt="Write a complete article with headings on: \n\n {}".format(prompt1),
temperature=0.7,
max_tokens=200,
top_p=1,
frequency_penalty=0,
presence_penalty=0
)
return response['choices'][0]['text']
def passiveToActive(prompt1):
response = openai.Completion.create(
engine="text-davinci-002",
prompt="Convert passive to active voice: \n\n {}".format(prompt1),
temperature=0.9,
max_tokens=200,
top_p=1,
frequency_penalty=0,
presence_penalty=0
)
return response['choices'][0]['text']
This file is responsible for the whole processing and output of the website.
Code For config.py File:
Open the config.py file which is in the root directory and paste the following code in there.
OPENAI_API_KEY = 'ENTER_YOUR_OPENAI_API_KEY_HERE'
class Config(object):
DEBUG = True
TESTING = False
class DevelopmentConfig(Config):
SECRET_KEY = "this-is-a-super-secret-key"
config = {
'development': DevelopmentConfig,
'testing': DevelopmentConfig,
'production': DevelopmentConfig
}
This file is responsible for all the configuration of the Flask project including the API key of OpenAI.
In the value of the variable OPENAI_API_KEY enter the OpenAI API key that you got after signing up for OpenAI in the first step.
Files in Templates Folder
Code For index.html File:
Open the index.html file which is in the templates folder and paste the following code in there.
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Tech Trim AI Writer Tool</title>
<link rel="shortcut icon" type="image/x-icon" href="{{ url_for('static', filename='images/favicon.png') }}">
<link rel="stylesheet" href="../static/style/style.css">
<link rel="stylesheet" href="../static/style/sidebar.css">
<link rel="stylesheet" href="../static/style/navbar.css">
<link rel="stylesheet" href="../static/style/bootstrap.css">
<script>
const openSidenav = () => {
document.getElementById('sidebar').style.width = '272px';
}
const closeSidenav = () => {
document.getElementById('sidebar').style.width = '0px';
}
$(window).scroll(function () {
$(".fade-to-top").css("opacity", 1 - $(window).scrollTop() / 350);
});
</script>
<style>
.main{
background: linear-gradient(57deg, rgb(40, 59, 167), rgb(52, 105, 175));
color: white;
}
</style>
</head>
<body>
<!-- Navbar start -->
<header class="nav">
<nav>
<div class="main-menuButton">
<span class="menuButton" onclick="openSidenav()">☰</span>
</div>
<div class="logo">
<h1 style="padding-top: 30px;">Tech Trim</h1>
</div>
<div class="menu">
<ul>
<a href="#blogTopic" class="menu-links">
<li>Topic</li>
</a>
<a href="#blogSection" class="menu-links">
<li>Outline</li>
</a>
<a href="#blogExpander" class="menu-links">
<li>Writer</li>
</a>
<a href="#passiveVoice"><button class="joinnow-btn">Passive To Active</button></a>
</ul>
</div>
</nav>
<!-- Sidebar -->
<div class="sidebar" id="sidebar">
<a href="javascript:void(0)" class="xbutton" onclick="closeSidenav()">×</a>
<a href="#blogTopic" class="sidebar-a">Topic</a>
<a href="#blogSection" class="sidebar-a">Outline</a>
<a href="#blogExpander" class="sidebar-a">Writer</a>
<a href="#passiveVoice" class="sidebar-a">Passive To Active</a>
</div>
<!-- Side bar end -->
<!-- Main -->
<div class="main">
<h2>Unlimited writing with<i> Tech Trim</i><br><i> AI Writing Tool</i>.</h2>
</div>
<!-- Main end -->
</header>
<!-- Navbar end -->
<br><br><br><br><br><br><br>
<!-- AI -->
<div class="container">
<div class="row">
<div class="col-lg-6">
<form class="" action="/" method="post">
<div class="mb-3">
<label for="blogTopic" class="form-label">Topic Generator</label><br>
<input type="text" class="form-control" id="blogTopic" name="blogTopic" required placeholder="Enter a blog topic">
</div>
<input type="hidden" name="generateTopics" value="generateTopics">
<button type="submit" id="blogTopicButton" class="btn btn-primary">Generate Topics</button>
</form>
</div>
<div class="col-lg-6">
{{Topics|safe}}
</div>
</div>
<br>
<hr>
<br>
<div class="row">
<div class="col-lg-6">
<form class="" action="/" method="post">
<div class="mb-3">
<label for="blogSection" class="form-label">Blog Outline Generator</label><br>
<input type="text" class="form-control" id="blogSection" name="blogSection" required placeholder="Enter the blog title to generate blog sections on">
</div>
<input type="hidden" name="generateOutline" value="generateOutline">
<button type="submit" class="btn btn-primary">Generate Outline</button>
</form>
</div>
<div class="col-lg-6">
{{Outline|safe}}
</div>
</div>
<br>
<hr>
<br>
<div class="row">
<div class="col-lg-6">
<form class="" action="/" method="post">
<div class="mb-3">
<label for="blogExpander" class="form-label">Write on a specific topic</label><br>
<input type="text" class="form-control" id="blogExpander" name="blogExpander" required placeholder="Enter the blog section title">
</div>
<input type="hidden" name="write" value="write">
<button type="submit" class="btn btn-primary">Write</button>
</form>
</div>
<div class="col-lg-6">
{{Write|safe}}
</div>
</div>
<br>
<hr>
<br>
<div class="row">
<div class="col-lg-6">
<form class="" action="/" method="post">
<div class="mb-3">
<label for="passiveToActive" class="form-label">Convert passive voice to active voice</label><br>
<input type="text" class="form-control" id="passiveVoice" name="passiveVoice" required placeholder="Enter text">
</div>
<input type="hidden" name="passiveVoice" value="passiveVoice">
<button type="submit" class="btn btn-primary">Convert</button>
</form>
</div>
<div class="col-lg-6">
{{activeVoice|safe}}
</div>
</div>
</div>
<!-- Option 1: Bootstrap Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
</body>
</html>
This file is responsible for all the front-end of the tool. Feel free to change the HTML code, but don’t change the code written in <div class=”col-lg-6″>.
Code For 404.html File:
Open the file 404.html which is in the templates folder and paste the following code in there.
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>404</title>
</head>
<body>
<div class="container">
<h1>There's nothing in here. Go to the home page if you dare.
</h1>
<a href="/">I dare</a>
</div>
</body>
</html>
This file is rendered when a user requests a resource that’s not on the server. Feel free to add styling to this page.
Files in Images and Style Folders inside of Static Folder
Image in images folder:
Go to the images folder inside of the static folder and paste any desired image with the name favicon.png. This image will appear at the top of the website with the page title.
Files in Style Folder:
Go to the style folder and create four files named bootstrap.css, navbar.css, sidebar.css, and style.css.
Code For Bootstrap.css File:
Open the bootstrap.css file which is in the style folder and paste the 5313 lines of code from this link.
Code For navbar.css File:
Open the navbar.css file which is in the style folder as well and paste the following code in there.
@import url('https://fonts.googleapis.com/css2?family=Poppins:[email protected]&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Montserrat:[email protected]&display=swap');
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
.nav{
width: 100%;
height: 100px;
background: linear-gradient(57deg, rgb(40, 59, 167), rgb(52, 105, 175));
color: #fff;
font-family: "Montserrat", "sans-serif";
}
nav{
display: flex;
}
.logo{
width: 60%;
height: 100px;
}
.logo img{
line-height: 90px;
}
.menu{
width: 40%;
height: 100px;
}
.menu ul{
list-style: none;
width: 100%;
height: 100px;
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
}
a:hover{
color: rgb(197, 194, 194);
}
::selection{
background-color: rgb(114, 150, 204);
color: white;
}
.current-page{
font-size: 14px;
text-decoration: none;
font-weight: 600;
text-transform: capitalize;
color: rgb(197, 194, 194);
letter-spacing: 1px;
}
.heading{
text-transform: capitalize;
font-size: 24px;
}
.menu-links{
font-size: 14px;
text-decoration: none;
font-weight: 600;
text-transform: capitalize;
font-family: "Montserrat", "sans-serif";
color: #fff;
letter-spacing: 1px;
opacity: 1;
transition: 0.3s;
}
a{
text-decoration: none;
}
.joinnow-btn{
width: 120px;
height: 33px;
background: transparent;
color: #fff;
border: 1px solid #fff;
border-radius: 3px;
transition: 0.3s;
font-weight: bold;
}
.joinnow-btn:hover{
background-color: #fff;
color: #000;
cursor: pointer;
}
Code For sidebar.css File:
Open the file sidebar.css which is also in the style folder and paste the following code in there.
@import url('https://fonts.googleapis.com/css2?family=Montserrat:[email protected]&display=swap');
*{
font-family: "Montserrat", "sans-serif";
}
.menuButton{
font-size: 30px;
cursor: pointer;
color: #fff;
visibility: visible;
}
.main-menuButton{
margin-top: 24px;
padding-left: 10px;
}
.sidebar{
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 10001;
background: linear-gradient(57deg, rgb(40, 59, 167), rgb(52, 105, 175));
width: 0;
overflow-x: hidden;
padding-top: 50px;
transition: all, 0.3s;
visibility: visible;
}
.sidebar a:hover{
color: rgb(209, 206, 206);
}
.xbutton{
position: absolute;
top: 20px;
left: 10px;
font-size: 45px;
color: #fff;
padding-left: 8px;
}
.sidebar-a{
color: #fff;
text-decoration: none;
display: block;
padding-top: 26px;
padding-bottom: 8px;
padding-left: 20px;
transition: 0.3s;
}
.sprovider-main-points-a:hover{
text-decoration: underline;
color: rgb(40, 59, 167);
}
@media (min-width: 1200px){
.menuButton{
visibility: hidden;
}
}
Code For style.css File:
Go to the style.css file which is in the style folder and paste the following code in there.
@import url('https://fonts.googleapis.com/css2?family=Poppins:[email protected]&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Montserrat:[email protected]&display=swap');
*{
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: "Montserrat", "sans-serif";
}
html, body{
overflow-x: hidden;
}
.nav{
width: 100vw;
height: 300px;
background: linear-gradient(57deg, rgb(40, 59, 167), rgb(52, 105, 175));
color: #fff;
font-family: "Montserrat", "sans-serif";
}
nav{
width: 100vw;
height: 100px;
display: flex;
}
.logo{
width: 60%;
height: 100px;
}
.logo img{
line-height: 90px;
}
.menu{
width: 50vw;
height: 100px;
visibility: visible;
}
.menu ul{
list-style: none;
width: 100%;
height: 100px;
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
}
.menu ul a:hover{
color: rgb(197, 194, 194);
}
::selection{
background-color: rgb(114, 150, 204);
color: white;
}
.current-page{
font-size: 14px;
text-decoration: none;
font-weight: 600;
text-transform: capitalize;
color: rgb(197, 194, 194);
letter-spacing: 1px;
}
.heading{
text-transform: capitalize;
font-size: 24px;
}
.menu-links{
font-size: 14px;
text-decoration: none;
font-weight: 600;
font-family: "Montserrat", "sans-serif";
color: #fff;
letter-spacing: 1px;
opacity: 1;
transition: 0.3s;
}
a{
text-decoration: none;
}
.joinnow-btn{
width: 80px;
height: 25px;
background: transparent;
color: #fff;
border: 1px solid #fff;
border-radius: 3px;
transition: 0.3s;
font-weight: bold;
}
.joinnow-btn:hover{
background-color: #fff;
color: #000;
cursor: pointer;
}
.main h2{
line-height: 90px;
padding-left: 50px;
font-family: "Poppins", "sans-serif";
font-weight: bold;
font-size: 40px;
}
.search-bar{
line-height: 70px;
padding-left: 50px;
}
.search-input{
height: 40px;
width: 400px;
padding-left: 15px;
border: 1px solid rgb(146, 146, 146);
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
display: inline-block;
box-sizing: border-box;
position: relative;
}
.search-button{
height: 40px;
background-color: rgb(78, 97, 202);
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
width: 100px;
border: none;
color: #fff;
transition: 0.3s;
cursor: pointer;
font-weight: bold;
position: relative;
border-radius: 1px solid rgb(66, 86, 202);
left: -5px;
}
.search-button:hover{
background-color: rgb(66, 86, 202);
color: #fff;
}
input:focus{
outline: none;
}
.services-icon{
margin-left: 50px;
display: flex;
}
.services-heading{
font-weight: bold;
font-size: 1.5em;
}
.services{
padding-left: 50px;
font-family: "Poppins", "sans-serif";
}
.services ul{
list-style-type: none;
display: flex;
flex-direction: row;
justify-content: space-around;
margin-top: 20px;
}
.services a{
font-weight: bold;
font-size: large;
color: rgb(87, 86, 86);
}
.services a:hover{
color: rgb(40, 59, 167);
transition: 0.3s;
}
.about{
text-align: center;
margin-top: 20px;
/* background-color: red; */
}
.about p{
padding-top: 10px;
text-align: justify;
}
.container{
width: 60vw;
/* background-color: red; */
margin: auto;
}
/* Media queries */
@media (max-width: 574px){
.main h2{
font-size: 25px;
}
}
/* Sidebar */
@media (max-width: 1200px){
.menu{
visibility: hidden;
}
}
/* Sidebar end */
/* Services */
@media (max-width: 771px){
.services ul a{
font-size: 16px;
text-align: center;
position: relative;
display: inline-block;
word-spacing: 0px;
line-break: auto;
}
}
@media (max-width: 635px){
.services ul a{
font-size: 12px;
}
}
/* Services End */
/* Media queries end */
This file is responsible for the complete UI (User Interface) and mobile responsiveness of the website. You can change the styling according to your preferences.
Get The Tool Running
Now you have all the source files we need to get your tool running now so that you can use it. Go to the root directory and open the terminal/power shell in there and run the following command.
$ python app.py
By running this command if you’re getting this error:
Traceback (most recent call last):
File “app.py”, line 2, in
from flask import Flask, render_template, request
ImportError: No module named flask
Then try running this command.
$ python3 app.py
Hoorah! your AI writing tool is live and ready to use on 127.0.0.1:8888. Just enter this in any browser and you will be able to access the website.
How To Use The AI Writing Tool?
When you open the website on 127.0.0.1:8888 you will see a beautiful UI like this.
![How I Created My Own AI Content Writing Tool? [Complete Guide] 4 Image showing the UI of AI Writing Tool](https://techtrim.tech/wp-content/uploads/2022/07/AI-writer-tool-user-interface-1024x489.png)
The website has four sections:
- Topic generator
- Outline generator
- Article writer
- Passive voice to active voice convertor
Topic Generator
Enter the keyword on which you want to write about in the input field and click Generate Topics. The tool will automatically generate five eye-catching titles for you.
Outline Generator
The second section of this tool allows you to generate a complete outline for a blog post. Just enter your blog title and it will generate an outline that you can use to write the complete article.
Article Writer
Article writer writes a complete article of more than 500 words on the entered blog topic. You can make some changes and publish your article anywhere.
Passive Voice to Active Voice Convertor
The use of active voice sentences is very important in a blog post to keep the flow. The passive voice-to active voice converter converts the provided passive voice sentence into active voice.
Final Words
It has taken a lot of hard work and dedication to create this tool.
This tool has helped me become a better writer, and I hope that it can help you, too. I believe that this tool can help people in a variety of ways, whether it be for school, work, or personal use. I am excited to see how people use it and what they think of it.
This article explains the complete process of how to create your own AI content writing tool.
What do you think about this tool? Let us know in the comments.