【LangChain系列4】【Chain模块详解】


前言

LangChain给自身的定位是:用于开发由大语言模型支持的应用程序的框架。它的做法是:通过提供标准化且丰富的模块抽象,构建大语言模型的输入输出规范,利用其核心概念chains,灵活地连接整个应用开发流程。 这里是LangChain系列的第四篇,主要介绍LangChain的Chain模块。

一、LangChain

1-1、介绍

LangChain是一个框架,用于开发由大型语言模型(LLM)驱动的应用程序。

LangChain 简化了 LLM 应用程序生命周期的每个阶段:

  • 开发:使用LangChain的开源构建块和组件构建应用程序。使用第三方集成和模板开始运行。
  • 生产化:使用 LangSmith 检查、监控和评估您的链条,以便您可以自信地持续优化和部署。
  • 部署:使用 LangServe 将任何链转换为 API。

总结: LangChain是一个用于开发由LLM支持的应用程序的框架,通过提供标准化且丰富的模块抽象,构建LLM的输入输出规范,主要是利用其核心概念chains,可以灵活地链接整个应用开发流程。(即,其中的每个模块抽象,都是源于对大模型的深入理解和实践经验,由许多开发者提供出来的标准化流程和解决方案的抽象,再通过灵活的模块化组合,才得到了langchain)

在这里插入图片描述

1-2、LangChain抽象出来的核心模块

想象一下,如果要组织一个AI应用,开发者一般需要?

  • 提示词模板的构建,不仅仅只包含用户输入!
  • 模型调用与返回,参数设置,返回内容的格式化输出。
  • 知识库查询,这里会包含文档加载,切割,以及转化为词嵌入(Embedding)向量。
  • 其他第三方工具调用,一般包含天气查询、Google搜索、一些自定义的接口能力调用。
  • 记忆获取,每一个对话都有上下文,在开启对话之前总得获取到之前的上下文吧?

由上边的内容,引出LangChain抽象的一些核心模块:

LangChain通过模块化的方式去高级抽象LLM在不同场景下的能力,其中LangChain抽象出的最重要的核心模块如下:

  • Model I/O :标准化各个大模型的输入和输出,包含输入模版,模型本身和格式化输出;
  • Retrieval :检索外部数据,然后在执行生成步骤时将其传递到 LLM,包括文档加载、切割、Embedding等;
  • Chains :链条,LangChain框架中最重要的模块,链接多个模块协同构建应用,是实际运作很多功能的高级抽象;
  • Memory : 记忆模块,以各种方式构建历史信息,维护有关实体及其关系的信息;
  • Agents : 目前最热门的Agents开发实践,未来能够真正实现通用人工智能的落地方案;
  • Callbacks :回调系统,允许连接到 LLM 应用程序的各个阶段。用于日志记录、监控、流传输和其他任务;

1-3、特点

LangChain的特点如下:

  • 大语言模型(llm): LangChain为自然语言处理提供了不同类型的模型,这些模型可用于处理非结构化文本数据,并且可以基于用户的查询检索信息

  • PromptTemplates: 这个特征使开发人员能够使用多个组件为他们的模型构造输入提示。在查询时,开发人员可以使用PromptTemplates为用户查询构造提示模板,之后模板会传递到大模型进行进一步的处理。

  • :在LangChain中,链是一系列模型,它们被连接在一起以完成一个特定的目标。聊天机器人应用程序的链实例可能涉及使用LLM来理解用户输入,使用内存组件来存储过去的交互,以及使用决策组件来创建相关响应。

  • agent: LangChain中的agent与用户输入进行交互,并使用不同的模型进行处理。Agent决定采取何种行动以及以何种顺序来执行行动。例如,CSV Agent可用于从CSV文件加载数据并执行查询,而Pandas Agent可用于从Pandas数据帧加载数据并处理用户查询。可以将代理链接在一起以构建更复杂的应用程序。

在这里插入图片描述

1-4、langchain解决的一些行业痛点

在使用大模型的过程中,一些行业痛点:

  • 大模型的使用规范以及基于大模型的开发范式不尽相同,当使用一个新模型时,我们往往需要学习新的模型规范。
  • 大模型知识更新的滞后性
  • 大模型的外部API调用能力
  • 大模型输出的不稳定问题,如何稳定输出?
  • 大模型与私有化数据的连接方式?

1-5、安装

pip install langchain

二、Chain模块

2-1、介绍

LangChain的chain模块是其框架中用于构建智能对话和任务式应用的核心组件之一,主要负责流程控制和数据传递。以下是chain模块的一些详细介绍:

  • 流程控制:Chains是LangChain中的核心流程控制单元,它们负责串联不同的组件和步骤,定义应用程序的执行逻辑。
  • 数据传递:Chains可以传递上下文和数据,使得不同的模块之间能够共享信息。
  • 组合与嵌套:Chains支持嵌套和组合,可以构建复杂的流程,例如顺序执行、条件判断和循环等。
  • 可重用性:Chains可以被定义为可重用的模块,在不同的应用场景中复用。
  • 灵活性:LangChain支持多种类型的Chains,如简单链、索引链、对话链等,以满足不同的需求。

链的创建与组合:

  • 单一链:开发者可以创建一个包含特定功能的单一链,例如文本预处理、模型推理等。
  • 自定义链:利用内置的基础链类,开发者可以自定义链的输入、输出和处理逻辑。
  • 顺序组合:将多个链按照执行顺序串联起来,前一个链的输出作为下一个链的输入。
  • 并行组合:同时执行多个链,将它们的输出合并或选择性地使用。
  • 嵌套链:在一个链的内部调用另一个链,实现更复杂的流程控制

核心链类型:

  • LLMChain:与大型语言模型(LLMs)直接交互的链,用于生成和理解自然语言
  • SimpleSequentialChain:一个简单的顺序执行链,用于按顺序执行一系列步骤
  • SequentialChain:一个顺序链,可以包含多个步骤,每个步骤可以是另一个链
  • RouterChain:用于智能路由决策,根据输入决定执行哪个链
  • TransformChain:用于数据处理,可以对输入数据进行转换或处理

通过这些链的组合和嵌套,LangChain框架能够实现复杂的自然语言处理应用程序,提供高度的扩展性和可维护性

2-2、LLMChain

LLMChain 是 LangChain 中最简单的链,作为其他复杂 Chains 和 Agents 的内部调用,被广泛应用。一个LLMChain由PromptTemplate和语言模型(LLM or Chat Model)组成。它使用直接传入(或 memory 提供)的 key-value 来规范化生成 Prompt Template(提示模板),并将生成的 prompt (格式化后的字符串)传递给大模型,并返回大模型输出。

案例如下:

from langchain_community.chat_models import ChatZhipuAI
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
import os

os.environ["ZHIPUAI_API_KEY"] = ""
chat = ChatZhipuAI(
    model="glm-4",
    temperature=0.5,
)

prompt = PromptTemplate(
    input_variables=["product"],
    template="给制造{product}的有限公司取10个好名字,并给出完整的公司名称",
)

chain = LLMChain(llm=chat, prompt=prompt)
print(chain.invoke({
    'product': "性能卓越的GPU"
    }))

输出:
在这里插入图片描述

设置chain.verbose =True可以给出中间推理过程。
在这里插入图片描述

2-3、Sequential Chain(顺序链)

SequentialChain是一种链(Chain)类型,用于定义一系列步骤或组件,这些步骤或组件将按顺序执行。SequentialChain的核心功能是将多个处理步骤串联起来,使得每一步的输出成为下一步的输入,从而形成一个有序的执行流程。顺序链(Sequential Chain )允许用户连接多个链并将它们组合成执行特定场景的流水线(Pipeline)。有两种类型的顺序链:

  • SimpleSequentialChain:最简单形式的顺序链,每个步骤都具有单一输入/输出,并且一个步骤的输出是下一个步骤的输入。
  • SequentialChain:更通用形式的顺序链,允许多个输入/输出。

SimpleSequentialChain-Demo: 包含参数chains以及参数verbose

  • chains:列表,包含了要顺序执行的链。前边链的输出作为后边链的输入。
  • verbose:用于控制链的执行是否应该输出详细的日志信息。当设置为 True 时,链在执行过程中会打印出更多的信息,这有助于调试和监控链的执行状态。
from langchain.llms import OpenAI
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate

os.environ["ZHIPUAI_API_KEY"] = ""
llm = ChatZhipuAI(
    model="glm-4",
    temperature=0.5,
)

template = """You are a playwright. Given the title of play, it is your job to write a synopsis for that title.

Title: {title}
Playwright: This is a synopsis for the above play:"""
prompt_template = PromptTemplate(input_variables=["title"], template=template)
synopsis_chain = LLMChain(llm=llm, prompt=prompt_template)


template = """You are a play critic from the New York Times. Given the synopsis of play, it is your job to write a review for that play.

Play Synopsis:
{synopsis}
Review from a New York Times play critic of the above play:"""
prompt_template = PromptTemplate(input_variables=["synopsis"], template=template)
review_chain = LLMChain(llm=llm, prompt=prompt_template)


