WEEK 11 / 16 AI 应用 · RAG 实战 / 多模态
PYTHON 程序设计 · V2 · 第 11 周(100 分钟 · L23–L24)

搭一个知识库问答
再让 AI 看图说话

上周的原理今天变成产品:numpy 手搓完整 RAG 链路(不用任何框架), 做出「课程 FAQ 问答机器人」;然后串起 Vision(看图)→ 文本 → TTS(说话)的多模态链路。

所属模块 M5 AI 应用开发← → 翻页 · F 全屏

今日课表(100 分钟)

时间环节要点
0–8今日目标课程 FAQ 问答机器人——把上周原理变成产品
8–20离线建库切分 chunk → Embedding API → numpy 存向量;chunk 大小是可调参数
20–34在线检索生成余弦相似度全库打分 → top-k → 拼接 prompt → 有据回答
34–46动手练习运行场:二维语义地图上的余弦检索排序
46–58调参实验改 k(2→5)、改 chunk 大小,观察命中变化——检索质量决定上限
58–68为什么不用框架LangChain 把每步藏进黑盒;numpy+SDK 每行看得见
68–80多模态:看图Vision API;base64/URL 传图;OCR/图表解读
80–90多模态:说话TTS 文字转语音;模态链路=一个 API 的输出是另一个的输入
90–100小测随堂小测 3 题

今日产出:一个能回答课程问题的 RAG 问答系统(numpy 手搓版)。

今日目标:课程 FAQ 问答机器人

课程文档 ×N 份
→
numpy 向量库
→
提问「作业怎么提交」
→
检索 top-3
→
基于资料的回答
为什么不用 LangChain?框架把每一步都藏进黑盒——课程要求每一行都看得见、改得动: numpy + openai SDK 就是全部依赖。理解了原理,框架只是「别人替你写好的循环」。

阶段一:离线建库

import numpy as np

# 1) 文档 → 切块(chunking)
chunks = split_docs(docs, size=200)        # 按段落/长度切

# 2) 每块 → 向量(Embedding API,一次性)
vecs = np.array([embed(c.text) for c in chunks])   # (N, 1536)

np.save("kb_vectors.npy", vecs)      # 存下来,下次不用重新算钱

阶段二:在线检索 + 生成

def cosine(a, b):                          # 余弦相似度:方向越一致越相关
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

def answer(question, k=3):
    qv = embed(question)
    scores = [ cosine(qv, v) for v in vecs ]       # 全库打分
    top = np.argsort(scores)[::-1][:k]            # 取 top-k

    context = "\n\n".join(chunks[i].text for i in top)
    return llm_chat(
        f"基于以下资料回答问题,没有依据就说不知道:\n\n{context}\n\n问题:{question}"
    )

动手:向量检索的直觉

交互 · 二维「语义地图」上的余弦检索

多模态:让 AI 看图与说话

Vision看图
  • 图片 → base64 编码(或 URL)放进消息
  • 应用:OCR、图表解读、视觉问答
TTS说话
  • 文本 → 语音文件(.mp3)
  • 程序可直接播放或保存
模态链路设计模式:一个 API 的输出是另一个 API 的输入。
课堂演示「图片描述生成器」:读图片 → Vision 生成描述 → TTS 朗读保存。

判断力:不是所有场景都要多模态——能用文字说清的,不必强行看图。

随堂小测(3 题)

交互 · 点击选项作答

课后与下周预告

本周课后
  • 练习:给迷你知识库加两份自己的文档,测试检索命中
  • 交互演示复习:RAG 流程模拟
下周:W12 AI Agent 从「你问它答」到「它自己决定调什么工具」——手写 ReAct 循环,不用任何框架。 提前看下周课件 →

深入阅读:M5 模块页 · 经典笔记 15.4(数据→结论链路)