自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

開發(fā)arXiv論文引擎機(jī)器人程序:基于RAG+LangChain+Chainlit+ChromaDB 原創(chuàng)

發(fā)布于 2024-6-3 09:26
瀏覽
0收藏

本文將完整細(xì)致地介紹如何使用RAG技術(shù)與LangChain、Chainlit Copilot組件以及Literal AI可觀測性特征聯(lián)合開發(fā)一款語義論文搜索引擎程序。

簡介

在本文中,我將演示如何使用檢索增強(qiáng)生成(RAG)技術(shù)構(gòu)建語義研究論文引擎。具體地說,我將使用LangChain(https://www.langchain.com/)作為構(gòu)建語義引擎的主要框架,以及OpenAI公司的大語言模型和ChromaDB開源向量數(shù)據(jù)庫(https://www.trychroma.com/)。為了構(gòu)建名稱為Copilot的嵌入式Web應(yīng)用程序,我將使用Chainlit中的Copilot插件功能,并結(jié)合Literal AI公司(https://literalai.com/)的可觀察性特征。借助于該應(yīng)用程序,用戶可以更容易地查找相關(guān)論文,從而促進(jìn)學(xué)術(shù)研究。用戶還可以通過詢問有關(guān)推薦論文的問題直接與內(nèi)容互動(dòng)。最后,我們將在應(yīng)用程序中集成可觀察性特征,以便跟蹤和調(diào)試對LLM的調(diào)用。整個(gè)應(yīng)用程序的架構(gòu)如下圖所示。

開發(fā)arXiv論文引擎機(jī)器人程序:基于RAG+LangChain+Chainlit+ChromaDB-AI.x社區(qū)

Copilot嵌入式語義研究論文應(yīng)用程序整體架構(gòu)

以下先來看一下我們將在本教程中介紹的所有內(nèi)容的概覽:

  • 使用OpenAI、LangChain和ChromaDB開發(fā)RAG管道,以處理和檢索arXiv API中最相關(guān)的PDF文檔。
  • 使用Copilot插件開發(fā)Chainlit應(yīng)用程序,用于在線論文檢索。
  • 使用Literal AI公司的LLM可觀察性特征進(jìn)一步增強(qiáng)本應(yīng)用程序功能。

開發(fā)arXiv論文引擎機(jī)器人程序:基于RAG+LangChain+Chainlit+ChromaDB-AI.x社區(qū)

Copilot嵌入式語義研究論文引擎的運(yùn)行時(shí)快照

注意,本教程中的完整示例工程代碼可以在GitHub地址https://github.com/tahreemrasul/semantic_research_engine處找到:

開發(fā)arXiv論文引擎機(jī)器人程序:基于RAG+LangChain+Chainlit+ChromaDB-AI.x社區(qū)

環(huán)境設(shè)置

首先,我們要?jiǎng)?chuàng)建一個(gè)新的conda環(huán)境:

conda create -n semantic_research_engine python=3.10

然后,使用如下命令激活環(huán)境:

conda activate semantic_research_engine

最后,通過運(yùn)行以下命令,在激活的環(huán)境中安裝所有必需的依賴項(xiàng):

pip install -r requirements.txt

RAG管道創(chuàng)建

檢索增強(qiáng)生成(RAG)是一種流行的技術(shù),允許你使用自己的數(shù)據(jù)構(gòu)建自定義的對話式人工智能應(yīng)用程序。RAG的原理相當(dāng)簡單:我們將文本數(shù)據(jù)轉(zhuǎn)換為向量嵌入,并將其插入向量數(shù)據(jù)庫;然后將該數(shù)據(jù)庫鏈接到大型語言模型(LLM)。需要說明的是,我們將限制LLM從自己的數(shù)據(jù)庫中獲取信息,而不是依賴先驗(yàn)知識來回答用戶查詢。在接下來的幾個(gè)步驟中,我將詳細(xì)介紹如何為我們的語義研究論文引擎做到這一點(diǎn)。我們將創(chuàng)建一個(gè)名為rag_test.py的測試腳本來理解和構(gòu)建RAG管道的組件。之后,這些組件將在構(gòu)建我們的集成Copilot插件的Chainlit應(yīng)用程序時(shí)重復(fù)使用。

步驟1:注冊賬戶

需要注冊一個(gè)賬戶,以便保護(hù)OpenAI API密鑰。完成后,在項(xiàng)目目錄中創(chuàng)建一個(gè).env文件,并添加該OpenAI API密鑰,如下所示:

OPENAI_API_KEY="your_openai_api_key"

在本文應(yīng)用程序中,我們將使用這個(gè).env文件來存儲我們項(xiàng)目的所有API密鑰。

步驟2:輸入數(shù)據(jù)

