01 · 为什么需要 LangChain:从一次”朴素 API 调用”开始
本片目标:用一个朴素requests调智谱 API 的例子,展示”没有 LangChain 的世界”,再展示 LangChain 的 ChatModel 如何统一一切,并回答:LangChain 到底多做了哪几件事? 新增规定性:1(此后你调模型只有一个入口:chat_model.invoke(...)) 数据字典:ChatAnthropic 构造参数、AIMessage 骨架。 进程线程模型:同步invoke在当前线程阻塞,直到响应返回。 网络模型:一次 HTTPS POST 到/v1/messages,JSON 请求体、JSON 响应体。
1. 上集回顾
第 00 篇我们有了环境和 API key。现在问题来了:
为什么我不直接 requests.post 调智谱的 API,而要学一个叫 LangChain 的框架?
这个问题必须在第 01 篇回答。因为如果 LangChain 只是”给 requests 套了层皮”,那它不值得学——你用 requests 就够了。理解 LangChain 的价值 = 理解它解决了什么必须解决的问题。
2. 朴素世界:直接调智谱 API(Anthropic 协议)
你打开智谱的文档,看到它的接口长这样(Anthropic Messages API):requests 写出来是这样的(code/01_first_chat.py 里的 raw_api_call() 函数):
- 协议细节写死在代码里——
anthropic-version头、data["content"][0]["text"]这种取数逻辑,全是你搜文档搜来的。换一家模型(比如 DeepSeek,OpenAI 协议),响应结构变成data["choices"][0]["message"]["content"],这段代码全部要重写。 - 消息序列化是你自己做的——
{"role": "system", "content": ...}这个字典结构,你得自己记住”system 对应什么、user 对应什么”。 - 错误处理、重试、超时、流式——全都没有。生产环境第一个月就会因为一次 429 超限而崩。
- 没法组合——你后面要做的 RAG(检索→拼上下文→生成)是多个环节的组合。用 requests 写,每个环节都要自己管理”输入从哪来、输出去哪”。
3. LangChain 的做法:一个接口,调用所有模型
这就是”统一接口”(规定性 1):不管底层是 Anthropic 协议还是 OpenAI 协议,你面对的都是同一个类
ChatAnthropic/ChatOpenAI,同一个方法 invoke(),同一个返回类型 AIMessage。
逻辑必然性:只要你有”换模型厂商不用重写业务代码”的诉求,就必然需要一个”统一信封”——把各家协议的差异全部吸收掉。这就是 langchain-core 存在的第一理由。
4. 数据字典:ChatAnthropic(关键类的数据)
4.1 ChatAnthropic 构造参数(langchain-anthropic)
4.2 invoke() 返回:AIMessage 骨架(完整 9 字段在第 02 篇)
response_metadata(智谱 glm-4.7,Anthropic 协议,2026-08 实测):
usage_metadata:
model_provider: "anthropic"是判断协议来源的关键字段——智谱返回anthropic,DeepSeek 返回openai(第 02 篇细讲)。
5. 关键方法
注意:invoke 接受字符串(一个 HumanMessage 的快捷方式)、消息对象列表或字典。本片用字符串;第 02 篇开始用消息对象。
6. 进程线程模型
invoke 是阻塞调用——调用期间当前线程什么都不干,就等网络。单线程下,一次问答 = 一次”卡住” 1~3 秒。生产环境(第 11、12 篇)会学怎么用线程池/异步解决。
7. 网络模型
- 传输协议:HTTPS,一次 POST 请求。
- 请求体/响应体:JSON。
- 请求头
anthropic-version由 SDK 自动带(这是 Anthropic 协议的规定性)。 - 超时、重试(默认 2 次)、429 处理,
ChatAnthropic已内置——这是朴素 requests 没有的。
8. 验证:跑起来
配套代码code/01_first_chat.py 同时包含朴素 requests 版和 LangChain 版,并打印两者的原始响应让你对比。
9. 边界
- ChatAnthropic 不是唯一入口——还有
ChatOpenAI(DeepSeek/通义/Kimi)。两个类的invoke行为一致,但构造参数略有差异(OpenAI 协议 base_url 要带/v1)。 - 别自己 new httpx 调模型 API——除非你有极特殊的诉求(比如自己控制 HTTP 会话复用)。框架已内置超时/重试/流式。
- AIMessage 还不是字符串——
invoke返回对象。想直接拿文本要么.content,要么(第 04 篇)接StrOutputParser。
推荐资料(延伸阅读)
- LangChain 官方文档 · 总览 —— LangChain 到底解决了什么问题(官方口径)
- LangChain 官方文档 · 模型 —— ChatModel 概念与统一接口的权威说明
- LangChain 官方文档 · 组件架构 —— 标准接口 + 集成包的架构设计
10. 未完待续
model.invoke("你好") 返回的 AIMessage 里有 9 个字段——content、tool_calls、usage_metadata…… 为什么一个”回答”要带这么多东西?模型到底返回了什么、怎么被表达成统一信封? 这就是第 02 篇。
→ 02 · 消息类数据字典