structured-writer — AI Agent
Project description
Structured Writer — 结构化写作智能体
基于 LLM 的结构化长文写作系统。子结构驱动、两级 RAG 增强、续写容断、交互式大纲控制。
核心架构
用户输入主题
→ [大纲规划器] LLM 生成结构化 JSON 大纲(节×子结构)
→ [交互式大纲] 用户可调整:勾选/排序/字数/重点/RAG
→ [串行写作器] 逐子结构调用 LLM 写作
├─ 节级别 RAG 查询(背景资料)
├─ 子结构级别 RAG 查询(针对性资料)
├─ 前文上下文注入(保连贯性)
└─ token 耗尽自动续写
→ 合并 .md 输出
特性
| 特性 | 说明 |
|---|---|
| 子结构系统 | 每节自动分解为 2-4 个子结构,逐子结构串行写作,### 标题分隔 |
| 两级 RAG | 节级别查背景资料 + 子结构级别查针对性资料,prompt 分两段注入 |
| 续写机制 | 检测 finish_reason="length" 自动续写,最多 5 轮。空内容跳过续写 |
| 交互式大纲 | 勾选/取消节和子结构、阿拉伯数字排序、罗马数字子结构排序、字数编辑、重点标记 |
| 大纲双级排序 | 节:1-N;子结构:i-iv(每节独立) |
| 多模板 | 通用公文/新闻报道/论文综述/技术报告/自定义,切换即生效 |
| 实时进度 | 写作过程显示进度条 + 状态文本(RAG查询/写作中/完成) |
| 会话恢复 | 断线重连后恢复大纲和进度 |
| RAG 冷启动 | 配置页一键启动 rag-assistant 子进程,自动检测在线状态 |
快速开始
pip install structured-writer-ldxs
structured-writer-ldxs --port 8770
打开 http://localhost:8770
配置
配置 Tab 设置写作者模型(LM Studio / Ollama)、规划者模型、上下文窗口、提示词模板。
模型推荐
| 角色 | 推荐模型 | 注意事项 |
|---|---|---|
| 写作者 | Qwen3.5-35b-A3B / 同级别 | 推理模型 max_tokens 建议 ≥8192 |
| 规划者 | Qwen3.5-35b-A3B / 同级别 | 大纲生成需要语义理解能力 |
RAG 对接
本系统依赖 rag-assistant 的知识库查询能力:
- 启动 rag-assistant(或通过配置页一键冷启动)
- 配置页填入 rag-assistant 路径,点击冷启动
- 大纲中勾选 RAG + 选择知识库
- 系统自动做两级 RAG 查询:节背景 + 子结构针对性
高级用法
大纲勾选
取消勾选的节/子结构在生成时完全跳过,不写标题也不占字数。
续写
LLM 输出被 max_tokens 截断时自动追加"请继续写"指令重试。content 为空(推理吃光 token)时放弃续写,不卡死。
PyPI
pip install structured-writer-ldxs
许可证
Apache 2.0 © wUwproject
更新说明
[1.0.28] - 2026-07-27
新增
- 每子结构字数可编辑:章节字数改为子结构字数之和(自动实时求和),子结构字数输入框直接可改;取消勾选的子结构不计入章节字数
- 进度条按过滤后子结构总数计算:取消勾选的子结构不再计入进度分母
- RAG 离线时复选框禁用:8767 未上线时 RAG 复选框 disabled+title 提示;上线后自动同步 KB 下拉框
- 子结构辅助知识模态框:每个子结构 "+" 按钮 → 弹窗支持文本输入 + .txt/.md 文件上传(FileReader 前端读取)
- RAG 与辅助知识 Prompt 分离注入:
【RAG 参考资料】和【辅助知识】两段独立标注 - 前文回顾字数可配置:配置页 "写作参数" 新增输入框,
context_review_length写入 config.json - 配置项自动合并:
config_manager.load()深层合并(嵌套 dict 中新 key 自动补上);update()支持写入新增键 - LLM 模型自动检测:
_build_payload中 model 为空时自动调list_models()取第一个已加载模型 - 批量自动撰写:输入框写入多行(每行一个主题)→ 后端
/api/batch_auto逐篇规划+RAG+生成 → 前端轮询批量进度 - 单篇自动撰写:输入框旁 "自动撰写" 按钮 → 前端 chain
plan→generate,全量自动 RAG - 事实自检系统:配置页 "事实自检" 开关 → 写作 prompt 末尾内嵌
【事实待核查】标记 → LLM 在同一 response 中自检 → 解析标记收集 → 文章末尾编号列表汇总。零额外 LLM 调用 - 无问题时也输出自检段落:即使所有子结构都返回"无",文章末尾也输出
## 建议人工复审+未发现需标记的问题 - 会话归档/恢复/删除:侧边栏每项 "🗂 归档" 按钮 →
data/archives/sessions/折叠区 → "↩ 恢复" + "✕ 删除"(confirm()确认) - 自动会话限额:
max_sessions(默认 20)→ 新建会话超出时自动归档最旧非当前会话 - 停止生成:聊天区底部 "延时停止"(当前子结构写完停)+ "立即停止"(续写边界停)→ 保留已写内容输出 .md
- 规划器优先遵循用户指令:约束前加 "优先遵循用户明确指定的结构要求",
sections 数量改为 "如用户未指定" - 规划/写作模型温度可配置:配置页新增 "温度" 输入框(0-1,step=0.05),规划默认 0.6、写作默认 0.7,持久化到 config.json
- LLM 客户端 temperature 参数:
LLMClient.__init__加temperature,chat/chat_detailed/_build_payload默认值改为None(走self.temperature) - 模型下拉框始终显示已保存的模型:
refreshModels接受savedValue参数,配置模型不在 API 返回列表时追加xxx(已配置)option - RAG 停止按钮:配置页新增 "停止 RAG" 按钮 → 后端
_handle_rag_stop→taskkill /F /T杀进程树 +netstat查 8767 + 等端口释放 + auto-restart 检测 - RAG 停止后不再显示"运行中":
_ragManuallyStopped标记阻止轮询跳回运行中状态,直到用户手动点击"冷启动 RAG" - RAG 状态轮询加速:cache-buster 防缓存,间隔 3s→1.5s,启动后立即查一次
变更
- 自检从额外 LLM 调用改为内嵌标记:删除
FACT_CHECK_PROMPT和独立SELF_CHECK_SYSTEM_PROMPT,改为在写作 prompt 末尾追加【事实待核查】标注要求,response 里直接解析 - 规划器
max_tokens从配置读:删除硬编码 4096,改用max(4096, llm_client.max_tokens) - 写作器/规划器 LLM 客户端统一工厂:
_create_writer_client()/_create_planner_client()传temperature - Planner/writer temperature 硬编码删除:
planner.pytemperature=0.6→None;writer.pytemperature=0.7→None(走客户端配置) status_text仅 writing 阶段返回:get_progress()非 writing 阶段返回空字符串,防止加载旧会话显示脏数据- 状态文本生成时自动清空:
_handle_generate入口调用set_status_text("") - 配置页提示文案更新:改为 "推理模型建议不低于 4096(默认最低值),长文建议 8192 以上"
修复
planner.py硬编码max_tokens=4096导致推理模型 thinking 吃掉全部 token → JSON 输出为空config_manager.pyupdate()无法写入新增配置键 →fact_check_enabled等不持久化config_manager.pyload()不合并 DEFAULT_CONFIG 缺失项 → 旧 config.json 没有新字段- 自检
max_tokens各值(2048/8192/512)导致推理模型 thinking 吃光 → 改为None(走配置的 81920) - 自检使用独立 system prompt → LLM 混淆角色 → 改为共享
WRITER_SYSTEM_PROMPT - 自检额外 LLM 调用导致额外 token 消耗 → 改为内嵌标记法,零额外调用
- 加载旧会话时
_status_text脏数据被轮询读出并显示 - 章节字数 input 可编辑但子结构字数不变 → 数据不一致
- 子结构取消勾选后章节字数不减 → 重算函数忽略未勾选
- 模型下拉框加载时显示"(请选择)"而非已保存模型 →
refreshModels接受savedValue回退 - RAG 冷启动后无法关闭 → 新增停止按钮 + 后端进程树 kill + 端口释放等待
- RAG 停止后轮询仍跳回"运行中" →
_ragManuallyStopped标记保护 - RAG 状态检测被浏览器缓存 → 加
?_=Date.now()cache-buster
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file structured_writer_ldxs-1.0.28-py3-none-any.whl.
File metadata
- Download URL: structured_writer_ldxs-1.0.28-py3-none-any.whl
- Upload date:
- Size: 49.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3ad82200951b725f8ac234bd6ec568f187a7d3eaa3ff8420fa7176da3285f4f3
|
|
| MD5 |
7e60e88002ba15f94748771142faac58
|
|
| BLAKE2b-256 |
18b6b437d71a626cc25329213d1d8e5d80a7f0a17f7b77413fb951e8133a1682
|
Provenance
The following attestation bundles were made for structured_writer_ldxs-1.0.28-py3-none-any.whl:
Publisher:
publish-pypi.yml on Ldxs001/workbuddy-skills
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
structured_writer_ldxs-1.0.28-py3-none-any.whl -
Subject digest:
3ad82200951b725f8ac234bd6ec568f187a7d3eaa3ff8420fa7176da3285f4f3 - Sigstore transparency entry: 2258154388
- Sigstore integration time:
-
Permalink:
Ldxs001/workbuddy-skills@965c6999ca24ab6837bdea29f4202b1c2b4ecb27 -
Branch / Tag:
refs/tags/v1.0.28 - Owner: https://github.com/Ldxs001
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@965c6999ca24ab6837bdea29f4202b1c2b4ecb27 -
Trigger Event:
push
-
Statement type: