LangChain“链”的使用 | 豆包MarsCode AI刷题

78 阅读8分钟

1. 什么是Chain(链)

核心概念
LangChain中的“链”是一个核心组件,用于将不同的模块(如模型、提示模板、输出解析器等)串联起来。通过链的机制,可以将复杂任务分解成多个步骤,并以模块化的方式执行,从而开发更加灵活、清晰和可维护的应用程序。

主要优势

  1. 模块化:链将复杂的功能封装到独立组件中,便于调试、测试和维护。
  2. 灵活性:链之间可以嵌套组合,实现复杂的逻辑功能。
  3. 简化代码:通过封装常见操作,减少重复代码,提高开发效率。
  4. 可扩展性:支持自定义链或使用预置链满足多样化需求。

2. 基础链:LLMChain

LLMChain是LangChain中最基础的链,它整合了提示模板(PromptTemplate)、语言模型(LLM或聊天模型)和输出解析器,将语言模型的输入输出逻辑封装在一起,简化操作流程。

示例:花语查询

不使用链的实现

  1. 构建提示模板。
  2. 单独调用语言模型处理提示。
  3. 输出结果。
from langchain import PromptTemplate, OpenAI

# 第一步:创建提示模板
template = "{flower}的花语是?"
prompt_template = PromptTemplate.from_template(template)
prompt = prompt_template.format(flower="玫瑰")

# 第二步:创建模型实例并调用
model = OpenAI(temperature=0)
result = model(prompt)

print(result)

使用LLMChain的实现: 将提示模板和模型调用整合到一个链中,简化代码结构。

from langchain import PromptTemplate, OpenAI, LLMChain

template = "{flower}的花语是?"
llm = OpenAI(temperature=0)
llm_chain = LLMChain(llm=llm, prompt=PromptTemplate.from_template(template))

result = llm_chain("玫瑰")
print(result)

输出示例

{'flower': '玫瑰', 'text': '\n\n爱情、浪漫、美丽、永恒、誓言、坚贞不渝。'}

3. 链的多种调用方式

LangChain提供了多种调用链的方法,便于应对不同的输入场景和需求:

3.1. 直接调用

调用链对象即可触发其__call__方法。

llm_chain("玫瑰")

3.2. 使用run方法

功能与直接调用相同。

llm_chain.run("玫瑰")

3.3. 使用predict方法

通过关键字参数传递输入变量。

result = llm_chain.predict(flower="玫瑰")

3.4. 使用apply方法

一次处理多个输入,将输入以列表形式传入。

input_list = [
    {"flower": "玫瑰", "season": "夏季"},
    {"flower": "百合", "season": "春季"},
]
result = llm_chain.apply(input_list)

3.5. 使用generate方法

返回包含更多细节的结果(如模型信息、生成过程等)。

result = llm_chain.generate(input_list)

4. 顺序链:SequentialChain

SequentialChain是LangChain提供的高级链功能,支持将多个链组合成一个按顺序运行的链条。

案例:鲜花推文生成

目标:生成一篇鲜花推文,包括三步逻辑:

  1. 鲜花介绍:生成鲜花的知识性描述。
  2. 鲜花评论:根据介绍生成评论。
  3. 社交媒体文案:结合介绍和评论生成一篇推文。

实现步骤

1. 导入依赖

from langchain.llms import OpenAI
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain.chains import SequentialChain

2. 定义子链(LLMChain)

  • 子链1:鲜花介绍
template = """
你是一个植物学家。给定花的名称和类型,你需要为这种花写一个200字左右的介绍。

花名: {name}
颜色: {color}
植物学家: 这是关于上述花的介绍:"""
prompt_template = PromptTemplate(input_variables=["name", "color"], template=template)
introduction_chain = LLMChain(llm=OpenAI(temperature=0.7), prompt=prompt_template, output_key="introduction")
  • 子链2:鲜花评论
