LangChain 基础对话链构建新手指南

从零开始跑通你的第一个智能对话机器人,附完整可运行代码 + 避坑大全


① 开发环境搭建与依赖安装

先说个很多人踩过的坑。你去搜“LangChain 安装教程”,看到的第一个命令大概率是 pip install langchain。你照着做了,然后兴冲冲地写了一个 from langchain_openai import ChatOpenAI,一运行,报错:

ModuleNotFoundError: No module named 'langchain_openai'

你会觉得是代码写错了,但其实不是。问题在于:langchain 这个包早就被拆分了。你只装了主包,但那些具体和大模型对接的功能,都在别的包里。

正确的安装方式(一步到位):

# 第一步:建虚拟环境(跳过这步以后有的苦吃)
python -m venv langchain_env
# Windows:
langchain_env\Scripts\activate
# Mac/Linux:
source langchain_env/bin/activate

# 第二步:装需要的包(别只装langchain)
pip install langchain langchain-community langchain-core
pip install langchain-openai
pip install python-dotenv

推荐用 Python 3.10 或更高版本,低版本在某些组件上会有奇怪的兼容性问题。

装完验证一下:

python -c "from langchain_openai import ChatOpenAI; print('OK')"

如果没报错,说明环境好了。

补充说明: LangChain 生态主要有这几个包:

  • langchain:主包,包含链、记忆等核心抽象
  • langchain-core:最底层的基础接口(Runnable 等)
  • langchain-community:社区维护的第三方集成
  • langchain-openai:OpenAI 模型的专用包

如果你要用其他国产大模型(智谱、通义千问等),也有对应的包。不过初学者建议先用 OpenAI 兼容的接口,后面再换。


② 核心概念解析与大模型连接

LangChain 有很多新名词,但你先别被吓住。最核心的东西就三块:

第一块:大模型(LLM/ChatModel)

就是那个负责“说话”的东西。在 LangChain 里,ChatOpenAI 就是你的大模型实例。你给它输入,它返回输出。

第二块:提示词模板(Prompt Template)

你每次问模型的问题,大部分时候只是其中几个关键词在变。模板就是帮你把这种重复劳动的活儿抽象出来。比如你写“把下面的文字翻译成英文:{text}”,这里的 {text} 就是等你填进去的变量。

第三块:链(Chain)

把上面两样东西串起来。你输入一个变量(比如待翻译的文字),模板先生成完整的提示词,再交给模型,模型返回结果。整个流程就是一条链。

后来 LangChain 又推出了 LCEL(LangChain Expression Language),你可以用管道符号 | 把这几个组件拼在一起,写起来非常直观:

chain = prompt_template | model | output_parser

现在先不急记这些,后面实战里你亲手写了就理解了。

连接一个大模型(以 OpenAI 为例):

from langchain_openai import ChatOpenAI

model = ChatOpenAI(
    model="gpt-3.5-turbo",  # 换成你有的模型
    temperature=0.7,        # 控制随机性,0~1之间
    api_key="你的密钥"       # 当然,实际上别这么写
)

temperature 是个挺重要的参数。数值越低,回答越保守、越确定;数值越高,回答越有创造性,但也可能跑偏。聊天机器人一般设在 0.7 左右就行。


③ 构建最小可运行对话链

这里我们只做一件事:让模型回答一个问题。不求花哨,先跑通。

第一步:配置 API Key(安全第一,别硬编码)

建一个 .env 文件:

OPENAI_API_KEY=sk-你的真实密钥
OPENAI_BASE_URL=https://api.openai.com/v1

加上 .gitignore.env 排除掉,防止上传。

然后在代码里加载:

from dotenv import load_dotenv
import os

load_dotenv()
api_key = os.getenv("OPENAI_API_KEY")
base_url = os.getenv("OPENAI_BASE_URL")

第二步:最小可运行代码

from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os

load_dotenv()

# 初始化模型
model = ChatOpenAI(
    model="gpt-3.5-turbo",
    api_key=os.getenv("OPENAI_API_KEY"),
    base_url=os.getenv("OPENAI_BASE_URL"),  # 如果用国产厂商就填他们的地址
    temperature=0.7
)

# 发出请求
response = model.invoke("你好,请简单介绍一下LangChain是什么?")
print(response.content)

运行,看到输出,恭喜你——第一个 LangChain 程序跑通了。

如果你用的是国产大模型(比如 DeepSeek、智谱、通义千问),只要它们提供 OpenAI 兼容的接口,ChatOpenAI 一样能用,把 base_url 换成厂商给的地址就行。零成本方案后面会专门讲。


④ 自定义提示词模板设计

