AI实战课程笔记-08 链(上)

226 阅读15分钟

LangChain六大核心组件

  • Model
  • Prompts
  • Chains
  • Memory
  • Agents
  • Indexes

1 链

1.1 链的定义

链其实可以被视为LangChain中的一种基本功能单元。 将多个组件相互链接,组合成一个链。链在内部把一系列的功能进行封装,而链的外部则又可以组合串联。

1.2 链的实现和使用

  • 首先LangChain通过设计好的接口,实现一个具体的链的功能。例如,LLM链(LLMChain)能够接受用户输入,使用 PromptTemplate 对其进行格式化,然后将格式化的响应传递给 LLM。这就相当于把整个Model I/O的流程封装到链里面。
  • 实现了链的具体功能之后,我们可以通过将多个链组合在一起,或者将链与其他组件组合来构建更复杂的链。

1.3 LangChain中的预置链

  • LLMChain: 是基于大模型构建的最简单、最基本的链。它包含提示模板,能根据用户输入对其进行格式化,把格式化的提示传入模型,然后返回LLM的响应,同时解析输出。LLMChain广泛用在整个LangChain中,包括其他链和代理中都经常有LLMChain的应用。
  • SequentialChain(顺序链):一个应用程序通常不会只调用一次语言模型,当你想要获取一个调用的输出时,顺序链就特别有用。SimpleSequentialChain是顺序链的最简单形式,其中每个步骤都有一个单一的输入/输出,并且一个步骤的输出就是下一步的输入。而SequentialChain是更通用的顺序链形式,允许多个输入输出。
  • TransformChain(转换链):能通过设置转换函数,对输入文本进行一系列的格式转换。例如,你可以用它接受一个很长的鲜花相关的文档,给文档分割成句子,仅保留前N句,以满足LLM的令牌数量的限制,然后将其传递到LLMChain中以总结这些内容。
  • RouterChain(路由链):包含条件判断和一系列的目标链。通过调用LLM,路由链能动态判断条件,以确定调用后续哪一个目标Chain。
  • 其他工具链
    • APIChain允许使用LLM与API交互以检索相关信息,通过提供与所提供的API相关的问题来构建链。
    • LLMMathChain允许调用大模型作为数学工具,构建链,并解决数学问题。
    • RetrieveQA通过嵌入向量索引进行查询,用于构建问答系统。在第2课构建智能问答系统是曾使用过该链。

2 链的调用方法

2.0 调用准备

设置OpenAI API密钥

import os

导入所需库

from langchain import PromptTemplate, LLMChain
from langchain_openai import ChatOpenAI

Warning 1: UserWarning: Importing PromptTemplate from langchain root module is no longer supported. Please use langchain_core.prompts.PromptTemplate instead. UserWarning: Importing LLMChain from langchain root module is no longer supported. Please use langchain.chains.LLMChain instead.

这个warning表示不再支持直接从Langchain的根模块导入PromptTemplate类和LLMChain类,需要从具体的子模块分别导入。

根据Warning 1更改后的代码:

from langchain_core.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain_openai import ChatOpenAI

设置提示模板

prompt = PromptTemplate(
    input_variables=["flower", "season"], template="{flower}在{season}的花语是?"
)

初始化大模型

llm = ChatOpenAI(model=os.environ.get("LLM_MODELEND"), temperature=0)

初始化链

llm_chain = LLMChain(llm=llm, prompt=prompt)

warning 2: LangChainDeprecationWarning: The class `LLMChain` was deprecated in LangChain 0.1.17 and will be removed in 1.0. Use RunnableSequence, e.g., `prompt | llm` instead.

这个warning表示,LLMChain类将被弃用,可以用可运行的序列代替原来的 LLMChain 类。 同时LLMChain类中的 __call__ 方法和run 方法也将会弃用,替换为invoke 方法,

需要注意的是,原先在LLMChain中使用output_key参数的目的是为了指定模型输出中的特定字段作为解析结果的关键字。在新的代码中,可以通过对模型输出进行处理来获得相应的输出结果,而不需要显式指定一个输出关键字。所以,参数output_key在使用RunnableSequence时并不需要额外指定。

llm_chain = prompt | llm

2.1 直接调用

response = llm_chain({"flower": "玫瑰", "season": "夏季"})
print(response)

当我们像函数一样调用一个对象时,它实际上会调用该对象内部实现的 __call__ 方法。

如果提示模板中包含多个变量,在调用链的时候,可以使用字典一次性输入它们。

warning 3: LangChainDeprecationWarning: The method `Chain.__call__` was deprecated in langchain 0.1.0 and will be removed in 1.0. Use invoke instead. 根据Warning 3更改后的代码:

response = llm_chain.invoke({"flower": "玫瑰", "season": "夏季"})

2.2 通过run方法

llm_chain.run("玫瑰")

通过 run 方法,也等价于直接调用 _call_ 函数。所以,llm_chain.run("玫瑰")等价于llm_chain("玫瑰")

warning 3:LangChainDeprecationWarning: The method Chain.run was deprecated in langchain 0.1.0 and will be removed in 1.0. Use invoke instead.

2.3 通过predict方法

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

predict 方法类似于 run ,只是输入键被指定为关键字参数而不是 Python 字典。

2.4 通过apply方法

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

apply 方法允许我们针对输入列表运行链,一次处理多个输入。

课程示例输出

'''[{'text': '\n\n玫瑰在夏季的花语是“恋爱”、“热情”和“浪漫”。'}, 
{'text': '\n\n百合在春季的花语是“爱情”和“友谊”。'},
 {'text': '\n\n郁金香在秋季的花语表达的是“热情”、“思念”、“爱恋”、“回忆”和“持久的爱”。'}]'''

我的输出

[
{'text': '玫瑰在夏季的花语可能会因具体的颜色和文化背景而有所不同。以下是一些常见的玫瑰颜色在夏季的花语:\n- **红玫瑰**:热情、热爱、爱情。\n- **粉玫瑰**:初恋、特别的关怀、喜欢你那灿烂的微笑。\n- **白玫瑰**:纯洁、高贵、天真和纯纯的爱。\n- **黄玫瑰**:友谊、快乐、道歉。\n- **橙玫瑰**:羞怯、献给你一份神秘的爱。\n- **紫玫瑰**:忧郁、梦幻、爱做梦。\n- **黑玫瑰**:你是恶魔,且为我所有。\n- **绿玫瑰**:纯真简朴、青春长驻,我只钟情你一个。\n\n需要注意的是,花语可能因文化、地区和个人的理解而有所差异。此外,玫瑰的花语也可以根据具体的情境和赠送对象进行调整和解读。如果你对特定的玫瑰花语有更深入的了解需求,建议参考相关的花卉书籍、网站或咨询专业的花卉专家。'}, 
{'text': '百合在春季的花语可能包括以下几种常见的含义:\n\n纯洁:百合花通常象征着纯洁和无暇,代表着纯真的情感和高尚的品质。\n\n希望:它可以寓意着对未来的希望和憧憬,给人带来积极向上的感觉。\n\n神圣:百合花在一些文化中具有神圣的象征意义,可能与宗教或精神层面相关联。\n\n高雅:其优雅的形态赋予了它高雅的花语,代表着高贵和不凡。\n\n美好:象征着美好、幸福的生活和情感。\n\n当然,花语也可能因文化、地域和个人理解的不同而有所差异。在具体情境中,百合花的花语还可能根据送花的对象、场合和关系而有所变化。'}, 
{'text': '郁金香的花语因颜色不同而有所差异,且在秋季并没有特定的花语。\n\n一般来说,郁金香的花语包括:\n- 红色:爱的告白、喜悦、热烈的爱意。\n- 粉色:美人、热爱、爱惜、幸福。\n- 黄色:高雅、珍贵、财富、友谊。\n- 白色:纯洁、清高的恋情。\n- 紫色:高贵的爱、无尽的爱。\n\n需要注意的是,花语是一种文化象征和情感表达,不同的人可能会有不同的理解和感受。在送花时,最好结合对方的喜好和具体情境来选择合适的花朵和颜色。'}
]

2.5 通过generate方法

input_list = [
    {"flower": "玫瑰",'season': "夏季"},
    {"flower": "百合",'season': "春季"},
    {"flower": "郁金香",'season': "秋季"}
]
result = llm_chain.generate(input_list)
print(result)

课程示例输出

generations=[
    [
        Generation(
            text='\n\n玫瑰在夏季的花语是“热情”、“爱情”和“幸福”。', 
            generation_info={'finish_reason': 'stop', 'logprobs': None}
        )
    ], 
    [
        Generation(
            text='\n\n春季的花语是爱情、幸福、美满、坚贞不渝。', 
            generation_info={'finish_reason': 'stop', 'logprobs': None}
        )
     ], 
    [
        Generation(
            text='\n\n秋季的花语是“思念”。银色的百合象征着“真爱”,而淡紫色的郁金香则象征着“思念”,因为它们在秋天里绽放的时候,犹如在思念着夏天的温暖。', 
            generation_info={'finish_reason': 'stop', 'logprobs': None}
        )
     ]
] 
llm_output={
    'token_usage': {
        'completion_tokens': 243, 
        'total_tokens': 301, 
        'prompt_tokens': 58
     }, 
     'model_name': 'gpt-3.5-turbo-instruct'
} 
run=[
    RunInfo(run_id=UUID('13058cca-881d-4b76-b0cf-0f9c831af6c4')), 
    RunInfo(run_id=UUID('7f38e33e-bab5-4d03-b77c-f50cd195affb')), 
    RunInfo(run_id=UUID('7a1e45fd-77ee-4133-aab0-431147186db8'))
]

我的输出

generations=[
    [
        ChatGeneration(
            text='玫瑰在夏季的花语与其他季节并没有本质区别,其常见花语主要包括以下这些:\n\n爱情:象征着真挚、热烈的爱情。\n\n美丽:代表着美丽与优雅。\n\n热情:传达出热情似火的情感。\n\n不过需要注意的是,花语也可能因文化背景、不同的解读等而存在一定差异。',
            generation_info={'finish_reason': 'stop', 'logprobs': None}, 
            message=AIMessage(
                content='玫瑰在夏季的花语与其他季节并没有本质区别,其常见花语主要包括以下这些:\n\n爱情:象征着真挚、热烈的爱情。\n\n美丽:代表着美丽与优雅。\n\n热情:传达出热情似火的情感。\n\n不过需要注意的是,花语也可能因文化背景、不同的解读等而存在一定差异。', 
                additional_kwargs={'refusal': None}, 
                response_metadata={
                    'token_usage': {
                        'completion_tokens': 74, 
                        'prompt_tokens': 15, 
                        'total_tokens': 89
                     }, 
                     'model_name': 'Doubao-pro-32k', 
                     'system_fingerprint': '', 
                     'finish_reason': 'stop', 
                     'logprobs': None
                 }, 
                 id='run-e7689f85-4911-497d-b453-dca81e413e10-0',
                 usage_metadata={
                     'input_tokens': 15, 
                     'output_tokens': 74,
                     'total_tokens': 89
                 }
            )
        )
    ],
    
    [
        ChatGeneration(
            text='百合的花语因颜色和品种的不同而有所差异,以下是一些常见的百合在春季的花语:\n- **白色百合**:纯洁、庄严、心心相印。\n- **粉色百合**:纯洁、可爱、高雅。\n- **黄色百合**:财富、高贵、感激。\n- **橙色百合**:繁荣、骄傲、胜利。\n\n需要注意的是,花语是一种文化现象,不同的文化和地区可能会有不同的解释和理解。此外,花语也可能会随着时间和文化的变迁而发生变化。因此,在使用花语时,最好结合具体的情境和文化背景进行理解。', 
            generation_info={
                'finish_reason': 'stop', 
                'logprobs': None
            }, 
            message=AIMessage(
                content='百合的花语因颜色和品种的不同而有所差异,以下是一些常见的百合在春季的花语:\n- **白色百合**:纯洁、庄严、心心相印。\n- **粉色百合**:纯洁、可爱、高雅。\n- **黄色百合**:财富、高贵、感激。\n- **橙色百合**:繁荣、骄傲、胜利。\n\n需要注意的是,花语是一种文化现象,不同的文化和地区可能会有不同的解释和理解。此外,花语也可能会随着时间和文化的变迁而发生变化。因此,在使用花语时,最好结合具体的情境和文化背景进行理解。', 
                additional_kwargs={'refusal': None}, 
                response_metadata={
                    'token_usage': {
                        'completion_tokens': 138, 
                        'prompt_tokens': 15, 
                        'total_tokens': 153
                    }, 
                    'model_name': 'Doubao-pro-32k', 
                    'system_fingerprint': '', 
                    'finish_reason': 'stop', 
                    'logprobs': None
                }, 
                id='run-007e03d3-7c08-469f-9df5-bfab162681bd-0',
                usage_metadata={
                    'input_tokens': 15, 
                    'output_tokens': 138, 
                    'total_tokens': 153
                }
            )
        )
    ],
    
    [
        ChatGeneration(
            text='郁金香在秋季通常并没有特定的、被广泛认可的花语。\n\n郁金香的花语在不同的文化和情境中可能会有所差异,但一般来说,郁金香的花语包括:\n1. **爱的表白**:代表着爱情和浪漫。\n2. **高贵优雅**:象征着高贵、优雅和美丽。\n3. **胜利和荣誉**:也可以表示胜利和荣誉。\n\n需要注意的是,花语是一种文化现象,不同的人可能会有不同的理解和解释。此外,郁金香的花语也可能会受到颜色的影响,不同颜色的郁金香可能具有不同的花语。\n\n如果你想了解郁金香在秋季的花语,建议参考相关的花卉书籍、网站或咨询专业的花卉专家。', 
            generation_info={
                'finish_reason': 'stop', 
                'logprobs': None
            },
            message=AIMessage(
                content='郁金香在秋季通常并没有特定的、被广泛认可的花语。\n\n郁金香的花语在不同的文化和情境中可能会有所差异,但一般来说,郁金香的花语包括:\n1. **爱的表白**:代表着爱情和浪漫。\n2. **高贵优雅**:象征着高贵、优雅和美丽。\n3. **胜利和荣誉**:也可以表示胜利和荣誉。\n\n需要注意的是,花语是一种文化现象,不同的人可能会有不同的理解和解释。此外,郁金香的花语也可能会受到颜色的影响,不同颜色的郁金香可能具有不同的花语。\n\n如果你想了解郁金香在秋季的花语,建议参考相关的花卉书籍、网站或咨询专业的花卉专家。',
                additional_kwargs={'refusal': None}, 
                response_metadata={
                    'token_usage': {
                        'completion_tokens': 156, 
                        'prompt_tokens': 15, 
                        'total_tokens': 171
                     }, 
                     'model_name': 'Doubao-pro-32k', 
                     'system_fingerprint': '', 
                     'finish_reason': 'stop', 
                     'logprobs': None
                 }, 
                 id='run-4e0cc369-21af-4901-995e-82586b9231bb-0',
                 usage_metadata={
                     'input_tokens': 15,
                     'output_tokens': 156,
                     'total_tokens': 171
                 }
            )
        )
    ]
] 


llm_output={
    'token_usage': {
        'completion_tokens': 368,
        'prompt_tokens': 45,
        'total_tokens': 413
     }, 
     'model_name': 'Doubao-pro-32k'
} 

run=[
    RunInfo(run_id=UUID('e7689f85-4911-497d-b453-dca81e413e10')),
    RunInfo(run_id=UUID('007e03d3-7c08-469f-9df5-bfab162681bd')),
    RunInfo(run_id=UUID('4e0cc369-21af-4901-995e-82586b9231bb'))
]

generate 方法类似于 apply ,只不过它返回一个 LLMResult 对象,而不是字符串。LLMResult 通常包含模型生成文本过程中的一些相关信息,例如令牌数量、模型名称等。

3 LLMChain

# 导入所需的库
from langchain import PromptTemplate, OpenAI, LLMChain
# 原始字符串模板
template = "{flower}的花语是?"
# 创建模型实例
llm = OpenAI(temperature=0)
# 创建LLMChain
llm_chain = LLMChain(
    llm=llm,
    prompt=PromptTemplate.from_template(template))
# 调用LLMChain,返回结果
result = llm_chain("玫瑰")
print(result)

LLMChain围绕着语言模型推理功能又添加了一些功能,整合了PromptTemplate、语言模型(LLM或聊天模型)和 Output Parser相当于把Model I/O放在一个链中整体操作。它使用提示模板格式化输入,将格式化的字符串传递给 LLM,并返回 LLM 输出。

4 Sequential Chain:顺序链

4.1 导入所需要的库

import os
os.environ["OPENAI_API_KEY"] = '你的OpenAI API Key'

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

4.2 LLMChain1

llm = OpenAI(temperature=.7)
template = """
你是一个植物学家。给定花的名称和类型,你需要为这种花写一个200字左右的介绍。

花名: {name}
颜色: {color}
植物学家: 这是关于上述花的介绍:"""
prompt_template = PromptTemplate(input_variables=["name", "color"], template=template)
introduction_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="introduction")

添加第一个LLMChain,生成鲜花的知识性说明,输入为花的名称和种类。

4.3 LLMChain2

llm = OpenAI(temperature=.7)
template = """
你是一位鲜花评论家。给定一种花的介绍,你需要为这种花写一篇200字左右的评论。

鲜花介绍:
{introduction}
花评人对上述花的评论:"""
prompt_template = PromptTemplate(input_variables=["introduction"], template=template)
review_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="review")

添加第二个LLMChain,根据鲜花的知识性说明生成评论。

4.4 LLMChain3

template = """
你是一家花店的社交媒体经理。给定一种花的介绍和评论,你需要为这种花写一篇社交媒体的帖子,300字左右。

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

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

添加第三个LLMChain,根据鲜花的介绍和评论写出一篇自媒体的文案。

4.5 添加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)

# 运行链,并打印结果
result = overall_chain({"name":"玫瑰", "color": "黑色"})
print(result)

定义了一个名为 overall_chain 的 SequentialChain 对象,它是由三个 LLMChain对象组成的序列,分别是 introduction_chainreview_chain 和 social_post_chain

其中verbose是一个布尔值,用于控制是否打印详细的执行信息。在这个例子中,verbose=True,所以在执行链时会打印详细的信息。