跳转至

AI Web 应用 — 跨过脚本与应用之间那条线

这一章讲什么: 每个开发者都会跨过一条线:线这边,你写脚本——有用, 但基本只服务你自己;线那边,你建应用——别人能点、能刷新、能依赖。 这一章带你跨过去,而且是用 AI 当脚手架。你将搭出一个最小但完整的闭环: 浏览器里一个输入框 → JavaScript 把文字发给你的 Flask 后端 → 后端问 OpenAI 的模型 → 回答回到页面上。 读完你会理解每一个现代 Web 应用的骨架:请求-响应循环。

1. 这一章讲什么

前八章的产物都有一个共同点:它们活在你的机器上、你的终端里。 这一章的产物第一次有了用户。书里给这个转变的定义很准: 它不在于复杂度增加多少,而在于心态——从「我写了个有用的 Python 脚本」 到「我建了一个别人能用的 Web 应用」3。

同时书里先澄清一个用词:「AI 驱动的 Web 应用」不是 AI 包办一切的应用, 而是 AI 在开发的特定环节、有意为之地点上帮忙的应用——决定仍然由你做, 只是不再独自一人、不再靠猜4。

为什么值得跨?Web 应用给你四样脚本给不了的东西5:

触达(Reach) 代码为任何有浏览器的人运行
持久(Persistence) 数据可以存、可以改、可以复用
交互(Interactivity) 用户不是读输出,而是与输出互动
可信度(Credibility) 交付一个应用,改变别人对你技能的看法

本章的边界也先说死:没有账户、没有数据库。 一个窄而清晰的目标—— 一个收文本、返回处理结果的端点——因为 AI 在请求具体的时候表现最好6。 这一章在全书链条里是落点:第一章的 key 纪律、第三章的 CCG、第四章的防御式错误处理、 第八章的管道,全部在这里合龙。

2. 顶层全景:请求-响应循环

  浏览器(用户视角)                Flask 后端(开发者视角)            模型(API)
  ─────────────────                ──────────────────────           ──────────
  输入框 textarea
      │ 点击按钮
      ▼
  fetch(POST /api/process, {text})  →  @app.route("/api/process")
                                        校验输入(非 JSON?缺字段?)
                                            │ 合法
                                            ▼
                                        client.chat.completions.create()
                                              →  AI 回复
                                        组装 JSON 响应 ◀──────────────
      ▼  回传 JSON
  页面更新 result 区域
  (404/CORS/JSON 错 → 各自的排查路径)

  图说:每一方只做一件事——浏览器发问,Flask 校验与转述,模型作答;全章就是给这三方接线的过程。

3. 核心原理

3.1 设计先于编码:API 契约

大多数人卡在第一行后端代码之前。 书里列了新手最常见的四个迷思: 先建哪个文件?路由放哪?逻辑怎么组织才能两周后不乱?小应用什么程度算「结构过多」?7

答案是一个反直觉的顺序:先让 AI 帮你设计,再让它写码。 第一条约好的提示:「我想用 Flask 建一个小型 Python 后端:一个 POST 端点收文本、返回 JSON。 请给一个初学者友好的项目结构,并解释每个文件干什么。」8 这条提示做了三件要紧的事:定了框架(Flask)、定了范围(单端点)、要解释而不只是要代码—— 最后一点比多数人想的更重要9。

AI 会给出两种常见结构:极简版 app.py + requirements.txt + README.md; 进阶版 app/(routes.py、services.py) + run.py + requirements.txt。 书里选了极简版起步——概念清晰之后随时重构10。

装 Flask 并固化依赖:pip install flask,然后 pip freeze > requirements.txt (把当前环境所有库及版本写进清单文件——重装环境时照单抓药)11。

3.2 最小端点:让 AI 写第一版,你逐行读懂

提示:「写一个最小的 Flask 应用:一个 POST 端点 /api/process,收 JSON、返回 JSON,初学者友好。」12

from flask import Flask, request, jsonify

app = Flask(__name__)                       # ① 创建应用

@app.route("/api/process", methods=["POST"]) # ② 声明:我只听这里的 POST
def process_text():
    data = request.get_json()               # ③ 取请求里的 JSON
    user_text = data.get("text", "")
    return jsonify({                        # ④ 组装 JSON 响应
        "original_text": user_text,
        "message": "Text received successfully"
    })

if __name__ == "__main__":
    app.run(debug=True)                     # ⑤ 启动开发服务器