在這一步中,我們將創(chuàng)建一個(gè)數(shù)據(jù)庫來存儲針對用戶查詢的研究論文。為此,我們首先需要從arXiv API中檢索相關(guān)論文的列表以進(jìn)行查詢。我們將使用LangChain的ArxivLoader包,因?yàn)榇税橄罅伺cAPI的交互,然后檢索論文以供進(jìn)一步處理。我們可以將這些論文分割成更小的塊,以確保以后的高效處理和相關(guān)信息檢索。

為此,我們將使用LangChain中的RecursiveTextSplitter()函數(shù),因?yàn)樗梢源_保在分割文檔時(shí)信息的語義保留。接下來,我們將使用HuggingFace(https://python.langchain.com/docs/integrations/platforms/huggingface/#embedding-models)中的sentence-transformers嵌入為這些塊創(chuàng)建嵌入。最后,我們將把這些分割文檔嵌入到ChromaDB數(shù)據(jù)庫中進(jìn)行進(jìn)一步查詢。

# rag_test.py 
from langchain_community.document_loaders import ArxivLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import HuggingFaceEmbeddings

query = "lightweight transformer for language tasks"
arxiv_docs = ArxivLoader(query=query, load_max_docs=3).load()
pdf_data = []
for doc in arxiv_docs:
    text_splitter = RecursiveCharacterTextSplitter(
                    chunk_size=1000,
                    chunk_overlap=100)
    texts = text_splitter.create_documents([doc.page_content])
    pdf_data.append(texts)

embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-l6-v2")
db = Chroma.from_documents(pdf_data[0], embeddings)

步驟3:檢索和生成

一旦創(chuàng)建了特定主題的數(shù)據(jù)庫,我們就可以使用該數(shù)據(jù)庫作為檢索器,并根據(jù)提供的上下文回答用戶問題。LangChain提供了一些不同的檢索鏈,我們將在本教程中使用最簡單的RetrievalQA鏈。我們將使用from_chain_type()方法設(shè)置此鏈,指定模型和檢索器。對于LLM中的文檔集成,我們將使用stuff鏈類型,因?yàn)樗軌驅(qū)⑺形臋n填充到一個(gè)提示中。

# rag_test.py
from langchain.chains import RetrievalQA
from langchain_openai import OpenAI
from dotenv import load_dotenv

load_dotenv()
llm = OpenAI(model='gpt-3.5-turbo-instruct', temperature=0)
qa = RetrievalQA.from_chain_type(llm=llm, 
                                 chain_type="stuff", 
                                 retriever=db.as_retriever())

question = "how many and which benchmark datasets and tasks were 
            compared for light weight transformer?"
result = qa({"query": question})

現(xiàn)在,我們已經(jīng)介紹了arXiv API的在線檢索以及RAG管道的數(shù)據(jù)輸入和檢索步驟。接下來,我們將著手開發(fā)語義研究引擎Web應(yīng)用程序。

理解Literal AI可觀察性特征

Literal AI(https://literalai.com/)是一個(gè)提供可觀察性特征并能夠進(jìn)行評估和分析的平臺,用于構(gòu)建生產(chǎn)級LLM應(yīng)用程序。歸納起來看,Literal AI提供的一些關(guān)鍵功能包括:

  • 可觀察性:能夠監(jiān)控LLM應(yīng)用程序,包括對話、中間步驟、提示等。
  • 數(shù)據(jù)集:允許創(chuàng)建混合生產(chǎn)數(shù)據(jù)和手寫示例的數(shù)據(jù)集。
  • 在線評估:允許使用不同的評估器評估線程和生產(chǎn)中的執(zhí)行。
  • 提示詞管理:允許對提示詞進(jìn)行迭代、版本控制和部署。

我們將使用可觀察性和提示迭代功能來評估和調(diào)試我們的語義研究論文應(yīng)用程序進(jìn)行的諸多調(diào)用。

使用Literal AI提示詞管理

在創(chuàng)建對話式人工智能應(yīng)用程序時(shí),開發(fā)人員需要迭代多個(gè)版本的提示,以獲得產(chǎn)生最佳結(jié)果的提示詞。提示工程在大多數(shù)LLM任務(wù)中起著至關(guān)重要的作用,因?yàn)槲⑿〉男薷木涂梢燥@著改變語言模型的響應(yīng)。Literal AI提示詞管理可以用來簡化這個(gè)過程。一旦選擇了模型提供程序,就可以輸入初始提示模板,添加任何其他信息,并反復(fù)完善提示以找到最合適的提示。在接下來的幾個(gè)步驟中,我們將使用這個(gè)功能為我們的應(yīng)用程序找到最佳提示信息。

步驟1

