An AI-powered intelligent diary system that transforms your voice into beautifully written diary entries. Talk naturally to your AI companion, and watch as it creates personalized, reflective diary entries that capture your thoughts, feelings, and experiences.
- Overview
- Team Members
- Docker Images
- Features
- System Architecture
- Technology Stack
- Getting Started
- Development
- Testing
- CI/CD Pipeline
- API Documentation
- Database Schema
- Contributing
AI Diary System is a full-stack web application that revolutionizes the traditional diary-writing experience. Instead of typing, users can simply speak to an AI companion that listens, responds warmly, and automatically generates well-structured diary entries with emotion analysis and personalized styling.
- ๐๏ธ Voice-First Interface: Record your thoughts naturally through your browser
- ๐ค Intelligent Conversation: Powered by Google Gemini, the AI asks thoughtful follow-up questions
- ๐ Automatic Diary Generation: Converts conversations into first-person diary entries
- ๐ Emotion Analysis: Tracks your mood with sentiment analysis (mood & mood_score)
- ๐จ Personalized Styles: Choose themes and writing styles (reflective, humorous, poetic, etc.)
- ๐ Privacy First: Complete user isolation with secure authentication
Our containerized services are available on Docker Hub under the sophiafujy account:
๐ก Note for Users: These images are pre-built and hosted by our team. You can pull and use them directly without needing your own Docker Hub account. The username
sophiafujyis our team's Docker Hub account - you don't need to change it unless you're forking the project and publishing your own images.
-
Web Application:
sophiafujy/web-app:latest- Flask-based web application serving the frontend and API
- Handles user authentication and diary management
-
AI Service:
sophiafujy/ai-service:latest- FastAPI service for speech-to-text and AI conversation
- Powered by Faster-Whisper and Google Gemini
# Pull web application image
docker pull sophiafujy/web-app:latest
# Pull AI service image
docker pull sophiafujy/ai-service:latestFor End Users (Most Common) โ
- Just want to run the application? Keep
sophiafujyas-is - Our images are public and ready to use
- Simply set your
GEMINI_API_KEYand you're good to go!
For Developers/Contributors ๐ ๏ธ
- Want to build and push your own images?
- Create your own Docker Hub account
- Update
DOCKER_USERNAMEin your.envfile - Configure your GitHub Secrets accordingly
- ๐ค Real-time Voice Recording: Browser-based audio capture and processing
- ๐ฌ AI Conversation: Natural, warm responses powered by Google Gemini Flash
- ๐ Automatic Diary Generation: Transform conversations into structured diary entries
- ๐ Emotion Analysis: Automatic mood detection and scoring
- ๐ Diary Search & Browsing: View all your entries with date-based navigation
- ๐ Calendar View: Visual timeline of your diary entries
- ๐จ Custom Diary Styles: Choose from reflective, humorous, poetic, or professional tones
- ๐ฏ Theme Focusing: Emphasize specific aspects (work, travel, relationships, etc.)
- ๐ฃ๏ธ Voice Input for Preferences: Speak your preferences instead of typing
1. User Records Audio
โ
2. Browser โ Web-App: POST /api/conversations/<cid>/audio
โ
3. Web-App โ AI-Service: POST /api/chat/audio
โ
4. AI-Service:
โข Faster-Whisper transcribes audio โ text
โข Fetches conversation history from ai_diary
โข Gemini generates warm reply
โข Saves context to ai_diary.conversations
โ
5. AI-Service โ Web-App: { reply, transcript }
โ
6. Web-App saves to diary_db.conversations
โ
7. User clicks "Complete" โ Generate Diary
โ
8. Web-App โ AI-Service: POST /api/generate-diary
โ
9. Gemini analyzes conversation โ structured diary
โ
10. Web-App saves to diary_db.diaries
| Layer | Technology |
|---|---|
| Frontend | HTML5, CSS3, JavaScript (Vanilla), Web Audio API |
| Web Framework | Flask (Python 3.10) |
| AI Service | FastAPI (Python 3.10) |
| LLM | Google Gemini 2.5 Flash Lite |
| Speech-to-Text | Faster-Whisper (OpenAI Whisper, tiny model) |
| Database | MongoDB 6 |
| Containerization | Docker, Docker Compose |
| CI/CD | GitHub Actions |
| Deployment | DigitalOcean Droplet |
| Testing | Pytest, Coverage.py |
| Package Management | Pipenv |
Before you begin, ensure you have the following installed on your system:
- Docker (v20.10 or higher) - Install Docker
- Docker Compose (v2.0 or higher) - Install Docker Compose
- Git - Install Git
Optional for development:
- Python 3.10+
- Pipenv
# Clone the repository
git clone https://github.com/swe-students-fall2025/5-final-finally.git
# Navigate to project directory
cd 5-final-finallyThe project requires a Google Gemini API key for AI functionality.
Create the AI Service environment file:
# Copy the example file
cp ai-service/.env.example ai-service/.env
# Edit the file with your API key
nano ai-service/.env # or use your preferred editorUpdate ai-service/.env with your credentials:
GEMINI_API_KEY=your_gemini_api_key_here
Ensure the following files exist:
ai-service/.env- Contains your Gemini API keydocker-compose.yaml- Orchestrates local development services
| Variable | Description | Required | Default |
|---|---|---|---|
GEMINI_API_KEY |
Google Gemini API key for LLM | Yes | - |
MONGO_URI |
MongoDB connection string | No | mongodb://mongo:27017 |
MONGO_URL |
Alternative MongoDB URI format | No | mongodb://mongo:27017/ |
AI_SERVICE_URL |
URL of the AI service | No | http://ai-service:8000 |
DOCKER_USERNAME |
Docker Hub username (for production) | No | sophiafujy |
- Visit Google AI Studio
- Sign in with your Google account
- Click "Create API Key"
- Copy the key and paste it into
ai-service/.env
Run all services with a single command:
docker-compose up --buildThis will:
- Build Docker images for web-app and ai-service
- Pull MongoDB 6 image
- Start all three services
- Create a persistent volume for MongoDB data
If you prefer to use our pre-built images from Docker Hub:
# Pull images from Docker Hub (sophiafujy is our team's account)
docker pull sophiafujy/web-app:latest
docker pull sophiafujy/ai-service:latest
# Run with docker-compose
docker-compose -f docker-compose.prod.yaml upNote: For production deployment, you'll need to create a
.envfile in the root directory:cp .env.example .env # Edit .env to add your GEMINI_API_KEY # DOCKER_USERNAME is already set to 'sophiafujy' - no need to change it!
Once the services are running:
- Web Application: http://localhost:5001
- AI Service API: http://localhost:8000
- AI Service Docs: http://localhost:8000/docs (FastAPI auto-generated)
- MongoDB: localhost:27017 (not exposed in production)
- Navigate to http://localhost:5001
- You'll be redirected to the login page
- Enter a username and password to create a new account
- Start your first conversation!
# Stop all services (Ctrl+C in the terminal running docker-compose)
# Or in detached mode:
docker-compose down
# Stop and remove all data (โ ๏ธ deletes all conversations and diaries)
docker-compose down -vFor active development without Docker:
cd web-app
# Install dependencies
pipenv install --dev
# Run development server
pipenv run python app.py
# Server runs on http://localhost:5000cd ai-service
# Create .env file with your API key
cp .env.example .env
nano .env # Add your GEMINI_API_KEY
# Install dependencies
pipenv install --dev
# Run development server
pipenv run uvicorn app.main:app --reload --host 0.0.0.0 --port 8001
# API docs available at http://localhost:8001/docs# Run MongoDB in Docker (recommended)
docker run -d -p 27017:27017 --name mongo-dev mongo:6
# Or install MongoDB locally
# https://www.mongodb.com/docs/manual/installation/# Create a feature branch
git checkout -b feature/your-feature-name
# Make changes and test locally
docker-compose up --build
# Run tests
cd web-app && pipenv run pytest
cd ai-service && pipenv run pytest
# Commit and push
git add .
git commit -m "feat: your feature description"
git push origin feature/your-feature-name
# Create pull request on GitHubOur project maintains โฅ80% test coverage enforced by CI/CD.
cd web-app
# Run all tests
pipenv run pytest
# Run with coverage report
pipenv run pytest --cov=app --cov-report=term-missing
# Run with coverage requirement (CI mode)
pipenv run pytest --cov=app --cov-report=term-missing --cov-fail-under=80cd ai-service
# Run all tests
pipenv run pytest
# Run with coverage
pipenv run pytest --cov=app --cov-report=term-missing --cov-fail-under=80web-app/tests/
โโโ conftest.py # Pytest fixtures (client, fake_db, login_user)
โโโ test_app.py # 650+ lines of comprehensive tests
โโโ Unit tests (analyze_mood_and_summary)
โโโ Auth tests (login, logout, session)
โโโ Conversation tests (CRUD, audio handling)
โโโ Diary tests (generation, retrieval)
โโโ API integration tests
ai-service/app/tests/
โโโ test_main.py # FastAPI endpoint tests
โโโ test_db.py # Database operations
โโโ test_geminiclient.py # Gemini client mocking
โโโ test_sttservice.py # Speech-to-text service
Example test with mocking:
import pytest
from unittest.mock import patch
def test_add_audio_message(client, fake_db, login_user):
"""Test audio message processing with AI service mock"""
user_id = login_user()
# Create a conversation
conv_id = create_test_conversation(client, fake_db, user_id)
# Mock AI service response
with patch("requests.post") as mock_post:
mock_post.return_value.status_code = 200
mock_post.return_value.json.return_value = {
"reply": "That sounds great!",
"history": [{"role": "user", "text": "I went for a walk"}]
}
# Send audio file
audio_data = BytesIO(b"fake audio content")
response = client.post(
f"/api/conversations/{conv_id}/audio",
data={"audio": (audio_data, "test.wav")}
)
assert response.status_code == 200
data = response.json()
assert "ai_response" in dataOur project uses GitHub Actions for automated testing, building, and deployment.
Triggers: Push or PR to service directories
Web-App CI (.github/workflows/web-app-ci.yml):
- Runs on: push to web-app/**, pull_request to web-app/**
- Steps:
1. Checkout code
2. Setup Python 3.10
3. Install pipenv and dependencies
4. Run pytest with โฅ80% coverage requirementAI-Service CI (.github/workflows/ai-service-ci.yml):
- Runs on: push to ai-service/**, pull_request to ai-service/**
- Steps: Same as web-app-ci.ymlTriggers: PR merged to main branch
Web-App Release (.github/workflows/web-app-release.yml):
- Runs on: pull_request closed and merged to main
- Steps:
1. Checkout repository
2. Login to Docker Hub
3. Build Docker image
4. Push to sophiafujy/web-app:latestAI-Service Release (.github/workflows/ai-service-release.yml):
- Runs on: pull_request closed and merged to main
- Steps: Same as web-app-release.yml
- Pushes to: sophiafujy/ai-service:latestDeploy to DigitalOcean (.github/workflows/deploy.yml):
- Runs on: push to main branch
- Steps:
1. Checkout code
2. Copy docker-compose.prod.yaml to server via SCP
3. SSH into DigitalOcean Droplet
4. Create .env with secrets
5. Login to Docker Hub
6. Pull latest images
7. Restart services with docker-compose up -dPOST /login # User login/registration
GET /logout # User logout
POST /api/conversations # Create new conversation
GET /api/conversations # Get all user conversations
POST /api/conversations/<cid>/messages # Add text message
POST /api/conversations/<cid>/audio # Add audio message
POST /api/conversations/<cid>/complete # Complete conversation & generate diary
GET /api/diaries # Get all user diaries
GET /api/diaries/<did> # Get specific diary by ID
POST /api/transcribe # Transcribe audio (no chat)
Full interactive documentation available at /docs when running.
GET /health
Response: {"status": "ok"}
POST /api/chat
Body: {"user_id": "string", "text": "string"}
Response: {"reply": "string", "history": [...]}
POST /api/chat/audio
Query: ?user_id=string
Body: multipart/form-data with "file" field
Response: {"reply": "string", "history": [...]}
POST /api/transcribe
Body: multipart/form-data with "file" field
Response: {"text": "string"}
POST /api/generate-diary
Body: {
"messages": [{"role": "user", "text": "..."}, ...],
"preferences": {
"theme": "daily life",
"style": "reflective",
"custom_instructions": "Focus on..."
}
}
Response: {
"title": "string",
"content": "string",
"summary": "string",
"mood": "positive|negative|neutral",
"mood_score": -5 to 5
}
{
"_id": ObjectId("..."),
"username": "alice",
"password": "hashed_password", // Plain text in development, should use bcrypt
"created_at": ISODate("2024-12-09T00:00:00Z")
}{
"_id": ObjectId("..."),
"user_id": ObjectId("..."), // Reference to users._id
"date": "2024-12-09",
"messages": [
{
"role": "user",
"text": "I went for a walk today",
"timestamp": ISODate("...")
},
{
"role": "ai",
"text": "That sounds lovely! How was the weather?",
"timestamp": ISODate("...")
}
],
"created_at": ISODate("..."),
"completed": false // true when diary is generated
}{
"_id": ObjectId("..."),
"user_id": ObjectId("..."), // Reference to users._id
"conversation_id": ObjectId("..."), // Reference to conversations._id
"date": "2024-12-09",
"time": "14:30",
"title": "A Peaceful Walk in the Park",
"content": "Today I took a long walk in the park...",
"summary": "Enjoyed a peaceful walk in nature",
"mood": "positive", // "positive" | "negative" | "neutral"
"mood_score": 3, // -5 to 5
"preferences": {
"theme": "daily life",
"style": "reflective",
"custom_instructions": "Focus on sensory details"
},
"created_at": ISODate("...")
}{
"_id": ObjectId("..."),
"user_id": "alice", // String, not ObjectId
"date": "2024-12-09",
"messages": [
{
"role": "user",
"text": "I went for a walk today"
},
{
"role": "ai",
"text": "That sounds lovely! How was the weather?"
}
],
"updated_at": ISODate("...")
}