Skip to main content

AI-powered novel writer with vector memory, RAG, and a PyQt6 desktop UI

Project description

NovelForge AI

⚠️ Work in Progress — NovelForge is actively under development. Features may change, break, or be incomplete. Not production-ready.

NovelForge is an AI-powered desktop novel writer that runs entirely on your local machine. Give it a title, genre, and premise — it writes Chapter 1, remembers everything, and keeps writing with full narrative continuity across as many chapters as you want. Ask it questions about your story and it searches its vector memory to answer accurately.

Built on three local services: Ollama for LLM inference, Endee for vector memory, and PyQt6 for the desktop UI.


NovelForge Screenshot

What Makes This Different

Most AI writing tools forget everything after each message. NovelForge doesn't. Every chapter you generate is broken into chunks, embedded, and stored across four dedicated Endee vector indexes — story, characters, lore, and summaries. When the next chapter is generated, the RAG layer retrieves the most semantically relevant chunks from all four indexes and feeds them into the prompt. Characters stay consistent. Locations don't move. Plot threads don't get dropped.


Powered by Endee

Endee is the vector database that makes NovelForge's memory work. It runs locally via Docker, stores all embeddings on disk, and serves queries over HTTP — no cloud, no API keys, no data leaving your machine.

Why Endee for this project:

  • Multi-index architecture — NovelForge uses four separate indexes (story_memory, character_memory, lore_memory, summary_memory). Endee makes it trivial to create, manage, and query multiple indexes independently, so character recall and lore recall don't interfere with each other.
  • Filtered queries — Every vector is tagged with a novel_id filter. Endee's $eq filter operator means queries are always scoped to the active novel — no cross-contamination between your different stories.
  • INT8 precision — All indexes use Precision.INT8 quantization. This halves the memory footprint of stored vectors with negligible quality loss, which matters when you're embedding hundreds of chunks across long novels.
  • Cosine similarity — The embedding model (nomic-embed-text) and cosine space type are a natural fit; semantic similarity is what you want when searching story memory by meaning, not distance.
  • Persistent Docker volume — Everything written to Endee survives restarts. Your novel memory is durable.
  • Zero-latency cold start — Indexes are lazily initialized; the first query creates the index if it doesn't exist, so there's no setup ceremony.

Endee docs: https://docs.endee.io/quick-start


Features

  • Create novels — title, genre, and premise is all you need; Chapter 1 is written and saved automatically
  • Continue stories — type a chapter instruction; the RAG layer retrieves relevant memory before writing
  • Ask questions — query any detail about your story; answers are grounded in stored chapter memory
  • Interactive / Read-only toggle — switch between writing mode and read-only browsing at any time
  • Collapsible sidebar — novel tree with per-chapter navigation; click any chapter to load its full text and summary
  • Per-context chat history — separate conversation thread per novel and per chapter
  • Story Bible — characters, locations, factions, and lore auto-extracted from every chapter and saved to the novel's JSON metadata
  • GPU-accelerated inference — all Ollama calls (generation + embeddings) are configured to use full GPU offload
  • Fully local — Ollama, Endee, and the app all run on your machine; no data leaves it

Minimum Requirements

NovelForge runs heavy local inference. These are the minimum tested specs:

Component Minimum
GPU NVIDIA RTX 4050 6 GB VRAM (or equivalent)
RAM 16 GB
CPU AMD Ryzen 7 (or equivalent 8-core)
Storage ~10 GB free (models + novel data)
OS Windows 10/11, Ubuntu 20.04+, macOS 12+

Expected generation time: 1–3 minutes per chapter or query, depending on GPU and chapter length. The qwen3:8b model runs at roughly 20–40 tokens/sec on an RTX 4050 with full GPU offload.


Prerequisites

You need Ollama and Endee running locally before launching NovelForge.

1. Start Ollama

Download and install Ollama from https://ollama.ai, then pull the two required models:

ollama pull qwen3:8b
ollama pull nomic-embed-text

Ollama starts automatically on install and runs at http://localhost:11434. Verify it's running:

ollama list

You should see both qwen3:8b and nomic-embed-text listed.

2. Start Endee (Docker)

Endee runs as a Docker container. Install Docker Desktop from https://www.docker.com/products/docker-desktop first, then run:

docker run \
  --ulimit nofile=100000:100000 \
  -p 8080:8080 \
  -v ./endee-data:/data \
  --name endee-server \
  --restart unless-stopped \
  endeeio/endee-server:latest

What each flag does:

Flag Purpose
--ulimit nofile=100000:100000 Raises the file descriptor limit — required for Endee's index files under load
-p 8080:8080 Exposes Endee's HTTP API on localhost port 8080
-v ./endee-data:/data Mounts a local folder so all vector data persists across restarts
--name endee-server Names the container so you can stop/start it easily
--restart unless-stopped Auto-restarts Endee if Docker restarts

Verify Endee is running by visiting http://localhost:8080 in your browser — you should see the Endee API response.