template = """
你是一位鲜花评论家。给定一种花的介绍,你需要为这种花写一篇200字左右的评论。

鲜花介绍:
{introduction}
花评人对上述花的评论:"""
prompt_template = PromptTemplate(input_variables=["introduction"], template=template)
review_chain = LLMChain(llm=OpenAI(temperature=0.7), prompt=prompt_template, output_key="review")
  • 子链3:社交媒体文案
template = """
你是一家花店的社交媒体经理。给定一种花的介绍和评论,你需要为这种花写一篇社交媒体的帖子,300字左右。

鲜花介绍:
{introduction}
花评人对上述花的评论:
{review}

社交媒体帖子:
"""
prompt_template = PromptTemplate(input_variables=["introduction", "review"], template=template)
social_post_chain = LLMChain(llm=OpenAI(temperature=0.7), prompt=prompt_template, output_key="social_post_text")

3. 定义顺序链: 将子链按顺序串联成一个完整的SequentialChain。

overall_chain = SequentialChain(
    chains=[introduction_chain, review_chain, social_post_chain],
    input_variables=["name", "color"],
    output_variables=["introduction", "review", "social_post_text"],
    verbose=True
)

4. 执行顺序链

result = overall_chain({"name": "玫瑰", "color": "黑色"})
print(result)

输出示例

{
  'introduction': '...',
  'review': '...',
  'social_post_text': '...'
}

5. 什么是RouterChain与MultiPromptChain

  1. RouterChain(路由链)

    • 用途:通过路由机制,根据用户输入动态选择最适合的处理链。
    • 功能:
      • 动态判断输入类型。
      • 根据输入选择适当的目标链处理问题。
      • 可扩展逻辑:允许添加更多处理链,实现复杂业务分发。
  2. MultiPromptChain(多路选择链)

    • 用途:整合RouterChain、目标链和默认链,动态路由输入并处理。
    • 特点:
      • 支持多种提示模板和目标链。
      • 提供默认处理链作为兜底方案,确保输入不会被遗漏。
    • 工作机制:
      1. 输入传递到RouterChain进行分析。
      2. RouterChain决定目标链或默认链。
      3. 最终链根据模板和输入生成响应。

6. 任务场景:鲜花智能客服系统

  • 目标:根据客户问题自动分配处理链。
  • 任务类型:
    1. 鲜花养护问题:如如何浇水、施肥等。
    2. 鲜花装饰问题:如如何搭配花朵、场地布置等。
  • 路由规则:
    • 若问题为鲜花养护,选择“鲜花养护链”。
    • 若问题为鲜花装饰,选择“鲜花装饰链”。
    • 若问题无法匹配,默认转入“通用处理链”。

7. 实现步骤

7.1 构建处理模板

根据问题场景,分别构建两个处理模板。

# 构建两个场景的模板
flower_care_template = """你是一个经验丰富的园丁,擅长解答关于养花育花的问题。
下面是需要你来回答的问题:
{input}"""

flower_deco_template = """你是一位网红插花大师,擅长解答关于鲜花装饰的问题。
下面是需要你来回答的问题:
{input}"""

# 提示信息列表
prompt_infos = [
    {"key": "flower_care", "description": "适合回答关于鲜花护理的问题", "template": flower_care_template},
    {"key": "flower_decoration", "description": "适合回答关于鲜花装饰的问题", "template": flower_deco_template},
]

7.2 初始化语言模型

from langchain.llms import OpenAI
import os

os.environ["OPENAI_API_KEY"] = '你的OpenAI Key'
llm = OpenAI()

7.3 构建目标链

针对每种问题类型,构建对应的目标链(LLMChain),用于处理该类型问题。

from langchain.chains.llm import LLMChain
from langchain.prompts import PromptTemplate

# 构建目标链映射
chain_map = {}
for info in prompt_infos:
    prompt = PromptTemplate(template=info["template"], input_variables=["input"])
    chain = LLMChain(llm=llm, prompt=prompt, verbose=True)
    chain_map[info["key"]] = chain

