AI-automatically-generates-novels is a pipeline with a contract tree and a ledger
一个基于ai +提示词 的aigc创作生产力工具, 已经有数百家工作室和个人作者通过该工具实现了快速、批量生成小说、剧本、镜头。
At a glance
- What is it?
- This Apache-2.0 project turns a one-sentence premise into finished long text through a multi-stage pipeline where the program, not the model, checks contracts, picks among candidate drafts and computes review scores. The honest trade is that it needs a lot of model calls, and the README is unusually candid about both the cost and the failure modes.
- Who is it for?
- AI-automatically-generates-novels suits an author or studio that wants batch production of long text with an audit trail, and who is prepared to wire in their own OpenAI-compatible gateway and read the call counts before starting.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 39 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Four content types, one engine, no engine changes
The project presents itself as a long-text creation pipeline that turns a one-sentence premise into finished output, and it is explicit that the scope is wider than novels. Four content types share the same engine, which is built from a contract tree, multi-candidate selection, programmatic review and automatic repair. Only the hierarchy and the finished artefact differ.
The four are long-form novels, short-drama scripts, film scripts and anime storyboards. A novel runs outline to volumes to per-chapter outlines to body text, and exports as txt or epub. A short drama runs series planning to episodes to a shot script, and the artefact is a shot script with hook pacing. A film script runs story outline to acts and scenes to script pages, exporting as Fountain or FDX. An anime storyboard runs planning outline to episodes to a shot table, where each row carries shot number, shot size, image, dialogue and duration.
The type definition lives in `packs/type/*.json`, where the hierarchy, fields, prompt templates, default style and exporter are all declared inside the pack. Adding a new content type therefore does not require changing engine code. Each type also has a gate test, in `tests/unit/test_content_types.py`, so a new pack is checked against the same expectations as the existing four.
That structure is the central architectural claim of the project: the pipeline is generic and the content type is data.
The contract tree checks continuity in code, not in the prompt
The novel pipeline is described as a chain, and the interesting step is the second one. From a seed premise the engine builds a root contract, which holds structured fields for the whole book: accounts, threads and facts, in fields rather than prose. From there it produces a milestone chain that splits the book into 30 linked stages, checked programmatically so that adjacent stages interlock.
The interlock check is the part worth stressing. Every node carries structured entry and exit conditions across the three field types, and the program compares them field by field, so the rule that the exit of one block equals the entry of the next is enforced by code rather than by asking a model to be careful. The structure page of the interface shows either that everything interlocks or where it breaks.
The same principle reappears elsewhere. The ledger tracks countable state such as troops and money by program, and mismatches are reported on the spot, so a chapter that ends with 119 bullets and a next chapter with 12 does not slip through. The chapter-level selection is also programmatic: three candidate outlines are judged on criteria such as whether promised chapters are recovered, whether a planted foreshadowing is scheduled for payoff, whether hooks repeat, and whether the ledger advances at the right ratio.
For body text the filter is in two stages. Three candidates face a hard gate first, where any hit on seam repetition, meta-language leakage or a blacklisted giveaway word eliminates the draft, and the survivors are then compared on style metrics.
Review is split the same way. The model reports only a problem plus the exact sentence from the body as evidence, and a report without the quoted sentence is discarded by the program. Scores are then computed by the program from a deduction table, so a reader can recount them.
Gateway configuration is where model compatibility actually bites
Model configuration lives in `config/providers.yaml`, and real addresses and keys live in `.env`, which is gitignored and contains no credentials in the repository. Every gateway is an OpenAI-compatible endpoint at `/v1/chat/completions`, with `base_url` and `api_key` read from the environment.
The interesting configuration detail is the reasoning switch. The README states that this is where vendors genuinely differ in behaviour, and it splits them into styles. A `toggle` style can be turned off completely, as vLLM and the Qwen family do with `enable_thinking=false`. An `effort` style cannot be turned off, only adjusted, and the GLM family returns a 400 when `enable_thinking=false` is sent. A `thinking_style_by_model` option overrides by model name prefix, which is for aggregate gateways carrying several model families at once.
The cost of getting this wrong is given as a measurement: with the same 62,000-character prompt, a Qwen family model configured as effort took 109 seconds and burned 4096 reasoning tokens, while the same model under toggle took 36 seconds with zero reasoning tokens. That is a 25x wall-clock difference caused by one configuration field.
Tasks are then grouped into profiles, each naming a gateway, a thinking switch and a temperature. Planning and drafting run at temperature 1.0, polishing at 0.95, and judging at 0.30. The reasoning behind the spread is given plainly: multi-candidate selection needs temperature to pull the three drafts apart, and the judge needs a low temperature because if the measuring stick drifts, scores between chapters are not comparable.
Adding a gateway takes two steps, a block in `config/providers.yaml` and matching variables in `.env`, with no code change.
Two ways in: a web studio and a sentinel that keeps writing
The README describes two usage paths. The web interface covers creating a book, viewing the contract tree, reading chapters one at a time, changing settings and adjusting parameters. There are screenshot references for the workbench, the new-project dialog, chapter text, the contract tree, outline and chapter outlines, the memory budget, quality inspection, pack management, export and global settings.
The second path is the sentinel. `scripts/guard.sh` starts a watcher that restarts the run if it crashes and keeps going until the target chapter count is reached. The documented invocation passes a title, a check interval and a chapters-per-round count, and the comment describes a check every 180 seconds writing 20 chapters per round with automatic restart on failure. There is a matching stop script.
The memory view is labelled as a five-layer budget, and the settings page can override several baseline values. The override chain is: project override first, then `config/settings.local.yaml`, then `settings.yaml`, then the code defaults. The UI writes only the items that differ from the baseline into `config/settings.local.yaml`.
What the settings page can change is worth listing. Body temperature and planning temperature override the drafting and planning profiles. The concurrent candidate count, defaulting to 3, is used at the milestone, outline and body stages for multi-candidate selection, and setting it to 1 degrades the pipeline to a single draft. Chapter word count bounds, chapters per outline batch, inspection, summary and self-review intervals, and the memory budget all override the same-named entries in `config/settings.yaml`.
Running it: requirements, environment file and the compose stack
The quick start is short and every command is given verbatim.
pip install -r requirements.txt
cp .env.example .env && vim .envThe `requirements.txt` in the repository lists Flask 3.0 or later, requests 2.31 or later, PyYAML 6.0 or later, python-dotenv 1.0 or later, openai 1.30 or later and playwright 1.44 or later.
The service can then be started directly:
python3 -m server.appThe port comes from `NOVEL_PORT` and defaults to 60001. A script variant starts it in the background with logs in `reports/server.log`:
bash scripts/serve.sh startThe compose stack is the other route, and it brings its own search container:
cp .env.example .env && vim .env
docker compose up -d
docker compose up -d appThe first form starts the web service plus a bundled SearXNG retrieval container, the second starts only the main service with retrieval degraded automatically. The compose file names the app container `novel-studio`, publishes the port, mounts `./projects`, `./config` and `./packs` as volumes so drafts persist on the host and configuration and packs can be changed without a rebuild, and pins `NOVEL_PORT: 60001` with `NOVEL_SEARCH_URL: http://searxng:8080`. The Dockerfile is based on `python:3.12-slim` and deliberately filters playwright out of the installed requirements, since the server does not need it.
The unit test suite is a single command:
python3 -m pytest tests/unit -qThe README counts 357 unit tests alongside browser end-to-end tests.
The bill: measured call counts per chapter
The README quantifies what the pipeline costs, and it is the most useful section for anyone deciding whether to run it.
A smooth chapter takes about 11 to 15 calls: 3 body candidates, 2 to 4 review passes, 2 outline and planning calls, and roughly 6 small calls for ledger extraction, titles and summaries. The book average is higher, because repair, rework and inspection all call the model. The measured figures quoted are a 183-chapter book at 5013 calls total, about 27 per chapter, a 60-chapter book at 2197 calls, about 37 per chapter, and a book with heavy repair burning 731 calls over 9 chapters, about 80 per chapter.
Individual prompts are large too. A drafting prompt runs about 20,000 characters and a review prompt about 35,000 characters.
The model selection advice follows directly from that arithmetic. For drafting and polishing, which are the most frequent and longest outputs, a small fast low price model is enough, and the README names qwen-flash series, glm-4-flash and deepseek-chat as examples. It notes that two 500,000-character books in this repository were written with a qwen flash tier model. For judging, the requirement is not literary quality but stable instruction following that produces parseable JSON, because a review result that fails to parse or is missing a field is silently dropped, and temperature is pushed down to 0.3. For planning, which is the most reasoning heavy stage, a stronger model can be assigned if budget allows, which the per-profile gateway setting makes possible.
The measured figures come from trace records under `projects/<title>/trace/`, so they are reproducible from a run rather than asserted.
Known limits, the circuit breaker and what happens when the model drifts
The README has a section on known limitations and it is specific in a way most project documentation is not.
Continuation drift cannot be driven to zero for small models. The opening of chapter N+1 still sometimes fails to match the end of chapter N. The mitigation is review catching it and repair catching the repair, not prevention at generation time.
A chapter rejected by review stays in the book. The pipeline keeps accounting, queues the chapter for repair and keeps writing, and it does not automatically take a bad chapter off the shelf. Only consecutive failures reach the threshold.
That threshold drives the circuit breaker. Five consecutive chapters judged as needing a human, or 6 bad chapters in a sliding window of 10, writes `HALT.md` and stops the run. The reasoning is given: a run of bad chapters usually shares one root cause, and continuing to spend money producing waste is pointless.
Below the threshold the self-healing has three levels. The guard first attempts automatic repair, then rework by diverging again, rolling back the bad section and regenerating three fresh outline candidates, and only marks the segment MANUAL for a human after two failed rework rounds on the same segment.
Two more constraints. External web search is off by default through `memory.web_search: false`, and in invented-world mode the pipeline never goes online regardless of the switch, because invented lore has no authority to check against. The consequence is stated plainly: historical detail such as specific numbers and official titles carries a fabrication risk when it comes from model knowledge rather than a source. And the web service uses Flask's own development server, designed for single machine personal use.
The web service binds `0.0.0.0`, and the README is unambiguous that `NOVEL_PASSWORD` must be set in `.env` when the service is reachable from the public internet, since without it anyone can connect and drive your model account.
Retrieval: four providers, and a model-knowledge fallback that writes its own fact cards
Search is the part of the pipeline with the most moving pieces, and the design decision here is unusual.
Four retrieval types are declared in the `search:` section of `config/providers.yaml`, with `default:` choosing which one runs. A `bocha` type is an AI search with what the README calls the best Chinese results, billed per call, with results cached across books so a cache hit is not charged, and real request counts kept in `search_usage.json`. A `searxng` type points at a self-hosted or public SearXNG instance, free, with an `engines:` list for priority, though the README warns that public instances vary, citing one nominally supporting 85 engines that actually had 2 in service, with half of its Bing results being short video commerce content, so it advises using it only as a fallback. An `http_json` type accepts any OpenSearch-compatible JSON endpoint with custom field mapping. A `null` type is a placeholder implementation so that upper layers never need a null check.
The alternative to searching is more interesting than the search configuration. `fact_from_model` in `server/retrieval.py` keeps the planning in the model, so after reading the settings and outlines the model still lists what this chapter needs to verify, but the retrieval source becomes the model's own knowledge. The output is a structured fact card with concrete numbers, times, forms of address and procedures, plus a note on where writing it wrong would break the world. Those cards are written to disk and reused, per book at `projects/<title>/facts.json` and shared across books in `.cache/facts.json`, so a fact another book already established for the same period is reused directly.
Turning web search on is a three-step change: set `memory.web_search` to `true` in `config/settings.yaml`, fill the key or address in `.env`, and optionally switch `providers.yaml` `search.default`. The number of external lookups per chapter is capped by `memory.web_max_per_chapter`, defaulting to 4, and results are reused across the book.
Editorial conclusion
AI-automatically-generates-novels suits an author or studio that wants batch production of long text with an audit trail, and who is prepared to wire in their own OpenAI-compatible gateway and read the call counts before starting. It does not suit a single novel written by hand, and it does not suit anyone who needs the output to be free of model errors, because the README states that continuation drift in small models cannot be driven to zero and that a chapter flagged by review stays in the book until it is repaired. Verify three things first: that the gateway you point at matches the `thinking_style` your model family expects, since a mismatch cost 109 seconds and 4096 reasoning tokens per call in the measured case, that `NOVEL_PASSWORD` is set before the service is reachable from anywhere but localhost, and that `memory.web_search` is turned on deliberately, since historical detail is otherwise drawn from model knowledge and carries a fabrication risk.
Frequently asked questions
How do I install and start AI-automatically-generates-novels?
Run `pip install -r requirements.txt`, copy `.env.example` to `.env` and fill in at least one gateway, then start the service with `python3 -m server.app` or `bash scripts/serve.sh start`. The port comes from `NOVEL_PORT` and defaults to 60001.
Which model providers does the pipeline support?
Any OpenAI-compatible endpoint at `/v1/chat/completions`. Providers are defined in `config/providers.yaml` and each one needs a URL and a key in `.env`, such as `NOVEL_GW1_URL`, `NOVEL_GW1_KEY` and `NOVEL_GW1_MODEL`. A self-hosted vLLM instance works with `api_key` set to `EMPTY`.
How much does it cost to generate a chapter?
The README measures a smooth chapter at about 11 to 15 model calls, with a drafting prompt around 20,000 characters and a review prompt around 35,000. A 183-chapter book totalled 5013 calls, about 27 per chapter, while a book with heavy repair used 731 calls over 9 chapters.
What does the pipeline do when the model keeps producing broken chapters?
Five consecutive chapters judged as needing a human, or 6 bad chapters in a sliding window of 10, writes `HALT.md` and stops the run. Below that threshold it tries automatic repair first, then rework with fresh outline candidates, and only marks a segment MANUAL after two failed rework rounds on the same segment.
Can it check facts against the web?
Yes, but it is off by default through `memory.web_search: false`. You enable it in `config/settings.yaml`, add the key or address in `.env`, and optionally change `search.default` in `config/providers.yaml`. The `bocha`, `searxng` and `http_json` provider types are supported, and external lookups per chapter are capped by `memory.web_max_per_chapter`, defaulting to 4.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/wfcz10086-ai-automatically-generates-novels)Was this useful?