精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

從API到Agent:萬字長文洞悉LangChain工程化設計 精華

發布于 2024-4-10 11:20
瀏覽
1收藏

我想做一個嘗試,看看能不能用盡量清晰的邏輯,給“AI外行人士”(當然,我也是)引入一下LangChain,試著從工程角度去理解LangChain的設計和使用。同時大家也可以將此文檔作為LangChain的“10分鐘快速上手”手冊,本意是希望幫助需要的同學實現AI工程的Bootstrap。

文中所有的示例代碼都已托管到GitHub:https://github.com/TuGraph-contrib/langchain-demo,喜歡實操的小伙伴可以邊閱讀,邊復現。

一、引言

1.1 什么是LangChain?

正式開始前,還是有必要從定義(What)開始。LangChain是2022年10月底,由哈佛大學的Harrison Chase發起的基于開源大語言模型的AI工程開發框架。當然也可以問一下AI:

我:LangChain是什么? 

GPT-4:LangChain 是一個開源的語言模型工具鏈框架,旨在使研究人員和開發人員能夠更輕松地構建、實驗和部署以自然語言處理(NLP)為中心的應用程序。它提供了多種組件和工具,可幫助用戶利用最近的語言模型進展,如大型 Transformer 模型等,并且可以與 Hugging Face 等平臺集成。LangChain 的核心理念是將語言模型用作協作工具,通過它,開發者可以構建出處理復雜任務的系統,并且可以高效地對接不同的數據源和應用程序接口(APIs)。這個框架試圖簡化連接不同的輸入和輸出流,以及在流中實現語言模型的過程。

顧名思義,LangChain中的“Lang”自然是指大語言模型,“Chain”即“鏈”,也就是將大模型與其他組件連接成鏈,借此構建AI工程應用。那么LangChain該如何(How)做到這一點的呢?解答這個問題之前,需要先回答什么是工程?什么是AI工程?

1.2 什么是AI工程?

我們先Review一下“工程”的百科定義:

工程是指以某組設想的目標為依據,應用有關的科學知識和技術手段,通過有組織的一群人將某個(或某些)現有實體(自然的或人造的)轉化為具有預期使用價值的人造產品過程。

其中,“目標”定義了要解決的問題域,決定了工程的頂層設計和能力邊界,同時也定義了“產品”的最終形態。提升“人”的ROI是工程設計的價值歸屬。“實體”是工程的生產材料輸入,“科學 | 技術”是工程有序運行的基礎,對它們的合理利用可以提升工程的整體產出效率。

從API到Agent:萬字長文洞悉LangChain工程化設計-AI.x社區

“工程”關鍵概念剖析

于是,我們可以這樣解讀“AI工程”中的關鍵概念:

  • 目標:待解決的特定AI用戶需求。如內容創作、智能問答、文檔摘要、圖像識別等等。
  • 人:實施AI工程的具體角色。可以是程序員,或者AI應用的研發團隊、創業公司。
  • 科學 | 技術:顯然是大模型與相關工具服務,以及其后的計算科學理論。
  • 實體:已有的文檔、知識庫、業務數據等生產材料。
  • 產品:能滿足目標需求的具體產品。如聊天機器人、內容生成工具等。

1.3 如何設計LangChain?

因此,如果我們是LangChain的設計者,希望構建通用的AI工程框架。需要回答如下問題:

  1. 【目標 | 產品】LangChain的設計目標是什么,能解決哪些AI工程問題?
  2. 【人】LangChain的編程接口如何定義,才能提升AI工程師的研發效率?
  3. 【實體 | 科學 | 技術】LangChain的核心組件如何抽象,以提升框架的擴展能力?

當然,作為“事后諸葛”,這些問題目前有比較明確的答案:

  1. 作為AI工程框架,LangChain實際是對LLM能力的擴展和補充。如果把LLM比作人的大腦,LangChain則是人的軀干和四肢,協助LLM完成“思考”之外的“臟活累活”。它的能力邊界只取決于LLM的智力水平和LangChain能提供的工具集的豐富程度。
  2. LangChain提供了LCEL(LangChain Expression Language)聲明式編程語言,降低AI工程師的研發成本。
  3. LangChain提供了Models、Prompts、Indexes、Memory、Chains、Agents六大核心抽象,用于構建復雜的AI應用,同時保持了良好的擴展能力。

很明顯,LLM作為LangChain能力的基礎,是了解LangChain工程化設計的前提。接下來我們就從最基礎的LLM API使用談起,一步步了解LangChain的工程化構建過程及其背后的設計理念。

二、環境準備

  • Python環境:建議3.8版本以上。

下載鏈接:https://www.python.org/downloads[1]

  • OpenAI SK:自備。
  • 申請地址:https://platform.openai.com/api-keys
  • 環境變量:export OPENAI_API_KEY="<Your-OpenAI-SK>"
  • 安裝LangChain:
  • 執行命令:pip install langchain langchain-openai

三、設計推演

架構設計領域有個比較流行的術語——樂高架構,當然也可以叫可插拔架構。說白就是通過對系統基本組件的合理抽象,找到構造復雜系統的統一規律和可達路徑,從而實現在降低系統實現復雜度的同時,提升系統整體的擴展性。(非官方表達,大家能Get到我的意思就好……)

LangChain實際上也遵循了樂高架構的思想。當然,作為最關鍵的樂高組件之一,LLM的能力自然是我們優先了解的對象,那我們就從OpenAI的API開始吧!

3.1 造夢基礎——API

文本生成模型服務是OpenAI提供的最核心的API服務,自ChatGPT發布后經歷過幾次版本迭代。

3.1.1 Chat Completion API

當下最新的是Chat Completion API[2],是AI與LLM交互的核心入口。

代碼示例參考:

import os
import requests


# API Key
api_key = os.getenv('OPENAI_API_KEY')


# 頭部信息
headers = {
    'Content-Type': 'application/json',
    'Authorization': f'Bearer {api_key}'
}


