第1节 第一次对话:发一个问题给LLM,拿一个回答

这一节要做什么

做一个最小最小的程序:你说一句中文,程序把这句话发给大模型(大模型就是ChatGPT、Claude背后那个大脑),大模型回你一句,然后把答案打印出来。

就像:

你:    "你好"
程序:  把"你好"发给大模型
大模型:回 "你好!有什么我可以帮你的吗?"
程序:  打印出来

就这么多功能。这一节结束后,你会理解:大模型本质就是一个"能理解文字的网页接口"。


先搞懂几个概念(零基础解释)

什么是"网页接口"(API)

你去外卖软件点餐,步骤是:

  1. 你选好饭,按"下单"

  2. 外卖软件把订单发给餐厅

  3. 餐厅做好饭,送过来

在这个过程里,你(用户)和餐厅之间,靠外卖软件传递信息

网页接口(API)就像是这个场景里的"外卖软件"。只不过这里不是传递饭菜,而是传递文字信息

你的程序把一段文字"送出去",大模型把另一段文字"送回来"。这个过程叫"请求-响应"。

什么是HTTP

HTTP是传输协议,可以理解成"传递信息的快递规则"。

就像快递有规则(寄件→运输→收件),HTTP也有规则。你的程序按照这个规则的格式把数据"打包"寄出去,大模型按同样规则"拆包"处理,然后按规则把结果寄回来。

什么是POST

在HTTP里,"POST"是一种发送数据的方式,意思是"把我给你的数据发过去"。

类比:你去银行办业务,跟柜员说"我要存款,把这些钱存进去"。柜员收下你的钱,给你一个回执。POST就是这样——把数据交给对方,等对方处理完拿结果。

和POST对应的叫GET——"把某个东西拿给我看",比如你打开网页,浏览器用GET把网页内容"拿回来"。

什么是JSON

JSON是一种组织数据的格式,让数据排列整齐、容易读取。

就像你给朋友写信有两种格式:

普通格式(不工整):

我叫小明,我22岁,我喜欢编程

JSON格式(工整):

{
    "姓名": "小明",
    "年龄": 22,
    "爱好": ["编程", "音乐", "游戏"]
}

JSON的好处是:格式固定,程序好读也好写。大模型接口要求数据必须用JSON格式。

什么是大模型的"接口地址"(URL)

就像每个快递网点有自己的地址,每个大模型服务也有自己的"地址"。这个地址叫URL,比如:

https://api.openai.com/v1/chat/completions

这一长串的意思是:去 api.openai.com 这个服务器,找 /v1/chat/completions 这个"窗口"办理业务。


完整代码

把下面这段代码复制到一个文件里,比如叫 chat.py,然后运行它(前提是你有API key,没有的话先跳过实操,只看解释):

# ============================================================
# 第1节完整代码:发一个问题给大模型,拿一个回答
# ============================================================

# ---------- 1. 导入工具 ----------
import requests

# ---------- 2. 设置大模型的"地址" ----------
url = "https://api.openai.com/v1/chat/completions"
api_key = "sk-xxxxxxxxxxxxxxxxxxxxxxxx"   # <-- 换成你的真实API密钥
model = "gpt-4o-mini"

# ---------- 3. 准备要发给大模型的数据 ----------
messages = [
    {
        "role": "user",
        "content": "你好,介绍一下你自己"
    }
]

# ---------- 4. 拼装完整的HTTP请求 ----------
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {api_key}"
}

body = {
    "model": model,
    "messages": messages
}

# ---------- 5. 发送请求,等待大模型回复 ----------
response = requests.post(url, headers=headers, json=body, timeout=60)
print("服务器返回的原始数据:")
print(response.json())

# ---------- 6. 从返回结果里提取大模型的回答 ----------
result = response.json()["choices"][0]["message"]["content"]

