国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

基于Llama 3的AI代理開發(fā)實(shí)戰(zhàn)演練 原創(chuàng)

發(fā)布于 2024-8-7 08:28
瀏覽
0收藏

通過(guò)本文,您將學(xué)會(huì)基于開源的深度學(xué)習(xí)模型可視化工具Gradio構(gòu)建一個(gè)具有Llama 3模型函數(shù)調(diào)用功能的AI代理的完整過(guò)程。

簡(jiǎn)介

想象一下,你想買點(diǎn)東西。于是,你訪問(wèn)某個(gè)電子商務(wù)網(wǎng)站并使用搜索選項(xiàng)查找所需內(nèi)容。也許你有很多東西要買,所以這個(gè)過(guò)程不是很有效。現(xiàn)在,請(qǐng)考慮一下這樣一個(gè)場(chǎng)景:打開一個(gè)應(yīng)用程序,用簡(jiǎn)單的英語(yǔ)描述一下你想要的東西,然后按下回車鍵。你不必?fù)?dān)心搜索和價(jià)格比較,因?yàn)閼?yīng)用程序會(huì)自動(dòng)為你處理了。很酷,對(duì)吧?這正是我們將在本文中要構(gòu)建的目標(biāo)程序。

下面,先讓我們先看一些例子。

基于Llama 3的AI代理開發(fā)實(shí)戰(zhàn)演練-AI.x社區(qū)

用戶同時(shí)請(qǐng)求多個(gè)產(chǎn)品

基于Llama 3的AI代理開發(fā)實(shí)戰(zhàn)演練-AI.x社區(qū)

用戶咨詢他/她能做出的最劃算的購(gòu)買

接下來(lái),讓我們?yōu)檫@個(gè)應(yīng)用程序增強(qiáng)一些功能。我們將使用Meta公司開發(fā)的具有函數(shù)調(diào)用功能的Llama 3開源模型。不過(guò),本文示例程序也可以使用此模型的3.1版本來(lái)實(shí)現(xiàn)。根據(jù)Meta公司的公告(https://ai.meta.com/blog/meta-llama-3-1/),3.1版本模型可以更有效地使用工具和函數(shù)。

【注意】這些模型是支持多語(yǔ)言的,具有128K的更長(zhǎng)的上下文長(zhǎng)度和最先進(jìn)的工具使用能力和整體更強(qiáng)的推理能力。

我將在本文示例開發(fā)中使用Groq云平臺(tái),特別是他們?cè)诒疚闹械拇髷?shù)據(jù)模型。此應(yīng)用程序的初始工作流程包括一個(gè)嵌入模型、一個(gè)檢索器,還有兩個(gè)主要工具,用于處理用戶購(gòu)買興趣和與成本相關(guān)的問(wèn)題。總之,我們需要類似于下圖所述的組件內(nèi)容。

基于Llama 3的AI代理開發(fā)實(shí)戰(zhàn)演練-AI.x社區(qū)

示例應(yīng)用程序架構(gòu)圖

現(xiàn)在,我們必須要在開發(fā)中選擇使用一個(gè)LLM組件框架。為此,我選擇了我一直最喜歡的生產(chǎn)級(jí)開源AI平臺(tái)框架Haystack(https://haystack.deepset.ai/)。

準(zhǔn)備好了我們需要的內(nèi)容后,接下來(lái)就讓我們開始投入關(guān)鍵的開發(fā)工作吧!

加載和索引數(shù)據(jù)

由于我們本示例程序中使用了一個(gè)RAG管道,我們首先構(gòu)建一個(gè)文檔索引服務(wù),將使用Haystack提供的內(nèi)存向量數(shù)據(jù)庫(kù)。請(qǐng)注意,我們矢量數(shù)據(jù)庫(kù)中的每個(gè)文檔都包含如下字段:

  • 內(nèi)容(Content)——我們用來(lái)執(zhí)行相似性搜索的內(nèi)容
  • Id——唯一標(biāo)識(shí)符
  • 價(jià)格(Price)——產(chǎn)品價(jià)格
  • URL——產(chǎn)品URL

當(dāng)調(diào)用我們的RAG管道時(shí),Content字段用于向量搜索。所有其他字段都作為元數(shù)據(jù)包含在矢量數(shù)據(jù)庫(kù)中。注意,保存這些元數(shù)據(jù)是至關(guān)重要的,因?yàn)樗鼈冊(cè)谟脩舻那岸搜菔局兄陵P(guān)重要。