To stop and restart later:

docker stop endee-server
docker start endee-server

Full Endee documentation: https://docs.endee.io/quick-start


Installation

Once Ollama and Endee are both running:

pip install novelforge

Launch

novelforge

Or from Python:

from novelforge import launch
launch()

Usage

  1. Click + New Novel in the top bar
  2. Enter a title, genre, and premise — then click Generate Chapter 1
  3. Wait 1–3 minutes while the chapter is generated, embedded, and saved
  4. The chapter appears in the chat area and the sidebar updates with Chapter 1
  5. Type a chapter instruction (e.g. "The lion and rat discover an abandoned village") and press Send or Ctrl+Enter to generate the next chapter
  6. Ask questions about your story at any time (e.g. "What does the rat look like?")
  7. Use the Interactive / Read-only toggle in the top-right to switch to browse mode
  8. Click any chapter in the sidebar to read its full text and summary

Project Layout

novelforge/
├── pyproject.toml
├── README.md
├── LICENSE
│
├── novelforge/
│   ├── __init__.py              # public API — exposes launch()
│   ├── __main__.py              # python -m novelforge entry point
│   │
│   ├── core/                    # backend — no UI dependency
│   │   ├── __init__.py
│   │   ├── prompts.py           # all LLM prompt templates
│   │   ├── generators.py        # Ollama calls + GPU options
│   │   ├── memory.py            # Endee vector DB layer (lazy init)
│   │   ├── novel_manager.py     # JSON metadata + flat-file chapter storage
│   │   └── rag.py               # RAG orchestration layer
│   │
│   └── ui/                      # PyQt6 frontend
│       ├── __init__.py
│       ├── style.py             # full QSS stylesheet + colour palette
│       ├── widgets.py           # ToggleSwitch, Spinner, LoaderOverlay, MessageBubble
│       ├── workers.py           # QThread workers (CreateNovelWorker, SendMessageWorker)
│       ├── dialogs.py           # New Novel dialog
│       ├── sidebar.py           # collapsible novel/chapter tree
│       ├── chat_panel.py        # chat area (header, scroll, bubbles, input bar)
│       └── app.py               # MainWindow + run() entry point

How the Memory System Works

Chapter generated
       │
       ▼
  chunk_text()          splits chapter into 400-word chunks
       │
       ▼
  get_embedding()       nomic-embed-text via Ollama (GPU accelerated)
       │
       ├──▶ story_memory index      full chapter chunks
       ├──▶ summary_memory index    compressed continuity summary
       ├──▶ character_memory index  extracted character data
       └──▶ lore_memory index       locations, factions, world rules

Next chapter generation:
  query = user instruction
       │
       ▼
  retrieve_all_memory()
       ├── story_memory.query(top_k=8)
       ├── character_memory.query(top_k=6)
       ├── lore_memory.query(top_k=6)
       └── summary_memory.query(top_k=8)
                 │
                 ▼
         context injected into LLM prompt
                 │
                 ▼
         consistent chapter generated

Known Limitations

  • Generation time is 1–3 minutes — there is no streaming output yet; the full chapter appears when complete
  • The app has been tested on Windows 11 with an RTX 4050; other configurations may need tuning
  • Endee must be running before the app starts; there is no auto-start or connection retry yet
  • Chapter deletion is not yet implemented in the UI
  • Export to EPUB/PDF is not yet implemented

License

MIT — see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

novelforge-1.0.2.tar.gz (28.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

novelforge-1.0.2-py3-none-any.whl (29.2 kB view details)

Uploaded Python 3

File details

Details for the file novelforge-1.0.2.tar.gz.

File metadata

  • Download URL: novelforge-1.0.2.tar.gz
  • Upload date:
  • Size: 28.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for novelforge-1.0.2.tar.gz
Algorithm Hash digest
SHA256 22f3894a73c93532a4a1d11c9bca645000e5dfc99994c8ced3f9a97a6cd48bde
MD5 b43e170dda738088ee6d72d282ef4e85
BLAKE2b-256 63f5f94d63f4ed0232923e7c3b7eea334a752037dc24fcb6f01b0932fff3b9fd

See more details on using hashes here.

Provenance

The following attestation bundles were made for novelforge-1.0.2.tar.gz:

Publisher: publish.yml on Kshitijbudholiya/NovelForge

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file novelforge-1.0.2-py3-none-any.whl.

File metadata

  • Download URL: novelforge-1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 29.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for novelforge-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 b9d16d395de34458d0f26908fa71f935eee7d053e4b062fdc2c1358d3b560619
MD5 f874980a469ce55d87e45634c6312dbb
BLAKE2b-256 7057b143adca81ded156158826d2cfe7550d691622481bf6e1c5867371012640

See more details on using hashes here.

Provenance

The following attestation bundles were made for novelforge-1.0.2-py3-none-any.whl:

Publisher: publish.yml on Kshitijbudholiya/NovelForge

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page