逐行读懂(书里的要求:slow down and read it line by line13): Flask(__name__) 创建应用本体;request 是进来的请求,get_json() 把请求体解析成字典; jsonify 保证回出去的是干净的 JSON;@app.route(...) 那行装饰器(decorator, 贴在函数上方、给函数加功能的语法)的意思是「我在这个地址监听,且只听 POST」。 到此为止,你建的是一个标准 API——还没接 AI14。

3.3 接入 AI:密钥进环境变量,模型进端点

装 OpenAI 官方库:pip install openai,再 freeze 一次15。

密钥纪律(第一章的复述,本章升级为铁律):绝不把密钥硬编码(直接写死在代码里)进源码。 用环境变量:macOS/Linux export OPENAI_API_KEY=你的key, Windows PowerShell setx OPENAI_API_KEY 你的key——让密钥离开代码库和版本控制16。

改造端点:

from flask import Flask, request, jsonify
import os
from openai import OpenAI

app = Flask(__name__)
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))   # 从环境变量读 key

@app.route("/api/process", methods=["POST"])
def process_text():
    data = request.get_json()
    user_text = data.get("text", "")
    if not user_text:
        return jsonify({"error": "No text provided"}), 400

    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": user_text},
        ],
    )
    ai_reply = response.choices[0].message.content
    return jsonify({"input": user_text, "ai_response": ai_reply})

if __name__ == "__main__":
    app.run(debug=True)

三个技术点:os.getenv("OPENAI_API_KEY") 从环境变量取密钥; messages 是对话的角色列表(system 定人设、user 放输入); response.choices[0].message.content 从模型响应里剥出文本。 跑起来 python app.py,看到 Running on http://127.0.0.1:5000,你的 AI 后端就活了17。

测试端点的标准姿势 curl(在终端里直接发请求的工具):

curl -X POST http://127.0.0.1:5000/api/process \
  -H "Content-Type: application/json" \
  -d '{"text": "Explain AI in simple terms"}'

回的是一段 JSON:输入原样返回 + AI 的解答18。这个回包意味着三件事同时成立: 后端通了、端点通了、结构稳了19。

3.4 REST API:一套干净的四方法约定

REST API 听起来重,书里给了一个轻定义:它是你的后端与任何对话方(浏览器、 移动应用、别的服务、未来的你)之间的一份干净协议20。 四个要点:每个端点代表一种资源;用 HTTP 方法表达意图;响应可预测、结构化;错误显式处理21。 最常用的四个方法22:

方法 意图
GET 取数据
POST 创建或处理数据
PUT 更新已有数据
DELETE 删除数据

扩展端点前,先问 AI 要命名建议——这是本章第二个「设计先于编码」: 「我有一个 Flask 应用、一个 POST 端点。想扩成带清晰路由和错误处理的小 REST API。 先别写码,给端点名与职责的建议。」23 合理的回答:POST /api/process 处理文本;GET /api/status 健康检查。

健康检查端点(三行,日后监控与部署排障全靠它):

@app.route("/api/status", methods=["GET"])
def status():
    return jsonify({"status": "running", "message": "API is up and responding"})

浏览器直接访问 http://127.0.0.1:5000/api/status 就能看到 JSON24。 书里说它「看起来微不足道,日后无比有用」——监控、部署检查、调试,全靠这一口25。

让 POST 端点抗造。 它现在默认输入合法——太乐观,真实用户会搞坏一切。 提示:「改进这个 Flask POST 端点:优雅处理非 JSON、缺字段,返回有意义的错误。」26

@app.route("/api/process", methods=["POST"])
def process_text():
    if not request.is_json:
        return jsonify({"error": "Request must be JSON"}), 400
    data = request.get_json()
    text = data.get("text")
    if not text:
        return jsonify({"error": "Missing text field"}), 400
    return jsonify({"original_text": text, "length": len(text),
                    "message": "Text processed successfully"})

状态码是协议的一部分:400 表示「你的请求有问题」(而非服务器崩了)。 现在你的 API 会校验输入、说清楚话、可预测地失败——演示与可用品的分界就在这里27。 书里给了一个反常识的练习:故意发坏请求——不带 JSON、JSON 里不给 text 字段, 看返回的错误消息;测试坏情况比测试好情况教你的更多28。

路由的可读性纪律:端点变多,杂乱是真敌人。保持路由短、命名清、一个函数别塞太多; 路由一长,就是该让 AI 帮你重构的信号:「重构这个路由:把校验逻辑与处理逻辑分开,别加不必要的复杂度。」29

