如何構建自己的 LLM 聊天機器人

自 OpenAI 發佈 ChatGPT 以來,生成式 AI 領域已經有了巨大的發展。現在,有大量的開源模型和工具供我們使用。本文旨在向你展示生成式 AI 是如何讓我們生成令人驚歎的內容的。即使你的編碼經驗很基礎,也有可能利用 LLM 創建你的自定義聊天機器人。

在本文中,我們將深入探討與 LLM 工作時經常遇到的專業術語和工具。此外,我們還將使用 Meta 發佈的高性能開源 LLM LLaMa-2,來製作一個簡易的定製化聊天機器人。

Google Colab 鏈接:

https://colab.research.google.com/drive/1MRJRPjlhuGOxltMSdJ_VORNZJJsd7Wp3?usp=sharing

什麼是生成式 AI?

“生成式 AI” 這個詞最近變得炙手可熱,但它和普通的 AI 有什麼不同?在以前,人們通常使用 AI 來分析大量的數據並進行深入的預測,這更確切地被稱爲預測式 AI。

生成式 AI 的核心在於生成全新的內容,無論是文本、圖像、音頻等。以文本生成爲例,ChatGPT 是一個典型代表;在圖像生成領域,DALL·E 是一個很受歡迎的工具。

在這篇文章裏,我們將重點探討由所謂的 LLM 驅動的文本生成技術。

