Description 背景
在本地使用过程中遇到几类体验和稳定性问题:
/api/polish 在部分 AI 服务返回 { content, usage } 对象时,会把整个对象写入 polished_text,导致 Pydantic 校验失败并返回 500。
已有大纲/角色设定的 AI 优化入口之前直接在前端循环调用润色接口,绕过了统一后台任务系统,因此开始后无法在右下角任务面板查看或取消。
章节管理页导出只能导出整本合并 TXT,无法选择章节范围,也无法按章节拆分导出,不方便上传到第三方写作平台。
章节列表只有搜索,缺少状态/分析/内容/大纲维度筛选。
Gemini 在 promptFeedback.blockReason=PROHIBITED_CONTENT 或空候选返回时,错误信息不够清晰,章节分析容易表现为“秒失败”但原因不明确。
拆书导入时,角色生成容易根据标题或模型推断出原文不存在的人名/组织名;原文为空或 summary 为 None 时也存在兜底摘要不稳的问题。
Docker build 时如果宿主机存在嵌套 node_modules,可能被复制进镜像,造成 esbuild 平台二进制不匹配。
本地补丁实现概述
1. 修复 /api/polish 返回对象导致的 500
涉及文件:
backend/app/api/polish.py
backend/app/schemas/polish.py
backend/app/main.py
实现:
新增 _extract_generated_text(response),兼容 AI 服务返回字符串或 { content, usage } 对象。
PolishRequest.project_id 从 Optional[int] 改为 Optional[str],匹配项目 UUID。
PolishRequest 增加 instruction 字段,用于复用润色接口做“定向优化”。
修正 GenerationHistory 写入字段,使用现有模型字段 generated_content、model。
将 polish router 挂载到主应用:app.include_router(polish.router, prefix="/api")。
2. 已有大纲优化改为统一后台任务
涉及文件:
backend/app/api/polish.py
backend/app/schemas/polish.py
backend/app/services/background_task_service.py
frontend/src/pages/Outline.tsx
frontend/src/services/api.ts
frontend/src/components/FloatingTaskPanel.tsx
实现:
新增 POST /api/polish/outlines/background。
支持传入 outline_ids;为空时可扩展为全项目大纲优化。
后端任务类型为 outline_optimize。
任务逐条处理大纲,解析 AI JSON 输出后更新:
outline.content
outline.structure.summary
outline.structure.content
key_points
key_events
emotion
goal
前端单条“AI优化”和批量“AI优化已有大纲”都改为创建后台任务。
通过 pollTaskUntilComplete 刷新状态与结果。
右下角任务面板新增任务类型显示:大纲优化。
排队中取消的任务会在 worker 开始前被跳过。
3. 角色/组织设定优化
涉及文件:
backend/app/api/polish.py
backend/app/schemas/polish.py
frontend/src/pages/Characters.tsx
frontend/src/services/api.ts
frontend/src/components/FloatingTaskPanel.tsx
实现:
新增 POST /api/polish/characters/background。
后端任务类型为 character_optimize。
支持批量优化选中的角色/组织。
对角色优化字段:
personality
appearance
background
对组织优化字段:
organization_purpose
motto
background
前端“批量优化设定”改为走后台任务流程,可在任务面板查看/取消。
编辑弹窗中增加单个角色/组织的 AI 优化按钮,优化结果先填入表单,由用户检查后保存。
4. 章节管理页筛选和导出增强
涉及文件:
backend/app/api/projects.py
frontend/src/pages/Chapters.tsx
frontend/src/services/api.ts
实现:
GET /api/projects/{project_id}/export 增加查询参数:
start_chapter
end_chapter
split
支持按章节号范围导出。
split=true 时返回 ZIP,每章一个 TXT 文件。
合并导出仍返回单个 TXT。
前端导出按钮改为弹窗:
章节管理页增加筛选:
优化顶部工具区布局,解决搜索框和按钮区域不对齐问题。
5. Gemini 错误处理与章节分析兜底
涉及文件:
backend/app/services/ai_clients/gemini_client.py
backend/app/services/plot_analyzer.py
backend/app/api/chapters.py
实现:
Gemini client 增加:
GeminiResponseError
GeminiPromptBlockedError
promptFeedback.blockReason 检测
空 candidate / 空 parts 检测
finishReason 标准化
usageMetadata 统一转换为 token usage
PlotAnalyzer 增加 last_error,将真实失败原因向外传递。
对不可重试的 Gemini 拦截错误不再盲目重试。
章节分析后台任务在 Gemini 专用模型被拦截时,尝试切换到默认模型兜底。
批量生成中章节分析失败时,将真实 error_message 透传给上层,而不是只显示笼统的“章节分析失败”。
6. 拆书导入稳定性改进
涉及文件:
backend/app/services/book_import_service.py
backend/app/services/txt_parser_service.py
实现:
fallback outline summary 统一走安全方法,避免 None.strip()。
TXT 章节识别增强:
更严格区分强章节标题和弱标题。
减少误把正文短句识别为章节标题。
支持更完整的“第 X 节/章/回/卷/集/部/篇”形式。
拆书导入生成角色/组织时传入原文章节上下文。
角色卡生成要求改为“从原文抽取”,避免模型编造原文不存在的人名、组织名。
增加原文姓名候选抽取与过滤逻辑:
优先保留原文明确出现的名称。
对原文未出现的角色/组织进行过滤。
AI 结果不足时,用原文高频姓名候选构建保守 fallback 角色。
7. Docker build 防宿主依赖污染
涉及文件:
实现:
.dockerignore 增加 **/node_modules/,避免嵌套 node_modules 被复制进镜像。
.gitignore 增加 .playwright-cli/,避免本地浏览器自动化缓存误提交。
验证
本地已验证:
npm run build 通过。
python -m py_compile 覆盖相关后端文件通过。
git diff --check 通过。
Docker 容器热更新后 /health 正常。
OpenAPI 中可见:
/api/polish
/api/polish/outlines/background
/api/polish/characters/background
前端刷新后控制台无新增 error。
本地敏感信息检查没有发现真实 API key、.env、本地路径或项目数据进入拟提交内容。
期望
希望上游考虑合并或参考这些改动,尤其是:
让 AI 优化统一走后台任务系统。
保留明确的错误原因,特别是 Gemini 安全拦截和空响应。
增强章节导出能力,支持范围和分章 ZIP。
拆书导入应尽量从原文抽取角色,避免模型自动补全不存在的设定。
Reactions are currently unavailable
You can’t perform that action at this time.
背景
在本地使用过程中遇到几类体验和稳定性问题:
/api/polish在部分 AI 服务返回{ content, usage }对象时,会把整个对象写入polished_text,导致 Pydantic 校验失败并返回 500。promptFeedback.blockReason=PROHIBITED_CONTENT或空候选返回时,错误信息不够清晰,章节分析容易表现为“秒失败”但原因不明确。node_modules,可能被复制进镜像,造成 esbuild 平台二进制不匹配。本地补丁实现概述
1. 修复
/api/polish返回对象导致的 500涉及文件:
backend/app/api/polish.pybackend/app/schemas/polish.pybackend/app/main.py实现:
_extract_generated_text(response),兼容 AI 服务返回字符串或{ content, usage }对象。PolishRequest.project_id从Optional[int]改为Optional[str],匹配项目 UUID。PolishRequest增加instruction字段,用于复用润色接口做“定向优化”。GenerationHistory写入字段,使用现有模型字段generated_content、model。app.include_router(polish.router, prefix="/api")。2. 已有大纲优化改为统一后台任务
涉及文件:
backend/app/api/polish.pybackend/app/schemas/polish.pybackend/app/services/background_task_service.pyfrontend/src/pages/Outline.tsxfrontend/src/services/api.tsfrontend/src/components/FloatingTaskPanel.tsx实现:
POST /api/polish/outlines/background。outline_ids;为空时可扩展为全项目大纲优化。outline_optimize。outline.contentoutline.structure.summaryoutline.structure.contentkey_pointskey_eventsemotiongoalpollTaskUntilComplete刷新状态与结果。大纲优化。3. 角色/组织设定优化
涉及文件:
backend/app/api/polish.pybackend/app/schemas/polish.pyfrontend/src/pages/Characters.tsxfrontend/src/services/api.tsfrontend/src/components/FloatingTaskPanel.tsx实现:
POST /api/polish/characters/background。character_optimize。personalityappearancebackgroundorganization_purposemottobackground4. 章节管理页筛选和导出增强
涉及文件:
backend/app/api/projects.pyfrontend/src/pages/Chapters.tsxfrontend/src/services/api.ts实现:
GET /api/projects/{project_id}/export增加查询参数:start_chapterend_chaptersplitsplit=true时返回 ZIP,每章一个 TXT 文件。5. Gemini 错误处理与章节分析兜底
涉及文件:
backend/app/services/ai_clients/gemini_client.pybackend/app/services/plot_analyzer.pybackend/app/api/chapters.py实现:
GeminiResponseErrorGeminiPromptBlockedErrorpromptFeedback.blockReason检测finishReason标准化usageMetadata统一转换为 token usagePlotAnalyzer增加last_error,将真实失败原因向外传递。error_message透传给上层,而不是只显示笼统的“章节分析失败”。6. 拆书导入稳定性改进
涉及文件:
backend/app/services/book_import_service.pybackend/app/services/txt_parser_service.py实现:
None.strip()。7. Docker build 防宿主依赖污染
涉及文件:
.dockerignore.gitignore实现:
.dockerignore增加**/node_modules/,避免嵌套 node_modules 被复制进镜像。.gitignore增加.playwright-cli/,避免本地浏览器自动化缓存误提交。验证
本地已验证:
npm run build通过。python -m py_compile覆盖相关后端文件通过。git diff --check通过。/health正常。/api/polish/api/polish/outlines/background/api/polish/characters/background.env、本地路径或项目数据进入拟提交内容。期望
希望上游考虑合并或参考这些改动,尤其是: