Spaces:
Sleeping
Sleeping
Clare AI Agent:前后端配合说明 & Podcast 集成到独立网站
一、前后端需要配合做什么
整体上:前端负责 UI 和用户操作,后端负责会话状态、RAG、LLM 调用和音频生成。具体分工如下。
1. 会话与身份
| 能力 | 后端 | 前端 |
|---|---|---|
| 登录 | POST /api/login 校验并建立会话(内存里存 user_id) |
收集姓名/ID,调用 login,存 user(如 user_id = email) |
| 会话状态 | 按 user_id 存 history、course_outline、weaknesses、cognitive_state、上传文件等 |
所有需要会话的请求都带 user_id(如 user.email) |
2. 对话与内容
| 能力 | 后端 | 前端 |
|---|---|---|
| 对话 | POST /api/chat:RAG 检索 + LLM 生成,返回回复 + 可选 references |
发 message、learning_mode、language_preference,渲染回复和引用 |
| 上传 | POST /api/upload:解析文件、更新该用户的 course_outline / RAG chunks |
选文件、doc_type,上传后刷新侧边栏/状态 |
| 导出 | POST /api/export:根据当前会话 history 生成 Markdown 文本 |
调 export,展示或下载文本 |
| 总结 | POST /api/summary:对当前会话做总结,返回 Markdown |
调 summary,展示在右侧或弹窗 |
3. 音频(TTS / Podcast)
| 能力 | 后端 | 前端 |
|---|---|---|
| TTS | POST /api/tts:接收一段 text,调用 OpenAI TTS,返回 MP3 二进制(audio/mpeg) |
传 user_id + text,用 response.blob() 得到 Blob → URL.createObjectURL(blob) 给 <audio src> 播放或下载 |
| Podcast | POST /api/podcast:根据 `source=summary |
conversation 用当前会话生成脚本,再 TTS 合成,返回 **MP3 二进制**(audio/mpeg`) |
4. 其他
- Memory Line、Profile 状态、Quiz 等:前端按需调对应 API,后端按
user_id读会话状态并返回。 - 前端需统一配置 API 基地址(如
VITE_API_BASE),保证请求发到 Clare 后端。
小结:后端不写前端 UI,只提供 REST API 和会话状态;前端负责所有展示、表单和把「当前用户」(user_id) 带到每次请求里。Podcast 当前是「请求一次、返回一段 MP3 流」,不落盘。
二、把 Podcast 集成到「独立网站」的两种方式
当前实现里,Podcast 不会生成可下载的 MP3 文件链接,而是接口直接返回 MP3 字节流,由调用方在内存里播放或触发下载。
若你要在独立网站(与当前 React 应用分离的站点)里集成 podcast,有两种常见做法。
方式 A:不落盘,直接用 API 返回的 MP3 流(当前能力即可)
流程:
- 独立网站(同源或配置好 CORS 的后端代理)向 Clare 后端发:
POST /api/podcast,body:{ "user_id": "...", "source": "summary" | "conversation", "voice": "nova" }。 - 后端生成 podcast,直接在响应体里返回 MP3(
Content-Type: audio/mpeg)。 - 独立网站用
fetch拿到response.blob(),然后:- 播放:
URL.createObjectURL(blob)得到临时 URL,赋给<audio src="...">; - 下载:用
<a download>+ Object URL,或 Blob 转成文件让用户保存。
- 播放:
特点:
- 不需要在后端生成「可下载的 MP3 文件」再让网站访问;
- 不占磁盘、不涉及文件 URL;适合「当前会话、一次性听/下」;
- 独立网站只要能用 JavaScript 调 Clare 的 API(或通过自己的后端转发)即可。
结论:
若独立网站可以发 POST 并处理 Blob,不需要先生成可下载的 MP3 文件再给网站访问;直接使用接口返回的 MP3 流即可播放和下载。
方式 B:生成可下载的 MP3 文件,网站用「链接」播放/下载
适用于:
- 需要固定、可分享的链接(例如发给别人、放 RSS、嵌入第三方播放器);
- 希望缓存同一脚本的 MP3,避免重复生成;
- 独立网站只能提供「一个 MP3 地址」,不能发 POST(例如纯静态页、外嵌
<audio src="https://...">)。
做法:
- 后端在生成完 podcast 后:
- 把 MP3 写入文件(例如
/static/podcasts/<session_id>_<timestamp>.mp3)或对象存储(如 S3/OSS), - 返回一个可访问的 URL,例如:
https://your-api.com/static/podcasts/xxx.mp3或存储的 public URL。
- 把 MP3 写入文件(例如
- 独立网站:
- 用该 URL 做
<audio src="...">播放; - 或用
<a href="..." download>下载</a>提供下载。
- 用该 URL 做
这样就是「生成可下载的 MP3,再让网站通过文件 URL 访问/播放」。
若要采用方式 B,后端需要增加逻辑(例如):
- 在
POST /api/podcast里,生成 MP3 后写入指定目录或上传到存储; - 在响应里不再只返回
audio/mpeg流,而是返回 JSON,例如:{ "url": "https://.../podcasts/xxx.mp3", "expires_in": 3600 };
或保留当前「直接返回 MP3」的行为,并额外提供一个GET /api/podcast/<id>或静态路径,用于通过 URL 访问已生成的 MP3。
三、简要对比
| 维度 | 方式 A:直接用 API 返回的 MP3 流 | 方式 B:生成 MP3 文件 + URL |
|---|---|---|
| 是否需要生成可下载文件 | 否 | 是(写盘或对象存储) |
| 网站如何播放/下载 | 用 Blob + Object URL 或 <a download> |
用返回的 URL 做 <audio src> / 下载链接 |
| 是否可分享/固定链接 | 否(每次请求新生成) | 是 |
| 是否适合纯静态页「只填 URL」 | 否(需能发 POST) | 是 |
| 当前 Clare 是否支持 | 是(现有 /api/podcast 即可) |
需在后端增加「落盘/存储 + 返回 URL」 |
总结:
- 不需要「先生成可下载的 MP3 再让网站访问」:用现有
/api/podcast,在独立网站里用 POST + Blob 即可播放和下载(方式 A)。 - 需要「可分享链接、外嵌播放器、纯 URL 访问」时:再在后端增加「生成 MP3 文件并返回 URL」的能力(方式 B)。