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

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

步驟1:注冊(cè)賬戶

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

OPENAI_API_KEY="your_openai_api_key"

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

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

在這一步中,我們將創(chuàng)建一個(gè)數(shù)據(jù)庫來存儲(chǔ)針對(duì)用戶查詢的研究論文。為此,我們首先需要從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è)置此鏈,指定模型和檢索器。對(duì)于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)行評(píng)估和分析的平臺(tái),用于構(gòu)建生產(chǎn)級(jí)LLM應(yīng)用程序。歸納起來看,Literal AI提供的一些關(guān)鍵功能包括:

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

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

使用Literal AI提示詞管理

在創(chuàng)建對(duì)話式人工智能應(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管理控制臺(tái)(https://cloud.getliteral.ai/)來創(chuàng)建API密鑰。為此,需要注冊(cè)一個(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平臺(tái)的提示面板

進(jìn)入相應(yīng)界面后,在左側(cè)邊欄的模板(Template)部分添加一條新的系統(tǒng)(System)消息。括號(hào)中的任何內(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提示詞管理界面

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

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

Literal AI面板提示詞版本管理

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

理解Chainlit的Copilot組件功能

Chainlit(https://github.com/Chainlit/chainlit)是一個(gè)開源Python包,旨在構(gòu)建可用于生產(chǎn)級(jí)別的對(duì)話式人工智能應(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)對(duì)話框中顯示,我們可以配置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ù):接下來,我們對(duì)文章進(jìn)行分組,并創(chuàng)建嵌入以供進(jìn)一步處理。大塊可以確保有效地處理長論文。然后,從處理過的文檔塊和嵌入中創(chuàng)建Chroma數(shù)據(jù)庫。
  • 檢索:最后,我們建立了RetrievalQA鏈,將LLM和新創(chuàng)建的數(shù)據(jù)庫集成為檢索器。我們還提供了之前在Literal AI管理界面中創(chuàng)建的提示。
  • 存儲(chǔ)變量:我們使用cl.user_session.set功能將鏈和數(shù)據(jù)庫存儲(chǔ)在變量中,以便以后重用。
  • 用戶消息:我們?cè)谡麄€(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ì)話中檢索以前存儲(chǔ)的鏈和數(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ù)請(qǐng)求的上下文定制應(yīng)用程序的行為,從而獲得更動(dòng)態(tài)、更響應(yīng)的用戶體驗(yàn)。

步驟4

Copilot組件可以調(diào)用你網(wǎng)站上的函數(shù)。這對(duì)于代表用戶執(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)處理。對(duì)于我們的語義研究論文引擎程序來說,每當(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針對(duì)用戶查詢提取的在線結(jié)果。
  • showDatabaseResults:此函數(shù)將負(fù)責(zé)顯示針對(duì)用戶問題從我們獲取的數(shù)據(jù)庫中提取的結(jié)果。

首先,讓我們?cè)趕earch_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事件注冊(cè)一個(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)級(jí)應(yīng)用程序中,例如我們現(xiàn)在開發(fā)的集成Copilot組件的語義研究引擎,以確保應(yīng)用程序在生產(chǎn)環(huán)境中的可靠性。我們將在Literal AI框架中使用它。

對(duì)于任何Chainlit應(yīng)用程序,Literal AI都會(huì)自動(dòng)啟動(dòng)監(jiān)控應(yīng)用程序,并將數(shù)據(jù)發(fā)送到Literal人工智能平臺(tái)。在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)”。你將看到針對(duì)以下諸功能的日志輸出信息。

線程 ( Threads )

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

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

Literal AI線程界面

展開特定的對(duì)話將提供關(guān)鍵的細(xì)節(jié)描述,例如每個(gè)步驟所花費(fèi)的時(shí)間、用戶消息的細(xì)節(jié),以及詳細(xì)說明所有步驟的基于樹的視圖。你還可以將對(duì)話添加到數(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ù)的模型名稱,符號(hào)計(jì)數(shù),以及請(qǐng)求完成任務(wù)的用戶(如果你配置了多個(gè)用戶會(huì)話)。

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

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

Literal AI提示評(píng)價(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)用程序中獲得最佳性能,往往都需要整合評(píng)估和可觀察性功能。此外,Copilot對(duì)于不同的軟件應(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)載,請(qǐng)注明出處,否則將追究法律責(zé)任
標(biāo)簽
收藏
回復(fù)
舉報(bào)
回復(fù)
相關(guān)推薦
17videosex性欧美| 亚洲a视频在线| 精品视频亚洲| 正在播放亚洲一区| www.亚洲视频.com| 国产一区二区三区福利| 国产资源在线一区| 69av在线播放| 狂野欧美性猛交| 福利在线一区| 欧美在线观看一二区| 热久久最新网址| 肉丝一区二区| 麻豆精品一区二区综合av| 久久免费在线观看| 精品一区二区在线观看视频| 高清一区二区三区| 欧美三级电影精品| 日本免费黄视频| 在线免费观看a视频| 久久久九九九九| 91久久国产婷婷一区二区| av资源免费观看| 97精品视频| 国产午夜精品视频免费不卡69堂| 中文字幕一二三区| 久久69成人| 欧美午夜精品伦理| 成人午夜看片网址| 日韩欧美亚洲一区二区| 人妻熟女一二三区夜夜爱| 黄色网页在线看| www日韩大片| 亚洲综合日韩中文字幕v在线| 啦啦啦免费高清视频在线观看| 欧美好骚综合网| 国产婷婷成人久久av免费高清| 成人av毛片在线观看| 一区二区三区短视频| 国产日韩欧美一区二区三区乱码| 91久久久久久久久久| 一级黄色av片| 宅男噜噜噜66国产日韩在线观看| 久久精品视频导航| 精品人妻中文无码av在线| 给我免费播放日韩视频| 欧美一区二区久久久| 99精品视频播放| 毛片电影在线| 亚洲一区二区三区四区在线观看| 这里只有精品久久| 国产女人aaa级久久久级| 欧美激情网友自拍| 日日碰狠狠添天天爽| 亚洲性视频大全| 欧美大片拔萝卜| 亚洲黄色av片| 亚洲欧美韩国| 色综合天天天天做夜夜夜夜做| 妞干网在线观看视频| h网站久久久| 亚洲欧洲99久久| 亚洲国产激情一区二区三区| 麻豆国产在线播放| av电影在线观看一区| 岛国视频一区免费观看| 国产女无套免费视频| 老司机一区二区| 国产精品久久久久久久久免费| xxxx.国产| 亚洲一区区二区| 97在线看免费观看视频在线观看| 久久综合色综合| 欧美激情精品久久久六区热门| 成年无码av片在线| 日日骚一区二区三区| 天天综合网网欲色| 久久久国产一区二区| 一区二区三区影视| 真实国产乱子伦精品一区二区三区| 色琪琪综合男人的天堂aⅴ视频| 亚洲av无码一区二区三区网址| 在线播放一区二区精品视频| 日韩一区二区麻豆国产| 中文字幕成人在线视频| 亚洲精品aaa| 91精品国产综合久久精品性色| 蜜桃福利午夜精品一区| 精品视频一区二区三区| 欧美一区二区三区在线看| 欧美高清精品一区二区| 成人免费在线电影网| 亚洲国产精品久久91精品| 精品夜夜澡人妻无码av| 欧美色图激情小说| 久久精品国产亚洲| 久久r这里只有精品| 伊人精品视频| 国产精品白丝jk喷水视频一区| 亚洲午夜无码久久久久| 国产酒店精品激情| 国产自产精品| 在线毛片网站| 一区二区三区在线免费视频| av免费观看大全| 小黄鸭精品aⅴ导航网站入口| 欧美午夜精品久久久| 一区二区三区四区毛片| 成人另类视频| 中文字幕日韩在线观看| 成人免费看片98| 午夜亚洲伦理| 国产日韩av高清| 天堂中文网在线| 国产精品久久久久久久久免费相片 | 欧美激情亚洲| 欧美在线观看网址综合| 中文字幕 自拍偷拍| 国产99精品在线观看| 日本一区二区三区视频在线观看| 成人在线观看亚洲| 在线亚洲精品福利网址导航| 色哟哟在线观看视频| 国产永久精品大片wwwapp| 久久91精品国产| 中文字幕一区在线播放| 国产在线播精品第三| 日韩国产精品一区二区| 丁香影院在线| 欧美肥妇毛茸茸| 美女被到爽高潮视频| 亚洲特色特黄| 国产日韩在线播放| 男人天堂亚洲二区| 亚洲一区精品在线| 中文字幕永久有效| 最近国产精品视频| 欧美激情精品久久久久久久变态| 最近中文在线观看| 91在线精品一区二区| 中文字幕日韩精品无码内射| 91福利精品在线观看| 亚洲精品日韩久久久| 久久久久亚洲AV| 国产精品亚洲午夜一区二区三区 | 最新亚洲国产精品| 中文字幕精品三级久久久| 国产成人在线视频网址| 一区二区三区精品国产| 日韩精品影片| 亚洲开心激情网| 日韩精品视频免费看| 国产福利91精品| gogogo免费高清日本写真| 欧美少妇激情| 日韩亚洲一区二区| 久久精品偷拍视频| 不卡的av电影在线观看| 国产原创popny丨九色| 国内毛片久久| 欧美激情一区二区久久久| 国产黄色片网站| 亚洲激情五月婷婷| xxxx国产视频| 欧美日韩蜜桃| 99理论电影网| 污污网站在线观看| 日韩美女一区二区三区| 黄色一级视频免费| 粉嫩av亚洲一区二区图片| av在线免费观看国产| 国产成人夜色高潮福利影视| 久久久久久久999精品视频| 国产成人三级一区二区在线观看一 | 999这里有精品| 欧美在线视屏| 鬼打鬼之黄金道士1992林正英| 国产精品偷拍| 亚洲精品v天堂中文字幕 | 国产精品大片免费观看| 成人av片网址| 日韩精品美女| 在线成人免费网站| 国产精品无码一区二区桃花视频| 亚洲视频香蕉人妖| 国产免费无码一区二区| 国产欧美日韩综合一区在线播放| 欧美二区在线看| 在线一区视频观看| 久久亚洲精品一区| 黄频网站在线观看| 色www精品视频在线观看| 在线观看免费黄色网址| 国产在线不卡一区| 成人免费毛片在线观看| 欧美猛男同性videos| 国产免费一区二区三区在线能观看 | 在线男人天堂| 最好看的2019年中文视频| 国产视频在线观看视频| 亚洲午夜免费电影| 久久久久久久久久久国产精品| 免费观看日韩av| 欧美精品久久96人妻无码| 久久久久观看| 国产日本欧美一区二区三区| 日韩三级免费| 亚洲欧美中文字幕| 99久久国产热无码精品免费| 精品久久久久久久久久久久| 国产第一页精品| 成人sese在线| 亚洲天堂国产视频| 国产精品婷婷| 黄瓜视频免费观看在线观看www| 国产精品毛片久久久| 日韩免费av在线| a级片国产精品自在拍在线播放| 精品国产一区二区三区不卡 | 五月婷婷在线视频| 亚洲精品久久久久久久久久久久久 | 男操女免费网站| 禁久久精品乱码| 一区二区不卡在线视频 午夜欧美不卡' | 少妇高潮av久久久久久| 亚洲精品国产一区二区三区四区在线| 国产毛片毛片毛片毛片毛片毛片| 激情国产一区二区| 亚洲黄色a v| 国产精品综合| www.好吊操| 亚洲精品二区三区| 色乱码一区二区三在线看| 久久久伦理片| 产国精品偷在线| 国产一区二区高清在线| 国产精品扒开腿做爽爽爽男男 | 亚洲精品乱码久久久久久黑人| 亚洲av无码一区二区三区人 | 免费网站免费进入在线| 亚洲人成网站色在线观看| 久久亚洲AV成人无码国产野外| 成人综合在线网站| 国产黑丝在线视频| 久久精品国产亚洲高清剧情介绍| 欧美精品成人网| 性欧美xxxx大乳国产app| 青青青在线视频播放| 午夜电影亚洲| eeuss中文| 亚洲综合中文| 伊人久久大香线蕉午夜av| 精品国产91乱码一区二区三区四区| 精品亚洲一区二区三区四区五区高| 大型av综合网站| 国产福利一区二区三区在线观看| 美女国产精品久久久| 91欧美激情另类亚洲| 日韩三级一区| 国产精品久久久久久久久久久新郎 | 色哺乳xxxxhd奶水米仓惠香| 99re6这里只有精品| 亚洲欧美日本国产有色| 日韩一区电影| 亚洲精品无人区| 婷婷久久综合| 中文字幕第50页| 日韩精品1区| 五月天亚洲综合| 欧美gayvideo| 黄色高清视频网站| 欧美在线三级| 久久av综合网| 国产精品久久久久久模特| av免费观看大全| 久久蜜桃资源一区二区老牛| 已婚少妇美妙人妻系列| 日产欧产美韩系列久久99| 久久综合伊人77777麻豆最新章节| 日韩成人午夜精品| 亚洲欧美日本一区二区三区| 国产一区二区福利视频| 亚洲成a人无码| 91性感美女视频| 五月天综合视频| 国产精品电影一区二区| 欧美日韩成人免费观看| 婷婷综合在线观看| 五月婷婷激情视频| 欧美日韩一级视频| 国产欧美久久久| 日韩精品黄色网| 99中文字幕一区| 欧美精品在线观看91| 99爱在线观看| 国产精品美女在线观看| 国产精品一区二区美女视频免费看| 高清av免费一区中文字幕| 九色精品91| 99亚洲精品视频| 亚洲毛片在线| 欧美wwwwwww| 成人午夜视频福利| 人人人妻人人澡人人爽欧美一区| 一区视频在线播放| 韩国av免费观看| 欧美精品三级在线观看| 三级小视频在线观看| 亚洲天堂男人天堂女人天堂| 黄色网在线播放| 羞羞色国产精品| 超碰超碰人人人人精品| 国产欧美精品日韩精品| 大香伊人久久精品一区二区| 日本不卡在线观看| 亚洲在线日韩| 四虎成人在线播放| 久久久综合视频| 国产精彩视频在线| 欧美日韩激情在线| 五月婷婷在线观看视频| 久久综合88中文色鬼| 欧美人体一区二区三区| 超碰97在线人人| 久久伦理在线| 国产成人黄色片| 成人深夜福利app| 手机在线中文字幕| 在线亚洲欧美专区二区| 天天操天天干天天| 欧美成人激情在线| 日韩午夜电影免费看| 日本视频精品一区| 99精品福利视频| 中文字幕第66页| 中文字幕免费在线观看视频一区| 日韩少妇裸体做爰视频| 欧美一三区三区四区免费在线看| 国内在线免费高清视频| 26uuu久久噜噜噜噜| 欧美91在线|欧美| 麻豆av一区二区三区久久| 午夜精彩国产免费不卡不顿大片| 日韩一级片播放| 99久久久久久99| 深夜福利影院在线观看| 日韩视频一区二区三区在线播放| 青青操视频在线| 97国产一区二区精品久久呦| 亚洲欧美日本国产| 激情六月天婷婷| 久久99久国产精品黄毛片色诱| 精品人妻无码一区二区三区换脸| 欧美日韩国产一区在线| 熟妇人妻系列aⅴ无码专区友真希| 欧美精品制服第一页| 国产欧美视频在线| 一区二区视频在线播放| 久久99国产精品久久99| 大地资源高清在线视频观看| 欧美精品第1页| 黄色国产网站在线播放| 国产视频福利一区| 99精品在线免费在线观看| 亚洲视频一二三四| 亚洲欧洲av一区二区三区久久| 91在线公开视频| 久久九九全国免费精品观看| 亚洲天堂网站| 五月天在线免费视频| 国产成人午夜99999| 日日骚一区二区三区| 日韩精品一区二区三区老鸭窝| 性直播体位视频在线观看| 国产99在线免费| 性欧美videos另类喷潮| 黄色国产在线播放| 6080国产精品一区二区| 污视频在线看网站| 国产精品一区二区三区观看| 亚洲日韩视频| 好吊视频在线观看| 欧美亚日韩国产aⅴ精品中极品| 亚洲视频tv| 高清不卡日本v二区在线| 国产视频一区三区| 国产精成人品免费观看| 欧美精三区欧美精三区| 亚洲按摩av| 免费在线成人av| 另类欧美日韩国产在线| 精品在线视频观看| 亚洲品质视频自拍网| 四虎精品在线观看| 999在线观看视频| 国产性天天综合网| 国产女人爽到高潮a毛片| 8x拔播拔播x8国产精品| 日韩理论片av| 免费啪视频在线观看|