文章目录

AI 应用开发与项目实战学习笔记

适合目标:8 小时内建立 AI 应用开发全景图,覆盖 LLM、向量数据库、SSE 流式输出、TTS、ASR、Skills、结构化输出、RAG、项目实战与高频面试题。
学习重点:不是只会调 API,而是能把模型、检索、工具调用、语音能力、前端渲染和业务工作流串成一个完整应用。
学习原则:先理解链路,再学单点;先掌握“为什么这样设计”,再记接口;先会做 MVP,再谈大而全。

说明:你提到的 soe 我先按 SSE / 流式输出 来整理。如果你原本指的是别的缩写,我后面可以再单独补一节。


目录

  1. 学习总览
  2. AI 应用开发全景图
  3. LLM 集成核心
  4. Embedding 与向量数据库
  5. SSE 流式输出、Realtime、TTS、ASR
  6. Skills、Tool Calling 与工作流设计
  7. 项目实战:AI 生成 LeaferJS 课件 JSON
  8. 技术选型与模块拆分
  9. 高频面试题
  10. 更好记的学习方法
  11. 8 小时学习节奏建议
  12. 一页速记总结
  13. 背诵口诀

1. 学习总览

1.1 AI 应用开发到底在学什么

很多人学 AI 应用时,容易停留在这一步:

会发一个 prompt,拿回一段文本。

但真实项目里,AI 应用开发远不止这样,它要解决的是:

  1. 如何让模型稳定理解用户需求
  2. 如何给模型补充业务上下文
  3. 如何让模型调用工具而不是只会“说”
  4. 如何把输出变成程序可直接消费的数据
  5. 如何处理流式、语音、检索、缓存、权限、成本和监控

所以,AI 应用开发的本质不是“接一下模型”,而是:

把模型变成系统中的一个智能节点,并与检索、工具、前端、数据库、语音能力一起组成一条完整业务链路。

1.2 你可以把 AI 应用看成什么

把 AI 应用压缩成一句话:

输入 -> 理解 -> 补充上下文 -> 决策 -> 调工具 -> 结构化输出 -> 渲染/执行 -> 反馈

也就是说,一次 AI 交互往往不是单轮文本生成,而是一条流水线:

  1. 用户输入文本、语音或图片
  2. 系统做上下文拼装
  3. 模型判断要不要查资料、调工具、走工作流
  4. 模型返回结构化结果
  5. 程序把结果渲染成页面、JSON、音频或业务动作

1.3 这份笔记的主线

主线 1:LLM 解决“理解、生成、决策”

  • 理解用户意图
  • 生成文本或结构化内容
  • 决定是否调用工具

主线 2:向量数据库解决“找上下文”

  • 给模型补知识
  • 做相似内容召回
  • 让模型不只依赖参数记忆

主线 3:SSE / Realtime / TTS / ASR 解决“交互体验”

  • 让回答边生成边展示
  • 让语音输入输出更自然
  • 让 AI 应用从“静态问答”升级成“实时交互”

主线 4:Skills 解决“模型如何真正做事”

  • 查询知识
  • 生成组件
  • 调用业务能力
  • 写入数据库或渲染数据

主线 5:项目实战解决“如何把这些能力组织成产品”

  • 数据结构怎么设计
  • 后端链路怎么组织
  • 前端怎么渲染
  • 如何保证生成结果稳定

1.4 核心记忆主线

把 AI 应用开发记成一句话:

模型负责思考,检索负责补知识,Skills 负责执行,结构化输出负责落地,前端负责呈现。

再压缩成五个词:

模型、检索、工具、结构、渲染


2. AI 应用开发全景图

2.1 一个完整 AI 应用通常由哪些模块组成

模块 作用 典型输入输出
LLM 理解、生成、决策 文本输入 -> 文本/结构化输出
Embedding 把文本变向量 文本 -> 向量
向量数据库 相似检索 向量 -> TopK 相关内容
RAG 检索增强生成 用户问题 + 召回文档 -> 更可靠答案
SSE / Realtime 流式展示、实时交互 增量 token / 音频帧
TTS 文本转语音 文本 -> 音频
ASR 语音转文本 音频 -> 文本
Skills / Tools 让模型调用业务能力 模型意图 -> 程序动作
结构化输出 让结果可编程 prompt -> JSON / Schema
前端渲染 页面、图形、课件展示 JSON -> UI / Canvas / LeaferJS

2.2 AI 应用和普通 Web 应用最大的区别

普通 Web 应用更偏:

固定逻辑 + 固定界面 + 固定接口

AI 应用更偏:

不确定输入 + 模型推理 + 检索上下文 + 工具协作 + 结果校验

也就是说,AI 应用会新增这些挑战:

  1. 输出不稳定
  2. 成本与延迟波动
  3. prompt 质量直接影响产品效果
  4. 工具调用和状态管理更复杂
  5. 需要评估、回放、追踪和观测

2.3 一个通用 AI 应用架构

你可以先记住这个通用架构:

Client -> API Server -> Prompt Builder -> Retriever -> Model -> Tool Router -> Validator -> Renderer / Business Action

拆开理解:

  1. Client:输入问题、播放流式结果、展示界面
  2. API Server:鉴权、限流、组织上下文
  3. Prompt Builder:构造系统指令、上下文、示例
  4. Retriever:从向量库召回知识
  5. Model:进行生成或决策
  6. Tool Router:根据模型意图调用 Skills
  7. Validator:检查 JSON 合法性和业务约束
  8. Renderer / Business Action:渲染结果或执行操作

2.4 面试里怎么概括 AI 应用开发

标准答法可以这样说:

AI 应用开发本质上是在传统应用架构中加入模型推理、上下文检索、工具调用和结构化输出能力,让系统从固定逻辑扩展为“可理解、可生成、可决策、可执行”的应用。


3. LLM 集成核心

这一部分是 AI 应用开发的中心。你不需要先背所有模型名,而要先理解:模型在系统里扮演什么角色,以及该如何稳定调用它。

3.1 LLM 在项目里通常承担什么角色