首先,我們需要使用瀏覽器打開Literal AI管理控制臺(https://cloud.getliteral.ai/)來創(chuàng)建API密鑰。為此,需要注冊一個(gè)帳戶,導(dǎo)航到項(xiàng)目(“projects”)頁面,然后創(chuàng)建新項(xiàng)目。每個(gè)項(xiàng)目都有其唯一的API密鑰。在設(shè)置(“Settings”)選項(xiàng)卡上,你將在API密鑰部分找到你自己的API密鑰。最后,將其添加到.env文件中:

LITERAL_API_KEY="your_literal_api_key"

步驟2

在左側(cè)邊欄中,單擊“提示(Prompts)”,然后導(dǎo)航到“新建提示(New Prompt)”。這將打開一個(gè)新的提示創(chuàng)建會(huì)話。

開發(fā)arXiv論文引擎機(jī)器人程序:基于RAG+LangChain+Chainlit+ChromaDB-AI.x社區(qū)

Literal AI平臺的提示面板

進(jìn)入相應(yīng)界面后,在左側(cè)邊欄的模板(Template)部分添加一條新的系統(tǒng)(System)消息。括號中的任何內(nèi)容都將被添加到變量(Variables)中,并被視為提示中的輸入:

You are a helpful assistant. Use provided {{context}} to answer user 
{{question}}. Do not use prior knowledge. 
Answer:

接下來,在右側(cè)欄中,你可以提供你的OpenAI API密鑰。選擇參數(shù),如“模型(Model)”、“溫度(Temperature)”和“最大完成長度(Maximum Length)”等,以便配合提示詞使用。

開發(fā)arXiv論文引擎機(jī)器人程序:基于RAG+LangChain+Chainlit+ChromaDB-AI.x社區(qū)

Literal AI提示詞管理界面

對提示版本感到滿意后,單擊“保存(Save)”。系統(tǒng)將提示你輸入提示的名稱和可選說明。我們可以將此版本添加到我們的代碼中。在名為search_engine.py的新腳本中,添加以下代碼:

#search_engine.py
from literalai import LiteralClient
from dotenv import load_dotenv

load_dotenv()

client = LiteralClient()

# 下面的代碼將會(huì)使用最新版本,你也可以選擇使用特定版本
prompt = client.api.get_prompt(name="test_prompt")
prompt = prompt.to_langchain_chat_prompt_template()
prompt.input_variables = ["context", "question"]

Literal AI允許你保存提示詞對應(yīng)的不同的運(yùn)行結(jié)果,并具有版本管理功能。你還可以查看每個(gè)版本與上一個(gè)版本的不同之處。默認(rèn)情況下,最新版本會(huì)被取消。如果你想將某個(gè)版本更改為最新版本,你可以在管理面板上選擇它,然后單擊“升級(Promote)”。

開發(fā)arXiv論文引擎機(jī)器人程序:基于RAG+LangChain+Chainlit+ChromaDB-AI.x社區(qū)

Literal AI面板提示詞版本管理

添加上述代碼后,我們將能夠在Literal AI 控制面板中查看特定提示的生成結(jié)果(稍后將對此進(jìn)行詳細(xì)介紹)。

理解Chainlit的Copilot組件功能

Chainlit(https://github.com/Chainlit/chainlit)是一個(gè)開源Python包,旨在構(gòu)建可用于生產(chǎn)級別的對話式人工智能應(yīng)用程序。這個(gè)包能夠?yàn)閹讉€(gè)事件(聊天開始、用戶消息、會(huì)話恢復(fù)、會(huì)話停止等)提供裝飾器支持。你可以查看鏈接處https://medium.com/@tahreemrasul/building-a-chatbot-application-with-chainlit-and-langchain-3e86da0099a6?source=post_page-----9c345fcd1cd8--------------------------------我撰寫的文章,了解更全面的解釋。

在本教程中,我們將重點(diǎn)關(guān)注使用Chainlit為我們的RAG應(yīng)用程序構(gòu)建軟件Copilot。Chainlit Copilot能夠在我們的應(yīng)用程序中提供上下文指導(dǎo)和自動(dòng)化用戶操作功能。

開發(fā)arXiv論文引擎機(jī)器人程序:基于RAG+LangChain+Chainlit+ChromaDB-AI.x社區(qū)

使用相關(guān)工具構(gòu)建的研究論文應(yīng)用程序架構(gòu)

開發(fā)Copilot應(yīng)用程序

在你的應(yīng)用程序網(wǎng)站中嵌入一個(gè)Copilot組件可能很有用。原因有幾個(gè):我們將為我們的語義研究論文引擎構(gòu)建一個(gè)簡單的Web界面,并在其中集成一個(gè)Copilot組件。這個(gè)Copilot組件將提供幾項(xiàng)不同的功能,但以下是最突出的幾個(gè)功能:

  • 它將嵌入到我們網(wǎng)站的HTML文件中。
  • Copilot組件將能夠代表用戶采取相應(yīng)的動(dòng)作。假設(shè)用戶要求提供關(guān)于某個(gè)特定主題的在線研究論文。這些要求可以在一個(gè)模態(tài)對話框中顯示,我們可以配置Copilot組件自動(dòng)完成,而無需用戶輸入。

在接下來的幾個(gè)步驟中,我將詳細(xì)介紹如何使用Chainlit為我們的語義研究引擎創(chuàng)建軟件中的Copilot組件。

步驟1

第一步涉及為我們的chailit應(yīng)用程序編寫邏輯。我們將在本項(xiàng)目中使用兩個(gè)chailit裝飾器函數(shù):@cl.on_chat_start和@cl.on_message。我們將把來自在線搜索和RAG管道的邏輯添加到這些功能中。需要記住的幾件事:

  • @cl.on_chat_start中將包含在新用戶會(huì)話開始時(shí)需要執(zhí)行的所有代碼。
  • @cl.on_message中將包含用戶發(fā)送新消息時(shí)需要執(zhí)行的所有代碼。

我們將封裝從接收研究主題到創(chuàng)建數(shù)據(jù)庫以及在@cl.on_chat_start裝飾器函數(shù)中接收文檔的整個(gè)過程。

首先,需要在search_engine.py腳本中,導(dǎo)入所有必要的模塊和庫:

# search_engine.py
import chainlit as cl
from langchain_community.document_loaders import ArxivLoader
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv

load_dotenv()

現(xiàn)在,讓我們添加@cl.on_chat_start裝飾器的代碼。我們將使此函數(shù)以異步方式執(zhí)行,以確保多個(gè)任務(wù)可以同時(shí)運(yùn)行。

# search_engine.py
# contd.

@cl.on_chat_start
async def retrieve_docs():
    # QUERY PORTION
    arxiv_query = None
    # 等待用戶輸入一個(gè)標(biāo)題
    while arxiv_query is None:
        arxiv_query = await cl.AskUserMessage(
            content="Please enter a topic to begin!", timeout=15).send()
    query = arxiv_query['output']

    # ARXIV文檔部分
    arxiv_docs = ArxivLoader(query=arxiv_query, load_max_docs=3).load()
    # 準(zhǔn)備arXiv結(jié)果,用于顯示
    arxiv_papers = [f"Published: {doc.metadata['Published']} \n "
                    f"Title: {doc.metadata['Title']} \n "
                    f"Authors: {doc.metadata['Authors']} \n "
                    f"Summary: {doc.metadata['Summary'][:50]}... \n---\n"
                    for doc in arxiv_docs]

    await cl.Message(content=f"{arxiv_papers}").send()

    await cl.Message(content=f"Downloading and chunking articles for {query} "
                             f"This operation can take a while!").send()

    #數(shù)據(jù)庫部分
    pdf_data = []
    for doc in arxiv_docs:
        text_splitter = RecursiveCharacterTextSplitter(
                        chunk_size=1000, chunk_overlap=100)
        texts = text_splitter.create_documents([doc.page_content])
        pdf_data.append(texts)
  
    llm = ChatOpenAI(model='gpt-3.5-turbo',
                         temperature=0)
    embeddings = HuggingFaceEmbeddings(
                 model_name="sentence-transformers/all-MiniLM-l6-v2")
    db = Chroma.from_documents(pdf_data[0], embeddings)

    # 鏈部分
    chain = RetrievalQA.from_chain_type(llm=llm,
                                            chain_type="stuff",
                                            retriever=db.as_retriever(),
                                            chain_type_kwargs={
                                                "verbose": True,
                                                "prompt": prompt
                                            }
                                            )

    # 讓用戶知道管道已經(jīng)準(zhǔn)備到位
    await cl.Message(content=f"Database creation for `{query}` complete. "
                             f"You can now ask questions!").send()

    cl.user_session.set("chain", chain)
    cl.user_session.set("db", db)

讓我們來看看這個(gè)函數(shù)中包含的代碼:

提示用戶查詢:我們首先讓用戶發(fā)送一個(gè)研究主題。在用戶提交主題之前,此函數(shù)不會(huì)繼續(xù)往下執(zhí)行。

  • 在線搜索:我們使用LangChain的arXiv搜索包裝器檢索相關(guān)論文,并以可讀的格式顯示每個(gè)條目中的相關(guān)字段。
  • 輸入數(shù)據(jù):接下來,我們對文章進(jìn)行分組,并創(chuàng)建嵌入以供進(jìn)一步處理。大塊可以確保有效地處理長論文。然后,從處理過的文檔塊和嵌入中創(chuàng)建Chroma數(shù)據(jù)庫。
  • 檢索:最后,我們建立了RetrievalQA鏈,將LLM和新創(chuàng)建的數(shù)據(jù)庫集成為檢索器。我們還提供了之前在Literal AI管理界面中創(chuàng)建的提示。
  • 存儲變量:我們使用cl.user_session.set功能將鏈和數(shù)據(jù)庫存儲在變量中,以便以后重用。
  • 用戶消息:我們在整個(gè)函數(shù)中使用Chainlit的cl.Message功能來與用戶交互。

現(xiàn)在,讓我們定義@cl.on_message函數(shù),并添加RAG管道的生成部分。用戶應(yīng)該能夠從獲取的論文中提出問題,應(yīng)用程序應(yīng)該提供相關(guān)答案。

@cl.on_message
async def retrieve_docs(message: cl.Message):
    question = message.content
    chain = cl.user_session.get("chain")
    db = cl.user_session.get("db")
    # 為每次調(diào)用創(chuàng)建一個(gè)新的回調(diào)處理程序?qū)嵗?    cb = client.langchain_callback()
    variables = {"context": db.as_retriever(search_kwargs={"k": 1}), 
                 "query": question}
    database_results = await chain.acall(variables,
                                         callbacks=[cb])
    results = [f"Question: {question} "
               f"\n Answer: {database_results['result']}"]
    await cl.Message(results).send()

以下是上面函數(shù)中代碼的各功能說明:

  • 鏈和數(shù)據(jù)庫檢索:我們首先從用戶會(huì)話中檢索以前存儲的鏈和數(shù)據(jù)庫。
  • LangChain回調(diào)集成:為了確保我們能夠跟蹤我們的提示和使用特定提示版本的所有生成結(jié)果,我們需要在調(diào)用我們的鏈時(shí)添加來自Literal AI的LangChain回調(diào)處理程序。我們使用的是LiteralClient實(shí)例中的langchain_callback()方法創(chuàng)建回調(diào)處理程序。此回調(diào)會(huì)自動(dòng)將所有LangChain交互結(jié)果記錄到Literal AI中。
  • 生成:我們定義有關(guān)變量,使用數(shù)據(jù)庫作為檢索的上下文,用戶的問題作為查詢,還指定檢索頂部結(jié)果(k:1)。最后,我們使用所提供的變量和回調(diào)來調(diào)用鏈。

步驟2

第二步是將Copilot組件嵌入到我們的應(yīng)用程序網(wǎng)站中。我們將創(chuàng)建一個(gè)簡單的網(wǎng)站進(jìn)行演示。創(chuàng)建一個(gè)index.html文件,并向其中添加以下代碼:

<!DOCTYPE html>
<html>
  <head>
    <title>Semantic Search Engine</title>
  </head>
 <body>
   <!-- ... -->
   <script src="http://localhost:8000/copilot/index.js"></script>
   <script>
     window.mountChainlitWidget({
       chainlitServer: "http://localhost:8000",
     });
   </script>
 </body>

在上面的代碼中,我們通過指向托管我們應(yīng)用程序的Chainlit服務(wù)器的位置,將Copilot組件嵌入了我們的網(wǎng)站中。上述代碼中,window.mountChainlitWidget能夠在當(dāng)前網(wǎng)站的右下角添加一個(gè)浮動(dòng)按鈕。點(diǎn)擊它將打開Copilot功能。為了確保我們的Copilot正常工作,我們需要首先運(yùn)行Chainlit應(yīng)用程序。在項(xiàng)目目錄中導(dǎo)航到合適的位置并運(yùn)行如下命令:

chainlit run search_engine.py -w

這段代碼將在地址https://localhost:8000處運(yùn)行應(yīng)用程序。接下來,我們需要托管我們的應(yīng)用程序網(wǎng)站。在瀏覽器中打開index.html腳本是不起作用的。相反,我們需要?jiǎng)?chuàng)建一個(gè)HTTPS測試服務(wù)器。你可以用不同的方法來實(shí)現(xiàn)這一點(diǎn),但一種簡單的方法是使用npx工具。npx包含在Node.js附帶的npm(節(jié)點(diǎn)包管理器)中;因此,要獲得npx,只需在系統(tǒng)上安裝Node.js即可。在項(xiàng)目目錄中導(dǎo)航到合適的位置并運(yùn)行如下命令:

npx http-server

這段代碼將在地址https://localhost:8080處啟動(dòng)服務(wù)器程序。導(dǎo)航到該地址,你將能夠看到一個(gè)嵌入Copilot組件的簡單Web界面。

開發(fā)arXiv論文引擎機(jī)器人程序:基于RAG+LangChain+Chainlit+ChromaDB-AI.x社區(qū)

嵌入Copilot組件的Web界面

由于我們將使用@cl.on_chat_start包裝器函數(shù)來歡迎用戶,因此我們可以在Chainlit配置中將show_readme_as_default設(shè)置為false,以避免界面閃爍。你可以在項(xiàng)目目錄中的.Chainlit/config.toml中找到你的配置文件。

開發(fā)arXiv論文引擎機(jī)器人程序:基于RAG+LangChain+Chainlit+ChromaDB-AI.x社區(qū)

Copilot組件小窗預(yù)覽

步驟3

要僅在Copilot組件內(nèi)部執(zhí)行代碼,我們可以添加以下內(nèi)容:

@cl.on_message
async def retrieve_docs(message: cl.Message):
    if cl.context.session.client_type == "copilot":
        # code to be executed only inside the Copilot

只有當(dāng)你在Copilot組件中與應(yīng)用程序交互時(shí),才會(huì)執(zhí)行此塊中的任何代碼。例如,如果在位于https://localhost:8000地址的Chainlit應(yīng)用程序接口上運(yùn)行查詢,上面if塊中的代碼將不會(huì)執(zhí)行,因?yàn)樗谕蛻舳祟愋蜑镃opilot。這是一個(gè)有用的功能,可以用來區(qū)分直接在Chainlit應(yīng)用程序中執(zhí)行的操作和通過Copilot界面啟動(dòng)的操作。通過這樣做,你可以根據(jù)請求的上下文定制應(yīng)用程序的行為,從而獲得更動(dòng)態(tài)、更響應(yīng)的用戶體驗(yàn)。

步驟4

Copilot組件可以調(diào)用你網(wǎng)站上的函數(shù)。這對于代表用戶執(zhí)行操作非常有用,例如打開模態(tài)、創(chuàng)建新文檔等。我們將進(jìn)一步修改Chainlit裝飾器函數(shù),使其包含兩個(gè)新的Copilot函數(shù)。為此,我們需要在index.html文件中指定當(dāng)Chainlit后端應(yīng)用程序中的Copilot函數(shù)被激活時(shí),前端應(yīng)該如何響應(yīng)。具體響應(yīng)情況將根據(jù)應(yīng)用程序的不同而作相應(yīng)處理。對于我們的語義研究論文引擎程序來說,每當(dāng)需要顯示相關(guān)論文或數(shù)據(jù)庫答案以響應(yīng)用戶查詢時(shí),我們都會(huì)在前端生成彈出通知。

開發(fā)arXiv論文引擎機(jī)器人程序:基于RAG+LangChain+Chainlit+ChromaDB-AI.x社區(qū)

響應(yīng)Copilot組件中的用戶查詢而彈出

我們將在應(yīng)用程序中創(chuàng)建兩個(gè)Copilot函數(shù):

  • showArxivResults:此函數(shù)將負(fù)責(zé)顯示arXiv API針對用戶查詢提取的在線結(jié)果。
  • showDatabaseResults:此函數(shù)將負(fù)責(zé)顯示針對用戶問題從我們獲取的數(shù)據(jù)庫中提取的結(jié)果。

首先,讓我們在search_engine.py腳本中設(shè)置后端邏輯,并修改@cl.on_chat_start函數(shù):

@cl.on_chat_start
async def retrieve_docs():
    if cl.context.session.client_type == "copilot":
        # 代碼同上

        #觸發(fā)顯示arXiv論文結(jié)果的彈出窗口
        fn_arxiv = cl.CopilotFunction(name="showArxivResults", 
                   args={"results": "\n".join(arxiv_papers)})
        await fn_arxiv.acall()
        
        # same code as before

在上面的代碼中,定義并異步調(diào)用了一個(gè)名為showArxivResults的Copilot函數(shù)。此函數(shù)作用是直接在Copilot界面中顯示arXiv論文的格式化列表。函數(shù)簽名非常簡單:我們指定函數(shù)的名稱及其將發(fā)送回的參數(shù)。我們將在index.html文件中使用這些信息來創(chuàng)建一個(gè)彈出窗口。

接下來,我們需要用第二個(gè)Copilot函數(shù)修改我們的@cl.on_message函數(shù),當(dāng)用戶根據(jù)獲取的論文提出問題時(shí),將執(zhí)行該函數(shù):

@cl.on_message
async def retrieve_docs(message: cl.Message):
    if cl.context.session.client_type == "copilot":
        #代碼同上
        
        # 激活相應(yīng)于數(shù)據(jù)庫查詢結(jié)果的彈出小窗口
        fn_db = cl.CopilotFunction(name="showDatabaseResults", 
                args={"results": "\n".join(results)})
        await fn_db.acall()
        
        #代碼同前

在上面的代碼中,我們定義了要異步調(diào)用的第二個(gè)Copilot函數(shù)showDatabaseResults。此函數(shù)的任務(wù)是在Copilot界面中顯示從數(shù)據(jù)庫檢索到的結(jié)果。函數(shù)簽名指定函數(shù)的名稱及其將發(fā)送回的參數(shù)。

步驟5

接下來,我們將進(jìn)一步編輯我們的index.html文件,這包括以下幾個(gè)方面的更改:

  • 添加兩個(gè)Copilot函數(shù)。
  • 指定當(dāng)兩個(gè)Copilot函數(shù)中的任何一個(gè)被觸發(fā)時(shí),我們的網(wǎng)站上會(huì)發(fā)生什么。我們將創(chuàng)建一個(gè)彈出窗口來顯示應(yīng)用程序后端的結(jié)果。
  • 為彈出窗口添加簡單的樣式。

首先,我們需要為Copilot函數(shù)添加事件偵聽器。在index.html文件的<script>標(biāo)記中,添加以下代碼:

<script>
 // 前面的代碼
 window.addEventListener("chainlit-call-fn", (e) => {
 const { name, args, callback } = e.detail;
 if (name === "showArxivResults") {
   document.getElementById("arxiv-result-text").innerHTML =
     args.results.replace(/\n/g, "<br>");
   document.getElementById("popup").style.display = "flex";
   if (callback) callback();
 } else if (name === "showDatabaseResults") {
   document.getElementById("database-results-text").innerHTML =
     args.results.replace(/\n/g, "<br>");
   document.getElementById("popup").style.display = "flex";
   if (callback) callback();
 }
 });
</script>

以下是上述代碼的解釋:

  • 包括顯示(showPopup())和隱藏(hidePopup())彈出窗口的函數(shù)。
  • 為chainlit-call-fn事件注冊一個(gè)事件偵聽器,該事件在調(diào)用Copilot函數(shù)(showArxivResults或showDatabaseResults)時(shí)觸發(fā)。
  • 檢測到事件后,偵聽器將檢查調(diào)用的Copilot函數(shù)的名稱。根據(jù)函數(shù)名稱,它會(huì)使用函數(shù)提供的結(jié)果更新彈出窗口中相關(guān)部分的內(nèi)容。它將換行符(\\n)替換為HTML換行符(<br>),以便為HTML顯示正確格式化的文本。
  • 更新內(nèi)容后,將顯示彈出模式(顯示:“flex”),允許用戶查看結(jié)果。可以使用關(guān)閉按鈕隱藏窗口,該按鈕調(diào)用hidePopup()函數(shù)。

接下來,我們需要定義上面指定的彈出窗口。我們可以通過將以下代碼添加到index.html腳本的<body>標(biāo)記中來實(shí)現(xiàn)這一點(diǎn):

<div id="popup" class="popup">
 <span class="close-btn" onclick="hidePopup()">×</span>
 <div class="arxiv-results-wrapper">
   <h1>Arxiv Results</h1>
   <p id="arxiv-result-text">Online results will be displayed here.</p>
 </div>
 <div class="database-results-wrapper">
   <h1>Database Results</h1>
   <p id="database-results-text">Database results will be displayed here.</p>
 </div>
</div>

讓我們也為彈出窗口添加一些樣式。編輯index.html文件的<head>標(biāo)記:

<style>
 * {
   box-sizing: border-box;
 }
 
 body {
   font-family: sans-serif;
 }
 
 .close-btn {
   position: absolute;
   top: 10px;
   right: 20px;
   font-size: 24px;
   cursor: pointer;
 }
 
 .popup {
   display: none;
   position: fixed;
   top: 50%;
   left: 50%;
   transform: translate(-50%, -50%);
   background-color: white;
   padding: 20px;
   box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;
   width: 40%;
   flex-direction: column;
   gap: 50px;
 }
 
 p {
   color: #00000099;
 }
</style>

啟動(dòng)應(yīng)用程序

至此,我們已經(jīng)將Copilot邏輯添加到Chainlit應(yīng)用程序中,我們可以運(yùn)行應(yīng)用程序和網(wǎng)站了。要使Copilot工作,我們的應(yīng)用程序必須首先運(yùn)行起來。在項(xiàng)目目錄中打開一個(gè)終端,然后運(yùn)行以下命令啟動(dòng)Chainlit服務(wù)器:

chainlit run search.py -h

在新的終端中,使用以下方式啟動(dòng)網(wǎng)站:

npx http-server

開發(fā)arXiv論文引擎機(jī)器人程序:基于RAG+LangChain+Chainlit+ChromaDB-AI.x社區(qū)

應(yīng)用程序示例界面

Literal AI 的LLM可 觀察性

通常,我們需要將可觀察性特征集成到生產(chǎn)級應(yīng)用程序中,例如我們現(xiàn)在開發(fā)的集成Copilot組件的語義研究引擎,以確保應(yīng)用程序在生產(chǎn)環(huán)境中的可靠性。我們將在Literal AI框架中使用它。

對于任何Chainlit應(yīng)用程序,Literal AI都會(huì)自動(dòng)啟動(dòng)監(jiān)控應(yīng)用程序,并將數(shù)據(jù)發(fā)送到Literal人工智能平臺。在search_engine.py腳本中創(chuàng)建提示時(shí),我們已經(jīng)啟動(dòng)了Literal AI客戶端。現(xiàn)在,每次用戶與我們的應(yīng)用程序交互時(shí),我們都會(huì)在Literal AI面板中看到有關(guān)日志信息。

控制面板

導(dǎo)航到Literal AI控制界面(https://cloud.getliteral.ai/projects/),從左側(cè)面板中選擇項(xiàng)目,然后單擊“可觀察性(Observability)”。你將看到針對以下諸功能的日志輸出信息。

線程 ( Threads )

線程表示助理和用戶之間的會(huì)話。你應(yīng)該能夠看到用戶在應(yīng)用程序中進(jìn)行的所有對話。

開發(fā)arXiv論文引擎機(jī)器人程序:基于RAG+LangChain+Chainlit+ChromaDB-AI.x社區(qū)

Literal AI線程界面

展開特定的對話將提供關(guān)鍵的細(xì)節(jié)描述,例如每個(gè)步驟所花費(fèi)的時(shí)間、用戶消息的細(xì)節(jié),以及詳細(xì)說明所有步驟的基于樹的視圖。你還可以將對話添加到數(shù)據(jù)集中。

開發(fā)arXiv論文引擎機(jī)器人程序:基于RAG+LangChain+Chainlit+ChromaDB-AI.x社區(qū)

Literal AI線程界面概覽

運(yùn)行(Runs)

運(yùn)行是代理或鏈所執(zhí)行的一系列步驟。這一部分提供了每次執(zhí)行鏈或代理時(shí)所采取的所有步驟的詳細(xì)信息。通過這個(gè)選項(xiàng)卡,我們可以獲得每個(gè)用戶查詢的輸入和輸出。

開發(fā)arXiv論文引擎機(jī)器人程序:基于RAG+LangChain+Chainlit+ChromaDB-AI.x社區(qū)

Literal AI Runs面板

你可以展開一個(gè)Run,這將提供更多細(xì)節(jié)信息。同樣,你可以將此信息添加到數(shù)據(jù)集中。

開發(fā)arXiv論文引擎機(jī)器人程序:基于RAG+LangChain+Chainlit+ChromaDB-AI.x社區(qū)

Literal AI Runs面板運(yùn)行時(shí)概覽

生成(Generations)

Generations面板包含發(fā)送到LLM的輸入信息及完成信息。這個(gè)面板提供的詳細(xì)信息包括用于完成任務(wù)的模型名稱,符號計(jì)數(shù),以及請求完成任務(wù)的用戶(如果你配置了多個(gè)用戶會(huì)話)。

開發(fā)arXiv論文引擎機(jī)器人程序:基于RAG+LangChain+Chainlit+ChromaDB-AI.x社區(qū)

Literal AI Generations面板運(yùn)行時(shí)概覽

Literal AI提示評價(jià)

自從我們添加了LangChain集成以來,我們可以根據(jù)應(yīng)用程序代碼中創(chuàng)建和使用的每個(gè)提示跟蹤生成和線程。因此,每次為用戶查詢調(diào)用鏈時(shí),都會(huì)在Literal AI面板中添加日志信息。這有助于查看特定生成的提示,并比較不同版本的性能。

開發(fā)arXiv論文引擎機(jī)器人程序:基于RAG+LangChain+Chainlit+ChromaDB-AI.x社區(qū)

Copilot集成了具有可觀察性功能的語義研究引擎應(yīng)用程序

結(jié)論

在本教程中,我演示了如何使用LangChain框架、OpenAI大數(shù)據(jù)模型和ChromaDB向量數(shù)據(jù)庫并結(jié)合RAG功能創(chuàng)建一個(gè)語義研究論文引擎。此外,我還展示了如何為該引擎開發(fā)一個(gè)Web應(yīng)用程序,集成了Literal AI的Copilot組件和可觀測性特征。為了確保在現(xiàn)實(shí)世界的語言模型應(yīng)用程序中獲得最佳性能,往往都需要整合評估和可觀察性功能。此外,Copilot對于不同的軟件應(yīng)用程序來說也是一個(gè)非常有用的功能;因此,本教程可以成為了解如何為應(yīng)用程序設(shè)置Copilot功能的一個(gè)很好的起點(diǎn)。

最后,你可以在我的GitHub(https://github.com/tahreemrasul/semantic_research_engine)上找到本教程中的所有代碼。

譯者介紹

朱先忠,51CTO社區(qū)編輯,51CTO專家博客、講師,濰坊一所高校計(jì)算機(jī)教師,自由編程界老兵一枚。

原文標(biāo)題:Building an Observable arXiv RAG Chatbot with LangChain, Chainlit, and Literal AI,作者:Tahreem Rasul

鏈接:

https://towardsdatascience.com/building-an-observable-arxiv-rag-chatbot-with-langchain-chainlit-and-literal-ai-9c345fcd1cd8?。

?著作權(quán)歸作者所有,如需轉(zhuǎn)載,請注明出處,否則將追究法律責(zé)任
標(biāo)簽
收藏
回復(fù)
舉報(bào)
回復(fù)
相關(guān)推薦