每次都把完整提示词写在代码里,不优雅。而且如果你想用同样的模板去处理不同内容,就得反复写重复的代码。

最简单的字符串模板:

from langchain_core.prompts import PromptTemplate

template = PromptTemplate.from_template(
    "请用{字数}字以内的中文总结以下内容:\n\n{内容}"
)

# 填入变量
prompt = template.format(字数="50", 内容="LangChain是一个用于开发由语言模型驱动的应用程序的框架...")
print(prompt)

更常用的是 ChatPromptTemplate(适用多轮对话场景):

from langchain_core.prompts import ChatPromptTemplate

chat_template = ChatPromptTemplate.from_messages([
    ("system", "你是一个{角色},回答需要简洁专业。"),
    ("human", "{用户输入}"),
])

# 使用
messages = chat_template.format_messages(
    角色="编程助手",
    用户输入="什么是Python装饰器?"
)

ChatPromptTemplate 专门为聊天场景设计,可以包含 system、human、ai 等多种角色,比单条字符串更灵活。

把提示词模板和模型串起来(不用解析器版本):

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个翻译助手,把用户输入翻译成{目标语言}。"),
    ("human", "{user_input}")
])

model = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.3)

# 用管道符号串起来(LCEL写法)
chain = prompt | model

response = chain.invoke({
    "目标语言": "英语",
    "user_input": "今天天气真好"
})
print(response.content)

这里你还没有输出解析器,模型返回的还是 AIMessage 对象,取 .content 就能拿到文本。后面会讲怎么直接把结果解析成 Python 对象。

注意: ChatPromptTemplate 和普通 PromptTemplate 的区别在于,前者输出的是一组消息(适用于聊天 API),后者输出的是纯字符串。用 OpenAI 风格的大模型,建议用 ChatPromptTemplate


⑤ 多轮对话记忆机制实现

大模型本身是不记事的。你问它第一轮“我叫张三”,第二轮问“我叫什么”,它大概率不知道,因为每次调用都是独立的。

你需要一个“记忆组件”来保存对话历史,每次把历史塞回输入里。

LangChain 里最简单的记忆组件是 ConversationBufferMemory,它把整个对话历史放在一个缓冲区里,每次都全部打包带走。

基本用法:

from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationChain
from langchain_openai import ChatOpenAI

memory = ConversationBufferMemory()
model = ChatOpenAI(model="gpt-3.5-turbo")

# ConversationChain 是一个封装好的对话链,自动处理记忆的存取
conversation = ConversationChain(
    llm=model,
    memory=memory,
    verbose=True   # 设为True可看到内部处理过程,方便调试
)

# 第一轮
print(conversation.predict(input="你好,我叫小明。"))
# 第二轮
print(conversation.predict(input="你还记得我叫什么吗?"))

运行一下,你会发现第二轮模型真的回答对了。

verbose=True 是个好东西。运行的时候会打印出 LangChain 内部生成的完整提示词,你可以看到记忆是怎么被塞进去的,对理解背后原理很有帮助。

如果不喜欢全记下来(对话长了 Token 会爆炸怎么办):

全量记忆会导致对话越长花销越大。你可以用 ConversationBufferWindowMemory,只保留最近 K 轮对话:

from langchain.memory import ConversationBufferWindowMemory

memory = ConversationBufferWindowMemory(k=3)  # 只保留最近3轮

LCEL 新写法(高级用法):

从 LangChain 0.2 开始,官方推荐用 LCEL 自己构建带记忆的链,而不是依赖 ConversationChain 这种封装类。但初学者先用 ConversationChain 足够了,等你熟练了再切到 LCEL 版。

一个容易混淆的点: memory_key 参数。ConversationBufferMemory 默认的 memory_key 是 “history”。如果你的提示词模板里的变量不叫这个名字,会匹配不上导致记忆没被用上。用 ConversationChain 就不用操心这个,它会自动处理好。


⑥ 完整代码实战与效果验证

把前面学的所有东西串起来,写一个完整的对话机器人。支持:

  • 自定义 system prompt(定角色)
  • 记住多轮对话
  • 流式输出
  • 可随时退出
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationChain

# 加载密钥
load_dotenv()

# 初始化模型
model = ChatOpenAI(
    model="gpt-3.5-turbo",
    api_key=os.getenv("OPENAI_API_KEY"),
    base_url=os.getenv("OPENAI_BASE_URL"),
    temperature=0.7,
    streaming=True   # 开启流式输出
)

# 记忆
memory = ConversationBufferMemory()

# 对话链
conversation = ConversationChain(
    llm=model,
    memory=memory,
    verbose=False
)

print("🤖 对话机器人已启动!输入 'quit' 或 'exit' 退出。\n")

