This repository provides a Flask application that:
- Exposes JWT-protected endpoints for user registration, login, and AI-driven text generation.
- Uses OpenAI to generate text from a prompt.
- Stores generated texts in a PostgreSQL database.
- Supports Docker and Docker Compose for containerized deployment and testing.
- Overview
- Project Structure
- Setup & Configuration
- Database Migrations (Alembic)
- Running the Application
- Testing
- API Endpoints
- Additional Notes
The AI-Powered Text Generation API offers the following features:
- User Registration & Login: JWT-based auth ensures secure access to endpoints.
- Text Generation: Sends prompts to OpenAI’s text completion endpoint.
- CRUD on Stored Texts: Users can retrieve, update, and delete their previously generated responses.
- PostgreSQL Integration: Database schemas managed via SQLAlchemy.
- Containerization: Docker & Docker Compose for easy setup in various environments.
- Comprehensive Testing: Pytest-based suite with optional Docker-based test environment.
A typical directory layout:
. ├── app │ ├── init.py │ ├── config.py │ ├── models.py │ ├── validation.py │ ├──routes | ├──init.py ├──auth_routes.py ├──generated_text_routes.py └──user_routes.py ├──services | ├──init.py ├──ai_service.py └──user_service.py ├──repositories | ├──init.py ├──generated_text_repository.py └──user_repository.py ├──providers | ├──init.py ├──base_ai_provider.py └──openai_provider.py └── main.py ├── tests │ ├── init.py │ ├── conftest.py │ ├── test_api │ ├──test_auth_api.py ├──test_generate_text.py └──test_user_api.py ├── test_repositories | ├──test_generated_text_repository.py └──test_user_repository.py ├──test_services | ├──test_ai_service.py └──test_user_service.py ├── .env (example environment file for dev) ├── .env.test (example environment file for testing) ├── docker-compose.yml ├── docker-compose.test.yml ├── Dockerfile ├── requirements.txt └── README.md
app/config.py: Loads environment variables and sets up Flask config.app/models.py: DefinesUserandGeneratedTextmodels, plus SQLAlchemy integration.app/routes: All API endpoints (register, login, generate-text, CRUD).app/main.py: App factory (create_app) and the main entry point.tests/: Pytest-based test suite, including fixtures and test modules.docker-compose.yml: Defines containers for PostgreSQL and the Flask app (dev or production usage).docker-compose.test.yml: Defines containers specifically for running tests (test DB, test environment).
This project depends on environment variables for database credentials, JWT secrets, and your OpenAI API key. You can specify these in:
.env(for development/production).env.test(for testing)
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=ai_db
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
SECRET_KEY=super-secret-key
JWT_SECRET_KEY=super-jwt-secret-key
OPENAI_API_KEY=your_openai_api_keyPOSTGRES_USER=test_user
POSTGRES_PASSWORD=test_password
POSTGRES_DB=ai_test_db
POSTGRES_HOST=db_test
POSTGRES_PORT=5432
SECRET_KEY=super-secret-test-key
JWT_SECRET_KEY=super-jwt-secret-test-key
OPENAI_API_KEY=fake_test_keyThis project uses Alembic to manage database schema changes over time. Below are the key commands you’ll need:
- Initial Setup
- Install Alembic (already in
requirements.txt). - If you haven’t already, you can initialize Alembic in your local environment by running:
- Install Alembic (already in
alembic init alembic *(This is already done in this repo, so you should see an `alembic/` folder and `alembic.ini`.)*
- Autogenerate New Migrations
Whenever you change your SQLAlchemy models:
alembic revision --autogenerate -m "Your descriptive message"Alembic will create a new file in alembic/versions/. Inspect it to confirm it matches your intended schema changes.
- Apply Migrations To bring your DB to the latest schema:
alembic upgrade headIf you need to revert to a previous revision:
alembic downgrade <revision>or to go all the way back to an empty DB:
alembic downgrade base- Install PostgreSQL (if not already) and ensure it’s running.
- Create a database (e.g., ai_text_gen_db) and user matching your .env credentials.
- Run Alembic migrations to ensure your local DB has the latest schema:
alembic upgrade head- Create a virtual environment and install dependencies:
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt- Run the app:
python -m app.main- Access at http://127.0.0.1:5000.
- Update .env with your dev environment variables.
- Run:
docker compose up --buildIf you’re on an older Docker version, use docker-compose up --build 3. Access at http://localhost:5000. 4. Data Persistence: By default, the Postgres container uses a named volume (e.g., db_data) defined in docker-compose.yml, preserving data across container restarts.
If you prefer running tests on your host machine:
- Create a test DB (e.g.,
ai_text_gen_test_db) in Postgres - Update
.env.testwith the test DB credentials. - Install dev dependencies (e.g., pytest):
pip install -r requirements.txt- Run:
pytest --disable-warnings -sThis will:
- Load
.env.test(viaconftest.pyorpytest-dotenv, if configured). - Spin up a Flask test client, connect to the test db, create tables, run all tests, then tear down.
We also provide a docker-compose.test.yml for running tests in containers, ensuring a reproducible environment (especially useful for CI/CD).
- Check .env.test ensures credentials match what’s in docker-compose.test.yml.
- Run:
docker compose -f docker-compose.test.yml up --build --abort-on-container-exitThis:
- Starts a db_test container with Postgres.
- Builds a web_test container running pytest --disable-warnings -s.
- Shuts down automatically when tests finish (due to --abort-on-container-exit).
Base URL: http://localhost:5000 (or http://127.0.0.1:5000 if local)
-
POST /register Request Body:
{ "username": "myuser", "password": "mypassword" }Response: 201 Created on success, 400 if user exists.
-
POST /login Request Body:
{ "username": "myuser", "password": "mypassword" }Response: 200 OK with { "access_token": "..." } or 401 on invalid credentials.
-
POST /generate-text (JWT Protected)
{ "prompt": "Write a poem about cats." }Returns a 201 with stored data, or 500 if OpenAI errors.
-
GET /generated-text/ (JWT Protected) Retrieves a stored AI response by ID. Must belong to the user.
-
PUT /generated-text/ (JWT Protected) Updates stored prompt/response.
-
DELETE /generated-text/ (JWT Protected) Deletes the record.
Send the token in the Authorization header:
Authorization: Bearer <access_token>- Mocking OpenAI: Our tests illustrate how to mock
openai.Completion.create()withunittest.mock.patchor via a fixture, avoiding real API calls. - Production Considerations:
- Use a secure
SECRET_KEYandJWT_SECRET_KEY. - Serve over HTTPS.
- Use Gunicorn or another production WSGI server for better performance.
- Use a secure
Enjoy the AI-Powered Text Generation API! If you encounter any issues, please open an issue or contribute improvements via pull requests.