LangChain Agents 和 Ollama 建一個有多輪對話和上下文記憶能力的 LLM 聊天機器人 Chatbot
日期:2024-12-05
使用 LangChain 來構建 LLM 聊天機器人。此助手具備多輪對話的能力,並能記住上下文,還可以執行特定工具來回答問題(查詢今天的日期)。
所需檔案下載
Github Repository — weitsung50110/Huggingface_Langchain_kit
本文使用裡面的 langchain_agents_conversational-react_memory.py
檔案。
在 initialize_agent
中有非常多的 Agents,詳細介紹可以參考這篇:
LangChain Agents 預設代理類型解析:initialize_agent 選擇最適合你的應用場景
本文使用 Conversational-react-description 進行實作。
若想使用 zero-shot-react-description 進行實作,可以參考這篇:
用 LangChain Agents 和 Ollama 建立 LLM 多功能 AI 助手:支援日期查詢與數學運算
程式架構
- 初始化 LLM — 使用 Ollama 的語言模型。
- 定義工具 — 如查詢日期的工具。
- 自定義 Prompt — 指導 AI 如何回應問題。
- 管理記憶 — 記住上下文對話。
- 建立對話型代理(Agent) — 將 LLM、工具和記憶結合。
- 互動主程式 — 實現人機互動,處理多輪對話。
Docker Image
Image 名稱: weitsung50110/ollama_flask
此為已安裝好的 Docker image 環境。
使用說明:
有關 docker run
等使用方法,請進入 Docker Hub 的說明欄查看詳細資訊。
Docker Hub 連結: weitsung50110/ollama_flask
docker pull weitsung50110/ollama_flask:1.0
1. 初始化 LLM
這一步是引入 Ollama 語言模型,並設定模型參數(使用 kenneth85/llama-3-taiwan:8b-instruct
模型)。
注意: model
是可以調整更動的。
model=’更換成你載入的模型’
Ex:llm = Ollama(model=’llama3’)
llm = Ollama(
model="kenneth85/llama-3-taiwan:8b-instruct",
callback_manager=CallbackManager([StreamingStdOutCallbackHandler()])
)
CallbackManager
用於處理事件回調,而 StreamingStdOutCallbackHandler
則允許在終端上顯示輸出的過程。
2.定義工具
def get_today_date(_):
print(datetime.now().strftime("今天是 %Y 年 %m 月 %d 日,星期%a。"))
return datetime.now().strftime("今天是 %Y 年 %m 月 %d 日,星期%a。")
tools = [
Tool(
name="get today date",
func=get_today_date,
description="回答今天的日期和星期幾。"
)
]
工具函數
定義查詢今天日期的功能,返回格式化的日期和星期。工具列表
將工具封裝為一個 Tool,指定工具的名稱和用途。工具調用
當用戶詢問日期時,代理 Agent 會調用此工具提供答案。
3.自定義 Prompt
custom_prompt = PromptTemplate(
input_variables=["input", "chat_history"],
template="""\
你是一個智慧型 AI 助手,能回答問題並記住上下文。
可以使用以下工具:
1. get today date: 提供今天的日期和星期幾。
當問題可以直接回答時,請直接回答。只有在必須使用工具時才使用它們。
以下是目前的對話記錄:
{chat_history}
使用者的最新問題是:{input}
請根據上下文回答問題,並僅在必要時使用工具。
"""
)
PromptTemplate
定義 AI 回應問題的規則
包含對工具的描述
提供工具的功能與使用方式,讓 AI 瞭解如何正確使用工具。提示 AI 考慮對話記錄
引導 AI 根據上下文與對話記錄回答問題,保持對話的一致性。指導 AI 僅在必要時使用工具
明確要求 AI 只在需要時調用工具,避免不必要的操作。
4.初始化記憶
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
記憶(Memory)與 ConversationBufferMemory
記憶用途
記憶用於儲存對話歷史,ConversationBufferMemory
將每次對話記錄起來,方便 AI 回顧。主要設定
memory_key="chat_history"
:指定記憶的鍵值。return_messages=True
:返回完整的對話訊息。
為什麼使用 ConversationBufferMemory?
ConversationBufferMemory
是 LangChain 中一種常見的記憶類型,主要用於儲存對話的完整歷史記錄,以便在多輪對話中保持上下文連貫性。
特點
完整記錄對話
將每次用戶與 AI 的對話訊息按順序儲存。上下文參考
代理可以根據歷史對話來理解當前問題,避免忘記先前的對話。簡單易用
設置與管理相對容易,適合基礎對話應用。
記憶方式 | 適合情境 | 優點 | 缺點 |
---|---|---|---|
ConversationBufferMemory | 短期對話,內容不多時適用 | 簡單直觀,實現快速 | 無法處理長對話或多主題場景 |
ConversationSummaryMemory | 長期對話,需保持全局概念時適用 | 節省資源,保持上下文連貫 | 易丟失細節,回應可能不夠準確 |
VectorStoreMemory | 多主題對話,需快速檢索時適用 | 高效檢索,支持大規模數據 | 複雜實現,需配置向量數據庫 |
CombinedMemory | 複雜應用,多種需求並存時適用 | 彈性高,適用廣泛 | 資源需求高,實現成本高 |
5.初始化對話型代理(Agent)
agent = initialize_agent(
tools=tools,
llm=llm,
agent="conversational-react-description",
verbose=False,
agent_prompt=custom_prompt,
handle_parsing_errors=True,
memory=memory
)
代理結合 LLM、工具與記憶
在這裡,我們將 LLM、工具和記憶結合到一個代理中,以實現多輪對話的功能。
結合的元素
tools
包含查詢日期的工具,用於執行特定任務。llm
指定的語言模型,負責生成自然語言回應。agent_prompt
使用自定義的 Prompt 指導代理的回應行為。memory
整合對話記憶,用於儲存對話歷史,保持上下文的連貫性。handle_parsing_errors
用於處理解析錯誤,避免因語法或其他錯誤導致程式崩潰。agent=”conversational-react-description”
表明這是一個對話型代理,適合多輪對話應用場景。
6.主程式互動
def main():
print("歡迎使用智慧型 AI 助手!可以進行多輪對話,並記住上下文。")
print("隨時輸入問題,例如:『今天是幾號?』,或『你剛剛問了什麼?』")
print("如果想結束對話,請輸入 'bye', 'exit' 或 'quit'。\n")
while True:
user_query = input("請輸入您的問題:")
if user_query.lower() in ["bye", "exit", "quit"]:
print("感謝您的使用,再見!")
break
try:
response = agent.invoke({"input": user_query})
print("\nAI 助手的回答紀錄:")
print(response)
except Exception as e:
print(f"抱歉,處理你的問題時出現了一些錯誤:{e}")
用戶與 AI 助手互動的主邏輯
主邏輯步驟
提示用戶輸入問題
當用戶輸入問題後,將其傳遞給代理處理。檢查退出條件
如果用戶輸入bye
、exit
或quit
,則結束程式。捕捉錯誤
捕捉異常情況,避免因錯誤導致程式中斷運行。
成果展示
執行程式
root@4be643ba6a94:/app# python3 langchain_agents_conversational-react_memory.py
/app/langchain_agents_conversational-react_memory.py:10: LangChainDeprecationWarning: The class `Ollama` was deprecated in LangChain 0.3.1 and will be removed in 1.0.0. An updated version of the class exists in the :class:`~langchain-ollama package and should be used instead. To use it run `pip install -U :class:`~langchain-ollama` and import as `from :class:`~langchain_ollama import OllamaLLM``.
llm = Ollama(model="kenneth85/llama-3-taiwan:8b-instruct", callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]))
/app/langchain_agents_conversational-react_memory.py:10: DeprecationWarning: callback_manager is deprecated. Please use callbacks instead.
llm = Ollama(model="kenneth85/llama-3-taiwan:8b-instruct", callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]))
/app/langchain_agents_conversational-react_memory.py:44: LangChainDeprecationWarning: Please see the migration guide at: https://python.langchain.com/docs/versions/migrating_memory/
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
/app/langchain_agents_conversational-react_memory.py:47: LangChainDeprecationWarning: The function `initialize_agent` was deprecated in LangChain 0.1.0 and will be removed in 1.0. Use :meth:`~Use new agent constructor methods like create_react_agent, create_json_agent, create_structured_chat_agent, etc.` instead.
agent = initialize_agent(
歡迎使用智慧型 AI 助手!可以進行多輪對話,並記住上下文。
隨時輸入問題,例如:『今天是幾號?』,或『你剛剛問了什麼?』
如果想結束對話,請輸入 'bye', 'exit' 或 'quit'。
請輸入您的問題:
Q: 請問今天是幾號?
AI: 今天是 2024 年 12 月 5 日,星期四。
請輸入您的問題:請問今天是幾號?
Thought: Do I need to use a tool? Yes
Action: get today date
Action Input: None今天是 2024 年 12 月 05 日,星期Thu。
Do I need to use a tool? No
AI: 今天是 2024 年 12 月 5 日,星期四。
AI 助手的回答紀錄:
{'input': '請問今天是幾號?', 'chat_history': [HumanMessage(content='請問今天是幾號?', additional_kwargs={}, response_metadata={}), AIMessage(content='今天是 2024 年 12 月 5 日,星期四。', additional_kwargs={}, response_metadata={})], 'output': '今天是 2024 年 12 月 5 日,星期四。'}
Q: 我是好崴寶Weibert Weiberson,很高興認識你, 我的ig是@weibert_coding, 我的yt是Weibert好崴寶程式, 歡迎訂閱我!
AI: 你好,好崴寶!很高興認識你。謝謝你在 Instagram 和 YouTube 上追蹤我。我希望能提供有用的資訊和見解來回答你的問題或與你進行對話。請隨時提出任何問題或讓我們討論任何主題。你今天想談什麼?
請輸入您的問題:我是好崴寶Weibert Weiberson,很高興認識你, 我的ig是@weibert_coding, 我的yt是Weibert好崴寶程式, 歡迎訂閱我!
Thought: Do I need to use a tool? No
AI: 你好,好崴寶!很高興認識你。謝謝你在 Instagram 和 YouTube 上追蹤我。我希望能提供有用的資訊和見解來回答你的問題或與你進行對話。請隨時提出任何問題或讓我們討論任何主題。你今天想談什麼?
AI 助手的回答紀錄:
{'input': '我是好崴寶Weibert Weiberson,很高興認識你, 我的ig是@weibert_coding, 我的yt是Weibert好崴寶程式, 歡迎訂閱我!', 'chat_history': [HumanMessage(content='請問今天是幾號?', additional_kwargs={}, response_metadata={}), AIMessage(content='今天是 2024 年 12 月 5 日,星期四。', additional_kwargs={}, response_metadata={}), HumanMessage(content='我是好崴寶Weibert Weiberson,很高興認識你, 我的ig是@weibert_coding, 我的yt是Weibert好崴寶程式, 歡迎訂閱我!', additional_kwargs={}, response_metadata={}), AIMessage(content='你好,好崴寶!很高興認識你。謝謝你在 Instagram 和 YouTube 上追蹤我。我希望能提供有用的資訊和見解來回答你的問題或與你進行對話。請隨時提出任何問題或讓我們討論任何主題。你今天想談什麼?', additional_kwargs={}, response_metadata={})], 'output': '你好,好崴寶!很高興認識你。謝謝你在 Instagram 和 YouTube 上追蹤我。我希望能提供有用的資訊和見解來回答你的問題或與你進行對話。請隨時提出任何問題或讓我們討論任何主題。你今天想談什麼?'}
Q: 請問你記得我的ig是多少嗎
AI: 我記得你告訴我你的 Instagram 帳號是 @weibert_coding。
請輸入您的問題:請問你記得我的ig是多少嗎
Thought: Do I need to use a tool? No
AI: 我記得你告訴我你的 Instagram 帳號是 @weibert_coding。
AI 助手的回答紀錄:
{'input': '請問你記得我的ig是多少嗎', 'chat_history': [HumanMessage(content='請問今天是幾號?', additional_kwargs={}, response_metadata={}), AIMessage(content='今天是 2024 年 12 月 5 日,星期四。', additional_kwargs={}, response_metadata={}), HumanMessage(content='我是好崴寶Weibert Weiberson,很高興認識你, 我的ig是@weibert_coding, 我的yt是Weibert好崴寶程式, 歡迎訂閱我!', additional_kwargs={}, response_metadata={}), AIMessage(content='你好,好崴寶!很高興認識你。謝謝你在 Instagram 和 YouTube 上追蹤我。我希望能提供有用的資訊和見解來回答你的問題或與你進行對話。請隨時提出任何問題或讓我們討論任何主題。你今天想談什麼?', additional_kwargs={}, response_metadata={}), HumanMessage(content='請問你記得我的ig是多少嗎', additional_kwargs={}, response_metadata={}), AIMessage(content='我記得你告訴我你的 Instagram 帳號是 @weibert_coding。', additional_kwargs={}, response_metadata={})], 'output': '我記得你告訴我你的 Instagram 帳號是 @weibert_coding。'}
Q: 你記得我的yt帳號名稱嗎
AI: 我記得你告訴我你的 YouTube 頻道名稱是 Weibert好崴寶程式。
請輸入您的問題:你記得我的yt帳號名稱嗎
Thought: Do I need to use a tool? No
AI: 我記得你告訴我你的 YouTube 頻道名稱是 Weibert好崴寶程式。
AI 助手的回答紀錄:
{'input': '你記得我的yt帳號\udce5名稱嗎', 'chat_history': [HumanMessage(content='請問今天是幾號?', additional_kwargs={}, response_metadata={}), AIMessage(content='今天是 2024 年 12 月 5 日,星期四。', additional_kwargs={}, response_metadata={}), HumanMessage(content='我是好崴寶Weibert Weiberson,很高興認識你, 我的ig是@weibert_coding, 我的yt是Weibert好崴寶程式, 歡迎訂閱我!', additional_kwargs={}, response_metadata={}), AIMessage(content='你好,好崴寶!很高興認識你。謝謝你在 Instagram 和 YouTube 上追蹤我。我希望能提供有用的資訊和見解來回答你的問題或與你進行對話。請隨時提出任何問題或讓我們討論任何主題。你今天想談什麼?', additional_kwargs={}, response_metadata={}), HumanMessage(content='請問你記得我的ig是多少嗎', additional_kwargs={}, response_metadata={}), AIMessage(content='我記得你告訴我你的 Instagram 帳號是 @weibert_coding。', additional_kwargs={}, response_metadata={}), HumanMessage(content='你記得我的yt帳號\udce5名稱嗎', additional_kwargs={}, response_metadata={}), AIMessage(content='我記得你告訴我你的 YouTube 頻道名稱是 Weibert好崴寶程式。', additional_kwargs={}, response_metadata={})], 'output': '我記得你告訴我你的 YouTube 頻道名稱是 Weibert好崴寶程式。'}
Q: 你記得我的名字嗎?
AI: 我記得你提到過你的名字是好崴寶。你還想讓我查找任何其他資訊嗎?
請輸入您的問題:你記得我的名字嗎?
Thought: Do I need to use a tool? No
AI: 我記得你提到過你的名字是好崴寶。你還想讓我查找任何其他資訊嗎?
AI 助手的回答紀錄:
{'input': '你記得我的名字嗎?', 'chat_history': [HumanMessage(content='請問今天是幾號?', additional_kwargs={}, response_metadata={}), AIMessage(content='今天是 2024 年 12 月 5 日,星期四。', additional_kwargs={}, response_metadata={}), HumanMessage(content='我是好崴寶Weibert Weiberson,很高興認識你, 我的ig是@weibert_coding, 我的yt是Weibert好崴寶程式, 歡迎訂閱我!', additional_kwargs={}, response_metadata={}), AIMessage(content='你好,好崴寶!很高興認識你。謝謝你在 Instagram 和 YouTube 上追蹤我。我希望能提供有用的資訊和見解來回答你的問題或與你進行對話。請隨時提出任何問題或讓我們討論任何主題。你今天想談什麼?', additional_kwargs={}, response_metadata={}), HumanMessage(content='請問你記得我的ig是多少嗎', additional_kwargs={}, response_metadata={}), AIMessage(content='我記得你告訴我你的 Instagram 帳號是 @weibert_coding。', additional_kwargs={}, response_metadata={}), HumanMessage(content='你記得我的yt帳號\udce5名稱嗎', additional_kwargs={}, response_metadata={}), AIMessage(content='我記得你告訴我你的 YouTube 頻道名稱是 Weibert好崴寶程式。', additional_kwargs={}, response_metadata={}), HumanMessage(content='你記得我的名字嗎?', additional_kwargs={}, response_metadata={}), AIMessage(content='我記得你提到過你的名字是好崴寶。你還想讓我查找任何其他資訊嗎?', additional_kwargs={}, response_metadata={})], 'output': '我記得你提到過你的名字是好崴寶。你還想讓我查找任何其他資訊嗎?'}
崴寶總結
本教學帶你探索如何用 LangChain Agents 構建一個超聰明的 LLM 聊天機器人!
這不僅僅是一個簡單的對話機器人,它還能記住上下文,進行多輪對話,讓你感覺像是在和一位聰明的朋友聊天!
此外,崴寶還教你如何加入一個超實用的自定義工具(例如:「今天是幾號?」)來讓它完成有趣的小任務。🥰
喜歡 好崴寶 Weibert Weiberson 的文章嗎?在這裡留下你的評論!本留言區支援 Markdown 語法。