LangChain 入门指南:用 Python 搭建大模型应用
一、开头痛点:调通一个大模型 demo 容易,做成一个应用很难
很多同学第一次调 OpenAI 接口,几行requests就跑起来了,很有成就感。但真要把大模型塞进一个产品,事情就不一样了:
- 用户问一个问题,你要把历史对话拼进 prompt,还得控制长度,不然超 token;
- 想让模型「先检索资料再回答」(RAG),你得自己下载网页、切文本、算向量、存数据库、再拼回 prompt;
- 同一个功能要在测试、生产里换不同的模型,代码到处是
if; - 流程一长,代码就变成一团乱麻的字符串拼接,改一处崩一片。
LangChain 就是为了解决这些「胶水工作」而生的框架。它把「模型、提示词、记忆、检索、工具调用」都抽象成可组合的组件(chain),让你像搭积木一样把大模型应用串起来,而不用重复造轮子。本文带你用 Python 从零跑通一个能检索网页并回答的问答机器人。
二、环境准备:三行命令装好
LangChain 从 0.1 版本起把各厂家的集成拆分成了独立子包,OpenAI 相关的要单独装。建议先建虚拟环境:
# 创建并激活虚拟环境(可选但推荐)python-mvenv .venvsource.venv/bin/activate# Windows 用 .venv\Scripts\activate# 安装核心包与 OpenAI 集成pipinstalllangchain langchain-openai langchain-community装好之后,还需要一个 OpenAI API Key(或兼容的本地/第三方 endpoint)。把它放进环境变量,避免硬编码:
exportOPENAI_API_KEY="sk-你的密钥"# Windows 用 set OPENAI_API_KEY=...下面所有示例都基于这套环境,模型用通用的gpt-3.5-turbo。文末会告诉你换成国产模型或本地 Ollama 的方法。
三、最小可运行示例:一句话调用大模型
先写一个「能跑起来」的最小例子,建立整体直觉——LangChain 里最核心的对象就是ChatOpenAI,它对标 OpenAI 的聊天接口:
# hello_langchain.pyfromlangchain_openaiimportChatOpenAI# 实例化一个聊天模型,temperature 控制随机性(0 最稳,1 最发散)llm=ChatOpenAI(model="gpt-3.5-turbo",temperature=0.7)# invoke 是最通用的同步调用方式,传入字符串即可response=llm.invoke("用一句话解释什么是 LangChain?")print(response.content)# .content 才是真正的文本回复运行python hello_langchain.py,你会看到一段中文解释。response是一个AIMessage对象,里面除了content还有usage_metadata(token 用量)等信息。这就是 LangChain 统一消息格式的好处:换模型、换接口,调用方式不变。
四、核心概念:模型、提示词、链、解析器
1) 提示词模板(PromptTemplate)
把可变部分抽成占位符,避免手写字符串拼接:
fromlangchain_core.promptsimportChatPromptTemplate# from_messages 支持 system/user 多角色,{topic} 是占位符prompt=ChatPromptTemplate.from_messages([("system","你是乐于助人的技术博主,用简洁的中文回答。"),("user","请讲讲 {topic} 的核心价值。"),])2) 链(LCEL)与输出解析器
LangChain 0.2+ 推荐使用 LCEL 的管道语法|把组件串起来,最后一个StrOutputParser()把消息对象转成纯文本:
fromlangchain_core.output_parsersimportStrOutputParser# prompt -> llm -> 解析成字符串,构成一条可复用的链chain=prompt|llm|StrOutputParser()print(chain.invoke({"topic":"向量数据库"}))3) 记忆(Memory / 历史)
多轮对话需要把历史传入。最简做法是用MessagesPlaceholder:
fromlangchain_core.promptsimportMessagesPlaceholder chat_prompt=ChatPromptTemplate.from_messages([("system","你是中文助手。"),MessagesPlaceholder("history"),# 运行时注入历史消息("user","{input}"),])理解这三块,你就掌握了 LangChain 的骨架:模板负责组 prompt,链负责把数据流过模型,解析器负责把结果变干净。
五、进阶用法:用管道拼出检索增强(RAG)雏形
真正有用的应用,往往要让模型「先查资料再答」。下面演示一个最小 RAG 链路:加载网页 → 切分 → 向量化 → 检索 → 拼接回答。注意这里每个环节都是独立组件,可以任意替换。
fromlangchain_community.document_loadersimportWebBaseLoaderfromlangchain_text_splittersimportRecursiveCharacterTextSplitterfromlangchain_openaiimportOpenAIEmbeddingsfromlangchain_community.vectorstoresimportFAISS# 1) 加载一篇网页文档loader=WebBaseLoader("https://python.langchain.com/docs/get_started/")docs=loader.load()# 2) 按 500 字切块,留 50 字重叠,保证语义连续splitter=RecursiveCharacterTextSplitter(chunk_size=500,chunk_overlap=50)chunks=splitter.split_documents(docs)# 3) 用 OpenAI 嵌入模型向量化,建一个内存里的 FAISS 索引vectorstore=FAISS.from_documents(chunks,OpenAIEmbeddings())retriever=vectorstore.as_retriever(search_kwargs={"k":3})# 每次取最相关的 3 段这一步跑完,retriever就能根据问题返回最相关的文本片段了。进阶点上,你可以把FAISS换成Chroma/Milvus,把OpenAIEmbeddings换成OllamaEmbeddings实现完全离线。
六、实战场景:一个能「读网页再回答」的问答机器人(完整代码)
把前面所有概念串起来,做一个真正能用的小工具:给它一个网址和一个问题,它先检索网页内容,再基于检索结果作答,而不是瞎编。
# qa_bot.pyfromlangchain_openaiimportChatOpenAI,OpenAIEmbeddingsfromlangchain_community.document_loadersimportWebBaseLoaderfromlangchain_text_splittersimportRecursiveCharacterTextSplitterfromlangchain_community.vectorstoresimportFAISSfromlangchain_core.promptsimportChatPromptTemplatefromlangchain_core.output_parsersimportStrOutputParserfromlangchain_core.runnablesimportRunnablePassthrough# 1. 准备模型llm=ChatOpenAI(model="gpt-3.5-turbo",temperature=0)# 2. 构建检索器loader=WebBaseLoader("https://python.langchain.com/docs/get_started/")docs=loader.load()chunks=RecursiveCharacterTextSplitter(chunk_size=500,chunk_overlap=50).split_documents(docs)retriever=FAISS.from_documents(chunks,OpenAIEmbeddings()).as_retriever()# 3. 提示词:明确要求「只根据上下文回答」prompt=ChatPromptTemplate.from_template("你是一个严谨的助手,只根据下面的上下文回答问题,""如果上下文没有答案就回答「资料里没提到」。\n\n""上下文:\n{context}\n\n问题:{question}")# 4. 把检索到的片段拼成一段文本defformat_docs(docs):return"\n\n".join(d.page_contentfordindocs)# 5. 用 LCEL 管道组装完整链路qa_chain=({"context":retriever|format_docs,"question":RunnablePassthrough()}|prompt|llm|StrOutputParser())# 6. 提问answer=qa_chain.invoke("LangChain 里的 chain 是什么?")print(answer)运行python qa_bot.py,它会自动抓网页、建索引、检索、生成答案。这里RunnablePassthrough()把用户问题原样传下去,retriever | format_docs把「问题→相关段落」的检索过程封装成一步。整条链路可读性很强,要加记忆、加工具调用,都是往管道里再接一段而已。
七、常见坑与报错(附解决办法)
坑 1:ImportError: cannot import name 'ChatOpenAI' from 'langchain'
现象:照着老教程写from langchain.chat_models import ChatOpenAI报错。
原因:LangChain 0.1+ 把所有厂家集成拆到了独立包,ChatOpenAI现已归属langchain-openai。
解决:先pip install langchain-openai,再改成from langchain_openai import ChatOpenAI;类似地,OpenAIEmbeddings也来自这个包。
坑 2:AuthenticationError: Incorrect API key provided/ 返回空
现象:代码没错,但调用直接抛鉴权错误,或报OPENAI_API_KEY未设置。
原因:没配置密钥,或配置到了错误的 shell 会话 / 虚拟环境。
解决:在运行脚本的同一环境里export OPENAI_API_KEY=...;更稳妥的是在项目根目录放一个.env文件,并用python-dotenv的load_dotenv()加载,避免密钥进入代码仓库。
坑 3:DeprecationWarning: class 'LLMChain' is deprecated或模型已退役
现象:老代码跑出来一堆警告,甚至调用text-davinci-003时报 404。
原因:LLMChain/ConversationChain等旧式链已被 LCEL 管道取代;text-davinci-*系列模型也早已下线。
解决:用本文第四节的prompt | llm | StrOutputParser()管道写法替代LLMChain;模型统一改用gpt-3.5-turbo/gpt-4o等聊天模型,别再碰已退役的 completion 模型。
八、总结与下一步
LangChain 的核心价值就一句话:把大模型应用里那些重复的「胶水代码」标准化成可组合的组件。本文覆盖了安装、最小调用、提示词模板、LCEL 管道、输出解析,以及一条完整的「读网页再回答」RAG 问答链路,并点出了三个最容易踩的真实坑。
下一步建议你:
- 把
OpenAIEmbeddings换成OllamaEmbeddings,模型换成qwen2之类的本地模型,跑通离线 RAG; - 引入
langchain_core.messages的AIMessage/HumanMessage自己管理多轮对话历史; - 学习
tools与bind_tools,让模型能调用你自定义的函数(比如查天气、算账),进阶到 Agent。
动手把今天这个qa_bot.py换成你自己的博客 URL,你就拥有了人生第一个检索增强的大模型应用。