3.5 接上前端:浏览器怎么问到你的后端

后端藏在幕后,用户不跟 API 打交道,用户跟界面打交道。前后端的关系一句话30:

  用户在网页输入 → JavaScript 把数据发给 Flask API → Flask 处理 → JSON 返回 → JavaScript 更新页面

项目结构按 Flask 的约定摆(约定省配置):templates/ 放 HTML、static/ 放 JS/CSS31。

后端开一个页面路由:

from flask import render_template

@app.route("/")
def home():
    return render_template("index.html")

HTML 三件套(一个输入区、一个按钮、一块结果显示区):

<h1>Text Processor</h1>
<textarea id="userInput" rows="6" cols="50" placeholder="Type or paste text here…"></textarea>
<br><br>
<button id="submitBtn">Process Text</button>
<pre id="result"></pre>
<script src="/static/script.js"></script>

JavaScript 的核心是 fetch(浏览器里发 HTTP 请求的函数):

document.getElementById("submitBtn").addEventListener("click", async () => {
    const text = document.getElementById("userInput").value;
    const resultBox = document.getElementById("result");
    if (!text) { resultBox.textContent = "Please enter some text."; return; }
    resultBox.textContent = "Processing…";
    try {
        const response = await fetch("/api/process", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ text })
        });
        if (!response.ok) throw new Error(`Server error: ${response.status}`);
        const data = await response.json();
        resultBox.textContent = JSON.stringify(data, null, 2);
    } catch (error) {
        console.error("Request failed:", error);
        resultBox.textContent = `Something went wrong: ${error.message}`;
    }
});

这段脚本的骨架:读输入 → 发请求 → 显示响应,外加两条失败路径(网络层、HTTP 层)。 书里建议对流程本身再追问 AI:「逐步解释这个 fetch 调用怎么和我的 Flask 后端通信, 包括请求失败时会发生什么」——用它强化理解,而不是跳过理解32。

全链路测试四步:起 Flask → 开浏览器 → 输文字 → 点按钮。 看到回包的那一刻,书里的话是:浏览器、JavaScript、后端、逻辑、响应——全部连上了, 这就是每个现代 Web 应用的地基33。

前端出错三剑客(书里把每个错误都标成教材):

症状 病根 排查起点
404 (NOT FOUND) 路由不匹配——fetch 的地址和后端声明的地址对不上 核对两边路径逐字符
CORS 错误 前后端不同源(不同域名或端口) 本章 setup 不会遇到(见下注)
JSON 解析错 请求头缺 Content-Type 或请求体不是合法 JSON 查 headers 与 body

CORS 为什么本章遇不到:Flask 同时从同一个源(同域名同端口)伺服 HTML、JS 和 API, 跨源问题不存在;一旦前后端分开部署,它必然出现(补充:CORS 是浏览器的跨源安全机制, 需要后端额外放行)34。

3.6 错误处理:从「终端红字」到「接口语言」

脚本里的错误和 Web 应用里的错误是两个物种。 脚本崩了,终端给你红字,清清楚楚; 应用里的错误会躲——后端失败显示为白屏,前端 bug 表现为「点了没反应」35。 所以错误处理与测试在跨线之后不再是可选项36。

错误的四分类(书里给的全景):输入错误(用户数据缺失或非法)、逻辑错误(跑通但结果错)、 运行时错误(执行中抛异常)、集成错误(前后端没谈拢)。 修任何东西之前,先判断是哪一类——这一步本身就该问 AI: 「这是我的 Flask 应用的一个报错。帮我判断它属于哪一类,通常什么原因引起。」37

故意打破再修复的练习(本章的调试教学):

  1. 把路由里 data.get("text") 改成 data["text"],发空 JSON → 终端 KeyError: 'text'。 书里的解读:这不是 Flask 的问题,是 Python 在告诉你发生了什么38。 好提示:「这个路由在缺 text 字段时抛 KeyError。解释为什么,并给一个不掩盖错误的防御写法。」39
  2. 防御版:先 if not request.is_json: return ..., 400,再 if "text" not in data: return ..., 400, 最后才取 data["text"]。既保护应用,也告诉用户哪错了40。
  3. 前端版:把 fetch 的 URL 改错 → 点按钮没反应 → 打开浏览器开发者控制台,看到 404。 这不是 JavaScript 的 bug,是路由不匹配。问 AI:「我的前端 fetch 返回 404。 Flask + JavaScript 设置里我先查什么?」41