# 準備數據
data = {
    'model': 'gpt-4',
    'messages': [{'role': 'user', 'content': '什么是圖計算?'}],
    'temperature': 0.7
}


# 調用API
url = 'https://api.openai.com/v1/chat/completions'
response = requests.post(url, jsnotallow=data, headers=headers)
answer = response.json()['choices'][0]['message']['content']
print(answer)

代碼示例輸出:

圖計算是一種計算模型,用于處理大規模圖形結構的數據,并執行各種復雜的算法和計算。這種計算模型主要用于社交網絡分析、Web搜索、生物信息學、網絡路由優化、數據挖掘等領域。圖計算模型的核心是將數據表示為圖形結構(節點和邊),這樣可以更好地揭示數據之間的關系和互動。在圖計算中,算法通常以迭代的方式運行,每次迭代都會更新圖中節點的狀態,直到達到某種停止條件。

3.1.2 Completion API

早先的Completion API[3]已經在2023年7月后不再維護,和最新的Chat Completion API參數和結果格式有所不同,最明顯的是Prompt是以純文本方式傳遞,而非Message格式。

# 準備數據
data = {
    'model': 'gpt-3.5-turbo-instruct',
    'prompt': ['什么是圖計算?'],
    'max_tokens': 1024
}


# 調用API
url = 'https://api.openai.com/v1/completions'
response = requests.post(url, jsnotallow=data, headers=headers)
answer = response.json()['choices'][0]['text']
print(answer)

除了文本生成服務,OpenAI也提供了大量的LLM的周邊服務,以協助AI工程構建更復雜的應用能力。如:函數調用、嵌入、微調、多模態等,具體可參考OpenAI開發文檔[4]的內容。

3.2 智能開端——Chat

自2022年11月底ChatGPT發布以來,AI的大門才真正地向人類打開,其中給用戶留下最深印象的功能,自然是智能對話。OpenAI的Chat Completion API參數支持傳入消息歷史,可以輕松地實現簡單的對話服務。

代碼示例參考:

# 對話歷史
messages = []


def chat_with_ai(message):
    # 記錄歷史
    messages.append({'role': 'user', 'content': message})
    print(f'me: {message}')


    # 對話請求
    data = {
        'model': 'gpt-4',
        'messages': messages,
        'temperature': 0.7
    }
    url = 'https://api.openai.com/v1/chat/completions'
    response = requests.post(url, jsnotallow=data, headers=headers)


    # 解析回答
    if response.status_code == 200:
        answer = response.json()['choices'][0]['message']['content']
        messages.append({'role': 'assistant', 'content': answer})
        print(f"ai: {answer}")
    else:
        print(f'Error: {response.status_code}', response.json())


# 多輪對話
chat_with_ai('什么是圖計算?')
chat_with_ai('剛才我問了什么問題?')

代碼示例輸出:

me: 什么是圖計算?ai: 圖計算是一種計算模型,用于處理大規模圖形結構數據的計算和分析。在這種計算模型中,數據被表示為圖形,其中節點代表實體,邊代表實體之間的關系。圖計算可以用于解決許多實際問題,如社交網絡分析、網絡路由、生物信息學等。圖計算的主要挑戰是如何有效地處理大規模的圖形數據,并提供快速的計算和分析結果。me: 剛才我問了什么問題?ai: 你問的問題是:“什么是圖計算?”

3.3 初步封裝——SDK

到目前為止,我們還只是用OpenAI最原始的RESTful API構建LLM工程能力,甚至連OpenAI提供的SDK都未使用。顯然這不是一個高效的方式,使用前邊安裝的LangChain-OpenAI集成包langchain-openai可以大大降低代碼的開發成本。

代碼示例參考:

from langchain_openai import ChatOpenAI


# 調用Chat Completion API
llm = ChatOpenAI(model_name='gpt-4')
response = llm.invoke('什么是圖計算?')
print(response)

代碼示例輸出:

cnotallow='圖計算是一種計算模型,主要用于處理圖形結構數據的計算和分析。圖計算的對象是圖,圖由節點和邊組成,節點代表實體對象,邊代表實體對象之間的關系。圖計算主要用于解決實體關系復雜、關系密集的問題,如社交網絡分析、網絡拓撲分析、推薦系統等。圖計算的主要任務是通過對圖中節點和邊的計算,發現和提取出圖中隱含的知識和信息。'

3.4 數據抽象——IO

對于文本生成模型服務來說,實際的輸入和輸出本質上都是字符串,因此直接裸調用LLM服務帶來的問題是要在輸入格式化和輸出結果解析上做大量的重復的文本處理工作。LangChain當然考慮到這一點,提供了Prompt[5]和OutputParser[6]抽象,用戶可以根據自己的需要選擇具體的實現類型使用。

從API到Agent:萬字長文洞悉LangChain工程化設計-AI.x社區

IO數據抽象示意

代碼示例參考:

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI


# 創建LLM
llm = ChatOpenAI(model_name='gpt-4')


# 創建Prompt
prompt = ChatPromptTemplate.from_template("{question}")


# 創建輸出解析器
output_parser = StrOutputParser()


# 調用LLM
message = prompt.invoke({'question': '什么是圖計算?'})
response = llm.invoke(message)
answer = output_parser.invoke(response)
print(answer)

3.5 組裝成鏈——Chain

模型的IO組件確實可以減少重復的文本處理工作,但形式上依然不夠清晰,這里就引入了LangChain中的關鍵概念:鏈(Chain)。

3.5.1 HelloWorld

LangChain的表達式語言(LCEL[7])通過重載__or__運算符的思路,構建了類似Unix管道運算符的設計,實現更簡潔的LLM調用形式。

代碼示例參考:

# 創建Chain
chain = prompt | llm | output_parser


# 調用Chain
answer = chain.invoke({'question': '什么是圖計算?'})
print(answer)

至此,我們終于看到了LangChain版的“HelloWorld”……

