
如何快速實現REST API集成以優化業務流程
agent = initialize_agent(
tools, # 配置工具集
llm, # 配置大語言模型 負責決策
agent=AgentType.OPENAI_FUNCTIONS, # 設置 agent 類型
agent_kwargs=agent_kwargs, # 設定 agent 角色
verbose=True,
memory=memory, # 配置記憶模式 )
首先是配置工具集 Tools,代碼如下:可以看到這是一個二元數組,也就意味著本示例中的 Agent 依賴兩個工具。
from langchain.agents import initialize_agent, Tool
tools = [
Tool(
name="search",
func=search,
description="useful for when you need to answer questions about current events, data. You should ask targeted questions"
),
ScrapeWebsiteTool(),
]
先看第一個工具:在配置工具時,需要聲明工具依賴的函數,由于該示例實現的功能為依賴網絡收集相應的信息,然后匯總成一篇論文,所以創建了一個 search 函數,這個函數用于調用 Google 搜索。它接受一個查詢參數,然后將查詢發送給Serper API。API 的響應會被打印出來并返回。
# 調用 Google search by Serper
def search(query):
serper_google_url = os.getenv("SERPER_GOOGLE_URL")
payload = json.dumps({
"q": query
})
headers = {
'X-API-KEY': serper_api_key,
'Content-Type': 'application/json'
}
response = requests.request("POST", serper_google_url, headers=headers, data=payload)
print(f'Google 搜索結果: \n {response.text}')
return response.text
再來看一下所依賴的第二個工具函數,這里用了另一種聲明工具的方式 Class ?聲明:ScrapeWebsiteTool(),它有以下幾個屬性和方法:
class ScrapeWebsiteTool(BaseTool):
name = "scrape_website"
description = "useful when you need to get data from a website url, passing both url and objective to the function; DO NOT make up any url, the url should only be from the search results"
args_schema: Type[BaseModel] = ScrapeWebsiteInput
def _run(self, target: str, url: str):
return scrape_website(target, url)
def _arun(self, url: str):
raise NotImplementedError("error here")
name:工具的名稱,這里是 “scrape_website”;description:工具的描述;args_schema:工具的參數模式,這里是 ScrapeWebsiteInput 類,表示這個工具需要的輸入參數,聲明代碼如下,這是一個基于 Pydantic 的模型類,用于定義 scrape_website 函數的輸入參數。它有兩個字段:target 和 url,分別表示用戶給Agent 的目標和任務以及需要被爬取的網站的 URL。
class ScrapeWebsiteInput(BaseModel):
"""Inputs for scrape_website"""
target: str = Field(
description="The objective & task that users give to the agent")
url: str = Field(description="The url of the website to be scraped")
_run 方法:這是工具的主要執行函數,它接收一個目標和一個 URL 作為參數,然后調用 scrape_website 函數來爬取網站并返回結果。scrape_website 函數根據給定的目標和 URL 爬取網頁內容。首先,它發送一個 HTTP 請求來獲取網頁的內容。如果請求成功,它會使用 BeautifulSoup 庫來解析 HTML 內容并提取文本。如果文本長度超過 5000 個字符,它會調用 summary 函數來對內容進行摘要。否則,它將直接返回提取到的文本。其代碼如下:
# 根據 url 爬取網頁內容,給出最終解答
# target :分配給 agent 的初始任務
# url :Agent 在完成以上目標時所需要的URL,完全由Agent自主決定并且選取,其內容或是中間步驟需要,或是最終解答需要
def scrape_website(target: str, url: str):
print(f"開始爬取: {url}...")
headers = {
'Cache-Control': 'no-cache',
'Content-Type': 'application/json',
}
payload = json.dumps({
"url": url
})
post_url = f"https://chrome.browserless.io/content?token={browserless_api_key}"
response = requests.post(post_url, headers=headers, data=payload)
# 如果返回成功
if response.status_code == 200:
soup = BeautifulSoup(response.content, "html.parser")
text = soup.get_text()
print("爬取的具體內容:", text)
# 控制返回內容長度,如果內容太長就需要切片分別總結處理
if len(text) > 5000:
# 總結爬取的返回內容
output = summary(target, text)
return output
else:
return text
else:
print(f"HTTP請求錯誤,錯誤碼為{response.status_code}")
從上述代碼中我們可以看到其還依賴一個 summary 函數,用此函數解決內容過長的問題,這個函數使用 Map-Reduce 方法對長文本進行摘要。它首先初始化了一個大語言模型(llm),然后定義了一個大文本切割器(text_splitter)。接下來,它創建了一個摘要鏈(summary_chain),并使用這個鏈對輸入文檔進行摘要。
# 如果需要處理的內容過長,先切片分別處理,再綜合總結
# 使用 Map-Reduce 方式
def summary(target, content):
# model list :https://platform.openai.com/docs/models
# gpt-4-32k gpt-3.5-turbo-16k-0613
llm = ChatOpenAI(temperature=0, model="gpt-3.5-turbo-16k-0613")
# 定義大文本切割器
# chunk_overlap 是一個在使用 OpenAI 的 GPT-3 或 GPT-4 API 時可能會遇到的參數,特別是需要處理長文本時。
# 該參數用于控制文本塊(chunks)之間的重疊量。
# 上下文維護:重疊確保模型在處理后續塊時有足夠的上下文信息。
# 連貫性:它有助于生成更連貫和一致的輸出,因為模型可以“記住”前一個塊的部分內容。
text_splitter = RecursiveCharacterTextSplitter(
separators=["\n\n", "\n"], chunk_size=5000, chunk_overlap=200)
docs = text_splitter.create_documents([content])
map_prompt = """
Write a summary of the following text for {target}:
"{text}"
SUMMARY:
"""
map_prompt_template = PromptTemplate(
template=map_prompt, input_variables=["text", "target"])
summary_chain
# 初始化大語言模型,負責決策
llm = ChatOpenAI(temperature=0, model="gpt-3.5-turbo-16k-0613")
這段代碼初始化了一個名為 llm 的大語言模型對象,它是 ChatOpenAI 類的實例。ChatOpenAI 類用于與大語言模型(如GPT-3)進行交互,以生成決策和回答。在初始化 ChatOpenAI 對象時,提供了以下參數:
temperature:一個浮點數,表示生成文本時的溫度。溫度值越高,生成的文本將越隨機和多樣;溫度值越低,生成的文本將越確定和一致。在這里設置為 0,因為本 Demo 的目的為生成一個論文,所以我們并不希望大模型有較多的可變性,而是希望生成非常確定和一致的回答。
model:一個字符串,表示要使用的大語言模型的名稱。在這里,我們設置為 “gpt-3.5-turbo-16k-0613″,表示使用 GPT-3.5 Turbo 模型。
首先來看一下 AgentType 這個變量的初始化,這里是用來設置 Agent 類型的一個參數,具體可以參考官網:AgentType, 如下所示:
可以看到官網里列舉了7種 Agent 類型,可以根據自己的需求進行選擇,在本示例中選用的是第一種類型 OpenAI functions。此外,還要設定 Agent 角色以及記憶模式:
# 初始化agents的詳細描述
system_message = SystemMessage(
content="""您是一位世界級的研究員,可以對任何主題進行詳細研究并產生基于事實的結果;
您不會憑空捏造事實,您會盡最大努力收集事實和數據來支持研究。
請確保按照以下規則完成上述目標:
1/ 您應該進行足夠的研究,盡可能收集關于目標的盡可能多的信息
2/ 如果有相關鏈接和文章的網址,您將抓取它以收集更多信息
3/ 在抓取和搜索之后,您應該思考“根據我收集到的數據,是否有新的東西需要我搜索和抓取以提高研究質量?”如果答案是肯定的,繼續;但不要進行超過5次迭代
4/ 您不應該捏造事實,您只應該編寫您收集到的事實和數據
5/ 在最終輸出中,您應該包括所有參考數據和鏈接以支持您的研究;您應該包括所有參考數據和鏈接以支持您的研究
6/ 在最終輸出中,您應該包括所有參考數據和鏈接以支持您的研究;您應該包括所有參考數據和鏈接以支持您的研究"""
)
# 初始化 agent 角色模板
agent_kwargs = {
"extra_prompt_messages": [MessagesPlaceholder(variable_name="memory")],
"system_message": system_message,
}
# 初始化記憶類型
memory = ConversationSummaryBufferMemory(
memory_key="memory", return_messages=True, llm=llm, max_token_limit=300)
在設置 agent_kwargs 時:”extra_prompt_messages”:這個鍵對應的值是一個包含 MessagesPlaceholder 對象的列表。這個對象的 variable_name 屬性設置為 “memory”,表示我們希望在構建 Agent 的提示詞時,將 memory 變量的內容插入到提示詞中。”system_message”:這個鍵對應的值是一個 SystemMessage 對象,它包含了 Agent 的角色描述和任務要求。
# 初始化記憶類型
memory = ConversationSummaryBufferMemory(
memory_key="memory", return_messages=True, llm=llm, max_token_limit=300)
在設置memory 的記憶類型對象時:利用了 ConversationSummaryBufferMemory 類的實例。該類用于在與 AI 助手的對話中緩存和管理信息。在初始化這個對象時,提供了以下參數:memory_key:一個字符串,表示這個記憶對象的鍵。在這里設置為 “memory”;return_messages:一個布爾值,表示是否在返回的消息中包含記憶內容。在這里設置為 True,表示希望在返回的消息中包含記憶內容;llm:對應的大語言模型對象,這里是之前初始化的 llm 對象。這個參數用于指定在處理記憶內容時使用的大語言模型;max_token_limit:一個整數,表示記憶緩存的最大令牌限制。在這里設置為 300,表示希望緩存的記憶內容最多包含 300 個 token。
這里導入所需庫:這段代碼導入了一系列所需的庫,包括 os、dotenv、langchain相關庫、requests、BeautifulSoup、json 和 streamlit。
import os
from dotenv import load_dotenv
from langchain import PromptTemplate
from langchain.agents import initialize_agent, Tool
from langchain.agents import AgentType
from langchain.chat_models import ChatOpenAI
from langchain.prompts import MessagesPlaceholder
from langchain.memory import ConversationSummaryBufferMemory
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains.summarize import load_summarize_chain
from langchain.tools import BaseTool
from pydantic import BaseModel, Field
from langchain.schema import SystemMessage
from typing import Type
from bs4 import BeautifulSoup
import requests
import json
import streamlit as st
# 加載必要的參數
load_dotenv()
serper_api_key=os.getenv("SERPER_API_KEY")
browserless_api_key=os.getenv("BROWSERLESS_API_KEY")
openai_api_key=os.getenv("OPENAI_API_KEY")
main 函數:這是 streamlit 應用的主函數。它首先設置了頁面的標題和圖標,然后創建了一些 header,并提供一個文本輸入框讓用戶輸入查詢。當用戶輸入查詢后,它會調用 Agent 來處理這個查詢,并將結果顯示在頁面上。
def main():
st.set_page_config(page_title="AI Assistant Agent", page_icon=":dolphin:")
st.header("LangChain 實例講解 3 -- Agent", divider='rainbow')
st.header("AI Agent :blue[助理] :dolphin:")
query = st.text_input("請提問題和需求:")
if query:
st.write(f"開始收集和總結資料 【 {query}】 請稍等")
result = agent({"input": query})
st.info(result['output'])
至此 Agent 的使用示例代碼就描述完畢了,我們可以看到,其實 Agent 的功能就是其會自主的去選擇并利用最合適的工具,從而解決問題,我們提供的 Tools 豐富,則其功能越強大。
文章轉自微信公眾號@玄姐聊AGI