接下來(lái),讓我們看看如何實(shí)現(xiàn)這一點(diǎn)。

from haystack import Pipeline, Document
from haystack.document_stores.in_memory import InMemoryDocumentStore
from haystack.components.writers import DocumentWriter
from haystack.components.embedders import SentenceTransformersDocumentEmbedder
from haystack.components.generators import OpenAIGenerator
from haystack.utils import Secret
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.components.builders import PromptBuilder
from haystack.components.embedders import SentenceTransformersTextEmbedder
from haystack.components.retrievers.in_memory import InMemoryEmbeddingRetriever
from haystack.dataclasses import ChatMessage
import pandas as pd

#從CSV加載產(chǎn)品數(shù)據(jù)
df = pd.read_csv("product_sample.csv")

#初始化內(nèi)存中的文檔存儲(chǔ)區(qū)
document_store = InMemoryDocumentStore()

#將產(chǎn)品數(shù)據(jù)轉(zhuǎn)換為Haystack文檔對(duì)象
documents = [
Document(
content=item.product_name, 
meta={
"id": item.uniq_id, 
"price": item.selling_price, 
"url": item.product_url
}
) for item in df.itertuples()
]

#創(chuàng)建一個(gè)用于編制文檔索引的管道
indexing_pipeline = Pipeline()

#使用句子轉(zhuǎn)換器模型向管道中添加一個(gè)文檔嵌入器
indexing_pipeline.add_component(
instance=SentenceTransformersDocumentEmbedder(model="sentence-transformers/all-MiniLM-L6-v2"), name="doc_embedder"
)

# 向管道中添加文檔寫入器,以便在文檔存儲(chǔ)區(qū)中存儲(chǔ)文檔
indexing_pipeline.add_component(instance=DocumentWriter(document_store=document_store), name="doc_writer")

#將嵌入器的輸出連接到寫入器的輸入
indexing_pipeline.connect("doc_embedder.documents", "doc_writer.documents")

#運(yùn)行索引管道來(lái)處理和存儲(chǔ)文檔
indexing_pipeline.run({"doc_embedder": {"documents": documents}})

太好了,我們已經(jīng)完成了AI代理應(yīng)用程序的第一步。現(xiàn)在,是時(shí)候構(gòu)建產(chǎn)品標(biāo)識(shí)符函數(shù)工具了。為了更好地理解產(chǎn)品標(biāo)識(shí)符的主要任務(wù),讓我們考慮下面的示例。

用戶查詢內(nèi)容如下:

英語(yǔ)原文: I want to buy a camping boot, a charcoal and google pixel 9 back cover.

中文意思:我想買一雙露營(yíng)靴、一塊木炭和谷歌pixel 9手機(jī)外殼。

現(xiàn)在,先讓我們了解一下產(chǎn)品標(biāo)識(shí)符函數(shù)的理想化工作流程。

基于Llama 3的AI代理開發(fā)實(shí)戰(zhàn)演練-AI.x社區(qū)

產(chǎn)品標(biāo)識(shí)函數(shù)工作流程

首先,我們需要?jiǎng)?chuàng)建一個(gè)工具來(lái)分析用戶查詢并識(shí)別用戶感興趣的產(chǎn)品。我們可以使用下面的代碼片段構(gòu)建這樣一個(gè)工具。

構(gòu)建用戶查詢分析器

template = """
Understand the user query and list of products the user is interested in and return product names as list.
You should always return a Python list. Do not return any explanation.

Examples:
Question: I am interested in camping boots, charcoal and disposable rain jacket.
Answer: ["camping_boots","charcoal","disposable_rain_jacket"]

Question: Need a laptop, wireless mouse, and noise-cancelling headphones for work.
Answer: ["laptop","wireless_mouse","noise_cancelling_headphones"]

Question: {{ question }}
Answer:
"""

product_identifier = Pipeline()

product_identifier.add_component("prompt_builder", PromptBuilder(template=template))
product_identifier.add_component("llm", generator())

product_identifier.connect("prompt_builder", "llm")

好了,現(xiàn)在我們已經(jīng)完成了第一個(gè)函數(shù)的一半,現(xiàn)在是時(shí)候通過(guò)添加RAG管道來(lái)完成該函數(shù)了。

基于Llama 3的AI代理開發(fā)實(shí)戰(zhàn)演練-AI.x社區(qū)