大語言模型(LLM

大語言模型(LLM)是通過深度學習算法,在龐大的文本數據集上訓練出來的 AI 模型。本質上,LLM 旨在仿照人類的語言表達和書寫,其學習方式與兒童學習語言頗爲相似:都是通過分析語義結構、語言用法和相似性來掌握。

以下是幾個知名的 LLM:

這些基礎的 LLM 都是在互聯網上的大量文本資料上進行預訓練的。爲了讓 LLM 能夠回答那些它最初未接受訓練的內容,有兩種主流方法:精細調整(fine-tuning)和上下文注入(context injection)。

精細調整與上下文注入

精細調整是一種策略,通過在新數據上對預訓練的 LLM 進行二次訓練來實施。此過程能夠爲特定任務(例如情感分析或增強預測能力)優化 LLM。在這種再訓練過程中,模型的神經網絡權重和偏置會基於新數據進行更新。但精細調整的缺陷在於它可能代價高昂、耗時,並需要大量計算資源。

上下文注入(也被稱爲實時場景學習)則是一個重點放在如何使用輸入到 LLM 的提示的策略。而不是改變 LLM,相關的上下文信息直接被融入到這些提示中。這樣,LLM 可以利用這些提示中的上下文信息來作出迴應。

儘管每種方法都有其特殊的適用場景和優勢,但對新手來說,上下文注入往往更爲簡便。在這篇文章中,我們將重點討論涉及上下文注入的相關項目。

上下文注入的一般步驟

上圖對上下文注入基礎知識做了很好的展示。我們可以將上下文注入的流程簡要總結爲:

  1. 收集你想讓 LLM 回答的結構或非結構數據。

  2. 通過加載數據(文本加載器)和對其進行標記(文本分割器)來處理這些數據。Token 通常是一個短字符串,一般長度爲 4 個字符。例如,“generative” 這個詞可能被分割爲 “ge”、“n”、“erat” 和 “ive” 這些 Token。LLM 以 Token 方式處理數據。

  3. Token 將被送入一個 Embedding 模型,此模型會將 Token 轉化爲向量嵌入。Embedding 是單詞和句子在向量空間中的表示方式。(下一部分將深入解釋此點)

  4. Embedding 模型生成的向量會被存儲在向量數據庫中。在我們的例子裏,我們使用的是 ChromaDB。

  5. 接下來是關鍵部分。當用戶提問時,我們會將他們的查詢轉化爲向量,並在數據庫中查找與其最相近的向量。從本質上說,這個步驟會找到與用戶查詢最匹配的文本段,並將其轉化迴文本。

  6. 用戶的問題及與之相關的文本段(上下文)會被整合到一個提示模板中,再提交給 LLM。而不對原始 LLM 進行任何修改,模型就可以利用這注入的上下文爲查詢提供精確答案。

Embedding 模型和向量數據庫

Embedding 模型是一種神經網絡,它能將單詞和句子及其間的關係轉化爲向量。

高維向量可能如此表示:[1, 0.2, 0.6, 2.0, …]

向量倉庫(也稱爲向量數據庫)能存儲大量的向量數據,特別適合於搜索和提取向量。

選擇的 Embedding 模型類型對上下文注入 LLM 的結果質量有顯著影響。低維度的 Embedding 模型在將自然語言轉化爲向量時可能不夠準確。這可能對用戶的查詢和數據庫中的向量之間的相似度搜索造成影響。因此,建議嘗試不同的 Embedding 模型以找到最佳結果。

市面上有很多 Embedding 模型,如 Word2Vec。但在本文中,我們將採用 OpenAI 的 Embedding 模型,即 “text-embedding-ada-002”,其輸出維度爲 1536。需要注意的是,OpenAI 的 Embedding 模型是收費的,但好消息是 Ada 模型是其提供的最爲經濟的選項,且非常適合我們的項目。

費用是基於 Embedding 模型處理的 Token 數量計算的。

LangChain 框架

LangChain 是一個強大的框架,專門用於開發受語言模型支持的應用。它包含了許多工具,可以有效整合 LLM 應用的各個方面,如文檔加載、向量數據庫和 LLM。LangChain 可以支持多種 LLM 和結構化或非結構化的數據類型。我們也將利用 LangChain 來設計我們 LLM 聊天機器人所需的提示模板。

至此,我們具備了使用自定義知識庫構建首個 LLM 聊天機器人所需的所有工具和知識。讓我們開始行動!

使用自定義知識庫構建 LLM 聊天機器人

我們可以利用 Google Colab 筆記本來搭建我們的聊天機器人。在這個示例中,我會創建一個在線香水公司的客服聊天機器人。你可以根據需要加入你的個性化數據。

在這個教程裏,我們會使用 HuggingFace 平臺上的 “meta-llama/Llama-2–7b-chat-hf” 模型。這個來自 Meta 的 7 億參數的模型是 LLaMa-2 系列中最小的一個。如果你還沒有 HuggingFace 賬戶,需要註冊一個。接着,前往 “Settings” > “Access Tokens” 並生成一個新 Token。

請確保保管好這個訪問 Token。

現在,在 Google Colab 中新建一個筆記本,並將其運行時環境設置爲 GPU T4。

首先,我們得安裝一些必要的依賴。

!pip install -q transformers einops accelerate langchain bitsandbytes
!pip install -qqq openai
!pip install -Uqqq chromadb

現在我們可以導入所需的包了。

import os
import textwrap

import langchain
import chromadb
import transformers
import openai
import torch

from transformers import AutoTokenizer
from langchain import HuggingFacePipeline
from langchain.text_splitter import CharacterTextSplitter
from langchain.document_loaders.csv_loader import CSVLoader
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate

我們之前生成的 HuggingFace 訪問 Token 現在將派上用場。我們需要通過 HuggingFace CLI 登錄才能訪問 “meta-llama/Llama-2–7b-chat-hf”。

!huggingface-cli login

輸出如下所示:

現在我們需要生成一個 OpenAI API 鑰匙。首先,你需要在 OpenAI 上註冊賬號。點擊你的用戶資料並選擇 “View API Keys”。在此處,你能夠生成一個私密的 API 鑰匙。確保立刻進行復制,因爲這個鑰匙只能被查看一次!

我們將使用此 OpenAI API 鑰匙來設置我們的環境變量,從而可以訪問 OpenAI 的 Embedding 模型。

os.environ["OPENAI_API_KEY"] = "INSERT_YOUR_API_KEY"

爲了建立 LLaMa-2 7B 模型,我們需要使用 LangChain 的 HuggingFace Pipeline 並初始化 LLM。我們需要定義模型和標記器來配置管道。

#Set up HuggingFace Pipeline with Llama-2-7b-chat-hf model
model = "meta-llama/Llama-2-7b-chat-hf"
tokenizer = AutoTokenizer.from_pretrained(model)
pipeline = transformers.pipeline(
      "text-generation"#task
      model=model,
      tokenizer=tokenizer,
      torch_dtype=torch.bfloat16,
      trust_remote_code=True,
      device_map="auto",
      max_length=1000,
      do_sample=True,
      top_k=10,
      num_return_sequences=1,
      eos_token_id=tokenizer.eos_token_id
)

#LLM intialized in HuggingFace Pipeline wrapper
llm = HuggingFacePipeline(pipeline = pipeline, model_kwargs = {'temperature':0})

這段代碼可能需要幾分鐘才能運行。結果如下:

現在我們可以加載我們的數據了。我們將使用 LangChain 的 CSVLoader 來加載一個包含我們自定義知識庫數據的 CSV 文件。儘管 LangChain 支持 ExcelLoader 這樣的文檔加載器,但爲了簡單起見,我們會在一個電子表格中創建一個簡短的問題和答案列表,並將其轉換爲 CSV 文件。

以下是我的 Excel 數據的樣子:

在你的 Google Colab 筆記本中,單擊左側的文件圖標並上傳 CSV 文件。右鍵單擊你上傳的文件並複製其文件路徑。現在我們可以使用 LangChain 的 CSVLoader 通過提供本地文件路徑來加載我們的 CSV 文件。我們還可以打印加載的 CSV 文件第一行的輸出,以查看數據的樣子。

# Load documents locally as CSV
loader = CSVLoader('YOUR_CSV_FILE_PATH')
docs = loader.load()
docs[0]

#Output: 
#Document(page_content='\ufeffQuestion: What types of fragrances do you offer in perfumes?\nAnswer: We sell exotic Indian fragrances, Earthy, Herbal & Spicy Fragrances, Fresh And Floral Fragrances, Specialty Fragrances, Musk & Amber Fragrances, and Warm & Woody Fragrances.', metadata={'source': '/content/sample_data/Fragrances-Dataset.csv', 'row': 0})

爲了讓 Embedding 模型爲我們的數據創建向量表示,我們必須對其進行標記化處理。本質上,我們是將文本分割成文本塊。

# Split document into text chunks
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.split_documents(docs)

我們將使用的 Embedding 模型是 OpenAI 的 Ada 模型,稱爲 “text-embedding-ada-002”。

# Initialize the open-source embedding function, default: text-embedding-ada-002
embedding_function = OpenAIEmbeddings()

Embedding 模型會幫助我們把 Token 轉化爲向量,並保存在一個名爲 ChromaDB 的向量數據庫中,這是開源向量數據庫中的熱門選擇。這裏,我們利用 LangChain 的 ChromaDB 模塊,通過嵌入函數來處理已標記化的文檔。生成的向量隨後存儲在 ChromaDB 裏。

# Load it into ChromaDB
db = Chroma.from_documents(docs, embedding_function)

接下來的部分對於上下文注入是關鍵:即提示模板。設計提示模板實際上很直接。就好比是讓你的 LLM 假裝成某個特定角色。在這個場景下,我們要讓 LLM 扮演一個客服代表。

以下是我們打算使用的提示模板。你可以根據自己的需求進行調整。

#Design Prompt Template
template = """You are a customer service chatbot for an online perfume company called Fragrances International.

{context}

Answer the customer's questions only using the source data provided. If you are unsure, say "I don't know, please call our customer support". Use engaging, courteous, and professional language similar to a customer representative.
Keep your answers concise.

Question:

Answer: """

使用 LangChain 的 PromptTemplate 模塊,我們通過提供模板和上下文來初始化提示。

#Intiliaze prompt using prompt template via LangChain
prompt = PromptTemplate(template=template, input_variables=["context"])
print(
    prompt.format(
        context = "A customer is on the perfume company website and wants to chat with the website chatbot."
    )
)

現在我們將所有部件組合在一起。我們將採用 LangChain 的 RetrievalQA 模塊,這是一個針對文檔的 Q&A 優化模塊。該模塊使用鏈功能,將我們的 LLM、向量數據庫和提示模板連接起來。簡而言之,RetrievalQA 可以讓我們在向量數據庫中尋找與用戶問題最相近的向量(通過相似性搜尋),並與提示一同輸入給 LLM。

#Chain to have all components together and query the LLM
chain_type_kwargs = {"prompt": prompt}

chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=db.as_retriever(search_kwargs={"k": 1}),
    chain_type_kwargs=chain_type_kwargs,
)

現在剩下要做的就是查詢 LLM!提出與你的自定義知識庫相關的問題。

# Formatted printing
def print_response(response: str):
    print("\n".join(textwrap.wrap(response, width=80)))

#Running chain through LLM with query
query = "What types of perfumes do you sell?"
response = chain.run(query)
print_response(response)

結果將爲你的查詢提供一個令人印象深刻並且近似人類的回答。根據你的數據,你可能需要調整提示模板。

恭喜你!你已成功創建了自己的第一個 LLM 聊天機器人。

總結

在這篇文章中,我們探討了構建 LLM 應用的基礎。即便你編程經驗很基礎,也能夠製作出各種實用且令人印象深刻的 LLM 應用。

作者:韓冰

來源:分佈式實驗室

原文:https://medium.com/@alisha3/build-your-first-llm-chatbot-77456438f57b

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/aBx-Ta3lnyGOZrPHt4Xpfg