價(jià)格方面,DeepSeek-V2 API 的價(jià)格為 每百萬(wàn) tokens 輸入 1 元、輸出 2 元(32K 上下文),價(jià)格僅為 GPT-4-Turbo 的近百分之一,LLaMA3-70B 出來(lái)時(shí)的成本已經(jīng)震驚我了,DeepSeek-V2 這波屬于是殺紅眼了 ??,對(duì)應(yīng)用層是極大的利好。

DeepSeek-V2 在中文方面是最好用的,價(jià)格也是最便宜的(社區(qū)里微調(diào) LLaMA3-70B 中文版的朋友估計(jì)哭暈在廁所了 ??)

3. DeepSeek-V2 為什么這么強(qiáng)

對(duì) Transformer 架構(gòu)中的自注意力機(jī)制進(jìn)行了全方位的創(chuàng)新

更詳細(xì)的技術(shù)解讀請(qǐng)看這篇 ?? 幻方發(fā)布全球最強(qiáng) MOE 大模型!DeepSeek-V2

4. 更多內(nèi)容

總結(jié)

一句話(huà)總結(jié):參數(shù)更多、能力更強(qiáng)、成本更低!當(dāng)然能不能干活,我得試了才知道,所以我決定使用 LangChainLangGraph 組件構(gòu)建一個(gè)編碼類(lèi) Agent 測(cè)試下(編碼能力、工具調(diào)用能力、推理能力),順便提下,自從上次 LLaMA3-70B 發(fā)布,我還在測(cè)試其在各類(lèi)開(kāi)源 Agent 項(xiàng)目中的實(shí)際效果,接下來(lái)要替換為 DeepSeek-V2 了。

LangGraph 介紹

LangGraph 是一套構(gòu)建于 LangChain 框架之上的開(kāi)發(fā)組件,可以與 LangChain 現(xiàn)有的鏈(Chain)、LCEL(LangChain Express Language)等無(wú)縫協(xié)作,與其生態(tài)系統(tǒng)完全兼容。

