1 概述
大語言模型雖然已經有了很多的背景知識,但針對模型訓練之後新產生的內容,或者領域內的知識進行提問,大模型本身通常無法準確給出回應,一個常用的解決方法是,藉助檢索增強生成(RAG),將能夠用於回答問題的相關上下文給到大模型,利用大模型強大的理解和生成能力,來緩解這個問題。
本文主要介紹如何藉助搜尋引擎,獲取比較新的內容,並對這部分內容的問題進行回答。首先會簡單介紹原理,然後是環境準備,程式碼介紹,最後會透過Chainlit,構造一個完整的AI搜尋問答助手,完全免費。
本文所介紹方法,不需要使用付費大語言模型API,整個流程可以在一臺膝上型電腦上執行。
程式碼已開源,地址在:https://github.com/Steven-Luo/AISearchQA
最終效果如下:
可以看出,問到一些比較新的內容時,大模型也能結合網路搜尋結果給出準確的回答。
2 基本原理
本文所介紹內容,總體依然是RAG,下面是總體處理流程,此流程圖參考此處修改而來。
AI搜尋問答並非現去網際網路爬取資料,這樣會來不及處理,通常都是藉助搜尋引擎。從搜過引擎獲取到相關文件後,後續的所有流程,就跟一般的RAG完全一致了。
3 環境準備
3.1 作業系統
本文使用的所有元件、庫,在Windows、Linux、macOS上都可以安裝,理論上在這三個系統上都可以正常執行,但沒有對所有系統做相容性測試,下文以macOS 14.4 Sonoma系統,ARM系列晶片膝上型電腦的環境為例進行介紹。
3.2 Python環境準備
推薦使用Anaconda或者Miniconda準備Python環境,具體相容的Python版本沒有做完整測試,本文所使用的是Python 3.11.4。Python安裝完成後,安裝如下依賴包:
pip install -r requirements.txt
3.3 Ollama安裝及模型下載
Ollama是一個能夠在本地執行大語言模型的應用,可以直接在命令列中進行問答互動、或者使用相應的API(本文要用到的方式),以及使用第三方GUI工具,如Lobechat等。
從Ollama官網下載並安裝對應作業系統的Ollama,Ollama詳細的安裝配置,請參考Ollama官網。
3.3.1 模型下載
Ollama安裝好之後,在命令列中,執行如下兩條命令,下載相應的大語言模型和向量模型:
ollama pull qwen:7b
ollama pull znbang/bge:large-zh-v1.5-q8_0
在Ollama官方的Models頁面,提供了非常多支援的模型,如果對相關模型比較熟,可以根據機器的配置選擇更大或更小的模型。
下載完成後,執行如下命令,進行二次確認,確保下圖中框選的部分在列表中:
ollama list
使用如下命令,檢查大語言模型是否可以正常工作:
ollama run qwen:7b
如果輸出如上圖所示內容,則說明大語言模型工作正常。輸入/exit
退出問答介面。
3.3.2 使用API
3.3.2.1 大語言模型
如果是依照本文,在本機安裝Ollama,執行如下Python程式碼:
from langchain_community.llms.ollama import Ollama
model_name = 'qwen:7b'
model = Ollama(base_url='http://localhost:11434', model=model_name)
print(model('你是誰'))
如果輸出如下內容,則表示API呼叫正常:
我是阿里雲研發的大規模語言模型,我叫通義千問。
如果Ollama安裝在其他機器,替換上述程式碼中的base_url
3.3.2.2 向量模型
類似大語言模型的部分,執行如下Python程式碼:
from langchain_community.embeddings import OllamaEmbeddings
embedding_model = OllamaEmbeddings(
base_url='http://localhost:11434',
model='znbang/bge:large-zh-v1.5-q8_0'
)
print(embedding_model.embed_query('你是誰'))
如果輸出類似如下內容,則表明向量模型API呼叫正常:
[0.8701383471488953, 0.926769495010376, ...
3.4 搜尋引擎API準備
許多搜尋引擎都有專門的API,只需要兩三行程式碼即可獲取結果,但有些需要複雜的申請流程,有些則不合規,本文使用Bing中文版網頁請求地址,藉助BeautifulSoup庫解析結果的方式,獲取Bing搜尋結果。
執行如下程式碼:
def search_with_bing(query):
import requests
from bs4 import BeautifulSoup
from urllib.parse import quote
url = f'https://cn.bing.com/search?q={quote(query)}'
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36'
}
resp = requests.get(url, headers=headers)
soup = BeautifulSoup(resp.text, 'html.parser')
result_elements = soup.select('#b_results > li')
data = []
for parent in result_elements:
if parent.select_one('h2') is None:
continue
data.append({
'title': parent.select_one('h2').text,
'abstract': parent.select_one('div.b_caption > p').text.replace('\u2002', ' '),
'link': parent.select_one('div.b_tpcn > a').get('href')
})
return data
search_with_bing('大語言模型')
如果結果類似如下所示,則表明執行成功:
[{'title': '什麼是LLM大語言模型?Large Language Model,從量變到質變',
'abstract': '網頁2023年4月17日 · 大語言模型(英文:Large Language Model,縮寫LLM),也稱大型語言模型,是一種人工智慧模型,旨在理解和生成人類語言。. 它們在大量的文字資料上進行訓練,可以執行廣泛的任務,包括文字總結、翻譯、情感分析等等。. LLM的特點是 規模龐大,包含數十億的引數 ...',
'link': 'https://zhuanlan.zhihu.com/p/622518771'},
{'title': '什麼是大模型(LLMs)?一文讀懂大型語言模型(Large ...',
'abstract': '網頁2 天之前 · 大模型是指具有大規模引數和複雜計算結構的機器學習模型。 這些模型通常由 深度神經網路 構建而成,擁有數十億甚至數千億個引數。 大模型的設計目的是為了提高模型的表達能力和預測效能,能夠處理更加複雜的任務和資料。 大模型在各種領域都有廣泛的應用,包括自然語言處理、計算機視覺、語音識別和 推薦系統 等。 大模型透過訓練海量資料 …',
'link': 'https://www.aigc.cn/large-models'},
{'title': '一文讀懂“大語言模型” - 知乎',
'abstract': '網頁2023年7月17日 · 谷歌的 Gen AI 開發工具介紹. 2、大語言模型介紹. 2.1 大語言模型的定義. 大語言模型是深度學習的分支. 深度學習是機器學習的分支,大語言模型是深度學習的分支。 機器學習是人工智慧(AI)的一個子領域,它的核心是讓計算機系統能夠透過對資料的學習來提高效能。 在機器學習中,我們不是直接程式設計告訴計算機如何完成任務,而是提供大量 …',
'link': 'https://zhuanlan.zhihu.com/p/644183721'},
...
4 主要流程
4.1 使用搜尋引擎檢索網際網路內容
使用上文提到的search_with_bing函式,直接呼叫即可
...
search_results = search_with_bing('大語言模型')
...
4.2 獲取網頁全文
此處簡潔起見,使用requests庫傳送GET請求,獲取網頁全文。
4.3 文件解析、切片、向量化及檢索
本文使用BeautifulSoup解析上文獲取到原始HTML對應的文字html。通常使用這種方式解析的HTML效果比較差,可以使用Jina Reader、Firecrawl等庫,獲得更高質量的解析結果。
...
soup = BeautifulSoup(html, 'html.parser')
item['body'] = soup.get_text()
...
下方的程式碼,會對文字進行切片,進行向量化,並使用query獲取檢索結果:
...
text_splitter = RecursiveCharacterTextSplitter(
["\n\n\n", "\n\n", "\n"],
chunk_size=400,
chunk_overlap=50
)
documents = [Document(
item['body'],
metadata={'href': item['href'], 'title': item['title']}
) for item in search_results.values()]
split_docs = text_splitter.split_documents(documents)
vectorstore = Chroma.from_documents(split_docs, embedding_model)
retriever = vectorstore.as_retriever(search_args={'k': 6})
retrieved_docs = retriever.get_relevant_documents(query)
context = '\n\n'.join([doc.page_content for doc in retrieved_docs])
4.4 Prompt構造
使用Prompt如下:
prompt = """請使用下方的上下文(<<<context>>><<</context>>>之間的部分)回答使用者問題,如果所提供的上下文不足以回答問題,請回答“我無法回答這個問題”
<<<context>>>
{context}
<<</context>>>
使用者提問:{query}
請回答:
""".format(query=query, context=context)
5執行
完整程式碼訪問https://github.com/Steven-Luo/AISearchQA獲取。
首先完成第3節中的環境準備,然後執行如下命令:
sh start.sh
出現類似如下的介面,表明啟動成功