while True:
    user_input = input("你:")
    if user_input.lower() in ["quit", "exit"]:
        print("再见!")
        break
    
    # 流式输出(逐个字符打印)
    response = conversation.predict(input=user_input)
    print("🤖:", response)
    print()

效果验证:

  • 流式输出:每个字出来你就看到了,不用等全部生成完。
  • 多轮记忆:问完“我叫小明”,再问“我叫什么”,模型应该能答对。
  • 角色扮演:默认用的是 ConversationChain 的默认 System Prompt,你也可以自己定制,下一节会讲。

注意: 流式输出在 Jupyter Notebook 里效果不如命令行终端明显,建议直接在终端里跑这个脚本。


⑦ 常见报错排查与解决思路

LangChain 迭代速度快,版本之间经常有不兼容的改动。下面是几个最常碰到的报错和解决方案。

No.1:ModuleNotFoundError: No module named ‘langchain_openai’

原因:你只装了 langchain,没装专门的大模型集成包。LangChain 把具体模型的支持拆成了独立包,需要单独装。

解决:pip install langchain-openai。同理,用智谱就装 langchain-zhipu

No.2:ImportError: cannot import name ‘ConversationBufferMemory’ from ‘langchain.memory’

这个一般发生在高版本上。不同版本的 LangChain 模块结构变化很大,有教程用的是 0.1.x,你装的是 0.2.x 甚至 1.x,路径可能已经不一样了。

解决方案:先去官方文档确认当前版本的正确导入路径,或者在代码里打印一下 dir(langchain.memory) 看看有什么。

No.3:版本冲突导致旧代码跑不通

现象:照着 2023 年的教程写 from langchain.schema import Document,结果报错 ModuleNotFoundError: No module named 'langchain.schema'

原因:新版 LangChain 已经把 Document 挪到了 langchain_core.documents

解决:升级代码,或者固定版本 pip install langchain==0.1.12。初学者建议先固定版本,避免踩坑。

No.4:API Key 读不到

现象:各种 AuthenticationError

原因:load_dotenv() 没执行,或者 .env 文件不在当前目录,或者 Key 前面有空格被当成字符串一部分了。

排查:打印前几位看看,print(os.getenv("OPENAI_API_KEY")[:10]),如果是 None 说明没读到。

No.5:Rate Limit 429

调用太快,超过免费额度。加重试逻辑或者 time.sleep(1) 控制频率。

通用排查流程:

  1. 看报错的最后一行,基本能定位问题类型
  2. 确认 langchain 版本:pip show langchain
  3. 用最简单的调用测试(就一个 model.invoke("hi")
  4. 搜一下官方文档或者 GitHub Issues

另外,LangChain 社区有一个避坑指南专门讲了从旧版本迁移到新版本的模块路径变化,碰到了可以找来看看。


⑧ 输出格式化与解析技巧

大模型返回的是自然语言文本。但很多场景下,你想要的是一段 JSON、一个列表、或者一个自定义的对象(比如“提取这段文本里的姓名、年龄、职业”)。

PydanticOutputParser:把模型输出变成 Python 对象

from langchain_core.output_parsers import PydanticOutputParser
from langchain_core.prompts import PromptTemplate
from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAI

# 定义你想要的数据结构
class PersonInfo(BaseModel):
    name: str = Field(description="人物的姓名")
    age: int = Field(description="人物的年龄")
    occupation: str = Field(description="人物的职业")

parser = PydanticOutputParser(pydantic_object=PersonInfo)

# 提示词模板(引导模型按格式输出)
prompt = PromptTemplate(
    template="从以下文本中提取人物信息:\n{text}\n\n{format_instructions}",
    input_variables=["text"],
    partial_variables={"format_instructions": parser.get_format_instructions()}
)

model = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)

# 构建并执行链
chain = prompt | model | parser

result = chain.invoke({"text": "张伟,今年28岁,是一名软件工程师。"})
print(result)
print(result.name)       # 张伟
print(result.age)        # 28
print(result.occupation) # 软件工程师

跑一下,你会发现 result 直接是一个 Python 对象,字段都可以用点号访问。

parser.get_format_instructions() 会自动生成一段指导模型按 JSON 格式输出的说明,默认会写在提示词里。这是 LangChain 的一大便利功能。

如果不想要额外依赖,最简单的 JSON 解析:

import json
from langchain_core.output_parsers import StrOutputParser

chain = prompt | model | StrOutputParser()  # 先拿到字符串
response_str = chain.invoke({"text": "..."})
# 假设模型返回的是标准JSON
data = json.loads(response_str)

但这种方式依赖模型“自觉”输出正确 JSON,没有 PydanticOutputParser 稳定。

