Spaces:
Running
Running
Commit
·
1867fb4
1
Parent(s):
9ff714e
Update README.md with project details and instructions
Browse files- README.md +60 -10
- app.py +45 -0
- dockerfile +28 -0
- requirements.txt +0 -0
- static/js/script.js +12 -0
- templates/base.html +23 -0
- templates/index.html +45 -0
- templates/results.html +21 -0
README.md
CHANGED
@@ -1,10 +1,60 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# AI Blog Writer
|
2 |
+
|
3 |
+
AI Blog Writer is a web application that leverages artificial intelligence to help users generate blog posts on various topics
|
4 |
+
|
5 |
+
## Features
|
6 |
+
|
7 |
+
- **Custom Blog Generation**: Users can input the topic, select the desired tone, specify length, and add any specific instructions to guide the content generation.
|
8 |
+
- **Responsive Design**: Built with Bootstrap, the application is fully responsive and user-friendly, suitable for both desktop and mobile users.
|
9 |
+
- **Dark Mode**: A sleek dark mode interface for comfortable usage in low-light conditions.
|
10 |
+
|
11 |
+
## Getting Started
|
12 |
+
|
13 |
+
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes.
|
14 |
+
|
15 |
+
### Prerequisites
|
16 |
+
|
17 |
+
Before you begin, ensure you have the following installed:
|
18 |
+
|
19 |
+
- Python 3.9 or later
|
20 |
+
- Flask
|
21 |
+
- OpenAI
|
22 |
+
- OpenAI API key
|
23 |
+
|
24 |
+
### Installation
|
25 |
+
|
26 |
+
1. Clone the repository:
|
27 |
+
|
28 |
+
```bash
|
29 |
+
git clone https://github.com/yourusername/ai-blog-writer.git
|
30 |
+
```
|
31 |
+
|
32 |
+
2. Navigate to the project directory:
|
33 |
+
|
34 |
+
```bash
|
35 |
+
cd ai-blog-writer
|
36 |
+
```
|
37 |
+
|
38 |
+
3. Install the required Python packages:
|
39 |
+
|
40 |
+
```bash
|
41 |
+
pip install -r requirements.txt
|
42 |
+
```
|
43 |
+
|
44 |
+
4. Run the Flask application:
|
45 |
+
|
46 |
+
```bash
|
47 |
+
flask run
|
48 |
+
```
|
49 |
+
|
50 |
+
The application should now be running on [http://localhost:5000](http://localhost:5000).
|
51 |
+
|
52 |
+
## Usage
|
53 |
+
|
54 |
+
To use the application, simply navigate to the homepage, fill in the form with your blog post requirements, and click on the "Generate Blog Post" button. The AI will process your request and display a generated blog post based on your specifications.
|
55 |
+
|
56 |
+
## Built With
|
57 |
+
|
58 |
+
- [Flask](https://flask.palletsprojects.com/) - The web framework used
|
59 |
+
- [Bootstrap](https://getbootstrap.com/) - The front-end framework used for responsive design
|
60 |
+
- [OpenAI API](https://openai.com/) - The AI model API for content generation
|
app.py
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from flask import Flask, render_template, request
|
2 |
+
from dotenv import load_dotenv, find_dotenv
|
3 |
+
from openai import OpenAI
|
4 |
+
|
5 |
+
load_dotenv(find_dotenv())
|
6 |
+
|
7 |
+
app = Flask(__name__)
|
8 |
+
client = OpenAI()
|
9 |
+
|
10 |
+
def generate_post(tone, topic, length, instructions):
|
11 |
+
prompt = f"Write a {tone} blog post about {topic}. Make sure the blog post is no longer than {length} words and ends with a conclusion. {instructions}"
|
12 |
+
response = client.chat.completions.create(
|
13 |
+
model="gpt-3.5-turbo",
|
14 |
+
messages=[
|
15 |
+
{"role": "system", "content": f"You are an expert {tone} blogger and creative writer."},
|
16 |
+
{"role": "user", "content": prompt}
|
17 |
+
],
|
18 |
+
max_tokens=600,
|
19 |
+
temperature=0.7,
|
20 |
+
top_p=0.9,
|
21 |
+
frequency_penalty=0,
|
22 |
+
presence_penalty=0,
|
23 |
+
stop=["In conclusion", "In summary"]
|
24 |
+
)
|
25 |
+
return response.choices[0].message.content.strip()
|
26 |
+
|
27 |
+
@app.route('/')
|
28 |
+
def index():
|
29 |
+
return render_template('index.html')
|
30 |
+
|
31 |
+
@app.route('/generate', methods=['POST'])
|
32 |
+
def generate_blog():
|
33 |
+
# Retrieve form data
|
34 |
+
topic = request.form.get('topic')
|
35 |
+
tone = request.form.get('tone')
|
36 |
+
length = request.form.get('length')
|
37 |
+
instructions = request.form.get('instructions')
|
38 |
+
|
39 |
+
# Here, you would add your model inference code to generate the blog post
|
40 |
+
generated_text = generate_post(tone, topic, length, instructions)
|
41 |
+
|
42 |
+
return render_template('results.html', generated_text=generated_text)
|
43 |
+
|
44 |
+
if __name__ == '__main__':
|
45 |
+
app.run(debug=True)
|
dockerfile
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Use the official Python image as base
|
2 |
+
FROM python:3.9
|
3 |
+
|
4 |
+
# Set environment variables
|
5 |
+
ENV FLASK_APP=app.py \
|
6 |
+
FLASK_RUN_HOST=0.0.0.0 \
|
7 |
+
FLASK_RUN_PORT=7860
|
8 |
+
|
9 |
+
# Set the working directory in the container
|
10 |
+
WORKDIR /app
|
11 |
+
|
12 |
+
# Copy the requirements file into the container at /app
|
13 |
+
COPY requirements.txt .
|
14 |
+
|
15 |
+
# Install any needed dependencies specified in requirements.txt
|
16 |
+
RUN pip install -r requirements.txt
|
17 |
+
|
18 |
+
# Expose the secret OPENAI_API_KEY environment variable at build time
|
19 |
+
RUN --mount=type=secret,id=OPENAI_API_KEY,mode=0444,required=true
|
20 |
+
|
21 |
+
# Copy the rest of the application code into the container at /app
|
22 |
+
COPY . .
|
23 |
+
|
24 |
+
# Expose the port that Flask is running on
|
25 |
+
EXPOSE 7860
|
26 |
+
|
27 |
+
# Command to run the application when the container starts
|
28 |
+
CMD ["flask", "run"]
|
requirements.txt
ADDED
Binary file (1.54 kB). View file
|
|
static/js/script.js
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
document.addEventListener('DOMContentLoaded', function() {
|
2 |
+
const form = document.getElementById('promptForm');
|
3 |
+
const button = form.querySelector('button[type="submit"]');
|
4 |
+
const spinner = button.querySelector('.spinner-border');
|
5 |
+
|
6 |
+
form.addEventListener('submit', function() {
|
7 |
+
button.childNodes[0].nodeValue = "Loading... ";
|
8 |
+
spinner.style.display = 'inline-block'; // Show spinner
|
9 |
+
button.disabled = true; // Disable button to prevent multiple submissions
|
10 |
+
});
|
11 |
+
});
|
12 |
+
|
templates/base.html
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>AI Blog Writer</title>
|
7 |
+
<!-- Include Bootstrap CSS -->
|
8 |
+
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
|
9 |
+
</head>
|
10 |
+
<body class="bg-dark text-white">
|
11 |
+
|
12 |
+
<div class="container custom-container">
|
13 |
+
<div class="row justify-content-center">
|
14 |
+
<div class="col-md-6">
|
15 |
+
{% block content %}
|
16 |
+
{% endblock %}
|
17 |
+
</div>
|
18 |
+
</div>
|
19 |
+
</div>
|
20 |
+
|
21 |
+
<script src="{{ url_for('static', filename='js/script.js') }}"></script>
|
22 |
+
</body>
|
23 |
+
</html>
|
templates/index.html
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends "base.html" %}
|
2 |
+
|
3 |
+
{% block content %}
|
4 |
+
<div class="container mt-5"> <!-- Increase margin-top if needed -->
|
5 |
+
<div class="row justify-content-center">
|
6 |
+
<div class="col-md-8 col-lg-12"> <!-- Adjusted for wider width -->
|
7 |
+
<div class="card bg-secondary text-white">
|
8 |
+
<div class="card-body">
|
9 |
+
<h1 class="card-title text-center">AI Blog Writer</h1>
|
10 |
+
<form id="promptForm" action="/generate" method="post">
|
11 |
+
<div class="form-group">
|
12 |
+
<label for="topic">Blog Topic:</label>
|
13 |
+
<input type="text" class="form-control" id="topic" name="topic" required>
|
14 |
+
</div>
|
15 |
+
<div class="form-group">
|
16 |
+
<label for="tone">Desired Tone:</label>
|
17 |
+
<select class="form-control" id="tone" name="tone">
|
18 |
+
<option value="informative">Informative</option>
|
19 |
+
<option value="casual">Casual</option>
|
20 |
+
<option value="persuasive">Persuasive</option>
|
21 |
+
<option value="formal">Formal</option>
|
22 |
+
<option value="humorous">Humorous</option>
|
23 |
+
</select>
|
24 |
+
</div>
|
25 |
+
<div class="form-group">
|
26 |
+
<label for="length">Length:</label>
|
27 |
+
<input type="number" class="form-control" id="length" name="length" required max="500" min="100">
|
28 |
+
</div>
|
29 |
+
<div class="form-group">
|
30 |
+
<label for="instructions">Specific Instructions:</label>
|
31 |
+
<textarea class="form-control" id="instructions" name="instructions" rows="3"></textarea>
|
32 |
+
</div>
|
33 |
+
<div class="d-flex justify-content-center">
|
34 |
+
<button type="submit" class="btn btn-success">
|
35 |
+
Generate Blog Post
|
36 |
+
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" style="display: none;"></span>
|
37 |
+
</button>
|
38 |
+
</div>
|
39 |
+
</form>
|
40 |
+
</div>
|
41 |
+
</div>
|
42 |
+
</div>
|
43 |
+
</div>
|
44 |
+
</div>
|
45 |
+
{% endblock %}
|
templates/results.html
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends "base.html" %}
|
2 |
+
|
3 |
+
{% block content %}
|
4 |
+
<div class="container mt-5"> <!-- Increase margin-top if needed -->
|
5 |
+
<div class="row justify-content-center">
|
6 |
+
<div class="col-md-8 col-lg-12"> <!-- Adjusted for wider width -->
|
7 |
+
<div class="card bg-secondary text-white">
|
8 |
+
<div class="card-body">
|
9 |
+
<h1 class="card-title">Generated Blog Post</h1>
|
10 |
+
<article class="card-text">
|
11 |
+
{{ generated_text|safe }}
|
12 |
+
</article>
|
13 |
+
<div class="mt-3 text-center">
|
14 |
+
<a href="{{ url_for('index') }}" class="btn btn-light">Generate another post</a>
|
15 |
+
</div>
|
16 |
+
</div>
|
17 |
+
</div>
|
18 |
+
</div>
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
+
{% endblock %}
|