產(chǎn)品標(biāo)識(shí)功能工作流程

創(chuàng)建RAG管道

template = """
Return product name, price, and url as a python dictionary. 
You should always return a Python dictionary with keys price, name and url for single product.
You should always return a Python list of dictionaries with keys price, name and url for multiple products.
Do not return any explanation.

Legitimate Response Schema:
{"price": "float", "name": "string", "url": "string"}
Legitimate Response Schema for multiple products:
[{"price": "float", "name": "string", "url": "string"},{"price": "float", "name": "string", "url": "string"}]

Context:
{% for document in documents %}
product_price: {{ document.meta['price'] }}
product_url: {{ document.meta['url'] }}
product_id: {{ document.meta['id'] }}
product_name: {{ document.content }}
{% endfor %}
Question: {{ question }}
Answer:
"""

rag_pipe = Pipeline()
rag_pipe.add_component("embedder", SentenceTransformersTextEmbedder(model="sentence-transformers/all-MiniLM-L6-v2"))
rag_pipe.add_component("retriever", InMemoryEmbeddingRetriever(document_store=document_store, top_k=5))
rag_pipe.add_component("prompt_builder", PromptBuilder(template=template))
rag_pipe.add_component("llm", generator())

rag_pipe.connect("embedder.embedding", "retriever.query_embedding")
rag_pipe.connect("retriever", "prompt_builder.documents")
rag_pipe.connect("prompt_builder", "llm")

執(zhí)行上面的代碼之后,我們就完成了RAG和查詢分析管道的構(gòu)建。現(xiàn)在是時(shí)候把它轉(zhuǎn)換成一個(gè)工具了。為此,我們可以使用常規(guī)函數(shù)聲明,如下所示。為AI代理創(chuàng)建工具就像創(chuàng)建Python函數(shù)一樣。如果你有類似于下面這樣的問(wèn)題:

代理如何調(diào)用這個(gè)函數(shù)?

解決方案很簡(jiǎn)單:利用特定于模型的工具模式。當(dāng)然,我們將在稍后的步驟中加入該模式。現(xiàn)在,是時(shí)候創(chuàng)建一個(gè)同時(shí)使用查詢分析器和RAG管道的包裝器函數(shù)了。

還是先讓我們來(lái)明確一下這個(gè)函數(shù)的目標(biāo)。

目標(biāo)1:識(shí)別用戶感興趣的所有產(chǎn)品,并將其作為列表返回。

目標(biāo)2:對(duì)于每個(gè)已識(shí)別的產(chǎn)品,從數(shù)據(jù)庫(kù)中檢索最多五個(gè)產(chǎn)品及其元數(shù)據(jù)。

實(shí)現(xiàn)產(chǎn)品標(biāo)識(shí)符函數(shù)

def product_identifier_func(query: str):
"""
根據(jù)給定的查詢來(lái)標(biāo)識(shí)產(chǎn)品,并檢索每個(gè)已標(biāo)識(shí)的產(chǎn)品的相關(guān)詳細(xì)信息。

參數(shù):
query (str): 用于標(biāo)識(shí)產(chǎn)品的查詢字符串。

返回值:
dict: 一個(gè)字典,其中鍵是產(chǎn)品名稱,值是每個(gè)產(chǎn)品的詳細(xì)信息。如果沒(méi)有找到產(chǎn)品,則返回“No product found”。
"""
product_understanding = product_identifier.run({"prompt_builder": {"question": query}})

try:
product_list = literal_eval(product_understanding["llm"]["replies"][0])
except:
return "No product found"

results = {}

for product in product_list:
response = rag_pipe.run({"embedder": {"text": product}, "prompt_builder": {"question": product}})
try:
results[product] = literal_eval(response["llm"]["replies"][0])
except:
results[product] = {}

return results

基于Llama 3的AI代理開發(fā)實(shí)戰(zhàn)演練-AI.x社區(qū)

產(chǎn)品標(biāo)識(shí)函數(shù)工作流程

至此,我們完成了代理的第一個(gè)工具的構(gòu)建。現(xiàn)在,先讓我們來(lái)看看它是否按預(yù)期工作。

query = "I want crossbow and woodstock puzzle"
#執(zhí)行函數(shù)
product_identifier_func(query)

