Meta把内部设计系统开源了:支撑内部13000+应用:专为Agent调优
2026-07-03
2026-07-09 0
LangChain由 Harrison Chase 创建于2022年10月,它是围绕LLMs(大语言模型)建立的一个框架,它的核心理念是为各种LLMs实现通用的接口,把LLMs相关的组件“链接”在一起,简化LLMs应用的开发难度,方便开发者快速地开发复杂的LLMs应用。
LangChain官网:python.langchain.com/docs/introd…
LangChain官网中文版:www.langchain.com.cn/
LangChain 简化了 LLM 应用程序生命周期的每个阶段:
langchain-core:聊天模型和其他组件的基础抽象。
集成包(例如 langchain-openai、langchain-anthropic 等):重要的集成被拆分为轻量级的独立包,由 LangChain 团队和集成方共同维护。
langchain:包含链(chains)、智能体(agents)和检索策略,这些构成了应用的认知架构。
langchain-community:由社区维护的第三方集成。
langgraph:一个编排框架,用于将 LangChain 组件组合成可用于生产的应用,支持持久化、流式处理及其他关键特性。
本课程以LangChain+Qwen进行学习,需要提前安装
借助阿里云-百炼平台(需要申请API Key 以及Secret Key):
现在市面上的模型多如牛毛,各种各样的模型不断出现,LangChain模型组件提供了与各种模型的集成,并为所有模型提供一个精简的统一接口。
LangChain目前支持三种类型的模型:LLMs、Chat Models(聊天模型)、Embeddings Models(嵌入模型)。
LangChain支持的三类模型,它们的使用场景不同,输入和输出不同,开发者需要根据项目需要选择相应的模型。
LLMs(大语言模型)使用场景最多,常用大模型的下载库:
下面Qwen为例进行讲解。
模型调用有2种方式:
from langchain_openai import ChatOpenAIimportos# 实例化模型model = ChatOpenAI(base_url=os.environ.get('base_url','https://dashscope.aliyuncs.com/compatible-mode/v1'),model='qwen-plus',openai_api_key=os.environ.get('api_key','sk-XXXXXX'),max_tokens=1000,temperature=0)# 获取问答结果result = model.invoke("帮我讲个笑话吧")print(result.content)
# from langchain_community.llms import Ollama # Langchain 0.x版本使用from langchain_ollama import OllamaLLM# 实例化模型# model = Ollama(model="qwen2.5:7b") # Langchain 0.x版本使用model = OllamaLLM(model="qwen2.5:7b")# 获取问答结果result = model.invoke("请给我讲个笑话吧")print(result)
聊天模型,聊天消息包含下面几种类型,使用时需要按照约定传入合适的值:
AIMessage: 就是 AI 输出的消息,可以是针对问题的回答.
HumanMessage: 人类消息就是用户信息,由人给出的信息发送给LLMs的提示信息,比如“实现一个快速排序方法”.
SystemMessage: 可以用于指定模型具体所处的环境和背景,如角色扮演等。你可以在这里给出具体的指示,比如“作为一个代码专家”,或者“返回json格式”.
ChatMessage: Chat 消息可以接受任意角色的参数,但是在大多数时间,我们应该使用上面的三种类型.
LangChain支持大量的chat 模型,可以通过官网查询:
也可以通过langchain源码查看
from langchain_core.messages import HumanMessage, SystemMessage, AIMessage# from langchain_community.chat_models import ChatOllama # Langchain 0.x版本使用from langchain_ollama import ChatOllama# 实例化模型model = ChatOllama(model="qwen2.5:7b")# 定义提示词messages = [SystemMessage(content="现在你是一个著名的诗人"),HumanMessage(content="给我写一首唐诗")]# 获取问答结果result = model.invoke(messages)# print(result)print(result.content)
Embeddings Models(嵌入模型)特点:将字符串作为输入,返回一个浮动数的列表。在NLP中,Embedding的作用就是将数据进行文本向量化。
不同的Embedding模型对多语言支持和文本类型有不同的特点:
text-embedding-ada-002:支持多种语言,但对中文等亚洲语言的支持相对较弱bge-large-zh:对中文有很好的支持multilingual-e5-large:对多语言都有较好的支持CodeBERTtext-embedding-ada-002或 bge-large-zh可以参考MTEB(大规模文本嵌入基准)排行榜以获取最新模型效果:huggingface.co/spaces/mteb…
接下来以一个文本嵌入模型的例子进行说明:
# from langchain_community.embeddings import OllamaEmbeddings # Langchain 0.x版本使用from langchain_ollama import OllamaEmbeddings# 初始化Ollama嵌入模型,使用mxbai-embed-large模型,温度设置为0model = OllamaEmbeddings(model="mxbai-embed-large", temperature=0)# 对单个查询文本进行嵌入编码res1 = model.embed_query('这是第一个测试文档')print(f'result1->{res1}')print(f'result1的长度->{len(res1)}')# 对多个文档进行批量嵌入编码res2 = model.embed_documents(['这是第一个测试文档', '这是第二个测试文档'])print(res2)
运行结果:
Prompt是指当用户输入信息给模型时加入的提示,这个提示的形式可以是zero-shot或者few-shot等方式,目的是让模型理解更为复杂的业务场景以便更好的解决问题。
提示模板:如果你有了一个起作用的提示,你可能想把它作为一个模板用于解决其他问题,LangChain就提供了PromptTemplates组件,它可以帮助你更方便的构建提示。
# from langchain import PromptTemplate # Langchain 0.x版本使用from langchain_core.prompts import PromptTemplate# from langchain_community.llms import Ollama# Langchain 0.x版本使用from langchain_ollama import OllamaLLM# model = Ollama(model="qwen2.5:7b") # Langchain 0.x版本使用model = OllamaLLM(model="qwen2.5:7b")# 定义模板template = "我的邻居姓{lastname},他生了个儿子,给他儿子起个名字"prompt = PromptTemplate(input_variables=["lastname"],template=template)prompt_text = prompt.format(lastname="王")print(prompt_text)# result: 我的邻居姓王,他生了个儿子,给他儿子起个名字result = model.invoke(prompt_text)print(result)
运行结果:
# from langchain import PromptTemplate, FewShotPromptTemplate # Langchain 0.x版本使用from langchain_core.prompts import PromptTemplate, FewShotPromptTemplatefrom langchain_ollama import OllamaLLMmodel = OllamaLLM(model="qwen2.5:7b")examples = [{"word": "开心", "antonym": "难过"},{"word": "高", "antonym": "矮"}]example_template = """单词: {word}反义词: {antonym}\n"""example_prompt = PromptTemplate(input_variables=["word", "antonym"],template=example_template,)few_shot_prompt = FewShotPromptTemplate(examples=examples,example_prompt=example_prompt,prefix="给出每个单词的反义词",suffix="单词: {input}\n反义词:",input_variables=["input"],example_separator="\n",)prompt_text = few_shot_prompt.format(input="粗")print(model.invoke(prompt_text))# 细
适合交互式对话应用,如聊天机器人、智能客服等,这些应用需要处理用户和LLM之间的多轮对话。
提示模板就是把一些常见的提示整理成模板,用户只需要修改模板中特定的词语,就能快速准确地告诉模型自己的需求。我们看个例子:
from langchain_core.prompts import ChatPromptTemplatefrom langchain_ollama import OllamaLLM# 实例化模型model = OllamaLLM(model="qwen2.5:7b")# 定义提示词模版template_str = "帮我讲个关于{name}笑话吧"prompt_template = ChatPromptTemplate.from_template(template_str)prompt = prompt_template.format_messages(name="气球")print(f'prompt-->{prompt}')# 调用模型result = model.invoke(prompt)print(f'result-->{result}')
from langchain_core.prompts import ChatPromptTemplate, HumanMessagePromptTemplatefrom langchain_core.messages import SystemMessagefrom langchain_ollama import OllamaLLM# 实例化模型model = OllamaLLM(model="qwen2.5:7b")# 系统信息system_prompt = SystemMessage("你是取名专家。")# 用户信息模版human_str = "我的邻居姓{lastname},他生了个儿子,给他儿子起个名字。"human_template = HumanMessagePromptTemplate.from_template(human_str)# 组装chat_template = ChatPromptTemplate.from_messages([system_prompt, human_template])# 生成最终的提示词prompt = chat_template.format_messages(lastname="王")print(f'prompt-->{prompt}')# 调用模型result = model.invoke(prompt)# 返回结果出了content外,还有元数据信息print(f'result-->{result}')
运行结果:

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholderfrom langchain_ollama import OllamaLLM# 实例化模型model = OllamaLLM(model="qwen2.5:7b")# 创建 prompt 模版prompt_template = ChatPromptTemplate.from_messages([ ("system", "给出每个单词的反义词"), MessagesPlaceholder("history"), ("human", "{question}")])# 创建 few-shot prompt# history = [# HumanMessage(content="开心"),# AIMessage(content="难过"),# HumanMessage(content="高"),# AIMessage(content="矮")# ]history = [("human", "开心"), ("ai", "难过"),("human", "高"), ("ai", "矮")]prompt = prompt_template.format_messages(history=history, question="富有")print(f"prompt-->{prompt}")# 调用模型result = model.invoke(prompt)print(f'result-->{result}')
运行结果:
在LangChain中,Chains描述了将LLM与其他组件结合起来完成一个应用程序的过程。针对上一小节的提示模版例子,zero-shot里面,我们可以用链来连接提示模版组件和模型,进而可以实现代码的更改,主要使用LCEL方法。
LCEL(Lang Chain Expression Language) 是一种声明式的方法,用于轻松组合链条。
LCEL的基本语法规则是使用|符号将不同的组件连接起来,形成一个链式结构。|符号类似于Unix的管道操作符,它将一个组件的输出作为下一个组件的输入,从而实现数据的传递和处理。
上一个组件的输出作为下一个组件的输入,输出和输入的类型必须保持一致,否则不能连接。
from langchain import PromptTemplatefrom langchain_core.prompts import PromptTemplatefrom langchain_ollama import OllamaLLM# 定义模板template = "我的邻居姓{lastname},他生了个儿子,给他儿子起个名字"prompt = PromptTemplate(input_variables=["lastname"],template=template)# 实例化模型llm = OllamaLLM(model="qwen2.5:7b")chain = prompt | llm# 执行链print(chain.invoke("王"))
如果你想将第一个模型输出的结果,直接作为第二个模型的输入,直接使用管道符, 代码如下:
from langchain_core.prompts import PromptTemplatefrom langchain_ollama import OllamaLLM# 创建第一条链template = "我的邻居姓{lastname},他生了个儿子,给他儿子起个名字"first_prompt = PromptTemplate(input_variables=["lastname"],template=template,)# 实例化模型llm = OllamaLLM(model="qwen2.5:7b")first_chain = first_prompt | llm# 创建第二条链second_prompt = PromptTemplate(input_variables=["child_name"],template="邻居的儿子名字叫{child_name},给他起一个小名")second_chain = second_prompt | llm# 链接两条链overall_chain = first_chain | second_chainprint(overall_chain)print('*'*80)# 执行链,只需要传入第一个参数catchphrase = overall_chain.invoke("王")print(catchphrase)
运行结果:
LLM 的输出是自然语言文本,但在应用开发中,我们经常需要将这些文本转换为结构化的数据格式,如列表、字典或对象。LangChain 输出解析器负责获取 LLM 的输出并将其转换为更合适的格式。
部分解析器如下:
| 解析器名称 | 核心功能 | 输出的 Python 类型 | 工业级应用场景 |
|---|---|---|---|
| StrOutputParser | 默认解析器。将 LLM 的输出直接解析为字符串。 | str | 只需要原始回答时(如问答任务、对话场景) |
| CommaSeparatedListParser | 将 LLM 输出的、用逗号分隔的文本解析为列表。 | list[str] | 列表/枚举型输出 |
| JsonOutputParser | 极其常用。将 LLM 输出的 JSON 字符串解析为 Python 字典。 | dict | 结构化 JSON 输出 |
| PydanticOutputParser | 极其常用。将 LLM 输出解析为预先定义的 Pydantic 对象,提供类型安全和数据验证。 | 自定义的 pydantic.BaseModel 对象 | 输出需要严格结构化(JSON-like)数据时 |
| DatetimeOutputParser | 从文本中智能地解析出日期和时间信息。 | datetime.datetime | 需要时间格式时 |
StrOutputParser,最简单的解析器,用于提取模型返回的原始文本:
from langchain_core.output_parsers import StrOutputParserfrom langchain_core.prompts import ChatPromptTemplatefrom langchain_ollama import OllamaLLM# 实例化模型model = OllamaLLM(model="qwen2.5:7b")# 创建简单链prompt = ChatPromptTemplate.from_template("解释{topic}是什么?回答控制20字以内")chain1 = prompt | modelresult1 = chain1.invoke({"topic": "ai"})print(f"result1-->{result1}")# 添加字符串解析器parser = StrOutputParser()chain2 = prompt | model | parserresult2 = chain2.invoke({"topic": "ai"})print(f"result2-->{result2}")
CommaSeparatedListOutputParser,将逗号分隔的文本转换为Python列表:
from langchain_core.output_parsers import CommaSeparatedListOutputParserfrom langchain_core.prompts import ChatPromptTemplatefrom langchain_ollama import OllamaLLM# 实例化模型model = OllamaLLM(model="qwen2.5:7b")# 创建列表解析器parser = CommaSeparatedListOutputParser()# 创建带格式说明的提示模板format_instructions = parser.get_format_instructions()prompt = ChatPromptTemplate.from_template("用中文列出{topic}的五个最重要特点。n{format_instructions}")# 组合组件chain = prompt | model | parser# 调用链result = chain.invoke({"topic": "大模型","format_instructions": format_instructions})print(result)
JsonOutputParser,将JSON格式文本转换为Python字典或列表:
from langchain_core.output_parsers import JsonOutputParserfrom langchain_core.prompts import ChatPromptTemplatefrom langchain_ollama import OllamaLLM# 实例化模型model = OllamaLLM(model="qwen2.5:7b")# 创建JSON解析器json_parser = JsonOutputParser()# 创建带格式说明的提示模板json_format_instructions = json_parser.get_format_instructions()json_prompt = ChatPromptTemplate.from_template("生成一个包含{person}基本信息的JSON。应包括姓名、职业、年龄和技能列表, 不要包含任何注释或额外说明。n{format_instructions}")# 组合组件json_chain = json_prompt | model | json_parser# 调用链result = json_chain.invoke({"person": "雷军","format_instructions": json_format_instructions})print(result)
运行结果:
PydanticOutputParser,使用Pydantic模型定义输出结构:
from langchain_core.prompts import ChatPromptTemplatefrom langchain_core.output_parsers import PydanticOutputParserfrom pydantic import BaseModel, Fieldfrom typing import Listfrom langchain_ollama import OllamaLLM# 实例化模型model = OllamaLLM(model="qwen2.5:7b")# 定义Pydantic模型class Movie(BaseModel):title: str = Field(description="电影标题")director: str = Field(description="导演姓名")year: int = Field(description="上映年份")genre: List[str] = Field(description="电影类型")rating: float = Field(description="评分(1-10)")# 创建Pydantic解析器pydantic_parser = PydanticOutputParser(pydantic_object=Movie)# 创建带格式说明的提示模板format_instructions = pydantic_parser.get_format_instructions()pydantic_prompt = ChatPromptTemplate.from_template("生成一部{genre}电影的信息。n{format_instructions}")# 组合组件pydantic_chain = pydantic_prompt | model | pydantic_parser# 调用链movie_data = pydantic_chain.invoke({"genre": "科幻","format_instructions": format_instructions})print(movie_data)
运行结果:
创建自定义输出解析器
from langchain_core.output_parsers import BaseOutputParserfrom typing import Dict, Anyfrom langchain_core.prompts import ChatPromptTemplatefrom langchain_ollama import OllamaLLM# 实例化模型model = OllamaLLM(model="qwen2.5:7b")class CustomKeyValueParser(BaseOutputParser[Dict[str, Any]]):"""解析形如'key: value'的文本"""def parse(self, text: str) -> Dict[str, Any]:"""从文本中解析键值对"""result = {}lines = text.strip().split('n')for line in lines:if ':' in line:key, value = line.split(':', 1)result[key.strip()] = value.strip()return resultdef get_format_instructions(self) -> str:"""提供格式指导给模型"""return """请以'键: 值'的格式返回信息,每行一个键值对。例如:名称: 爱因斯坦职业: 物理学家贡献: 相对论"""# 使用自定义解析器custom_parser = CustomKeyValueParser()custom_prompt = ChatPromptTemplate.from_template("提供关于{person}的基本信息。n{format_instructions}")# 组合组件custom_chain = custom_prompt | model | custom_parser# 调用模型result = custom_chain.invoke({"person": "屠呦呦","format_instructions": custom_parser.get_format_instructions()})print(result)
运行结果:
大模型本身不具备上下文的概念,它并不保存上次交互的内容,ChatGPT之所以能够和人正常沟通对话,因为它进行了一层封装,将历史记录回传给了模型。
因此 LangChain 也提供了Memory组件, Memory分为两种类型: 短期记忆和长期记忆 。短期记忆一般指单一会话时传递数据,长期记忆则是处理多个会话时获取和更新信息。
from langchain_community.chat_message_histories import ChatMessageHistoryfrom langchain_core.messages import messages_to_dict, messages_from_dictimport json# 1.创建一个ChatMessageHistory对象,用来存储对话信息history = ChatMessageHistory()# 添加用户消息history.add_user_message("在吗?")# 添加大模型消息history.add_ai_message("在")# 打印所有消息print(f'history.messages-->{history.messages}')# 2.可以将history.messages中的信息保存到字典中,然后保存到数据库或者文件中,方便后续读取# 2.1 messages_to_dict()方法将history.messages中的信息转换成字典dicts = messages_to_dict(history.messages)print(f'dicts-->{dicts}')# 2.2 这里将dicts保存到文件中with open('history.json', 'w', encoding='utf-8') as f:f.write(json.dumps(dicts, indent=2, ensure_ascii=False))# 3.从文件中读取出字典,然后将字典转换成消息# 3.1 读取文件messages = json.load(open('history.json', 'r', encoding='utf-8'))# 3.2 然后将字典转换成消息chat_messages = messages_from_dict(messages)print(f'chat_messages-->{chat_messages}')
运行结果:
LangChain v1.0 版本对 Memory(记忆) 组件进行了深度优化与工程化重构,使其不仅支持多轮对话上下文管理,更成为构建生产级智能体(Agent)不可或缺的核心能力之一。在 LangChain 从“实验性框架”迈向“企业级平台”的关键转型中,Memory 模块被赋予了更清晰的职责边界、更灵活的策略机制以及更强的可扩展性,从而支撑复杂任务场景下的长期记忆、状态追踪与个性化交互。
短期记忆的本质是线程级状态管理]。在 LangGraph 中:
(1)状态(State)
通常是一个包含 messages 字段的字典或 Pydantic 模型(如 MessagesState 或自定义 CustomState),用于存储当前会话的所有消息、中间变量、工具调用结果等。
(2)检查点器(Checkpointer)
负责将状态序列化并持久化到内存、SQLite、PostgreSQL 等后端。每次状态变更(如新增一条消息)都会触发一次检查点保存。
(3)会话ID(thread_id)
作为会话的唯一标识符,确保不同用户或不同对话之间的状态完全隔离。即使多个用户并发交互,也不会发生记忆混淆。
from langchain.agents import create_agentfrom langgraph.checkpoint.memory import InMemorySaverfrom langchain.messages import HumanMessagefrom langchain_ollama import OllamaLLMimport time# 初始化大模型,这里使用的是 Qwen 的聊天模型model = OllamaLLM(model="qwen2.5:7b")# 创建内存保存器 (Checkpointer)# 这是 LangGraph 的核心概念之一,用于在对话过程中保存和恢复状态(记忆)checkpointer = InMemorySaver()# 定义 Agent 的配置# "thread_id" (线程ID) 非常关键:它相当于对话的 ID,用于区分不同的会话记忆# 使用时间戳作为 ID,确保每次运行脚本时的线程 ID 不同(但在同一次运行中复用)timestamp = time.time()config = {"configurable": {"thread_id": f"{int(timestamp)}"}}# 创建 Agent 实例# model: 指定使用的底层大模型# tools: 工具列表,这里为空,表示 Agent 只能进行对话,不能调用外部工具(如搜索、计算器等)# checkpointer: 传入上面的内存保存器,赋予 Agent 记忆能力# system_prompt: 设定 Agent 的角色和行为模式agent = create_agent(model=model,tools=[],checkpointer=checkpointer,system_prompt="你是一个翻译官,擅长中英互译。")# 第一轮对话输入input_1 = {"messages": [HumanMessage("你好,我叫小呆。")]}# 调用 Agent (Response A)# 使用 config,这意味着这次对话会记录在 thread_id 对应的内存中# Agent 会记住 "我叫小呆" 这个信息response_a = agent.invoke(input=input_1,config=config)# 第二轮对话输入(测试是否记得之前的信息)input_2 = {"messages": [HumanMessage("你好,我叫什么?")]}# 定义一个新的配置 (config_2),使用完全不同的 thread_id# 这代表开启了一个全新的、独立的对话会话config_2 = {"configurable": {"thread_id": f"{int(time.time())}"}# 这里生成了一个新的时间戳 ID}# 调用 Agent (Response B)# 使用新的 config_2,Agent 看不到 config_1 中的历史记录# 因此,Agent 应该不知道用户叫 "小呆",因为它处于一个新的 "线程" 中response_b = agent.invoke(input=input_2,config=config_2)# 调用 Agent (Response C)# 再次使用最初的 config# 这会恢复到第一个会话的记忆中# Agent 应该能回想起用户叫 "小呆",因为它共享同一个 thread_idresponse_c = agent.invoke(input=input_2,config=config)# 输出结果进行对比print("Response A (第一次对话):")print(response_a)print("nResponse B (新线程,无记忆):")print(response_b)print("nResponse C (回到原线程,有记忆):")print(response_c)
代码运行逻辑:
对于需要长期运行和可靠记忆的应用,推荐使用数据库进行持久化。详见后面阶段LangGraph部分。
Indexes组件的目的是让LangChain具备处理文档处理的能力,包括:文档加载、检索等。注意,这里的文档不局限于txt、pdf等文本类内容,还涵盖email、区块链、视频等内容。
Indexes组件主要包含类型:
文档加载器主要基于Unstructured 包,Unstructured 是一个python包,可以把各种类型的文件转换成文本。文档加载器使用起来很简单,只需要引入相应的loader工具。
LangChain支持的文档加载器 (部分):
示例代码:
from langchain_unstructured import UnstructuredLoader# 创建 UnstructuredLoader 对象loader = UnstructuredLoader('./data/衣服属性.txt', encoding='utf8')docs = loader.load()print(f'docs-->{docs}')print(f'len-->{len(docs)}')print(f'第一行数据-->{docs[0].page_content}')print('*' * 100)from langchain_community.document_loaders import TextLoader# 创建 TextLoader 对象loader = TextLoader('./data/衣服属性.txt', encoding='utf8')docs = loader.load()print(f'docs-->{docs}')print(f'len-->{len(docs)}')print('第一行数据-->{}'.format(docs[0].page_content.split('n')[0]))
运行结果:
由于模型对输入的字符长度有限制,我们在碰到很长的文本时,需要把文本分割成多个小的文本片段。
文本分割最简单的方式是按照字符长度进行分割,但是这会带来很多问题,比如说如果文本是一段代码,一个函数被分割到两段之后就成了没有意义的字符,所以整体的原则是把语义相关的文本片段放在一起。
LangChain中最基本的文本分割器是CharacterTextSplitter ,它按照指定的分隔符(默认“nn”)进行分割,并且考虑文本片段的最大长度。我们看个例子:
from langchain_core.documents import Documentfrom langchain_text_splitters import CharacterTextSplitter# 创建分词器 separator参数指的是分割的分隔符,chunk_size指的是分割出来的每个块的大小,chunk_overlap指的是每个块之间重叠的大小text_splitter = CharacterTextSplitter(separator=" ", chunk_size=5, chunk_overlap=1)# 一句话分割result1 = text_splitter.split_text("a b c d e f")print(f'result1--->{result1}')# 多句话分割result2 = text_splitter.create_documents(["a b c d e f", "e f g h"])print(f'result2--->{result2}')# 多句话分割result3 = text_splitter.split_documents([Document(page_content="a b c d e f", metadata={"id": "1"})])print(f'result3--->{result3}')
运行结果:
除了CharacterTextSplitter分割器,LangChain还支持其他文档分割器 (部分):
| 分割器名称 | 功能描述 | 类型 | 工业场景应用 |
|---|---|---|---|
| CharacterTextSplitter | 简单按指定分隔符(如换行、逗号)直接分割。 | 基础字符解析 | 简单字符串或 CSV 数据处理,如传感器数据日志。 |
| RecursiveCharacterTextSplitter | 递归按字符分割,先尝试自然边界(如段落、句子),太大则继续细分。 | 通用字符解析 | 通用文本处理,如日志、报告、PDF 文档分割,便于 RAG 检索。 |
| TokenTextSplitter | 按 token(词元)分割,支持 LLM token 计数。 | Token 基于解析 | LLM 输入优化,如处理 API 响应或长查询,控制 token 限制。 |
| SentenceTextSplitter | 按句子边界分割,使用 NLP 识别句子(包括标点)。 | 语义解析 | 自然语言文本,如文章或对话分析,保持句子完整。 |
| SpacyTextSplitter | 使用 SpaCy NLP 库按句子或实体分割(需安装 SpaCy)。 | 语义解析 | 高级 NLP 场景,如实体提取或生物医学文本。 |
| NLTKTextSplitter | 使用 NLTK 库按句子或词分割(需安装 NLTK)。 | 语义解析 | 文本研究或分析,如时间序列数据描述。 |
| MarkdownHeaderTextSplitter | 按 Markdown 结构(如标题、列表)智能分割。 | 结构化解析 | Markdown 文档分割,保留语义结构,用于知识库构建。 |
| HTMLSplitter | 按 HTML 标签(如 、)分割网页内容。 | 结构化解析 | 网页数据爬取,如在线技术文档或新闻提取。 |
| LatexTextSplitter | 按 LaTeX 结构(如章节、公式)分割。 | 结构化解析 | 学术论文或数学文档处理。 |
| PythonCodeTextSplitter | 按 Python 代码结构(如函数、类)分割。 | 代码解析 | 源代码文件分析,如脚本调试或代码库管理。 |
下面就几个重要的分割器进行讲解。
其他拓展知识可以参考:blog.csdn.net/qq_28540861…
VectorStores是一种特殊类型的数据库,它的作用是存储由嵌入创建的向量,提供相似查询等功能。
LangChain支持的VectorStore有python.langchain.com/docs/integr…,常见的如下:
from langchain_text_splitters import CharacterTextSplitterfrom langchain_chroma import Chromafrom langchain_community.document_loaders import TextLoaderfrom langchain_ollama import OllamaEmbeddings# 1.加载文档# 创建 TextLoader 对象loader = TextLoader('./data/pku.txt', encoding='utf-8')# 加载文档docs = loader.load()# print(f'docs-->{docs}')# 2.将文档进行分块# 创建 CharacterTextSplitter 对象text_splitter = CharacterTextSplitter(separator="nn", chunk_size=200, chunk_overlap=30)# 分块split_docs = text_splitter.split_documents(docs)print(f'split_docs-->{split_docs}')# 3.将分割后的文档存储到向量数据库中# 加载embedding模型embedding = OllamaEmbeddings(model="mxbai-embed-large")# 创建向量数据库,需要指定 存储的文档和向量模型名称以及持久化目录chromadaDB = Chroma.from_documents(documents=split_docs, embedding=embedding, persist_directory='./chroma_db')# 假如你的向量数据库已经存在,那么可以直接加载# chromadaDB = Chroma(persist_directory='./chroma_db', embedding_function=embedding)# 4.使用向量数据库进行查询query = "1937年北京大学发生了什么?"result = chromadaDB.similarity_search(query, k=2)print(f'result-->{result}')
运行结果:
检索器是 LangChain 中负责信息检索的模块,通常与 索引(Indexes) 模块(如向量存储、嵌入模型)结合使用。它的核心功能是:
检索器在以下场景中扮演关键角色:
检索器通常与 向量存储(Vector Stores) 配合,通过嵌入模型(Embedding Models)将查询和文档转为向量,基于相似性进行检索。工作流程可以分为以下步骤:
检索器的核心依赖:
langchain支持很多检索器python.langchain.com/docs/integr…,部分如下:
此处我们讲解VectorStoreRetriever。
在 LangChain 中,as_retriever() 方法的 search_type 参数决定了向量检索的具体算法和行为。
retriever = vector_store.as_retriever(search_type="similarity",# 可选 "similarity"|"mmr"|"similarity_score_threshold"search_kwargs={"k": 5,# 返回结果数量"score_threshold": 0.7,# 仅当search_type="similarity_score_threshold"时有效,低于阈值的都丢弃。"filter": {"source": "重要文档.pdf"},# 元数据过滤,只会检索满足条件的文档。"lambda_mult": 0.25# 仅MMR搜索有效(控制多样性):接近 0 则更强调和查询的相关性;接近 1 则更强调结果之间的差异性})
以下是三种搜索类型的对比:
示例代码:
from langchain_chroma import Chromafrom langchain_ollama import OllamaEmbeddingsembedding = OllamaEmbeddings(model="mxbai-embed-large")# 向量数据库已经存在,那么可以直接加载chromadaDB = Chroma(persist_directory='./chroma_db', embedding_function=embedding)# 使用向量数据库进行查询query = "1937年北京大学发生了什么?"# result = chromadaDB.similarity_search(query, k=2)# 使用 as_retriever 方法返回 Retriever 对象,然后调用 invoke 方法进行查询retriever = chromadaDB.as_retriever(search_kwargs={"k":2})result = retriever.invoke(query)print(f'result-->{result}')
运行结果:
拓展:
vectordb.as_retriever() 和 vectordb.similarity_search() 都是用于从向量数据库中检索相关文档的方法,它们有什么异同:
相同
不同
其他几种常用的检索器介绍如下。
Agent(智能体)是一种能够感知环境、进行决策和执行动作的智能实体。不同于传统的人工智能,Agent 具备通过主动思考、调用工具去逐步完成给定目标的能力。
为什么要调用工具?
从大模型的角度来看,Agent其实就是基于大模型的语义理解和推理能力,让大模型拥有解决复杂问题时的任务规划能力,并调用外部工具来执行各种任务,利用向量数据库保留“记忆”的一个智能体。
工作流程概述:
任务规划(Planning)
Agent需要提前将一项复杂任务拆解为多个更小、更易于处理的子任务,从而实现对复杂任务的高效处理
长短期记忆(Memory)
聊天上下文,长期保留和回忆信息
工具&执行(Tools&Action)
根据拆分好的子任务,调用外部提供好的专业API解决专业问题,完成一个个具体的子任务,并把处理结果返回给大模型
LangChain 提供了不同类型的袋里(主要罗列一下三种):
Zero-shot ReAct Description
基于 ReAct 框架(推理 + 行动),仅依赖工具的 描述 来决定调用哪个工具。
特点:无需额外示例(zero-shot),但 不具备记忆能力,每次推理都独立进行。
使用场景:简单任务,工具选择完全靠工具描述即可。
Structured Chat Zero-shot ReAct Description
同样基于 ReAct 框架,但可以处理 结构化输入,即支持带多个参数的工具(类似函数调用)。
特点:不仅能像第一种袋里那样根据描述选择工具,还能正确组织并传递复杂参数。
使用场景:调用接口类工具、需要多参数输入的任务。
Conversational ReAct Description
在 ReAct 框架基础上,增强了 对话记忆能力。
特点:能根据上下文对话历史来做出工具选择和回应,更适合持续性对话场景。
使用场景:多轮对话,用户可能引用之前的内容或需要长期上下文跟踪。
LangChain 中集成了很多工具,可以通过下面的方式进行查询:
from langchain_community.agent_toolkits.load_tools import get_all_tool_namesresults = get_all_tool_names()print(results)
运行结果:
['sleep', 'wolfram-alpha', 'google-search', 'google-search-results-json', 'searx-search-results-json', 'bing-search', 'metaphor-search', 'ddg-search', 'google-books', 'google-lens', 'google-serper', 'google-scholar', 'google-finance', 'google-trends', 'google-jobs', 'google-serper-results-json', 'searchapi', 'searchapi-results-json', 'serpapi', 'dalle-image-generator', 'twilio', 'searx-search', 'merriam-webster', 'wikipedia', 'arxiv', 'golden-query', 'pubmed', 'human', 'awslambda', 'stackexchange', 'sceneXplain', 'graphql', 'openweathermap-api', 'dataforseo-api-search', 'dataforseo-api-search-json', 'eleven_labs_text2speech', 'google_cloud_texttospeech', 'read_file', 'reddit_search', 'news-api', 'tmdb-api', 'podcast-api', 'memorize', 'llm-math', 'open-meteo-api', 'requests', 'requests_get', 'requests_post', 'requests_patch', 'requests_put', 'requests_delete', 'terminal']
接下来,通过一个示例来学习Agent的基本使用。
示例代码:
from langchain_core.messages import HumanMessagefrom langgraph.checkpoint.memory import MemorySaverfrom langchain.agents import create_agentfrom langchain_community.agent_toolkits.load_tools import load_toolsfrom langchain_openai import ChatOpenAIimportos# 实例化模型model = ChatOpenAI(base_url=os.environ.get('base_url','https://dashscope.aliyuncs.com/compatible-mode/v1'),model='qwen-plus',openai_api_key=os.environ.get('api_key','sk-XXXXXXXX'),max_tokens=1000,temperature=0)# Create the agentmemory = MemorySaver()tools = load_tools(['wikipedia', 'llm-math'], llm=model)agent_executor = create_agent(model, tools, checkpointer=memory)# Use the agentconfig = {"configurable": {"thread_id": "abc123"}}for chunk in agent_executor.stream({"messages": [HumanMessage(content="计算一下300的25%是多少?")]}, config):print(chunk)print("----")# for chunk in agent_executor.stream(# {"messages": [HumanMessage(content="大熊猫是哪个国家的国宝?")]}, config# ):# print(chunk)# print("----")
运行结果: