LangChain 链允许以设定的顺序连接多个对 LLM 或其他组件的调用。这项能力对于构建需要不止一次语言模型交互的应用是十分重要的。在此动手练习中,我们将构建一个 SequentialChain。这种类型的链会按顺序执行其组成链,并将一个链的输出作为下一个链的输入。我们的目标是创建一个两步工作流程:第一步: 给定一个话题(例如,一项特定技术),为其博客文章生成一个简短、吸引人的标题。第二步: 给出生成的标题,撰写一条简短的推文(280字符以内)来公告该博客文章。这需要两次独立的 LLM 交互,其中第二次交互直接依赖于第一次的输出。前置条件在开始前,请确保您已按第2章所述设置好 Python 环境,包括:LangChain 已安装(pip install langchain langchain-openai)。一个 LLM 提供商库已安装(我们将使用 OpenAI 的,但其他也可以替代)。您的 API 密钥已安全配置(例如,使用环境变量)。# 基本导入和环境设置 import os from langchain_openai import ChatOpenAI from langchain.prompts import PromptTemplate from langchain.chains import LLMChain, SequentialChain # 确保您的 OPENAI_API_KEY 环境变量已设置 # 例如:os.environ["OPENAI_API_KEY"] = "您的API密钥" # 或者使用 python-dotenv 从 .env 文件加载 # 初始化 LLM # 我们将使用 ChatOpenAI 模型 llm = ChatOpenAI(temperature=0.7, model_name="gpt-3.5-turbo")注意:如果您之前没有加载环境变量,请记住将 "your_api_key_here" 替换为您的实际密钥。如果需要,请调整 model_name。步骤 1:定义标题生成链首先,我们需要一个链,它接收一个技术话题并生成一个合适的博客文章标题。这需要定义一个提示模板和一个 LLMChain。# --- 链 1:生成博客文章标题 --- # 用于标题生成的提示模板 title_template_string = """ You are an expert technical writer. Given the following topic, create a catchy and informative blog post title. Topic: {topic} Blog Post Title: """ title_prompt_template = PromptTemplate( input_variables=["topic"], template=title_template_string ) # 创建第一个 LLMChain # 我们明确将输出键命名为 'blog_title' title_chain = LLMChain( llm=llm, prompt=title_prompt_template, output_key="blog_title" # 此键保存此链的输出 ) # 独立测试此链(可选) # result_title = title_chain.invoke({"topic": "Vector Databases"}) # print(f"生成的标题:{result_title['blog_title']}")这里,我们创建一个 PromptTemplate,它期望一个 topic 变量。然后我们使用我们的 LLM 和此提示实例化 LLMChain。重要地,我们指定了 output_key="blog_title"。这给此链的输出分配了一个名称,对于将其正确传递给序列中的下一个链非常重要。步骤 2:定义推文生成链接下来,我们创建一个链,它接收博客文章标题(由第一个链生成)并撰写一条简短的推文来公告它。# --- 链 2:生成推文 --- # 用于推文生成的提示模板 tweet_template_string = """ You are a social media expert specializing in tech promotion. Given the blog post title below, write a concise and engaging tweet (under 280 characters) announcing it. Include relevant hashtags. Blog Post Title: {blog_title} Tweet: """ tweet_prompt_template = PromptTemplate( input_variables=["blog_title"], # 输入来自前一个链的输出 template=tweet_template_string ) # 创建第二个 LLMChain # 这里的输出键将是序列的最终输出 tweet_chain = LLMChain( llm=llm, prompt=tweet_prompt_template, output_key="tweet" # 此键保存最终输出 ) # 独立测试此链(可选) # 示例标题:“解锁语义搜索:向量数据库的应用” # result_tweet = tweet_chain.invoke({"blog_title": "Unlocking Semantic Search: An Exploration of Vector Databases"}) # print(f"生成的推文:{result_tweet['tweet']}")此链的 PromptTemplate 期望一个名为 blog_title 的输入变量,这完美匹配我们为 title_chain 定义的 output_key。它自己的输出被命名为 tweet。步骤 3:使用 SequentialChain 组合链现在,我们使用 SequentialChain 将这两个链组合成一个工作流程。这个类处理执行顺序以及组成链之间的输出到输入的传递。# --- 将链组合成一个 SequentialChain --- # 创建 SequentialChain # 它接受按顺序运行的链列表 # 输入变量是 *第一个* 链所需的变量 # 输出变量是 *最后一个* 链(或如果需要,中间链)产生的变量 overall_chain = SequentialChain( chains=[title_chain, tweet_chain], input_variables=["topic"], # 第一个链(title_chain)所需的输入 output_variables=["blog_title", "tweet"], # 序列产生的输出 verbose=True # 设置为 True 以查看执行步骤 )我们以期望的执行顺序提供了链列表([title_chain, tweet_chain])。input_variables=["topic"]:指定整个顺序链期望的输入。这必须匹配序列中 第一个 链(title_chain)的输入变量。output_variables=["blog_title", "tweet"]:列出我们希望 SequentialChain 返回的输出键。这包括最终输出(tweet),也可以选择性地包含中间输出(blog_title)。verbose=True:这对于调试很有帮助,因为它会打印关于每个执行步骤的信息。步骤 4:执行多步链最后,我们可以通过提供初始输入话题来运行我们的 overall_chain。# --- 执行顺序链 --- # 定义输入话题 input_topic = "The role of Embeddings in RAG systems" # 运行链 # 使用 .invoke() 进行执行 result = overall_chain.invoke({"topic": input_topic}) # 打印结果 print("\n--- 结果 ---") print(f"输入话题:{input_topic}") print(f"生成的博客标题:{result['blog_title']}") print(f"生成的推文:{result['tweet']}")运行此代码将触发以下顺序:input_topic 被传递给 title_chain。title_chain 使用其提示模板与 LLM 交互并生成一个标题。此标题内部存储并关联到键 blog_title。SequentialChain 自动将与 blog_title 关联的值作为输入传递给 tweet_chain。tweet_chain 使用其提示模板和提供的标题与 LLM 交互,生成一条推文。此推文内部存储并关联到键 tweet。SequentialChain 返回一个包含指定 output_variables 的字典:blog_title 和 tweet。digraph G { rankdir=LR; node [shape=box, style=rounded, fontname="sans-serif", color="#495057", fillcolor="#dee2e6", style="filled,rounded"]; edge [fontname="sans-serif", color="#495057"]; input [label="输入\n(话题)", shape=ellipse, fillcolor="#a5d8ff"]; chain1 [label="链 1:标题生成\n(LLMChain)", fillcolor="#bac8ff"]; chain2 [label="链 2:推文生成\n(LLMChain)", fillcolor="#bac8ff"]; output [label="输出\n(blog_title, tweet)", shape=ellipse, fillcolor="#a5d8ff"]; input -> chain1 [label="topic"]; chain1 -> chain2 [label="blog_title"]; chain2 -> output [label="tweet"]; }两步顺序链实现的流程图。总结在此练习环节中,您成功使用 LangChain 的 SequentialChain 实现了一个多步工作流程。您定义了单独的 LLMChain 组件,每个负责特定任务,并将它们连接起来,使一个步骤的输出作为下一个步骤的输入。您还了解了正确命名输入和输出变量(input_variables、output_key)对于确保链之间数据流畅通的重要性。这种模式对于自动化涉及顺序推理或生成步骤的流程非常有用,构成构建更复杂 LLM 应用的核心组成部分。您可以通过添加更多链、纳入不同类型的链(如用于数据操作的 TransformChain),或使用更灵活的 SequentialChain 来扩展此功能,后者在需要时可以处理更复杂的输入/输出。