LangChain 核心模块学习:Chains

对于简单的大模型应用,单独使用语言模型(LLMs)是可以的。

但更复杂的大模型应用需要将 LLMsChat Models 链接在一起。 要么彼此链接,要么与其他组件链接。

LangChain 为这种“链式”应用程序提供了 Chain 接口。

LangChain 以通用方式定义了 Chain,它是对组件进行调用序列的集合,其中可以包含其他链。

Chain Class 基类

类继承关系:

Chain --> <name>Chain  # Examples: LLMChain, MapReduceChain, RouterChain
# 定义一个名为Chain的基础类
class Chain(Serializable, Runnable[Dict[str, Any], Dict[str, Any]], ABC):
"""为创建结构化的组件调用序列的抽象基类。 链应该用来编码对组件的一系列调用,如模型、文档检索器、其他链等,并为此序列提供一个简单的接口。 Chain接口使创建应用程序变得容易,这些应用程序是:
- 有状态的:给任何Chain添加Memory可以使它具有状态,
- 可观察的:向Chain传递Callbacks来执行额外的功能,如记录,这在主要的组件调用序列之外,
- 可组合的:Chain API足够灵活,可以轻松地将Chains与其他组件结合起来,包括其他Chains。 链公开的主要方法是:
- `__call__`:链是可以调用的。`__call__`方法是执行Chain的主要方式。它将输入作为一个字典接收,并返回一个字典输出。
- `run`:一个方便的方法,它以args/kwargs的形式接收输入,并将输出作为字符串或对象返回。这种方法只能用于一部分链,不能像`__call__`那样返回丰富的输出。
""" # 调用链
def invoke(
self, input: Dict[str, Any], config: Optional[runnableConfig] = None
) -> Dict[str, Any]:
"""传统调用方法。"""
return self(input, **(config or {})) # 链的记忆,保存状态和变量
memory: Optional[BaseMemory] = None
"""可选的内存对象,默认为None。
内存是一个在每个链的开始和结束时被调用的类。在开始时,内存加载变量并在链中传递它们。在结束时,它保存任何返回的变量。
有许多不同类型的内存,请查看内存文档以获取完整的目录。""" # 回调,可能用于链的某些操作或事件。
callbacks: Callbacks = Field(default=None, exclude=True)
"""可选的回调处理程序列表(或回调管理器)。默认为None。
在对链的调用的生命周期中,从on_chain_start开始,到on_chain_end或on_chain_error结束,都会调用回调处理程序。
每个自定义链可以选择调用额外的回调方法,详细信息请参见Callback文档。""" # 是否详细输出模式
verbose: bool = Field(default_factory=_get_verbosity)
"""是否以详细模式运行。在详细模式下,一些中间日志将打印到控制台。默认值为`langchain.verbose`。""" # 与链关联的标签
tags: Optional[List[str]] = None
"""与链关联的可选标签列表,默认为None。
这些标签将与对这个链的每次调用关联起来,并作为参数传递给在`callbacks`中定义的处理程序。
你可以使用这些来例如识别链的特定实例与其用例。""" # 与链关联的元数据
metadata: Optional[Dict[str, Any]] = None
"""与链关联的可选元数据,默认为None。
这些元数据将与对这个链的每次调用关联起来,并作为参数传递给在`callbacks`中定义的处理程序。
你可以使用这些来例如识别链的特定实例与其用例。"""

LLMChain

LLMChain 是 LangChain 中最简单的链,作为其他复杂 Chains 和 Agents 的内部调用,被广泛应用。

一个LLMChain由PromptTemplate和语言模型(LLM or Chat Model)组成。它使用直接传入(或 memory 提供)的 key-value 来规范化生成 Prompt Template(提示模板),并将生成的 prompt (格式化后的字符串)传递给大模型,并返回大模型输出。

(图片)

from langchain_openai import OpenAI
from langchain.prompts import PromptTemplate llm = OpenAI(model_name="gpt-3.5-turbo-instruct", temperature=0.9, max_tokens=500) prompt = PromptTemplate(
input_variables=["product"],
template="给制造{product}的有限公司取10个好名字,并给出完整的公司名称",
) from langchain.chains import LLMChain chain = LLMChain(llm=llm, prompt=prompt)
print(chain.invoke({
'product': "性能卓越的GPU"
}))

输出:

