偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

五分鐘理透 LangChain 的 Chain

人工智能
本文主要聊了 LangChain 中的 Chain 概念。Chain 是 LangChain 中的核心組件,我們對(duì)多個(gè)組件的一系列調(diào)用就是Chain。

LangChain幾乎是LLM應(yīng)用開(kāi)發(fā)的第一選擇,它的野心也比較大,它致力于將自己打造成LLM應(yīng)用開(kāi)發(fā)的最大社區(qū)。而LangChain最核心的部分非 Chain 莫屬。

那Chain到底是個(gè)啥,概念比較模糊,像霧像雨又像風(fēng),這篇文章將帶你快速理透 LangChain 中的 Chain 概念。

1. Chain是核心

LangChain的Chain到底是什么?一句話總結(jié):Chain是指對(duì) LangChain 多個(gè)組件的一系列調(diào)用。

再看看官網(wǎng)的解釋?zhuān)篊hain是指調(diào)用的序列 - 無(wú)論是調(diào)用 LLM、工具還是數(shù)據(jù)預(yù)處理步驟,主要支持的方法是使用 LCEL。

官網(wǎng)里還提到了LCEL,LCEL是LangChain 表達(dá)式語(yǔ)言,是一種更加高效簡(jiǎn)介的鏈接 LangChain 組件的方式,也是官網(wǎng)推薦的方式。

從下圖官網(wǎng)的描述,也可以看到,Chain可以是從最簡(jiǎn)單的“prompt + LLM”鏈 到 最復(fù)雜的鏈(運(yùn)行了包含 100 多個(gè)步驟的鏈)。

2. 為什么需要Chain

我們所期待的LLM是能處理許多復(fù)雜任務(wù),而非簡(jiǎn)單的一問(wèn)一答,也不是簡(jiǎn)單的處理單一任務(wù)。

所以,最終我期待的LLM處理任務(wù)的流程應(yīng)該是這樣,它中間的復(fù)雜過(guò)程對(duì)用戶來(lái)說(shuō)是一個(gè)黑盒:

既然定位是完成復(fù)雜任務(wù),那自然就需要通過(guò)某個(gè)機(jī)制將多個(gè)單一任務(wù)串起來(lái),形成一個(gè)大的鏈條,多個(gè)步驟共同完成某個(gè)復(fù)雜任務(wù)。

Chain可以將多個(gè)步驟連接到一起,最終完成各種復(fù)雜繁瑣的任務(wù)。這就是Chain存在的必要性了。我很喜歡LangChain的Logo,很形象地表達(dá)了這一思想。

Chain需要對(duì)多個(gè)組件一系列的調(diào)用或者一系列的串聯(lián),這樣才能完成復(fù)雜任務(wù)。當(dāng)然,我們也可以把 Chain 看作是流水線。通過(guò)使用 Chain,你可以將各個(gè)步驟定義為獨(dú)立的模塊,然后按順序串聯(lián)起來(lái)。這樣不僅大大簡(jiǎn)化了代碼邏輯,也使得整個(gè)流程更加直觀和易于管理。

而LCEL的存在,也只是為了讓構(gòu)建鏈的過(guò)程更簡(jiǎn)單,讓鏈的表達(dá)力更清晰更簡(jiǎn)單。

接下來(lái),我將通過(guò)一個(gè)示例展示沒(méi)有 Chain 和有Chain的2種實(shí)現(xiàn)方式,以便更清晰地理解 Chain 的價(jià)值。

3. 如果沒(méi)有Chain

這里舉個(gè)例子,比如:我們給LLM輸入一段項(xiàng)目描述,讓LLM給這個(gè)項(xiàng)目起一個(gè)名稱(chēng)和Slogan。

如果不使用Chain的話,我們可以這樣實(shí)現(xiàn)。

# 本次需求:我們給LLM輸入一段項(xiàng)目描述,讓LLM給這個(gè)項(xiàng)目起一個(gè)名稱(chēng)和Slogan
# 以下是實(shí)現(xiàn):

from langchain.prompts import PromptTemplate, ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser


proj_desc = """
    我們本次的項(xiàng)目是去森林里探險(xiǎn)救援,我們有一個(gè)10人小隊(duì),
    我們要到達(dá)一個(gè)叫做“蝴蝶谷”的目的地,去那里解救一位被困的科學(xué)家。
    這期間我們可能會(huì)遇到許多危險(xiǎn),我們需要共同合作,互相幫助,歷經(jīng)磨難,才能到達(dá)目的地。
    我們的任務(wù)是要在5天內(nèi)到達(dá)目的地并且救出探險(xiǎn)家,才算完成這次探險(xiǎn),否則任務(wù)失敗,我們將受到懲罰。
    出發(fā)前我們要各自準(zhǔn)備好自己的裝備和干糧,加油!
"""


def name_slogan_by_desc(project_desc):
    """
    根據(jù)項(xiàng)目描述,生成項(xiàng)目名稱(chēng)和slogan
    """
    str_parser = StrOutputParser()

    promt_template_project_name = "請(qǐng)你根據(jù)<desc>標(biāo)簽里的關(guān)于某個(gè)項(xiàng)目的描述,生成一個(gè)項(xiàng)目名稱(chēng),只需要返回項(xiàng)目名稱(chēng)。<desc>{project_desc}</desc>"
    promt_project_name = PromptTemplate.from_template(promt_template_project_name)
    final_promt_project_name = promt_project_name.invoke({"project_desc": project_desc})
    res_project_name = model.invoke(final_promt_project_name)
    parsed_res_project_name = str_parser.invoke(res_project_name)


    promt_template_slogan = "請(qǐng)你根據(jù)<desc>標(biāo)簽里的關(guān)于某個(gè)項(xiàng)目的描述,和這個(gè)項(xiàng)目的名稱(chēng){project_name},給這個(gè)項(xiàng)目起一個(gè)slogan,slogan要求干脆簡(jiǎn)潔積極向上,只返回slogan。<desc>{project_desc}</desc>"
    promt_slogan = PromptTemplate.from_template(promt_template_slogan)
    final_promt_slogan = promt_slogan.invoke(
        {"project_desc": project_desc, "project_name": parsed_res_project_name}
    )
    response_slogan = model.invoke(final_promt_slogan)
    parsed_response_slogan = str_parser.invoke(response_slogan)


    final_result = {
        "project_name": parsed_res_project_name,
        "slogan": parsed_response_slogan,
    }
    return final_result

# 輸入項(xiàng)目描述,輸出項(xiàng)目名稱(chēng)和slogan
result = name_slogan_by_desc(proj_desc)
print(result)

執(zhí)行結(jié)果如下:

{'project_name': '蝴蝶谷救援行動(dòng)', 'slogan': '拯救科學(xué)家,共同合作,蝴蝶谷等你來(lái)!'}

可以看到,實(shí)現(xiàn)過(guò)程比較繁瑣,變量和代碼也多,不夠直觀,很容易出錯(cuò)。這還只是簡(jiǎn)單場(chǎng)景,如果碰到復(fù)雜場(chǎng)景就更麻煩了。

4. 因?yàn)橛辛薈hain

接下來(lái),我們使用 LangChain 的 Chain 功能,來(lái)實(shí)現(xiàn)相同的功能。代碼如下:

# 本次需求:我們給LLM輸入一段項(xiàng)目描述,讓LLM給這個(gè)項(xiàng)目起一個(gè)名稱(chēng)和Slogan
# 以下是實(shí)現(xiàn):

from operator import itemgetter
from langchain.prompts import PromptTemplate, ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain.chains import LLMChain, SequentialChain

proj_desc = """
    我們本次的項(xiàng)目是去森林里探險(xiǎn)救援,我們有一個(gè)10人小隊(duì),
    我們要到達(dá)一個(gè)叫做“蝴蝶谷”的目的地,去那里解救一位被困的科學(xué)家。
    這期間我們可能會(huì)遇到許多危險(xiǎn),我們需要共同合作,互相幫助,歷經(jīng)磨難,才能到達(dá)目的地。
    我們的任務(wù)是要在5天內(nèi)到達(dá)目的地并且救出探險(xiǎn)家,才算完成這次探險(xiǎn),否則任務(wù)失敗,我們將受到懲罰。
    出發(fā)前我們要各自準(zhǔn)備好自己的裝備和干糧,加油!
"""

def name_slogan_by_desc(project_desc):
    """
    根據(jù)項(xiàng)目描述,生成項(xiàng)目名稱(chēng)和slogan
    """

    # 第1條鏈
    promt_template_project_name = "請(qǐng)你根據(jù)<desc>標(biāo)簽里的關(guān)于某個(gè)項(xiàng)目的描述,生成一個(gè)項(xiàng)目名稱(chēng),只需要返回項(xiàng)目名稱(chēng)。<desc>{project_desc}</desc>"
    chain_one = LLMChain(
        llm=model,
        prompt=PromptTemplate.from_template(promt_template_project_name),
        output_parser=StrOutputParser(),
        output_key="project_name",
    )

    # 第2條鏈
    promt_template_slogan = "請(qǐng)你根據(jù)<desc>標(biāo)簽里的關(guān)于某個(gè)項(xiàng)目的描述,和這個(gè)項(xiàng)目的名稱(chēng){project_name},給這個(gè)項(xiàng)目起一個(gè)slogan,slogan要求干脆簡(jiǎn)潔積極向上,只返回slogan。<desc>{project_desc}</desc>"
    chain_two = LLMChain(
        llm=model,
        prompt=PromptTemplate.from_template(promt_template_slogan),
        output_parser=StrOutputParser(),
        output_key="slogan",
    )

    # 串聯(lián)兩條鏈
    sequential_chain = SequentialChain(
        chains=[chain_one, chain_two],
        input_variables=["project_desc"],
        output_variables=["project_name", "slogan"],
    )
    final_res = sequential_chain(project_desc)

    final_result = {
        "project_name": final_res["project_name"],
        "slogan": final_res["slogan"],
    }
    return final_result

# 輸入項(xiàng)目描述,輸出項(xiàng)目名稱(chēng)和slogan
result = name_slogan_by_desc(proj_desc)
print(result)

執(zhí)行結(jié)果如下:

{'project_name': '蝴蝶谷救援行動(dòng)', 'slogan': '團(tuán)結(jié)合作,共赴蝴蝶谷'}

可以看到代碼更簡(jiǎn)潔,也很直觀,當(dāng)然,也可以使用LCEL讓整個(gè)鏈條更加簡(jiǎn)潔清晰。

5. LCEL表達(dá)式

LCEL方式的代碼如下:

# 本次需求:我們給LLM輸入一段項(xiàng)目描述,讓LLM給這個(gè)項(xiàng)目起一個(gè)名稱(chēng)和Slogan
# 以下是實(shí)現(xiàn):

from langchain.prompts import PromptTemplate, ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

proj_desc = """
    我們本次的項(xiàng)目是去森林里探險(xiǎn)救援,我們有一個(gè)10人小隊(duì),
    我們要到達(dá)一個(gè)叫做“蝴蝶谷”的目的地,去那里解救一位被困的科學(xué)家。
    這期間我們可能會(huì)遇到許多危險(xiǎn),我們需要共同合作,互相幫助,歷經(jīng)磨難,才能到達(dá)目的地。
    我們的任務(wù)是要在5天內(nèi)到達(dá)目的地并且救出探險(xiǎn)家,才算完成這次探險(xiǎn),否則任務(wù)失敗,我們將受到懲罰。
    出發(fā)前我們要各自準(zhǔn)備好自己的裝備和干糧,加油!
"""

def name_slogan_by_desc(project_desc):
    """
    根據(jù)項(xiàng)目描述,生成項(xiàng)目名稱(chēng)和slogan
    """

    # 第1條鏈
    promt_template_project_name = "請(qǐng)你根據(jù)<desc>標(biāo)簽里的關(guān)于某個(gè)項(xiàng)目的描述,生成一個(gè)項(xiàng)目名稱(chēng),只需要返回項(xiàng)目名稱(chēng)。<desc>{project_desc}</desc>"
    chain_one = (
        PromptTemplate.from_template(promt_template_project_name)
        | model
        | {"project_name": StrOutputParser(), "project_desc": lambda x: project_desc}
    )

    # 第2條鏈
    promt_template_slogan = "請(qǐng)你根據(jù)<desc>標(biāo)簽里的關(guān)于某個(gè)項(xiàng)目的描述,和這個(gè)項(xiàng)目的名稱(chēng){project_name},給這個(gè)項(xiàng)目起一個(gè)slogan,slogan要求干脆簡(jiǎn)潔積極向上,只返回slogan。<desc>{project_desc}</desc>"
    chain_two = (
        PromptTemplate.from_template(promt_template_slogan)
        | model
        | {"slogan": StrOutputParser(), "project_info": lambda x: chain_one}
    )

    # 串聯(lián)兩條鏈
    final_chain = chain_one | chain_two
    final_res = final_chain.invoke({"project_desc": project_desc})

    final_result = {
        "project_name": final_res["project_info"]["project_name"],
        "slogan": final_res["slogan"],
    }

    return final_result

# 輸入項(xiàng)目描述,輸出項(xiàng)目名稱(chēng)和slogan
result = name_slogan_by_desc(proj_desc)
print(result)

普通方式和LCEL方式的核心代碼對(duì)比:

普通方式:

LCEL方式:

責(zé)任編輯:趙寧寧 來(lái)源: 程序員半支煙
相關(guān)推薦

2024-06-25 12:25:12

LangChain路由鏈

2023-05-25 08:02:09

構(gòu)建工具源碼JS

2020-06-16 08:47:53

磁盤(pán)

2025-03-13 06:22:59

2009-11-16 10:53:30

Oracle Hint

2024-12-11 07:00:00

面向?qū)ο?/a>代碼

2021-09-07 09:40:20

Spark大數(shù)據(jù)引擎

2025-01-07 08:11:06

ArrayArrayList場(chǎng)景

2009-11-17 14:50:50

Oracle調(diào)優(yōu)

2025-01-21 07:39:04

Linux堆內(nèi)存Golang

2009-11-16 09:53:56

PHP上傳類(lèi)

2023-09-07 23:52:50

Flink代碼

2023-07-23 18:47:59

Docker開(kāi)源

2022-12-16 09:55:50

網(wǎng)絡(luò)架構(gòu)OSI

2021-12-01 06:50:50

Docker底層原理

2024-07-10 18:55:09

Python定時(shí)

2024-09-18 08:21:24

JavaScriptTypeScriptprototype

2025-01-20 08:50:00

2009-11-05 14:53:54

Visual Stud

2021-06-07 09:51:22

原型模式序列化
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)