偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

LangGraph實(shí)戰(zhàn):從零分階打造人工智能航空客服助手 精華

發(fā)布于 2024-11-13 14:40
瀏覽
0收藏

客服助手機(jī)器人能夠幫助團(tuán)隊(duì)更高效地處理日常咨詢(xún),但要打造一個(gè)能夠穩(wěn)定應(yīng)對(duì)各種任務(wù)且不會(huì)讓用戶(hù)感到煩惱的機(jī)器人并非易事。

完成本教程后,你不僅會(huì)擁有一個(gè)功能完備的機(jī)器人,還將深入理解LangGraph的核心理念和架構(gòu)設(shè)計(jì)。這些知識(shí)將幫助你在其他人工智能項(xiàng)目中運(yùn)用相似的設(shè)計(jì)模式。

由于內(nèi)容較多,本文將由淺入深,分四個(gè)階段進(jìn)行講解,每個(gè)階段都將打造出一個(gè)具備以上描述所有能力的機(jī)器人。但受限于LLM的能力,初期階段的機(jī)器人的運(yùn)行可能存在各類(lèi)問(wèn)題,但都將在后續(xù)階段得到解決。

你最終完成的聊天機(jī)器人將類(lèi)似于以下示意圖:

LangGraph實(shí)戰(zhàn):從零分階打造人工智能航空客服助手-AI.x社區(qū)

最終示意圖

現(xiàn)在,讓我們開(kāi)啟這第一階段段的學(xué)習(xí)之旅吧!

準(zhǔn)備工作

在開(kāi)始之前,我們需要搭建好環(huán)境。本教程將安裝一些必要的先決條件,包括下載測(cè)試用的數(shù)據(jù)庫(kù),并定義一些在后續(xù)各部分中會(huì)用到的工具。

我們會(huì)使用 Claude 作為語(yǔ)言模型(LLM),并創(chuàng)建一些定制化的工具。這些工具大多數(shù)會(huì)連接到本地的 SQLite 數(shù)據(jù)庫(kù),無(wú)需額外依賴(lài)。此外,我們還會(huì)通過(guò) Tavily 為代理提供網(wǎng)絡(luò)搜索功能。

%%capture --no-stderr
% pip install -U langgraph langchain-community langchain-anthropic tavily-python pandas

數(shù)據(jù)庫(kù)初始化

接下來(lái),執(zhí)行下面的腳本來(lái)獲取我們?yōu)檫@個(gè)教程準(zhǔn)備的 SQLite 數(shù)據(jù)庫(kù),并更新它以反映當(dāng)前的數(shù)據(jù)狀態(tài)。具體細(xì)節(jié)不是重點(diǎn)。

import os
import requests
import sqlite3
import pandas as pd
import shutil

# 下載數(shù)據(jù)庫(kù)文件
db_url = "https://storage.googleapis.com/benchmarks-artifacts/travel-db/travel2.sqlite"
local_file = "travel2.sqlite"
backup_file = "travel2.backup.sqlite"
overwrite = False
if not os.path.exists(local_file) or overwrite:
    response = requests.get(db_url)
    response.raise_for_status()  # 確保請(qǐng)求成功
    with open(local_file, "wb") as file:
        file.write(response.content)

# 創(chuàng)建數(shù)據(jù)庫(kù)備份,以便在每個(gè)教程部分開(kāi)始時(shí)重置數(shù)據(jù)庫(kù)狀態(tài)
shutil.copy(local_file, backup_file)

# 將航班數(shù)據(jù)更新為當(dāng)前時(shí)間,以適應(yīng)我們的教程
conn = sqlite3.connect(local_file)
cursor = conn.cursor()

# 讀取數(shù)據(jù)庫(kù)中的所有表
tables = pd.read_sql(
    "SELECT name FROM sqlite_master WHERE type='table';", conn
).name.tolist()
tdf = {}
for table_name in tables:
    tdf[table_name] = pd.read_sql(f"SELECT * from {table_name}", conn)

# 找到最早的出發(fā)時(shí)間,并計(jì)算時(shí)間差
example_time = pd.to_datetime(
    tdf["flights"]["actual_departure"].replace("\\N", pd.NaT)
).max()
current_time = pd.to_datetime("now").tz_localize(example_time.tz)
time_diff = current_time - example_time