LLM 最常见的三类角色:

  1. 生成者:写文案、写总结、写 JSON
  2. 理解者:做分类、提取字段、识别意图
  3. 调度者:判断要不要调用工具、选哪个工具、按什么顺序执行

所以,模型并不只是“回答问题”,它还可以是:

一个语言驱动的决策层

3.2 新项目里优先记哪类 API

学习时你可以先把 OpenAI 相关能力分成三层:

能力 适合场景 记忆重点
Responses API 大多数文本、多模态、结构化、工具调用场景 新项目优先记它
Realtime API 低延迟语音对话、双向实时流 语音应用重点
Chat Completions 旧项目兼容或历史代码 了解即可,不作为主线

当前官方文档的主线已经围绕 Responses API / Streaming / Realtime / Structured Outputs / Function Calling 组织,所以学习新项目时优先围绕这条主线建立认知。

学习阶段怎么记模型选择

为了方便记忆,你可以先按任务类型记:

  1. 复杂推理、复杂生成:优先高能力主模型
  2. 日常文本生成、结构化输出:优先更轻量的通用模型
  3. 向量检索:使用专门的 embedding 模型
  4. TTS:使用语音合成模型
  5. ASR:使用语音转写模型

学习时不用一开始就死背所有模型名,但要形成这个意识:

文本、向量、语音,不一定是同一个模型。

前后端安全边界怎么记

这一点非常重要:

  1. 正式 API Key 只应该放在服务端
  2. 浏览器不要直接持有标准密钥
  3. 实时语音场景通常使用后端下发的临时令牌
  4. 所有调用最好经过你自己的业务后端做鉴权、限流和审计

一句话记忆:

模型能力可以在前端展示,但密钥和真实调用链路应由后端控制。

3.3 一次最基本的 LLM 调用长什么样

示例:

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

const response = await client.responses.create({
  model: "gpt-5.4-mini",
  input: "用一句话解释什么是向量数据库",
});

console.log(response.output_text);

看这段代码时,你脑子里要立刻有这个模型:

  1. client:和平台通信
  2. model:选哪个模型
  3. input:给模型的输入
  4. response.output_text:最终文本结果

3.4 LLM 调用最常见的四种模式

模式 1:普通文本生成

适合:

  1. 问答
  2. 总结
  3. 改写
  4. 文案生成

模式 2:结构化输出

适合:

  1. 生成 JSON
  2. 信息抽取
  3. 组件配置
  4. 表单字段解析

模式 3:工具调用

适合:

  1. 查询知识库
  2. 调用数据库
  3. 生成页面组件
  4. 执行业务动作

模式 4:多轮状态延续

适合:

  1. 对话助手
  2. 复杂任务拆解
  3. 长链路生成

3.5 为什么“结构化输出”比“让模型自己写 JSON”更可靠

很多初学者会这样写:

请返回一个 JSON,不要有多余文字。

这能用,但稳定性不够,因为:

  1. 模型可能多说解释
  2. 字段名可能漂移
  3. 数组和对象层级可能不一致
  4. 一旦输出不合法,程序就崩

更好的做法是:

使用 Structured Outputs + JSON Schema

这样做的价值是:

  1. 限定字段结构
  2. 减少自由发挥
  3. 程序更容易直接消费
  4. 更适合组件生成、表单抽取、工作流输入

3.6 一个结构化输出示例

const response = await client.responses.create({
  model: "gpt-5.4-mini",
  input: "生成一个标题页组件配置",
  text: {
    format: {
      type: "json_schema",
      name: "slide_component",
      schema: {
        type: "object",
        properties: {
          type: { type: "string" },
          title: { type: "string" },
          subtitle: { type: "string" },
        },
        required: ["type", "title"],
        additionalProperties: false,
      },
    },
  },
});

这里最关键的记忆点是:

  1. type: "json_schema":告诉模型按 Schema 输出
  2. required:哪些字段必须有
  3. additionalProperties: false:禁止乱加字段

3.7 工具调用是什么

工具调用可以理解成:

模型不只是“说应该怎么做”,而是告诉系统“请帮我调用这个工具去做”。

例如:

  1. 用户说“生成一页课程封面”
  2. 模型判断应该调用 create_title_slide
  3. 系统执行这个 skill
  4. 返回组件 JSON
  5. 模型再基于结果继续组织最终输出

3.8 Tool Calling 的本质

本质上,Tool Calling 解决的是:

模型只负责决策,真正执行交给程序。

这是非常重要的架构思想,因为:

  1. 模型擅长理解和规划
  2. 程序擅长确定性执行
  3. 把二者分开,系统更稳定

3.9 tool_choice 要解决什么问题

工具很多时,你要考虑:

  1. 让模型自己决定是否调用
  2. 强制调用某个工具
  3. 禁止调用工具,只做文本返回

也就是说,tool_choice 控制的是:

模型在这次请求里能不能调工具,以及调哪个工具。

3.10 多轮状态怎么记

多轮对话或长流程任务里,要理解一个关键点:

模型本身不是持久数据库,状态要靠应用层管理。

常见做法:

  1. 前端保存会话 ID
  2. 后端保存对话记录、业务状态、用户资料
  3. 模型请求时附带历史上下文
  4. 或使用 previous_response_id 继续串联前后轮次

3.11 提示词不是“文案”,而是“接口设计”

很多人把 Prompt 理解成“写几句话”。

更准确的理解是:

Prompt 是给模型设计输入协议。

一个好的 Prompt,应该包含:

  1. 角色和任务
  2. 输入变量
  3. 输出格式
  4. 约束条件
  5. 示例
  6. 失败时的兜底策略

3.12 LLM 集成的常见错误

  1. 让前端直接持有正式 API Key
  2. 把所有业务逻辑都塞到 prompt 里
  3. 不做结构化校验
  4. 不做重试和超时控制
  5. 不记录 prompt、响应和工具调用链路
  6. 让模型直接生成最终生产数据而不做二次验证

3.13 一句话压缩 LLM 集成

模型负责理解与决策,结构化输出负责可编程,工具调用负责可执行,应用层负责状态和稳定性。


4. Embedding 与向量数据库

