12 KiB
AI 写作助手后端接口与 Prompt 协议文档
1. 文档目标
本文档用于指导 AI 写作助手第二阶段升级中的后端开发、接口设计、提示词设计和联调约束。
本轮后端目标不是重做 DeerFlow 的整体架构,而是在保留现有 Python + LangGraph + 线程体系的基础上,新增一套稳定的“选区改写型能力”,服务前端的 Tiptap 写作编辑器。
2. 本轮后端职责
后端负责:
- 接收当前线程信息
- 接收用户选区文本
- 接收改写动作
- 选取必要上下文
- 调用模型生成候选改写结果
- 返回纯净候选文本
后端本轮不负责:
- 直接编辑 Tiptap JSON
- 直接操作前端编辑器选区
- 直接替换前端文档内容
- 做复杂富文本 patch
- 做 tracked changes
3. 设计原则
3.1 纯文本协议优先
首版只让后端处理:
- 选区文本
- 前后文文本
- 动作类型
- 风格参数
不让后端直接理解完整富文本 JSON。
3.2 前端负责应用,后端负责生成
- 前端负责选区获取
- 前端负责候选结果展示
- 前端负责替换 / 插入
- 后端只负责“给出候选文本”
3.3 结果必须可直接落文档
后端输出必须尽量是可直接放回编辑器的正文,不应带解释性前缀,例如:
- “当然可以,以下是润色版本:”
- “我帮你改写如下:”
- “下面是优化后的内容:”
这类内容必须禁止。
4. 推荐接口设计
4.1 主接口
推荐新增统一接口:
POST /api/writing/rewrite
由 action 决定具体重写类型。
4.2 为什么推荐统一接口
因为前端交互是一套统一浮层和统一预览面板,拆成多个接口会导致:
- 前端判断分支增多
- 埋点与异常处理分散
- 后续新增动作不方便扩展
统一接口更适合本轮需求。
5. 请求体定义
建议请求体如下:
{
"threadId": "string",
"documentId": "string",
"selection": {
"from": 120,
"to": 260,
"text": "待改写文本"
},
"action": "polish",
"tone": "professional",
"surroundingContext": {
"before": "选区前文",
"after": "选区后文"
}
}
6. 字段说明
6.1 threadId
用途:
- 关联当前 DeerFlow 线程
- 必要时取线程上下文或会话元数据
6.2 documentId
用途:
- 标识当前右侧文档
- 首版可选
- 如果当前系统还没有独立文档 ID,可先允许为空
6.3 selection.from / selection.to
用途:
- 帮助前后端联调排查
- 首版后端通常不需要真正使用偏移量
- 建议保留,便于日志定位
6.4 selection.text
用途:
- 这是本轮最核心输入
- 后端实际重写的主文本
6.5 action
允许值:
polishexpandshortentone
6.6 tone
仅当 action = tone 时使用。
建议允许值:
professionalcasualreadableacademicexpressive
6.7 surroundingContext.before
用途:
- 提供选区前文
- 帮助模型理解语气、主语、叙事连续性
建议:
- 控制长度
- 不要塞太多无关上下文
6.8 surroundingContext.after
用途:
- 提供选区后文
- 帮助模型在扩写、改语气时与后续内容衔接
7. 返回体定义
建议返回体如下:
{
"output": "AI 改写后的候选文本",
"originalSelection": {
"from": 120,
"to": 260,
"text": "待改写文本"
},
"metadata": {
"action": "polish",
"tone": null,
"model": "your-model-name"
}
}
8. 返回字段要求
8.1 output
必须:
- 只包含候选正文
- 尽量不夹带解释语
- 能直接被前端替换或插入
8.2 originalSelection
作用:
- 前端可以做校验
- 联调时方便确认是针对哪段文本返回的
8.3 metadata
作用:
- 便于埋点
- 便于日志记录
- 便于问题追踪
9. 错误响应规范
建议统一错误结构:
{
"error": {
"code": "WRITING_REWRITE_FAILED",
"message": "rewrite failed"
}
}
建议错误码:
WRITING_REWRITE_FAILEDWRITING_INVALID_ACTIONWRITING_INVALID_TONEWRITING_EMPTY_SELECTIONWRITING_MODEL_UNAVAILABLEWRITING_CONTEXT_TOO_LARGE
10. 动作语义定义
10.1 polish
目标:
- 保持原意
- 改善表达
- 提升通顺度、自然度和可读性
不应:
- 引入新事实
- 改写成完全不同内容
10.2 expand
目标:
- 保持主旨
- 扩充细节
- 增强画面感、解释性或完整度
不应:
- 无限制发散
- 添加明显脱离主题的新内容
10.3 shorten
目标:
- 压缩篇幅
- 保留关键信息
- 减少重复表达
不应:
- 丢失关键论点
- 压缩到语义残缺
10.4 tone
目标:
- 不改变原意
- 调整语言风格
不应:
- 改写事实
- 改写逻辑结构到完全不同
11. Prompt 设计原则
11.1 通用系统约束
所有改写类 prompt 都应包含以下约束:
- 直接输出最终可用正文
- 不输出标题,除非原文本身就是标题改写
- 不输出解释
- 不输出分析过程
- 不输出“以下是结果”之类前缀
- 保持与上下文语气一致
11.2 上下文使用原则
前后文只用于理解,不要求模型重写前后文。
明确告诉模型:
- 只改写选中文本
- 前后文仅用于参考衔接
11.3 长度控制原则
polish:长度与原文接近expand:长度可明显增加,但不要失控shorten:长度明显缩短,但要保留关键信息tone:长度尽量与原文接近
12. Prompt 模板建议
12.1 润色模板
你是一名中文写作编辑助手。
请在不改变原意的前提下,对“选中文本”进行润色,使表达更自然、更流畅、更清晰。
要求:
1. 保留原文事实和核心意思。
2. 不要添加原文没有的新事实。
3. 不要输出解释,不要输出前缀,不要输出分析过程。
4. 直接输出润色后的正文。
前文参考:
{before}
选中文本:
{selection}
后文参考:
{after}
12.2 扩写模板
你是一名中文写作编辑助手。
请在不偏离主题的前提下,对“选中文本”进行扩写,增加必要细节、画面感或补充说明,使内容更充实。
要求:
1. 保持原文主旨不变。
2. 增加内容时要自然,不要跑题。
3. 不要输出解释,不要输出前缀,不要输出分析过程。
4. 直接输出扩写后的正文。
前文参考:
{before}
选中文本:
{selection}
后文参考:
{after}
12.3 缩写模板
你是一名中文写作编辑助手。
请在保留关键信息和原意的前提下,对“选中文本”进行缩写,使其更精炼。
要求:
1. 不要丢掉核心信息。
2. 去掉重复、冗余和拖沓表达。
3. 不要输出解释,不要输出前缀,不要输出分析过程。
4. 直接输出缩写后的正文。
前文参考:
{before}
选中文本:
{selection}
后文参考:
{after}
12.4 改语气模板
你是一名中文写作编辑助手。
请在不改变原意和事实的前提下,把“选中文本”改写成更{tone_label}的表达方式。
要求:
1. 保持原文信息不变。
2. 只调整表达风格,不改变事实和逻辑。
3. 不要输出解释,不要输出前缀,不要输出分析过程。
4. 直接输出改写后的正文。
前文参考:
{before}
选中文本:
{selection}
后文参考:
{after}
13. Tone 映射建议
建议前端传标准值,后端映射中文标签:
professional-> 专业、正式casual-> 口语化、轻松自然readable-> 更易读、更清晰academic-> 学术、严谨expressive-> 更有文采、更有表现力
14. 上下文截取策略
14.1 推荐策略
前端传:
- 选区前固定长度文本
- 选区后固定长度文本
例如:
- 前文 200 到 500 字
- 后文 200 到 500 字
原因
- 足够帮助模型理解文气和衔接
- 不会让请求太重
14.2 不建议
- 把整篇长文全量塞进去
- 把整个线程消息都塞进改写接口
如果后端确实要参考线程上下文,也建议只取最近和写作相关的少量消息摘要。
15. LangGraph 接入建议
15.1 推荐接入方式
在现有 LangGraph / gateway 架构中新增一个写作改写专用入口。
建议二选一:
方案 A
新增专用 router:
POST /api/writing/rewrite
内部调用现有模型层 / agent 层。
方案 B
新增专用 graph node 或 tool:
rewrite_selection
再由 router 调用该能力。
15.2 更推荐方案
推荐:
- 对外暴露统一 router
- 内部走已有模型封装或 LangGraph 节点
这样前端接口更稳定,后续后端内部重构不会影响前端。
16. 后端模块拆解
16.1 模块 A:接口层
负责:
- 请求校验
- 错误响应
- 参数标准化
需要完成:
- 统一 rewrite API
- action / tone 校验
- 空选区校验
16.2 模块 B:上下文拼装层
负责:
- 拼装 before / selection / after
- 必要时提取线程相关信息
需要完成:
- 上下文长度控制
- 清洗空白和异常字符
16.3 模块 C:Prompt 层
负责:
- 选择模板
- 填充 action 和 tone
需要完成:
- 4 类动作模板
- tone 映射
16.4 模块 D:模型调用层
负责:
- 走现有模型配置体系
- 执行大模型请求
需要完成:
- 统一调用入口
- 模型不可用错误处理
16.5 模块 E:结果清洗层
负责:
- 去掉解释性前缀
- 去掉多余包裹
- 标准化返回
需要完成:
- 输出清洗
- metadata 填充
17. 返回结果清洗建议
即使 prompt 已经约束,模型仍可能输出:
- “以下是润色后的内容:”
- “当然,这里是改写结果:”
- “优化如下:”
建议后端加一层轻量清洗:
- 去掉常见说明性前缀
- 去掉包裹性 markdown 代码块
- 去掉多余首尾空白
注意:
- 清洗必须保守
- 不要误删正文
18. 日志与观测建议
建议记录:
threadIddocumentIdactiontoneselection_lengthbefore_lengthafter_lengthmodel_namelatency_mssuccess / fail
不要直接把整段用户正文原文打到普通日志里,避免敏感信息风险。
19. 后端测试清单
19.1 单元测试
- action 校验
- tone 校验
- 空选区校验
- prompt 选择逻辑
- 输出清洗逻辑
19.2 集成测试
polishexpandshortentone-professionaltone-casualtone-readabletone-academictone-expressive
19.3 边界测试
- 选区过短
- 选区过长
- 前后文为空
- 多段文本带换行
- 模型超时
- 模型不可用
20. 联调约束
20.1 前后端必须统一
action枚举值tone枚举值- 错误码
- 返回体字段名
20.2 联调重点
- 多段落文本中换行保留是否正确
- AI 返回内容是否适合直接落文档
- 超时和失败时前端是否能优雅重试
20.3 联调建议顺序
- 先 mock 返回固定文本
- 再接真实模型
- 先验证单段落
- 再验证多段落
- 最后验证大段文本
21. 优先级建议
P0
- 统一 rewrite API
- 4 类动作支持
- 输出纯净正文
- 错误结构标准化
P1
- 输出清洗增强
- 埋点与日志
- 上下文截断策略优化
P2
- 更细粒度风格控制
- 结果质量二次校验
22. 完成定义
后端满足以下条件即可视为本轮完成:
- 前端能通过统一接口发起改写
- 4 类动作均可稳定返回候选文本
- 返回文本基本可直接用于替换或插入
- 多段落文本能稳定处理
- 错误结构规范统一
23. 结论
本轮后端最重要的,不是做复杂文档结构编辑,而是把“选区改写”做成稳定、可预测、可直接接入前端编辑器的能力。
最稳妥的路线是:
- 统一接口
- 统一动作枚举
- 统一 prompt 模板
- 统一错误结构
- 统一输出约束
只要这层做稳,前端的 Tiptap 写作编辑器就能很顺畅地完成豆包式“选中即改、预览后应用”的核心体验。