{'product': '性能卓越的GPU', 'text': '\n\n1. 星火卓越科技有限公司\n2. 利益达太空科技有限公司\n3. 未来视界智能科技有限公司\n4. 强力算力科技有限公司\n5. 极速计算科技有限公司\n6. 无限创想智能科技有限公司\n7. 高能创新科技有限公司\n8. 天马行空科技有限公司\n9. 极致计算科技有限公司\n10. 全能加速科技有限公司'}

Sequential Chain

串联式调用语言模型(将一个调用的输出作为另一个调用的输入)。

顺序链(Sequential Chain )允许用户连接多个链并将它们组合成执行特定场景的流水线(Pipeline)。有两种类型的顺序链:

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

使用 SimpleSequentialChain 实现戏剧摘要和评论(单输入/单输出)

(图片)

# 这是一个 LLMChain,用于根据剧目的标题撰写简介。

llm = OpenAI(temperature=0.7, max_tokens=1000)

template = """你是一位剧作家。根据戏剧的标题,你的任务是为该标题写一个简介。

标题:{title}
剧作家:以下是对上述戏剧的简介:""" prompt_template = PromptTemplate(input_variables=["title"], template=template)
synopsis_chain = LLMChain(llm=llm, prompt=prompt_template)
# 这是一个LLMChain,用于根据剧情简介撰写一篇戏剧评论。
# llm = OpenAI(temperature=0.7, max_tokens=1000)
template = """你是《纽约时报》的戏剧评论家。根据剧情简介,你的工作是为该剧撰写一篇评论。 剧情简介:
{synopsis} 以下是来自《纽约时报》戏剧评论家对上述剧目的评论:""" prompt_template = PromptTemplate(input_variables=["synopsis"], template=template)
review_chain = LLMChain(llm=llm, prompt=prompt_template)

(图片)

# 这是一个SimpleSequentialChain,按顺序运行这两个链
from langchain.chains import SimpleSequentialChain overall_chain = SimpleSequentialChain(chains=[synopsis_chain, review_chain], verbose=True)
review = overall_chain.invoke("星球大战第九季")

输出:

> Entering new SimpleSequentialChain chain...

《星球大战第九季》是一部充满惊险刺激的科幻戏剧,它延续了《星球大战》系列的传奇故事。在这一季中,我们将见证新的冒险和挑战,因为银河系再次陷入战争的深渊。反抗军和第一秩序之间的战争仍在继续,但这一次,他们将面临着更加强大的敌人。新的角色和老朋友将再次出现,与我们的英雄们一起并肩作战。随着战争的进展,我们也将见证力量和黑暗的永恒对抗,以及对自由和正义的不懈追求。在这场史诗般的战役中,我们将看到勇气、牺牲和爱的力量,同时也会思考我们对未来的选择和命运。《星球大战第九季》将带给观众无与伦比的视觉盛宴和感人心弦的故事,让我们一起来见证这一壮丽的星际冒险!

《星球大战第九季》是一部不容错过的史诗般的科幻戏剧。该剧延续了《星球大战》系列的传奇故事,将观众带入一个充满惊险和刺激的银河系。在这一季中,我们将再次与我们熟悉的英雄们一起并肩作战,同时也会见证新的挑战和冒险。

该剧不仅仅是一场视觉盛宴,更是一部让人思考的故事。通过力量和黑暗的永恒对抗,以及对自由和正义的追求,观众将被带入一个关于命运和选择的深刻思考。在这场史诗般的战役中,我们将见证勇气、牺牲和爱的力量,这些都是《星球大战》系列一直探讨的重要主题。

该剧不仅有着令人惊叹的特效和精彩的动作场面,更重要的是它成功地将这些元素与深刻的人物关系和情感表达相结合。观众将会被带入一个充满希望和感动的星际冒险,与角色们一起经历他们的成长和转变。

总的来说,《星球大战第九季》是一部充满情感和故事的出色作品,它将让观众沉浸在一个充满惊喜和挑战的星际世界。无论您是《星球大战》系列的忠实粉丝,还是对科幻题材感兴趣的观众,这部戏剧都会给您带来一场令人难忘的体验。不容错过!

> Finished chain.

Router Chain: 实现条件判断的大模型调用

这段代码构建了一个可定制的链路系统,用户可以提供不同的输入提示,并根据这些提示获取适当的响应。

主要逻辑:从prompt_infos创建多个LLMChain对象,并将它们保存在一个字典中,然后创建一个默认的ConversationChain,最后创建一个带有路由功能的MultiPromptChain

(图片)