# ---------- 7. 打印结果 ----------
print("
" + "=" * 50)
print("大模型的回答:")
print(result)

代码逐行详解

第1部分:导入工具

import requests

解释: Python自己不会发送网页请求,需要借助别人写好的工具。import requests 就是从Python的工具箱里拿出 requests 工具。

类比: 就像做饭前要从厨房拿出菜刀,import就是在"拿工具"。

为什么需要这个: 如果没有这个工具,Python不知道怎么跟网页服务器说话。requests把HTTP的复杂规则包装好了,我们只需要调用几个简单命令。


第2部分:配置地址和密钥

url = "https://api.openai.com/v1/chat/completions"
api_key = "sk-xxxxxxxxxxxxxxxxxxxxxxxx"
model = "gpt-4o-mini"

解释: 这里设置三样东西:

  • url:大模型服务的"窗口地址"。这里用的是OpenAI的格式,大部分兼容OpenAI格式的模型(硅基流动、DeepSeek等)都可以用同一个地址,只是换密钥和模型名。

  • api_key:相当于"会员卡号"。大模型服务不是免费的,你要有账号和密钥才能用。就像去停车场要有停车卡一样。

  • model:用哪个大脑。gpt-4o-mini是一个比较便宜又好用的小模型,适合学习用。

类比: 就像你去快递站寄件,要填:寄到哪里(url)、你是谁(api_key)、用哪家快递公司(model)。


第3部分:准备对话内容

messages = [
    {
        "role": "user",
        "content": "你好,介绍一下你自己"
    }
]

解释: messages 是一个列表,里面装着"谁说了什么"的信息。

role(角色)有三种:

  • "user" = 用户,就是你

  • "assistant" = 助手,就是大模型

  • "system" = 系统提示词,用来设定大模型的身份

content 就是具体说的内容。

类比: 就像剧本里写:

角色:用户
台词:你好,介绍一下你自己

目前只有一个"用户"说的话,所以大模型还不知道自己是谁(下一节会加 system 角色设定)。


第4部分:拼装HTTP请求

headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {api_key}"
}

body = {
    "model": model,
    "messages": messages
}

解释: HTTP请求分成两部分:请求头(headers)和请求体(body)。

headers(请求头) = 相当于快递的面单,填的是"寄件人信息、快递公司"这类元数据:

  • Content-Type: application/json:告诉服务器"我寄给你的东西是JSON格式"

  • Authorization: Bearer xxx:告诉服务器"我是有权限的用户,密钥是xxx"

body(请求体) = 相当于快递里的东西,这里放我们真正的数据:

  • model:用哪个模型

  • messages:说什么

类比: 去银行汇款,headers就是汇款单上的账号信息,body就是汇款金额那一栏要填的内容。


第5部分:发送请求

response = requests.post(url, headers=headers, json=body, timeout=60)

解释:

  • requests.post() = 用POST方式发送请求

  • url = 发到哪里

  • headers=headers = 带上请求头(身份验证信息)

  • json=body = 要发送的数据(自动转成JSON格式)

  • timeout=60 = 最长等60秒,防止程序卡死

返回的 response 是一个响应对象,里面有服务器返回的所有数据。


第6部分:提取回答

result = response.json()["choices"][0]["message"]["content"]

解释: 这是最难理解的一行。先搞清楚返回数据的结构:

{
    "choices": [
        {
            "message": {
                "role": "assistant",
                "content": "你好!我是..."
            }
        }
    ]
}

所以:

  • response.json() 把返回的JSON变成Python字典

  • ["choices"][0] 取出第一个答案

  • ["message"]["content"] 取出答案的文字内容

类比: 就像从抽屉里拿东西:

衣柜["衣服层"]["第一格"]["左边这件"] = "这件是T恤"

第7部分:打印结果

print("
" + "=" * 50)
print("大模型的回答:")
print(result)

解释: 打印出来让你看到。=" * 50 是打印50个等号,当分隔线用,让输出更好看。


这一节学到了什么

概念

一句话解释

HTTP请求

通过网页发送数据的规则

POST

一种发送数据的方式(把东西交出去)

JSON

一种整齐的数据格式

API地址(URL)

互联网上的"服务窗口"地址

API密钥

用服务的"会员卡号/密码"

requests

Python里用来发HTTP请求的工具

messages列表

大模型对话的剧本,列出谁说了什么


这一节的代码对应nanobot的哪里

用户提问
    ↓
本节代码:requests.post() 发送 HTTP 请求
    ↓
nanobot 对应位置:providers/base.py 里的 chat() 函数
    ↓
返回大模型的文字回答

nanobot的所有大模型调用,最终都是走的这个requests.post()逻辑,只是包装得更复杂(加了provider抽象、支持多模型、处理错误等)。