这部分是 RAG 的基础。只要你理解“文本为什么能被拿去做相似搜索”,向量数据库就不会神秘。

4.1 什么是 Embedding

Embedding 可以理解成:

把文本、图片、音频等非结构化内容,映射成一串数字向量。

这串向量不是给人看的,而是给机器做“相似度计算”的。

4.2 为什么需要 Embedding

因为模型和数据库要做这件事:

不是找字面一样,而是找语义接近。

例如:

  • “二分查找”
  • “折半查找”

虽然词不完全一样,但语义接近,向量空间里它们通常也会比较近。

4.3 Embedding 的基本调用

const embedding = await client.embeddings.create({
  model: "text-embedding-3-small",
  input: "二分查找适用于有序数组",
});

const vector = embedding.data[0].embedding;

记忆点:

  1. 文本进来
  2. 向量出去
  3. 向量会被存进向量数据库

4.4 向量数据库是做什么的

向量数据库主要解决三件事:

  1. 存向量
  2. 按相似度检索向量
  3. 配合 metadata 过滤

它不是普通关系数据库的替代品,而是:

专门为相似搜索和语义检索准备的检索层。

4.5 一个完整 RAG 链路

RAG 可以记成:

切分 -> 向量化 -> 入库 -> 查询向量化 -> 相似检索 -> 拼接上下文 -> 再问模型

展开来看:

  1. 把文档切成 chunk
  2. 给每个 chunk 生成 embedding
  3. 写入向量数据库
  4. 用户提问时,对问题也做 embedding
  5. 去库里找最相似的 TopK chunk
  6. 把这些 chunk 拼到 prompt 里
  7. 再让模型回答

4.6 为什么不能把所有知识直接塞给模型

原因很简单:

  1. 上下文窗口有限
  2. 成本会很高
  3. 长文本噪声多
  4. 每次都全塞,效率差

所以更合理的做法是:

按需召回,而不是全量灌输

4.7 向量数据库常见字段

一般一条数据会包含:

  1. id
  2. vector
  3. payload / metadata
  4. source
  5. chunk_text
  6. doc_id
  7. chunk_index

例如:

{
  "id": "chunk_1024",
  "vector": [0.12, -0.33, 0.88],
  "metadata": {
    "docId": "course_js_01",
    "chapter": "闭包",
    "level": "beginner",
    "type": "knowledge"
  },
  "text": "闭包是函数与其词法环境的组合"
}

4.8 切分策略很重要

RAG 效果不只是模型决定的,chunk 切分非常关键。

常见切分方式:

  1. 固定长度切分
  2. 按段落切分
  3. 按标题层级切分
  4. 语义切分

切分要注意:

  1. 不要太短,语义碎
  2. 不要太长,噪声大
  3. 要保留上下文连续性
  4. 可以适当 overlap

4.9 检索不是越多越好

很多人会误以为:

TopK 越大越全面

其实不是。TopK 太大时可能会:

  1. 引入噪声
  2. 稀释关键证据
  3. 提高 token 成本
  4. 降低回答聚焦度

所以 RAG 的重点不是“多”,而是:

召回准

4.10 metadata 过滤为什么重要

metadata 可以让检索更可控。

例如:

  1. 只查某个课程
  2. 只查某个学科
  3. 只查组件模板
  4. 只查某个用户的私人资料

这对 AI 课件项目尤其重要,因为你可能要把知识块、模板块、组件块分开检索。

4.11 RAG 和微调的区别

RAG

  • 动态补充知识
  • 更新知识不需要重新训练
  • 适合文档问答、知识库、模板召回

微调

  • 调整模型风格或任务行为
  • 更适合稳定格式、专业语气、固定任务
  • 更新成本更高

一句话区分:

RAG 补知识,微调改习惯。

4.12 向量数据库选型怎么记

你可以先用场景记,而不是死背产品:

类型 适合场景 记忆方式
pgvector 你本来就用 Postgres,想快速把向量和业务数据放一起 关系库一体化
Qdrant 检索能力清晰、工程接入友好、适合应用层快速落地 独立向量检索服务
Milvus 大规模、高性能、分布式向量检索场景 重型高规模方案

学习阶段不用纠结“哪家绝对最好”,先记:

轻量一体化用 pgvector,独立检索服务看 Qdrant,超大规模看 Milvus。

4.13 AI 课件项目里向量数据库能做什么

在你说的课件生成场景里,向量数据库非常有用:

  1. 检索知识库内容,生成更准确课件
  2. 检索历史优质课件结构
  3. 检索组件模板和布局示例
  4. 检索教师个人风格和常用措辞
  5. 检索某类题型或图示模板

4.14 一句话压缩向量数据库

Embedding 负责把内容变成可比较的向量,向量数据库负责把相似内容快速找回来。


5. SSE 流式输出、Realtime、TTS、ASR

这一部分决定用户体验。一个 AI 产品,如果只能等几十秒再一次性吐结果,体验会非常差;如果能边生成边展示、边说边听,产品感会立刻提升。

5.1 为什么需要流式输出

一次完整生成可能会比较慢,特别是:

  1. 回答很长
  2. 需要检索和工具调用
  3. 要生成多页课件

如果用户一直空等,会感觉:

系统卡了

所以流式输出的核心价值是:

  1. 更快感知到结果
  2. 更好的交互体验
  3. 方便分段渲染
  4. 便于展示生成过程

5.2 SSE 是什么

SSE 即 Server-Sent Events,可以理解成:

服务器不断把增量内容往客户端推。

在 AI 文本生成里,它很适合:

  1. token 流式展示
  2. 进度消息推送
  3. 生成步骤回显

5.3 一个基本流式示例

const stream = await client.responses.create({
  model: "gpt-5.4-mini",
  input: "请分三点解释 RAG",
  stream: true,
});

for await (const event of stream) {
  if (event.type === "response.output_text.delta") {
    process.stdout.write(event.delta);
  }
}

记忆点:

  1. stream: true
  2. 后端拿到一连串事件
  3. 前端按事件增量渲染

5.4 SSE 和 WebSocket 的区别

