跳到主要内容
版本:1.0

大模型 API 与 LangChain

从这里开始进入 AI 应用岗主战场。核心考点:模型为什么无状态、多轮怎么写、怎么稳定输出 JSON、LangChain 六抽象与 LCEL。

模型无状态:多轮要自己维护 messages​

模型本身没有记忆——每次调用都是独立的 next-token 预测,服务端不记得你上次说了什么。所谓"多轮对话",是客户端把完整历史重新发一遍:

messages = [
{"role": "system", "content": "你是一个严谨的技术面试官"},
{"role": "user", "content": "讲讲 GIL"},
{"role": "assistant", "content": "GIL 是 CPython 的全局解释器锁……"}, # ← 必须回填
{"role": "user", "content": "那怎么绕开它?"},
]
resp = client.chat.completions.create(model="xxx", messages=messages)
messages.append({"role": "assistant", "content": resp.choices[0].message.content}) # ← 漏了就失忆

两个必须做到的点:

  1. user 和 assistant 消息都要 append 回历史。漏了 assistant 那条,下一轮模型就"忘了自己刚说过什么",出现自相矛盾。
  2. 历史太长要截断/摘要(token 有上限,也直接关系成本)。

关键参数​

  • temperature:采样随机度。事实问答/代码/JSON 输出调低(0~0.3),创意写作调高(0.7+),要求稳定 JSON 直接用 0。
  • max_tokens:限制输出长度,防止失控长输出烧钱。
  • 流式输出:逐块读取 delta.content,要判空(部分块的 delta 里只有 role 或没有 content,直接拼接会崩)。
for chunk in stream:
delta = chunk.choices[0].delta
if delta and delta.content: # 判空再拼
print(delta.content, end="")

稳定输出 JSON 的四件套​

模型输出 JSON 偶尔会带 ```json 围栏、尾随文字或字段缺失。稳定方案 = 格式说明 + 示例 + 温度 0 + 清洗围栏:

import json, re

def extract_json(text: str) -> dict:
m = re.search(r"\{.*\}", text, re.S) # 清洗:从回复中抠出 JSON 体
if not m:
raise ValueError("未找到 JSON")
return json.loads(m.group())

失败处理两条路:程序侧重试(低温度再生成一次);或把报错信息回喂给模型让它自己修——"你上次输出的 JSON 缺 score 字段,请修正",模型通常一次就能改对。后者更优雅,也是面试加分项。

LangChain 六大抽象​

抽象职责例子
Model调用大模型ChatOpenAI
Prompt组装提示词模板ChatPromptTemplate
Parser解析模型输出StrOutputParser、PydanticOutputParser
Runnable统一调用协议一切组件的基类
Tool让模型调用外部工具@tool 装饰器
Retriever按查询取相关文档向量库检索器

核心是 Runnable 协议:所有组件都实现同样的 invoke / stream / batch 接口,所以能像管道一样串起来,换模型不用改链——把 ChatOpenAI 换成任何兼容的 Model,后面整条链照跑。这是"为什么换模型不用改链"的标准答案。

LCEL 与什么时候上 LangGraph​

LCEL(LangChain Expression Language)用 | 把组件接成链:

chain = prompt | model | parser # 顺序管道
chain.invoke({"question": "..."})

LCEL 天然支持并行(RunnableParallel)和分支(RunnableBranch),但它是单向无环的数据流。

遇到循环、暂停审批、持久化就上 LangGraph:

  • 循环:Agent 反复"思考→调工具→观察"直到完成,DAG 表达不了。
  • 暂停审批:执行到危险操作时停下来等人工确认再继续。
  • 持久化:跨请求记住状态、断点恢复。

详细对比见 LangGraph 与多智能体。

什么时候不该用 LangChain​

面试常拿这道题测工程判断力:

  • 逻辑简单:一次 API 调用 + 一个 prompt 就能搞定,套框架纯属负重。
  • 需要精细控制 token、报错、重试:框架层层封装反而难定位问题。
  • 强依赖厂商私有 SDK 能力:直接用官方 SDK 更直接。

框架的价值在于标准化组件与快速原型;生产系统里"轻量自研 + 关键处借力"往往更好。能说出"我知道它适合什么、不适合什么"就是好答案。

高频面试题​

问题答题要点
模型为什么没有记忆?多轮怎么写?模型无状态,只做 next-token 预测;客户端维护 messages,user/assistant 都要 append,漏 assistant 就失忆
怎么稳定输出 JSON?格式说明 + 示例 + temperature 0 + 正则清洗围栏;失败重试或把报错回喂让模型自修
六个抽象是什么?为什么换模型不用改链?Model/Prompt/Parser/Runnable/Tool/Retriever;核心是 Runnable 协议统一接口,组件可插拔
流式输出要注意什么?取 delta.content 且判空,部分块无 content
解析失败怎么办?清洗围栏 → 重试(温度 0)→ 回喂报错让模型自修;多级兜底
什么时候不该用 LangChain?逻辑简单一次调用就够、要精细控制 token 与报错、依赖厂商私有能力时;框架适合原型与标准化