# {'crossbow': {'name': 'DB Longboards CoreFlex Crossbow 41" Bamboo Fiberglass '
#                        'Longboard Complete',
#                'price': 237.68,
#                'url': 'https://www.amazon.com/DB-Longboards-CoreFlex-Fiberglass-Longboard/dp/B07KMVJJK7'},
#  'woodstock_puzzle': {'name': 'Woodstock- Collage 500 pc Puzzle',
#                       'price': 17.49,
#                       'url': 'https://www.amazon.com/Woodstock-Collage-500-pc-Puzzle/dp/B07MX21WWX'}}

成功了!然而,值得注意的是這里返回的輸出模式。下面給出輸出的總體模式架構(gòu)。

{
"product_key": {
"name": "string",
"price": "float",
"url": "string"
}
}

這正是我們建議RAG管道中生成的模式。下一步,讓我們構(gòu)建一個(gè)名為find_budget_friend_option的可選工具函數(shù)。

def find_budget_friendly_option(selected_product_details):
"""
為每一類產(chǎn)品找到最經(jīng)濟(jì)友好的選擇。

參數(shù):
selected_product_details (dict): 一個(gè)字典,其中的鍵是產(chǎn)品類別和值是列表的產(chǎn)品細(xì)節(jié)。每個(gè)產(chǎn)品的細(xì)節(jié)都應(yīng)該是一個(gè)包含一個(gè)“price”鍵的字典。

返回結(jié)果:
dict: 一個(gè)字典,其中鍵是產(chǎn)品類別,值是每個(gè)類別的最經(jīng)濟(jì)友好的產(chǎn)品詳細(xì)信息。
"""
budget_friendly_options = {}

for category, items in selected_product_details.items():
if isinstance(items, list):
lowest_price_item = min(items, key=lambda x: x['price'])
else:
lowest_price_item = items

budget_friendly_options[category] = lowest_price_item

return budget_friendly_options

