簡介
langchain中提供的chain鏈組件,能夠幫助我門快速的實現各個組件的流水線式的調用,和模型的問答
Chain鏈的組成
根據查閲的資料,langchain的chain鏈結構如下:
$$Input \rightarrow Prompt \rightarrow Model \rightarrow Output$$
其中langchain框架提供了幾個常用構建chain鏈的工具:
| 工具名稱 | 作用 | 流程 |
|---|---|---|
| RunnablePassthrough | 傳遞原本的數據或添加新的字段 | $$A->B$$ |
| RunnableParallel | 併發輸出結果並將結果同時傳遞 | $$A,B->C$$ |
| RunnableLambda | 自定義傳遞工具 |
乍一看很疑惑,我接下來用案例來解釋各種用法。
構建較為複雜的chain鏈
這個案例幾乎用了上面所有工具,用於演示用法
案例
案例描述:輸入論文的話題,寫一篇950字的高中論文。
import os
from langchain_community.chat_models.tongyi import ChatTongyi
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough, RunnableParallel
#你的qwen模型apikey
os.environ["DASHSCOPE_API_KEY"] = "apikey"
model = ChatTongyi(model="qwen-max")
outline_prompt = ChatPromptTemplate.from_template(
"請給主題為 {topic} 的議論文寫一個 總-遞進-總 的簡短大綱,一共分為5段。"
)
outline_chain = outline_prompt | model | StrOutputParser()
def mock_search(input_data):
return """
1. 利:Google Health AI 篩查乳腺癌準確率超人類。
2. 利:AlphaFold 預測蛋白質結構,縮短科研週期。
3. 弊:GPT-4 普及導致初級文案、原畫設計崗位萎縮。
4. 弊:Deepfake 技術被用於電信詐騙和虛假視頻。
"""
output_prompt = ChatPromptTemplate.from_template(
"你是一位高考作文專家。請基於大綱:\n{outline}\n並結合以下案例素材:\n{data}\n"
"就主題【{topic}】寫一篇高考論文。要求:950字左右,論證嚴密,文采斐然。"
)
output_chain = output_prompt | model | StrOutputParser()
complex_chain = (
RunnableParallel({
"outline": outline_chain,
"data": mock_search,
"topic": RunnablePassthrough()
})
| output_chain
)
topic_input = "AI 進步的利與弊:在智能時代保持人類的温度"
print(f"正在為您撰寫關於《{topic_input}》的論文...\n")
final_essay = complex_chain.invoke({"topic": topic_input})
print(final_essay)
代碼解釋
其他的代碼我上期解釋了,這裏就不廢話了,我着重講chain鏈的構建,總體chain鏈的流程如下:
輸入話題->獲取寫作的大綱 ──╮
├─▶ 根據大綱和示例寫一篇論文
查詢相關的示例 ──╯
根據輸入流程圖流程,我們個以分解成一個個相關的鏈,再將各個鏈串起來。
構建各部分的鏈
1.獲取寫作大綱
outline_prompt = ChatPromptTemplate.from_template(
"請給主題為 {topic} 的議論文寫一個 總-遞進-總 的簡短大綱,一共分為5段。"
)
outline_chain = outline_prompt | model | StrOutputParser()
流程描述:構建prompt->餵給ai->將返回解析成文本
這裏用的
ChatPromptTemplate.from_template和上的ChatPromptTemplate.from_messages不同,區別在於前者比較簡單,相當於後者直接用user字典的形式,後者from_messages有langchain框架提供的prompt模板
2.查詢相關的示例
這裏就直接用Gemini,mock一些模擬數據(不保證真),用於完成案例,實際情況可以自己完善搜索邏輯。
def mock_search(input_data):
return """
1. 利:Google Health AI 篩查乳腺癌準確率超人類。
2. 利:AlphaFold 預測蛋白質結構,縮短科研週期。
3. 弊:GPT-4 普及導致初級文案、原畫設計崗位萎縮。
4. 弊:Deepfake 技術被用於電信詐騙和虛假視頻。
"""
這個相當於
RanableLamda,後面可以不用顯示調用RanableLamda(mock_search)
3. 根據大綱和示例寫一篇論文
output_prompt = ChatPromptTemplate.from_template(
"你是一位高考作文專家。請基於大綱:\n{outline}\n並結合以下案例素材:\n{data}\n"
"就主題【{topic}】寫一篇高考論文。要求:950字左右,論證嚴密,文采斐然。"
)
output_chain = output_prompt | model | StrOutputParser()
流程描述:構建prompt->餵給ai->將返回解析成文本
將各個鏈連起來
complex_chain = (
RunnableParallel({
"outline": outline_chain,
"data": mock_search,
"topic": RunnablePassthrough()
})
| output_chain
)
這裏利用RunnableParallel將獲取寫作的大綱和查詢相關的示例兩個流程並列運行後一起輸出到後面,傳遞給output_chain繼續處理。
問題
- 我不想利用RunnableParallel行不行? 當然可以,可以用線性來代替,先查資料,後寫大綱,然後再進行文章輸出,但是效率可能會比較慢。
- 我希望看到輸出的data和outline字段怎麼辦? ,可以利用
RunnablePassthrough().assign將生成的文本保存在新的字段中,調用時根據字典的方式定位各個文本,如下:
complex_chain = (
RunnableParallel({
"outline": outline_chain,
"data": mock_search,
"topic": RunnablePassthrough()
})
| RunnablePassthrough().assign(essay=output_chain)
)
print(response['essay'])
print(response['data'])
......
如果❤喜歡❤本系列教程,就點個關注吧,後續不定期更新~