调试提示的好与坏(书里的对照,与第三章同源):

  • 坏:「我的 Flask 应用不工作。」——AI 只能猜;
  • 好:「这个路由用 curl 测能过,但从 JavaScript 调就失败。这是路由、fetch 调用和报错信息。」42

基础测试四习惯(不需要任何框架):curl/Postman 测端点;后端改了刷新浏览器; 开发期 print 中间值;故意搞坏东西。再配一句:「这个端点该测哪些边界情况?」43

何时不该信 AI 的建议(本章的清醒剂):AI 会建议让错误静音而不解决的修复、 加不必要的复杂度、掩盖更深的逻辑问题。每次采纳前问自己:我懂这个修复为什么有效吗? 它让代码更清楚吗?下次我自己会这么写吗?——有一个答不上,就慢下来44。

3.7 动手项目:迷你 AI 应用(书里的完整作业)

本章的练习是一道没有标准答案的大题:从文本摘要器、聊天机器人、情感分析器里挑一个, 用 Flask + HTML/JS + ChatGPT 提示,独立做出一个能给别人用的小应用45。 书里给的不是答案,是七步脚手架,每步一条「问自己的问题 + 问 AI 的提示」:

  1. 定义目的——「输入是什么?用户该看到什么输出?」先写下来,再碰代码;
  2. 搭后端骨架——一个 GET(状态或首页)+ 一个 POST(处理输入);
  3. 设计接口契约——「请求和响应的 JSON 长什么样?」字段、错误、成功三种形状先定死;
  4. 建前端——输入区 + 提交按钮 + 结果区,让 AI 写最小的 HTML/JS;
  5. 接入 AI——把模型调用塞进 POST 路由,聚焦校验、清晰输出、优雅失败;
  6. 制造并处理错误——空输入、非法 JSON、网络失败,故意各来一遍,只采纳你懂的修复;
  7. 改进结构——「怎么重构才能更可读、职责更清,又不过度设计?」收尾。

书里的验收标准只有一句:如果一个真实用户能毫无困惑地用你的应用,你就做完了46。 注意这条标准里没有「代码漂亮」——用户视角是这一章的总法官。

3.8 章末 Key Terms 七词与收尾判断

术语 含义
REST API 系统间用可预测的 URL 与请求类型通信的结构化方式
Endpoint(端点) Web 应用里做一件具体事的 URL(处理输入或返回数据)
HTTP Methods 描述请求意图的标准动作(GET、POST 等),不描述怎么做
Request–Response Cycle 数据的全旅程:请求 → 服务器处理 → 响应
Frontend–Backend Integration 用户所见(HTML/JS)与幕后逻辑(Python)的连接
Error Handling 预期失败,用清晰有意义的消息回应,而不是崩溃或沉默47

本章结语里有一句值得原文带走: 工具会变(今天 Flask、明天别的), 但你在这里练的思考——请求怎么流动、逻辑怎么安全地暴露、AI 怎么在不夺权的前提下 支持设计与调试——会留下来48。

3.9 章末 Points to Remember 五条(书里的原话收拢)

原书收尾五条,照录——每一条都能指回本章的某一节:

  1. Web 应用是对话,不是脚本:每个动作都是输入 → 处理 → 反馈;理解这个流,调试才容易;
  2. 好的 API 在编码前设计好:早想路由、输入、输出,项目长大后不迷路;
  3. 错误消息是界面的一部分:一条清楚的错误同时帮用户与未来的开发者;
  4. AI 在你已有上下文时最有用:你的提示与解释越好,它的输出越准;
  5. 简洁胜过后端的小聪明:直白的代码好测、好修、好扩展49。

第五条是本章的隐藏纪律:Flask 不强制结构,这是它的优点也是危险—— 「route 里塞六个职责」在 Flask 里没有任何东西拦你。书里给的约束是自觉的: 路由短、命名清、一个函数别贪多;route 变长就是重构信号50。 外加那句收尾格言:「如果你能大声把你的应用讲出来,你就懂它了」—— 讲不清楚的地方,就是结构模糊的地方51。

3.10 从本地到别人的电脑:一个没写进书里的下一步