# 更新預(yù)訂日期和航班時(shí)間
for column in ["book_date", "scheduled_departure", "scheduled_arrival", "actual_departure", "actual_arrival"]:
    tdf["flights"][column] = pd.to_datetime(
        tdf["flights"][column].replace("\\N", pd.NaT)
    ) + time_diff

# 將更新后的數(shù)據(jù)寫(xiě)回?cái)?shù)據(jù)庫(kù)
for table_name, df in tdf.items():
    df.to_sql(table_name, conn, if_exists="replace", index=False)
conn.commit()
conn.close()

# 在本教程中,我們將使用這個(gè)本地文件作為數(shù)據(jù)庫(kù)
db = local_file

工具定義

現(xiàn)在,我們來(lái)定義一些工具,以便助手可以搜索航空公司的政策手冊(cè),以及搜索和管理航班、酒店、租車(chē)和遠(yuǎn)足活動(dòng)的預(yù)訂。這些工具將在教程的各個(gè)部分中重復(fù)使用,具體的實(shí)現(xiàn)細(xì)節(jié)不是關(guān)鍵。

查詢(xún)公司政策

助手需要檢索政策信息來(lái)回答用戶(hù)的問(wèn)題。請(qǐng)注意,這些政策的實(shí)施還需要在工具或 API 中進(jìn)行,因?yàn)檎Z(yǔ)言模型可能會(huì)忽略這些信息。以下工具受限于篇幅將僅提供定義及描述,詳細(xì)代碼[1]可在github上獲取。

import re
import numpy as np
import openai
from langchain_core.tools import tool


@tool
def lookup_policy(query):
    """查詢(xún)公司政策,以確定某些選項(xiàng)是否允許。"""

航班管理

定義一個(gè)工具來(lái)獲取用戶(hù)的航班信息,然后定義一些工具來(lái)搜索航班和管理用戶(hù)的預(yù)訂信息,這些信息存儲(chǔ)在 SQL 數(shù)據(jù)庫(kù)中。

我們使用 ensure_config? 來(lái)通過(guò)配置參數(shù)傳遞 passenger_id。語(yǔ)言模型不需要顯式提供這些信息,它們會(huì)在圖的每次調(diào)用中提供,以確保每個(gè)用戶(hù)無(wú)法訪(fǎng)問(wèn)其他乘客的預(yù)訂信息。

from langchain_core.runnables import ensure_config
from typing import Optional
import sqlite3
import pytz
from datetime import datetime, timedelta, date

@tool
def fetch_user_flight_information():
    """獲取用戶(hù)的所有機(jī)票信息,包括航班詳情和座位分配。"""

@tool
def search_flights(
    departure_airport=None,
    arrival_airport=None,
    start_time=None,
    end_time=None,
    limit=20,
):
    """根據(jù)出發(fā)機(jī)場(chǎng)、到達(dá)機(jī)場(chǎng)和出發(fā)時(shí)間范圍來(lái)搜索航班。"""

@tool
def update_ticket_to_new_flight(ticket_no, new_flight_id):
    """將用戶(hù)的機(jī)票更新到一個(gè)新的有效航班上。"""

@tool
def cancel_ticket(ticket_no):
    """取消用戶(hù)的機(jī)票,并從數(shù)據(jù)庫(kù)中移除。"""

租車(chē)服務(wù)

用戶(hù)預(yù)訂了航班后,可能需要租車(chē)服務(wù)。定義一些工具,讓用戶(hù)能夠在目的地搜索和預(yù)訂汽車(chē)。

from typing import Optional, Union
from datetime import datetime, date

@tool
def search_car_rentals(
    locatinotallow=None,
    name=None,
    price_tier=None,
    start_date=None,
    end_date=None,
):
    """
    根據(jù)位置、公司名稱(chēng)、價(jià)格等級(jí)、開(kāi)始日期和結(jié)束日期來(lái)搜索租車(chē)服務(wù)。

    參數(shù):
        location (Optional[str]): 租車(chē)服務(wù)的位置。
        name (Optional[str]): 租車(chē)公司的名稱(chēng)。
        price_tier (Optional[str]): 租車(chē)的價(jià)格等級(jí)。
        start_date (Optional[Union[datetime, date]]): 租車(chē)的開(kāi)始日期。
        end_date (Optional[Union[datetime, date]]): 租車(chē)的結(jié)束日期。

    返回:
        list[dict]: 匹配搜索條件的租車(chē)服務(wù)列表。
    """

