三行代码的第一条链
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
load_dotenv()
llm = ChatOpenAI(model="deepseek-chat", temperature=0.7)
resp = llm.invoke("用一句话解释什么是变量")
print(resp.content)
ChatOpenAI 是对聊天模型的统一封装。只要对方兼容 OpenAI 接口(DeepSeek、月之暗面、通义、本地 Ollama 都兼容),换模型只需要改 model 和 base_url,业务代码一行不动。
invoke() 是 LangChain 所有组件的统一入口。 不管是模型、提示词模板还是整条链,调用方式都是 .invoke(输入)。记住这一个方法,整个框架的用法就通了一大半。
返回的是一个消息对象,取文本用 .content。
temperature:随机性旋钮
0:每次输出基本一样,适合抽取信息、分类、写代码0.7:有变化但不跑偏,适合对话、解释1.0+:发散,适合头脑风暴、创意写作
不确定就用 0 到 0.3。很多"模型不稳定"的抱怨,实际上是 temperature 设太高了。
消息形式的输入
from langchain_core.messages import SystemMessage, HumanMessage
resp = llm.invoke([
SystemMessage(content="你是一个严格的代码审查员,只指出问题,不夸奖。"),
HumanMessage(content="def f(a,b): return a+b"),
])
print(resp.content)
这和第一课那个 messages 列表是同一件事,只是换成了对象写法。
流式输出
等模型生成完再显示,用户会觉得卡。流式可以一个字一个字往外吐:
for chunk in llm.stream("讲讲 Python 的列表推导式"):
print(chunk.content, end="", flush=True)
end="" 不换行,flush=True 立刻刷到屏幕。你现在用的 AI 私教就是这么实现的。
用 | 把组件串起来
LCEL 的核心是一个管道符:
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_template("用一个生活中的比喻解释:{concept}")
chain = prompt | llm | StrOutputParser()
print(chain.invoke({"concept": "递归"}))
读作:输入先进 prompt 填空,填好的提示词进模型,模型的输出交给解析器变成纯字符串。
| 的意思就是"左边的输出当右边的输入",和 Linux 管道一样。StrOutputParser() 的作用只是把消息对象剥成字符串,省掉每次写 .content。
链本身也是个组件,所以它同样支持 .invoke()、.stream()、.batch():
for chunk in chain.stream({"concept": "递归"}):
print(chunk, end="", flush=True)
results = chain.batch([{"concept": "递归"}, {"concept": "指针"}]) # 批量,会并发
这就是 LCEL 最大的价值:你只拼装一次,流式、批量、异步全都白送。
报错怎么看
| 报错 | 原因 |
|---|---|
AuthenticationError | key 错了,或 .env 没被 load_dotenv() 读到 |
NotFoundError: model not found | 模型名拼错,或这个厂商没有这个模型 |
RateLimitError | 请求太频繁 / 余额不足 |
APIConnectionError | 网络不通、base_url 写错 |
KeyError: 'concept' | invoke 传的字典键和模板里的 {} 对不上 |
10 秒自测
prompt | llm | StrOutputParser() 里,如果去掉最后一个,invoke 的返回值会变成什么?
变成一个 AIMessage 对象,得自己写 .content 才能拿到文字。