技术 通信方向 适合场景
SSE 服务器 -> 客户端单向推送 文本流式输出、状态消息
WebSocket 双向通信 实时协作、低延迟语音、实时控制

一句话区分:

文本流式优先 SSE,实时双向交互看 WebSocket / Realtime。

5.5 Realtime API 适合什么

Realtime 更适合:

  1. 低延迟语音对话
  2. 连续语音输入输出
  3. 实时中断、打断、继续说
  4. 语音 Agent

学习时可以先记:

  1. 浏览器端实时语音更适合 WebRTC
  2. 服务端中间层更适合 WebSocket

5.6 TTS 是什么

TTS 即 Text To Speech,文本转语音。

它在 AI 应用里常见用途:

  1. 把回答读出来
  2. 给课件生成讲解音频
  3. 做 AI 老师、AI 主播、AI 导航助手

5.7 TTS 的关键关注点

  1. 音色是否自然
  2. 延迟是否可接受
  3. 语速、情感、停顿是否可控
  4. 是否支持流式音频
  5. 成本和并发是否可控

5.8 一个基础 TTS 示例

const speech = await client.audio.speech.create({
  model: "gpt-4o-mini-tts",
  voice: "coral",
  input: "欢迎来到二分查找课程",
  instructions: "语速平稳,适合教学解说",
});

在课件场景里,TTS 可以用于:

  1. 每页自动生成讲解音频
  2. 一键播放当前页内容
  3. 导出音频版课程

5.9 ASR 是什么

ASR 即 Automatic Speech Recognition,自动语音识别。

也就是:

把用户说的话转成文字。

5.10 ASR 适合哪些场景

  1. 语音输入 prompt
  2. 语音编辑课件
  3. 会议纪要转写
  4. 教师口述生成课件

5.11 一个基础 ASR 示例

import fs from "fs";

const transcription = await client.audio.transcriptions.create({
  file: fs.createReadStream("teacher.mp3"),
  model: "gpt-4o-mini-transcribe",
  response_format: "text",
});

console.log(transcription);

5.12 TTS 和 ASR 的关系怎么记

很简单:

  • TTS:字 -> 声
  • ASR:声 -> 字

再压缩成一句:

TTS 负责说,ASR 负责听。

5.13 语音 AI 应用的一条常见链路

用户说话 -> ASR 转文本 -> LLM 理解与决策 -> Tool / RAG -> 文本结果 -> TTS 播放

如果是更实时的模式,则会演化成:

语音流输入 -> Realtime -> 增量理解 -> 增量输出 -> 语音流播放

5.14 流式处理中常见坑

  1. 前端把流式片段当完整 JSON 解析
  2. 流断开后没有重试和恢复机制
  3. 没有区分“中间态”和“最终完成态”
  4. 后端不做 flush,前端感知不到增量
  5. 一边流式展示,一边又试图直接写最终数据库,导致状态错乱

5.15 课件项目里该如何用流式

推荐这样拆:

  1. 规划阶段:先流式展示“正在规划课件”
  2. 组件生成阶段:逐页、逐组件返回状态
  3. 渲染阶段:每页生成完立即预览
  4. 音频阶段:每页单独生成 TTS

这样用户的感受会很好,因为不是“一直等”,而是“不断看到进度和结果”。

5.16 一句话压缩语音与流式

SSE 负责边生成边看,Realtime 负责边说边听,TTS 负责输出声音,ASR 负责接收声音。


6. Skills、Tool Calling 与工作流设计

这部分是 AI 应用从“会说话”走向“会做事”的关键。

6.1 这里的 Skills 应该怎么理解

在这份笔记里,Skills 不是泛指“能力”,而是:

被模型调用的、具有明确输入输出的业务工具或组件工厂。

比如:

  1. search_course_knowledge
  2. create_title_slide
  3. create_timeline_component
  4. generate_teacher_voiceover
  5. save_courseware

6.2 为什么要设计 Skills,而不是全让模型自由生成

因为纯 prompt 方式有这些问题:

  1. 输出不稳定
  2. 不容易复用
  3. 不方便校验
  4. 不好观察和追踪
  5. 很难沉淀业务能力

而 Skills 的优势是:

  1. 输入输出可定义
  2. 逻辑可复用
  3. 可监控、可测试
  4. 容易做版本管理
  5. 更适合复杂项目长期维护

6.3 Skill 的设计原则

原则 1:单一职责

一个 Skill 最好只干一类事。

例如:

  • create_text_block
  • create_quiz_block

比一个超大 generate_anything 更稳定。

原则 2:输入明确

Skill 的参数要清晰:

  1. 字段名稳定
  2. 类型稳定
  3. 必填项明确

原则 3:输出确定

Skill 返回结果最好是:

  1. 稳定 JSON
  2. 可验证结构
  3. 不带多余文案

原则 4:可观测

你要知道:

  1. 谁调用了它
  2. 传了什么参数
  3. 调用成功没有
  4. 延迟多少
  5. 返回什么结果

6.4 Tool Calling 和 Workflow 的关系

Tool Calling 解决的是:

一次请求里模型如何调用工具

Workflow 解决的是:

多步任务如何按顺序组织

例如生成课件时:

  1. 先生成目录
  2. 再生成每一页规划
  3. 再生成每一页组件
  4. 再验证 JSON
  5. 再渲染和存储

这就是一个工作流,而不是一次单纯的工具调用。

6.5 为什么复杂 AI 项目一定要“拆步骤”

因为一步到位生成整个复杂产物,容易出现:

  1. token 太长
  2. 结构失控
  3. 局部错误拖垮整体
  4. 无法增量修复

更合理的设计是:

规划 -> 分页 -> 分组件 -> 校验 -> 编译 -> 渲染

6.6 Skills 的常见分层方式

你可以把 Skills 分成三层:

层级 作用 例子
数据技能 查数据、查文档、查模板 search_docs, search_components
生成技能 生成局部结构 create_title_block, create_chart_block
动作技能 触发业务动作 save_project, publish_courseware

6.7 一套适合课件项目的 Skills