from langchain.chains.router import MultiPromptChain
from langchain_openai import OpenAI
from langchain.chains import ConversationChain
from langchain.chains.llm import LLMChain
from langchain.prompts import PromptTemplate
physics_template = """你是一位非常聪明的物理教授。
你擅长以简洁易懂的方式回答关于物理的问题。
当你不知道某个问题的答案时,你会坦诚承认。 这是一个问题:
{input}""" math_template = """你是一位很棒的数学家。你擅长回答数学问题。
之所以如此出色,是因为你能够将难题分解成各个组成部分,
先回答这些组成部分,然后再将它们整合起来回答更广泛的问题。 这是一个问题:
{input}"""
prompt_infos = [
{
"name": "物理",
"description": "适用于回答物理问题",
"prompt_template": physics_template,
},
{
"name": "数学",
"description": "适用于回答数学问题",
"prompt_template": math_template,
},
]

llm = OpenAI(model_name="gpt-3.5-turbo-instruct")

# 创建一个空的目标链字典,用于存放根据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")

使用 LLMRouterChain 实现条件判断调用

这段代码定义了一个chain对象(LLMRouterChain),该对象首先使用router_chain来决定哪个destination_chain应该被执行,如果没有合适的目标链,则默认使用default_chain。

from langchain.chains.router.llm_router import LLMRouterChain, RouterOutputParser
from langchain.chains.router.multi_prompt_prompt import MULTI_PROMPT_ROUTER_TEMPLATE
# 从prompt_infos中提取目标信息并将其转化为字符串列表
destinations = [f"{p['name']}: {p['description']}" for p in prompt_infos]
# 使用join方法将列表转化为字符串,每个元素之间用换行符分隔
destinations_str = "\n".join(destinations)
# 根据MULTI_PROMPT_ROUTER_TEMPLATE格式化字符串和destinations_str创建路由模板
router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(destinations=destinations_str)
# 创建路由的PromptTemplate
router_prompt = PromptTemplate(
template=router_template,
input_variables=["input"],
output_parser=RouterOutputParser(),
)
# 使用上述路由模板和llm对象创建LLMRouterChain对象
router_chain = LLMRouterChain.from_llm(llm, router_prompt)

print(destinations)

输出:['物理: 适用于回答物理问题', '数学: 适用于回答数学问题']

# 创建MultiPromptChain对象,其中包含了路由链,目标链和默认链。
chain = MultiPromptChain(
router_chain=router_chain,
destination_chains=destination_chains,
default_chain=default_chain,
verbose=True,
)

print(chain.invoke("黑体辐射是什么??"))

输出:

> Entering new MultiPromptChain chain...
物理: {'input': 'What is blackbody radiation?'}
> Finished chain.
{'input': 'What is blackbody radiation?', 'text': '\n\n黑体辐射是一种物理现象,指的是由于物体内部的热运动导致的电磁辐射。简单来说,物体在受热时会发出电磁波,这些波的频率和强度取决于物体的温度。黑体辐射的特点是它的辐射频率与物体的温度无关,而只与物体的结构和性质有关。这个概念在热力学和量子力学中都有重要的应用。'}

LangChain基础篇 (02)的更多相关文章

  1. Java多线程系列--“基础篇”02之 常用的实现多线程的两种方式

    概要 本章,我们学习“常用的实现多线程的2种方式”:Thread 和 Runnable.之所以说是常用的,是因为通过还可以通过java.util.concurrent包中的线程池来实现多线程.关于线程 ...

  2. WebBug靶场基础篇 — 02

    本篇以第一人称记录这个关卡的第 1-5 关. 由于我记录的过程有点偏向于思考,所以截图截的多 = =!所以文章有点长... 下午一觉醒来,已经 4 点多了,然后开电脑,在虚拟机里,铺了铺靶场,但是毕竟 ...

  3. 【matlab 基础篇 02】基础知识一键扫盲,看完即可无障碍编程(超详细+图文并茂)

    博主快速入门matlab,系统地整理一遍,如何你和我一样是一个新手,那么此文很适合你: 本人能力有限,文中难免有错误和纰漏之处,请大佬们不吝赐教 创作不易,如果本文帮到了您: 请帮忙点个赞

  4. iOS系列 基础篇 02 StoryBoard 故事板文件

    iOS基础 02 StoryBoard 故事板文件 目录: 1. 故事板的导航特点 2. 故事板中的Scene和Segue 3. 本文最后 在上篇HelloWorld工程中有一个Main.storyb ...

  5. MySQL基础篇(02):从五个维度出发,审视表结构设计

    本文源码:GitHub·点这里 || GitEE·点这里 一.数据场景 1.表结构简介 任何工具类的东西都是为了解决某个场景下的问题,比如Redis缓存系统热点数据,ClickHouse解决海量数据的 ...

  6. Java基础篇(02):特殊的String类,和相关扩展API

    本文源码:GitHub·点这里 || GitEE·点这里 一.String类简介 1.基础简介 字符串是一个特殊的数据类型,属于引用类型.String类在Java中使用关键字final修饰,所以这个类 ...

  7. C#基础篇02

    首先:一个完整的方法是包括两部分的,代码和注释!!!! 程序的调试: 3:设置断点:  断点之前的程序已经确保正确,可是在断点后的部分可能出现错误,所以设置完断点后,直接点击启动,然后按F11逐步棸的 ...

  8. Java岗 面试考点精讲(基础篇02期)

    1. 两个对象的hashCode相同,则equals也一定为true,对吗? 不对,答案见下面的代码: @Override public int hashCode() { return 1; } 两个 ...

  9. React基础篇 - 02.JSX 简介

    JSX 简介 请观察下面的变量声明: const element = <h1>Hello, world!</h1>; 这种看起来可能有些奇怪的标签语法既不是字符串也不是HTML ...

  10. Java多线程系列 基础篇02 线程的创建和运行

    1.线程创建的方式常用有两种 1. 继承 Thread 类创建线程 2. 实现 Runnable 接口创建线程 2.Thread 和 Runnable的区别 Thread和Runnable的相同点:都 ...

