FastAPI 入门:查询参数、请求体与接口调试

这是我学 FastAPI 时整理的入门笔记。FastAPI 是现在最流行的 Python 后端框架之一,我用它完整走了一遍「写接口 → 启动服务 → 测试 → 读懂报错」的闭环。 一句话总结它的本质: 用 Python 写「后端接口(API)」的框架,靠类型注解自动帮你校验数据、生成文档。 下面按我实际学习的顺序展开。 一、FastAPI 是什么 先拆解几个词: 后端接口(API):你刷新页面、点开 App 时,背后有个服务器在「收到请求 → 处理 → 返回数据」。写这个逻辑就是写后端,对外的"窗口"就是 API。 框架(framework):别人提前搭好的脚手架,你只填业务逻辑,不用从零造轮子。 类比:你开餐厅,FastAPI 就是已经装修好的厨房——灶台水管都通了,你只管炒菜。 它这几年特别火,三个杀手锏: 快:性能在 Python 框架里数一数二(基于异步 asyncio)。 自动生成交互式文档:写完代码自动给你一个能点击测试的网页。 自动校验数据:声明字段类型,传错自动报错,不用手写校验。 对新手尤其友好:它强依赖 Python 类型提示,学它的同时 Python 基本功也会变扎实。 二、最小可运行例子 from fastapi import FastAPI app = FastAPI() # 创建一个"应用"实例 @app.get("/") # 当有人 GET 访问根路径 "/" 时... def read_root(): return {"hello": "world"} # ...就返回这个 JSON 逐行看: 代码 人话解释 app = FastAPI() 开张,建一个 app @app.get("/") 装饰器:下面这个函数负责处理 GET 访问 / 的请求 def read_root() 真正干活的函数 return {...} 返回的字典会被自动转成 JSON 发出去 三、接收数据的三件套 写接口的核心就是「怎么接收别人传来的数据」。FastAPI 有三种方式。 ...

4 min · 653 words · Jiaju

FastAPI 响应模型与请求体学习笔记

这篇是我接着上次学 FastAPI 时整理的笔记。上次学的都是「数据怎么进来」(查询参数、请求体、校验),这次换了个方向,研究「数据怎么出去」——也就是 response_model,顺带把困扰我很久的「请求体 vs 查询参数」彻底分清楚了。 一句话总结这次的核心: response_model 是给接口出口装的筛子:你规定它只准返回哪些字段,多余的(比如密码)自动被丢掉。 下面按「响应模型 → 请求体 vs 查询参数 → 路由和参数到底是什么 → 最该记住的几点」来展开。 一、响应模型 response_model 1. 先讲痛点:返回数据会泄露敏感字段 在 FastAPI 里有条铁律:你 return 什么,前端就收到什么。 假设数据库里的用户带密码字段: class User(BaseModel): username: str password: str # 敏感字段! email: str @app.post("/users/") async def create_user(user: User): return user # 灾难:把 password 原样返回给了前端 这样写,密码就跟着 JSON 一起发出去了。response_model 就是用来堵这个漏洞的。 类比一下:Pydantic 请求体像安检进站(检查你带进来的东西);response_model 像安检出站(检查你带出去的东西,违禁品没收)。 2. 怎么用:进、出各写一个模型 经典套路是定义两个模型——一个收(带敏感字段),一个发(不带)。 from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() # 进:注册时前端要传的(含密码) class UserIn(BaseModel): username: str password: str email: str # 出:返回给前端的(不含密码!) class UserOut(BaseModel): username: str email: str @app.post("/users/", response_model=UserOut) # 关键在这 async def create_user(user: UserIn): return user # 即使返回了带 password 的对象,也会被过滤成 UserOut 神奇之处:函数里 return 的明明是带密码的 user,但前端收到的 JSON 里根本没有 password。FastAPI 在出门那一刻,按 UserOut 重新「拓印」了一份。 ...

3 min · 471 words · Jiaju

A Scroll-Animated Roadmap Timeline for My Projects

While rebuilding the landing page of TicketCoach — my AI sparring-partner system for customer-support training — I replaced the usual feature grid with a progress timeline: one vertical line, one dot per milestone. Shipped work glows in a purple gradient; future work stays gray and dashed. As you scroll, the bright line literally grows down the page and stops exactly at the last completed dot. I ended up liking this little UI more than the product page itself. So I extracted it into a Hugo shortcode, and from now on every project I write about here gets one of these. This post is both the first real use of it and a short note on how it works. ...

4 min · 732 words · Jiaju

RAG 入门:在模型回答之前,先检索资料

这篇是我学 RAG 时的白板笔记整理。RAG(Retrieval-Augmented Generation,检索增强生成)是现在几乎所有"让 AI 读自己资料"产品的底层套路,比如企业知识库问答、文档助手、客服机器人。 一句话总结它的本质: 在模型回答之前,先检索资料,再基于资料生成回答。 下面按"为什么需要它 → 它怎么工作"的顺序展开。 一、为什么需要 RAG 1. 直接把所有资料喂给模型,为什么不可行? 最朴素的想法是:把全部文档塞进 prompt,让模型自己看。这条路有三个问题: 上下文窗口有限。模型一次能读的 token 数是有上限的,几百页的文档根本塞不下。 成本。就算塞得下,每次提问都把全部资料发一遍,token 费用会爆炸。 响应速度。输入越长,模型处理越慢,用户体验直线下降。 2. 模型本身也有短板 就算不考虑塞资料的问题,纯靠模型自己回答也有硬伤: 知识过时。模型的知识停留在训练截止日期,问它昨天发生的事它不知道。 私有数据。公司内部文档、个人笔记,模型训练时根本没见过。 幻觉。不知道的事情它可能一本正经地编。 RAG 的思路就是绕开这些限制:资料放在模型外面,每次只把和问题相关的一小段喂进去。 二、核心流程 整个 RAG 分两个阶段:数据准备(离线,只做一次)和用户提问(在线,每次提问都执行)。 flowchart LR subgraph prep["① 数据准备(离线,只做一次)"] direction LR A["📄 原始文档"] --> B["切分 Chunking按章节 / 段落 / 字数……"] B --> C["🧩 Chunks每一块语义相对完整"] C --> D["Embedding(向量化)"] D --> E[("向量数据库")] end flowchart LR subgraph query["② 用户提问(在线,每次提问都执行)"] direction LR Q["❓ 用户问题"] --> QE["问题也做Embedding"] QE --> S["相似度检索找距离最近的 top-k 块"] V[("向量数据库")] --> S S --> P["相关资料 + 问题拼成 Prompt"] P --> L["🤖 LLM 生成回答"] end 第一步:数据准备 切分(Chunking) 文档不能整篇存,要先切成一块块的 chunk。切分的依据可以是章节、段落、字数……没有标准答案,但有一条核心原则: ...