@tool
def book_car_rental(rental_id):
    """
    通過(guò)租車(chē)ID來(lái)預(yù)訂租車(chē)服務(wù)。

    參數(shù):
        rental_id (int): 要預(yù)訂的租車(chē)服務(wù)的ID。

    返回:
        str: 預(yù)訂成功與否的消息。
    """

@tool
def update_car_rental(
    rental_id,
    start_date=None,
    end_date=None,
):
    """
    通過(guò)租車(chē)ID來(lái)更新租車(chē)服務(wù)的開(kāi)始和結(jié)束日期。

    參數(shù):
        rental_id (int): 要更新的租車(chē)服務(wù)的ID。
        start_date (Optional[Union[datetime, date]]): 新的租車(chē)開(kāi)始日期。
        end_date (Optional[Union[datetime, date]]): 新的租車(chē)結(jié)束日期。

    返回:
        str: 更新成功與否的消息。
    """

@tool
def cancel_car_rental(rental_id):
    """
    通過(guò)租車(chē)ID來(lái)取消租車(chē)服務(wù)。

    參數(shù):
        rental_id (int): 要取消的租車(chē)服務(wù)的ID。

    返回:
        str: 取消成功與否的消息。
    """

酒店預(yù)訂

用戶(hù)需要住宿,因此定義一些工具來(lái)搜索和管理酒店預(yù)訂。

@tool
def search_hotels(
    locatinotallow=None,
    name=None,
    price_tier=None,
    checkin_date=None,
    checkout_date=None,
):
    """
    根據(jù)位置、名稱(chēng)、價(jià)格等級(jí)、入住日期和退房日期來(lái)搜索酒店。

    參數(shù):
        location (Optional[str]): 酒店的位置。
        name (Optional[str]): 酒店的名稱(chēng)。
        price_tier (Optional[str]): 酒店的價(jià)格等級(jí)。
        checkin_date
        
        # 入住日期和退房日期,用于搜索酒店
        checkin_date (Optional[Union[datetime, date]]): 酒店的入住日期。
        checkout_date (Optional[Union[datetime, date]]): 酒店的退房日期。

    返回:
        list[dict]: 符合搜索條件的酒店列表。
    """
    
@tool
def book_hotel(hotel_id):
    """
    通過(guò)酒店ID進(jìn)行預(yù)訂。

    參數(shù):
        hotel_id (int): 要預(yù)訂的酒店的ID。

    返回:
        str: 預(yù)訂成功與否的消息。
    """
    
@tool
def update_hotel(
    hotel_id,
    checkin_date=None,
    checkout_date=None,
):
    """
    通過(guò)酒店ID更新酒店預(yù)訂的入住和退房日期。

    參數(shù):
        hotel_id (int): 要更新預(yù)訂的酒店的ID。
        checkin_date (Optional[Union[datetime, date]]): 新的入住日期。
        checkout_date (Optional[Union[datetime, date]]): 新的退房日期。

    返回:
        str: 更新成功與否的消息。
    """
    
@tool
def cancel_hotel(hotel_id):
    """
    通過(guò)酒店ID取消酒店預(yù)訂。

    參數(shù):
        hotel_id (int): 要取消預(yù)訂的酒店的ID。

    返回:
        str: 取消成功與否的消息。
    """

遠(yuǎn)足活動(dòng)

最后,定義一些工具,讓用戶(hù)在到達(dá)目的地后搜索活動(dòng)并進(jìn)行預(yù)訂。

@tool
def search_trip_recommendations(
    locatinotallow=None,
    name=None,
    keywords=None,
):
    """
    根據(jù)位置、名稱(chēng)和關(guān)鍵詞搜索旅行推薦。

    參數(shù):
        location (Optional[str]): 旅行推薦的地點(diǎn)。
        name (Optional[str]): 旅行推薦的名字。
        keywords (Optional[str]): 與旅行推薦相關(guān)的關(guān)鍵詞。

    返回:
        list[dict]: 符合搜索條件的旅行推薦列表。
    """
    
@tool
def book_excursion(recommendation_id):
    """
    通過(guò)推薦ID預(yù)訂遠(yuǎn)足活動(dòng)。

    參數(shù):
        recommendation_id (int): 要預(yù)訂的旅行推薦的ID。

    返回:
        str: 預(yù)訂成功與否的消息。
    """
    