3.5.2 RunnablePassthrough

當然,為了簡化Chain的參數調用格式,也可以借助RunnablePassthrough透傳上游參數輸入。

代碼示例參考:

from langchain_core.runnables import RunnablePassthrough


# 創建Chain
chain = {"question": RunnablePassthrough()} | prompt | llm | output_parser


# 調用Chain
answer = chain.invoke('什么是圖計算?')
print(answer)

3.5.3 DAG

另外,Chain也可以分叉、合并,組合出更復雜的DAG計算圖結構。

代碼示例參考:

from operator import itemgetter


from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI


# 創建LLM
llm = ChatOpenAI(model_name='gpt-4')


# 創建輸出解析器
output_parser = StrOutputParser()


# 創建Prompt
topic_prompt = ChatPromptTemplate.from_template("生成一種'{input}'的名稱")
good_prompt = ChatPromptTemplate.from_template("列舉{topic}的好處:")
bad_prompt = ChatPromptTemplate.from_template("列舉{topic}的壞處:")
summary_prompt = ChatPromptTemplate.from_messages(
    [
        ("ai", "{topic}"),
        ("human", "好處:\n{good}\n\n壞處:\n{bad}"),
        ("system", "生成最終結論"),
    ]
)


# 創建組合Chain
topic_chain = topic_prompt | llm | output_parser | {"topic": RunnablePassthrough()}
goods_chain = good_prompt | llm | output_parser
bads_chain = bad_prompt | llm | output_parser
summary_chain = summary_prompt | llm | output_parser
chain = (
    topic_chain
    | {
        "good": goods_chain,
        "bad": bads_chain,
        "topic": itemgetter("topic"),
    }
    | summary_chain
)


# 調用chain
answer = chain.invoke({"input": '常見水果'})
print(answer)

代碼示例輸出:

蘋果是一種營養豐富的水果,具有幫助消化、保護心臟、降低糖尿病風險、強化免疫系統、幫助減肥、保護視力、預防哮喘、抗癌和提升記憶力等多種好處。然而,過度食用或者不適當的食用方式也可能帶來一些不利影響,如引發過敏、導致腹瀉、對牙齒造成傷害、可能攜帶農藥殘留、影響正常飲食和鈣質吸收、增加蛀牙風險和引發胃痛等。因此,我們在享受蘋果帶來的好處的同時,也需要注意適量和正確的食用方式。

通過調用chain.get_graph().print_ascii()可以查看Chain的計算圖結構。當然,使用LangSmith能更清晰的跟蹤每一步的計算結果。

從API到Agent:萬字長文洞悉LangChain工程化設計-AI.x社區

LangChain的計算圖與Trace

Tips:開啟LangSmith需要申請LangChain的AK[8],并配置環境變量:

export LANGCHAIN_TRACING_V2="true"

export LANGCHAIN_API_KEY="<Your-LangChain-AK>"

3.5.4 LangGraph

基于LCEL確實能描述比較復雜的LangChain計算圖結構,但依然有DAG天然的設計限制,即不能支持“循環”。于是LangChain社區推出了一個新的項目——LangGraph[9],期望基于LangChain構建支持循環和跨多鏈的計算圖結構,以描述更復雜的,甚至具備自動化屬性的AI工程應用邏輯,比如智能體應用。其具體使用方式可以參考LangGraph文檔[10]。

LangGraph聲稱其設計理念受Pregel/Beam的啟發,構建支持多步迭代的計算能力,這部分設計理念和我們設計的支持“流/批/圖”計算一體化的圖計算引擎TuGraph也十分相似,感興趣的朋友可以訪問TuGraph Analytics[11]項目進行學習。

3.6 開啟記憶——Memory

通過Chain,LangChain相當于以“工作流”的形式,將LLM與IO組件進行了有秩序的連接,從而具備構建復雜AI工程流程的能力。而我們都知道LLM提供的文本生成服務本身不提供記憶功能,需要用戶自己管理對話歷史。因此引入Memory組件[12],可以很好地擴展AI工程的能力邊界。

從API到Agent:萬字長文洞悉LangChain工程化設計-AI.x社區

帶記憶的問答處理

3.6.1 Memory接口

LangChain的BaseMemory接口提供了Memory的統一抽象(截至v0.1.12還是Beta版本),提供了多種類型的Memory組件的實現,我們選用最簡單的ConversationBufferMemory實現類型。

需要注意的是,要將Memory組件應用到Chain上,需要使用子類LLMChain進行創建Chain。

代碼示例參考:

from langchain.chains import LLMChain
from langchain.memory import ConversationBufferMemory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder, \
    HumanMessagePromptTemplate
from langchain_openai import ChatOpenAI


# 創建LLM
llm = ChatOpenAI(model_name='gpt-4')


# 創建Prompt
prompt = ChatPromptTemplate.from_messages([
    MessagesPlaceholder(variable_name='chat_history'),
    HumanMessagePromptTemplate.from_template('{question}')
])


# 創建Memory
memory = ConversationBufferMemory(memory_key='chat_history',
                                  return_messages=True)
# 創建LLMChain
llm_chain = LLMChain(llm=llm, memory=memory, prompt=prompt)


# 調用LLMChain
print(llm_chain.predict(questinotallow='什么是圖計算?'))
print(llm_chain.predict(questinotallow='剛才我問了什么問題?'))

代碼示例輸出:

圖計算是一種計算類型,主要處理的數據結構是圖。圖是由節點(或頂點)和邊組成的,節點代表實體,邊代表實體之間的關系。在圖計算中,主要解決的問題是如何在圖的結構上進行有效的計算和分析。你問的問題是:“什么是圖計算?”

這里可以看到,創建帶Memory功能的Chain,并不能使用統一的LCEL語法。調用LLMChain使用的是predict而非invoke方法,直接調用invoke會返回一個LLMResult類型的結果。因此,LLMChain也不能使用管道運算符接StrOutputParser。這些設計上的問題,個人推測也是目前Memory模塊還是Beta版本的原因之一吧。