讓我們關(guān)注這個(gè)應(yīng)用程序最關(guān)鍵的方面,也就是,讓AI代理能夠根據(jù)需要使用這些功能。正如我們之前所討論的,這可以通過(guò)特定于模型的工具模式來(lái)實(shí)現(xiàn)。因此,我們需要定位特定于所選模型的工具模式。幸運(yùn)的是,Groq模型庫(kù)(https://huggingface.co/Groq/Llama-3-Groq-70B-Tool-Use)中提到了這一點(diǎn)。我們僅需要把它調(diào)整一下,以適應(yīng)我們的使用場(chǎng)景即可。

最終確定聊天模板

chat_template = '''<|start_header_id|>system<|end_header_id|>

You are a function calling AI model. You are provided with function signatures within <tools></tools> XML tags. You may call one or more functions to assist with the user query. Don't make assumptions about what values to plug into functions. For each function call return a json object with function name and arguments within <tool_call></tool_call> XML tags as follows:
<tool_call>
{"name": <function-name>,"arguments": <args-dict>}
</tool_call>

Here are the available tools:
<tools>
{
"name": "product_identifier_func",
"description": "To understand user interested products and its details",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The query to use in the search. Infer this from the user's message. It should be a question or a statement"
}
},
"required": ["query"]
}
},
{
"name": "find_budget_friendly_option",
"description": "Get the most cost-friendly option. If selected_product_details has morethan one key this should return most cost-friendly options",
"parameters": {
"type": "object",
"properties": {
"selected_product_details": {
"type": "dict",
"description": "Input data is a dictionary where each key is a category name, and its value is either a single dictionary with 'price', 'name', and 'url' keys or a list of such dictionaries; example: {'category1': [{'price': 10.5, 'name': 'item1', 'url': 'http://example.com/item1'}, {'price': 8.99, 'name': 'item2', 'url': 'http://example.com/item2'}], 'category2': {'price': 15.0, 'name': 'item3', 'url': 'http://example.com/item3'}}"
}
},
"required": ["selected_product_details"]
}
}
</tools><|eot_id|><|start_header_id|>user<|end_header_id|>

I need to buy a crossbow<|eot_id|><|start_header_id|>assistant<|end_header_id|>

<tool_call>
{"id":"call_deok","name":"product_identifier_func","arguments":{"query":"I need to buy a crossbow"}}
</tool_call><|eot_id|><|start_header_id|>tool<|end_header_id|>

<tool_response>
{"id":"call_deok","result":{'crossbow': {'price': 237.68,'name': 'crossbow','url': 'https://www.amazon.com/crossbow/dp/B07KMVJJK7'}}}
</tool_response><|eot_id|><|start_header_id|>assistant<|end_header_id|>
'''

現(xiàn)在,只剩下幾步了。在做任何事情之前,還是先讓我們來(lái)測(cè)試一下我們的代理。

##測(cè)試代理
messages = [
ChatMessage.from_system(
chat_template
),
ChatMessage.from_user("I need to buy a crossbow for my child and Pokémon for myself."),
]

chat_generator = get_chat_generator()
response = chat_generator.run(messages=messages)
pprint(response)

## 響應(yīng)結(jié)果
{'replies': [ChatMessage(content='<tool_call>\n'
'{"id": 0, "name": "product_identifier_func", '
'"arguments": {"query": "I need to buy a '
'crossbow for my child"}}\n'
'</tool_call>\n'
'<tool_call>\n'
'{"id": 1, "name": "product_identifier_func", '
'"arguments": {"query": "I need to buy a '
'Pokemon for myself"}}\n'
'</tool_call>',
role=<ChatRole.ASSISTANT: 'assistant'>,
name=None,
meta={'finish_reason': 'stop',
'index': 0,
'model': 'llama3-groq-70b-8192-tool-use-preview',
'usage': {'completion_time': 0.217823967,
'completion_tokens': 70,
'prompt_time': 0.041348261,
'prompt_tokens': 561,
'total_time': 0.259172228,
'total_tokens': 631}})]}

至此,我們已經(jīng)完成了大約90%的工作。

基于Llama 3的AI代理開發(fā)實(shí)戰(zhàn)演練-AI.x社區(qū)

工作接近尾聲。

在上述響應(yīng)結(jié)果中,你可能已經(jīng)注意到XML標(biāo)簽<tool_call>包含了工具調(diào)用。因此,我們需要開發(fā)一種機(jī)制來(lái)提取tool_call對(duì)象。

def extract_tool_calls(tool_calls_str):
json_objects = re.findall(r'<tool_call>(.*?)</tool_call>', tool_calls_str, re.DOTALL)

result_list = [json.loads(obj) for obj in json_objects]

return result_list

available_functions = {
"product_identifier_func": product_identifier_func, 
"find_budget_friendly_option": find_budget_friendly_option
}

完成此步驟后,當(dāng)代理調(diào)用工具時(shí),我們可以直接訪問(wèn)代理的響應(yīng)。現(xiàn)在唯一懸而未決的是獲取工具調(diào)用對(duì)象并相應(yīng)地執(zhí)行函數(shù)。讓我們也把這一部分完成。

messages.append(ChatMessage.from_user(message))
response = chat_generator.run(messages=messages)

if response and "<tool_call>" in response["replies"][0].content:
function_calls = extract_tool_calls(response["replies"][0].content)
for function_call in function_calls:
# 解析函數(shù)調(diào)用信息
function_name = function_call["name"]
function_args = function_call["arguments"]

#找到相應(yīng)的函數(shù)并用給定的參數(shù)調(diào)用它
function_to_call = available_functions[function_name]
function_response = function_to_call(**function_args)

# 使用`ChatMessage.from_function`在消息列表中附加函數(shù)響應(yīng)
messages.append(ChatMessage.from_function(content=json.dumps(function_response), name=function_name))
response = chat_generator.run(messages=messages)

現(xiàn)在,是時(shí)候?qū)⑶懊娴拿總€(gè)組件連接在一起,從而構(gòu)建一個(gè)完整的聊天應(yīng)用程序了。為此,我選擇使用強(qiáng)大的開源的深度學(xué)習(xí)模型可視化工具Gradio。

import gradio as gr

messages = [ChatMessage.from_system(chat_template)]
chat_generator = get_chat_generator()

def chatbot_with_fc(message, messages):
messages.append(ChatMessage.from_user(message))
response = chat_generator.run(messages=messages)

while True:
if response and "<tool_call>" in response["replies"][0].content:
function_calls = extract_tool_calls(response["replies"][0].content)
for function_call in function_calls:
#解析函數(shù)調(diào)用信息
function_name = function_call["name"]
function_args = function_call["arguments"]

#找到相應(yīng)的函數(shù)并用給定的參數(shù)調(diào)用它
function_to_call = available_functions[function_name]
function_response = function_to_call(**function_args)