你这个项目里,可以先设计这几个核心 Skills:

  1. plan_courseware
  2. search_knowledge
  3. search_layout_templates
  4. create_title_slide
  5. create_bullet_slide
  6. create_timeline_slide
  7. create_quiz_slide
  8. create_chart_component
  9. validate_slide_schema
  10. compile_to_leafer_json
  11. generate_tts_voiceover
  12. save_courseware

6.8 Skills 和组件库是什么关系

你可以这样理解:

  1. 组件库定义“有哪些组件”
  2. Skills 负责“按业务参数生成这些组件的 JSON”

也就是说:

组件库是积木,Skill 是搭积木的方法。

6.9 为什么最好让 Skills 产出“中间 DSL”,而不是直接产出最终渲染 JSON

这是项目里最重要的架构点之一。

如果让模型直接输出最终 LeaferJS JSON,会有几个风险:

  1. 字段太多,容易漂移
  2. 绝对坐标容易乱
  3. 主题样式难统一
  4. 不方便切换渲染引擎
  5. 难做自动修复

更好的做法是:

先产出业务中间 DSL,再由程序编译成 LeaferJS JSON

6.10 什么是中间 DSL

DSL 即领域专用结构。

例如你可以定义:

{
  "slideType": "title",
  "title": "二分查找",
  "subtitle": "用有序数组快速定位目标值",
  "theme": "light-edu",
  "notes": "开场 15 秒解释应用场景"
}

这比直接生成一堆 x / y / width / fill / fontSize 更好控制。

6.11 为什么 DSL 更适合长期演进

因为它让系统层次更清楚:

  1. 模型只关心业务语义
  2. 编译器负责转成具体渲染格式
  3. 样式系统统一控制视觉
  4. 未来可以从 LeaferJS 切到别的引擎

6.12 一句话压缩 Skills

Skill 是被模型调用的业务工具;复杂项目里,Skill 最好生成中间 DSL,而不是直接生成最终渲染数据。


7. 项目实战:AI 生成 LeaferJS 课件 JSON

这一部分就是把前面所有知识串起来,做成一个真实项目。你提到的方向很适合拿来做作品集和面试项目,因为它同时覆盖了生成式 AI、结构化输出、前端渲染、组件化和工作流设计。

7.1 项目目标怎么定义

一句话目标:

用户通过自然语言描述教学主题,AI 自动生成课件结构、每页组件配置,并编译成可由 LeaferJS 渲染的 JSON 课件。

更完整一点可以是:

  1. 输入课程主题或教学需求
  2. AI 生成课件大纲
  3. AI 为每一页选择合适布局和组件
  4. Skills 生成每页组件 DSL
  5. 系统将 DSL 编译为 LeaferJS JSON
  6. 前端即时预览,可再编辑、重生成、配音

7.2 这个项目为什么有价值

因为它同时体现了:

  1. AI 内容生成
  2. 结构化输出
  3. Tool Calling / Skills
  4. 向量检索
  5. 前端图形渲染
  6. 语音输入输出
  7. 产品化工作流

面试官通常会觉得这是个“像真项目”的题目,而不是只会做聊天机器人。

7.3 最推荐的系统链路

推荐链路如下:

用户描述 -> 课件规划模型 -> 检索知识/模板 -> Slide Planner -> Skills 生成每页 DSL -> Schema 校验 -> Leafer Compiler -> 前端预览 -> 局部重生成 -> 保存 / 导出 / 配音

7.4 为什么不要一步让 AI 直接生成整份最终课件 JSON

因为这样做的风险非常大:

  1. 整体结构过长,容易截断
  2. 一页出错会污染整份结果
  3. 难以局部重做
  4. 样式不统一
  5. 坐标布局容易混乱

更合理的方案是:

  1. 先规划页级结构
  2. 再生成页内组件 DSL
  3. 再用编译器转成 LeaferJS JSON

7.5 一个推荐的分层架构

第 1 层:用户输入层

接收:

  1. 文本描述
  2. 语音描述
  3. 上传资料
  4. 课程模板选择

第 2 层:规划层

模型负责:

  1. 识别课程主题
  2. 判断适合几页
  3. 规划每页类型
  4. 决定哪些页需要图表、时间线、问答、总结

第 3 层:检索层

检索:

  1. 知识库
  2. 历史课件样例
  3. 布局模板
  4. 组件模板
  5. 教师个人风格

第 4 层:技能生成层

Skills 生成:

  1. 每页 DSL
  2. 每个组件参数
  3. 讲解词草稿

第 5 层:编译与校验层

负责:

  1. JSON Schema 校验
  2. 版式约束检查
  3. 编译成 LeaferJS JSON
  4. 修正越界布局

第 6 层:渲染与编辑层

负责:

  1. 用 LeaferJS 渲染页面
  2. 支持拖拽编辑
  3. 支持单页重生成
  4. 支持导出、播放、保存

7.6 你应该设计两套 JSON,而不是一套

这是整个项目最关键的设计。

第一套:业务 DSL

给模型和 Skills 用,表达“这一页是什么内容”。

第二套:渲染 JSON

给 LeaferJS 用,表达“这一页怎么画出来”。

这两个层次分开后,系统会非常清楚。

7.7 一份推荐的业务 DSL 结构

{
  "coursewareId": "cw_binary_search_001",
  "topic": "二分查找",
  "theme": "light-edu",
  "slides": [
    {
      "id": "slide_1",
      "slideType": "title",
      "title": "二分查找",
      "subtitle": "在有序数组中快速定位目标值",
      "notes": "开场介绍应用场景"
    },
    {
      "id": "slide_2",
      "slideType": "two-column",
      "title": "核心思路",
      "components": [
        {
          "componentType": "bulletList",
          "items": [
            "每次取中间值比较",
            "缩小搜索区间",
            "前提是数组有序"
          ]
        },
        {
          "componentType": "codeBlock",
          "language": "js",
          "code": "while (left <= right) { ... }"
        }
      ]
    }
  ]
}

7.8 一份推荐的 LeaferJS 渲染 JSON 结构

下面这份更偏“最终渲染层”:

{
  "tag": "Leafer",
  "width": 1280,
  "height": 720,
  "children": [
    {
      "tag": "Rect",
      "x": 0,
      "y": 0,
      "width": 1280,
      "height": 720,
      "fill": "#F8FAFC"
    },
    {
      "tag": "Text",
      "x": 80,
      "y": 70,
      "width": 1120,
      "text": "二分查找",
      "fontSize": 40,
      "fontWeight": "bold",
      "fill": "#111827"
    },
    {
      "tag": "Text",
      "x": 80,
      "y": 130,
      "width": 1120,
      "text": "在有序数组中快速定位目标值",
      "fontSize": 22,
      "fill": "#4B5563"
    }
  ]
}

学习时要记住:

LLM 更适合生成 DSL,程序更适合生成最终坐标和样式。

7.9 LeaferJS 这类渲染层要注意什么

根据官方 JSON 文档,App 元素本身不直接导入导出,通常导出 app.tree 的数据,再用 app.tree.set(...) 导入。

这说明一个很重要的工程点:

前端渲染层要有自己的导入导出适配,不要把模型输出直接硬塞给渲染实例。

7.10 项目里最重要的几个数据模型

数据模型 1:Courseware

表示整份课件。

常见字段:

  1. id
  2. topic
  3. theme
  4. slides
  5. authorId
  6. status

数据模型 2:Slide

表示单页。

常见字段:

  1. id
  2. slideType
  3. title
  4. components
  5. notes
  6. voiceoverStatus

数据模型 3:ComponentSpec

表示一页里的某个组件。

常见字段:

  1. componentType
  2. props
  3. layoutSlot
  4. priority

数据模型 4:Template

表示课件模板或布局模板。

常见字段:

  1. templateId
  2. name
  3. themeTokens
  4. allowedComponents
  5. sampleDsl

7.11 推荐的生成流程

步骤 1:课件规划

模型先输出:

  1. 总页数
  2. 每页标题
  3. 每页类型
  4. 每页核心内容

这一步只做“大纲规划”,不要直接出最终组件。

步骤 2:知识与模板检索

根据每页主题去检索:

  1. 课程知识块
  2. 相似课件页
  3. 布局模板
  4. 对应组件示例

步骤 3:Skills 生成每页 DSL

例如:

  1. create_title_slide
  2. create_definition_slide
  3. create_code_example_slide
  4. create_quiz_slide

步骤 4:Schema 校验

检查:

  1. 字段是否齐全
  2. 类型是否正确
  3. 组件是否在白名单
  4. 文本长度是否超限

步骤 5:布局编译

把 DSL 编译成:

  1. 组件坐标
  2. 字体样式
  3. 颜色主题
  4. 页级背景

最终产出 LeaferJS JSON。

步骤 6:渲染与反馈

前端渲染后可以:

  1. 让用户局部修改
  2. 局部重生成单个组件
  3. 对单页重新配图或配音

7.12 为什么“局部重生成”很重要

用户常常不是整份课件都不满意,而是:

  1. 这页标题不好
  2. 这块图表不合适
  3. 这页太密了
  4. 这页讲解词太长

如果没有局部重生成,体验会很差。

所以你要设计:

  1. 重新生成单页
  2. 重新生成单个组件
  3. 重新生成配音文本

7.13 一组非常实用的 Skills 设计

Skill 1:plan_courseware

输入:

  1. 主题
  2. 目标用户
  3. 课时长度
  4. 风格要求

输出:

  1. 页数
  2. 每页主题
  3. 每页 slideType

Skill 2:create_slide_components

输入:

  1. slideType
  2. 本页内容
  3. 布局模板
  4. 主题样式

输出:

  1. components[]

Skill 3:search_slide_examples

输入:

  1. 当前页主题
  2. 组件类型

输出:

  1. 相似课件案例
  2. 高质量布局样例

Skill 4:compile_to_leafer_json

输入:

  1. 页级 DSL
  2. 主题 token
  3. 画布尺寸

输出:

  1. LeaferJS JSON

Skill 5:generate_voiceover

输入:

  1. 当前页标题
  2. 组件内容
  3. 讲解风格

输出:

  1. 解说词
  2. TTS 音频链接

7.14 提示词设计该怎么做

你这个项目里,Prompt 最好分层写。

规划 Prompt

负责输出课件目录和页级意图。

组件生成 Prompt

负责输出组件 DSL。

讲解词 Prompt

负责输出配音文案。

修复 Prompt

负责修复校验失败的 JSON。

这样做的好处是:

  1. 每一步目标更单一
  2. 更方便排查问题
  3. 更方便做 A/B 测试

7.15 为什么一定要做 JSON 校验和自动修复

因为模型输出不可能 100% 稳定。

所以实际项目里至少要做:

  1. JSON Schema 校验
  2. 字段默认值填充
  3. 超长文本裁剪
  4. 坐标越界修复
  5. 不合法组件替换为兜底组件

这一步很关键,因为它决定:

AI 输出能不能真正进入生产链路

7.16 最佳实践:模型不要直接负责版式坐标

让模型直接生成精确坐标,一般不是个好主意。

因为模型更擅长:

  1. 语义组织
  2. 层级规划
  3. 内容选择

程序更擅长:

  1. 计算布局
  2. 保证边距
  3. 控制字号
  4. 保证响应式和统一视觉

所以:

模型负责“放什么”,布局引擎负责“放哪里”。

7.17 项目里向量数据库怎么用最值

你这个项目中,向量数据库最值得存这几类内容:

  1. 教材知识 chunk
  2. 历史优秀课件页
  3. 组件模板描述
  4. 教师个人风格样例
  5. 常见图示讲法

推荐检索策略:

  1. 先按 courseId / subject / grade 过滤
  2. 再做相似检索
  3. 召回后做轻量 rerank

7.18 加入 TTS / ASR 后,项目会更像产品

你可以增加这几个高级功能:

  1. 教师口述主题,ASR 转文本生成课件
  2. 每页自动生成讲解音频
  3. AI 老师朗读当前页
  4. 语音指令“把第二页改成时间线布局”

