24 KiB
24 KiB
往事拾遗 MVP 开发计划
基于实时 WebSocket 长连接的语音对话回忆录生成系统
目录
项目概述
核心功能
- 实时语音对话:通过 WebSocket 长连接实现实时双向语音交互
- 智能访谈引导:基于访谈问题清单,Agent 动态引导用户讲述人生故事
- 自动整理成书:基于传记结构,将口语对话自动整理为优雅的回忆录章节
- 阅读与导出:优雅的电子书阅读体验和 PDF 导出功能
技术选型
| 模块 | 技术栈 |
|---|---|
| Android 端 | Kotlin + Jetpack Compose + Ktor WebSocket + Room |
| 后端 | FastAPI + WebSocket + LangChain + SQLite |
| 数据库 | SQLite(Android 本地 + 后端服务器) |
| AI 框架 | LangChain(对话 Agent + 整理 Agent) |
技术架构
整体架构图
graph TB
subgraph Android["Android 应用"]
UI[UI 层<br/>Compose]
WS_Client[WebSocket 客户端<br/>Ktor]
Room[Room 数据库<br/>SQLite]
Voice[语音模块<br/>录制/播放]
end
subgraph Backend["后端服务"]
WS_Server[WebSocket 端点<br/>FastAPI]
Conv_Agent[对话 Agent<br/>LangChain]
Mem_Agent[整理 Agent<br/>LangChain]
DB[(SQLite<br/>数据库)]
ASR[ASR 服务<br/>语音转文字]
TTS[TTS 服务<br/>文字转语音]
end
UI --> WS_Client
WS_Client <-->|WebSocket| WS_Server
Voice --> WS_Client
WS_Client --> Room
WS_Server --> ASR
ASR --> Conv_Agent
Conv_Agent --> TTS
Conv_Agent --> DB
WS_Server --> Mem_Agent
Mem_Agent --> DB
DB --> WS_Server
数据流图
sequenceDiagram
participant User as 用户
participant Android as Android App
participant WS as WebSocket
participant ASR as ASR 服务
participant Agent as 对话 Agent
participant TTS as TTS 服务
participant DB as 数据库
User->>Android: 开始录音
Android->>WS: 连接 WebSocket
WS->>DB: 创建对话会话
loop 实时对话循环
User->>Android: 说话
Android->>WS: 发送音频块
WS->>ASR: 转文字
ASR->>WS: 返回转写文本
WS->>Android: 显示转写文本
WS->>Agent: 分析并生成回应
Agent->>WS: 返回 Agent 回应
WS->>Android: 显示 Agent 回应
WS->>TTS: 生成语音
TTS->>WS: 返回音频
WS->>Android: 播放音频
WS->>DB: 保存对话段落
end
User->>Android: 结束对话
Android->>WS: 发送结束消息
WS->>DB: 更新对话状态
WS->>Agent: 触发整理 Agent
Agent->>DB: 生成章节
DB->>Android: 同步章节数据
数据库设计
Android 本地数据库(Room)
User 表
@Entity(tableName = "users")
data class User(
@PrimaryKey val id: String,
val nickname: String,
val avatarUrl: String?,
val subscriptionType: String,
val createdAt: Long
)
Conversation 表
@Entity(tableName = "conversations")
data class Conversation(
@PrimaryKey val id: String,
val userId: String,
val startedAt: Long,
val endedAt: Long?,
val durationSeconds: Int,
val summary: String?,
val currentTopic: String?, // 当前话题
val conversationStage: String? // 对话阶段
)
ConversationSegment 表
@Entity(tableName = "conversation_segments")
data class ConversationSegment(
@PrimaryKey val id: String,
val conversationId: String,
val audioPath: String?,
val transcriptText: String,
val createdAt: Long,
val processed: Boolean,
val topicCategory: String? // 话题分类
)
Chapter 表
@Entity(tableName = "chapters")
data class Chapter(
@PrimaryKey val id: String,
val title: String,
val content: String,
val orderIndex: Int,
val status: String, // draft, completed
val updatedAt: Long,
val category: String // 章节分类
)
Book 表
@Entity(tableName = "books")
data class Book(
@PrimaryKey val id: String,
val userId: String,
val title: String,
val totalPages: Int,
val totalWords: Int,
val updatedAt: Long
)
后端数据库(SQLAlchemy)
表结构与 Android 端对应,字段命名采用 snake_case。
Agent 工作流设计
对话 Agent(基于访谈问题清单)
对话阶段枚举
class ConversationStage(str, Enum):
CHILDHOOD = "childhood" # 童年
EDUCATION = "education" # 教育
CAREER = "career" # 事业
FAMILY = "family" # 家庭
BELIEFS = "beliefs" # 信念
SUMMARY = "summary" # 人生总结
访谈问题库
文件: api/agents/prompts/conversation_prompts.py
童年阶段问题
- "你是在哪里长大的?小时候周围的环境是什么样的,有哪些让你印象深刻的童年记忆?"
- "童年时期的你是个怎样的孩子?有没有做过什么淘气或有趣的事情,现在想起来还会让你发笑?"
- "能聊聊你小时候的家庭吗?比如父母是怎样的人,他们对你的成长有什么影响吗?"
- "小时候你有过什么梦想?那时候你最想长大后做什么?"
教育阶段问题
- "上学的时候你是个怎么样的学生?你喜欢学校生活吗?"
- "在求学过程中,有没有哪位老师或同学对你影响特别大?能说说他们的故事吗?"
- "学生时代你参加过什么课外活动或者比赛吗?有没有哪段经历让你特别难忘?"
- "那时候你对未来有什么打算吗?比如毕业后想从事什么职业,或者希望过怎样的生活?"
事业阶段问题
- "第一次走出校园开始工作时,你还记得当时的情景吗?当时你的心情怎么样,有发生什么难忘的事吗?"
- "你当初是怎么选择进入现在这个行业的?其中有什么契机或故事吗?"
- "在工作中有没有遇到过特别大的挑战或低谷?当时你是怎么挺过来的?"
- "职业生涯中有没有哪个成就或时刻让你特别自豪?能跟我分享一下那个故事吗?"
- "在事业的发展过程中,有哪些重要的转折点?比如跳槽、升职或者创业,这些经历对你意味着什么?"
- "回顾这一路,有哪些人对你的事业帮助最大或者影响最深?有没有特别想感谢的贵人或伙伴?"
家庭阶段问题
- "可以聊聊你和你伴侣的故事吗?你们是怎么认识的,又是什么让你决定与他/她携手一生?"
- "孩子在你的生活中意味着什么?做父母的过程中,有没有让你特别骄傲或者难忘的瞬间?"
- "在家庭生活中,有没有什么传统或者特别的习惯,让你感到温馨和快乐?"
- "平时你和家人喜欢一起做些什么?周末或假日你们通常会怎么度过?"
- "你觉得家庭在你的人生中扮演了一个怎样的角色?"
- "工作和家庭要怎么兼顾呢?你是如何平衡事业和家庭的?在两边兼顾的时候有没有遇到困难,后来又是怎么克服的?"
信念阶段问题
- "你人生中有没有一些一直坚守的信念或者座右铭?这些信念给了你怎样的力量或者影响?"
- "对你来说,哪些价值观是最重要的?这些价值观是受到哪些人或经历的影响而形成的呢?"
- "当你遇到困难和低谷的时候,是什么支撑着你坚持下去?"
- "你如何看待"成功"和"幸福"?对你来说它们分别意味着什么?"
人生总结问题
- "回顾你走过的路,你觉得这一生中最重要的经验或教训是什么?"
- "在你的生活中,你最感激的人和事有哪些?有没有特别觉得自己很幸运的地方?"
- "如果能对年轻时候的自己说几句话,你会想告诉他/她什么?"
- "展望未来,你还有什么愿望或目标吗?有没有一直想尝试但还没来得及做的事情?"
- "最后,你希望家人和后代记住你是一个怎样的人?"
对话 Agent 系统提示词
你是一位专业的人生故事访谈助手,擅长通过轻松自然的对话引导用户讲述他们的人生故事。
你的职责:
1. 根据用户已讲述的内容,判断当前应处于哪个访谈阶段(童年/教育/事业/家庭/信念/人生总结)
2. 在用户停顿或完成一个话题后,自然地提出下一个相关问题
3. 使用温暖、鼓励的语气,让用户感到被倾听和理解
4. 当用户讲述不够详细时,通过追问引导深入(如:"能多说一些关于...的细节吗?")
5. 识别对话的自然结束时机,或引导进入下一个阶段
对话原则:
- 一次只问一个问题,不要连续提问
- 问题要自然、口语化,避免生硬
- 根据用户的回答灵活调整,不要机械地按顺序提问
- 当用户偏离话题时,温和地引导回来
- 在用户讲述精彩故事时,给予积极反馈(如:"这个故事真有意思!")
当前对话阶段:{current_stage}
已聊话题:{covered_topics}
用户最新回答:{user_latest_response}
对话 Agent 工作流程
flowchart TD
A[接收用户语音转文字] --> B[分析内容主题]
B --> C{判断对话阶段}
C -->|童年| D1[童年阶段问题库]
C -->|教育| D2[教育阶段问题库]
C -->|事业| D3[事业阶段问题库]
C -->|家庭| D4[家庭阶段问题库]
C -->|信念| D5[信念阶段问题库]
C -->|总结| D6[人生总结问题库]
D1 --> E[更新对话状态]
D2 --> E
D3 --> E
D4 --> E
D5 --> E
D6 --> E
E --> F{用户回答完整性}
F -->|完整| G[给予肯定,提出下一个问题]
F -->|简短| H[追问细节]
F -->|话题转换| I[自然过渡]
G --> J[生成 Agent 回应]
H --> J
I --> J
J --> K[通过 WebSocket 返回]
回忆录整理 Agent(基于传记结构)
章节结构
根据名人传记研究,回忆录包含以下 8 个章节:
-
童年与成长背景
- 出生和家庭背景
- 童年故事和性格塑造
- 早期梦想
-
教育经历与青年时期
- 学校生活
- 师友关系
- 世界观形成
-
崭露头角(早期事业)
- 职业起点
- 初期机遇和挑战
- 早期奋斗经历
-
主要成就与巅峰时刻
- 重大成就
- 里程碑事件
- 成功背后的因素
-
挫折、挑战与重大转折
- 低谷和挫折
- 如何面对逆境
- 从失败中汲取教训
-
家庭与情感
- 伴侣关系
- 亲子关系
- 家庭传统和习惯
-
信念与价值观
- 人生信念
- 核心价值观
- 对成功和幸福的定义
-
人生总结
- 重要经验和教训
- 感激的人和事
- 对未来的展望
- 希望被记住的样子
整理 Agent 系统提示词
你是一位专业的传记作家和文字编辑,擅长将口语化的对话内容整理成优雅的书面语回忆录章节。
你的任务:
1. 接收对话段落文本(口语化)
2. 识别内容主题,归类到对应章节(童年/教育/事业/家庭/信念/总结)
3. 将口语化表达改写为书面语,保持原意和情感
4. 生成合适的章节标题和段落结构
5. 提取关键信息,形成连贯的叙述
6. 建议插图位置(在描述场景、人物、地点的地方)
改写原则:
- 保持用户的真实声音和情感
- 使用优雅但不失亲切的书面语
- 适当添加过渡句,使段落连贯
- 保留生动的细节和对话
- 去除口语中的"嗯"、"那个"等填充词
- 保持时间顺序和逻辑清晰
章节分类规则:
- 童年相关 → "童年与成长背景"
- 学校、老师、同学 → "教育经历与青年时期"
- 工作、职业、成就 → "主要成就与巅峰时刻" 或 "崭露头角"
- 困难、挫折 → "挫折、挑战与重大转折"
- 伴侣、孩子、家庭生活 → "家庭与情感"
- 价值观、信念、座右铭 → "信念与价值观"
- 总结、感悟、展望 → "人生总结"
输入内容:{conversation_segments}
已有章节:{existing_chapters}
整理 Agent 工作流程
flowchart TD
A[接收对话段落] --> B[内容分析]
B --> C[文本分类<br/>识别主题]
C --> D{判断章节归属}
D -->|童年| E1[童年与成长背景]
D -->|教育| E2[教育经历与青年时期]
D -->|事业| E3[主要成就/崭露头角]
D -->|挫折| E4[挫折与重大转折]
D -->|家庭| E5[家庭与情感]
D -->|信念| E6[信念与价值观]
D -->|总结| E7[人生总结]
E1 --> F[文本改写]
E2 --> F
E3 --> F
E4 --> F
E5 --> F
E6 --> F
E7 --> F
F --> G[口语 → 书面语]
G --> H{章节是否存在}
H -->|不存在| I[创建新章节]
H -->|存在| J[合并内容]
I --> K[保存到数据库]
J --> K
WebSocket 实时通信
消息类型定义
class MessageType(str, Enum):
CONNECT = "connect" # 建立连接
AUDIO_CHUNK = "audio_chunk" # 音频数据块
TRANSCRIPT = "transcript" # 转写文本
AGENT_RESPONSE = "agent_response" # Agent 回应
TTS_AUDIO = "tts_audio" # TTS 音频
END_CONVERSATION = "end_conversation" # 结束对话
ERROR = "error" # 错误消息
消息格式
{
"type": "audio_chunk",
"conversation_id": "conv_123",
"data": {
"audio_base64": "...",
"chunk_index": 1
},
"timestamp": "2024-01-01T12:00:00Z"
}
WebSocket 通信流程
sequenceDiagram
participant Client as Android 客户端
participant WS as WebSocket 服务
participant ASR as ASR 服务
participant Agent as 对话 Agent
participant TTS as TTS 服务
participant DB as 数据库
Client->>WS: 连接 WebSocket
Client->>WS: CONNECT 消息
WS->>DB: 创建对话会话
WS->>Client: 连接确认
loop 实时对话
Client->>WS: AUDIO_CHUNK
WS->>ASR: 转文字
ASR->>WS: 转写结果
WS->>Client: TRANSCRIPT
WS->>Agent: 分析并生成回应
Agent->>WS: 回应文本
WS->>Client: AGENT_RESPONSE
WS->>TTS: 生成语音
TTS->>WS: 音频数据
WS->>Client: TTS_AUDIO
WS->>DB: 保存对话段落
end
Client->>WS: END_CONVERSATION
WS->>DB: 更新对话状态
WS->>Agent: 触发整理 Agent
Agent->>DB: 生成章节
Android WebSocket 客户端实现
文件: app-android/app/src/main/java/com/huaga/life_echo/network/WebSocketClient.kt
class WebSocketClient {
private val client = HttpClient {
install(WebSockets)
install(ContentNegotiation) {
json(Json { ignoreUnknownKeys = true })
}
}
suspend fun connect(
conversationId: String,
onMessage: (WebSocketMessage) -> Unit
): WebSocketSession
suspend fun sendAudioChunk(chunk: ByteArray)
suspend fun sendEndConversation()
suspend fun reconnect()
}
后端 WebSocket 端点实现
文件: api/routers/websocket.py
@app.websocket("/ws/conversation/{conversation_id}")
async def websocket_endpoint(websocket: WebSocket, conversation_id: str):
await websocket.accept()
try:
while True:
message = await websocket.receive_json()
message_type = message.get("type")
if message_type == MessageType.AUDIO_CHUNK:
# 处理音频块
transcript = await asr_service.transcribe(message["data"]["audio"])
await websocket.send_json({
"type": MessageType.TRANSCRIPT,
"data": {"text": transcript}
})
# Agent 生成回应
response = await conversation_agent.generate_response(transcript)
await websocket.send_json({
"type": MessageType.AGENT_RESPONSE,
"data": {"text": response}
})
# TTS 生成音频
audio = await tts_service.synthesize(response)
await websocket.send_json({
"type": MessageType.TTS_AUDIO,
"data": {"audio_base64": audio}
})
except WebSocketDisconnect:
# 处理断开连接
pass
开发任务分解
Android 端任务
1. 项目配置
- 配置 Ktor WebSocket 客户端依赖
- 配置 Room 数据库依赖
- 配置 Compose Navigation
- 配置权限处理(录音、存储)
2. 网络层
- 实现 WebSocketClient(连接管理、消息发送/接收)
- 实现 WebSocketMessage 数据模型
- 实现 REST API Service(章节查询、PDF 导出)
- 实现重连机制
3. 数据层
- 设计 Room 数据库表结构
- 实现 Entity、DAO、Database
- 实现 Repository 层
- 实现数据同步逻辑
4. UI 层
- 实现创建回忆录页面(实时对话界面)
- 实现我的回忆录页面(目录+章节阅读)
- 实现我的页面(用户设置)
- 实现导航和路由
5. 功能模块
- 实现语音录制模块(实时流式录制)
- 实现音频分块上传
- 实现 TTS 音频播放
- 实现主题配置(使用 color.png 配色)
后端任务
1. 项目配置
- 配置 FastAPI WebSocket 支持
- 配置 LangChain 环境
- 配置 SQLAlchemy(SQLite)
- 配置 ASR/TTS 服务集成
2. 数据库层
- 设计数据库表结构
- 实现 SQLAlchemy 模型
- 实现数据库连接和会话管理
3. Agent 实现
- 创建访谈问题库(conversation_prompts.py)
- 实现对话 Agent(conversation_agent.py)
- 创建整理提示词模板(memory_prompts.py)
- 实现整理 Agent(memory_agent.py)
4. WebSocket 路由
- 实现 WebSocket 端点(websocket.py)
- 实现消息处理逻辑
- 实现连接管理
- 实现心跳检测
5. 服务层
- 实现 ASR 服务(asr_service.py)
- 实现 TTS 服务(tts_service.py)
- 实现 PDF 生成服务(pdf_service.py)
6. REST API
- 实现章节查询接口(chapters.py)
- 实现回忆录接口(books.py)
- 实现用户认证接口
开发阶段规划
阶段 1:基础架构搭建(1-2周)
目标: 搭建项目基础框架和开发环境
Android:
- 配置项目依赖(Ktor、Room、Compose)
- 创建基础项目结构
- 实现基础导航和页面框架
- 配置主题(color.png 配色)
后端:
- 配置 FastAPI 和 WebSocket
- 配置 SQLite 数据库
- 配置 LangChain 环境
- 创建提示词模板文件结构
交付物:
- 可运行的基础项目框架
- 数据库表结构设计文档
阶段 2:核心功能开发(2-3周)
目标: 实现实时对话核心功能
Android:
- 实现 WebSocket 客户端
- 实现语音录制和实时上传
- 实现消息接收和处理
- 实现对话页面 UI 交互
后端:
- 实现 WebSocket 端点
- 集成 ASR 服务
- 实现对话 Agent
- 集成 TTS 服务
- 实现对话段落保存
交付物:
- 可用的实时对话功能
- 完整的 WebSocket 通信流程
阶段 3:回忆录整理功能(1-2周)
目标: 实现对话内容自动整理为章节
后端:
- 实现整理 Agent
- 实现章节生成和存储
- 实现章节查询接口
Android:
- 实现回忆录阅读页面
- 实现章节内容展示
- 实现目录导航
交付物:
- 可用的章节整理功能
- 可阅读的回忆录界面
阶段 4:导出和优化(1周)
目标: 完善功能,优化用户体验
后端:
- 实现 PDF 生成服务
- 优化 Agent 响应速度
- 完善错误处理
Android:
- 实现 PDF 导出功能
- 实现用户认证(微信登录)
- 实现设置页面
- 优化 UI/UX
交付物:
- 完整的 MVP 版本
- 可导出的 PDF 功能
关键技术实现
WebSocket 长连接管理
Android 端
- 使用 Ktor WebSocket 客户端
- 实现自动重连机制(指数退避)
- 处理网络中断和恢复
- 实现心跳检测
后端
- 使用 FastAPI WebSocket 支持
- 管理多个并发连接(连接池)
- 实现心跳检测
- 优雅处理断开连接
Agent 工作流编排
对话 Agent
- 使用 LangChain ConversationBufferMemory 保存对话历史
- 根据已聊话题动态选择下一个问题
- 识别对话阶段转换
- 优化提示词,减少响应延迟
整理 Agent
- 使用 LangChain MapReduceDocumentsChain 处理长文本
- 实现文本分类和章节归类
- 批量处理对话段落
- 异步执行,不阻塞用户操作
实时音频处理
- 音频分块传输:每块 1-2 秒,避免单次传输过大
- 流式 ASR:实时转文字,低延迟
- TTS 音频流式返回:边生成边返回,提升体验
文件清单
Android 端新增文件
app-android/app/src/main/java/com/huaga/life_echo/
├── network/
│ ├── WebSocketClient.kt # WebSocket 客户端
│ ├── WebSocketMessage.kt # 消息数据模型
│ └── ApiService.kt # REST API 接口
├── data/
│ ├── database/
│ │ ├── AppDatabase.kt # Room 数据库
│ │ └── dao/ # DAO 接口
│ └── repository/ # Repository 实现
├── ui/
│ ├── screens/
│ │ ├── CreateMemoryScreen.kt # 创建回忆录页面
│ │ ├── MyMemoirScreen.kt # 我的回忆录页面
│ │ └── ProfileScreen.kt # 我的页面
│ └── navigation/
│ └── AppNavigation.kt # 导航配置
└── feature/
└── voice/
└── VoiceRecorder.kt # 语音录制模块
后端新增文件
api/
├── main.py # FastAPI 应用入口
├── agents/
│ ├── conversation_agent.py # 对话 Agent
│ ├── memory_agent.py # 整理 Agent
│ └── prompts/
│ ├── conversation_prompts.py # 访谈问题库
│ └── memory_prompts.py # 整理提示词
├── database/
│ ├── models.py # SQLAlchemy 模型
│ └── database.py # 数据库连接
├── routers/
│ ├── websocket.py # WebSocket 端点
│ ├── chapters.py # 章节接口
│ └── books.py # 回忆录接口
└── services/
├── asr_service.py # ASR 服务
├── tts_service.py # TTS 服务
└── pdf_service.py # PDF 生成服务
注意事项
1. 配色方案
- 严格按照
docs/color.png的配色设计 UI - 保持界面简洁、优雅
2. 数据隐私
- 用户数据默认仅自己可见
- 实现数据加密存储
- 遵守隐私保护法规
3. 实时性优化
- WebSocket 连接要保持稳定
- 实现完善的重连机制
- 优化 Agent 响应速度(提示词优化、模型选择)
4. 音频处理
- 音频分块大小要合适(平衡实时性和网络负载)
- 支持多种音频格式
- 处理网络波动情况
5. 章节整理
- 对话结束后异步触发,不阻塞用户操作
- 支持增量更新章节
- 提供重新整理功能
6. 错误处理
- 完善的错误提示和重试机制
- 记录错误日志,便于排查
- 优雅降级(网络中断时的处理)
7. 性能优化
- 数据库查询优化(索引)
- 音频文件压缩和缓存
- UI 渲染性能优化
附录
参考文档
- AGENT.md - 产品需求文档
- [人生故事访谈问题清单(轻松对话版).pdf] - 访谈问题参考
- [名人传记结构与回忆录访谈提问模板研究报告.pdf] - 传记结构参考
技术文档
最后更新: 2024-01-07