@tool
def update_excursion(recommendation_id, details):
    """
    通過(guò)推薦ID更新旅行推薦的細(xì)節(jié)。

    參數(shù):
        recommendation_id (int): 要更新的旅行推薦的ID。
        details (str): 旅行推薦的新細(xì)節(jié)。

    返回:
        str: 更新成功與否的消息。
    """
    
@tool
def cancel_excursion(recommendation_id):
    """
    通過(guò)推薦ID取消旅行推薦。

    參數(shù):
        recommendation_id (int): 要取消的旅行推薦的ID。

    返回:
        str: 取消成功與否的消息。
    """

實(shí)用工具

定義一些輔助函數(shù),以便在調(diào)試過(guò)程中美化圖形中的消息顯示,并為工具節(jié)點(diǎn)添加錯(cuò)誤處理(通過(guò)將錯(cuò)誤添加到聊天記錄中)。

from langgraph.prebuilt import ToolNode
from langchain_core.runnables import RunnableLambda

def handle_tool_error(state):
    error = state.get("error")
    tool_calls = state["messages"][-1].tool_calls
    return {
        "messages": [
            ToolMessage(
                cnotallow=f"錯(cuò)誤: {repr(error)}\n請(qǐng)修正你的錯(cuò)誤。",
                tool_call_id=tc["id"],
            )
            for tc in tool_calls
        ]
    }

def create_tool_node_with_fallback(tools):
    return ToolNode(tools).with_fallbacks(
        [RunnableLambda(handle_tool_error)], exception_key="error"
    )

def _print_event(event, _printed, max_length=1500):
    current_state = event.get("dialog_state")
    if current_state:
        print(f"當(dāng)前狀態(tài): ", current_state[-1])
    message = event.get("messages")
    if message:
        if isinstance(message, list):
            message = message[-1]
        if message.id not in _printed:
            msg_repr = message.pretty_repr(html=True)
            if len(msg_repr) > max_length:
                msg_repr = msg_repr[:max_length] + " ... (內(nèi)容已截?cái)啵?
            print(msg_repr)
            _printed.add(message.id)

第一部分:零樣本代理

在構(gòu)建任何系統(tǒng)時(shí),最佳實(shí)踐是從最簡(jiǎn)單的可行方案開(kāi)始,并通過(guò)使用類(lèi)似LangSmith這樣的評(píng)估工具來(lái)測(cè)試其有效性。在條件相同的情況下,我們傾向于選擇簡(jiǎn)單且可擴(kuò)展的解決方案,而不是復(fù)雜的方案。然而,單一圖譜方法存在一些限制,比如機(jī)器人可能在未經(jīng)用戶(hù)確認(rèn)的情況下執(zhí)行不希望的操作,處理復(fù)雜查詢(xún)時(shí)可能遇到困難,或者在回答時(shí)缺乏針對(duì)性。這些問(wèn)題我們會(huì)在后續(xù)進(jìn)行改進(jìn)。 在這部分,我們將定義一個(gè)簡(jiǎn)單的零樣本代理作為用戶(hù)的助手,并將所有工具賦予給它。我們的目標(biāo)是引導(dǎo)它明智地使用這些工具來(lái)幫助用戶(hù)。 我們的簡(jiǎn)單兩節(jié)點(diǎn)圖如下所示:

LangGraph實(shí)戰(zhàn):從零分階打造人工智能航空客服助手-AI.x社區(qū)

第一部分圖解

首先,我們定義狀態(tài)。

狀態(tài)

我們將StateGraph的狀態(tài)定義為一個(gè)包含消息列表的類(lèi)型化字典。這些消息構(gòu)成了聊天的記錄,也就是我們簡(jiǎn)單助手所需要的全部狀態(tài)信息。

from langgraph.graph.message import add_messages, AnyMessage
from typing_extensions import TypedDict
from typing import Annotated


class State(TypedDict):
    messages: Annotated[list[AnyMessage], add_messages]

代理

然后,我們定義助手函數(shù)。這個(gè)函數(shù)接收?qǐng)D的狀態(tài),將其格式化為提示,然后調(diào)用一個(gè)大型語(yǔ)言模型(LLM)來(lái)預(yù)測(cè)最佳的響應(yīng)。