本章的应用跑在 127.0.0.1——只你自己能访问。书里到此为止, 但「别人能用」只差一步,值得点破(补充,不在书里,来自通用知识): 把 app.run(debug=True) 换成 app.run(host="0.0.0.0"), 同一局域网的人就能用你电脑的 IP 访问;要全世界能访问,需要部署到服务器 (书中未覆盖,见书卡 notCovered)。不要在 debug 模式下对外暴露—— 详细报错页会把你的代码结构透给任何访问者。这一步之险与这一步之近, 是本章留给读者的最后一个功课。

3.11 章节的暗线:一切始于「设计先于编码」

回看全章,九节内容其实只讲了一个习惯的两次应用:

  习惯:先设计,后编码——接口的形状先于实现存在
      │
      ├─ 应用一(§3.1):先要「项目结构 + 每个文件干什么」,再写码
      └─ 应用二(§3.4):先要「端点名与职责」,再写码
              │
              ▼
  同样的习惯在第四章是「先写失败测试」,
  在第三章是「先要结构不要代码」——全书是同一个主张的多次变奏。

这个习惯为什么如此重要?因为 AI 编码的引入把「写」变便宜了, 「想清楚」成了唯一的瓶颈——你设计的接口越清楚,AI 填空越准;你设计的接口含糊, AI 就替你瞎猜,而猜错的重构成本远高于想清的成本。 第九章把这个道理讲到了 Web 上。

3.12 全章的一句话验收

收一张验收卡——做完本章的动手项目后逐条自问:

  □ 我能画出浏览器 → JS → Flask → OpenAI → 原路返回 的箭头图吗?
  □ 我能不看代码说出 /api/process 收什么、回什么、哪几种错吗?
  □ curl 测过三个坏请求(无 JSON / 缺字段 / 错路径),返回都符合预期吗?
  □ 密钥在任何 .py 文件里都搜不到吗?(grep 自查)
  □ 换一个没看过代码的人,能不看解释就用这个应用吗?

五条全勾,本章达标;勾不满的那条,回到对应的小节。 书里的验收标准是最后一条46——其余四条是我们加的脚手架, 为的是让「别人能用」这个软标准有硬支撑。52

3.13 部署之外的两个「差一点」(书里没写、从缺口推的)

第九章把应用跑在本地之后,离「别人能用」还差两件事,书里停下了,我们补上 (通用知识,不改变书中任何结论):

第一件:持久化。 本章的端点把用户输入问完就忘——刷新页面,对话历史归零。 让应用「记住」需要数据库(书卡 notCovered 已列):最小可行方案是 SQLite—— 单文件、零安装、够用到几千用户。Flask 与之对接只需一个库(SQLAlchemy 或 sqlite3), 但「表怎么设计」是全新的思考维度,值得单独一章。

第二件:并发。 app.run(debug=True) 的开发服务器一次只处理一个请求; 两个人同时点按钮,第二个就排队。生产服务器(gunicorn/uwsgi)用多进程或协程解决, 但那引入「全局状态不能乱用」「请求之间怎么隔离」的新纪律。 这两条缺口正好是「下一步学什么」的答案——书末的未来方向里, 「学基础后端架构」一项说的就是把这两条补上53。

3.14 前端代码的读法(本章的「读懂」回合)

第九章也是第二章读法的一次实战:那 30 行 fetch 代码,按第二章的问法走一遍——

问「是什么」: 给按钮挂了一个点击监听器;点击后读输入框文本,POST 给 /api/process; 把返回的 JSON 格式化显示;出错时在结果区显示错误消息。

问「为什么」: 为什么先 if (!text) 再发请求?——空输入发过去也是 400, 本地拦下省一轮往返,体验更快;为什么 try/catch 里还查 response.ok?—— HTTP 层的错(404、500)不抛异常,网络层的错(断网)才抛,两层都要接54。

问「怎么办」: 「怎么在请求期间禁用按钮防重复提交?」「怎么把 JSON 显示换成漂亮的格式化?」 ——全是让 AI 给变体的标准句式。

走完这一圈,前端代码不再是「浏览器里的魔法」:它就是第二章的代码, 只是宿主从 Python 换成了 JavaScript。语言换了,读法没换——这正是第二章 「读法总谱」跨语言的证据。

3.15 好错误的三性质:书里给错误处理定的验收标准

§3.6 讲了错误处理怎么写,这一节讲写完了怎么验收——书里在错误处理的结尾 给了三条性质,作为「这个 API 的错误处理算不算合格」的判据1:

性质 含义 本章的对应实现
校验输入 不合法的东西进不来,或进来就挡下 检查 request.is_json、用 .get() 取字段
说得清 错误信息人读得懂,不是一坨 traceback 回 {"error": "..."} 带一句人话
败得可预期 同样错输入,永远同样错输出 每种坏请求都有固定状态码与固定 JSON 形状

书里紧跟一句判语:「这就是 demo(演示)与「能用的东西」之间的差别」2。 这句话值得当成本章的门槛——跑通一次成功请求只证明它是 demo; 故意发三种坏请求(空 JSON、缺字段、错路径)都得到预期响应,才证明它能用。 §3.12 验收卡里「curl 测过三个坏请求」一条,源头就在这里。

判断(我们的,不是书里的): 三性质里「败得可预期」是最容易被新手跳过、 又最值钱的一条——它的本质是「错误也是接口契约的一部分」: 前端(或任何调用方)能靠稳定的错误形状做分支,而不是每次解析一坨未知文本。 如果错,会错在: 对内部脚本,三性质是过度设计(脚本的用户是你自己, 错误形状稳定与否无所谓);本章是 Web 应用,调用方是别人,所以成立。

4. 作者的判断与证据

有演示支撑的判断:

  • 「设计先于编码」的两轮实践(先要结构、先要端点命名)——演示完整,可直接复用8;
  • 「错误信息是接口的一部分」——用故意打破-修复的两个练习支撑,是本章最扎实的教学40。

经验之谈:

  • 「健康检查端点日后无比有用」——运维常识,可信25;
  • 「curl 先行、浏览器殿后」的调试顺序——好习惯,但复杂前端状态(登录态、依赖前端路由)时 curl 覆盖不全。

推测:

  • 「把 AI 集成进端点就是『真正 AI 驱动』的时刻」——修辞性表述,技术上是把 API 调用包进路由而已17。

5. 边界与局限

  • 没有数据库与用户系统:书里明说「没有账户、没有数据库」——持久化、登录、会话全靠你自己后续补;
  • debug=True 不能上生产:开发模式的自动重载与详细报错页会泄露代码;部署要换生产服务器(gunicorn 等),本章未涉;
  • 没有鉴权与限流:端点裸露在公网会被刷爆;真实应用要加 API key/登录与速率限制;
  • 模型调用无重试与超时:网络抖动时端点会挂;生产要加超时、重试、降级;
  • 前端极简:一个 textarea 的静态页;真实产品的前端复杂度高几个数量级,本章只是打通链路。

6. 可带走的

本章主线例子,一行写完: pip install flask openai → app.py 里 POST /api/process (校验 JSON→取 text→调 OpenAI→回 JSON)→ GET /api/status 健康检查 → templates/index.html + static/script.js(fetch POST→渲染)→ curl 测 → 浏览器测 → 故意发坏请求 → 防御式改版。

  1. 应用与脚本的差别在人:别人能用、能依赖;
  2. 设计先于编码:先要结构、先要端点命名,先写「请求/响应长什么样」再写实现;
  3. 密钥永远走环境变量:os.getenv,不进代码、不进仓库;
  4. 端点三件套:POST 处理、GET 查健康、400 说人话;
  5. 请求-响应循环是地基:浏览器问、后端转述、模型答、页面更新;
  6. Flask 的 templates/static 约定省配置;fetch 是前端的发报机;
  7. 错误四分类先判型再修;「脚本红字 vs 应用沉默」是两个物种;
  8. 故意搞坏是必修课:空 JSON、错 URL、缺字段,坏请求教得比好请求多;
  9. 调试提示带三样:代码、报错、你怎么触发的——「不工作」三个字值零;
  10. 采纳 AI 修复前三问:懂为什么吗?更清楚吗?下次自己会写吗?44

7. 原文地图

