ClareCourseWare / docs /FRONTEND_BACKEND_AND_PODCAST.md
claudqunwang's picture
Add teacher agent, docs, and project updates; ClareVoiceV1 remains untracked (nested repo)
fbe1c8a

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 流(当前能力即可)

流程:

  1. 独立网站(同源或配置好 CORS 的后端代理)向 Clare 后端发:
    POST /api/podcast,body:{ "user_id": "...", "source": "summary" | "conversation", "voice": "nova" }
  2. 后端生成 podcast,直接在响应体里返回 MP3Content-Type: audio/mpeg)。
  3. 独立网站用 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://...">)。

做法:

  1. 后端在生成完 podcast 后:
    • 把 MP3 写入文件(例如 /static/podcasts/<session_id>_<timestamp>.mp3)或对象存储(如 S3/OSS),
    • 返回一个可访问的 URL,例如:
      https://your-api.com/static/podcasts/xxx.mp3 或存储的 public URL。
  2. 独立网站
    • 用该 URL 做 <audio src="..."> 播放;
    • 或用 <a href="..." download>下载</a> 提供下载。

这样就是「生成可下载的 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)。