什么是 LangChain
LangChain 是一个用于开发由大型语言模型提供支持的应用程序的框架 (LLMs)。旨在帮助开发人员使用语言模型构建端到端的应用程序。
它提供了一套工具、组件和接口,可简化创建由大型语言模型 (LLM) 和聊天模型提供支持的应用程序的过程。
LangChain 可以轻松管理与语言模型的交互,将多个组件链接在一起,并集成额外的资源,比如API,数据库等等。
目前 LangChain 提供了 Python 和 TypeScript 的软件包。
为什么要用 LangChain
智能数据整合:Langchain框架支持将大规模语言模型与多样化数据存储系统进行深度对接,包括结构化数据库、非结构化PDF文档及其他文件格式。该特性使得企业能够充分挖掘私有知识库中的潜在价值,通过语义解析实现精准信息抽取。
操作自动化扩展:Langchain不仅可以提取信息,还可以根据这些信息执行特定的操作,比如可以自动化发送邮件。其核心优势在于采用动态参数化编程范式,避免硬编码,显著提升系统可维护性和扩展性。
LangChain的核心组件
Compents:“组件”
- 为LLMs提供接口封装、模板提示和信息检索索引
Chains:“链”
- 将不同的组件组合起来解决特定的任务,比如在大量文本中查找某些具体信息
Agent:“代理”
- 使得大模型能够与外部环境进行交互,例如通过API请求执行某些具体操作
LangChain 的核心概念
- LLM Wrappers:包装器,允许应用程序连接到大型语言模型,如 GPT-4 等大模型
- Prompt Templates:提示词模板,让用户避免硬编码文本输入,用户输入可以动态插入到模板中,并发送给语言模型
- Indexes:索引,用户需要借助索引从大模型中提取信息
- Models:负责理解和生成语言,提示用于引导模型输出
- Chains:链,将不同的组件组合起来解决特定的任务,比如在大量文本中查找某些具体信息
- Agent:使得大模型能够与外部环境进行交互,例如通过API请求执行某些具体操作
- Embedding:嵌入与向量存储 VectorStore 是数据表示和检索的手段,为模型提供必要的语言理解基础
LangChain 的工作原理
用户提问:用户提交一个问题或请求
检索相关内容:从向量数据库中找出与问题相关的内容片段,并传递给语言模型
向语言模型发起查询:系统将用户的问题转化为向量表示,并在向量数据库中进行相似度匹配
生成回答或执行任务:语言模型结合问题和补充信息,生成对应的回答或执行相应的操作
graph TD A[用户提交问题或请求] --> B[提取并检索相关内容] B -->|从向量库中取出匹配片段| C[组装问题与相关知识] C --> D[向语言模型发起查询] D --> E([语言模型生成回答或执行具体任务])
组件 | 用途 |
文档加载器 | 从各种不同的数据源家在文档 |
文档转换器 | 拆分文档,将文档转换为问答格式,过滤掉冗余文档 |
文本嵌入(embedding)模型 | 将非结构化文本转换为向量形式,也就是浮点数数组表现形式 |
向量存储 | 存储、搜索嵌入的向量数据 |
检索器 | 提供数据查询的通用接口 |
Model I/O
LangChain 提供了与任何 Model 进行交互的的构建模块, 即 Model I/O。
LangChain 的 Model I/O 模块是与这些语言模型(LLMs)进行交互的核心组件,它包括模型输入(Prompts)、模型输出(Output Parsers)和模型本身(Language Models)
Model I/O 的核心概念
由三个核心组件构成:Prompt Template、Language Models、Output parser
- Prompt Template:通过预设模板对大模型输入进行结构化组织和管理。
- Model:负责通过统一接口接入和调用不同的大语言模型
- Output parser:用于从模型输出中提取所需信息,并根据既定格式进行规范化处理后输出
LLM 的分类:
- 基础 LLM(Base LLM):在 LangChain 中,LLM 通常指的是传统的文本补全模型(Text Completion)。这类模型通过封装的 API 接收一个字符串类型的提示词作为输入,并返回对应的文本补全结果,输出同样是一个字符串。
- 对话式 LLM(Chat LLM):Chat LLM 虽然通常构建在 Base LLM 之上,但针对多轮对话场景做了专门优化。它们采用不同于基础模型的接口形式,以聊天消息的列表作为输入,并返回结构化的响应(Response 类型),而不仅仅是简单的字符串文本。
graph LR A[输入变量<br>Variables] --> B[Prompt Template<br>提示词模板] B -->|格式化得到 Prompt| C((Language Model<br>LLM / ChatModel)) C -->|返回非结构化文本/Message| D[Output Parser<br>输出解析器] D -->|解析并格式化| E([最终输出的结构化数据])
Prompt Template
prompt templates
Prompt 模板是一种预定义的结构,用于构建(格式化)发送给大语言模型的 prompt。简单理解Prompt 模板就像一个事先设定好的“问题格式”,可以帮我们快速生成标准化的模型指令。LangChain 提供了一些与具体模型无关的通用 prompt 模板,这些模板可以在不同的 LLM 上复用,提高开发效率和适配灵活性。
PromptTemplate
PromptTemplate主要用于创建一个字符串prompt,其实它就是相当于的Python str.format ,用来格式化我们的输入。它支持任意数量的变量,也可以没有没有变量
指定参数
from langchain.prompts import PromptTemplate prompt_template = PromptTemplate.from_template( "请给我取一个{adjective}的{name}名字" ) prompt_template.format(adjective="搞笑的", name="男孩")
不带参数
同样,这个模板可以包含任意多个变量,也可以不包含任何变量
from langchain.prompts import PromptTemplate prompt_template = PromptTemplate.from_template( "请给我取一个名字" ) prompt_template.format()
通过 invoke 方法填入提示词参数
from langchain.prompts import PromptTemplate prompt_template = PromptTemplate.from_template( "请给我取一个{adjective}的{name}名字" ) prompt_template.invoke({"adjective":"很土","name":"男孩"})
通过加号增加临时内容
如果需要在既有的模板下增加临时内容,也可以使用+來增加提示内容。
from langchain.prompts import PromptTemplate prompt_template = PromptTemplate.from_template( "请给我取一个{adjective}的{name}名字,")+ "并告诉我你取名参考的是{content}" prompt_template.format(adjective="好听的",name="男孩",content="论语")
ChatPromptTemplate
ChatPromptTemplate 是专为多轮对话设计的提示模板,它允许开发者分别定义不同对话角色的内容,从而帮助 AI 模型更自然地进行交流。它的核心功能是模拟对话中的多个角色,包括用户输入(HumanMessage)、AI 回复(AIMessage),以及系统提示或背景信息(SystemMessage)。通过这种结构化的方式,可以提升对话的连贯性和真实感。
from langchain_deepseek import ChatDeepSeek from langchain.prompts.chat import ChatPromptTemplate import os load_dotenv() chat_template = ChatPromptTemplate.from_messages( [ ("system", "你是一位专业且有耐心的客服助手,负责解答用户的问题。你的名字叫{name}."), ("human", "你好,我的订单怎么还没有发货?"), ("ai", "您好,我来帮您查询一下订单状态,请您稍等。"), ("human", "{user_question}"), ] ) messages = chat_template.format_messages(name="小明", user_question="请问我可以修改收货地址吗?")
接下来再下一个cell中调用DeepDeek大模型接口,把这个messages传给DeepDeek,然后看下DeepDeek给我们返回什么?
from langchain_deepseek import ChatDeepSeek import os load_dotenv() # 创建 DeepSeek 模型实例 model = ChatDeepSeek( model="deepseek-chat", temperature=0, api_key=os.getenv("DEEPSEEK_API_KEY") ) # 将消息发送给模型 response = model.invoke(messages) # 输出响应内容 print(response.content)
您好,如果订单还未发货,是可以修改收货地址的。请您提供订单号,我帮您确认一下当前状态。
尽管上述传给大模型的是一组对话,但是用户最终的问题是“请问我可以修改收货地址吗?”,而这里DeepDeek给出的回答正好是这个问题的回答,而且回答的非常完美。
尽管上述传给大模型的是一组对话,但是用户最终的问题是“请问我可以修改收货地址吗?”,而这里DeepDeek给出的回答正好是这个问题的回答,而且回答的非常完美
这里有一个疑问,既然是要大模型回答用户的具体问题,按照上面的例子,我们直接给大模型最后的这个问题“请问我可以修改收货地址吗?”丢给大模型不就完了吗?为什么还要这么包装一组对话给它呢?
仔细思考一下,当你突然问一个人,“我可以修改收货地址吗?”,对方估计会一脸懵逼,啥玩意,突然来这么个问题,是不是搞错提问对象了?
大模型同样如此,我们完全可以把大模型想象成这个人,当你什么上下文都没提供给他的时候,就问这么个问题,他也很懵逼,最后只会给你乱说一通。所以这里再次回到ChatPromptTemplate本身,他其实是通过SystemMessage给大模型安置了一个背景或者事角色,然后通过前面的几组对话,告诉大模型现在处在一个什么场景下,所以接下来用户提的问题,大模型才会根据它的角色,基于当前场景来回答, 这样的回答才可能最终是我们想要的答案。
简单总结就是,ChatPromptTemplate可以给大模型的回答提供必要的上下文,使得大模型的回答准确性更高了
Language Model
在 LangChain 中,Language Model 模块是用于直接与语言模型进行交互的核心构建单元(Building Block)。
目前,LangChain 主要支持并集成了两类语言模型:
- LLMs:接受文本字符串作为输入,返回文本字符串作为输出的模型(即 text in → text out)。
- Chat Models:以一组对话消息作为输入,返回新的对话消息作为输出的模型(即 chat messages in → chat messages out)。这些消息通常包含文本内容(content)和角色(role)信息(如 system、human、ai)。
简单理解就是,LM可以认为是一个文本生成式模型,即大模型会根据用户输入的指示,生成一段相关的文本; 而Chat Model则是一个聊天驱动的模型,即可以进行多轮对话。
LLMS
LLM 是 LangChain 架构中的关键组成部分,也叫Base LLM。典型的交互模式是:文本输入 → 文本输出( text in → text out)。LangChain 提供了统一的标准接口,用于对接多种 LLM 类型。你可以在其文档中查看当前支持的各类模型。
所有 LLM 实现都遵循 LangChain 的 Runnable 接口规范,该接口提供了如
invoke、ainvoke、batch、abatch、stream、astream 等方法的默认实现,方便开发者灵活调用模型。Chat LLM
Chat Model可以认为是LLM 的变体,其底层通常还是由Base LLM支撑,但专门针对对话进行了调整。并且它提供的 Interface 有了比较大的差异,提供基于”聊天消息”的接口,而不单单是一个字符串。他的输入和输出可以简单理解如下:
输入 | 输出 |
一组聊天消息 | 一条聊天消息 |
Messages 类型
Chat models使用chat message作为输入和输出,LangChain目前支持的
chat message类型有:Messages类型 | 用途 |
SystemMessage | 设定大模型的身份,人设 |
HumanMessage | 用户输入 |
AIMessage | 模型输出 |
FunctionMessage | 函数调用的返回结果,用于标识某个函数执行的内容返回,除了对应的role和content参数外,还有一个name参数,表示对应名称的函数的执行结果,与 function_call 搭配使用 |
ToolMessage | 工具调用的返回结果,用于标识某个工具执行的内容返回,tool_call_id:表示对应哪一次工具调用的返回结果,与 tool_calls 搭配 |
from langchain_deepseek import ChatDeepSeek import os load_dotenv() # 创建 DeepSeek 模型实例 model = ChatDeepSeek( model="deepseek-chat", temperature=0, api_key=os.getenv("DEEPSEEK_API_KEY") ) messages = [ SystemMessage(content="你一名中国古诗词鉴赏专家"), HumanMessage(content="《青玉案·元夕》"), ] response = model.invoke(messages) print(response.content)
上述例子知识用SystemMessage给了AI一个身份,并且让其回答HumanMessage中用户的问题,很简单。既然学习了前面的提示词模板,这里同样可以用模板来给这几个message进行格式化。
# 构建 Prompt 模板(带变量) system_template = "你是一个专业的{role},回答问题要简洁清晰。" human_template = "请用{language} 写一个{task} 的程序。" # 使用模板封装 message system_message_prompt = SystemMessagePromptTemplate.from_template(system_template) human_message_prompt = HumanMessagePromptTemplate.from_template(human_template) # 构建最终 ChatPromptTemplate chat_prompt = ChatPromptTemplate.from_messages([ system_message_prompt, human_message_prompt ]) # 模板填充变量 formatted_messages = chat_prompt.format_messages( role="后端开发专家", language="Go语言", task="快速排序" ) response = model.invoke(formatted_messages) print(response.content)
[SystemMessage(content='你是一个专业的 后端开发专家,回答问题要简洁清晰。', additional_kwargs={}, response_metadata={}), HumanMessage(content='请用 Go语言 写一个 快速排序 的程序。', additional_kwargs={}, response_metadata={})]
可以看到最终将
chat_prompt变成了list的形式,并且讲原来message里的模板参数替换成了真正的变量。Output Parsers
Output Parsers 即输出解析器,从前面示例可以看到,
LLM和ChatModel的输出都是自然语言文本,也就是字符串 。但很多时候,我们希望它能以特定的格式输出,以便解析成结构化的数据。LangChain也提供的Output Parsers就是完成这个功能的Output Parsers 在使用的时候通常需要实现两个关键方法:
get_format_instructions():返回一段文本,用于告诉语言模型如何组织和格式化它的输出内容。
parse():用于接收语言模型返回的字符串结果,并将其解析为结构化的数据形式(如字典、对象等),便于后续程序处理。
目前LangChain提供了一些列预定义的类,以下是一些常用的预定义的 Output Parsers
from langchain.output_parsers import CommaSeparatedListOutputParser output_parser = CommaSeparatedListOutputParser() # 获取输出解析器提供的格式指导说明文本 parser_instructions = output_parser.get_format_instructions() ... # 调用模型,获取模型响应内容 response = model.invoke(final_prompt) # 使用解析器将模型输出内容转换成 Python 列表 ret = output_parser.invoke(response) ### Your response should be a list of comma separated values, eg: `foo, bar, baz` or `foo,bar,baz` ['中山陵', '夫子庙', '明孝陵', '玄武湖', '南京博物院'] ###
Model I/O模块是LangChain 框架的核心模块,它主要由 Prompt Template 模块、语言模型(LLM 与 Chat Model)、输出解析器(Output Parsers)三大核心组件构成。Prompt 作为与模型交互的“桥梁”,在提高指令清晰度和任务表达力方面发挥着重要作用;LLM 和 Chat Model 则构成了整个模型调用链的执行核心;而 Output Parsers 则帮助我们提升模型结果的可控性和可解析性。
数据连接
什么是数据连接
现在的通用大模型其实是没有处理用户特定数据的能力的,很多场景下,基于这些通用大模型的应用经常需要用到模型中没有的数据,而这些数据并不属于模型的训练集。针对这种情况,LangChaint提供了一些列的工具可以从各种数据源中加载新的数据,转换数据,存储数据以及访问数据。主要有以下几种组件