LangGraph 受到 NetworkX 框架的啟發(fā),將應(yīng)用流程抽象為一個(gè)圖,其中節(jié)點(diǎn)表示一個(gè)函數(shù)調(diào)用或一次大模型調(diào)用,而邊(則代表了節(jié)點(diǎn)的執(zhí)行順序(即數(shù)據(jù)流),并且可以通過(guò)設(shè)置條件邊(conditional edge)來(lái)實(shí)現(xiàn)流程的分支控制,進(jìn)而基于此圖編譯生成相應(yīng)的應(yīng)用。在任務(wù)執(zhí)行期間,系統(tǒng)維護(hù)一個(gè)中央狀態(tài)對(duì)象(state),該對(duì)象會(huì)隨著節(jié)點(diǎn)跳轉(zhuǎn)而持續(xù)更新,其包含的屬性可根據(jù)需求自由定義,這種方式使得創(chuàng)建具有狀態(tài)管理和可控循環(huán)的 LLM 應(yīng)用變得容易,比如多 Agent 應(yīng)用。LangGraph 的作用包括:

下面是官方通過(guò)使用 LangGraph 構(gòu)建 RAG 應(yīng)用的示意圖,晰地闡釋了 LangGraph 中的 3 個(gè)核心概念:

– StateGraph:狀態(tài)圖。通過(guò)提供狀態(tài)定義來(lái)初始化此類(lèi),該狀態(tài)定義代表了一個(gè)隨時(shí)間推移而更新的核心狀態(tài)對(duì)象。

代碼示例

下面的代碼展示了如何基于 DeepSeek-V2 和 LangGraph 實(shí)現(xiàn)一個(gè) AI 編碼代理,為 Python 代碼自動(dòng)編寫(xiě)單元測(cè)試。部分代碼參考自 Build an AI Coding Agent with LangGraph by LangChain[3]

配置環(huán)境

首先配置環(huán)境,并安裝基礎(chǔ)依賴(lài)。

mkdir langgraph_test && cd langgraph_test
python3 -m venv env
source env/bin/activate
pip install langgraph langchain langchain_openai colorama

創(chuàng)建示例文件

將code字符串寫(xiě)入到文件中

# 定義搜索路徑,即app目錄的絕對(duì)路徑
search_path = os.path.join(os.getcwd(), "app")

# 定義crud.py文件的路徑,該文件位于search_path/src目錄下
code_file = os.path.join(search_path, "src/crud.py")

# 定義測(cè)試文件test_crud.py的路徑,該文件位于search_path/test目錄下
test_file = os.path.join(search_path, "test/test_crud.py")

# 檢查search_path路徑是否存在,如果不存在則創(chuàng)建
if not os.path.exists(search_path):
os.mkdir(search_path)

# 創(chuàng)建search_path目錄
os.mkdir(os.path.join(search_path, "src"))

# 在search_path下創(chuàng)建src目錄
os.mkdir(os.path.join(search_path, "test"))

# 在search_path下創(chuàng)建test目錄

# 定義一個(gè)包含Item類(lèi)和CRUDApp類(lèi)的字符串,這些類(lèi)將被寫(xiě)入到code_file文件中
code = """
class Item:
def __init__(self, id, name, description=None):
self.id = id

# 初始化Item對(duì)象的id屬性
self.name = name

# 初始化Item對(duì)象的name屬性
self.description = description

# 初始化Item對(duì)象的description屬性,可省略

def __repr__(self):

# 定義對(duì)象的字符串表示方法,便于打印和調(diào)試
return f"Item(id={self.id}, name={self.name}, description={self.description})"

class CRUDApp:
def __init__(self):
self.items = []

# 初始化一個(gè)空列表,用于存儲(chǔ)Item對(duì)象

def create_item(self, id, name, description=None):

# 創(chuàng)建一個(gè)Item對(duì)象,并將其添加到items列表中
item = Item(id, name, description)
self.items.append(item)
return item

# 返回創(chuàng)建的Item對(duì)象

def read_item(self, id):

# 根據(jù)id讀取Item對(duì)象
for item in self.items:
if item.id == id:
return item

# 如果找到匹配的id,返回Item對(duì)象
return None

# 如果沒(méi)有找到匹配的id,返回None

def update_item(self, id, name=None, description=None):

# 根據(jù)id更新Item對(duì)象的name和/或description屬性
for item in self.items:
if item.id == id:
if name:
item.name = name

# 如果提供了name,更新Item對(duì)象的name屬性
if description:
item.description = description

# 如果提供了description,更新Item對(duì)象的description屬性
return item

# 更新完成后返回Item對(duì)象
return None

# 如果沒(méi)有找到匹配的id,返回None

def delete_item(self, id):

# 根據(jù)id刪除Item對(duì)象
for index, item in enumerate(self.items):
if item.id == id:
return self.items.pop(index)

# 如果找到匹配的id,從列表中移除Item對(duì)象并返回
return None

# 如果沒(méi)有找到匹配的id,返回None

def list_items(self):

# 返回所有存儲(chǔ)的Item對(duì)象的列表
return self.items
"""

# 使用with語(yǔ)句打開(kāi)code_file文件進(jìn)行寫(xiě)入
with open(code_file, 'w') as f:
f.write(code)

# 將code字符串寫(xiě)入到文件中

示例文件創(chuàng)建好后,接下來(lái)編寫(xiě) Agent 處理邏輯,即為這段代碼(code 字符串內(nèi)容)自動(dòng)生成單元測(cè)試。

編寫(xiě) Agent 應(yīng)用

大模型 API

開(kāi)始之前先設(shè)置好 DeepSeek-V2 大模型,由于 API 格式與 OpenAI 兼容 ,所以可以直接使用 OpenAI SDK (langchain_openai)來(lái)訪(fǎng)問(wèn) DeepSeek API。

llm = ChatOpenAI(base_url="https://api.deepseek.com/v1",
api_key=os.getenv("DEEPSEEK_KEY"),
model="deepseek-chat")

1. 定義 StateGraph

首先定義一個(gè) AgentState,負(fù)責(zé)在執(zhí)行過(guò)程中跟蹤代理的狀態(tài)。這主要是一個(gè) TypedDict 類(lèi),其中包含 Agent 狀態(tài)相關(guān)屬性。

class AgentState(TypedDict):

# 定義AgentState類(lèi)型,用于存儲(chǔ)代理的狀態(tài)
class_source: str
class_methods: List[str]
tests_source: str# 創(chuàng)建StateGraph
workflow = StateGraph(AgentState)

class_source 存儲(chǔ)代碼中的 Python 類(lèi)名稱(chēng),class_methods 用于存儲(chǔ) Python 類(lèi)類(lèi)的方法,tests_source 用于存儲(chǔ)生成的單元測(cè)試代碼。

2. 定義節(jié)點(diǎn)

現(xiàn)在為 AgentState 添加節(jié)點(diǎn),這里需要定義 3 個(gè)節(jié)點(diǎn),一個(gè)用于查找類(lèi)方法的節(jié)點(diǎn),一個(gè)用于更新單元測(cè)試到狀態(tài)對(duì)象的節(jié)點(diǎn),一個(gè)用于將生成的單元測(cè)試寫(xiě)入測(cè)試文件的節(jié)點(diǎn)

代碼解析函數(shù)

開(kāi)始之前先聲明一個(gè)提取源代碼的工具函數(shù),這里假設(shè)代碼片段在“`內(nèi)

def extract_code_from_message(message):
lines = message.split("n")

# 按行分割消息
code = ""
in_code = False# 標(biāo)記是否在代碼塊中
for line in lines:
if "```" in line:# 檢查是否是代碼塊的開(kāi)始或結(jié)束
in_code = not in_code
elif in_code:# 如果在代碼塊中,則累加代碼
code += line + "n"
return code# 返回提取的代碼

現(xiàn)在開(kāi)始定義節(jié)點(diǎn)

節(jié)點(diǎn) 1 用于查找類(lèi)方法的節(jié)點(diǎn)

節(jié)點(diǎn)對(duì)應(yīng)的函數(shù)

)