8. 构建路由链

8.1 路由模板

路由模板用于指导模型根据输入选择最适合的目标链。

from langchain.chains.router.llm_router import LLMRouterChain, RouterOutputParser
from langchain.chains.router.multi_prompt_prompt import MULTI_PROMPT_ROUTER_TEMPLATE as RouterTemplate

# 构建路由模板
destinations = [f"{p['key']}: {p['description']}" for p in prompt_infos]
router_template = RouterTemplate.format(destinations="\n".join(destinations))
router_prompt = PromptTemplate(
    template=router_template,
    input_variables=["input"],
    output_parser=RouterOutputParser(),
)

# 构建路由链
router_chain = LLMRouterChain.from_llm(llm, router_prompt, verbose=True)

8.2 路由模板解析

路由模板的作用:

  1. 列出所有候选提示及其适用范围。
  2. 引导语言模型根据输入选择合适的目标链。
  3. 若输入不匹配任何提示,返回默认链。

路由模板示例

<< CANDIDATE PROMPTS >>
flower_care: 适合回答关于鲜花护理的问题
flower_decoration: 适合回答关于鲜花装饰的问题

<< INPUT >>
如何为玫瑰浇水?

<< OUTPUT >>
{
    "destination": "flower_care",
    "next_inputs": "如何为玫瑰浇水?"
}

9. 构建默认链

用于处理路由链未匹配的输入。

from langchain.chains import ConversationChain

default_chain = ConversationChain(llm=llm, output_key="text", verbose=True)

10. 构建MultiPromptChain

将RouterChain、目标链和默认链整合为完整的路由系统。

from langchain.chains.router import MultiPromptChain

# 构建MultiPromptChain
chain = MultiPromptChain(
    router_chain=router_chain,
    destination_chains=chain_map,
    default_chain=default_chain,
    verbose=True
)

11. 测试路由链

通过输入不同问题,验证路由系统的效果。

测试A:鲜花护理问题

print(chain.run("如何为玫瑰浇水?"))

输出

目标链:flower_care
回答:玫瑰需要适量浇水,避免积水,保持土壤湿润。

测试B:鲜花装饰问题

print(chain.run("如何为婚礼场地装饰花朵?"))

输出

目标链:flower_decoration
回答:婚礼场地装饰可以选择白色和粉色花卉,搭配绿植增添自然气息。

测试C:非鲜花问题

print(chain.run("如何考入哈佛大学?"))

输出

目标链:DEFAULT
回答:这个问题与鲜花无关,我建议你咨询教育顾问。

12. 总结

核心功能

  1. LLMChain
    • 模块化与封装性:链在LangChain中提供了强大的模块化能力,使复杂任务的实现更加直观。
    • 灵活调用方式:支持单次调用、多次批量调用以及带更多信息的调用(如generate)。
  2. SequentialChain
    • 组合链功能:通过SequentialChain可以轻松实现复杂的多步骤逻辑。
  3. RouterChain
    • 根据用户输入动态选择目标链。
    • 支持扩展多种场景处理。
  4. MultiPromptChain
    • 整合RouterChain、目标链和默认链,实现完整路由系统。
    • 提供兜底处理机制,避免遗漏问题。

优势

  1. 动态决策:支持复杂问题分类与分发。
  2. 模块化设计:链路清晰,易于维护和扩展。
  3. 灵活性:可根据业务需求增加场景处理链。

适用场景

  • 智能客服系统(如根据客户问题分配处理链)。
  • 动态推荐系统(如电商推荐、教育咨询)。
  • 自动化内容生成(如社交媒体运营、行业报告撰写)。

通过LangChain的链机制,我们可以构建出更加高效、清晰、可扩展的生成任务,为AI应用开发提供强大支持。通过RouterChain和MultiPromptChain,我们可以轻松实现复杂问题的自动化决策和分类处理,为智能客服、推荐系统等场景提供了强大的解决方案。