# 使用`ChatMessage.from_function`在消息列表中附加函數(shù)響應(yīng)
messages.append(ChatMessage.from_function(content=json.dumps(function_response), name=function_name))
response = chat_generator.run(messages=messages)

# 定期對(duì)話
else:
messages.append(response["replies"][0])
break
return response["replies"][0].content


def chatbot_interface(user_input, state):
response_content = chatbot_with_fc(user_input, state)
return response_content, state

with gr.Blocks() as demo:
gr.Markdown("# AI Purchase Assistant")
gr.Markdown("Ask me about products you want to buy!")

state = gr.State(value=messages)

with gr.Row():
user_input = gr.Textbox(label="Your message:")
response_output = gr.Markdown(label="Response:")

user_input.submit(chatbot_interface, [user_input, state], [response_output, state])
gr.Button("Send").click(chatbot_interface, [user_input, state], [response_output, state])


demo.launch()

就是這么簡(jiǎn)單!至此,我們已經(jīng)成功構(gòu)建了一個(gè)基于Llama 3模型的人工智能代理程序,它本身具有函數(shù)調(diào)用功能。你可以從GitHub倉(cāng)庫(kù)(https://github.com/Ransaka/ai-agents-with-llama3)訪問(wèn)其完整的源代碼。

此外,你可以通過(guò)Kaggle鏈接(https://www.kaggle.com/datasets/promptcloud/amazon-product-dataset-2020)訪問(wèn)本文中使用的數(shù)據(jù)集。

結(jié)論

歸納來(lái)看,在構(gòu)建基于人工智能代理的系統(tǒng)程序時(shí),重要的是要考慮完成任務(wù)所需的時(shí)間以及每個(gè)任務(wù)所使用的API調(diào)用(令牌)的數(shù)量。這方面開發(fā)面臨的一個(gè)主要挑戰(zhàn)是減少系統(tǒng)中的幻覺(jué),這也是當(dāng)前一個(gè)十分活躍的研究領(lǐng)域。因此,構(gòu)建LLM和代理系統(tǒng)沒(méi)有固定的規(guī)則。開發(fā)團(tuán)隊(duì)有必要耐心和戰(zhàn)略性地規(guī)劃工作,以確保人工智能代理LLM正常運(yùn)行。

最后,除非另有說(shuō)明,本文中所有圖片均由作者本人提供。

參考資料

譯者介紹

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

原文標(biāo)題:Using Llama 3 for Building AI Agents,作者:Ransaka Ravihara

?著作權(quán)歸作者所有,如需轉(zhuǎn)載,請(qǐng)注明出處,否則將追究法律責(zé)任
已于2024-8-7 08:29:15修改
收藏
回復(fù)
舉報(bào)
回復(fù)
相關(guān)推薦
给我免费播放日韩视频| 草草草视频在线观看| 3d黄动漫网站| 国产亚洲在线| 久久久国产一区二区| av电影在线观看| 国产精品无人区| 亚洲欧美精品在线观看| 日韩黄色大片| 精品国内亚洲在观看18黄| 日本福利在线| 一区二区三区四区视频精品免费| 欧美 日韩 国产精品| 欧美激情1区2区3区| 欧美中在线观看| 成人在线日韩| 精品国产乱码久久| 欧美黄色小说| 中文字幕一区免费在线观看| 四虎4hu永久免费入口| 国产手机视频一区二区 | 麻豆精品蜜桃| 欧美一卡二卡三卡| 蜜桃视频在线观看视频| 亚洲人成网站精品片在线观看| 国产精品自拍合集| 日韩av成人高清| 久久99导航| 在线精品国产| 国产免费成人av| 国产欧美三级电影| 久久精品视频99| 久久亚洲精品人成综合网| 精品99999| 日本一级理论片在线大全| 欧美视频在线观看一区| 一级在线视频| 偷窥少妇高潮呻吟av久久免费| 99re6在线视频| 国产精品无遮挡| 四虎国产精品成人免费4hu| 国产午夜亚洲精品不卡| 国产91在线视频观看| 国产在线一区观看| 亚洲区成人777777精品| 国产呦萝稀缺另类资源| 亚洲最新免费视频| 精品一区二区av| 日韩在线视频在线| 国产一区二区三区在线观看精品| 伊人久久大香线蕉成人综合网| 激情欧美日韩一区二区| 桥本有菜av在线| 成人深夜在线观看| 人人妻人人添人人爽欧美一区| 国产91高潮流白浆在线麻豆 | 91精品天堂福利在线观看| 国产成人拍精品视频午夜网站| 欧美日韩一区二区三区不卡视频| 色综合久综合久久综合久鬼88 | 中文日产幕无线码一区二区| 亚洲精品乱码久久久久久按摩观| yellow在线观看网址| 国产小视频91| 亚瑟国产精品| 午夜精品在线视频| 日韩电影在线视频| 国产亚洲欧美另类一区二区三区| 蜜乳av另类精品一区二区| 资源网第一页久久久| 成人亚洲一区二区一| 国产精品wwwww| 亚洲一区二区三区国产| 免费在线高清av| 日韩欧美电影一二三| 亚洲精品一级二级| 欧美另类第一页| 91中文字幕精品永久在线| 久久久婷婷一区二区三区不卡| 国内精品国产三级国产a久久| 国产淫片免费看| 亚洲自拍另类综合| 青春草视频在线| 久久69精品久久久久久国产越南| 日韩精选在线| 99re资源| 成人av在线资源| 992tv在线| 亚洲级视频在线观看免费1级| 美女精品久久| av一区二区三区免费| 国产精品资源在线看| 国产真实伦在线观看| 日韩一区二区在线播放| 日韩精品免费视频一区二区三区| 国产在线不卡精品| 精品一区二区久久久| 男人插女人欧美| 欧美成人一区二区| 欧美人妖在线观看| 久久久久资源| 亚洲少妇屁股交4| 日韩伦理在线一区| 国产精品电影网站| 国产在线精品免费av| 亚洲人成77777男人| 最新国产精品拍自在线播放| 91青青国产在线观看精品| 最新不卡av| 欧美视频裸体精品| 成人在线不卡| 国产伦精品一区二区三区照片| 99久久国产综合精品色伊| 福利在线播放| 久久久视频在线| 美腿丝袜一区二区三区| 一个人看的免费视频色| 国产亚洲精品成人av久久ww| 99视频精品全国免费| 亚洲 欧美 综合 另类 中字| 91久久国产综合久久| 少妇久久久久| 人人妻人人澡人人爽欧美一区| 欧美怡红院视频| 亚洲国产最新| 农村妇女精品一二区| 日韩精品免费在线视频| 欧美在线网站| av女同在线| 97视频人免费观看| 丁香一区二区三区| 色女人在线视频| av资源一区二区| 一区二区三区四区乱视频| 成人在线高清| 综合色婷婷一区二区亚洲欧美国产| 欧洲视频一区二区| 欧美网色网址| 青青草原av在线播放| 国产亚洲成精品久久| 久久国产精品久久w女人spa| 亚洲精华国产精华| 欧美影院在线播放| 国产欧美在线观看一区| 国产探花视频在线观看| 亚洲综合一区二区不卡| 亚洲精品日产精品乱码不卡| 日韩电影精品| 全黄性性激高免费视频| 日韩精品高清在线| 久久资源在线| 偷拍自拍在线| 日本亚洲欧洲色| 国产精品理伦片| 欧美三级午夜理伦三级小说| 在线观看成人黄色| 亚洲不卡av不卡一区二区| av免费中文字幕| 欧美成人精精品一区二区频| 欧美精品日韩| 国产三级视频在线看| 91视频-88av| 亚洲国产婷婷综合在线精品| 天海翼精品一区二区三区| 国产黄色免费网| 国产日韩在线视频| 欧洲人成人精品| 蜜桃av一区| 成人日韩在线观看| 欧美日韩在线免费观看视频| 精品国产一区二区三区久久久蜜月 | 中文字幕免费国产精品| 日韩视频一区在线观看| 欧美一区三区二区| 91丝袜美腿高跟国产极品老师| 99久久精品网站| 1024日韩| 999久久久精品国产| 日韩精品免费观看视频| 日本高清中文字幕在线| 4444在线观看| 国产黄视频在线观看| 九九视频精品在线观看| av男人的天堂网| 黄色成人在线网| 国产乱码精品一区二区三区四区| 亚洲二区在线| 中文一区二区在线观看| 欧美人动与zoxxxx乱| 另类色图亚洲色图| 国产一区二区三区四区五区在线| 久久av综合网| av影片在线看| 欧美天天在线| 欧美日韩国产激情| 国产一区二区三区三区在线观看| 久久伊人免费视频| 国产av熟女一区二区三区| 欧美黄色小说| 久久精品一区二区国产|