7.19 一个适合面试展示的完整故事线

你可以这样讲你的项目:

这是一个 AI 课件生成系统。用户输入课程描述后,系统先通过模型规划页级结构,再结合向量检索召回教材知识和布局模板,随后由一组 Skills 生成每页组件 DSL,经过 Schema 校验和布局编译后产出 LeaferJS 可渲染 JSON。前端支持逐页预览、局部重生成和 TTS 配音,后端则负责流式输出、检索、工具编排和结果持久化。

如果你能把这段话讲顺,面试里会很加分。

7.20 一句话压缩项目方案

不要让模型一步吐最终课件,而要让模型规划、让 Skills 生成 DSL、让编译器生成 LeaferJS JSON。


8. 技术选型与模块拆分

8.1 一个适合 MVP 的技术栈

前端

  1. React / Next.js 或 React + Vite
  2. LeaferJS 负责课件渲染与编辑
  3. Zustand / Redux 管理编辑状态
  4. EventSource 或 fetch stream 处理流式输出

后端

  1. Node.js + NestJS / Express
  2. OpenAI SDK
  3. SSE 接口和任务编排层
  4. JSON Schema 校验层

数据层

  1. PostgreSQL 存业务数据
  2. pgvector 或独立向量库存 embedding
  3. Redis 做缓存、队列和会话状态
  4. OSS / S3 存音频、图片、导出文件

8.2 一个适合 MVP 的接口设计

  1. POST /api/courseware/plan
  2. POST /api/courseware/generate-slide
  3. POST /api/courseware/compile
  4. GET /api/courseware/stream/:taskId
  5. POST /api/courseware/asr
  6. POST /api/courseware/tts
  7. POST /api/courseware/regenerate-component

8.3 前后端职责怎么分

前端负责

  1. 输入描述
  2. 展示生成进度
  3. 预览 LeaferJS 画面
  4. 局部编辑和重生成
  5. 音频播放和录音

后端负责

  1. 鉴权
  2. 调模型
  3. 检索知识
  4. 执行 Skills
  5. 校验 JSON
  6. 存储结果

8.4 推荐的版本迭代路线

V1:最小可用版

只做:

  1. 文本输入
  2. 生成课件大纲
  3. 生成 3-4 种固定 slideType
  4. 编译成 LeaferJS JSON
  5. 前端预览

V2:增强版

增加:

  1. 流式生成
  2. 向量检索
  3. 单页重生成
  4. 组件局部编辑

V3:产品版

增加:

  1. TTS 配音
  2. ASR 语音输入
  3. 教师风格记忆
  4. 课件模板市场

8.5 成本与性能要怎么考虑

AI 项目里一定要考虑:

  1. 长 prompt 成本
  2. 检索次数
  3. 多步工作流调用次数
  4. TTS / ASR 额外成本
  5. 流式连接占用

常见优化:

  1. 先规划再分页生成,避免一次超长输出
  2. 模板复用,减少重复生成
  3. 缓存 embedding 和检索结果
  4. 把高频稳定内容做成规则或模板,不要每次都问模型

8.6 评估指标应该怎么定

项目落地后,至少看这些指标:

  1. 课件首版生成成功率
  2. JSON 校验通过率
  3. 首次渲染成功率
  4. 平均生成时长
  5. 单页重生成时长
  6. 用户修改次数
  7. TTS 生成成功率

8.7 一句话压缩技术选型

前端负责体验和渲染,后端负责模型、检索、技能编排和校验,数据层负责知识、状态和资源持久化。


9. 高频面试题

9.1 什么是 AI 应用开发

可以答:

AI 应用开发是在传统应用架构中加入模型推理、检索增强、工具调用和结构化输出能力,让系统能够理解用户意图、生成内容并触发业务动作。

9.2 LLM 集成时,为什么不能只靠 Prompt

可以答:

因为纯 Prompt 方式在复杂项目里稳定性不足,通常还需要结构化输出、工具调用、状态管理和结果校验来保证系统可控。

9.3 Structured Outputs 为什么比“请返回 JSON”更好

可以答:

因为 Structured Outputs 能约束字段结构并提高 schema 一致性,程序可以更稳定地直接消费结果,而不是赌模型每次都手写出合法 JSON。

9.4 RAG 是什么

可以答:

RAG 是检索增强生成,先从外部知识库召回相关内容,再把这些内容拼进上下文中辅助模型回答,从而提升准确率和时效性。

9.5 向量数据库和关系数据库有什么区别

可以答:

关系数据库更擅长精确查询和事务处理,向量数据库更擅长基于 embedding 做相似搜索和语义检索,两者通常是协作关系而不是替代关系。

9.6 为什么要做 chunk 切分

可以答:

因为原始文档通常太长,必须切成更适合检索的语义片段,切分质量会直接影响 RAG 的召回效果。

9.7 SSE 和 WebSocket 的区别是什么

可以答:

SSE 适合服务端单向推送,比如文本流式输出;WebSocket 适合双向实时通信,比如低延迟语音交互和实时控制。

9.8 Tool Calling 的价值是什么

可以答:

它让模型从只会生成文本,升级为能决定并触发程序动作。模型负责决策,程序负责确定性执行。

9.9 Skills 应该怎么设计

可以答:

Skills 最好单一职责、输入输出清晰、结构稳定、可观测,并尽量生成中间 DSL 而不是直接生成最终渲染层数据。

9.10 为什么课件项目里要设计中间 DSL

可以答:

因为 DSL 更贴近业务语义,更稳定、更容易校验,也方便统一主题样式和后续切换渲染引擎。最终坐标和样式更适合由程序编译生成。

9.11 为什么不能直接让模型生成最终 LeaferJS JSON

可以答:

因为最终渲染 JSON 结构冗长、字段多、对布局细节要求高,模型直接生成容易漂移和越界。更稳的方案是模型生成 DSL,程序做布局编译。

9.12 AI 项目里如何控制成本

可以答:

  1. 拆步骤,减少一次超长生成
  2. 缓存 embedding 和检索结果
  3. 模板化固定内容
  4. 对高频简单任务用更轻量模型
  5. 对失败流程做局部重试,而不是整链路重跑