3.6.2 History接口

但是,LangChain提供了工具類RunnableWithMessageHistory,支持了為Chain追加History的能力,從某種程度上緩解了上述問題。不過需要指定Lambda函數get_session_history以區分不同的會話,并需要在調用時通過config參數指定具體的會話ID。

SessionHistory必須是History接口類型BaseChatMessageHistory,用戶可以根據需要選擇不同的存儲實現。這里為了簡化,全局只用了一份內存類型的ChatMessageHistory。

代碼示例參考:

from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder, \
    HumanMessagePromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_openai import ChatOpenAI


# 創建LLM
llm = ChatOpenAI(model_name='gpt-4')


# 創建輸出解析器
output_parser = StrOutputParser()


# 創建Prompt
prompt = ChatPromptTemplate.from_messages([
    MessagesPlaceholder(variable_name="chat_history"),
    HumanMessagePromptTemplate.from_template("{question}")
])


# 創建Chain
chain = prompt | llm | output_parser


# 添加History
history = ChatMessageHistory()
chain_with_history = RunnableWithMessageHistory(
    chain,
    lambda session_id: history,
    input_messages_key="question",
    history_messages_key="chat_history",
)


# 調用Chain
print(chain_with_history.invoke({'question': '什么是圖計算?'},
                                cnotallow={"configurable": {"session_id": None}}))
print(chain_with_history.invoke({'question': '剛才我問了什么問題?'},
                                cnotallow={"configurable": {"session_id": None}}))

調用形式看起來是復雜了一些,不過代碼結構相比Memory組件更清晰一些,聊勝于無……

3.7 消除幻覺——RAG

擁有記憶后,確實擴展了AI工程的應用場景。但是在專有領域,LLM無法學習到所有的專業知識細節,因此在面向專業領域知識的提問時,無法給出可靠準確的回答,甚至會“胡言亂語”,這種現象稱之為LLM的“幻覺”。

檢索增強生成(RAG)把信息檢索技術和大模型結合起來,將檢索出來的文檔和提示詞一起提供給大模型服務,從而生成更可靠的答案,有效的緩解大模型推理的“幻覺”問題。

如果說LangChain相當于給LLM這個“大腦”安裝了“四肢和軀干”,RAG則是為LLM提供了接入“人類知識圖書館”的能力。

從API到Agent:萬字長文洞悉LangChain工程化設計-AI.x社區

基于RAG的問答處理流程

相比提示詞工程,RAG有更豐富的上下文和數據樣本,可以不需要用戶提供過多的背景描述,即能生成比較符合用戶預期的答案。相比于模型微調,RAG可以提升問答內容的時效性和可靠性,同時在一定程度上保護了業務數據的隱私性。

但由于每次問答都涉及外部系統數據檢索,因此RAG的響應時延相對較高。另外,引用的外部知識數據會消耗大量的模型Token資源。因此,用戶需要結合自身的實際應用場景做合適的技術選型。

從API到Agent:萬字長文洞悉LangChain工程化設計-AI.x社區

大語言模型優化技術

借助LCEL提供的RunnableParallel可以清晰描述RAG的計算圖結構,其中最關鍵的部分是通過context鍵注入向量存儲(Vector Store)的查詢器(Retriever)。

代碼示例參考:

from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores.faiss import FAISS
from langchain_core.documents import Document
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import OpenAIEmbeddings, ChatOpenAI


# 創建LLM
llm = ChatOpenAI(model_name='gpt-4')


# 創建Prompt
prompt = ChatPromptTemplate.from_template('基于上下文:{context}\n回答:{input}')


# 創建輸出解析器
output_parser = StrOutputParser()


# 模擬文檔
docs = [Document(page_cnotallow="TuGraph是螞蟻開源的圖數據庫產品")]


# 文檔嵌入
splits = RecursiveCharacterTextSplitter().split_documents(docs)
vector_store = FAISS.from_documents(splits, OpenAIEmbeddings())
retriever = vector_store.as_retriever()


# 創建Chain
chain_no_context = RunnablePassthrough() | llm | output_parser
chain = (
    {"context": retriever, "input": RunnablePassthrough()}
    | prompt | llm | output_parser
)


# 調用Chain
print(chain_no_context.invoke('螞蟻圖數據庫開源了嗎?'))
print(chain.invoke('螞蟻圖數據庫開源了嗎?'))

代碼示例輸出:

螞蟻圖數據庫目前沒有公開信息表明已經開源。開源狀態可能會隨時間和公司政策變化,建議直接查閱螞蟻集團或相關開源平臺的官方信息獲取最新和準確的消息。是的,螞蟻的圖數據庫產品TuGraph是開源的。

從API到Agent:萬字長文洞悉LangChain工程化設計-AI.x社區

向量存儲的寫入與查詢

結合示例和向量數據庫的存取過程,我們簡單理解一下RAG中關鍵組件。

  • DocumentLoader:從外部系統檢索文檔數據。簡單起見,示例中直接構造了測試文檔對象。實際上LangChain提供了文檔加載器BaseLoader的接口抽象和大量實現,具體可根據自身需要選擇使用。
  • TextSplitter:將文檔分割成塊,以適應大模型上下文窗口。示例中采用了常用的RecursiveCharacterTextSplitter,其他參考LangChain的TextSplitter接口和實現。
  • EmbeddingsModel:文本嵌入模型,提供將文本編碼為向量的能力。文檔寫入和查詢匹配前都會先執行文本嵌入編碼。示例采用了OpenAI的文本嵌入模型服務[13],其他參考LangChain的Embeddings接口和實現。
  • VectorStore:向量存儲,提供向量存儲和相似性檢索(ANN算法)能力。LangChain支持的向量存儲參考VectorStore接口和實現。示例采用了Meta的Faiss[14]向量數據庫,本地安裝方式:pip install faiss-cpu。需要額外提及的是,對于圖數據庫,可以將相似性搜索問題轉化為圖遍歷問題,并具備更強的知識可解釋性。螞蟻開源的TuGraph數據庫[15]目前正在做類似的技術探索。
  • Retriever:向量存儲的查詢器。一般和VectorStore配套實現,通過as_retriever方法獲取,LangChain提供的Retriever抽象接口是BaseRetriever