1 min · 207 words · Jiaju

A Records vs CNAME Records: How to Point a Domain at Your Website

I recently bought a domain and pointed it at my GitHub Pages site. It sounds like a one-click thing, but it comes down to two little DNS records: an A record and a CNAME record. Once I understood what each one does, the whole process stopped feeling like magic. Here’s the explanation I wish I’d had. A 30-Second DNS Refresher When someone types example.com into a browser, computers don’t actually understand names — they only talk to IP addresses (like 185.199.108.153). DNS (Domain Name System) is the giant phone book that translates a human-friendly name into a machine-friendly address. ...

4 min · 825 words · Jiaju

博客开发日志(中文):改动记录与前端原理

这是一篇按日期累积的开发日志。每次改动博客,我都把"做了什么"和"学到的前端原理"记在这里,方便以后翻查。最新的改动放在最上面。 维护约定:下次改动时,在 改动模板 上面新增一个 ## 日期 — 标题 小节即可。 2026-06-09 — 接入自定义域名 + 翻译按钮升级 这次做了什么 自定义域名上线:把 GoDaddy 买的 xungirl.com 接到 GitHub Pages,配置了 DNS(4 条 A 记录指向 GitHub IP + 1 条 www 的 CNAME),清掉了 GoDaddy 默认的停放记录,最后开启了自动 HTTPS(Let’s Encrypt 证书)。 新增文章:一篇讲 A 记录 vs CNAME 记录的英文文章。 翻译按钮:保护代码与公式:点翻译时,代码块、行内代码、数学公式保持原样不被翻译。 翻译按钮:升级为双向:自动判断当前文章是中文还是英文,翻成"另一种"——英文文章翻中文、中文文章翻英文。 涉及文件:layouts/partials/extend_head.html(翻译逻辑)、content/posts/(文章)。 前端原理 这次最值得记的是几个前端基础概念,比具体代码更重要。 1. 构建期 vs 运行期(最核心的一条线) 构建期(Hugo) 运行期(浏览器 JS) 谁在做 push 后 GitHub Actions 构建一次,生成静态 HTML 访客打开页面时,浏览器实时执行 适合 文章内容、菜单、固定文案(可走 Hugo 的 {{ i18n }} 翻译) 会动的东西:计时器、实时翻译、交互 特点 生成完就定死,之后不变 每次访问都重新跑,可以随时变 为什么重要:博客底部那个"已运行 X 天 X 时"的计时器,必须用运行期 JS(因为每秒都在变,Hugo 构建一次没法让它跳动);而它显示的英文字是写死在 JS 里的,脱离了 Hugo 的翻译体系,所以切语言不会变——这不是 bug,是它本来就在另一套系统里。 ...

2 min · 304 words · Jiaju

Blog Devlog: How This Site Was Built and Tweaked

This post documents the full history of changes to this blog. Partly for my own reference, partly because I think the process of setting up a dev blog is underrated as a learning exercise. Initial Setup — Feb 2026 Started with Hugo + the PaperMod theme. The decision was straightforward: Hugo is compiled Go, so builds are near-instant even with lots of posts PaperMod has clean typography, dark mode, math support, and search out of the box GitHub Pages + GitHub Actions = free hosting with automatic deploys on every push The deploy pipeline in .github/workflows/deploy.yml is about 20 lines: ...

4 min · 716 words · Jiaju

LLM Agents: How ReAct, Tool Use, and Planning Actually Work

“Agent” is one of the most overloaded words in AI right now. Everything from a simple function-calling wrapper to AutoGPT gets called an agent. This post cuts through the hype and explains the actual mechanics: how agents think, act, and plan, with the math to back it up. What Is an Agent? A bare LLM is a function: given a prompt, output a completion. An agent wraps that function in a loop: ...

6 min · 1219 words · Jiaju

How Transformers Work: Attention Is All You Need, Explained

The 2017 paper Attention Is All You Need changed NLP forever. Before it, sequence models meant RNNs or LSTMs — sequential, slow, and bad at long-range dependencies. The Transformer threw all of that out and replaced it with pure attention. This post walks through the key components with the actual math. The Problem with RNNs An RNN processes tokens one at a time. To compute the hidden state at step $t$, you need the state at $t-1$: ...

5 min · 914 words · Jiaju

My First Post

Welcome Hi, I’m Jiaju — a CS student at Northeastern University. This blog is where I share what I learn about programming, algorithms, and software engineering. Why I Started This Blog Writing helps me think more clearly. By explaining concepts in my own words, I understand them better. Plus, it’s a great way to track my learning journey. A Quick Math Demo The time complexity of merge sort can be expressed as: ...

2 min · 242 words · Jiaju