refactor: 重构 api-intro、api-design、transistor-to-cpu 组件为紧凑布局
- 重构 api-intro 7 个 Vue 组件为更紧凑的左右布局 - 重构 api-design 相关组件 - 重构 transistor-to-cpu 相关组件 - 统一使用 demo-root -> demo-header -> demo-layout -> info-box 结构 - 扩写文章内容为 MIT 讲义风格
This commit is contained in:
@@ -1,60 +1,66 @@
|
||||
# API 入门
|
||||
|
||||
::: tip 🎯 学习目标
|
||||
阅读完本节后,你将能够:
|
||||
- 理解 API 的本质概念和设计哲学
|
||||
- 区分不同类型的 API(函数 API、操作系统 API、Web API)
|
||||
- 掌握 HTTP 方法的语义和使用场景
|
||||
- 学会阅读和使用 API 文档
|
||||
- 理解 HTTP 调用与 SDK 调用的区别
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## 1. 从一个按钮开始
|
||||
|
||||
<ApiQuickStartDemo />
|
||||
|
||||
👆 看见了吗?点一下按钮,230 毫秒后,一句格言就回来了。
|
||||
👆 看见了吗?点击按钮,几百毫秒后,服务器返回了当前时间。
|
||||
|
||||
这个过程,就是 **API 调用**。
|
||||
这个过程,就是一次完整的 **API 调用**。虽然简单,但它包含了 API 交互的所有核心要素:
|
||||
|
||||
| 阶段 | 发生了什么 |
|
||||
|------|-----------|
|
||||
| **请求** | 客户端向服务器发送 "给我当前时间" 的请求 |
|
||||
| **处理** | 服务器接收请求,查询系统时间 |
|
||||
| **响应** | 服务器将时间数据返回给客户端 |
|
||||
|
||||
这就像你去便利店买水——你说"来瓶可乐",店员给你一瓶可乐。你问一句,他给一笔。
|
||||
|
||||
**API(Application Programming Interface,应用程序编程接口)**,本质上就是一种"对话约定":一方提出请求,另一方给出响应。
|
||||
|
||||
---
|
||||
|
||||
## 说白了,API 就是"问一句,拿一笔"
|
||||
## 2. API 的三种形态
|
||||
|
||||
你可能觉得"调用 API"是很高大上的操作。
|
||||
很多人一提到 API,就觉得这是很高深的东西。其实,你写代码的第一天就在用 API 了。
|
||||
|
||||
其实吧,就像你去便利店买水——你说"来瓶可乐",店员给你一瓶可乐。你问一句,他给一笔。
|
||||
|
||||
API 也是一样:
|
||||
|
||||
1. **你问**(发送请求)
|
||||
2. **别人答**(服务器处理)
|
||||
3. **你拿到**(返回结果)
|
||||
|
||||
只不过这次,你问的不是店员,而是一台远在千里之外的电脑。
|
||||
|
||||
---
|
||||
|
||||
## 但 API 远不止"网络接口"
|
||||
|
||||
一提到 API,很多人觉得这是很高深的东西,离自己很远。
|
||||
|
||||
其实吧,你写代码的第一天就在用 API 了,只是你不知道而已。
|
||||
|
||||
### 函数,就是最基础的 API
|
||||
### 2.1 函数 API:最基础的形态
|
||||
|
||||
<FunctionApiDemo />
|
||||
|
||||
```python
|
||||
length = len("hello")
|
||||
```
|
||||
当你调用 `len("hello")` 时,你就在使用 Python 提供的一个 API。你不需要知道 `len()` 内部是怎么数字符串长度的——是用 C 实现的还是用 Python 实现的?是遍历计数还是直接读取长度字段?这些细节都被隐藏了。
|
||||
|
||||
`len()` 这个东西,你觉得它是什么?
|
||||
**API 的核心价值:把复杂的东西藏起来,只给你一个简单的用法。**
|
||||
|
||||
它是个函数,没错。但同时,它也是 Python 给你留的一个 API。
|
||||
|
||||
什么意思呢?你不需要知道 `len()` 内部是怎么数字符串长度的,你不需要知道它是用 C 写的还是用 Python 写的,你只需要知道一件事——**把字符串给我,我告诉你多长**。
|
||||
|
||||
这就叫 API:**我把复杂的东西藏起来,只给你一个简单的用法**。
|
||||
|
||||
再看一个:
|
||||
再看一个更贴近实际的例子:
|
||||
|
||||
```python
|
||||
my_list = []
|
||||
my_list.append("item")
|
||||
# 你写这行代码
|
||||
response = requests.get("https://api.example.com/users")
|
||||
|
||||
# 背后发生了什么?
|
||||
# 1. DNS 解析:把域名转成 IP 地址
|
||||
# 2. TCP 连接:建立网络通道
|
||||
# 3. TLS 握手:加密通信
|
||||
# 4. HTTP 请求:发送数据包
|
||||
# 5. 等待响应:接收服务器返回
|
||||
# 6. 解析数据:把字节流转成 Python 对象
|
||||
```
|
||||
|
||||
`append()` 也是 API。背后可能是内存分配、指针移动、容量扩容...但你不用关心这些。你只需要说"给我加上去",它就帮你搞定。
|
||||
如果你要自己处理这 6 步,每次请求都要写几百行代码。但 `requests.get()` 把这些都封装好了,你只需要一行代码。
|
||||
|
||||
### 操作系统 API:让你的程序能"碰"硬件
|
||||
### 2.2 操作系统 API:让程序能"碰"硬件
|
||||
|
||||
当你在电脑上打开一个文件:
|
||||
|
||||
@@ -63,27 +69,17 @@ with open("file.txt", "r") as f:
|
||||
content = f.read()
|
||||
```
|
||||
|
||||
这行代码背后,Python 其实在调用**操作系统的 API**。
|
||||
这行代码背后,Python 调用了**操作系统的 API**。
|
||||
|
||||
Windows 有 Win32 API,Linux 有 POSIX API,macOS 有 Cocoa API。这些 API 是干嘛的?让程序能真正操作硬件——读写硬盘、显示窗口、播放声音。
|
||||
| 操作系统 | API 名称 | 作用 |
|
||||
|---------|---------|------|
|
||||
| Windows | Win32 API | 文件操作、窗口管理、进程控制 |
|
||||
| Linux | POSIX API | 系统调用、进程通信、设备访问 |
|
||||
| macOS | Cocoa API | 图形界面、文件系统、网络 |
|
||||
|
||||
没有操作系统 API,你的 Python 代码就是一堆文字,根本动不了硬盘里的文件。
|
||||
没有操作系统 API,你的 Python 代码就是一堆文字,根本动不了硬盘里的文件、显示不了窗口、连不上网络。
|
||||
|
||||
### 第三方库的 API:站在巨人的肩膀上
|
||||
|
||||
当你用 NumPy 做矩阵运算:
|
||||
|
||||
```python
|
||||
import numpy as np
|
||||
matrix = np.array([[1, 2], [3, 4]])
|
||||
result = np.dot(matrix, matrix)
|
||||
```
|
||||
|
||||
`np.dot()` 就是 NumPy 给你留的 API。背后可能是经过优化的 C++ 代码、多线程计算、SIMD 指令...但你只需要知道一件事——**给我两个矩阵,我还你一个乘积**。
|
||||
|
||||
这就是 API 的魅力:**把别人的能力,变成你的能力**。
|
||||
|
||||
### Web API:跨越网络的"超能力"
|
||||
### 2.3 Web API:跨越网络的"超能力"
|
||||
|
||||
最后,才是大多数人熟知的 Web API:
|
||||
|
||||
@@ -93,136 +89,180 @@ import requests
|
||||
response = requests.post(
|
||||
"https://api.deepseek.com/v1/chat/completions",
|
||||
headers={"Authorization": "Bearer sk-xxx"},
|
||||
json={"model": "deepseek-chat", "messages": [{"role": "user", "content": "你好"}]}
|
||||
json={
|
||||
"model": "deepseek-chat",
|
||||
"messages": [{"role": "user", "content": "你好"}]
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
这行代码做了什么?
|
||||
这行代码做了什么?它让你的程序穿越互联网,调用了千里之外 DeepSeek 服务器上的 AI 模型。就像你打了个越洋电话,让大洋彼岸的厨师帮你做了一道菜。
|
||||
|
||||
它让你的程序穿越互联网,调用了千里之外 DeepSeek 服务器上的 AI 模型。就像你打了个越洋电话,让大洋彼岸的厨师帮你做了一道菜。
|
||||
|
||||
**Web API 的神奇之处就在于:它让"调用别人的超级电脑"变得像调用本地函数一样简单。**
|
||||
**Web API 的神奇之处:让"调用别人的超级电脑"变得像调用本地函数一样简单。**
|
||||
|
||||
---
|
||||
|
||||
## 无论哪种 API,结构都一样
|
||||
## 3. API 的统一结构
|
||||
|
||||
说了这么多,你可能发现了——不管哪种 API,它们的结构都是一样的。
|
||||
|
||||
就像插头和插座,怎么变都离不开三样东西:
|
||||
|
||||
| 要素 | 函数 API 的例子 | Web API 的例子 |
|
||||
|------|----------------|---------------|
|
||||
| **地址/名称** | `len()` | `https://api.example.com/users` |
|
||||
| **输入/参数** | `"hello"` | `{"name": "张三"}` |
|
||||
| **输出/返回** | `5` | `{"id": 1}` |
|
||||
无论哪种 API,结构都一样。就像插头和插座,怎么变都离不开三样东西:
|
||||
|
||||
<ApiConceptDemo />
|
||||
|
||||
| 要素 | 函数 API | Web API |
|
||||
|------|---------|---------|
|
||||
| **地址/名称** | `len()` | `https://api.example.com/users` |
|
||||
| **输入/参数** | `"hello"` | `{"name": "张三"}` |
|
||||
| **输出/返回** | `5` | `{"id": 1, "name": "张三"}` |
|
||||
|
||||
理解了这个统一结构,你就掌握了 API 的本质。无论是调用一个 Python 函数,还是请求一个远程服务器,思路都是一样的:
|
||||
|
||||
1. **找到入口**(函数名或 URL)
|
||||
2. **传入参数**(按要求的格式)
|
||||
3. **处理返回**(按约定的结构解析)
|
||||
|
||||
---
|
||||
|
||||
## 调用服务器:你是在"问"还是在"做"?
|
||||
## 4. HTTP 方法:你是在"问"还是在"做"?
|
||||
|
||||
好,现在你知道调用 API 需要地址和参数。
|
||||
|
||||
但还有个问题没说:**你跟服务器说话的方式,不止一种。**
|
||||
|
||||
什么意思?
|
||||
调用 Web API 时,你需要告诉服务器你想做什么。这就是 HTTP 方法的由来。
|
||||
|
||||
想象你去一家餐厅:
|
||||
|
||||
| 场景 | 现实中你会怎么说? | 对应的 API 方式 |
|
||||
| 场景 | 现实中你会怎么说? | 对应的 HTTP 方法 |
|
||||
|------|-------------------|-----------------|
|
||||
| 你想知道今天有什么菜 | "服务员,菜单给我看看" | **GET** - 纯"问",不改数据 |
|
||||
| 你想点一份宫保鸡丁 | "给我来份宫保鸡丁" | **POST** - "做"件事 |
|
||||
| 你想点一份宫保鸡丁 | "给我来份宫保鸡丁" | **POST** - "做"件事,创建数据 |
|
||||
| 你想换一道菜 | "把宫保鸡丁改成糖醋里脊" | **PUT** - 替换数据 |
|
||||
| 你想改口味 | "宫保鸡丁不要放花生" | **PATCH** - 部分修改 |
|
||||
| 你不想要了 | "算了,那道菜不要了" | **DELETE** - 删除数据 |
|
||||
|
||||
这就是 HTTP 方法的来历:**不同的动词,对应不同的操作。**
|
||||
|
||||
但最常用的就两个:**GET 和 POST**。其他的先不用管。
|
||||
|
||||
<ApiMethodDemo />
|
||||
|
||||
::: warning 关于幂等性
|
||||
**幂等性**是一个重要概念:多次执行结果是否相同?
|
||||
|
||||
- **GET**:查询 10 次和查询 1 次,结果一样 → 幂等
|
||||
- **DELETE**:删除 10 次和删除 1 次,结果一样 → 幂等
|
||||
- **POST**:下单 10 次,可能创建 10 个订单 → 不幂等
|
||||
|
||||
实际开发中,POST 操作通常需要用唯一 ID 来防止重复处理。
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## HTTP vs SDK:自己跑腿还是让管家代办?
|
||||
## 5. HTTP vs SDK:自己跑腿还是让管家代办?
|
||||
|
||||
既然教程的重点是 AI 编程,我们就重点讲讲 Web API——这是你和 AI 模型打交道的主要方式。
|
||||
|
||||
你在教程里经常会看到两种调用方式:**HTTP** 和 **SDK**。很多人会被绕晕,其实很简单,就是**"自己跑腿"**和**"让管家代办"**的区别。
|
||||
|
||||
### HTTP API:自己跑腿
|
||||
|
||||
这是最原始的方式。就像你自己去餐厅,从头开始点菜。
|
||||
|
||||
所有编程语言都能用,甚至你在浏览器地址栏里敲一行字也是一种 HTTP 请求。
|
||||
|
||||
### SDK:让管家代办
|
||||
|
||||
SDK (Software Development Kit) 就像是餐厅派给你的专属管家。
|
||||
|
||||
你不需要自己填单子、贴邮票。你只需要跟管家说"来份宫保鸡丁",管家会自己在后台帮你填单子、发请求、处理报错。
|
||||
在 AI 编程教程中,你会经常看到两种调用方式:**HTTP** 和 **SDK**。它们的区别就像"自己跑腿"和"让管家代办"。
|
||||
|
||||
<RealWorldApiDemo />
|
||||
|
||||
> 能用 SDK 就用 SDK,把麻烦事留给别人,把时间留给自己。
|
||||
### 5.1 HTTP API:自己跑腿
|
||||
|
||||
## 怎么看 API 文档?
|
||||
这是最原始的方式。你需要:
|
||||
|
||||
文档就像说明书和菜单的结合体。你不需要从头读到尾,只需要学会查字典。
|
||||
1. **找到网址**(Base URL + Endpoint)
|
||||
2. **准备请求头**(Authorization、Content-Type)
|
||||
3. **构造请求体**(JSON 格式的参数)
|
||||
4. **发送请求**(处理网络错误、超时)
|
||||
5. **解析响应**(把 JSON 转成可用的数据)
|
||||
|
||||
所有编程语言都能用,但你需要处理很多细节。
|
||||
|
||||
### 5.2 SDK:让管家代办
|
||||
|
||||
SDK(Software Development Kit)就像是 API 提供方派给你的专属管家:
|
||||
|
||||
```python
|
||||
# HTTP 方式:自己处理所有细节
|
||||
import requests
|
||||
response = requests.post(
|
||||
"https://api.deepseek.com/v1/chat/completions",
|
||||
headers={"Authorization": "Bearer sk-xxx"},
|
||||
json={"model": "deepseek-chat", "messages": [...]}
|
||||
)
|
||||
result = response.json()["choices"][0]["message"]["content"]
|
||||
|
||||
# SDK 方式:管家帮你处理
|
||||
from openai import OpenAI
|
||||
client = OpenAI(api_key="sk-xxx")
|
||||
response = client.chat.completions.create(
|
||||
model="deepseek-chat",
|
||||
messages=[...]
|
||||
)
|
||||
result = response.choices[0].message.content
|
||||
```
|
||||
|
||||
SDK 自动处理了:鉴权、请求格式、错误处理、重试逻辑、响应解析。
|
||||
|
||||
::: tip 建议
|
||||
**能用 SDK 就用 SDK**,把麻烦事留给库,把时间留给自己。
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
## 6. 如何阅读 API 文档?
|
||||
|
||||
API 文档就像说明书和菜单的结合体。你不需要从头读到尾,只需要学会"查字典"。
|
||||
|
||||
打开任何一个 API 文档(比如 OpenAI 或 DeepSeek),你只需要找这几样东西:
|
||||
|
||||
1. **Base URL**:根地址(餐厅在哪?)
|
||||
2. **Authentication**:怎么证明你是会员?(通常是 `Authorization: Bearer sk-...`)
|
||||
3. **Endpoints**:具体的接口列表
|
||||
- `/v1/chat/completions` -> 对话(最常用的)
|
||||
- `/v1/images/generations` -> 画图
|
||||
4. **Parameters**:必填项有哪些?
|
||||
|
||||
<ApiDocumentDemo />
|
||||
|
||||
### 常见的"餐厅黑话"(状态码)
|
||||
### 6.1 文档阅读清单
|
||||
|
||||
服务员(API)回复你的时候,通常会先喊一个数字代码:
|
||||
| 项目 | 说明 | 示例 |
|
||||
|------|------|------|
|
||||
| **Base URL** | API 的根地址 | `https://api.deepseek.com` |
|
||||
| **Authentication** | 如何证明身份 | `Authorization: Bearer sk-xxx` |
|
||||
| **Endpoints** | 具体的接口列表 | `/v1/chat/completions` |
|
||||
| **Parameters** | 必填/可选参数 | `model`(必填)、`temperature`(可选) |
|
||||
| **Response** | 返回数据结构 | `{"choices": [...]}` |
|
||||
|
||||
| 状态码 | 含义 |
|
||||
|--------|------|
|
||||
| **200 OK** | 成功了 |
|
||||
| **400 Bad Request** | 你填错了 |
|
||||
| **401 Unauthorized** | 没权限 |
|
||||
| **404 Not Found** | 地址错了 |
|
||||
| **429 Too Many Requests** | 你点太快了 |
|
||||
| **500 Internal Server Error** | 对方服务器崩了 |
|
||||
### 6.2 常见状态码
|
||||
|
||||
服务器回复时,会先返回一个状态码,告诉你请求是否成功:
|
||||
|
||||
| 状态码 | 含义 | 常见原因 |
|
||||
|--------|------|---------|
|
||||
| **200 OK** | 成功 | 请求正常处理 |
|
||||
| **201 Created** | 创建成功 | POST 请求成功创建资源 |
|
||||
| **400 Bad Request** | 请求格式错误 | 参数缺失或格式不对 |
|
||||
| **401 Unauthorized** | 未认证 | 没有提供有效的 API Key |
|
||||
| **403 Forbidden** | 无权限 | API Key 没有访问该资源的权限 |
|
||||
| **404 Not Found** | 不存在 | 请求的地址或资源不存在 |
|
||||
| **429 Too Many Requests** | 请求过多 | 超过了速率限制 |
|
||||
| **500 Internal Server Error** | 服务器错误 | 服务端出了问题 |
|
||||
|
||||
---
|
||||
|
||||
## 练手场:弄坏它也没关系
|
||||
## 7. 动手练习
|
||||
|
||||
光说不练假把式。这里有个模拟 API,你可以随便填参数、随便改地址,看看会发生什么。
|
||||
|
||||
试着触发一下 401(假装没带钱)或者 404(瞎填地址)。
|
||||
|
||||
<ApiPlayground />
|
||||
|
||||
试着触发以下场景:
|
||||
- ✅ **成功请求**:填入正确的 Endpoint 和 API Key
|
||||
- ❌ **401 错误**:不填 API Key,看看服务器怎么拒绝你
|
||||
- ❌ **404 错误**:填一个不存在的地址
|
||||
|
||||
---
|
||||
|
||||
## 总结
|
||||
## 8. 小结
|
||||
|
||||
别把 API 想得太复杂。在 AI 编程的时代,你只需要记住这几件事:
|
||||
|
||||
1. **API 就是传声筒**,帮你把话传给 AI 模型
|
||||
2. **你早就用过 API**了,从 `len()` 到 `open()`
|
||||
::: info 核心要点
|
||||
1. **API 就是传声筒**,帮你把话传给另一段代码或远程服务器
|
||||
2. **你早就用过 API 了**,从 `len()` 到 `open()` 都是 API
|
||||
3. **Web API 是超能力**,让你调用千里之外的超级电脑
|
||||
4. **SDK 是好管家**,能用管家就别自己跑腿
|
||||
5. **看文档找三样**:地址、密钥、参数
|
||||
4. **SDK 是好管家**,能用 SDK 就别自己跑腿
|
||||
5. **看文档找三样**:地址、鉴权、参数
|
||||
:::
|
||||
|
||||
这就够了。剩下的,交给 IDE 去写吧。
|
||||
在 AI 编程的时代,你只需要记住这几个核心概念。剩下的细节,IDE 和 AI 助手会帮你处理。
|
||||
|
||||
---
|
||||
|
||||
## 名词速查表 (Glossary)
|
||||
## 名词速查表
|
||||
|
||||
| 名词 | 全称 | 解释 |
|
||||
|------|------|------|
|
||||
@@ -242,3 +282,4 @@ SDK (Software Development Kit) 就像是餐厅派给你的专属管家。
|
||||
| **Header** | - | HTTP 头,包含元信息 |
|
||||
| **Payload** | - | 请求或响应的实际数据 |
|
||||
| **Rate Limit** | - | 速率限制 |
|
||||
| **Idempotent** | - | 幂等,多次执行结果相同 |
|
||||
|
||||
Reference in New Issue
Block a user