from langchain.chains import SimpleSequentialChain
overall_chain = SimpleSequentialChain(chains=[synopsis_chain, review_chain], verbose=True)

review = overall_chain.run("Tragedy at sunset on the beach")

输出:
在这里插入图片描述
在这里插入图片描述

SequentialChain-Demo: 通用顺序链,包含多个输入以及输出。参数包括:chains、input_variables、output_variables、verbose

  • chains: 这是一个列表,包含了要顺序执行的子链。在这个例子中,synopsis_chain 和 review_chain 被包含在列表中,意味着这两个链将按顺序执行。
  • input_variables: 这是一个列表,定义了这个链的输入变量。在这个例子中,SequentialChain 期望接收两个输入变量:era 和 title。这些变量将被传递给链中的第一个子链,通常是用于初始化或配置子链的参数。
  • output_variables: 这是一个列表,定义了这个链的输出变量。在这个例子中,SequentialChain 将返回两个输出变量:synopsis 和 review。这些输出变量分别对应于 synopsis_chain 和 review_chain 的输出,表示这个链的最终结果。
  • verbose: 这是一个布尔值参数,用于控制链的执行是否应该输出详细的日志信息。当设置为 True 时,链在执行过程中会打印出更多的信息,这有助于调试和监控链的执行状态。
from langchain.llms import OpenAI
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate

os.environ["ZHIPUAI_API_KEY"] = ""
llm = ChatZhipuAI(
    model="glm-4",
    temperature=0.5,
)
template = """You are a playwright. Given the title of play and the era it is set in, it is your job to write a synopsis for that title.

Title: {title}
Era: {era}
Playwright: This is a synopsis for the above play:"""
prompt_template = PromptTemplate(input_variables=["title", 'era'], template=template)
synopsis_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="synopsis")

template = """You are a play critic from the New York Times. Given the synopsis of play, it is your job to write a review for that play.

Play Synopsis:
{synopsis}
Review from a New York Times play critic of the above play:"""
prompt_template = PromptTemplate(input_variables=["synopsis"], template=template)
review_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="review")

from langchain.chains import SequentialChain
overall_chain = SequentialChain(
    chains=[synopsis_chain, review_chain],
    input_variables=["era", "title"],
    # Here we return multiple variables
    output_variables=["synopsis", "review"],
    verbose=True)

overall_chain({"title":"Tragedy at sunset on the beach", "era": "Victorian England"})

输出:
在这里插入图片描述
在这里插入图片描述
SequentialChain与SimpleSequentialChain相比,重要的是定义好中间的输入变量以及输出变量(input_variables、output_variables),方便后续输出

2-4、Router Chain

RouterChain: 是LangChain框架中的一个组件,用于构建可以根据输入动态选择下一个执行链条的系统。它主要包含两个部分:RouterChain本身和destination_chains(目标链)。RouterChain负责选择下一个要调用的链条,而destination_chains是RouterChain可以路由到的链条集合

以下是RouterChain的一些关键特点和用途:

  • 动态路由:RouterChain可以根据用户的输入动态选择最合适的处理链条来执行任务。这种动态选择机制使得系统能够更加灵活地处理不同类型的请求。
  • 多链条集成:RouterChain可以与多个destination_chains(目标链)一起工作,每个目标链都是一个专门处理特定类型任务的链条。例如,在一个问答系统中,RouterChain可以根据问题的主题将问题路由到不同的专家链条,如物理、数学等。
  • 灵活性和扩展性:通过RouterChain,开发者可以轻松地添加或修改destination_chains,从而扩展系统的功能。这种设计使得系统能够适应不断变化的需求和新的应用场景。
  • LLMRouterChain:LangChain提供了LLMRouterChain,这是一种特殊的RouterChain,它使用大型语言模型(LLM)来确定如何路由输入。通过Prompt的形式,LLMRouterChain可以让大语言模型根据用户的输入来选择最合适的destination_chain。
  • MultiPromptChain:这是一种特殊的RouterChain,它可以根据给定的问题选择最相关的提示,并使用该提示回答问题。MultiPromptChain包含router_chain和destination_chains,以及一个默认链default_chain,用于处理无法路由到特定destination_chain的情况。
  • EmbeddingRouterChain:另一种RouterChain,它通过向量搜索的方式,将用户输入映射到最相关的destination_chain。

1、构建目标链 destination_chains: 即RouterChain可以路由到的链条集合。这里创建了一个默认的对话链ConversationChain ,在没有合适chain的情况下,会选择使用默认对话链。

from langchain.chains.router import MultiPromptChain
from langchain.llms import OpenAI
from langchain.chains import ConversationChain
from langchain.chains.llm import LLMChain
from langchain.prompts import PromptTemplate
from langchain_community.chat_models import ChatZhipuAI