3.8 使用工具——Tool

“會使用工具”是人類和動物的根本區別。

要構建更強大的AI工程應用,只有生成文本這樣的“紙上談兵”能力自然是不夠的。工具不僅僅是“肢體”的延伸,更是為“大腦”插上了想象力的“翅膀”。借助工具,才能讓AI應用的能力真正具備無限的可能,才能從“認識世界”走向“改變世界”。

這里不得不提到OpenAI的Chat Completion API提供的函數調用[16]能力(注意這里不是Assistant的函數調用[17]),通過在對話請求內附加tools參數描述工具的定義格式(原先的functions參數已過期),LLM會根據提示詞推斷出需要調用哪些工具,并提供具體的調用參數信息。用戶需要根據返回的工具調用信息,自行觸發相關工具的回調。下一章內容我們可以看到工具的調用動作可以通過Agent自主接管。

從API到Agent:萬字長文洞悉LangChain工程化設計-AI.x社區

LLM Tools執行流程示意

為了簡化代碼實現,我們用LangChain的注解@tool[18]定義了一個測試用的“獲取指定城市的當前氣溫”的工具函數。然后通過bind_tools方法綁定到LLM對象即可。需要注意的是這里需要用JsonOutputToolsParser解析結果輸出。

代碼示例參考:

import random


from langchain_core.output_parsers.openai_tools import JsonOutputToolsParser
from langchain_core.runnables import RunnablePassthrough
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI




# 定義Tool
@tool
def get_temperature(city: str) -> int:
    """獲取指定城市的當前氣溫"""
    return random.randint(-20, 50)




# 創建LLM
llm = ChatOpenAI(model_name='gpt-4')


# 創建JSON輸出解析器
output_parser = JsonOutputToolsParser()


# 創建Chain
chain = (
    RunnablePassthrough()
    | llm.bind_tools(tools=[get_temperature])
    | output_parser
)


# 調用Chain
print(chain.invoke('杭州今天多少度?'))

代碼示例輸出:

[{'type': 'get_temperature', 'args': {'city': '杭州'}}]

實際上LangChain提供了大量的內置工具和工具庫的支持。@tool只是提供了簡潔的工具創建的支持,要定制復雜的工具行為需要自行實現BaseTool工具接口。同時工具庫接口BaseToolkit下也有大量的實現,如向量存儲、SQL數據庫、GitHub等等。用戶可以根據自身需求選用或自行擴展。

3.9 走向智能——Agent

通用人工智能(AGI)將是AI的終極形態,幾乎已成為業界共識。類比之,構建智能體(Agent)則是AI工程應用當下的“終極形態”。

3.9.1 什么是Agent?

引用LangChain中Agent的定義,可以一窺Agent與Chain的區別。

Agent的核心思想是使用大型語言模型(LLM)來選擇要采取的行動序列。在Chain中行動序列是硬編碼的,而Agent則采用語言模型作為推理引擎來確定以什么樣的順序采取什么樣的行動。

Agent相比Chain最典型的特點是“自治”,它可以通過借助LLM專長的推理能力,自動化地決策獲取什么樣的知識,采取什么樣的行動,直到完成用戶設定的最終目標。

從API到Agent:萬字長文洞悉LangChain工程化設計-AI.x社區

LangChain Agent工作流程示意圖

因此,作為一個智能體,需要具備以下核心能力:

  • 規劃:借助于LLM強大的推理能力,實現任務目標的規劃拆解和自我反思。
  • 記憶:具備短期記憶(上下文)和長期記憶(向量存儲),以及快速的知識檢索能力。
  • 行動:根據拆解的任務需求正確地調用工具以達到任務的目的。
  • 協作:通過與其他智能體交互合作,完成更復雜的任務目標。

Agent的核心能力

3.9.2 構建智能體

我們使用Agent繼續完成前邊Tool部分沒有完成的例子。這里使用create_openai_tools_agent方法創建一個簡單的OpenAI工具Agent,AgentExecutor會自動接管工具調用的動作。如果希望給Agent添加記憶能力,依然可以采用前邊Memory章節提過的RunnableWithMessageHistory的方案[19]。

代碼示例參考:

import random


from langchain.agents import create_openai_tools_agent, \
    AgentExecutor
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder, \
    HumanMessagePromptTemplate, SystemMessagePromptTemplate
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI


# 創建LLM
llm = ChatOpenAI()


# 定義Tool
@tool
def get_temperature(city: str) -> int:
    """獲取指定城市的當前氣溫"""
    return random.randint(-20, 50)




# 創建Agent提示詞模板
prompt = ChatPromptTemplate.from_messages([
    SystemMessagePromptTemplate.from_template('You are a helpful assistant'),
    MessagesPlaceholder(variable_name='chat_history', optinotallow=True),
    HumanMessagePromptTemplate.from_template('{input}'),
    MessagesPlaceholder(variable_name='agent_scratchpad')
])


# 創建Agent
tools = [get_temperature]
agent = create_openai_tools_agent(llm, tools, prompt=prompt)


# 執行Agent
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
print(agent_executor.invoke({'input': '今天杭州多少度?'})['output'])

代碼示例輸出:

> Entering new AgentExecutor chain... Invoking: get_temperature with {'city': 'Hangzhou'} 16 今天杭州的氣溫是16度。

> Finished chain. 今天杭州的氣溫是16度。

需要補充說明的是,LangChain提供了Hub[20]功能,幫助大家管理共享Agent的提示詞模板。上述示例代碼的Agent提示詞模板和hwchase17/openai-tools-agent[21]的定義等價。

