🌟 一、LangChain 是什么?(一句话版)
LangChain 是一个帮你"组装 AI 应用"的工具箱。
就像你搭乐高积木:
- 大模型(比如通义千问、ChatGPT)是"马达";
- 数据库、网页、文件是"零件";
- LangChain 就是连接它们的接口和框架,让你不用从零造轮子。
🧩 二、打个比方:你想做一个"智能客服"
❌ 没有 LangChain 时,你要自己:
- 调用大模型 API(比如 Qwen)
- 把用户问题拼成特定格式
- 解析返回结果
- 如果要查公司知识库,还得自己写数据库查询
- 如果要聊天记录,还得自己存历史
- 如果要流式输出(一个字一个字出),还得处理网络分块......
👉 非常麻烦,重复劳动多!
✅ 有了 LangChain 后:
它已经把上面这些事封装好了,你只需要:
from langchain_community.chat_models import ChatQwen
llm = ChatQwen(api_key="xxx")
response = llm.invoke("你好啊!")
print(response.content)
💡 LangChain 的核心思想:让开发者专注"业务逻辑",而不是底层通信细节。
🔧 三、LangChain 的几个关键概念(小白友好版)
| 术语 | 类比解释 | 例子 |
|---|---|---|
| LLM / ChatModel | "会说话的大脑" | 通义千问、ChatGPT |
| Message | "对话的一句话" | 你说:"你好" → HumanMessage("你好") AI回:"Hi!" → AIMessage("Hi!") |
| Chain(链) | "做事的流程" | 先查资料 → 再总结 → 最后回答 |
| Agent(代理) | "会自己想办法的AI" | 你问"今天天气怎样?",它自动去查天气API |
| Tool(工具) | "AI能用的外挂" | 计算器、搜索、发邮件...... |
🎭 四、代码实践------马冬梅
它是在 "假装自己是一个 AI",专门用来搞笑 + 演示 LangChain 的规范写法。
数据流 :你的问题 → 包成"人话" → 传给大爷 → 大爷查计数器 → 选一句台词 → 拆成字 → 一个一个慢悠悠吐出来 → 你看到经典三连问。
langchain包下载:如果是在pycharm内,代码复制进去点击红线报错处安装即可
# 第1行:导入 time 模块,用来让程序"暂停一下"(模拟老人说话慢)
import time
# 第2行:导入 re 模块,用来"查找文字"(比如检查有没有"马冬梅")
import re
# 第3行:导入一些类型工具,帮助代码更规范(不用深究,照抄就行)
from typing import Any, List, Iterator, Optional
# 第4行:导入 PrivateAttr,用来定义"私有变量"(比如记住问到第几句了)
from pydantic import PrivateAttr
# 第5行:导入回调管理器,用于流式输出时通知外部(比如告诉界面"新字来了")
from langchain_core.callbacks import CallbackManagerForLLMRun
# 第6行:导入 BaseChatModel,这是 LangChain 里"自定义聊天AI"的标准模板
from langchain_core.language_models.chat_models import BaseChatModel
# 第7行:导入消息类型:
# HumanMessage = 人说的话
# AIMessage = AI 说的话
# BaseMessage = 所有消息的统称
# AIMessageChunk = AI 说的一个字(用于流式输出)
from langchain_core.messages import HumanMessage, AIMessage, BaseMessage, AIMessageChunk
# 第8行:导入输出格式:
# ChatGeneration = 一次完整的AI回答
# ChatGenerationChunk = AI回答中的一个字
# ChatResult = 包含所有回答的结果对象
from langchain_core.outputs import ChatGeneration, ChatGenerationChunk, ChatResult
# 第11行:定义一个新类,叫 ChatWithOlderAI,它继承自 BaseChatModel
# 意思是:"我要造一个符合 LangChain 标准的聊天AI"
class ChatWithOlderAI(BaseChatModel):
"""模拟《夏洛特烦恼》里记不住"马冬梅"的老大爷"""
# 第14行:定义一个内部计数器,用来记住这是第几次听到"马冬梅"
# PrivateAttr 表示这是"私有属性",不能被外面随便改
_counter: int = PrivateAttr(default=0)
# 第17行:告诉 LangChain 这个AI的类型名字(随便起,但要有)
@property
def _llm_type(self) -> str:
return "ma-dong-mei-daddy"
# 第20行:定义 _generate 方法 ------ 这是 LangChain 要求必须实现的
# 它的作用是:一次性返回完整的AI回答
def _generate(
self,
messages: List[BaseMessage], # 用户发来的所有消息(列表形式)
stop: Optional[List[str]] = None, # 可选:遇到哪些词就停止(这里不用)
run_manager: Optional[CallbackManagerForLLMRun] = None, # 回调管理(流式用)
**kwargs: Any, # 其他可能的参数
) -> ChatResult: # 返回值必须是 ChatResult 类型
# 第27行:调用内部方法 _ask_remote,拿到AI的回答(是一个消息列表)
responses = self._ask_remote(messages)
# 第28行:把每个回答包装成 ChatGeneration(LangChain 要求的格式)
generations = [ChatGeneration(message=msg) for msg in responses]
# 第29行:把所有回答打包成 ChatResult 返回
return ChatResult(generations=generations)
# 第31行:定义 _ask_remote 方法 ------ 这是我们自己写的"大脑逻辑"
def _ask_remote(self, messages: List[BaseMessage]) -> List[BaseMessage]:
# 第33-37行:定义大爷的经典三连问(存成一个列表)
replies = [
"马什么梅?",
"什么冬梅??",
"马东什么??"
]
# 第39行:取出用户最新的一条消息内容(比如"马冬梅啊!")
user_input = messages[-1].content # [-1] 表示"最后一个"
# 第41行:用正则表达式检查用户是否说了"马冬梅"或"马东梅"(不区分大小写)
if re.search(r"马冬梅|马东梅", user_input, re.IGNORECASE):
# 第42行:根据当前计数器,选出对应的回复(比如第0次 → "马什么梅?")
reply_text = replies[self._counter]
# 第43行:计数器加1,并对3取余(实现循环:0→1→2→0→1...)
self._counter = (self._counter + 1) % len(replies)
else:
# 第45行:如果没提到"马冬梅",就回一句敷衍的"哦..."
reply_text = "哦..."
# 第47行:把回复包装成 AIMessage(表示这是AI说的话),放进列表返回
return [AIMessage(content=reply_text)]
# 第49行:定义 _stream 方法 ------ 这是 LangChain 要求支持"流式输出"时必须实现的
def _stream(
self,
messages: List[BaseMessage], # 用户消息列表
stop: Optional[List[str]] = None,
run_manager: Optional[CallbackManagerForLLMRun] = None,
**kwargs: Any,
) -> Iterator[ChatGenerationChunk]: # 返回一个"字"的生成器
# 第56行:先调用 _ask_remote 拿到完整的AI回答(取第一个)
response = self._ask_remote(messages)[0]
# 第57行:遍历回答中的每一个字符(比如"马"、"什"、"么"......)
for char in response.content:
# 第58行:每输出一个字,暂停0.08秒(模拟老人说话慢)
time.sleep(0.08)
# 第59行:把这个字包装成 AIMessageChunk(流式专用格式)
chunk = ChatGenerationChunk(message=AIMessageChunk(content=char))
# 第60-61行:如果外部有监听(比如网页界面),就通知它"新字来了"
if run_manager:
run_manager.on_llm_new_token(token=char, chunk=chunk)
# 第62行:把这个字"吐出去"(yield 是 Python 的流式关键词)
yield chunk
# ===== 以下是测试代码(不是AI本身,只是用来演示怎么用)=====
# 第66行:如果直接运行这个文件(而不是被别人导入),就执行下面的测试
if __name__ == "__main__":
# 第68-74行:定义一组用户要问的问题(模拟夏洛反复喊"马冬梅")
user_questions = [
"大爷,楼上322住的是马冬梅家吗?",
"马冬梅啊!",
"我是说马冬梅!!",
"您歇着吧...",
"今天吃了吗?"
]
# 第76行:创建一个"马冬梅大爷"AI 实例
llm = ChatWithOlderAI()
# 第78行:遍历每个问题
for q in user_questions:
# 第79行:把问题包装成 HumanMessage(人说的话)
human_msg = HumanMessage(content=q)
# 第80行:打印夏洛的问题
print(f"\n\n👴 夏洛:{q}")
# 第81行:打印"大爷:",但不换行(后面要接逐字输出)
print("🧓 大爷:", end="", flush=True)
# 第84行:调用 .stream() 方法,传入消息列表 [human_msg]
for chunk in llm.stream([human_msg]):
# 第85行:打印当前这个字(end="" 表示不换行,flush=True 立刻显示)
print(chunk.text, end="", flush=True)
# 第86行:所有字输出完后,换行
print()
它做了什么?
- 继承了 LangChain 的 BaseChatModel
→ 相当于"注册成为官方认可的聊天机器人" - 实现了两个方法:
- _generate():一次性返回整句话(比如直接说"马什么梅?")
- _stream():一个字一个字慢慢说(模拟老人说话慢)
- 用了 LangChain 规定的消息格式:
- 人说的话 → HumanMessage
- AI说的话 → AIMessage
- 流式输出的每个字 → AIMessageChunk
✅ 这样做的好处是:这个"假AI"可以无缝接入 LangChain 的生态!
比如你可以把它塞进一个"聊天机器人界面",或者和其他真实 AI 组合使用。
🤔 五、那我为什么要关心 LangChain?
如果你只是想调用大模型聊天,其实可以直接用通义app、文心一言、Kimi......
但如果你想要:
- 📚 让 AI 回答基于你自己的文档(比如公司手册、产品说明书)
- 💬 做一个带记忆的聊天机器人(记得你上次说了啥)
- 🌐 让 AI 自动上网查资料再回答
- 🏗️ 搭建复杂工作流(比如:收邮件 → 提取订单 → 查库存 → 回复客户)
→ 那么 LangChain 就是你的好帮手!