实际场景建议:

  • 开发调试阶段用 StrOutputParser 看原始输出最快
  • 上生产环境要求稳定的结构化输出,用 PydanticOutputParser
  • 如果模型经常输出格式错误,适当调低 temperature(比如 0 或 0.1)

⑨ 本地模型替换与配置调整

免费方案来了。如果你不想花 API 费用,或者有数据隐私方面的顾虑,可以用 Ollama 在本地跑开源模型。

第一步:安装 Ollama

到 https://ollama.com 下载安装包,一路下一步就行。装完后命令行应该能用 ollama 命令了。

第二步:下载一个模型(以 llama3.2 为例,只有几十MB,很快)

ollama run llama3.2

第一次运行会自动下载,等它跑完。你也可以用国内的 Qwen 系列:

ollama run qwen:7b   # 7B 版本,需要比较多内存

第三步:在 LangChain 里调用本地模型

Ollama 启动后会默认跑在 http://localhost:11434/ 上,而且提供了 OpenAI 兼容的 API 接口。你什么都不用改,把 base_url 指过去就行:

from langchain_openai import ChatOpenAI

local_model = ChatOpenAI(
    model="llama3.2",          # 用你下载的模型名
    base_url="http://localhost:11434/v1",
    api_key="ollama",          # 本地服务不需要真实Key,随便填
    temperature=0.7
)

response = local_model.invoke("介绍一下什么是LangChain")
print(response.content)

注意:ollama run 命令会直接进入交互模式,建议另开一个终端窗口运行它,或者在后台挂着。这样你的 Python 脚本就可以调用它了。

内存需求提醒:

  • llama3.2(3B)约 2GB 内存,普通电脑都能跑
  • qwen:7b 约 4-6GB 内存
  • 更大的模型需要 16GB 以上

内存不够的话,建议还是用国产大模型的云端 API,价格也不贵。DeepSeek 最近有优惠活动,用不了几个钱。

如果 Ollama 报错连不上:

检查一下服务有没有在跑。访问 http://localhost:11434/v1/models,如果能返回 JSON 说明正常。


⑩ 进阶功能扩展与安全注意事项

到了这一步,你已经能把 LangChain 的基础功能跑通了。下面是几个进阶方向的提示,以及绕不开的安全红线。

进阶一:添加工具调用(让模型能做事)

大模型只会说话,但如果你给它一个“计算器”工具,它就能帮你算数学。LangChain 的 Agent 功能就是干这个的:模型判断什么时候需要调用工具,然后执行并返回结果。这个方向值得单独写一篇教程,初学者先了解有这么个东西就行。

进阶二:RAG(检索增强生成)

当你需要模型回答它“不知道”的问题(比如你们公司的内部知识库),可以让模型先去搜一堆相关文档,再基于这些文档来回答。LangChain 在这一块有非常完善的工具链,从文档加载、切分、向量化存储到检索检索,全都支持。

进阶三:LCEL 高级玩法

前面我们用管道符号 | 串了 prompt、model、parser,这只是 LCEL 的冰山一角。你还可以做并行处理、条件分支、流式输出等更复杂的编排。

安全注意事项(这条要读三遍):

  1. API Key 绝不提交到 Git 仓库。.env + .gitignore 是最低要求。
  2. 生产环境不要暴露调试信息。 verbose=True 开发用用就好,上线前一定关掉。
  3. 用户输入做清洗和限制长度。 恶意用户可能故意输入超长文本让你的 API 费用爆炸。
  4. 设置用量预算和限流。 多轮对话很容易 Token 暴增,设计好记忆窗口大小(k 值别设太大)。
  5. 本地跑私有模型有门槛,但值得。 如果处理的是敏感业务数据,建议上 Ollama + 本地模型,数据不出本机。虽然质量可能不如 GPT-4,但在数据安全和成本之间能找到一个不错的平衡点。

WEB项目地址:演示地址
安卓APP下载地址:演示地址

写在最后

从环境搭建到本地模型替换,你已经把 LangChain 对话机器人开发的整个链路摸了一遍。别想着一次全记住,把这篇文章存下来,动手敲一遍代码。

有个常用的调试技巧——设置 verbose=True。运行时会打印出 LangChain 内部生成的完整提示词,能看到记忆是怎么被塞进去的、模型实际收到了什么内容,对理解原理帮助很大。

下一步想往哪个方向走?可以试试 RAG(让模型读你的 PDF)、Agent(让模型帮你干活),或者换成国产大模型跑通中文场景。这些每个都能单独写一篇,有需要的话我接着写。

遇到问题先去搜一下具体报错,或者到 LangChain 的 GitHub Issues 看看,大部分坑别人已经踩过了。祝顺利 🙌

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