LangChain的Agent使用介紹

LangChain

LangChain 介紹

隨著各種開源大模型的發(fā)布崖媚,越來越多的人開始嘗試接觸和使用大模型痒玩。在感嘆大模型帶來的驚人表現(xiàn)的同時愤估,也發(fā)現(xiàn)一些問題嵌牺,比如沒法查詢到最新的信息打洼,有時候問一些數(shù)學問題時候,會出現(xiàn)錯誤答案逆粹,還有一些專業(yè)領(lǐng)域類問題甚至編造回答等等募疮。有沒有什么辦法能解決這些問題呢?答案就是LangChain枯饿。

LangChain 是一個開源的語言模型集成框架酝锅,旨在簡化使用大型語言模型(LLM)創(chuàng)建應(yīng)用程序的過程。利用它可以讓開發(fā)者使用語言模型來實現(xiàn)各種復(fù)雜的任務(wù)奢方,例如文本到圖像的生成搔扁、文檔問答、聊天機器人蟋字、調(diào)用特定的SaaS服務(wù)等等稿蹲。隨著ChatGPT、midjourney等AI技術(shù)的爆火鹊奖,LangChain也是在短時間內(nèi)得到6w+的star數(shù)苛聘,版本迭代也是異常的快,社區(qū)十分活躍忠聚。

LangChain 在沒有任何收入也沒有任何明顯的創(chuàng)收計劃的情況下设哗,獲得了 1000 萬美元的種子輪融資和 2000-2500 萬美元的 A 輪融資,估值達到 2 億美元左右两蟀。

LangChain架構(gòu)圖

上面是LangChain的核心架構(gòu)圖网梢,可以看到LangChain主要包含如下模塊:

  • Model I/O:大模型的輸入輸出,包含提示詞赂毯、任何大模型战虏、結(jié)果解析器拣宰。
  • Retrieval:涉及到數(shù)據(jù)集相關(guān),主要包含文檔提取器烦感、文檔轉(zhuǎn)換器巡社、向量數(shù)據(jù)庫等。
  • Chains:允許將多個不同組件組合在一起使用手趣,形成鏈條式調(diào)用晌该。
  • Memory:在大模型調(diào)用期間提供存儲能力。
  • Agents:鏈式調(diào)用是硬編碼的回懦,而代理是由大模型根據(jù)實時情況來決定如何調(diào)用工具气笙。
  • Callbacks:大模型各個階段的的回調(diào)系統(tǒng),對于日志記錄怯晕、監(jiān)控潜圃、流傳輸和其他任務(wù)非常有用。

Agent

大模型一般只擁有他們被訓練的知識舟茶,這種知識可能很快就會過時了谭期,所以在推理的時候大模型與外界是處于“斷開”狀態(tài)。為了克服這一限制吧凉,LangChain在Yao等人在2022年11月提出的推理和行動(ReAct)框架上提出了“代理”(Agent)的解決方案隧出。此方案可以獲取最新的數(shù)據(jù),并將其作為上下文插入到提示中阀捅。Agent也可以用來采取行動(例如胀瞪,運行代碼,修改文件等)饲鄙,然后該行動的結(jié)果可以被LLM觀察到凄诞,并被納入他們關(guān)于下一步行動的決定。

運行大體流程: 1用戶給出一個任務(wù)(Prompt) -> 2思考(Thought) -> 3行動(Action) -> 4觀察(Observation)忍级,
然后循環(huán)執(zhí)行上述 2-4 的流程帆谍,直到大模型認為找到最終答案為止。

Agent內(nèi)部具體拆解:


Agent結(jié)構(gòu)圖

使用Agent有兩個必備條件:相關(guān)能力工具和對這些工具的正確描述轴咱。

定義工具

工具的定義只需要集成BaseTool類汛蝙,然后在_run方法中編寫你的邏輯就行,大模型會把合適的參數(shù)傳進來朴肺。
需要定義類變量有:

  • name: 工具名稱窖剑,很重要,大模型內(nèi)部會使用到
  • description:工具描述戈稿,很重要苛吱,告知大模型在什么情況下來使用這個工具
  • return_direct:這個字段默認為false,如果設(shè)置為true器瘪,工具返回結(jié)果后翠储,大模型就不再循環(huán)思考了會直接將這個結(jié)果當做答案。

LangChain 已經(jīng)內(nèi)置了 duckduckgo 搜索引擎橡疼,pip install duckduckgo-search安裝一下依賴包即可使用援所,只是需要科學上網(wǎng)才能調(diào)通。

下面是我定義的兩個工具欣除,一個用于電影搜索住拭,一個用于數(shù)學計算:

from langchain.tools import BaseTool, DuckDuckGoSearchRun

# 搜索工具
class SearchTool(BaseTool):
    name = "Search"
    description = "當問電影相關(guān)問題時候,使用這個工具"
    return_direct = False  # 直接返回結(jié)果

    def _run(self, query: str) -> str:
        print("\n正在調(diào)用搜索引擎執(zhí)行查詢: " + query)
        search = DuckDuckGoSearchRun()
        return search.run(query)

# 計算工具
class CalculatorTool(BaseTool):
    name = "Calculator"
    description = "如果問數(shù)學相關(guān)問題時历帚,使用這個工具"
    return_direct = False  # 直接返回結(jié)果

    def _run(self, query: str) -> str:
        return eval(query)

定義結(jié)果解析類

每次大模型輸出之后滔岳,都會對結(jié)果進行解析,如果找到action就會去調(diào)用挽牢。但是默認的解析類我測試的時候總報錯谱煤,所以我改寫了一下:

from typing import Dict, Union, Any, List

from langchain.output_parsers.json import parse_json_markdown
from langchain.agents.conversational_chat.prompt import FORMAT_INSTRUCTIONS
from langchain.agents import AgentExecutor, AgentOutputParser
from langchain.schema import AgentAction, AgentFinish

# 自定義解析類
class CustomOutputParser(AgentOutputParser):

    def get_format_instructions(self) -> str:
        return FORMAT_INSTRUCTIONS

    def parse(self, text: str) -> Union[AgentAction, AgentFinish]:
        print(text)
        cleaned_output = text.strip()
        # 定義匹配正則
        action_pattern = r'"action":\s*"([^"]*)"'
        action_input_pattern = r'"action_input":\s*"([^"]*)"'
        # 提取出匹配到的action值
        action = re.search(action_pattern, cleaned_output)
        action_input = re.search(action_input_pattern, cleaned_output)
        if action:
            action_value = action.group(1)
        if action_input:
            action_input_value = action_input.group(1)
        
        # 如果遇到'Final Answer',則判斷為本次提問的最終答案了
        if action_value and action_input_value:
            if action_value == "Final Answer":
                return AgentFinish({"output": action_input_value}, text)
            else:
                return AgentAction(action_value, action_input_value, text)

        # 如果聲明的正則未匹配到禽拔,則用json格式進行匹配
        response = parse_json_markdown(text)
        
        action_value = response["action"]
        action_input_value = response["action_input"]
        if action_value == "Final Answer":
            return AgentFinish({"output": action_input_value}, text)
        else:
            return AgentAction(action_value, action_input_value, text)
output_parser = CustomOutputParser()

初始化Agent

如果你使用ChatGPT的話刘离,這里需要配置ChatGPT的api-key,同時需要科學上網(wǎng)睹栖。也可以配置一些本地的開源大模型硫惕,比如ChatGLM2-6BBaichuan-13B等野来,但是效果確實要比ChatGPT差很多恼除。

from langchain.memory import ConversationBufferMemory
from langchain.agents.conversational_chat.base import ConversationalChatAgent 
from langchain.agents import AgentExecutor, AgentOutputParser

SYSTEM_MESSAGE_PREFIX = """盡可能用中文回答以下問題。您可以使用以下工具"""

# 初始化大模型實例曼氛,可以是本地部署的豁辉,也可是是ChatGPT
# llm = ChatGLM(endpoint_url="http://你本地的實例地址")
llm = ChatOpenAI(openai_api_key="sk-xxx", model_name='gpt-3.5-turbo', request_timeout=60)
# 初始化工具
tools = [CalculatorTool(), SearchTool()]
# 初始化對話存儲,保存上下文
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
# 配置agent
chat_agent = ConversationalChatAgent.from_llm_and_tools(
    system_message=SYSTEM_MESSAGE_PREFIX, # 指定提示詞前綴
    llm=llm, tools=tools, memory=memory, 
    verbose=True, # 是否打印調(diào)試日志搪锣,方便查看每個環(huán)節(jié)執(zhí)行情況
    output_parser=output_parser # 
)
agent = AgentExecutor.from_agent_and_tools(
    agent=chat_agent, tools=tools, memory=memory, verbose=True,
    max_iterations=3 # 設(shè)置大模型循環(huán)最大次數(shù)秋忙,防止無限循環(huán)
)

調(diào)用Agent

調(diào)用就很簡單了,執(zhí)行agent.run(prompt)即可构舟,下面是一個詳細的調(diào)用日志輸出:

執(zhí)行結(jié)果