physics_template = """You are a very smart physics professor. 
You are great at answering questions about physics in a concise and easy to understand manner. 
When you don't know the answer to a question you admit that you don't know.

Here is a question:
{input}"""

math_template = """You are a very good mathematician. You are great at answering math questions. 
You are so good because you are able to break down hard problems into their component parts, 
answer the component parts, and then put them together to answer the broader question.

Here is a question:
{input}"""

# 主要构建物理、数学两条链,所以这里先构建了相关信息,用于下边构建目标链。
prompt_infos = [
    {
        "name": "physics",
        "description": "Good for answering questions about physics",
        "prompt_template": physics_template,
    },
    {
        "name": "math",
        "description": "Good for answering math questions",
        "prompt_template": math_template,
    },
]

os.environ["ZHIPUAI_API_KEY"] = ""
llm = ChatZhipuAI(
    model="glm-4",
    temperature=0.5,
)

# 创建一个空的目标链字典,用于存放根据prompt_infos生成的LLMChain。
destination_chains = {}

# 遍历prompt_infos列表,为每个信息创建一个LLMChain。
for p_info in prompt_infos:
    name = p_info["name"]  # 提取名称
    prompt_template = p_info["prompt_template"]  # 提取模板
    # 创建PromptTemplate对象
    prompt = PromptTemplate(template=prompt_template, input_variables=["input"])
    # 使用上述模板和llm对象创建LLMChain对象
    chain = LLMChain(llm=llm, prompt=prompt)
    # 将新创建的chain对象添加到destination_chains字典中
    destination_chains[name] = chain

# 创建一个默认的ConversationChain
default_chain = ConversationChain(llm=llm, output_key="text")

输出:
在这里插入图片描述
2、使用LLMRouterChain实现条件判断:

  • destinations_str: 将destinations列表中的所有元素用换行符连接成一个字符串,用于构建路由提示模板。
  • RouterOutputParser:用于解析路由链的输出。
  • MULTI_PROMPT_ROUTER_TEMPLATE:一个预定义的用于构建路由提示的模板。
from langchain.chains.router.llm_router import LLMRouterChain, RouterOutputParser
from langchain.chains.router.multi_prompt_prompt import MULTI_PROMPT_ROUTER_TEMPLATE

destinations = [f"{p['name']}: {p['description']}" for p in prompt_infos]
destinations_str = "\n".join(destinations)
router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(destinations=destinations_str)
router_prompt = PromptTemplate(
    template=router_template,
    input_variables=["input"],
    output_parser=RouterOutputParser(),
)
router_chain = LLMRouterChain.from_llm(llm, router_prompt)

chain = MultiPromptChain(
    router_chain=router_chain,
    destination_chains=destination_chains,
    default_chain=default_chain,
    verbose=True,
)

print(chain.run("What is black body radiation?"))

输出:
在这里插入图片描述

总结:

1、 用户输入一个问题。
2、 router_chain使用router_prompt处理用户的输入,并根据输出决定将问题路由到哪个destination_chain。
3、 根据router_chain的路由结果,MultiPromptChain将问题发送到相应的destination_chain进行处理。
4、 destination_chain处理问题并生成答案。
5、 如果router_chain无法确定合适的destination_chain,问题将被发送到default_chain进行处理。

这个系统允许根据用户的输入动态选择最合适的处理链,提高了系统的灵活性和准确性。同时,verbose参数可以帮助开发者调试和监控系统的执行过程。

2-4、Transform Chain

Transform Chain: 主要用于对数据进行转换处理,然后再将转换后的结果输出给后续的处理链。

参考文章:

langchain_community.utilities.sql_database.SQLDatabase
LangChain 🦜️🔗 中文网,跟着LangChain一起学LLM/GPT开发
LangChain官网
Rebuff: 防止提示词注入检测器

未完成:
Build a Question/Answering system over SQL data
langchain101 AI应用开发指南

总结

今天下大雨🤕