from langchain_core.runnables import Runnable, RunnableConfig
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_anthropic import ChatAnthropic
from langchain_core.prompts import ChatPromptTemplate


class Assistant:
    def __init__(self, runnable: Runnable):
        self.runnable = runnable

    def __call__(self, state: State, config: RunnableConfig):
        while True:
            passenger_id = config.get("passenger_id", None)
            state = {**state, "user_info": passenger_id}
            result = self.runnable.invoke(state)
            # 如果大型語(yǔ)言模型返回了一個(gè)空響應(yīng),我們將重新提示它給出一個(gè)實(shí)際的響應(yīng)。
            if (
                not result.content
                or isinstance(result.content, list)
                and not result.content[0].get("text")
            ):
                messages = state["messages"] + [("user", "請(qǐng)給出一個(gè)真實(shí)的輸出。")]
                state = {**state, "messages": messages}
            else:
                break
        return {"messages": result}


# Haiku模型更快、成本更低,但準(zhǔn)確性稍差
# llm = ChatAnthropic(model="claude-3-haiku-20240307")
llm = ChatAnthropic(model="claude-3-sonnet-20240229", temperature=1)

primary_assistant_prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "你是一個(gè)為瑞士航空提供幫助的客戶(hù)支持助手。"
            "使用提供的工具來(lái)搜索航班、公司政策和其他信息以幫助回答用戶(hù)的查詢(xún)。"
            "在搜索時(shí),要有毅力。如果第一次搜索沒(méi)有結(jié)果,就擴(kuò)大你的查詢(xún)范圍。"
            "如果搜索結(jié)果為空,不要放棄,先擴(kuò)大搜索范圍。"
            "\n\n當(dāng)前用戶(hù):\n<User>\n{user_info}\n</User>"
            "\n當(dāng)前時(shí)間:{time}。",
        ),
        ("placeholder", "{messages}"),
    ]
).partial(time=datetime.now())

part_1_tools = [
    TavilySearchResults(max_results=1),
    fetch_user_flight_information,
    search_flights,
    lookup_policy,
    update_ticket_to_new_flight,
    cancel_ticket,
    search_car_rentals,
    book_car_rental,
    update_car_rental,
    cancel_car_rental,
    search_hotels,
    book_hotel,
    update_hotel,
    cancel_hotel,
    search_trip_recommendations,
    book_excursion,
    update_excursion,
    cancel_excursion,
]
part_1_assistant_runnable = primary_assistant_prompt | llm.bind_tools(part_1_tools)

定義圖

現(xiàn)在,我們來(lái)創(chuàng)建圖。這張圖是我們這部分的最終助手。

from langgraph.checkpoint.sqlite import SqliteSaver
from langgraph.graph import StateGraph, END
from langgraph.prebuilt import tools_condition, ToolNode

builder = StateGraph(State)


# 定義節(jié)點(diǎn):這些節(jié)點(diǎn)執(zhí)行具體的工作
builder.add_node("assistant", Assistant(part_1_assistant_runnable))
builder.add_node("action", create_tool_node_with_fallback(part_1_tools))
# 定義邊:這些邊決定了控制流程如何移動(dòng)
builder.set_entry_point("assistant")
builder.add_conditional_edges(
    "assistant",
    tools_condition,
    # "action"調(diào)用我們的工具之一。END導(dǎo)致圖終止(并向用戶(hù)做出響應(yīng))
    {"action": "action", END: END},
)
builder.add_edge("action", "assistant")

# 檢查點(diǎn)器允許圖保存其狀態(tài)
# 這是整個(gè)圖的完整記憶。
memory = SqliteSaver.from_conn_string(":memory:")
part_1_graph = builder.compile(checkpointer=memory)

from IPython.display import Image, display

try:
    display(Image(part_1_graph.get_graph(xray=True).draw_mermaid_png()))
except:
    # 這需要一些額外的依賴(lài)項(xiàng),是可選的
    pass

LangGraph實(shí)戰(zhàn):從零分階打造人工智能航空客服助手-AI.x社區(qū)

示例對(duì)話(huà)

現(xiàn)在,讓我們通過(guò)一系列對(duì)話(huà)示例來(lái)測(cè)試我們的聊天機(jī)器人。

import uuid
import shutil

