Chain 链
概述
为开发更复杂的应用程序,需要使用 Chain 来链接 LangChain 中的各个组件和功能,包括模型之间的链接以及模型与其他组件之间的链接。
LangChain 链是连接组件的基本功能单元,分为 LCEL 构建链和遗留链。文章介绍常用链构造器与遗留链的使用场景,通过代码示例演示 LLMChain 基础用法、LCEL 表达式语言及 invoke、predict、apply、generate 等调用方式,展示如何组合模型与工具完成复杂任务。

为开发更复杂的应用程序,需要使用 Chain 来链接 LangChain 中的各个组件和功能,包括模型之间的链接以及模型与其他组件之间的链接。
链在内部把一系列的功能进行封装,而链的外部则又可以组合串联。链其实可以被视为 LangChain 中的一种基本功能单元。
LangChain 中提供了很多种类型的预置链,目的是使各种各样的任务实现起来更加方便、规范。
LangChain 支持两种类型的链:
1. 使用 LCEL 构建的链,LangChain 提供了一个更高级别的构造方法,实际上所有工作都是使用 LCEL 构建链。
2. [遗留] 通过从继承自遗留 Chain 类构建的链,这些链独立于 LCEL 而存在。
如何使用:
访问文档,搜索链名称,查看具体用法。
说明:
链构造器:这是链的构造函数,返回 LCEL 可运行对象的方法。可查看 API 文档了解更多信息。
函数调用:确定是否需要调用 OpenAI 函数。
其他工具:在链中使用了哪些其他工具(如果有的话)。
以下是一个包含所有 LCEL 链构造器的表格
| 链构造器 | 函数调用 | 其他工具 | 使用场景 |
|---|---|---|---|
| create_stuff_documents_chain | 将文档列表收集并格式化成一个提示,然后传递给 LLM。LLM 将传递所有文档,所以请确保提示适合 LLM 的上下文窗口。 | ||
| create_openai_fn_runnable | √ | 使用 OpenAI 函数调用来有选择性地构建输出响应。可以传递多个函数供其调用,但不一定要调用这些函数。 | |
| create_structured_output_runnable | √ | 可以使用 OpenAI 函数调用来强制 LLM 以某个函数进行响应。只能传入一个函数,并且链将始终返回此响应。 | |
| load_query_constructor_runnable | 可以用来生成查询。需指定允许的操作列表,然后将自然语言查询转换为这些允许的操作的可运行对象。 | ||
| create_sql_query_chain | SQL 数据库 | 从自然语言构建 SQL 数据库的查询 | |
| create_history_aware_retriever | Retriever 检索器 | 该链将收集对话历史记录,然后将其用于生成传递给底层检索器的搜索查询。 | |
| create_retrieval_chain | Retriever 检索器 | 该链将接收用户查询,然后传递给检索器以获取相关文档。随后,将这些文档(以及原始输入)传递给 LLM 以生成响应。 |
说明:
链:链的名称,或构造方法的名称。如果是构造方法,这将返回一个 Chain 子类。
函数调用:是否需要 OpenAI 函数调用。
其他工具:链中使用的其他工具。
以下是一个包含所有遗留链的表格
| 链 | 函数调用 | 其他工具 | 使用场景 |
|---|---|---|---|
| APIChain | Requests Wrapper 请求包装器 | 该链使用 LLM 将查询转换为 API 请求,执行请求并获取响应,最后将该响应传递给 LLM 进行处理。 | |
| OpenAPIEndpointChain | OpenAPI 规范 | 该链类似于 APIChain,专注于与 API 进行交互。主要区别在于它针对 OpenAPI 端点的易用性进行了优化。 | |
| ConversationalRetrievalChain | Retriever 检索器 | 该链可以用于与文档进行对话。它接受用户提出的问题和可能包含的对话历史记录。如果有对话历史记录,它会使用 LLM 将对话重写为查询后发送给检索器。接着,获取相关文档并将它们和对话传递给 LLM 生成响应。 | |
| StuffDocumentsChain | 该链会获取文档列表,将它们格式化为提示后传递给 LLM。它传递所有文档,需确保适用于 LLM 的上下文窗口。 | ||
| ReduceDocumentsChain | 该链会通过迭代减少文档数量来组合文档。将文档分组后传递至 LLM 中处理,获取响应后再继续进行操作,直到能够将所有内容传递给最终的 LLM 调用。适用于处理大量文档,并希望 LLM 并行执行时。 | ||
| MapReduceDocumentsChain | 该链会首先通过 LLM 传递每个文档,然后使用 ReduceDocumentsChain 来减少文档数量。在与 ReduceDocumentsChain 相同的情况下非常有用,但会在尝试减少文档之前进行初始 LLM 调用。 | ||
| ConstitutionalChain | 该链会回答问题,然后根据提供的宪法原则尝试完善答案,以确保答案符合这些原则。可用来强制链的答案遵循指定的原则。 | ||
| LLMChain | LLMChain 是最基础也是最常见的链 | ||
| ElasticsearchDatabaseChain | Elasticsearch 实例 | 该链将自然语言问题转换为 Elasticsearch 查询,执行查询后总结响应。适用于向 Elasticsearch 数据库提出自然语言问题时使用。 | |
| FlareChain | 这是 FLARE 的实现,一种高级检索技术,主要用作一种探索性高级检索方法。 | ||
| ArangoGraphQAChain | Arango 图 | 该链利用自然语言构建 Arango 查询,针对图数据库执行该查询,并将结果传递回 LLM 进行响应。 | |
| GraphCypherQAChain | 使用 Cypher 查询语言的图 | 该链根据自然语言构建 Cypher 查询,针对图数据库执行查询,然后将结果传递回 LLM 进行响应。 | |
| FalkorDBGraphQAChain | Falkor 数据库 | 该链根据自然语言构建 FalkorDB 查询,针对图数据库执行查询,然后将结果传递回 LLM 进行响应。 | |
| HugeGraphQAChain | HugeGraph | 该链使用自然语言构造 HugeGraph 查询,对图数据库执行查询,然后将结果传递回 LLM 进行响应。 | |
| KuzuQAChain | Kuzu 图 | 该链根据自然语言构建 Kuzu Graph 查询,对图数据库执行查询,再将结果传递回 LLM 进行响应。 | |
| NebulaGraphQAChain | Nebula 图 | 该链根据自然语言构造 Nebula Graph 查询,对图数据库执行查询,然后将结果传递回 LLM 进行响应。 | |
| NeptuneOpenCypherQAChain | Neptune 图 | 该链使用自然语言构建 Neptune 图查询,执行查询后将结果传递回 LLM 进行响应。 | |
| GraphSparqlChain | 适用于 SparQL 的图 | 该链根据自然语言构造 SPARQL 查询,执行查询后将结果传递回 LLM 进行响应。 | |
| LLMMath | 该链将用户问题转换为数学问题,然后执行它(使用 numexpr) | ||
| LLMCheckerChain | 该链使用第二个 LLM 调用来验证初始答案,并在初始 LLM 调用上添加额外的验证层时选择此选项。 | ||
| LLMSummarizationChecker | 该链使用一系列 LLM 调用创建摘要,以确保准确性。当更关注准确性而不是速度/成本时,可以在正常摘要链上使用这种方法。 | ||
| create_citation_fuzzy_match_chain | √ | 使用 OpenAI 函数调用来回答问题并引用其来源。 | |
| create_extraction_chain | √ | 使用 OpenAI 函数调用从文本中提取信息。 | |
| create_extraction_chain_pydantic | √ | 使用 OpenAI 函数调用将文本信息提取到 Pydantic 模型中,它与 Pydantic 的集成比 create_extraction_chain 更紧密。 | |
| get_openapi_chain | √ | OpenAPI 规范 | 使用 OpenAI 函数调用来查询 OpenAPI |
| create_qa_with_structure_chain | √ | 使用 OpenAI 函数调用通过文本进行问答并以特定格式进行响应 | |
| create_qa_with_sources_chain | √ | 使用 OpenAI 函数调用来回答带有引文的问题 | |
| QAGenerationChain | 从文档创建问题和答案。用于生成问题/答案对以评估检索项目 | ||
| RetrievalQAWithSourcesChain | Retriever | 对检索到的文档进行问答,并引用来源。当希望答案在文本响应中包含来源时,请使用此选项。在 load_qa_with_sources_chain 上使用此选项,以便在链的一部分中获取相关文档而不是传递它们。 | |
| load_qa_with_sources_chain | Retriever | 对传入的文件进行问答,并引用来源。当希望答案在文本响应中带有来源时,请使用此选项。如果想直接传递文档而不依赖检索器获取它们,请使用这种方法而不是 RetrievalQAWithSources。 | |
| RetrievalQA | Retriever | 该链首先进行检索步骤以获取相关文档,然后将这些文档传递给 LLM 以生成响应。 | |
| MultiPromptChain | Retriever | 该链在多个提示之间路由输入。当有多个潜在提示可用于响应,且只想路由到一个提示时,请使用此选项。 | |
| MultiRetrievalQAChain | 该链在多个检索器之间路由输入。当有多个潜在的检索器可获取相关文档,并且只希望路由到一个检索器时,请使用此选项。 | ||
| EmbeddingRouterChain | 该链使用嵌入相似性来路由传入查询 | ||
| LLMRouterChain | 该链使用 LLM 在潜在选项之间进行路由 | ||
| load_summarize_chain | 用于进行摘要和总结的链 | ||
| LLMRequestsChain | 该链根据用户输入构造一个 URL,获取数据,然后汇总响应。相较于 APIChain,这个链更加通用,不专注于单一 API 规范。 |
LLMChain 是最基础也是最常见的链。LLMChain 结合了语言模型推理功能,并添加了 PromptTemplate 和 Output Parser 等功能,将模型输入输出整合在一个链中操作。它利用提示模板格式化输入,将格式化后的字符串传递给 LLM 模型,并返回 LLM 的输出。这样使得整个处理过程更加高效和便捷。
当未使用 Chain 时,Model I/O 的实现分为两个部分,提示模板的构建和模型的调用独立处理。
# 导入 LangChain 中的提示模板
from langchain_core.prompts import PromptTemplate
# 原始字符串模板
template = "猪八戒吃{fruit}?"
# 创建 LangChain 模板
prompt_temp = PromptTemplate.from_template(template)
# 根据模板创建提示
prompt = prompt_temp.format(fruit='人参果')
# 导入 LangChain 中的 OpenAI 模型接口
from langchain_openai import OpenAI
# 创建模型实例
model = OpenAI(temperature=0)
# 传入提示,调用模型返回结果
result = model.invoke(prompt)
print(result)
猪八戒是《西游记》中的一个角色,他是一只贪吃懒惰的猪妖,平时喜欢吃各种美食。在《西游记》中,猪八戒曾经吃过人参果,但并不是真的吃了人参果,而是被唐僧误认为是人参果而被骗吃了。事实上,人参果是一种神奇的果实,可以让人长生不老,但是只有在特定的条件下才能生长,非常稀少。因此,猪八戒并没有真的吃到人参果。
当使用 Chain 链时,代码结构则更简洁。
from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI
# 原始字符串模板
template = "猪八戒吃{fruit}?"
# 创建模型实例
llm = OpenAI(temperature=0)
# 创建 LLMChain
llm_chain = LLMChain(
llm=llm,
prompt=PromptTemplate.from_template(template))
# 调用 LLMChain,返回结果
result = llm_chain.invoke({"fruit": "人参果"})
print(result)
{'fruit': '人参果', 'text': '\n\n猪八戒是《西游记》中的一个角色,他是一只贪吃懒惰的猪妖,平时喜欢吃各种美食。在《西游记》中,猪八戒曾经吃过人参果,但并不是真的吃了人参果,而是被唐僧误认为是人参果而被骗吃了。事实上,人参果是一种神奇的果实,可以让人长生不老,但是只有在特定的条件下才能生长,非常稀少。因此,猪八戒并没有真的吃到人参果。'}
LangChain 表达式语言,或 LCEL,是一种声明式的方法,可以轻松地将链组合在一起。
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI
# 原始字符串模板
template = "猪八戒吃{fruit}?"
prompt = PromptTemplate.from_template(template)
# 创建模型实例
llm = OpenAI(temperature=0)
# 创建 Chain
chain = prompt | llm
# 调用 Chain,返回结果
result = chain.invoke({"fruit": "人参果"})
print(result)
通过 invoke 方法,在调用链的时候,传入一个字典参数。在新、高版本中推荐使用。
from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI
# 创建模型实例
template = PromptTemplate(
input_variables=["role", "fruit"],
template="{role}喜欢吃{fruit}?",
)
# 创建 LLM
llm = OpenAI(temperature=0)
# 创建 LLMChain
llm_chain = LLMChain(llm=llm, prompt=template)
# 调用 LLMChain,返回结果
# 如果提示模板中包含多个变量,在调用链的时候,可以使用字典一次性输入它们。
result = llm_chain.invoke({"role": "猪八戒", "fruit": "人参果"})
print(result)
{'role': '猪八戒', 'fruit': '人参果', 'text': '\n\n猪八戒是一只贪吃懒惰的猪妖,他最喜欢吃的是猪食。人参果是唐僧师徒在取经途中遇到的一种神奇的水果,具有延年益寿的功效,但并非猪八戒的最爱。'}
通过 predict 方法,将输入键指定为关键字参数
from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI
# 创建模型实例
template = PromptTemplate(
input_variables=["role", "fruit"],
template="{role}喜欢吃{fruit}?",
)
# 创建 LLM
llm = OpenAI(temperature=0)
# 创建 LLMChain
llm_chain = LLMChain(llm=llm, prompt=template)
# 调用 LLMChain,返回结果
result = llm_chain.predict(role="猪八戒", fruit="人参果")
print(result)
apply 方法允许输入列表运行链,一次处理多个输入。
from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI
# 创建模型实例
template = PromptTemplate(
input_variables=["role", "fruit"],
template="{role}喜欢吃{fruit}?",
)
# 创建 LLM
llm = OpenAI(temperature=0)
# 创建 LLMChain
llm_chain = LLMChain(llm=llm, prompt=template)
# 输入列表
input_list = [
{"role": "猪八戒", "fruit": "人参果"}, {"role": "孙悟空", "fruit": "仙桃"}
]
# 调用 LLMChain,返回结果
result = llm_chain.apply(input_list)
print(result)
[{'text': '\n\n猪八戒是一个贪吃的角色,他喜欢吃各种美味的食物,包括人参果。在《西游记》中,猪八戒曾经在取经路上遇到过人参果树,他非常贪婪地摘下来吃,结果被孙悟空和唐僧发现并教训。虽然人参果具有补气养血的功效,但是对于猪八戒来说,它更像是一种美味的水果,他并不在意它的药用价值。因此,可以说猪八戒是喜欢吃人参果的。'}, {'text': '\n\n是的,孙悟空非常喜欢吃仙桃。在《西游记》中,他经常会偷吃仙桃,甚至为了吃仙桃而闹出许多笑话和故事。仙桃也是孙悟空的最爱,因为它们具有神奇的功效,可以让他长生不老。'}]
generate 方法类似于 apply,但它返回一个 LLMResult 对象,而不是字符串。LLMResult 通常包含了在模型生成文本过程中的一些相关信息,例如令牌数量、模型名称等。
from langchain.chains.llm import LLMChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI
# 创建模型实例
template = PromptTemplate(
input_variables=["role", "fruit"],
template="{role}喜欢吃{fruit}?",
)
# 创建 LLM
llm = OpenAI(temperature=0)
# 创建 LLMChain
llm_chain = LLMChain(llm=llm, prompt=template)
input_list = [
{"role": "猪八戒", "fruit": "人参果"}, {"role": "孙悟空", "fruit": "仙桃"}
]
# 调用 LLMChain,返回结果
result = llm_chain.generate(input_list)
print(result)
generations=[[Generation(text='\n\n猪八戒是一个贪吃的角色,他喜欢吃各种美味的食物,包括人参果。在《西游记》中,猪八戒曾经在取经路上遇到过人参果树,他非常贪婪地摘下来吃,结果被孙悟空和唐僧发现并责备他。虽然人参果具有补气养血的功效,但是对于猪八戒来说,它更像是一种美味的水果,他并不在意它的药用价值。因此可以说,猪八戒确实喜欢吃人参果。', generation_info={'finish_reason': 'stop', 'logprobs': None})], [Generation(text='\n\n是的,孙悟空非常喜欢吃仙桃。在《西游记》中,他经常会偷吃仙桃,甚至为了吃仙桃而闹出许多笑话和故事。仙桃也是孙悟空的最爱,因为它们具有神奇的功效,可以让他长生不老。', generation_info={'finish_reason': 'stop', 'logprobs': None})]] llm_output={'token_usage': {'completion_tokens': 309, 'total_tokens': 343, 'prompt_tokens': 34}, 'model_name': 'gpt-3.5-turbo-instruct'} run=[RunInfo(run_id=UUID('1354a070-6820-4005-9436-af859e65ebc3')), RunInfo(run_id=UUID('7d5d6633-b56d-487f-ae18-24a3f4ac21db'))]
可以直接调用链对象,实际调用对象内部实现的
__call__方法。在新、高版本中不推荐使用且将被弃用。
注意:
当像函数一样调用一个对象时,它实际上会调用该对象内部实现的
__call__方法。
# 创建 LLMChain
llm_chain = LLMChain(llm=llm, prompt=template)
# 调用 LLMChain,返回结果
result = llm_chain({"role": "猪八戒", "fruit": "人参果"})
print(result)
通过 run 方法,等价于直接调用 _call_ 函数。在新、高版本中不推荐使用且将被弃用。
# 创建 LLMChain
llm_chain = LLMChain(llm=llm, prompt=template)
# 调用 LLMChain,返回结果
result = llm_chain.run({"role": "猪八戒", "fruit": "人参果"})
print(result)

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online