開始使用¶
LCEL 可以輕鬆地從基本元件建立複雜的鏈,並支援開箱即用的功能,例如串流、平行性和日誌記錄。
Basic example: prompt + model + output parser¶
最基本和常見的用例是將提示模板和模型連結在一起。為了看看這是如何運作的,讓我們創建一個接受主題並產生笑話的鏈:
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
# 構建 prompt
prompt = ChatPromptTemplate.from_template("tell me a short joke about {topic}")
# 構建 llm 模型實例
model = ChatOpenAI(model="gpt-4")
# 構建輸出解析器
output_parser = StrOutputParser()
# 組合不同元件成為 chain
chain = prompt | model | output_parser
# 執行 chain
chain.invoke({"topic": "ice cream"})
結果:
請注意這行程式碼,我們使用 LCEL 將不同的元件拼湊成一個鏈:
|
符號類似於 Unix 管道運算符,它將不同的組件連結在一起,將一個組件的輸出作為下一個組件的輸入。
在此鏈中,使用者輸入傳遞到 prompt,然後 prompt 輸出傳遞到 model,然後 model 輸出傳遞到 output_parser。讓我們分別看一下每個組件,以真正了解發生了什麼。
1. Prompt¶
prompt
是一個 BasePromptTemplate
,這意味著它接受模板變數的 dict 並產生 PromptValue
。 PromptValue
是完整提示的包裝器,可以傳遞給 LLM
(將字串作為輸入)或 ChatModel
(將一系列訊息作為輸入)。它可以使用任一語言模型類型,因為它定義了用於產生 BaseMessage
和產生字串的邏輯。
結果:
用 BaseMessage 的型態來呈現:
結果:
用 string 的型態來呈現:
結果:
2. Model¶
然後將 PromptValue
傳遞給 model
。在本例中,我們的模型是 ChatModel
,這意味著它將輸出 BaseMessage
。
結果:
AIMessage(content="Why don't ice creams ever get invited to parties?\n\nBecause they always bring a melt down!")
如果我們的模型是 LLM,它將輸出一個字串。
from langchain_openai.llms import OpenAI
llm = OpenAI(model="gpt-3.5-turbo-instruct")
llm.invoke(prompt_value)
結果:
3. Output parser¶
最後,我們將 model
輸出傳遞給 output_parser
,它是一個 BaseOutputParser
,這意味著它接受 string
或 BaseMessage
作為輸入。 StrOutputParser
特別簡單地將任何輸入轉換為字串。
結果:
Why did the ice cream go to therapy? \n\nBecause it had too many toppings and couldn't find its cone-fidence!
4. Entire Pipeline¶
請依照以下步驟操作:
- 我們將所需使用者輸入傳遞為
{"topic": "ice Cream"}
prompt
組件接受使用者輸入,然後在使用topic
輸入構造PromptValue
。model
組件採用產生的提示,並傳遞到 OpenAI LLM 模型進行評估。模型產生的輸出是ChatMessage
物件。- 最後,
output_parser
元件接收ChatMessage
,並將其轉換為 Python 字串,該字串從invoke
方法傳回。
Tip
請注意,如果您對任何組件的輸出感到好奇,您始終可以測試鏈的較小版本,例如 prompt
或 prompt | model
以查看中間結果:
input = {"topic": "ice cream"}
prompt.invoke(input)
# > ChatPromptValue(messages=[HumanMessage(content='tell me a short joke about ice cream')])
(prompt | model).invoke(input)
# > AIMessage(content="Why did the ice cream go to therapy?\nBecause it had too many toppings and couldn't cone-trol itself!")
RAG Search Example¶
對於我們的下一個範例,我們希望運行檢索增強生成鏈以在回答問題時添加一些上下文。
# Requires:
# pip install langchain docarray tiktoken
from langchain_community.vectorstores import DocArrayInMemorySearch
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
from langchain_openai.chat_models import ChatOpenAI
from langchain_openai.embeddings import OpenAIEmbeddings
# 構建 vectorstore 實例
vectorstore = DocArrayInMemorySearch.from_texts(
["harrison worked at kensho", "bears like to eat honey"],
embedding=OpenAIEmbeddings(),
)
# 取得 retriever 實例
retriever = vectorstore.as_retriever()
# 設計 template
template = """Answer the question based only on the following context:
{context}
Question: {question}
"""
# 構建 ChatPromptTemplate 實例
prompt = ChatPromptTemplate.from_template(template)
# 構建 ChatOpenAI 模型實例
model = ChatOpenAI()
# 構建 StrOutputParser 實例
output_parser = StrOutputParser()
# 使用 RunnableParallet 來把 input 同時流向多個元件
setup_and_retrieval = RunnableParallel(
{"context": retriever, "question": RunnablePassthrough()}
)
# 組建完整的 chain
chain = setup_and_retrieval | prompt | model | output_parser
# 執行 chain
chain.invoke("where did harrison work?")
在這種情況下,組成的 chain 是:
為了解釋這一點,我們首先可以看到上面的提示範本將 context
和 question
作為要在提示中替換的值。在建立提示範本之前,我們希望檢索與搜尋相關的文件並將它們作為上下文的一部分包含在內。
首先我們使用 DocArrayInMemorySearch 來取得 retriever 實例,它可以根據查詢檢索文件。這也是一個可運行的元件,可以與其他元件連結在一起,但您也可以嘗試單獨運行它:
然後,我們使用 `RunnableParallel 透過使用檢索到的文件列表以及原始用戶問題來準備提示中的預期輸入,使用檢索器進行文檔搜索,並使用 RunnablePassthrough 傳遞用戶的問題:
回顧一下,完整的 chain 是:
setup_and_retrieval = RunnableParallel(
{"context": retriever, "question": RunnablePassthrough()}
)
chain = setup_and_retrieval | prompt | model | output_parser
流程為:
-
第一步建立一個包含兩個 entry 的
RunnableParallel
物件。第一個 entry 是context
將包括檢索器所取得的文件結果。第二個 entry 是question
將包含使用者的原始問題。為了傳遞問題,我們使用RunnablePassthrough
來複製此 entry。 -
將上述步驟中的字典作為
prompt
元件的輸入。它採用作為question
的使用者輸入以及作為context
的檢索到的文檔來建構提示並輸出PromptValue
。 -
model
組件使用PromptValue
作為輸入,並傳遞到 OpenAI LLM 模型進行評估。模型產生的輸出是ChatMessage
物件。 -
最後,
output_parser
元件接收ChatMessage
,並將其轉換為 Python 字串,該字串從invoke
方法傳回。