# 假設(shè)這是用戶(hù)與助手之間可能發(fā)生的對(duì)話(huà)示例
tutorial_questions = [
    "你好,我的航班是什么時(shí)候?",
    "我可以把我的航班改簽到更早的時(shí)間嗎?我想今天晚些時(shí)候離開(kāi)。",
    "那就把我的航班改簽到下周某個(gè)時(shí)間吧",
    "下一個(gè)可用的選項(xiàng)很好",
    "住宿和交通方面有什么建議?",
    "我想在為期一周的住宿中選擇一個(gè)經(jīng)濟(jì)實(shí)惠的酒店(7天),并且我還想租一輛車(chē)。",
    "好的,你能為你推薦的酒店預(yù)訂嗎?聽(tīng)起來(lái)不錯(cuò)。",
    "是的,去預(yù)訂任何中等價(jià)位且有可用性的酒店。",
    "對(duì)于汽車(chē),我有哪些選擇?",
    "太棒了,我們只選擇最便宜的選項(xiàng)。預(yù)訂7天。",
    "那么,你對(duì)我的旅行有什么建議?",
    "在我在那里的時(shí)候,有哪些活動(dòng)是可用的?",
    "有趣 - 我喜歡博物館,有哪些選擇?",
    "好的,那就為我在那里的第二天預(yù)訂一個(gè)。",
]

# 使用備份文件以便我們可以從每個(gè)部分的原始位置重新啟動(dòng)
shutil.copy(backup_file, db)
thread_id = str(uuid.uuid4())

config = {
    "configurable": {
        # passenger_id 在我們的航班工具中使用
        # 以獲取用戶(hù)的航班信息
        "passenger_id": "3442 587242",
        # 檢查點(diǎn)通過(guò) thread_id 訪(fǎng)問(wèn)
        "thread_id": thread_id,
    }
}


_printed = set()
for question in tutorial_questions:
    events = part_1_graph.stream(
        {"messages": ("user", question)}, config, stream_mode="values"
    )
    for event in events:
        _print_event(event, _printed)

第一部分回顧

我們的簡(jiǎn)單助手表現(xiàn)得還不錯(cuò)!它能夠合理地回答所有問(wèn)題,快速地在上下文中做出回應(yīng),并成功地執(zhí)行了我們所有的任務(wù)。你可以通過(guò)查看LangSmith的示例跟蹤[2]來(lái)更好地了解LLM在上述交互中是如何被提示的。

如果這是一個(gè)簡(jiǎn)單的問(wèn)答機(jī)器人,我們可能會(huì)對(duì)上述結(jié)果感到滿(mǎn)意。由于我們的客戶(hù)支持機(jī)器人是代表用戶(hù)采取行動(dòng),因此它的一些行為有點(diǎn)令人擔(dān)憂(yōu):

  1. 當(dāng)我們專(zhuān)注于住宿時(shí),助手預(yù)訂了一輛車(chē),然后又不得不取消并稍后重新預(yù)訂:哎呀!在預(yù)訂之前,應(yīng)該讓用戶(hù)有最終決定權(quán),以避免不需要的預(yù)訂。
  2. 助手在尋找推薦方面遇到了困難。我們可以通過(guò)添加更多的詳細(xì)指令和使用工具的示例來(lái)改進(jìn)這一點(diǎn),但為每個(gè)工具都這樣做可能會(huì)導(dǎo)致提示過(guò)長(zhǎng),讓代理感到不知所措。
  3. 助手不得不進(jìn)行明確的搜索才能獲取用戶(hù)的相關(guān)信息。我們可以通過(guò)立即獲取用戶(hù)的旅行詳細(xì)信息,讓助手能夠直接回應(yīng),從而節(jié)省大量時(shí)間。

在下一節(jié)中,我們將解決前兩個(gè)問(wèn)題,期待你的持續(xù)關(guān)注!。

Reference

[1] 詳細(xì)代碼: https://github.com/langchain-ai/langgraph/blob/main/examples/customer-support/customer-support.ipynb

[2] LangSmith的示例跟蹤: https://smith.langchain.com/public/f9e77b80-80ec-4837-98a8-254415cb49a1/r/26146720-d3f9-44b6-9bb9-9158cde61f9d

本文轉(zhuǎn)載自 ??AI小智??,作者: AI小智

收藏
回復(fù)
舉報(bào)
回復(fù)
相關(guān)推薦