JetLaggedByData/scifi-forge
<div align="center">
π SciFi Forge
Multi-Agent Science Fiction Story Generation Pipeline
How a Deep Learning coursework LSTM became a production-grade agentic AI system
   
</div>
π Project Overview
SciFi Forge is a three-generation AI evolution project β from a character-level LSTM trained on a 149M-character science fiction corpus, to a QLoRA fine-tuned LLM, to a fully agentic LangGraph pipeline with four specialised collaborating agents.
The project demonstrates the entire ML engineering lifecycle: data pipeline, model training, evaluation, agent orchestration, memory systems, experiment tracking, and production deployment. All tools are 100% free and everything runs on a single 8GB GPU.
π¬ Demo

Live interactive app (Qwen2.5-0.5B, CPU): β huggingface.co/spaces/JetLaggedByData/scifi-forge
ποΈ Architecture
Three-Generation Evolution
V1: LSTM (MSc coursework) V2: QLoRA LLM (self-directed) V3: Agentic (portfolio)
βββββββββββββββββββββββββ ββββββββββββββββββββββββββββββ ββββββββββββββββββββββ
TensorFlow / Keras Qwen2.5-1.5B-Instruct LangGraph state machine
Char-level, 75 vocab 4-bit QLoRA via bitsandbytes 4 specialised agents
EmbeddingβLSTM(1024)βDense 50k instruction samples FAISS chapter memory
149M char SciFi corpus 8GB GPU, 3 epochs MLflow tracking
Google Colab ~60% perplexity reduction Critic-gated revisionV3 Multi-Agent Pipeline
flowchart TD
A([π Seed Prompt]) --> B
B["πΊοΈ Planner
Generates story bible
title Β· acts Β· characters Β· world rules"]
B --> C
C["βοΈ Writer
Retrieves FAISS context
Generates ~600 word chapter"]
C --> D
D{"π Critic
consistency Β· style Β· coherence
scored 0β1 each"}
D -->|"score < 0.6 AND revisions remaining"| E
D -->|"score β₯ 0.6 OR budget exhausted"| F
E["βοΈ Editor
Rewrites chapter
per revision instructions"]
E --> D
F["βοΈ Advance Chapter
reset critique Β· increment counter"]
F -->|more chapters| C
F -->|done| G
G([π story.json])
style A fill:#e8f4f8,stroke:#2196F3,color:#1a1a2e
style B fill:#e3f2fd,stroke:#1976D2,color:#1a1a2e
style C fill:#fff8e1,stroke:#F57F17,color:#1a1a2e
style D fill:#e8eaf6,stroke:#3949AB,color:#1a1a2e
style E fill:#fff3e0,stroke:#E65100,color:#1a1a2e
style F fill:#f3e5f5,stroke:#7B1FA2,color:#1a1a2e
style G fill:#e8f5e9,stroke:#2E7D32,color:#1a1a2eMemory System
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MEMORY SYSTEM β
β β
β StoryBible (JSON) ChapterMemory (FAISS) β
β βββββββββββββββββ ββββββββββββββββββββββ β
β Planner writes once Writer adds each chapter β
β All agents read Semantic retrieval β
β ~500 token summary all-MiniLM-L6-v2 (CPU) β
β data/stories/<id>/bible.json 50% sentence overlap β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββπ Benchmark Results
V1 and V2 perplexity are on different scales (character-level vs word-level) and are not directly comparable. V3 critique scores are computed by the Critic agent: 75% LLM scoring + 25% embedding-based voice consistency. V3 scores improve with more chapters β each chapter adds to the FAISS memory, giving the Writer and Critic richer context for consistency scoring. The figures above are based on single-chapter stories; multi-chapter runs yield progressively stronger coherence signals.
π Project Structure
scifi-forge/
β
βββ v1_baseline/ # LSTM baseline β preserved as benchmark anchor
β βββ lstm_model.py # Embedding β LSTM(1024) β Dense
β βββ train.py # Original training config (unchanged)
β βββ generate.py # Character-level generation
β βββ evaluate.py # Perplexity, BLEU-2, inference speed
β
βββ v2_finetuned/ # QLoRA fine-tuned Qwen2.5-1.5B
β βββ finetune.py # 4-bit QLoRA training (8GB VRAM safe)
β βββ generate.py # Inference with LoRA adapters
β βββ evaluate.py # Word-level metrics, genre score
β βββ adapters/ # LoRA weights (gitignored β push to HF Hub)
β
βββ v3_agentic/ # π Main deliverable β agentic pipeline
β βββ agents/
β β βββ planner.py # Story bible JSON generation
β β βββ writer.py # Chapter generation + FAISS retrieval
β β βββ critic.py # 3-dimension scoring + MLflow logging
β β βββ editor.py # Revision with Critic feedback
β βββ memory/
β β βββ story_bible.py # Persistent JSON + token-capped summary
β β βββ chapter_store.py # FAISS semantic chapter memory (CPU)
β βββ pipeline/
β β βββ state.py # StoryState TypedDict
β β βββ graph.py # LangGraph with conditional routing
β β βββ runner.py # CLI + streaming entry point
β βββ evaluate/
β βββ benchmark.py # Full V1 vs V2 vs V3 report
β βββ consistency_scorer.py # Story-level metrics from stored JSONs
β
βββ data/
β βββ raw/ # internet_archive_scifi_v3.txt (gitignored)
β βββ chunks/ # Instruction-format JSONL (gitignored)
β βββ stories/ # Pre-generated stories (COMMITTED)
β βββ story_01/story.json
β βββ ...
β
βββ app/
β βββ main.py # Unified entry point (auto-detects CPU/GPU)
β βββ pages/
β βββ 1_forge.py # Live generation with agent feed
β βββ 2_model_arena.py # Benchmark charts
β βββ 3_story_library.py # Browse pre-generated stories
β βββ 4_about.py # Project timeline + architecture
β
βββ mlflow_runs/
β βββ benchmark_report.json # Full metrics (COMMITTED)
β βββ charts/ # Pre-exported Plotly JSON (COMMITTED)
β βββ export_charts.py # Regenerate charts from benchmark report
β
βββ scripts/
β βββ pregenerate_stories.py # Generate 5 seed stories before deployment
β
βββ tests/ # pytest suite
βββ Dockerfile # CPU image for HF Spaces / Docker
βββ docker-compose.yml # Local dev (lite + full + mlflow)
βββ requirements.txt
βββ README.md # You are hereβ‘ Quickstart
Prerequisites
- Ubuntu Linux (tested), Python 3.10+
- GPU with 8GB VRAM + CUDA (for V2 fine-tuning and V3 full pipeline)
- CPU-only mode works for the lite app and pre-generated story browsing
1. Clone and install
git clone https://github.com/JetLaggedByData/LanguageModel.git
cd scifi-forge
python3.10 -m venv .venv && source .venv/bin/activate
# Install PyTorch with CUDA (check your CUDA version: nvcc --version)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
pip install -r requirements.txt
python -m spacy download en_core_web_sm
python -c "import nltk; nltk.download('punkt')"2. Download the corpus
mkdir -p data/raw
# Download internet_archive_scifi_v3.txt (~149MB) to data/raw/
# Source: https://archive.org/details/SciFiStories3. Run V1 baseline
# Train (optional β checkpoint already committed if using pre-trained weights)
python v1_baseline/train.py
# Generate
python v1_baseline/generate.py
# Evaluate
python v1_baseline/evaluate.py4. Prepare data and fine-tune V2
# Prepare 50k instruction-format samples (~5β10 min)
python data/prepare_dataset.py
python data/verify_dataset.py
# Fine-tune (~4β6h on 8GB GPU, 3 epochs)
python v2_finetuned/finetune.py
# Test generation
python v2_finetuned/generate.py
# Evaluate
python v2_finetuned/evaluate.py5. Run V3 agentic pipeline
cd v3_agentic
# Single story (CLI)
python pipeline/runner.py \
--prompt "A dying colony ship discovers an alien signal" \
--chapters 4 \
--revisions 2
# Pre-generate 5 stories + export benchmark charts (~2β3h)
python ../scripts/pregenerate_stories.py
# Quick smoke test (1 chapter per story, ~15 min)
python ../scripts/pregenerate_stories.py --dry-run6. Launch the app
# Full local app (requires GPU + trained adapters)
streamlit run app/main.py
# Lite app (CPU-safe, mirrors HF Spaces deployment)
LITE_MODE=1 streamlit run app/main.py7. Run benchmarks
python v3_agentic/evaluate/benchmark.py
python mlflow_runs/export_charts.py
# View MLflow runs
mlflow ui --backend-store-uri mlflow_runs/π οΈ Tech Stack
Hardware: 8GB GPU VRAM Β· 32GB CPU RAM Β· Ubuntu Linux Cost: Β£0 β 100% free tools and hosting
π Key Design Decisions
VRAM management β all fine-tuning uses 4-bit QLoRA (nf4, double quantisation, bfloat16 compute) with per_device_train_batch_size=1, gradient_checkpointing=True, and paged_adamw_8bit. Peak VRAM stays under 6GB, leaving 2GB headroom on an 8GB card.
Agent model sharing β all four V3 agents share the same model, loaded once per run via a context manager (user-selectable; default: Qwen2.5-1.5B + LoRA adapters). Temperature varies by role: Planner (0.4, structured JSON), Writer (0.75, creative prose), Critic (0.2, deterministic scoring), Editor (0.65, tight revision).
Graceful degradation β every agent wraps generation in try/except and returns a minimal valid state on failure. The pipeline never hard-crashes; it logs the error to state["error"] and continues, so a single bad chapter doesn't abort a 6-chapter story.
Deployment split β full V3 runs locally on GPU and is screen-recorded for the demo video. HF Spaces runs the lite app (user-selectable CPU models, default Qwen2.5-0.5B) with pre-generated stories and pre-exported charts committed to the repo, so the deployed app looks rich without any GPU inference at runtime.
π§ͺ Running Tests
pytest tests/ -v
pytest tests/ -v --cov=v3_agentic --cov-report=term-missingπ Deployment
# Build and test Docker image locally
docker build -t scifi-forge .
docker run -p 7860:7860 scifi-forge
# Deploy to HF Spaces (GitHub Actions handles this automatically on push to main)
git push origin mainSee .github/workflows/deploy.yml for the full CI/CD pipeline.
π License
MIT β see LICENSE
<div align="center">
Built with β on 8GB VRAM Β· Ubuntu Linux Β· 100% free tools
</div>