随机推荐

  1. 基于Ubuntu搭建Pwn调试环境

    Pwn环境配置 本文演示使用干净的Vmware下安装的的 Ubuntu 18.04 LTS镜像 配置以下Pwn环境: OS(系统)配置 VMware Tools net-tools open-vm-t ...

  2. vscode c/c++ 和 MSYS2 环境配置记录

    vscode c/c++ 和 MSYS2 环境配置记录 网上的教程有一定错误和过时,这里收集了当前的最优配置. MinGW/MSYS2 安装 MSYS2 是一个类似于Linux的shell环境,可以在 ...

  3. LDA——线性判别分析基本推导与实验

    介绍与推导 LDA是线性判别分析的英文缩写,该方法旨在通过将多维的特征映射到一维来进行类别判断.映射的方式是将数值化的样本特征与一个同维度的向量做内积,即: $y=w^Tx$ 因此,建立模型的目标就是 ...

  4. 软件逆向之IDA Pro

    IDA Pro作为一款强大的逆向分析工具,对于软件开发和安全领域的专业人士来说是必不可少的. 1. 什么是逆向分析 逆向分析是指通过分析已有的软件或程序,推测出其内部运行机制.算法和逻辑等信息.通过逆 ...

  5. Git中使用tag

    什么是tag git仓库的tag是git版本库的一个标记,指向某个commit id标记的快照记录指针,所以,标签也是版本库的一个快照. tag主要用于发布版本的管理,一个当版本发布后,可以为git当 ...

  6. 分布式对象存储之FDFS

    1.它是一个开源的分布式文件系统,它对文件进行管理. 功能有:文件存储.文件同步.文件访问(文件的上传下载)等.特别适合以文件为主的在线服务. 2.fastDFS服务端有两个角色:跟踪器(tracke ...

  7. MySQL底层概述—6.索引原理

    大纲 1.索引原理 2.二叉查找树 3.平衡二叉树(AVL树) 4.红黑树 5.B-Tree 6.B+Tree 7.Hash索引 8.聚簇索引与非聚簇索引 1.索引原理 索引会在数据文件中(ibd文件 ...

  8. 【VMware VCF】管理 VCF 环境中组件的用户密码。

    默认情况下,VMware Cloud Foundation 使用 vCenter Single Sign-On 作为身份提供程序,并使用系统域作为其身份源,可以将基于 LDAP 和 OpenLDAP ...

  9. Python中所有子图标签Legend显示详解

    在数据可视化中,图例(legend)是一个非常重要的元素,它能够帮助读者理解图表中不同元素的含义.特别是在使用Python进行可视化时,matplotlib库是一个非常强大的工具,能够轻松创建包含多个 ...

  10. 【Python】【Flask】【字符串索引】计算人民币与美元的相互计算

    目录 简介 Python Code 导包 设置首页 计算的接口 问题0:设置请求方式 问题1:关于接收数据可能存在的问题 问题2:返回结果 启动 完整代码 HTML Code 问题分析 分析:获取下拉 ...