diff options
| -rw-r--r-- | README.md | 43 | ||||
| -rwxr-xr-x | fanfictioner | 56 |
2 files changed, 99 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..8f64898 --- /dev/null +++ b/README.md @@ -0,0 +1,43 @@ +# fanfictioner + +Turn a story idea into a text-free illustrated book. A local Gemma model +(llama-server) plans the pages and writes the image prompts; `sd-cli` +(stable-diffusion.cpp) draws them. You pick among three candidates at every +image stage. Pages land in the book-reader library as `NNN.png`. + +## Requirements + +- Python 3, stdlib only +- llama-server in router mode on `localhost:8181` serving `Gemma4-12B-qat-mtp` +- `sd-cli` with Vulkan, models under `/data/LLM-models/SD` +- ImageMagick 7 (`magick`), kitty (`kitty +kitten icat`), `$EDITOR` +- `~/.config/book-reader.conf` with a `LIBRARY="..."` line + +## Usage + + fanfictioner story.md [--base zimage|krea2] + fanfictioner --selftest + +Work files go to a directory named after the story (`stories/rooftop.md` -> +`stories/rooftop/`): `plan.md`, `plan.json`, `refs/`, `cand/`. Quit any time +with `q` or Ctrl-C; the next run resumes from what is on disk. + +Plan review keys: `c` confirm, `e` edit in `$EDITOR`, `g` ask Gemma to revise, +`q` quit. Image review keys: `1`-`3` pick, `r` regenerate, `p` edit prompt, +`s` skip edit (edit stage only), `q` quit. + +## License + +Copyright (C) 2026 Danilo M. <danix@danix.xyz> + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License version 2 as published by the Free +Software Foundation. See `LICENSE`. + +## Development Approach + +This project is developed using AI-assisted tools. Code is generated with the help of AI based on human-provided specifications, design decisions, and iterative feedback. + +All contributions are reviewed, tested, and curated by the maintainer before being included in the codebase. AI is used as a productivity and exploration tool, while human oversight remains central to all decisions. + +The goal is to combine the flexibility of AI-assisted development with standard open-source practices such as transparency, review, and accountability. diff --git a/fanfictioner b/fanfictioner new file mode 100755 index 0000000..49ec9b7 --- /dev/null +++ b/fanfictioner @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# fanfictioner: turn a story idea into a text-free illustrated book. +# Copyright (C) 2026 Danilo M. <danix@danix.xyz> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import argparse +import json +import os +import random +import re +import shlex +import shutil +import subprocess +import sys +import tempfile +import time +import urllib.request +from pathlib import Path + +LLM_URL = "http://localhost:8181" +LLM_MODEL = "Gemma4-12B-qat-mtp" +SD_DIR = Path("/data/LLM-models/SD") +CONF = Path.home() / ".config/book-reader.conf" + + +def selftest(): + print("selftest ok") + + +def main(): + ap = argparse.ArgumentParser(description="Turn story.md into a text-free illustrated book.") + ap.add_argument("story", nargs="?", type=Path, help="story idea in free prose") + ap.add_argument("--base", choices=("zimage", "krea2"), default="zimage", + help="base model for pages without a Model: line") + ap.add_argument("--selftest", action="store_true", help="run built-in checks and exit") + a = ap.parse_args() + if a.selftest: + return selftest() + if not a.story: + ap.error("story file required") + + +if __name__ == "__main__": + main() |
