LangChain 入门
为什么要学 LangChain?
| 痛点 | LangChain 怎么帮 |
|---|---|
| Prompt 拼来拼去很乱 | ChatPromptTemplate 统一管理模板 |
| 调 API、解析返回值重复写 | ChatOpenAI 封装模型调用 |
| 多步骤(Prompt → LLM → 解析)硬编码 | Chain 用 | 管道串联 |
LangChain 是框架,底层还是 Prompt + LLM + 循环。
安装依赖
pipinstalllangchain langchain-openai langchain-core三个包分工:
| 包 | 作用 |
|---|---|
| langchain | 主包,常用入口 |
| langchain-openai | ChatOpenAI(兼容 DeepSeek 等 OpenAI 格式 API) |
| langchain-core | PromptTemplate、Chain、消息类型等核心抽象 |
ChatModel(ChatOpenAI)
对应手搓的 OpenAI client + chat.completions.create。
最小示例:
fromlangchain_openaiimportChatOpenAI llm=ChatOpenAI(model="你的模型名",api_key="你的 key",base_url="你的 base_url",# DeepSeek 地址)# 直接调用(传入消息列表)response=llm.invoke("你好")print(response.content)# response 是 AIMessage 对象,不是 strinvoke 可以传字符串,也可以传消息列表。
PromptTemplate(ChatPromptTemplate)
把 Prompt 从代码里「抽出来」,用占位符填变量。
fromlangchain_core.promptsimportChatPromptTemplate,MessagesPlaceholder prompt=ChatPromptTemplate.from_messages([("system","你是一个简洁友好的助手,用中文回答。"),MessagesPlaceholder("history"),# 插槽,历史消息插在这里("human","{user_input}"),# {user_input} 是占位符])# 填变量,生成最终 messagesmessages=prompt.format_messages(user_input="什么是 Python?")# 结果类似:[SystemMessage(...), HumanMessage(...)]占位符命名规则:
MessagesPlaceholder("history")→ invoke 时传"history": history("{user_input}")→ invoke 时传"user_input": user_input
from_messages 里角色名
| 写法 | 等价 role |
|---|---|
| (“system”, “…”) | system |
| (“human”, “…”) | user |
| (“ai”, “…”) | assistant |
Chain(LCEL 管道)
LangChain 用 | 把步骤串成链:
fromlangchain_core.output_parsersimportStrOutputParser chain=prompt|llm|StrOutputParser()执行流程:
输入 dict → prompt 填模板 → llm 调 API → StrOutputParser 转成 str最小调用:
reply=chain.invoke({"user_input":"你好"})print(reply)# 直接是字符串,不用 .content什么时候用 Chain?
Chain(LCEL 管道)适合「固定、线性的数据流」:输入 → 格式化 → 调模型 → 解析输出,一步走完。
# 纯聊天,一次 invoke 就出最终文字reply=chain.invoke({"history":history,"user_input":user_input})| 特征 | 说明 |
|---|---|
| 单次调用 | 一次 invoke 就结束 |
| 无分支 | 不需要判断 tool_calls |
| 无循环 | 不需要「调模型 → 执行工具 → 再调模型」 |
| 可组合 | 想串多个步骤(prompt、llm、parser、后处理) |
多轮对话怎么接?
关键代码思路:每轮invoke时把当前history和user_input一并传入(key 名与模板占位符一致);拿到reply后,将本轮的HumanMessage和AIMessage追加到history,下一轮循环自动带上。
fromlangchain_core.messagesimportHumanMessage,AIMessage history=[]# 存历史,不含 system(system 在 prompt 模板里)# 循环内:reply=chain.invoke({"history":history,"user_input":user_input})history.append(HumanMessage(content=user_input))history.append(AIMessage(content=reply))