<think>好的,用户想了解langchain4j的执行流程。我需要先回忆一下langchain4j的基本结构和核心组件。记得langchain4j是一个Java库,用于集成大型语言模型(LLM)到应用中,类似于Python的LangChain。 首先,执行流程可能从创建提示模板开始。用户需要定义输入变量,比如问题或指令,然后通过模板生成具体的提示内容。这部分应该涉及到PromptTemplate类,用户可能需要从langchain_core.prompts导入,如引用[2]提到的,避免使用旧版本的导入方式。 接下来是模型调用。用户需要配置LLM的访问参数,比如API密钥、模型类型等。Langchain4j可能提供了不同的模型适配器,比如OpenAI或Cohere,用户需要选择合适的模型并实例化对应的类。例如,使用OpenAI的模型时,需要设置API key和模型名称。 然后是处理模型输出。生成的响应可能需要后处理,比如解析成特定格式或提取关键信息。这部分可能需要自定义工具或使用内置的工具类,比如OutputParser。此外,链式调用(Chain)可能涉及多个步骤的组合,比如先检索相关信息,再生成回答,最后验证结果。 还需要考虑内存管理,用于在多次调用之间保持上下文。例如,在对话应用中,保存历史消息以便模型理解当前对话的背景。内存组件可能包括ConversationMemory类,用于存储和检索之前的交互信息。 另外,用户提到的引用[3]提到Elasticsearch与LangChain的集成,可能涉及到检索增强生成(RAG)流程。在langchain4j中,可能通过检索文档库获取相关信息,再结合LLM生成回答,这涉及到检索器和生成器的协同工作。 最后,异常处理和性能优化也是执行流程的一部分。例如,引用[1]提到的EMT4J可能用于监控和调优Java应用的性能,确保langchain4j的高效运行。同时,正确的导入和依赖管理,如引用[2]的提示,能避免运行时错误。 总结执行流程的步骤大致是:初始化组件(模型、提示模板、内存等),构建处理链,执行链并处理输入,调用模型,处理输出,维护上下文。需要详细解释每个步骤,并可能结合代码示例说明流程。</think>### LangChain4j 执行流程详解 LangChain4j 是一个用于集成大型语言模型(LLM)到 Java 应用的框架,其核心目标是通过模块化设计简化复杂任务的构建。以下是其典型执行流程的分步说明: --- #### **1. 初始化组件** - **提示模板 (Prompt Template)** 定义输入变量的占位符模板,例如生成问答或指令。 ```java PromptTemplate promptTemplate = new PromptTemplate("请回答以下问题:{{question}}"); ``` 需确保导入正确的类(如引用[2]提示,使用 `langchain_core.prompts.PromptTemplate`)[^2]。 - **模型配置** 选择并配置 LLM 服务(如 OpenAI、Cohere 或本地模型),设置 API 密钥、超时等参数。 ```java OpenAiChatModel model = OpenAiChatModel.builder() .apiKey("YOUR_API_KEY") .modelName("gpt-3.5-turbo") .build(); ``` - **内存管理 (Memory)** 用于存储对话历史或上下文信息,例如 `ConversationMemory`。 ```java ConversationMemory memory = new ConversationMemory(); memory.add("用户: 你好!"); ``` --- #### **2. 构建处理链 (Chain)** LangChain4j 通过链式调用组合多个步骤,例如: - **检索增强生成 (RAG)** 结合检索器(如 Elasticsearch)和生成模型(如引用[3]提到的集成场景)[^3]。 ```java Chain chain = Chain.builder() .retriever(elasticsearchRetriever) // 从文档库检索信息 .promptTemplate(promptTemplate) // 生成提示 .llm(model) // 调用模型 .build(); ``` --- #### **3. 执行流程** - **输入处理** 将用户输入绑定到提示模板,并注入上下文(如内存中的历史对话)。 ```java Map<String, Object> variables = new HashMap<>(); variables.put("question", "如何优化快速排序?"); String prompt = promptTemplate.format(variables); ``` - **模型调用** 发送提示至 LLM 并获取原始响应。 ```java String rawResponse = model.generate(prompt); ``` - **输出后处理** 解析模型响应,可能包括 JSON 解析、关键词提取或格式化。 ```java OutputParser parser = new JsonParser(); String answer = parser.parse(rawResponse); ``` --- #### **4. 上下文维护** - **更新内存** 将当前输入和输出保存至内存,供后续交互使用。 ```java memory.add("AI: " + answer); ``` --- #### **5. 异常与性能优化** - **错误处理** 捕获 API 调用异常(如网络超时),并设计重试逻辑。 - **性能监控** 可借助 EMT4J 等工具(如引用[1])分析链式调用的性能瓶颈[^1]。 --- ### 示例代码:简单问答流程 ```java // 初始化模型和模板 OpenAiChatModel model = OpenAiChatModel.builder().apiKey("sk-xxx").build(); PromptTemplate template = new PromptTemplate("问题:{{query}}"); // 执行链 String query = "快速排序的时间复杂度是多少?"; String prompt = template.format(Map.of("query", query)); String response = model.generate(prompt); System.out.println("答案:" + response); // 输出: O(n log n) 平均情况 ``` ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ㄣ知冷煖★

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值