# 沒(méi)有要寫(xiě)的測(cè)試”且不要包含類(lèi)。
示例:
def test_function():
...
請(qǐng)務(wù)必遵循指令并編寫(xiě)高質(zhì)量的測(cè)試,不要寫(xiě)測(cè)試類(lèi),只寫(xiě)方法。
"""

import_prompt_template = """
這是一條包含代碼文件路徑的信息:{code_file}。
這是一條包含測(cè)試文件路徑的信息:{test_file}。
請(qǐng)為文件中的類(lèi)編寫(xiě)正確的導(dǎo)入語(yǔ)句。
"""

# 發(fā)現(xiàn)類(lèi)及其方法
def discover_function(state: AgentState):
assert os.path.exists(code_file)

# 確保代碼文件存在
with open(code_file, "r") as f:

# 打開(kāi)代碼文件進(jìn)行讀取
source = f.read()

# 讀取文件內(nèi)容
state["class_source"] = source

# 將源代碼存儲(chǔ)在狀態(tài)中

# 獲取方法
methods = []
for line in source.split("n"):
if "def " in line:

# 如果行中包含def,表示這是一個(gè)方法定義
methods.append(line.split("def ")[1].split("(")[0])
state["class_methods"] = methods

# 將方法名存儲(chǔ)在狀態(tài)中

# 生成導(dǎo)入語(yǔ)句并啟動(dòng)代碼
import_prompt = import_prompt_template.format(
code_file=code_file,

# 格式化導(dǎo)入提示模板
test_file=test_file
)
message = llm.invoke([HumanMessage(content=import_prompt)]).content

# 調(diào)用模型生成消息
code = extract_code_from_message(message)

# 提取消息中的代碼
state["tests_source"] = code + "nn"

# 將測(cè)試源代碼存儲(chǔ)在狀態(tài)中

return state

# 返回更新后的狀態(tài)

# 將節(jié)點(diǎn)添加到工作流中
workflow.add_node(
"discover",

# 節(jié)點(diǎn)名稱(chēng)
discover_function

# 節(jié)點(diǎn)對(duì)應(yīng)的函數(shù)
)

上面的代碼片段中從 AgentState 的 class_source 元素中提取代碼,并將它們傳遞給 LLM ,然后將 LLM 的響應(yīng)存儲(chǔ)在 AgentState 的 tests_source 元素中。

節(jié)點(diǎn) 2 更新單元測(cè)試到狀態(tài)對(duì)象的節(jié)點(diǎn)

將編寫(xiě)測(cè)試節(jié)點(diǎn)添加到工作流中

workflow.add_node(
"write_tests",
write_tests_function
)

def write_tests_function(state: AgentState):

# 獲取下一個(gè)要編寫(xiě)測(cè)試的方法
class_method = state["class_methods"].pop(0)
print(f"為{class_method}編寫(xiě)測(cè)試。")

# 獲取源代碼
class_source = state["class_source"]

# 創(chuàng)建提示
write_test_prompt = write_test_template.format(
class_source=class_source,
class_method=class_method
)
print(colorama.Fore.CYAN + write_test_prompt + colorama.Style.RESET_ALL)

# 打印提示信息

# 獲取測(cè)試源代碼
system_message = SystemMessage(system_message_template)

# 創(chuàng)建系統(tǒng)消息
human_message = HumanMessage(write_test_prompt)

# 創(chuàng)建人類(lèi)消息
test_source = llm.invoke([system_message, human_message]).content

# 調(diào)用模型生成測(cè)試代碼
test_source = extract_code_from_message(test_source)

# 提取消息中的測(cè)試代碼
print(colorama.Fore.GREEN + test_source + colorama.Style.RESET_ALL)

# 打印測(cè)試代碼
state["tests_source"] += test_source + "nn"

# 將測(cè)試源代碼添加到狀態(tài)中

return state

# 返回更新后的狀態(tài)

# 將編寫(xiě)測(cè)試節(jié)點(diǎn)添加到工作流中
workflow.add_node(
"write_tests",
write_tests_function
)

讓 LLM 為每個(gè)方法編寫(xiě)測(cè)試用例,并更新到 AgentState 的 tests_source 元素中。

節(jié)點(diǎn) 3 將生成的單元測(cè)試寫(xiě)入測(cè)試文件

# 編寫(xiě)文件
def write_file(state: AgentState):
with open(test_file, "w") as f:

# 打開(kāi)測(cè)試文件進(jìn)行寫(xiě)入
f.write(state["tests_source"])# 寫(xiě)入測(cè)試源代碼
return state# 返回狀態(tài)# 將寫(xiě)文件節(jié)點(diǎn)添加到工作流中
workflow.add_node(
"write_file",
write_file
)

3. 定義邊

現(xiàn)在已經(jīng)有 3 個(gè)節(jié)點(diǎn),接下來(lái)定義邊用于指定它們之間的執(zhí)行方向。Agent 工作流從查找類(lèi)方法的節(jié)點(diǎn)開(kāi)始執(zhí)行,然后轉(zhuǎn)到編寫(xiě)單元測(cè)試的節(jié)點(diǎn)。

“`

定義入口點(diǎn),這是流程開(kāi)始的地方

workflow.set_entry_point("discover")

總是從discover跳轉(zhuǎn)到write_tests

workflow.add_edge("discover", "write_tests")

add_conditional_edge 函數(shù)添加了 write_tests 函數(shù)和 should_continue 函數(shù),該函數(shù)根據(jù) class_methods 條目決定采取哪一步,

判斷是否完成

def should_continue(state: AgentState):
if len(state["class_methods"]) == 0:

如果沒(méi)有更多的方法要測(cè)試

    return "end"

結(jié)束流程

else:
return "continue"

繼續(xù)流程

添加條件邊

workflow.add_conditional_edges(
"write_tests",

條件邊的起始節(jié)點(diǎn)

should_continue,

條件函數(shù)

{
"continue": "write_tests",

如果應(yīng)該繼續(xù),則再次執(zhí)行write_tests節(jié)點(diǎn)

    "end": "write_file"

如果結(jié)束,則跳轉(zhuǎn)到write_file節(jié)點(diǎn)

}

)

總是從write_file跳轉(zhuǎn)到END

workflow.add_edge("write_file", END)

當(dāng)從 LLM 生成所有方法的單元測(cè)試后,測(cè)試代碼被寫(xiě)入測(cè)試文件。

### __4. 執(zhí)行工作流__

最后剩下的就是編譯工作流并運(yùn)行它。

app = workflow.compile()

編譯工作流

inputs = {}

輸入?yún)?shù)

config = RunnableConfig(recursion_limit=100)

設(shè)置遞歸限制

try:
result = app.invoke(inputs, config)

運(yùn)行應(yīng)用

print(result)

打印結(jié)果

except GraphRecursionError:

如果達(dá)到遞歸限制

print("達(dá)到圖遞歸限制。")

打印錯(cuò)誤信息

遞歸限制是給定工作流的 LLM 進(jìn)行循環(huán)推理的次數(shù),當(dāng)超過(guò)限制時(shí),工作流停止。

### __5. 生成的單元測(cè)試文件__

下面是最終生成的 test_crud.py 文件的內(nèi)容,大家自行評(píng)判。

class TestDict(unittest.TestCase):
def test_crudapp_init():

創(chuàng)建一個(gè)CRUDApp實(shí)例

    app = CRUDApp()

驗(yàn)證items列表是否為空

    assert app.items == []

def test_item_repr():
item = Item(1, 'Test Item', 'This is a test item')
expected_repr = "Item(id=1, name=Test Item, description=This is a test item)"
assert repr(item) == expected_repr

def test_crudapp_init():

創(chuàng)建一個(gè)CRUDApp實(shí)例

    app = CRUDApp()

驗(yàn)證items列表是否為空

    assert app.items == []

def test_create_item():

初始化CRUDApp實(shí)例

    app = CRUDApp()

創(chuàng)建一個(gè)新項(xiàng)目

    item = app.create_item(1, 'Test Item')

斷言項(xiàng)目已創(chuàng)建并存在于項(xiàng)目列表中

    assert item in app.list_items()
assert item.id == 1
assert item.name == 'Test Item'
assert item.description is None

創(chuàng)建另一個(gè)項(xiàng)目,確保ID是唯一的

    another_item = app.create_item(2, 'Another Test Item')
assert another_item in app.list_items()
assert another_item.id == 2
assert another_item.name == 'Another Test Item'
assert another_item.description is None

斷言列表中的項(xiàng)目數(shù)量正確

    assert len(app.list_items()) == 2

def test_read_item():

初始化CRUDApp實(shí)例

    app = CRUDApp()

創(chuàng)建一個(gè)測(cè)試項(xiàng)

    test_item = app.create_item(1, 'Test Item')

測(cè)試讀取存在的項(xiàng)

    read_item = app.read_item(1)
assert read_item == test_item

測(cè)試讀取不存在的項(xiàng)

    non_existent_item = app.read_item(99)
assert non_existent_item is None

def test_update_item():

初始化CRUDApp實(shí)例

    app = CRUDApp()

創(chuàng)建一個(gè)測(cè)試用的Item

    item = app.create_item(1, 'Test Item')

更新Item的名稱(chēng)

    updated_item = app.update_item(1, 'Updated Test Item')

驗(yàn)證更新是否成功

    assert updated_item is not None
assert updated_item.id == 1
assert updated_item.name == 'Updated Test Item'
assert updated_item.description is None

驗(yàn)證列表中的Item是否更新

    listed_items = app.list_items()
assert len(listed_items) == 1
assert listed_items[0].id == 1
assert listed_items[0].name == 'Updated Test Item'
assert listed_items[0].description is None

嘗試更新不存在的Item

    non_existent_item = app.update_item(2, 'Non Existent Item')
assert non_existent_item is None

更新Item的描述

    updated_item_description = app.update_item(1, description='Updated Test Description')

驗(yàn)證更新是否成功

    assert updated_item_description is not None
assert updated_item_description.id == 1
assert updated_item_description.name == 'Updated Test Item'
assert updated_item_description.description == 'Updated Test Description'

驗(yàn)證列表中的Item是否更新

    listed_items = app.list_items()
assert len(listed_items) == 1
assert listed_items[0].id == 1
assert listed_items[0].name == 'Updated Test Item'
assert listed_items[0].description == 'Updated Test Description'

def test_delete_item():

創(chuàng)建一個(gè)CRUDApp實(shí)例

    app = CRUDApp()

創(chuàng)建一些測(cè)試用的Item對(duì)象

    item1 = app.create_item(1, 'Item 1')
item2 = app.create_item(2, 'Item 2')

驗(yàn)證創(chuàng)建的Item對(duì)象是否在列表中

    assert item1 in app.list_items()
assert item2 in app.list_items()

刪除一個(gè)Item對(duì)象

    deleted_item = app.delete_item(1)

驗(yàn)證刪除操作是否成功

    assert deleted_item == item1
assert item1 not in app.list_items()
assert item2 in app.list_items()

嘗試刪除一個(gè)不存在的Item對(duì)象

    deleted_nonexistent_item = app.delete_item(3)

驗(yàn)證刪除不存在的Item對(duì)象時(shí)返回None

    assert deleted_nonexistent_item is None

def test_list_items():

創(chuàng)建一個(gè)CRUDApp實(shí)例

    app = CRUDApp()

創(chuàng)建一些測(cè)試用的Item實(shí)例

    item1 = app.create_item(1, 'Item 1')
item2 = app.create_item(2, 'Item 2', 'This is item 2')

調(diào)用list_items方法并檢查返回的列表是否包含我們創(chuàng)建的Item實(shí)例

    listed_items = app.list_items()
assert item1 in listed_items
assert item2 in listed_items

檢查列表的長(zhǎng)度是否正確

    assert len(listed_items) == 2
## 結(jié)論

生成的單元測(cè)試,屬于是一種基本可用的狀態(tài),多次(10 次)執(zhí)行輸出的結(jié)果也較為穩(wěn)定,通過(guò)和 GPT-4-Turbo、GLM-4 生成的進(jìn)行比較,DeepSeek-V2 在一些 Agent 應(yīng)用場(chǎng)景確實(shí)可以做到平替,畢竟百分之一的成本,性?xún)r(jià)比在這里擺著,還要啥自行車(chē),等我后續(xù)在其他更復(fù)雜的 Agent 項(xiàng)目進(jìn)行進(jìn)一步驗(yàn)證。

## 參考資料

[1]瘋狂的幻方:一家隱形 AI 巨頭的大模型之路: *https://36kr.com/p/2272896094586500*

[2]MoE 架構(gòu): *https://baoyu.io/translations/llm/what-is-mixture-of-experts*

[3]Build an AI Coding Agent with LangGraph by LangChain: *https://www.analyticsvidhya.com/blog/2024/03/build-an-ai-coding-agent-with-langgraph-by-langchain/*

文章轉(zhuǎn)自[微信公眾號(hào)@莫爾索隨筆](https://mp.weixin.qq.com/s/cVbwsPutLjAMj9z7nY0g3A)
熱門(mén)推薦
一個(gè)賬號(hào)試用1000+ API
助力AI無(wú)縫鏈接物理世界 · 無(wú)需多次注冊(cè)
3000+提示詞助力AI大模型
和專(zhuān)業(yè)工程師共享工作效率翻倍的秘密
返回頂部
上一篇
Structured Generation(3):如何讓大模型100%輸出符合json schema的結(jié)果
下一篇
DeepSeek-Coder-V2.1:最佳編碼LLM再度升級(jí)!(經(jīng)過(guò)全面測(cè)試并擊敗 Claude,GPT-4o)
国内精品久久久久影院日本,日本中文字幕视频,99久久精品99999久久,又粗又大又黄又硬又爽毛片
91日韩在线专区| 青椒成人免费视频| 精品一区二区三区日韩| 国产农村妇女精品| 欧美亚洲综合网| 国产成人精品网址| 亚洲aⅴ怡春院| 一区二区三区四区在线| 国产精品丝袜在线| 久久精品无码一区二区三区| 精品日本一线二线三线不卡| 欧美日韩一区二区三区高清| 91免费看`日韩一区二区| 国产精品一卡二卡| 久久精品国产99国产| 亚洲大片精品永久免费| 日韩激情中文字幕| 国产精品99久久久久久似苏梦涵| 在线精品观看国产| 欧美成人女星排行榜| 国产原创一区二区| 麻豆国产精品一区二区三区 | 国产日韩v精品一区二区| 欧美色爱综合网| 欧美日韩一区二区在线视频| 成人国产电影网| 国产sm精品调教视频网站| 国内成人免费视频| 国内久久婷婷综合| 成人在线视频一区| 91在线高清观看| 欧洲一区二区av| 欧美一级理论性理论a| 精品免费99久久| 日本一区二区三区国色天香 | 一区二区免费在线播放| 性欧美疯狂xxxxbbbb| 精品一区二区三区在线观看国产| 国产综合一区二区| 9久草视频在线视频精品| 欧美日韩精品一区二区三区| 精品美女在线播放| 亚洲欧美另类久久久精品2019| 亚洲女人的天堂| 美女在线观看视频一区二区| 国产伦精品一区二区三区免费迷 | 99riav久久精品riav| 欧美日韩一区二区三区在线看| 日韩精品综合一本久道在线视频| 2020日本不卡一区二区视频| 国产精品久久久久久久久图文区| 亚洲午夜私人影院| 国产精品白丝jk黑袜喷水| 日本高清免费不卡视频| 欧美成人福利视频| 亚洲欧洲www| 麻豆91在线播放免费| 日本久久一区二区| 国产亚洲精品bt天堂精选| 亚洲a一区二区| 91在线丨porny丨国产| 精品va天堂亚洲国产| 亚洲福利视频导航| 99久久精品一区| 精品999在线播放| 视频一区欧美日韩| 欧美在线一二三| 18欧美亚洲精品| 国产一区二区中文字幕| 在线电影国产精品| 天天色天天爱天天射综合| 91首页免费视频| 国产精品美女一区二区在线观看| 久久91精品国产91久久小草| 91精品在线免费| 午夜精品在线看| 欧美日韩在线直播| 亚洲成人午夜电影| 欧美日本一区二区在线观看| 亚洲国产wwwccc36天堂| 欧美午夜片在线观看| 一区二区三区日韩欧美| 在线观看日韩精品| 亚洲免费电影在线| 色哟哟日韩精品| 亚洲激情第一区| 欧美日韩中文字幕一区| 亚洲电影第三页| 欧美色综合影院| 婷婷久久综合九色综合绿巨人 | 日韩亚洲电影在线| 国产一区二区美女| 国产色91在线| 91精品91久久久中77777| 一区二区三区av电影| 欧美精品欧美精品系列| 老色鬼精品视频在线观看播放| 欧美xxxx在线观看| 国产一区二区三区电影在线观看| 久久婷婷国产综合精品青草| 99久久99精品久久久久久| 亚洲午夜一二三区视频| 日韩欧美一级片| 不卡av在线免费观看| 亚洲aaa精品| 国产偷国产偷亚洲高清人白洁 | 4438x成人网最大色成网站| 国产乱码精品一区二区三| 中文字幕精品一区二区精品绿巨人| 99re热视频这里只精品| 日本中文字幕一区二区视频| 国产精品久久久久久妇女6080 | 国产日韩精品一区| 欧美日韩视频第一区| 国产精品69久久久久水密桃| 一区二区三区91| 久久久久久久久久电影| 精品视频123区在线观看| 成人一级片在线观看| 人人狠狠综合久久亚洲| 国产精品久久久久久久久图文区| 91精品国产品国语在线不卡| 99视频有精品| 国产精品91一区二区| 日本不卡一区二区| 亚洲欧美日韩电影| 中文字幕一区二区三区乱码在线 | 久久女同精品一区二区| 欧美少妇xxx| 欧洲视频一区二区| 91香蕉视频污在线| 不卡免费追剧大全电视剧网站| 韩国av一区二区三区四区| 蜜桃一区二区三区在线观看| 亚洲国产精品一区二区www| 最好看的中文字幕久久| 久久午夜老司机| 日韩午夜激情视频| 欧美一区二区三区视频免费播放 | 国产女人18水真多18精品一级做| 欧美成人女星排名| 日韩精品中文字幕一区二区三区| 欧美理论在线播放| 欧美人体做爰大胆视频| 欧美美女黄视频| 欧美女孩性生活视频| 7777精品伊人久久久大香线蕉超级流畅 | 自拍偷自拍亚洲精品播放| 亚洲国产精品av| 国产清纯白嫩初高生在线观看91| 欧美电影免费观看高清完整版在| 欧美一级xxx| 久久综合色婷婷| 国产精品视频九色porn| 国产精品久久毛片av大全日韩| 国产精品二三区| 亚洲人成网站影音先锋播放| 亚洲一区二区三区中文字幕在线| 亚洲与欧洲av电影| 日av在线不卡| 国产精品一区二区视频| av一区二区不卡| 欧美性受xxxx| 欧美一三区三区四区免费在线看| 精品日韩99亚洲| 国产精品福利电影一区二区三区四区 | 欧美日韩综合一区| 日韩亚洲欧美高清| 中文字幕不卡的av| 亚洲国产精品自拍| 国产精品自拍av| 日本久久一区二区三区| 日韩一区二区三区电影| 日本一二三不卡| 亚洲线精品一区二区三区八戒| 午夜精品久久久久久久久久| 狠狠色狠狠色综合日日91app| youjizz国产精品| 欧美一二三四在线| 亚洲黄色小说网站| 国产又黄又大久久| 欧美日韩一区成人| 久久一夜天堂av一区二区三区| 亚洲精品日日夜夜| 国产真实乱子伦精品视频| 在线中文字幕一区二区| 91福利小视频| 久久久91精品国产一区二区三区| 亚洲综合免费观看高清完整版在线| 国产一区免费电影| 日韩一区二区三区观看| 一区二区三区四区蜜桃| 不卡在线观看av| 久久久天堂av| 久久99精品久久久久婷婷| 精品视频资源站| 亚洲大片免费看| 欧美日韩国产成人在线91| 夜夜亚洲天天久久| 在线精品国精品国产尤物884a|