主题 原书章 原文位置
脚本与应用的线 Building an AI-Powered Web Application text/21-ch09-9-building-an-ai-powered-web-application.txt:18(搜「line most developers cross」)
AI 驱动≠AI 包办 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:33(搜「specific, intentional points」)
Web 应用四样 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:46(搜「Reach」)
没有账户没有数据库 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:148(搜「No accounts」)
先要结构提示 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:163(搜「beginner-friendly project structure」)
最小端点与逐行读懂 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:276(搜「minimal Flask app」) · text/21-ch09-9-building-an-ai-powered-web-application.txt:318(搜「line by line」)
密钥走环境变量 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:375(搜「Never hardcode」) · text/21-ch09-9-building-an-ai-powered-web-application.txt:385(搜「export OPENAI_API_KEY」)
接入 AI 与运行 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:415(搜「OpenAI(api_key」) · text/21-ch09-9-building-an-ai-powered-web-application.txt:496(搜「Running on http」)
curl 测试 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:508(搜「curl -X POST」)
REST 四方法 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:594(搜「Method」)
先要端点命名 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:693(搜「suggest endpoint names」)
健康检查端点 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:719(搜「api/status」)
防御式 POST 与故意发坏 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:800(搜「Request must be JSON」) · text/21-ch09-9-building-an-ai-powered-web-application.txt:850(搜「Try sending bad requests」)
前后端接线五步行 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:972(搜「types something」)
templates/static 约定 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:1025(搜「templates folder」)
fetch 脚本 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:1142(搜「addEventListener」)
404/CORS/JSON 三剑客 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:1311(搜「404 errors」)
错误四分类 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:1388(搜「Input Errors」)
KeyError 与防御版 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:1452(搜「KeyError」) · text/21-ch09-9-building-an-ai-powered-web-application.txt:1505(搜「Expected JSON input」)
不信 AI 建议三问 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:1655(搜「Silence errors」) · text/21-ch09-9-building-an-ai-powered-web-application.txt:1669(搜「understand why」)
七步动手项目 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:1694(搜「Build a Mini」)
用户验收标准 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:1865(搜「without confusion」)
Key Terms 六词 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:1872(搜「REST API」)
工具会变思考会留下 同上 text/21-ch09-9-building-an-ai-powered-web-application.txt:1688(搜「remain relevant」)

  1. 出处:「Building an AI-Powered Web Application」第 834–840 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:834,搜「Validates input」;:837,搜「Communicates clearly」;:840,搜「Fails predictably」)。 ↩

  2. 出处:「Building an AI-Powered Web Application」第 844 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:844,搜「demo and something usable」)。 ↩

  3. 出处:「Building an AI-Powered Web Application」第 18 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:18,搜「line most developers cross」)。 ↩

  4. 出处:「Building an AI-Powered Web Application」第 33 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:33,搜「specific, intentional points」)。 ↩

  5. 出处:「Building an AI-Powered Web Application」第 46 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:46,搜「Reach」)。 ↩

  6. 出处:「Building an AI-Powered Web Application」第 148 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:148,搜「No accounts」)。 ↩

  7. 出处:「Building an AI-Powered Web Application」第 92 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:92,搜「Which file do I create first」)。 ↩

  8. 出处:「Building an AI-Powered Web Application」第 163 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:163,搜「beginner-friendly project structure」)。 ↩↩

  9. 出处:「Building an AI-Powered Web Application」第 180 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:180,搜「matters more」)。 ↩

  10. 出处:「Building an AI-Powered Web Application」第 228 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:228,搜「simpler version」)。 ↩

  11. 出处:「Building an AI-Powered Web Application」第 255 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:255,搜「pip freeze」)。 ↩

  12. 出处:「Building an AI-Powered Web Application」第 276 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:276,搜「minimal Flask app」)。 ↩

  13. 出处:「Building an AI-Powered Web Application」第 318 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:318,搜「line by line」)。 ↩

  14. 出处:「Building an AI-Powered Web Application」第 344 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:344,搜「standard API」)。 ↩

  15. 出处:「Building an AI-Powered Web Application」第 362 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:362,搜「pip install openai」)。 ↩

  16. 出处:「Building an AI-Powered Web Application」第 375 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:375,搜「Never hardcode」)。 ↩

  17. 出处:「Building an AI-Powered Web Application」第 481 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:481,搜「genuinely AI-powered」)。 ↩↩

  18. 出处:「Building an AI-Powered Web Application」第 508 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:508,搜「curl -X POST」)。 ↩

  19. 出处:「Building an AI-Powered Web Application」第 542 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:542,搜「structure is sound」)。 ↩

  20. 出处:「Building an AI-Powered Web Application」第 555 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:555,搜「clean agreement」)。 ↩

  21. 出处:「Building an AI-Powered Web Application」第 568 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:568,搜「Each endpoint」)。 ↩

  22. 出处:「Building an AI-Powered Web Application」第 594 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:594,搜「Method」)。 ↩

  23. 出处:「Building an AI-Powered Web Application」第 693 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:693,搜「suggest endpoint names」)。 ↩

  24. 出处:「Building an AI-Powered Web Application」第 719 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:719,搜「api/status」)。 ↩

  25. 出处:「Building an AI-Powered Web Application」第 767 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:767,搜「incredibly useful later」)。 ↩↩

  26. 出处:「Building an AI-Powered Web Application」第 785 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:785,搜「gracefully handles」)。 ↩

  27. 出处:「Building an AI-Powered Web Application」第 844 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:844,搜「demo and something usable」)。 ↩

  28. 出处:「Building an AI-Powered Web Application」第 895 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:895,搜「more than the successful ones」)。 ↩

  29. 出处:「Building an AI-Powered Web Application」第 40–41 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:927,搜「separate validation」)。 ↩

  30. 出处:「Building an AI-Powered Web Application」第 972 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:972,搜「types something」)。 ↩

  31. 出处:「Building an AI-Powered Web Application」第 1025 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1025,搜「templates folder」)。 ↩

  32. 出处:「Building an AI-Powered Web Application」第 1301 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1301,搜「step by step」)。 ↩

  33. 出处:「Building an AI-Powered Web Application」第 1292 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1292,搜「foundation of every modern web app」)。 ↩

  34. 出处:「Building an AI-Powered Web Application」第 1311 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1311,搜「404 errors」)与第 1332 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1332,搜「same origin」)。 ↩

  35. 出处:「Building an AI-Powered Web Application」第 1371 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1371,搜「backend failure may show up」)。 ↩

  36. 出处:「Building an AI-Powered Web Application」第 1378 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1378,搜「not optional」)。 ↩

  37. 出处:「Building an AI-Powered Web Application」第 1410 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1410,搜「category of error」)。 ↩

  38. 出处:「Building an AI-Powered Web Application」第 1452 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1452,搜「KeyError」)。 ↩

  39. 出处:「Building an AI-Powered Web Application」第 1467 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1467,搜「without hiding the error」)。 ↩

  40. 出处:「Building an AI-Powered Web Application」第 1532 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1532,搜「protects your app」)。 ↩↩

  41. 出处:「Building an AI-Powered Web Application」第 1571 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1571,搜「404 (NOT FOUND)」)与第 1586 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1586,搜「should I check first」)。 ↩

  42. 出处:「Building an AI-Powered Web Application」第 1607 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1607,搜「works when tested with curl」)。 ↩

  43. 出处:「Building an AI-Powered Web Application」第 1626 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1626,搜「curl or Postman」)。 ↩

  44. 出处:「Building an AI-Powered Web Application」第 1655 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1655,搜「Silence errors」)与第 1669 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1669,搜「understand why」)。 ↩↩

  45. 出处:「Building an AI-Powered Web Application」Hands-on Project(text/21-ch09-9-building-an-ai-powered-web-application.txt:1694,搜「Build a Mini」)。 ↩

  46. 出处:「Building an AI-Powered Web Application」Hands-on Project 收尾(text/21-ch09-9-building-an-ai-powered-web-application.txt:1865,搜「without confusion」)。 ↩↩

  47. 出处:「Building an AI-Powered Web Application」Key Terms(text/21-ch09-9-building-an-ai-powered-web-application.txt:1872,搜「REST API」)。 ↩

  48. 出处:「Building an AI-Powered Web Application」结论段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1688,搜「remain relevant」)。 ↩

  49. 出处:「Building an AI-Powered Web Application」Points to Remember(text/21-ch09-9-building-an-ai-powered-web-application.txt:1895,搜「Conversations, Not Scripts」至 :1911,搜「Beats Cleverness」)。 ↩

  50. 出处:「Building an AI-Powered Web Application」第 918 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:918,搜「signal」)。 ↩

  51. 出处:「Building an AI-Powered Web Application」Points to Remember(text/21-ch09-9-building-an-ai-powered-web-application.txt:1915,搜「Explain Your App out Loud」)。 ↩

  52. (我们的验收清单;用户标准一条出自原书,见 text/21-ch09-9-building-an-ai-powered-web-application.txt:1865。) ↩

  53. 出处:「Best Practices and Optimization」第 737 段(text/22-ch10-10-best-practices-and-optimization.txt:737,搜「Learn Basic Backend Architecture」)。持久化与并发的具体机制是通用知识,不在书里。 ↩

  54. 出处:「Building an AI-Powered Web Application」第 1190 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1190,搜「response.ok」)与第 1311 段(text/21-ch09-9-building-an-ai-powered-web-application.txt:1311,搜「404 errors」)。 ↩