日志已經(jīng)完整的體現(xiàn)出了整個流程灰追,大模型的確每次都匹配到了正確的tool。如果還覺得日志不詳細狗超,可以設(shè)置langchain.debug = True弹澎,這樣會打印更詳細日志。

總結(jié)

可以這么理解Agent努咐,它讓大模型變成了一個決策者苦蒿。用戶的問題首先由它去理解和拆分,它來從工具列表中找到覺得合適的工具渗稍,然后將用戶的提問信息轉(zhuǎn)化成結(jié)構(gòu)化的數(shù)據(jù)佩迟,當成參數(shù)傳遞給工具函數(shù)团滥。工具函數(shù)返回結(jié)果又交還給了大模型去觀察分析,如果它覺得不是正確答案报强,那么繼續(xù)這個循環(huán)直到得出它認為的正確答案灸姊。

它就像是一個優(yōu)秀的項目經(jīng)理,分解用戶的問題秉溉,可能他不擅長完成某一項任務(wù)力惯,但是他能找到合適專業(yè)的外部的人去完成子任務(wù),最后他再匯總?cè)蝿?wù)結(jié)果交付給用戶召嘶。

優(yōu)點

  • 框架層上來說父晶,對大模型的有更系統(tǒng)化的干預(yù)機制,方便集成弄跌。
  • 拓展了大模型更多的能力甲喝,而且是不需要經(jīng)過復(fù)雜且昂貴的訓練過程。
  • 不用再去寫那些匹配場景的規(guī)則了碟绑,大模型已經(jīng)幫你做了俺猿,前提是這個模型參數(shù)要夠大,能理解用戶的意思格仲。
  • 整個流程都有詳細的記錄日志押袍,方便調(diào)試。

不足

  • 大模型會被多次調(diào)用凯肋,響應(yīng)用戶的時間可能會比較久谊惭,因此相應(yīng)產(chǎn)品也就會限制在一些特定領(lǐng)域。
  • 雖然不用寫工具匹配規(guī)則侮东,但是這也讓這一塊邏輯變成一個黑盒了圈盔,很難去精準的匹配或者調(diào)試。
  • 對大模型本身能力要求很高悄雅,如果使用低參數(shù)大模型驱敲,很有可能無法識別問題并正確的分發(fā)給對應(yīng)工具。

當然還是有優(yōu)化的方向的:比如可以考慮去使用語料專門往解析action方面訓練宽闲,讓模型能更好的解析出action众眨。

引用鏈接:

  1. Introduction | ????? Langchain
  2. 【LangChain】模塊架構(gòu)解析:一圖帶你了解 LangChain 的內(nèi)部結(jié)構(gòu)!
  3. Prophet-Andrew-Ng/langchain/李魯魯學LangChain 11.md
  4. 面向開發(fā)者的 LLM 入門教程
  5. 我為什么放棄了 LangChain容诬? - 知乎 (zhihu.com)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末娩梨,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子览徒,更是在濱河造成了極大的恐慌狈定,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件习蓬,死亡現(xiàn)場離奇詭異纽什,居然都是意外死亡措嵌,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門芦缰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來铅匹,“玉大人,你說我怎么就攤上這事饺藤。” “怎么了流礁?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵涕俗,是天一觀的道長。 經(jīng)常有香客問我神帅,道長再姑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任找御,我火速辦了婚禮元镀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘霎桅。我一直安慰自己栖疑,他們只是感情好,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布滔驶。 她就那樣靜靜地躺著遇革,像睡著了一般。 火紅的嫁衣襯著肌膚如雪揭糕。 梳的紋絲不亂的頭發(fā)上萝快,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天,我揣著相機與錄音著角,去河邊找鬼揪漩。 笑死,一個胖子當著我的面吹牛吏口,可吹牛的內(nèi)容都是我干的奄容。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼锨侯,長吁一口氣:“原來是場噩夢啊……” “哼嫩海!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起囚痴,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤叁怪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后深滚,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奕谭,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡涣觉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了血柳。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片官册。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖难捌,靈堂內(nèi)的尸體忽然破棺而出膝宁,到底是詐尸還是另有隱情,我是刑警寧澤根吁,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布员淫,位于F島的核電站,受9級特大地震影響击敌,放射性物質(zhì)發(fā)生泄漏介返。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一沃斤、第九天 我趴在偏房一處隱蔽的房頂上張望圣蝎。 院中可真熱鬧,春花似錦衡瓶、人聲如沸徘公。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽步淹。三九已至,卻和暖如春诚撵,著一層夾襖步出監(jiān)牢的瞬間缭裆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工寿烟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留澈驼,地道東北人。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓筛武,卻偏偏與公主長得像缝其,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子徘六,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容