Skip to content

Repository files navigation

Paraline

English | 한국어

Paraline Concept

A service where an AI analyzes two photos uploaded by a user, creates a "Moment Frame", and connects them with other moments worldwide based on semantic similarity and geographic distance.

Tech Stack

CategoryStack
FrontendNext.js 16, React 19, TypeScript, MapLibre GL, h3-js
BackendFastAPI, Motor (async MongoDB), Celery
AIOpenAI / Google Gemini (Vision & Embeddings)
StorageMongoDB Atlas Local ($vectorSearch), Redis (Celery broker)
GeoH3 (Uber's Hexagonal Hierarchical Spatial Index)
InfraDocker Compose (MongoDB + Redis), Makefile

Prerequisites

  • Docker Desktop
  • Python 3.11+
  • Node.js 20+
  • make

Quick Start

# 1. Install dependencies (Python venv + npm)
make install
# 2. Configure backend/.env (refer to the Environment Variables section below)# 3. Initialize DB + Vector Index (first time only)
make setup
# 4. Start all services (Backend + Worker + Frontend)
make dev

After starting:

Make Commands

CommandDescription
make / make helpPrint available Makefile target help center (default command)
make installCreate Python venv + Install packages + npm install
make setupStart Docker → Wait for MongoDB boot (25s) → Create vector index
make upStart only MongoDB + Redis containers
make downStop Docker containers
make devRun all services in background (Docker + Backend + Worker + Frontend)
make backend / worker / frontendRun each service individually in the foreground
make stopTerminate all processes + Docker containers
make statusCheck Docker/process status
make logs-backend / logs-worker / logs-frontendTail logs
make endpointsPrint all available endpoints
make resetClear DB volumes/uploads/build caches completely

⚠️ Correct Execution Order After DB Reset

Running make dev directly after make reset without make setup will cause the vector search index to be missing, and matching will not work.

# First install or full DB reset
make reset # Clear DB volumes + uploads + build caches
make setup # Start Docker → Wait for MongoDB Search engine (25s) → Create 3072-dim index
make dev # Start all services# Routine restart (keep DB)
make stop
make dev

Environment Variables (backend/.env)

# InfrastructureMONGO_URI=mongodb://localhost:27018/?directConnection=trueMONGO_DB_NAME=paralineREDIS_URL=redis://localhost:6380/0# AI Provider Selection (openai | google)VISION_PROVIDER=googleEMBED_PROVIDER=google# OpenAI ConfigurationOPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxOPENAI_BASE_URL=https://api.openai.com/v1OPENAI_VISION_URI=/chat/completionsOPENAI_EMBEDDING_URI=/embeddingsOPENAI_VISION_MODEL=gpt-4oOPENAI_EMBEDDING_MODEL=text-embedding-3-large# Google Gemini ConfigurationGOOGLE_API_KEY=AIzaSyA...GOOGLE_BASE_URL=https://generativelanguage.googleapis.com/v1betaGOOGLE_VISION_URI=/models/{model}:generateContentGOOGLE_EMBEDDING_URI=/models/{model}:embedContentGOOGLE_VISION_MODEL=gemini-2.5-flashGOOGLE_EMBEDDING_MODEL=gemini-embedding-001# Common AI SettingsEMBEDDING_DIMENSIONS=3072# google: 3072, openai text-embedding-3-large: 3072, text-embedding-3-small: 1536AI_TEMPERATURE=0.7# Matching EngineSIMILARITY_THRESHOLD=0.75HORIZONTAL_MIN_DISTANCE_KM=200MAX_CONNECTIONS_PER_MOMENT=10# ServerBACKEND_PORT=8000PHOTO_UPLOAD_DIR=uploadsLOG_LEVEL=INFO

Project Structure

paraline2/
├── backend/
│ ├── api/ # FastAPI Routers (upload, moments, connections, ...)
│ ├── services/ # ai_service, matching_service, exif_service
│ ├── scripts/ # init_vector_index, rebuild_connections, etc.
│ ├── main.py # FastAPI Entry Point
│ ├── celery_app.py # Celery Instance
│ ├── models.py # Pydantic Models
│ └── requirements.txt
├── frontend/
│ ├── app/ # Next.js App Router Pages
│ ├── components/
│ └── lib/ # API Client, deviceId, etc.
├── docs/ # Plannings, Task Specs
├── docker-compose.yml # MongoDB + Redis
└── Makefile

Processing Flow

[Upload 2 photos]
↓
Extract EXIF (GPS + H3 Index)
↓
Save to Mongo (status=processing)
↓
Celery: analyze_moment_task
├─ AI Vision API → Output JSON
├─ AI Embeddings → High-dimensional Vector
└─ Update Mongo (status=completed)
↓
Celery: match_moment_task
└─ Mongo $vectorSearch → Match Similar Moments → Save connections → Create Notification

Matching Rules

  • Vertical (Same Location): At least one H3 grid cell overlaps between two moments.
  • Horizontal (Distant Location): No H3 overlap + central coordinate distance ≥ HORIZONTAL_MIN_DISTANCE_KM (default 200km).
  • Distances in between are intentionally excluded from connection.
  • Only candidates with Cosine Similarity ≥ SIMILARITY_THRESHOLD (default 0.75) are evaluated.

Port Mapping

Non-standard ports are used to avoid conflicts with other projects:

ServiceHost PortContainer Port
MongoDB2701827017
Redis63806379
Backend8000-
Frontend3000-

About

An AI-powered platform that analyzes user photos to create "Moment Frames" and connects them globally based on semantic similarity and geographic distance.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages