一个内容生成流程是一个实用的、多步骤的应用,使用 LangChain 表达式语言 (LCEL) 构建。此流程按顺序执行两项不同任务:首先,它根据给定主题生成博客文章大纲;其次,它使用生成的大纲为该博客文章撰写引言。这个过程类似于许多工作流,其中一个复杂的任务被分解为更小、可管理的子任务,并且一个步骤的输出作为下一个步骤的输入。配置组件在构建最终流程之前,我们需要定义构成流程的每个独立操作。我们的流程需要两个步骤:一个用于创建大纲,另一个用于撰写引言。首先,我们来设置语言模型和必要的导入。在此示例中,我们将使用 ChatOpenAI。from langchain_openai import ChatOpenAI from langchain_core.prompts import PromptTemplate from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import RunnablePassthrough # 初始化聊天模型。请确保您的 OpenAI API 密钥已配置。 llm = ChatOpenAI(temperature=0.7, model_name="gpt-3.5-turbo")链 1:大纲生成器我们流程的第一步是为博客文章生成结构化大纲。此链将接收一个输入 topic,并生成一个输出字符串。我们定义一个 PromptTemplate,它指示模型创建一个项目符号列表。然后,我们使用管道 | 运算符创建一个序列,连接提示词、模型和 StrOutputParser,以确保输出是干净的字符串。# 用于生成博客文章大纲的提示词和链 prompt_outline = PromptTemplate( input_variables=["topic"], template="为关于 {topic} 的博客文章创建一份简洁的项目符号大纲。" ) outline_chain = prompt_outline | llm | StrOutputParser()链 2:引言撰写器第二个链的任务是撰写引言。此链更复杂,因为它需要两个输入:原始 topic 和第一个链生成的大纲 outline。它的 PromptTemplate 反映了这一点,指示模型使用提供的大纲作为参考。# 用于撰写引言的提示词和链 prompt_intro = PromptTemplate( input_variables=["topic", "outline"], template="为关于 {topic} 的博客文章撰写一篇引人入胜的引言,请使用以下大纲作为参考:\n\n{outline}" ) intro_chain = prompt_intro | llm | StrOutputParser()组装流程定义了两个链之后,我们可以使用 LCEL 原语将它们组装成一个工作流。我们使用 RunnablePassthrough.assign 来管理数据流。这个函数使我们能够计算新值(如大纲或引言),并将它们添加到流经流程的输入字典中。下图说明了数据流。初始 topic 被两个链使用,而第一个链输出的 outline 成为第二个链的输入。digraph G { rankdir=TB; splines=ortho; node [shape=box, style="rounded,filled", fillcolor="#a5d8ff"]; edge [color="#495057"]; "User Input (topic)" [fillcolor="#ffec99", label="用户输入 (主题)"]; "Final Output (introduction)" [fillcolor="#b2f2bb", label="最终输出 (引言)"]; "User Input (topic)" -> "Outline Chain" [label=" 主题"]; "Outline Chain" [label="大纲链"]; "Introduction Chain" [label="引言链"]; "Outline Chain" -> "Introduction Chain" [label=" 大纲"]; "User Input (topic)" -> "Introduction Chain" [style=dashed, label=" 主题"]; "Introduction Chain" -> "Final Output (introduction)"; }一个内容生成流程图。topic 被两个链使用,而第一个链生成的大纲 outline 被传递给第二个链。在构建流程时,我们将赋值操作串联起来。首先,我们将 outline_chain 的输出赋值给键 outline。接下来,我们将 intro_chain 的输出赋值给键 introduction。这种结构确保第二个链能够访问初始 topic 和生成的大纲 outline。# 使用 RunnablePassthrough.assign 创建流程 # 这使我们能够在进程进行时向字典添加新键 content_pipeline = ( RunnablePassthrough.assign(outline=outline_chain) | RunnablePassthrough.assign(introduction=intro_chain) )运行流程现在,我们可以通过一次调用执行整个流程。我们提供一个包含初始输入变量 "topic" 的字典。# 提供一个主题并运行流程 topic = "the benefits of serverless computing" result = content_pipeline.invoke({"topic": topic})最终的 result 是一个字典,包含过程中累积的所有键,包括我们的输入和输出。让我们检查结果。# 打印结果 print("\n------ 生成的大纲 ------") print(result["outline"]) print("\n------ 生成的引言 ------") print(result["introduction"])示例输出:------ 生成的大纲 ------ - 无服务器计算引言 - 成本效益 - 可伸缩性和灵活性 - 提高开发者生产力 - 降低运营开销 - 无服务器计算的应用场景 - 结论 ------ 生成的引言 ------ 在不断发展的云计算行业,无服务器架构已成为应用程序构建和部署方式的一个重大转变。通过抽象底层基础设施,无服务器计算使开发者能够专注于编写代码,从而提高生产力和创新能力。本文讨论了采用无服务器方法的优势,从节省成本、自动伸缩性到降低运营负担。我们将审视该模型如何提升开发者生产力,并研究无服务器表现出色的实际应用场景,从而清晰地说明为什么它正在成为现代应用程序开发的优选。如您所见,流程成功执行了这两个步骤。intro_chain 有效地使用了 outline_chain 提供的情境,生成了相关且结构良好的引言。这个简单的两步过程说明了 LCEL 在创建精细、自动化工作流方面的能力。您可以通过添加更多链来进一步扩展此流程,根据大纲撰写博客文章的每个部分,从而从单个主题输入创建完整的草稿内容。