通過代碼prompt = hub.pull("hwchase17/openai-tools-agent")可以直接引用創建prompt。

hwchase17/openai-tools-agent的定義

四、LangChain架構

從API到Agent,我們“腦暴”了一個完整AI工程應用的發展軌跡,借此我相信大家對LangChain的設計理念應該有了進一步的理解。

最后,我們再看一眼LangChain的產品架構。除了本文未介紹的LangServe——將Chain部署為RESTful服務,其他不再贅述。

從API到Agent:萬字長文洞悉LangChain工程化設計-AI.x社區

LangChain產品架構

五、尾記

可能會有小伙伴疑問,為啥我一個搞圖計算的,在這搗鼓起AI工具來了。拋開“擁抱行業,跟進趨勢”這樣的大口號不談,單純從工作需要角度,使用AI工具加速內容的產出,本身就可以幫助我節省大量的時間和精力,空出的“閑暇”時間去帶娃也是極好的……

線上關于LangChain的文章,雖不說汗牛充棟,但也能隨手拈來。作為“后入場”者,我過去從事了多年的數倉、中臺、云產品的架構和研發,最近兩三年一直在搞圖計算這樣的基礎軟件,就想試試結合自身多面的工程經驗去理解LangChain背后的設計理念,給大家一個別樣的視角去觀察、體驗和思考AI工程。這兩天被“AI程序員”的新聞刷屏了,其中引用的Adam Rackis的一條Twitter令我感受頗深:“做好磨練和深入學習的準備,熟練地引導人工智能取得好的結果可能才是未來程序員能體現出來的價值。”,或許這正是AI工程的用武之地吧。

參考資料:

1. Retrieval-Augmented Generation for Large Language Models: A Survey:https://arxiv.org/abs/2312.10997

2. Chain-of-Thought Prompting Elicits Reasoning in Large Language Models:https://arxiv.org/pdf/2201.11903.pdf

3. Tree of Thoughts: Deliberate Problem Solving with Large Language Models:https://arxiv.org/pdf/2305.10601.pdf

4. ReAct: Synergizing Reasoning and Acting in Language Models:https://arxiv.org/abs/2210.03629

5. API-Bank: A Comprehensive Benchmark for Tool-Augmented LLMs:https://arxiv.org/abs/2304.08244

6. LangChain Docs:https://python.langchain.com/

7. OpenAI Docs:https://platform.openai.com/docs

8. LangGraph Docs:https://python.langchain.com/docs/langgraph