9.13 TTS 和 ASR 在项目里分别有什么作用

可以答:

TTS 负责把文本结果转成语音输出,ASR 负责把用户语音转成文本输入,它们配合后可以形成完整的语音交互链路。

9.14 如果让你设计一个 AI 课件生成系统,你会怎么做

推荐答法:

  1. 先定义课件业务 DSL
  2. 设计页级规划模型
  3. 接入知识库和模板检索
  4. 用 Skills 生成每页组件结构
  5. 做 JSON Schema 校验与自动修复
  6. 编译为 LeaferJS JSON 渲染
  7. 增加单页重生成、TTS 和 ASR 能力

10. 更好记的学习方法

10.1 用一条链路记住 AI 应用

把所有内容压成这条链:

输入 -> 检索 -> 推理 -> 调工具 -> 输出结构 -> 渲染 -> 反馈

10.2 用“谁负责什么”来记

  • LLM:理解与决策
  • Embedding:把内容变向量
  • 向量库:找相似内容
  • Skills:执行工具能力
  • Schema:约束输出结构
  • LeaferJS:渲染画面
  • TTS:说出来
  • ASR:听进来

10.3 用对比法记忆

对比 1:RAG vs 微调

  • RAG:补知识
  • 微调:改风格和习惯

对比 2:SSE vs WebSocket

  • SSE:单向流
  • WebSocket:双向实时

对比 3:DSL vs 最终渲染 JSON

  • DSL:业务语义层
  • 渲染 JSON:画布执行层

对比 4:Prompt vs Skills

  • Prompt:告诉模型怎么想
  • Skills:让模型知道怎么做

10.4 用口诀记

  1. 模型会想,工具会做
  2. RAG 补知识,微调改习惯
  3. TTS 负责说,ASR 负责听
  4. SSE 先看结果,Realtime 先做交互
  5. 模型出 DSL,程序做布局

10.5 最有效的记忆方式是输出

你至少要做到:

  1. 能口头讲清 AI 应用链路
  2. 能画出课件项目架构图
  3. 能手写一个 DSL JSON
  4. 能回答 10 个面试题

如果能做到这四点,就不只是“看过”,而是“掌握了”。


11. 8 小时学习节奏建议

第 1 小时:建立总框架

目标:

  1. 先理解 AI 应用开发全景图
  2. 记住“模型、检索、工具、结构、渲染”五个关键词
  3. 明白这不是单纯调 API

第 2-3 小时:集中突破 LLM、结构化输出、Tool Calling

重点:

  1. Responses API
  2. Structured Outputs
  3. Tool Calling
  4. Prompt 分层设计
  5. 状态管理思路

这两个小时的目标是:

  1. 能说明模型在系统里扮演什么角色
  2. 能解释为什么要结构化输出
  3. 能说出 Prompt 和 Skills 的区别

第 4 小时:集中突破 Embedding、向量数据库、RAG

重点:

  1. Embedding 是什么
  2. RAG 链路
  3. chunk 切分
  4. metadata 过滤
  5. 向量库选型认知

输出目标:

能画出一条 RAG 流程图

第 5 小时:集中突破 SSE、Realtime、TTS、ASR

重点:

  1. SSE 流式展示
  2. Realtime 场景
  3. TTS 与 ASR 的位置
  4. 文本应用和语音应用的链路差异

输出目标:

能区分 SSE、WebSocket、Realtime

第 6-7 小时:完整看懂课件项目方案

重点:

  1. 为什么需要 DSL
  2. 为什么要 Skills
  3. 为什么要编译层
  4. 为什么要局部重生成
  5. 为什么检索知识和模板

输出目标:

能不看笔记讲清 AI 课件项目架构

第 8 小时:冲刺复盘

做三件事:

  1. 默写一页速记总结
  2. 回答面试题
  3. 用 5 分钟讲一遍你的项目方案

12. 一页速记总结

12.1 AI 应用核心链路

输入 -> 检索 -> 推理 -> 调工具 -> 结构化输出 -> 渲染/执行

12.2 LLM 核心定位

  • 理解用户意图
  • 生成文本或 JSON
  • 决策是否调用工具

12.3 向量数据库核心定位

  • 存向量
  • 做相似检索
  • 给 RAG 提供上下文

12.4 语音与流式核心定位

  • SSE:边生成边展示
  • Realtime:低延迟双向实时交互
  • TTS:文本转语音
  • ASR:语音转文本

12.5 Skills 核心定位

  • 把业务能力封装成可调用工具
  • 输入输出结构明确
  • 最好生成中间 DSL

12.6 课件项目核心设计

  • 先规划页级结构
  • 再生成每页组件 DSL
  • 再编译为 LeaferJS JSON
  • 前端支持预览和局部重生成

12.7 最重要的一句话

不要让模型直接控制最终渲染层,让模型负责语义和结构,让程序负责布局和稳定性。


13. 背诵口诀

13.1 总口诀

模型来想,检索来补,工具来做,结构来稳,前端来显。

13.2 RAG 口诀

先切再向量,检索找证据,拼进上下文,再让模型答。

13.3 流式与语音口诀

SSE 边看边出,Realtime 边说边回,TTS 负责说,ASR 负责听。

13.4 项目口诀

先规划,再分页;先 DSL,再编译;先校验,再渲染。

13.5 面试口诀

回答 AI 项目题时,尽量按这个顺序说:

  1. 业务目标
  2. 系统链路
  3. 数据结构
  4. 工具与检索
  5. 稳定性与优化

只要你按这个顺序说,回答就会比较完整。


附:这份笔记最值得反复看的三部分

第一次学习

重点看:

  1. AI 应用开发全景图
  2. LLM 集成核心
  3. 向量数据库与 RAG

第二次复习

重点看:

  1. Skills 设计
  2. AI 课件项目方案
  3. 技术选型与模块拆分

第三次冲刺

只看:

  1. 一页速记总结
  2. 背诵口诀
  3. 高频面试题

如果你能把这三部分不看笔记讲出来,说明你已经真正掌握了这套内容。