# SpeakMind AI · 方案评估与技术路线 > 评估日期:2026-08-08 > 评估对象:SpeakMind AI 个人表达能力增强智能体 > 评估人:小小叶 🍃 --- ## 目录 1. [方案总体评价](#1-方案总体评价) 2. [四个致命问题](#2-四个致命问题) 3. [服务器资源现状(硬约束)](#3-服务器资源现状硬约束) 4. [最终技术栈选型](#4-最终技术栈选型) 5. [修正后的技术路线](#5-修正后的技术路线) 6. [数据库设计](#6-数据库设计) 7. [评分系统设计(核心难点)](#7-评分系统设计核心难点) 8. [语音模块设计](#8-语音模块设计) 9. [成本估算](#9-成本估算) 10. [第一周可执行任务清单](#10-第一周可执行任务清单) 11. [简历与学术包装](#11-简历与学术包装) --- ## 1. 方案总体评价 ### 综合评分:**7.5 / 10** | 维度 | 评分 | 说明 | |---|---|---| | 问题定义 | ⭐⭐⭐⭐⭐ | 真实需求,你自己就是用户,保研面试/答辩马上要用 | | 技术路线顺序 | ⭐⭐⭐⭐⭐ | 「不要从训练模型开始」这句话价值千金,方向完全正确 | | 差异化定位 | ⭐⭐⭐⭐ | 「长期记忆 + 个人画像」是真差异点,市面工具基本无状态 | | 技术选型合理性 | ⭐⭐⭐ | 有过度设计(Chroma、本地 7B 模型),需要砍 | | 评估体系可行性 | ⭐⭐ | **最大短板**,绝对分数会毁掉核心卖点 | | 落地可执行性 | ⭐⭐⭐ | 阶段划分合理,但 7 天 MVP 范围偏大 | ### 一句话结论 **方向对、顺序对、定位对;但评分体系设计有致命缺陷,且技术栈存在明显过度设计。砍掉一半组件,把评分做扎实,这个项目就成立。** --- ## 2. 四个致命问题 ### 🔴 问题 1:LLM 绝对打分不可信 —— 会直接毁掉核心卖点 **你的原方案:** ``` 逻辑评分: 85 专业评分: 90 表达评分: 75 ``` **为什么这是致命的:** | 现象 | 后果 | |---|---| | **方差大** — 同一段话跑两次,分数差 5-15 分很常见 | 用户看到「昨天 85 今天 78」,会怀疑系统瞎打分,而不是自己退步 | | **中心化倾向** — LLM 极少给 40 分或 98 分,绝大多数落在 70-90 | 分数区分度低,进步曲线看不出来 | | **长度偏见** — 回答越长分数越高 | 用户会学会「废话变多」而不是「表达变好」,训练目标被带偏 | | **无锚点** — 85 分是相对谁? | 无法解释,用户不服气 | > ⚠️ 你的核心卖点是「长期追踪进步」。如果分数本身不稳,这个卖点不存在。 **解决方案(三层,按可靠性排序):** **① 结构化 Checklist(最稳,MVP 必做)** 不让 LLM 打分,只让它做**二元判断**: ```json { "structure": { "has_claim": {"value": true, "evidence": "开头说明了研究动机"}, "has_reason": {"value": true, "evidence": "解释了为何选对比学习"}, "has_evidence": {"value": false, "evidence": "未给出具体数据"}, "has_conclusion": {"value": false, "evidence": "结尾突然结束"} }, "star": { "situation": true, "task": true, "action": true, "result": false } } ``` 二元判断的一致性远高于打分。**分数 = checklist 通过率**,可复现、可解释。 **② Pairwise 对比(追踪进步用)** 不问「这次多少分」,而问「这次 vs 上次最佳版本,哪个更好」: ``` A: <上次最佳回答> B: <本次回答> 问:哪个在「逻辑结构」上更好?只回答 A 或 B,并给一句理由。 ``` 再用 Elo / Bradley-Terry 算法把两两比较结果转成一个稳定评分。这是 LLM-as-Judge 的标准做法,方差远小于绝对打分。 **③ 客观指标(零 LLM,完全确定性)** 这些直接用代码算,不经过模型: | 指标 | 计算方式 | |---|---| | 填充词密度 | 「呃/那个/然后/就是/其实」出现次数 / 总字数 | | 平均句长 | 总字数 / 句子数(按。!?切分)| | 最长句长 | 用于检测「一句话说太长」| | 词汇丰富度 | TTR = 不同词数 / 总词数(jieba 分词后)| | 语速 | 总字数 / 音频时长(仅语音模式)| | 停顿次数 | VAD 检测静音段(仅语音模式)| > 💡 **客观指标是最可信的进步证据**。「你的『然后』从每百字 4.2 个降到 1.1 个」——这句话没人会质疑。 **MVP 评估体系 = ① Checklist + ③ 客观指标;第二阶段再加 ② Pairwise。** --- ### 🔴 问题 2:Chroma 向量库是伪需求 —— MVP 阶段直接砍掉 **你的原用途:** 检索「用户之前的最佳项目介绍版本」。 **为什么不需要:** ``` 一天练 3 次 × 30 天 = 90 条记录 一年 = 约 1000 条 ``` 1000 条数据用 `SELECT ... WHERE topic = ? ORDER BY score DESC LIMIT 1` 就解决了。上向量库是**用大炮打蚊子**,还引入了: - 额外依赖(chromadb + onnxruntime,装包 ~500MB) - 内存占用(你服务器只有 1.9GB,见第 3 节) - embedding 调用成本 - 一整套需要维护的索引同步逻辑 **MVP 方案:SQLite + FTS5** 已在你服务器上验证可用(SQLite 3.51.1,FTS5 已启用): ```sql CREATE VIRTUAL TABLE answer_fts USING fts5( answer_text, content='training_history', content_rowid='id' ); -- 中文需要配合 jieba 预分词后再入库 ``` **RAG 真正该用在哪里(第三阶段):** 不是检索用户自己,而是**引入外部标准**: | 语料库 | 用途 | |---|---| | 优秀 TED / 学术报告转录文本 | 给 AI 一个「好表达长什么样」的参照 | | STAR / SCQA / 金字塔原理范例 | 结构化改写的模板来源 | | 目标岗位 JD / 导师研究方向 | 让反馈贴合具体场景(例:面向程老师的 Agent 安全方向) | | 常见面试题库 + 高分答案 | 模拟面试的题目和评判基准 | **这时候 RAG 从「检索历史」变成「引入知识」,才有存在价值。** --- ### 🔴 问题 3:语音模块被低估了 —— 应该提前,但要砍功能 **矛盾点:** - 你把语音放**第三阶段**,只写了「语速、停顿、重复词」→ **价值被低估** - 但实际实现难度 → **被低估** **为什么语音是你最大的差异化机会:** > 文字表达分析工具满地都是(ChatGPT 直接就能做)。 > 但「你刚才 3 分钟说了 14 个『然后』,最长一次卡了 4.2 秒」——**这是文字版永远给不了的**,也是用户最有体感、最服气的反馈。 **实现难点(原方案没提到):** | 难点 | 说明 | 解法 | |---|---|---| | 词级时间戳 | Whisper 默认只给 segment 级 | 开 `word_timestamps=True`;中文准确度一般,需容忍误差 | | 停顿检测 | ASR 不直接输出静音时长 | 用 `silero-vad` 或 ffmpeg `silencedetect` 滤波器 | | 语速定义 | 中文按「字/分钟」还是「音节/分钟」 | 建议**字/分钟**,中文正常语速约 200-260 字/分 | | 填充词识别 | Whisper 会「美化」掉「呃」「嗯」 | 关闭 `condition_on_previous_text`;或用带 disfluency 的模型 | | **算力** | ⚠️ 见第 3 节 | **服务器跑不了,必须走 API 或本地机器** | **建议:提前到第二阶段,只做三个硬指标** 1. **语速**(字/分钟) 2. **填充词频次**(每百字) 3. **最长停顿 + 停顿次数** 这三个用「ASR 文本 + ffmpeg silencedetect」就能算,不需要词级时间戳,实现难度骤降,但用户体感极强。 --- ### 🟡 问题 4:LoRA 微调 —— 别写「计划做」,要写「架构预留」 **数据量现实检查:** | 微调方式 | 最低数据量 | 你能攒多久 | |---|---|---| | SFT(指令微调) | 500-1000 条高质量样本 | 一天 3 条 → **约 1 年** | | DPO / 偏好学习 | 2000+ 偏好对 | **2 年以上** | **结论:一个人用,一年内攒不到能微调的数据量。** **正确定位:不是「后期要做」,而是「第一天就把数据采集架构留好」。** 数据库从 MVP 开始就存三元组: ``` (original_answer, ai_suggested_version, user_final_version) ``` 这三元组天然构成 DPO 的 (prompt, rejected, chosen) 格式。 **表述差异(很重要):** | ❌ 弱表述 | ✅ 强表述 | |---|---| | 「计划后期做 LoRA 微调」 | 「设计了面向偏好学习(DPO)的数据采集架构,训练数据以 (原始回答, AI建议, 用户最终采纳版本) 三元组形式持久化,可直接用于后续偏好对齐训练」 | 后者显示你**懂 DPO 的数据格式**,前者只是喊口号。 > 💡 **额外价值**:程老师明确说「把 LLM 的强化学习学清楚,重点 DPO、GRPO、PPO、RLHF」。这个项目正好是你实践 DPO 数据构造的载体,套磁时可以直接讲。 --- ## 3. 服务器资源现状(硬约束) ### ⚠️ 实测数据(2026-08-08) ``` CPU : 2 核 内存 : 1931 MB 总量 / 已用 1364 MB / 可用约 567 MB 磁盘 : 50G 总量,已用 45G,剩余 5.8G(89% 占用) GPU : 无 Python : 3.13.12 Node : v22.22.0 ffmpeg : 7.0.2 ✅ 已装 SQLite : 3.51.1,FTS5 ✅ 可用 ``` ### 🚨 这意味着什么 | 原方案组件 | 可行性 | 说明 | |---|---|---| | **本地 Qwen2.5-7B** | ❌ **完全不可行** | 7B 模型 INT4 量化也要 ~4.5GB 内存,你只有 567MB 可用 | | **本地 Whisper(small/medium)** | ❌ **不可行** | whisper-small 约需 2GB 内存 + 磁盘 461MB;medium 需 5GB | | **本地 Whisper(tiny/base)** | ⚠️ 勉强 | tiny 约 390MB 内存,但中文准确率差,且和其他服务抢内存 | | **本地 Embedding 模型** | ⚠️ 勉强 | nomic-embed(你之前用过)约 500MB,会挤压其他服务 | | **Chroma 向量库** | ⚠️ 不建议 | chromadb + onnxruntime 装包约 500MB,磁盘只剩 5.8G | | **FastAPI + SQLite** | ✅ 完全可行 | 轻量,几十 MB | | **云端 LLM API** | ✅ 推荐 | 零本地算力开销 | ### 💡 应对策略 **方案 A:语音处理放本地电脑(推荐)** ``` 你的笔记本 → Whisper 本地转文字 → 上传文本到服务器 → 服务器分析 ``` - 优点:零 API 成本,隐私好,你笔记本性能肯定比这台服务器强 - 缺点:需要手动一步,或写个小脚本自动上传 **方案 B:语音走云端 ASR API** | 服务 | 价格 | 备注 | |---|---|---| | OpenAI Whisper API | $0.006/分钟 | 约 ¥0.044/分钟,中文效果好 | | 阿里云语音识别 | 有免费额度 | 国内网络快 | | 硅基流动 SenseVoice | 便宜 | 你已有 SILICONFLOW_API_KEY | 按每天练 10 分钟算,OpenAI Whisper API 一个月约 ¥13,完全可接受。 **方案 C:先清磁盘** ``` 磁盘只剩 5.8G(89%),装任何 ML 依赖前先清理。 建议检查:pip cache、conda pkgs、旧模型文件、copyparty-files(236M) ``` --- ## 4. 最终技术栈选型 ### ✅ MVP 阶段(必须,全部轻量) | 层 | 选择 | 理由 | |---|---|---| | **后端框架** | FastAPI + uvicorn | 你原方案已定,正确。异步、自动 API 文档 | | **数据库** | SQLite + FTS5 | 零部署、已验证可用、1000 条级数据完全够 | | **中文分词** | jieba | 客观指标计算 + FTS5 中文索引都要用 | | **LLM** | Kimi API / 火山方舟 / 硅基流动 | ⚠️ 你已有 SILICONFLOW_API_KEY 和火山引擎,直接复用 | | **数据校验** | Pydantic v2 | FastAPI 自带,用于强约束 LLM 的 JSON 输出 | | **前端** | 单页 HTML + Alpine.js(或纯 Jinja2 模板) | ❌ **不要上 React/Vue**,MVP 阶段纯浪费时间 | | **进程管理** | systemd | 服务器已在用(openclaw-gateway 就是 systemd)| **MVP 依赖总大小:< 100MB** ← 关键,你磁盘只剩 5.8G ``` fastapi uvicorn pydantic jieba httpx python-multipart jinja2 ``` ### 🔶 第二阶段(语音) | 组件 | 选择 | 备注 | |---|---|---| | **ASR** | 云端 API(推荐)或本地电脑跑 Whisper | ⚠️ 服务器跑不了 | | **静音检测** | ffmpeg `silencedetect` | ✅ ffmpeg 已装,零新增依赖 | | **音频格式转换** | ffmpeg | 已装 | | **可选:更精细 VAD** | silero-vad(约 1MB 模型) | 极轻量,比 ffmpeg 准 | ```bash # 停顿检测(零 Python 依赖) ffmpeg -i input.wav -af silencedetect=noise=-30dB:d=0.5 -f null - 2>&1 | grep silence ``` ### 🔷 第三阶段(RAG,引入外部标准) | 组件 | 选择 | 理由 | |---|---|---| | **检索** | 先用 SQLite FTS5 + jieba | 语料量 < 5000 条时够用 | | **升级路径** | sqlite-vec(不是 Chroma!) | ⭐ 你之前的 RAG 项目就用 sqlite-vec,**技术栈复用** | | **Embedding** | 云端 API(硅基流动 bge-m3 等) | 服务器内存不够跑本地 embedding | > 💡 **重要**:你已有 `rag-llm-qa-system` 项目用的就是 SQLite-vec + 混合检索 + RRF + LLM 重排序。**直接复用那套架构**,别引入 Chroma——既省时间,又能在简历上体现「技术积累的延续性」。 ### 🔵 第四阶段(多 Agent) | 组件 | 选择 | 备注 | |---|---|---| | **Agent 编排** | ⚠️ 见下方讨论 | 不建议一上来就上 LangGraph | **关于 Agent 框架的诚实建议:** 你原方案写「OpenClaw + LangGraph」。但: - **OpenClaw** 是你的个人助手运行时,适合「你和 AI 对话」,不适合「给别人用的 Web 服务」。当然,你可以让 SpeakMind 作为一个 skill 挂进 OpenClaw 供自己使用 —— 这条路很省事,值得做。 - **LangGraph** 学习曲线不低,且在「分析 → 反馈 → 生成任务」这种**线性流程**里,它的状态机能力用不上。 **建议:第一、二阶段直接手写编排(就是几个函数按顺序调用),到真正需要「多 Agent 互相争论 / 条件分支回环」时再上 LangGraph。** 过早引入框架 = 把时间花在学框架而不是解决问题上。 ### ❌ 明确不要的东西 | 组件 | 为什么不要 | |---|---| | 本地 Qwen2.5-7B | 内存不够,且云端 API 更便宜更快 | | Chroma | 过度设计,且有 sqlite-vec 这个更轻的替代 | | Docker | 单机单服务,systemd 足够,Docker 白占磁盘 | | React / Vue | MVP 阶段前端复杂度是纯负债 | | PostgreSQL | 数据量差三个数量级 | | Celery / Redis | 没有需要异步队列的场景 | | LangChain | 抽象层太厚,直接调 API 更可控(你 RAG 项目就是自研框架,保持一致)| --- ## 5. 修正后的技术路线 ``` ┌─────────────────────────────────────────────────────┐ │ 阶段 0:单场景垂直打通(3-5 天) ⭐ 最关键 │ │ 唯一场景:「3 分钟介绍我的 iCoLoc 研究工作」 │ │ → 文字输入 → Checklist 分析 + 客观指标 → 改写建议 │ │ → 存库(含偏好三元组字段) │ └─────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────┐ │ 阶段 1:MVP 完整化(+1 周) │ │ + 多题目支持(面试常见题库) │ │ + 历史记录与趋势图(客观指标折线) │ │ + Pairwise 对比评分(vs 历史最佳) │ │ + 简易 Web UI │ └─────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────┐ │ 阶段 2:语音能力(+2 周)⭐ 差异化核心 │ │ + 音频上传 → ASR │ │ + 语速 / 填充词 / 停顿三指标 │ │ + 语音版趋势追踪 │ │ + 个人表达画像自动更新 │ └─────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────┐ │ 阶段 3:RAG 引入外部标准(+2 周) │ │ + 优秀报告语料库 / STAR 范例 / 目标岗位 JD │ │ + 复用 sqlite-vec 混合检索架构 │ │ + 场景化反馈(针对具体导师方向调整评判) │ └─────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────┐ │ 阶段 4:多 Agent 模拟训练(+3 周) │ │ + 面试官 Agent(提问 + 追问) │ │ + 评审 Agent(打分 + 反馈) │ │ + 教练 Agent(生成下次训练任务) │ │ + 此时再考虑 LangGraph │ └─────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────┐ │ 阶段 5:偏好学习(数据够了再说,至少半年后) │ │ + 导出 DPO 格式数据集 │ │ + LoRA / DPO 微调个人表达风格模型 │ └─────────────────────────────────────────────────────┘ ``` ### ⭐ 为什么加了「阶段 0」 你原方案的「7 天 MVP」包含:输入 + 评分 + 修改 + 历史,范围偏大。 **阶段 0 只做一件事:把「介绍 iCoLoc」这一个场景端到端打通。** 理由: 1. **你 9 月下旬真的要面试**(上大双选 + 北邮套磁),这是刚需,不是练手 2. 单场景能验证最难的部分(评分是否可信) 3. 3 天能做完,有正反馈,不容易半途而废 4. 做完立刻能用 —— 这比做个通用工具有价值一百倍 --- ## 6. 数据库设计 ```sql -- ============ 训练记录主表 ============ CREATE TABLE training_session ( id INTEGER PRIMARY KEY AUTOINCREMENT, created_at TEXT NOT NULL DEFAULT (datetime('now','localtime')), scenario TEXT NOT NULL, -- 'research_intro' | 'interview' | 'defense' topic TEXT NOT NULL, -- 题目原文 input_mode TEXT NOT NULL, -- 'text' | 'voice' -- 原始输入 answer_text TEXT NOT NULL, -- 文字,或 ASR 转写结果 audio_path TEXT, -- 语音模式下的音频文件路径 duration_sec REAL, -- 语音时长 -- 客观指标(代码算,确定性) char_count INTEGER, sentence_count INTEGER, avg_sent_len REAL, max_sent_len INTEGER, filler_count INTEGER, -- 填充词总数 filler_per_100 REAL, -- 每百字填充词密度 ttr REAL, -- 词汇丰富度 speech_rate REAL, -- 字/分钟(语音模式) pause_count INTEGER, -- 停顿次数(语音模式) max_pause_sec REAL, -- 最长停顿(语音模式) -- Checklist 结果(JSON) checklist_json TEXT, -- 完整结构化判断 checklist_pass INTEGER, -- 通过项数 checklist_total INTEGER, -- 总项数 -- 相对评分(Pairwise 累积,阶段 1 加) elo_rating REAL, -- LLM 定性反馈 strengths_json TEXT, -- ["优点1","优点2"] issues_json TEXT, -- [{"issue":"...","severity":"high","fix":"..."}] model_used TEXT, -- 记录用了哪个模型,便于对比 prompt_version TEXT -- ⭐ prompt 版本号,改 prompt 后能区分数据 ); -- ============ 偏好三元组(为 DPO 预留)============ CREATE TABLE preference_pair ( id INTEGER PRIMARY KEY AUTOINCREMENT, session_id INTEGER NOT NULL REFERENCES training_session(id), created_at TEXT NOT NULL DEFAULT (datetime('now','localtime')), prompt_text TEXT NOT NULL, -- 题目(DPO 的 prompt) rejected_text TEXT NOT NULL, -- 用户原始回答(DPO 的 rejected) ai_suggested TEXT NOT NULL, -- AI 改写版本 chosen_text TEXT, -- ⭐ 用户最终采纳版本(DPO 的 chosen) user_action TEXT, -- 'accept_ai' | 'edit' | 'reject' | 'pending' user_note TEXT -- 用户为什么这样改 ); -- ============ Pairwise 对比记录(阶段 1)============ CREATE TABLE pairwise_judgment ( id INTEGER PRIMARY KEY AUTOINCREMENT, created_at TEXT NOT NULL DEFAULT (datetime('now','localtime')), session_a INTEGER NOT NULL REFERENCES training_session(id), session_b INTEGER NOT NULL REFERENCES training_session(id), dimension TEXT NOT NULL, -- 'logic' | 'clarity' | 'persuasion' winner TEXT NOT NULL, -- 'A' | 'B' | 'tie' reason TEXT, judge_model TEXT ); -- ============ 个人表达画像(动态更新)============ CREATE TABLE user_profile ( id INTEGER PRIMARY KEY CHECK (id = 1), -- 单行表 updated_at TEXT NOT NULL DEFAULT (datetime('now','localtime')), strengths_json TEXT, weaknesses_json TEXT, goals_json TEXT, habit_words TEXT, -- 高频口头禅统计 baseline_json TEXT -- ⭐ 首次基线指标,用于算进步幅度 ); -- ============ 全文检索(中文需 jieba 预分词)============ CREATE VIRTUAL TABLE session_fts USING fts5( answer_tokens, -- jieba 分词后用空格连接 topic, content='' -- 外部内容表模式 ); -- ============ 索引 ============ CREATE INDEX idx_session_scenario ON training_session(scenario, created_at DESC); CREATE INDEX idx_session_created ON training_session(created_at DESC); CREATE INDEX idx_pref_session ON preference_pair(session_id); ``` ### 设计要点说明 | 字段 | 为什么重要 | |---|---| | `prompt_version` | ⭐ 你一定会反复改 prompt。不记版本号,早期数据和后期数据没法比,趋势图全废 | | `baseline_json` | 「进步了多少」需要基线。第一次训练的指标要单独存 | | `preference_pair.chosen_text` | DPO 数据格式的核心,**从第一天就要收集** | | `model_used` | 换模型会影响评分,必须记录 | | `user_action` | 区分「用户全盘接受 AI 建议」和「用户自己改」,后者数据质量更高 | --- ## 7. 评分系统设计(核心难点) ### 7.1 Checklist Prompt 模板 ```python CHECKLIST_PROMPT = """你是一位严格的表达评估专家。请分析下面这段口头表达的结构完整性。 【题目】 {topic} 【回答内容】 {answer} 请严格按以下 JSON 格式输出,不要有任何额外文字。 每个维度只做「是/否」判断,并给出原文依据(找不到依据就填 null)。 {{ "structure": {{ "has_claim": {{"value": true/false, "evidence": "原文片段或null"}}, "has_reason": {{"value": true/false, "evidence": "..."}}, "has_evidence": {{"value": true/false, "evidence": "..."}}, "has_conclusion": {{"value": true/false, "evidence": "..."}} }}, "star": {{ "situation": {{"value": true/false, "evidence": "..."}}, "task": {{"value": true/false, "evidence": "..."}}, "action": {{"value": true/false, "evidence": "..."}}, "result": {{"value": true/false, "evidence": "..."}} }}, "clarity": {{ "opening_has_context": {{"value": true/false, "evidence": "..."}}, "avoids_jargon_dump": {{"value": true/false, "evidence": "..."}}, "has_concrete_numbers": {{"value": true/false, "evidence": "..."}} }}, "top_issues": [ {{"issue": "问题描述", "severity": "high/medium/low", "fix": "具体怎么改"}} ], "strengths": ["优点1", "优点2"] }} 判断标准(严格执行): - has_evidence:必须有具体数字、实验结果或真实案例,泛泛而谈算 false - avoids_jargon_dump:如果连续出现 3 个以上未解释的专业术语,算 false - has_concrete_numbers:必须出现具体数值,「效果提升明显」算 false """ ``` **关键技巧:** 1. **要求 evidence** —— 强制模型有根据,减少幻觉式判断 2. **明确判断标准** —— 减少模型主观漂移 3. **用 Pydantic 校验输出** —— 格式不对就重试 ```python from pydantic import BaseModel from typing import Literal, Optional class Judgment(BaseModel): value: bool evidence: Optional[str] = None class Issue(BaseModel): issue: str severity: Literal["high", "medium", "low"] fix: str class ChecklistResult(BaseModel): structure: dict[str, Judgment] star: dict[str, Judgment] clarity: dict[str, Judgment] top_issues: list[Issue] strengths: list[str] ``` ### 7.2 客观指标计算(零 LLM) ```python import re, jieba from collections import Counter FILLERS = ["然后", "就是", "那个", "呃", "嗯", "其实", "反正", "这个", "我觉得", "怎么说呢", "对吧", "是不是"] def objective_metrics(text: str, duration_sec: float | None = None) -> dict: clean = re.sub(r'\s+', '', text) char_count = len(clean) sentences = [s for s in re.split(r'[。!?;!?;]', text) if s.strip()] sent_lens = [len(re.sub(r'\s+', '', s)) for s in sentences] filler_count = sum(text.count(f) for f in FILLERS) filler_detail = {f: text.count(f) for f in FILLERS if text.count(f) > 0} words = [w for w in jieba.cut(text) if w.strip()] ttr = len(set(words)) / len(words) if words else 0 result = { "char_count": char_count, "sentence_count": len(sentences), "avg_sent_len": round(sum(sent_lens) / len(sent_lens), 1) if sent_lens else 0, "max_sent_len": max(sent_lens) if sent_lens else 0, "filler_count": filler_count, "filler_per_100": round(filler_count / char_count * 100, 2) if char_count else 0, "filler_detail": filler_detail, "ttr": round(ttr, 3), } if duration_sec and duration_sec > 0: result["speech_rate"] = round(char_count / duration_sec * 60, 1) return result ``` ### 7.3 参考基准(让指标可解释) | 指标 | 优秀 | 一般 | 需改进 | |---|---|---|---| | 语速(字/分钟) | 200–260 | 160–200 / 260–300 | < 160 或 > 300 | | 填充词密度(每百字) | < 1.5 | 1.5–3.5 | > 3.5 | | 平均句长(字) | 15–30 | 30–45 | > 45 | | 最长句长(字) | < 60 | 60–90 | > 90 | | TTR(3分钟内) | > 0.55 | 0.45–0.55 | < 0.45 | > ⚠️ 这些是通用经验值,不是权威标准。**建议你先用自己前 10 次训练建立个人基线**,之后只跟自己比。 --- ## 8. 语音模块设计 ### 8.1 停顿检测(ffmpeg,零新依赖) ```bash ffmpeg -i input.wav -af silencedetect=noise=-30dB:d=0.5 -f null - 2>&1 \ | grep -E "silence_(start|end|duration)" ``` ```python import subprocess, re def detect_pauses(audio_path: str, min_pause: float = 0.5) -> dict: cmd = ["ffmpeg", "-i", audio_path, "-af", f"silencedetect=noise=-30dB:d={min_pause}", "-f", "null", "-"] out = subprocess.run(cmd, capture_output=True, text=True).stderr durations = [float(m) for m in re.findall(r'silence_duration: ([\d.]+)', out)] return { "pause_count": len(durations), "max_pause_sec": round(max(durations), 2) if durations else 0, "total_pause_sec": round(sum(durations), 2), } ``` ### 8.2 音频时长 ```bash ffprobe -v error -show_entries format=duration -of csv=p=0 input.wav ``` ### 8.3 ASR 选择(服务器无法本地跑,见第 3 节) | 方案 | 成本 | 优点 | 缺点 | |---|---|---|---| | **本地电脑跑 Whisper** ⭐ | 免费 | 隐私、无限量 | 需手动传文件 | | OpenAI Whisper API | ~¥0.044/分钟 | 中文准确率高 | 需外网 | | 硅基流动 SenseVoice | 便宜 | ⭐ 你已有 API Key | — | | 阿里云 / 腾讯云 ASR | 有免费额度 | 国内快 | 需实名 | **推荐:先用硅基流动(你已有 key),跑通流程;对准确度不满意再换。** ### 8.4 保留填充词的关键设置 Whisper 默认会「美化」输出,把「呃」「嗯」删掉。要保留: ```python result = model.transcribe( audio_path, language="zh", condition_on_previous_text=False, # ⭐ 减少「顺滑化」 temperature=0, # 确定性输出 word_timestamps=True, # 需要词级时间戳时开 ) ``` > ⚠️ 即使这样,Whisper 对中文语气词的保留也不完美。如果填充词检测是核心功能,考虑用专门的 disfluency 检测模型,或接受一定漏检率。 --- ## 9. 成本估算 ### 月度 API 成本(按每天练 1 次,每次 3 分钟) | 项目 | 用量 | 单价 | 月成本 | |---|---|---|---| | Checklist 分析 | 30 次 × ~2000 token | 视模型 | ¥3–15 | | 改写建议生成 | 30 次 × ~1500 token | 视模型 | ¥2–10 | | Pairwise 对比 | 30 次 × ~2500 token | 视模型 | ¥3–15 | | ASR(如走 API) | 90 分钟 | ¥0.044/分 | ¥4 | | **合计** | | | **约 ¥12–45/月** | 用国产模型(Kimi / 豆包 / 硅基流动)成本在下限,用 Claude/GPT-4 在上限。 ### 服务器成本 **¥0 新增** —— 复用现有服务器,MVP 依赖 < 100MB。 > ⚠️ 但要先清磁盘:目前 50G 已用 45G(89%),剩 5.8G。 --- ## 10. 第一周可执行任务清单 ### Day 1:环境 + 数据库(2-3 小时) - [ ] 清理服务器磁盘,至少腾出 10G - [ ] 建项目目录 `/root/.openclaw/workspace/projects/speakmind/` - [ ] 装依赖:`fastapi uvicorn pydantic jieba httpx jinja2 python-multipart` - [ ] 按第 6 节建库,写 `init_db.py` - [ ] 验证 FTS5 中文分词入库能跑通 ### Day 2:客观指标 + LLM 接入(3-4 小时) - [ ] 实现 `objective_metrics()`(第 7.2 节代码可直接用) - [ ] 用自己的 iCoLoc 介绍稿测一遍,看指标是否合理 - [ ] 接通 LLM API(复用现有 key),封装成 `llm_call(prompt) -> dict` - [ ] 加 Pydantic 校验 + 失败重试逻辑 ### Day 3:Checklist 分析(3-4 小时) - [ ] 写 Checklist prompt(第 7.1 节模板) - [ ] **同一段文本跑 5 次,检查一致性** ⭐ 这步不能跳 - [ ] 一致性差的项,改 prompt 里的判断标准,再测 - [ ] 结果落库 ### Day 4:改写建议 + 偏好收集(3 小时) - [ ] 实现「AI 改写」功能 - [ ] 前端提供三个按钮:采纳 AI 版 / 我自己改 / 不改 - [ ] 用户操作写入 `preference_pair` 表 ### Day 5:最简 Web UI(3-4 小时) - [ ] 单页 HTML:题目下拉框 + 文本框 + 提交 - [ ] 结果展示:checklist 打勾图 + 客观指标 + 问题列表 + 改写对比 - [ ] 历史记录列表页 ### Day 6-7:自用打磨 - [ ] **用它练 5 次「介绍我的 iCoLoc 工作」** ⭐ 真实使用是唯一验证方式 - [ ] 记录哪些反馈有用、哪些是废话 - [ ] 调 prompt,砍掉没用的输出维度 - [ ] 写 README ### ⭐ 唯一的验收标准 > **第 7 天,你能用它把「3 分钟介绍 iCoLoc」这段话,从磕磕巴巴改到能直接对着导师讲。** 做到这一点,项目就成立了。做不到,说明反馈质量不够,继续调 prompt,不要急着加功能。 --- ## 11. 简历与学术包装 ### 简历写法(技术深度递进) > **SpeakMind AI · 个人表达能力智能训练系统**(2026.08 — 至今) > > 独立设计并实现基于 LLM Agent 的长期陪伴式表达训练系统,解决传统 AI 对话「无状态、无追踪」的问题。 > > - **可信评估体系**:针对 LLM 绝对打分方差大、存在长度偏见的问题,设计「结构化 Checklist + Pairwise 相对比较(Bradley-Terry 评分)+ 确定性客观指标」三层评估架构,使长期进步追踪具备可复现性 > - **多模态输入**:集成 ASR 与 ffmpeg VAD,实现语速、填充词密度、停顿分布等口语指标的自动量化 > - **长期记忆与个人画像**:基于 SQLite + FTS5 构建训练历史检索,动态维护用户优势/短板画像,驱动个性化训练任务生成 > - **偏好数据架构**:设计 (原始回答, AI建议, 用户采纳版本) 三元组持久化方案,可直接导出为 DPO 格式训练集,为后续偏好对齐微调预留数据通路 > - 技术栈:Python / FastAPI / SQLite+FTS5 / jieba / LLM API / ffmpeg ### 套磁邮件切入点(针对北邮) **给徐蔚然老师**(方向:Agent、对齐与安全、RLHF): > 「我在自研的表达训练系统中实践了 LLM-as-Judge 的可靠性问题,发现绝对打分方差过大,改用 Pairwise 比较 + Bradley-Terry 建模后稳定性显著提升;同时设计了面向 DPO 的偏好数据采集架构。这让我对偏好对齐中『奖励信号如何构造』产生了浓厚兴趣,也正在读您组 AgentRefine 关于 Agent 泛化的工作……」 **给常东良老师**(方向:细粒度视觉理解、AI Security): > 可以从「评估可信度」切入 —— 细粒度理解和表达评估都面临「细微差异如何稳定量化」的问题。 ### 可能的论文方向(如果想往学术走) | 方向 | 可行性 | 说明 | |---|---|---| | LLM-as-Judge 在口语表达评估中的可靠性研究 | ⭐⭐⭐⭐ | 有明确研究问题,实验易设计(一致性、偏见分析) | | 个性化反馈对表达能力提升的效果研究 | ⭐⭐ | 需要多被试,一个人做不了 | | 面向个人风格的偏好数据高效构造方法 | ⭐⭐⭐ | 和程老师的 DPO/GRPO 方向对得上 | --- ## 附:给你的三句真话 1. **最大的风险不是技术,是范围失控。** 你这份方案写了 14 个模块,但真正决定成败的只有一件事:**反馈是否真的有用**。先把一个场景做到能用,再谈扩展。 2. **服务器配置是硬约束,别硬扛。** 1.9GB 内存跑不了任何本地大模型。云端 API 一个月几十块,比折腾量化模型划算得多。 3. **你自己是唯一的第一批用户,这是优势。** 别想着「以后给别人用」。9 月你真要面试,做出来直接用上——这个真实反馈循环,比任何用户调研都值钱。 --- *评估:小小叶 🍃 | 2026-08-08*