9. LangChain:[https://github.com/langchain-ai/langchain]

10. LangGraph:[https://github.com/langchain-ai/langgraph]

11. TuGraph Analytics:https://github.com/TuGraph-family/tugraph-analytics

12. TuGraph DB:https://github.com/TuGraph-family/tugraph-db

13. Langchain-Chatchat:https://github.com/chatchat-space/Langchain-Chatchat

14. LLM Powered Autonomous Agents:https://lilianweng.github.io/posts/2023-06-23-agent/

15. Emerging Architectures for LLM Applications:https://a16z.com/emerging-architectures-for-llm-applications/

16. Prompt Engineering Guide:https://www.promptingguide.ai/

17. Bond Copilot: Unleashing Refinitiv Data Library Search API with AI (LLM) :https://developers.lseg.com/en/article-catalog/article/bond-copilot--unleashing-rd-lib-search-api-with-ai-llm-langchain

引用鏈接:

[1] https://www.python.org/downloads: https://www.python.org/downloads/
[2] Chat Completion API: https://platform.openai.com/docs/api-reference/chat
[3] Completion API: https://platform.openai.com/docs/api-reference/completions
[4] OpenAI開發文檔: https://platform.openai.com/docs
[5] Prompt: https://python.langchain.com/docs/modules/model_io/prompts/
[6] OutputParser: https://python.langchain.com/docs/modules/model_io/output_parsers/
[7] LCEL: https://python.langchain.com/docs/expression_language/
[8] AK: https://smith.langchain.com/settings
[9] LangGraph: https://github.com/langchain-ai/langgraph
[10] LangGraph文檔: https://python.langchain.com/docs/langgraph
[11] TuGraph Analytics: https://github.com/TuGraph-family/tugraph-analytics
[12] Memory組件: https://python.langchain.com/docs/modules/memory/
[13] 文本嵌入模型服務: https://platform.openai.com/docs/guides/embeddings
[14] Faiss: https://github.com/facebookresearch/faiss
[15] TuGraph數據庫: https://github.com/TuGraph-family/tugraph-db
[16] 函數調用: https://platform.openai.com/docs/guides/function-calling
[17] Assistant的函數調用: https://platform.openai.com/docs/assistants/tools/function-calling
[18] @tool: https://python.langchain.com/docs/modules/agents/tools/custom_tools#tool-decorator
[19] RunnableWithMessageHistory的方案: https://python.langchain.com/docs/modules/agents/quick_start#adding-in-memory
[20] Hub: https://smith.langchain.com/hub/
[21] hwchase17/openai-tools-agent: https://smith.langchain.com/hub/hwchase17/openai-tools-agent

本文轉載自??阿里云開發者??,作者:范志東 ????

已于2024-4-10 18:09:21修改
收藏 1
回復
舉報
回復
相關推薦
666欧美在线视频| 国产亚洲自拍一区| 久久久久久久久久av| 久久久国产精品久久久| 啊啊啊久久久| 久久久久久99久久久精品网站| 国产成人精品电影| 人妻人人澡人人添人人爽| 在线一区二区三区视频| 色综合久久久久久久久久久| 亚洲国产精品一区在线观看不卡| 精品国产av一区二区三区| 亚洲高清激情| 色噜噜狠狠狠综合曰曰曰| 先锋资源在线视频| 日韩经典一区| 亚洲一区自拍偷拍| 亚洲日本欧美在线| 亚欧洲精品视频| 精品在线一区二区| 欧日韩在线观看| 中文字幕手机在线观看| 国产精品羞羞答答在线观看| 日韩欧美区一区二| 宅男噜噜噜66国产免费观看| 蜜臀av国内免费精品久久久夜夜| 国产欧美久久久精品影院| 97久久天天综合色天天综合色hd| 337p粉嫩色噜噜噜大肥臀| 欧美日韩网站| 久久久精品国产网站| 欧美做受xxxxxⅹ性视频| 97视频一区| 欧美性色综合网| 337p粉嫩大胆噜噜噜鲁| 肉肉视频在线观看| 日韩一区中文字幕| 亚洲v日韩v欧美v综合| 午夜福利视频一区二区| 国产69精品久久久久777| 91精品久久久久久久| 91黑人精品一区二区三区| 夜夜嗨网站十八久久| 久久69精品久久久久久久电影好| 日本美女bbw| 国产欧美日韩| 亚洲欧美日韩精品久久亚洲区 | 日韩一区不卡| 天堂中文在线资源| 成人午夜在线免费| 97人人模人人爽人人少妇| 国产精品久久777777换脸| 日韩va亚洲va欧美va久久| 日本一区二区三区四区视频| 日本一级黄色录像| 伊人久久综合| 久久久久久久一| 久久精品99国产精| 国产精品chinese| 欧美激情一区二区久久久| 亚洲欧美小视频| 一区二区三区中文| 欧美大尺度在线观看| 国产大片免费看| 午夜亚洲福利| 午夜精品久久久久久99热| 国产精品9191| 国产精品女主播一区二区三区 | sis001欧美| 日韩欧美在线观看视频| 欧美少妇性生活视频| 日韩成人亚洲| 欧美高清你懂得| 手机看片国产精品| 加勒比色综合久久久久久久久 | 北岛玲日韩精品一区二区三区| 久久久精品综合| 日本一区视频在线观看| 国产对白叫床清晰在线播放| 国产精品美女久久久久久久网站| 一区二区日本伦理| 欧美女同一区| 欧美日韩免费看| 少妇黄色一级片| 国产精品一区二区精品视频观看| 日韩免费看网站| 亚洲综合自拍网| 国产伦精品一区二区三区视频| 最近中文字幕日韩精品| 国产性xxxx| 亚洲永久在线| 国产脚交av在线一区二区| 一区二区三区精| 不卡一区二区三区四区| 日本精品视频一区| 午夜av在线播放| 色婷婷综合久久久中文一区二区 | 国产电影一区二区三区爱妃记| 欧美剧情片在线观看| 成人做爰www看视频软件| 久久99国产成人小视频| 久久国内精品一国内精品| 亚洲一区 视频| 日韩电影免费一区| 97自拍视频| 国产高清视频在线观看| 亚洲一区二区三区四区五区中文| 成人在线观看a| 中文久久电影小说| 中文字幕视频一区二区在线有码| 久久久精品99| 久久精品国产一区二区三区免费看| 97视频资源在线观看| 国产高清在线看| 亚洲一级片在线观看| 精品999在线| 久久人人爽人人爽人人片av不| 中文字幕亚洲字幕| 久久久久久久久久免费视频| 黄网站免费久久| 欧美一级二级三级九九九| 香蕉成人app免费看片| 日本韩国欧美一区二区三区| 人妻 丝袜美腿 中文字幕| 青青草97国产精品麻豆| 欧美性受xxx| 免费观看毛片网站| 亚洲精品成人精品456| 亚洲三级视频网站| 女厕嘘嘘一区二区在线播放| 久久久久中文字幕| 国产极品999| 中文字幕制服丝袜成人av| 免费裸体美女网站| 高清精品xnxxcom| 欧美巨乳美女视频| 国产又粗又大又爽视频| 日本一区二区在线不卡| 久久美女福利视频| 欧美丝袜足交| 国内外成人免费激情在线视频| 国产裸体无遮挡| 国产精品久久久久影院色老大 | 中文有码久久| 99久久er| 色综合亚洲精品激情狠狠| 国产熟妇一区二区三区四区| 91丨porny丨蝌蚪视频| 国产69精品久久久久999小说| 婷婷综合国产| 精品视频9999| 囯产精品一品二区三区| 一区二区三区在线视频免费| 国产91在线免费观看| 中文视频一区| av一区二区三区免费| 亚洲丝袜精品| 亚洲а∨天堂久久精品9966| 国产性70yerg老太| 波多野洁衣一区| 免费av观看网址| 伊人春色之综合网| 国产精品高清网站| 自拍视频在线| 欧美一三区三区四区免费在线看 | 国产区高清在线| 91久久精品网| 青青青视频在线播放| 久久av资源站| av动漫在线免费观看| 91久久精品无嫩草影院| 97精品在线视频| 理论在线观看| 欧美日韩一区二区不卡| 在线观看黄网址| 国产精品一卡二| 国产69精品久久久久999小说| 欧美大胆视频| 国产精品久久久久久久久久新婚 | 少妇一级淫片免费看| 精品国产乱码久久久久久天美 | 国产精品影院在线观看| 看黄网站在线观看| 日韩欧美国产高清| 久久99精品波多结衣一区| 欧美激情一区二区在线| 午夜免费福利网站| 99精品视频免费观看视频| 欧美不卡在线一区二区三区| 精品美女一区| 欧美国产日韩精品| 日韩大胆人体| 欧美一级一级性生活免费录像| 国产污视频在线观看| 欧美激情在线看| 色综合久久久无码中文字幕波多| 中文一区在线| 免费看av软件| 丝袜av一区| 川上优av一区二区线观看| www.youjizz.com在线| 色小说视频一区| 日韩中文字幕影院| 欧美视频一区二区三区四区| 久草视频手机在线观看| 国产女同互慰高潮91漫画| 91精产国品一二三| 免费人成在线不卡| 老太脱裤子让老头玩xxxxx| 四季av在线一区二区三区| 国产女主播一区二区| 日韩一级特黄| 日本成人在线视频网址| 影音先锋在线播放| 综合久久五月天| 色资源在线观看| 精品日韩一区二区| 国产精品毛片一区二区在线看舒淇| 天天亚洲美女在线视频| 亚洲二区在线播放| 国产视频一区二区在线| 波多野结衣加勒比| 国产美女av一区二区三区| 爆乳熟妇一区二区三区霸乳| 国语自产精品视频在线看8查询8| 亚洲国产精品www| 亚洲福利天堂| 国产无套精品一区二区| 精品一区二区三区亚洲| 国产精品久久久久91| 都市激情亚洲一区| 欧美国产精品va在线观看| 欧美午夜电影一区二区三区| 亚洲网站在线观看| 亚洲欧美日韩综合在线| 精品国产网站在线观看| 国产探花精品一区二区| 欧美日韩精品一二三区| 波多野结衣激情视频| 欧美日韩国产一中文字不卡| 国产主播在线观看| 亚洲欧美电影院| 波多野结衣喷潮| 国产精品亲子伦对白| 亚洲人成人无码网www国产| 99精品视频一区二区三区| 日韩成人av影院| 国产激情视频一区二区在线观看| 青青草久久伊人| 九九九久久久精品| 男生操女生视频在线观看| 麻豆91在线观看| wwwwwxxxx日本| 蜜桃久久久久久| 午夜在线观看av| 久久国产精品区| 在线观看免费不卡av| 韩国理伦片一区二区三区在线播放| 黄色aaa级片| 裸体在线国模精品偷拍| 亚洲午夜精品一区| 国产精品1024久久| 精品伦一区二区三区| 成人黄色综合网站| 无码精品一区二区三区在线播放 | 亚洲国产av一区| 国产日韩欧美综合在线| 阿v天堂2014| 亚洲色图欧美在线| 久久机热这里只有精品| 懂色av影视一区二区三区| 黄色在线视频网址| 欧美在线三级电影| 国产日产亚洲系列最新| 精品日产卡一卡二卡麻豆| 人成网站在线观看| 亚洲欧美日韩高清| 日本天堂在线观看| 欧美激情伊人电影 | 一本一本大道香蕉久在线精品| 日本免费在线观看视频| 欧美日韩dvd在线观看| www.精品视频| 日韩精品中文字幕有码专区| 在线观看完整版免费| 久久99精品视频一区97| 樱花草涩涩www在线播放| 国产精品日韩精品| 8848成人影院| 色一情一区二区三区四区| 91不卡在线观看| 97成人在线免费视频| 免费在线观看视频一区| 国产污在线观看| 欧美国产一区二区在线观看| 高h视频免费观看| 日韩欧美黄色动漫| 999免费视频| 亚洲区免费影片| 怡红院av在线| 国产成人精品久久亚洲高清不卡| 日韩成人视屏| 亚洲精品美女久久7777777| 亚洲区第一页| 亚洲一二三av| 国产亚洲一区二区三区在线观看| 国产精品久久久久久久精| 91九色最新地址| 国产综合视频在线| 日韩一区二区久久久| 在线天堂资源| 国产精品一区二区三区四区五区| 日韩理论电影大全| 黄色片视频在线免费观看| 国产乱人伦偷精品视频不卡 | 日韩69视频在线观看| 综合久久成人| 亚洲 欧洲 日韩| 日本午夜一区二区| 亚洲第一黄色网址| 亚洲一卡二卡三卡四卡五卡| 国产精品久久久久久久一区二区| 亚洲男人天堂视频| 九色porny视频在线观看| 99国精产品一二二线| 亚洲国产一区二区在线观看| 天天干天天干天天干天天干天天干| 91片黄在线观看| 国产污视频在线观看| 欧美va在线播放| 日本三级在线观看网站| 亚洲精品免费在线视频| 99久久99久久精品国产片果冰| 国产精品久久久久9999小说| 91在线视频播放地址| 可以在线观看av的网站| 精品播放一区二区| 羞羞的网站在线观看| 成人激情视频在线观看| 欧美精选一区二区三区| 久久国产亚洲精品无码| 99精品偷自拍| 国产网友自拍视频| 日韩av网址在线观看| 福利成人导航| 国产一区免费视频| 欧美成人精品| 国产艳妇疯狂做爰视频| 一区二区三区在线视频免费| 国产五月天婷婷| 亚洲国产精品va在看黑人| 在线观看电影av| 99理论电影网| 欧美久久视频| 国产a级黄色片| 亚洲成人激情av| 精品国产一级片| 久久久久久97| 国产精品任我爽爆在线播放| 黄色一级片在线看| 成人免费毛片嘿嘿连载视频| 日本道在线观看| 国产视频丨精品|在线观看| 成人免费影院| 日韩三级电影免费观看| 日韩高清不卡一区| 精品在线观看一区| 欧美一区二区久久| 91福利在线尤物| 裸体丰满少妇做受久久99精品| 丝袜诱惑制服诱惑色一区在线观看| 最新中文字幕视频| 欧美日韩高清一区二区| 免费观看在线黄色网| 国产精品入口日韩视频大尺度| 久久久久av| 亚洲精品成人无码毛片| 欧美日韩在线一区| 韩国福利在线| 99久久99久久| 在线一区欧美| 国产又色又爽又高潮免费| 欧美一区二区三区在线电影| 电影在线观看一区| 欧美一卡2卡3卡4卡无卡免费观看水多多 | 久久精品www| 日韩av影视在线| 影视一区二区三区| 777久久精品一区二区三区无码| 成人激情av网| 中文字幕第2页| 九色精品美女在线| 精品成人影院| 日本一区二区三区在线免费观看| 精品国产999| 黄色网址在线免费| 蜜桃91精品入口| 国产主播一区二区三区| 亚洲av中文无码乱人伦在线视色| 综合国产在线视频|