探索LangGraph:如何创建一个既智能又可控的航空客服AI

这种设计既保持了用户控制权,又确保了对话流程的顺畅。但随着工具数量的增加,单一的图结构可能会变得过于复杂。我们将在下一节中解决这个问题。

第三部分的图将类似于下面的示意图:

第三部分示意图

状态定义

首先,定义图的状态。我们的状态和LLM调用与第二部分相同

python
复制代码
from typing import Annotated

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

from langgraph.graph.message import AnyMessage, add_messages


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


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

    def __call__(self, state: State, config: RunnableConfig):
        while True:
            result = self.runnable.invoke(state)
            # 如果LLM碰巧返回了一个空响应,我们将重新提示它
            # 以获得一个实际的响应。
            if not result.tool_calls and (
                not result.content
                or isinstance(result.content, list)
                and not result.content[0].get("text")
            ):
                messages = state["messages"] + [("user", "请给出真实的输出。")]
                state = {**state, "messages": messages}
                messages = state["messages"] + [("user", "请给出真实的输出。")]
                state = {**state, "messages": messages}
            else:
                break
        return {"messages": result}


# Haiku更快更便宜,但准确性较低
# llm = ChatAnthropic(model="claude-3-haiku-20240307")
llm = ChatAnthropic(model="claude-3-sonnet-20240229", temperature=1)
# 你可以更新LLMs,尽管你可能需要更新提示
# from langchain_openai import ChatOpenAI

# llm = ChatOpenAI(model="gpt-4-turbo-preview")

assistant提示 = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "你是一位乐于助人的瑞士航空客户支持助手。"
            " 使用提供的工具搜索航班、公司政策和其他信息以协助用户的查询。"
            " 当搜索时,要坚持不懈。如果第一次搜索没有结果,扩大你的查询范围。"
            " 如果搜索空手而归,请在放弃之前扩大你的搜索。"
            "\n\n当前用户:\n<User>\n{user_info}\n</User>"
            "\n当前时间:{time}。",
        ),
        ("placeholder", "{messages}"),
    ]
).partial(time=datetime.now())


# "阅读"仅工具(例如检索器)不需要用户确认即可使用
part_3_safe_tools = [
    TavilySearchResults(max_results=1),
    fetch_user_flight_information,
    search_flights,
    lookup_policy,
    search_car_rentals,
    search_hotels,
    search_trip_recommendations,
]

# 这些工具都改变了用户的预订。
# 用户有权控制做出什么决定
part_3_sensitive_tools = [
    update_ticket_to_new_flight,
    cancel_ticket,
    book_car_rental,
    update_car_rental,
    cancel_car_rental,
    book_hotel,
    update_hotel,
    cancel_hotel,
    book_excursion,
    update_excursion,
    cancel_excursion,
]
sensitive_tool_names = {t.name for t in part_3_sensitive_tools}
# 我们的LLM不需要知道它必须路由到哪个节点。在它的"思维"中,它只是在调用函数。
part_3_assistant_runnable = assistant_prompt | llm.bind_tools(
    part_3_safe_tools + part_3_sensitive_tools
)

图的定义

现在,创建图。我们的图与第二部分几乎相同,只是我们将工具分为了两个不同的节点。我们只在实际更改用户预订的工具之前进行中断。

python
复制代码
from typing import Literal

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

builder = StateGraph(State)


def user_info(state: State):
    return {"user_info": fetch_user_flight_information.invoke({})}


# 新增:fetch_user_info节点首先运行,这意味着我们的助手可以在
# 不需要采取行动的情况下看到用户的航班信息
builder.add_node("fetch_user_info", user_info)
builder.set_entry_point("fetch_user_info")
builder.add_node("assistant", Assistant(part_3_assistant_runnable))
builder.add_node("safe_tools", create_tool_node_with_fallback(part_3_safe_tools))
builder.add_node(
    "sensitive_tools", create_tool_node_with_fallback(part_3_sensitive_tools)
)
# 定义逻辑
builder.add_edge("fetch_user_info", "assistant")


def route_tools(state: State) -> Literal["safe_tools", "sensitive_tools", "__end__"]:
    next_node = tools_condition(state)
    # 如果没有调用工具,返回用户
    if next_node == END:
        return END
    ai_message = state["messages"][-1]
    # 这假设是单个工具调用。要处理并行工具调用,你将想要
    # 使用ANY条件
    first_tool_call = ai_message.tool_calls[0]
    if first_tool_call["name"] in sensitive_tool_names:
        return "sensitive_tools"
    return "safe_tools"


builder.add_conditional_edges(
    "assistant",
    route_tools,
)
builder.add_edge("safe_tools", "assistant")
builder.add_edge("sensitive_tools", "assistant")

memory = SqliteSaver.from_conn_string(":memory:")
part_3_graph = builder.compile(
    checkpointer=memory,
    # 新增:图将在执行"tools"节点之前始终停止。
    # 用户可以在助手继续之前批准或拒绝(甚至更改请求)
    interrupt_before=["sensitive_tools"],
)

示例对话

接下来,让我们尝试新修订的聊天机器人!我们将在以下对话列表上运行它。这次,我们将减少确认的次数。

python
复制代码
import shutil
import uuid

# 使用备份文件更新,以便我们可以从每个部分的原始位置重新启动
shutil.copy(backup_file, db)
thread_id = str(uuid.uuid4())

config = {
    "configurable": {
        # passenger_id在我们的航班工具中使用
        # 以获取用户的航班信息
        "passenger_id": "3442 587242",
        # 通过thread_id访问检查点
        "thread_id": thread_id,
    }
}

tutorial_questions = [
    "嗨,我的航班是什么时候?",
    "我可以更新我的航班到更早的时间吗?我想今天晚些时候离开。",
    "那就更新到下周的某个时间",
    "下一个可用的选项很好",
    "关于住宿和交通呢?",
    "是的,我想要一个负担得起的酒店,用于我为期一周的住宿(7天)。我还想要租一辆车。",
    "好的,可以为你推荐的酒店预订吗?听起来不错。",
    "是的,继续预订任何中等费用且有可用性的酒店。",
    "现在对于汽车,我的选择是什么?",
    "太棒了,我们只需要最便宜的选项。继续预订7天",
    "好的,现在你对旅行有什么建议?",
    "在我在那里的时候,它们可用吗?",
    "有趣 - 我喜欢博物馆,有什么选择?",
    "好的,选一个并在我到达的第二天为我预订。",
]


_printed = set()
# 我们可以重用第一部分的教程问题,看看它的表现如何。
for question in tutorial_questions:
    events = part_3_graph.stream(
        {"messages": ("user", question)}, config, stream_mode="values"
    )
    for event in events:
        _print_event(event, _printed)
    snapshot = part_3_graph.get_state(config)
    while snapshot.next:
        # 我们有中断!代理试图使用工具,用户可以批准或拒绝它
        # 注意:此代码都在图之外。通常,你会将输出流到UI。
        # 然后,当用户提供输入时,你会通过API调用触发新的运行。
        user_input = input(
            "你是否批准上述操作?输入'y'继续;"
            " 否则,请说明你请求的更改。\n\n"
        )
        if user_input.strip() == "y":
            # 只是继续
            result = part_3_graph.invoke(
                None,
                config,
            )
        else:
            # 通过提供有关请求更改/改变主意的说明
            # 满足工具调用
            result = part_3_graph.invoke(
                {
                    "messages": [
                        ToolMessage(
                            tool_call_id=event["messages"][-1].tool_calls[0]["id"],
                            content=f"API调用被用户拒绝。理由:'{user_input}'。继续协助,考虑用户的输入。",
                        )
                    ]
                },
                config,
            )
        snapshot = part_3_graph.get_state(config)

第三部分回顾

现在,我们的聊天机器人工作得很好,你可以通过LangSmith跟踪来检查它的最新运行情况。这个设计可能已经满足了你的需求。代码是封闭的,并且它的行为符合预期。

然而,这个设计的一个潜在问题是,它对单个提示施加了很大压力。如果我们想要添加更多工具,或者每个工具变得更加复杂,那么机器人使用工具的效率和整体行为可能会受到影响。

如何系统的去学习大模型LLM ?

作为一名热心肠的互联网老兵,我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。

但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的 AI大模型资料 包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来

😝有需要的小伙伴,可以V扫描下方二维码免费领取🆓

在这里插入图片描述

一、全套AGI大模型学习路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

img

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

img

三、AI大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

img

在这里插入图片描述

四、AI大模型商业化落地方案

img

阶段1:AI大模型时代的基础理解

  • 目标:了解AI大模型的基本概念、发展历程和核心原理。
  • 内容
    • L1.1 人工智能简述与大模型起源
    • L1.2 大模型与通用人工智能
    • L1.3 GPT模型的发展历程
    • L1.4 模型工程
      - L1.4.1 知识大模型
      - L1.4.2 生产大模型
      - L1.4.3 模型工程方法论
      - L1.4.4 模型工程实践
    • L1.5 GPT应用案例

阶段2:AI大模型API应用开发工程

  • 目标:掌握AI大模型API的使用和开发,以及相关的编程技能。
  • 内容
    • L2.1 API接口
      - L2.1.1 OpenAI API接口
      - L2.1.2 Python接口接入
      - L2.1.3 BOT工具类框架
      - L2.1.4 代码示例
    • L2.2 Prompt框架
      - L2.2.1 什么是Prompt
      - L2.2.2 Prompt框架应用现状
      - L2.2.3 基于GPTAS的Prompt框架
      - L2.2.4 Prompt框架与Thought
      - L2.2.5 Prompt框架与提示词
    • L2.3 流水线工程
      - L2.3.1 流水线工程的概念
      - L2.3.2 流水线工程的优点
      - L2.3.3 流水线工程的应用
    • L2.4 总结与展望

阶段3:AI大模型应用架构实践

  • 目标:深入理解AI大模型的应用架构,并能够进行私有化部署。
  • 内容
    • L3.1 Agent模型框架
      - L3.1.1 Agent模型框架的设计理念
      - L3.1.2 Agent模型框架的核心组件
      - L3.1.3 Agent模型框架的实现细节
    • L3.2 MetaGPT
      - L3.2.1 MetaGPT的基本概念
      - L3.2.2 MetaGPT的工作原理
      - L3.2.3 MetaGPT的应用场景
    • L3.3 ChatGLM
      - L3.3.1 ChatGLM的特点
      - L3.3.2 ChatGLM的开发环境
      - L3.3.3 ChatGLM的使用示例
    • L3.4 LLAMA
      - L3.4.1 LLAMA的特点
      - L3.4.2 LLAMA的开发环境
      - L3.4.3 LLAMA的使用示例
    • L3.5 其他大模型介绍

阶段4:AI大模型私有化部署

  • 目标:掌握多种AI大模型的私有化部署,包括多模态和特定领域模型。
  • 内容
    • L4.1 模型私有化部署概述
    • L4.2 模型私有化部署的关键技术
    • L4.3 模型私有化部署的实施步骤
    • L4.4 模型私有化部署的应用场景

学习计划:

  • 阶段1:1-2个月,建立AI大模型的基础知识体系。
  • 阶段2:2-3个月,专注于API应用开发能力的提升。
  • 阶段3:3-4个月,深入实践AI大模型的应用架构和私有化部署。
  • 阶段4:4-5个月,专注于高级模型的应用和部署。
这份完整版的大模型 LLM 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

😝有需要的小伙伴,可以Vx扫描下方二维码免费领取🆓

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/639118.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Blazor 下支持 Azure AD 的多套登录方案

比如上图配置了两套不同的登录方案&#xff0c;各有自己的 TenantId 和 ClientId &#xff0c;要同时支持他们的登录&#xff08;其实在同一套 TenantId 和 ClientId 里面配置多个登录账户不就好了&#xff0c;但是......那套登录的管理是在客户自己的Azure AD账户管理下的&…

Python数据可视化(七)

绘制 3D 图形 到目前为止&#xff0c;我们一直在讨论有关 2D 图形的绘制方法和绘制技术。3D 图形也是数据可视化的 一个很重要的应用方面&#xff0c;我们接下来就重点讲解有关 3D 图形的实现方法。绘制 3D 图形通常需要导 入 mpl_toolkits 包中的 mplot3d 包的相关模块&#x…

【openlayers系统学习】3.6-3.7添加可视化选择器,手动选择可视化的图像源

六、添加可视化选择器&#xff08;选择可视化的图像类型&#xff09; 在前面的示例中&#xff0c;我们已经看到了同一Sentinel-2图像的真彩色合成、假彩色合成和NDVI渲染。如果能让用户从这些可视化中选择一个或更多&#xff0c;而不必每次都更改我们的代码&#xff0c;那就太…

2024年顶级算法-黑翅鸢优化算法(BKA)-详细原理(附matlab代码)

黑翅鸢是一种上半身蓝灰色&#xff0c;下半身白色的小型鸟类。它们的显著特征包括迁徙和捕食行为。它们以小型哺乳动物、爬行动物、鸟类和昆虫为食&#xff0c;具有很强的悬停能力&#xff0c;能够取得非凡的狩猎成功。受其狩猎技能和迁徙习惯的启发&#xff0c;该算法作者建立…

C++利用TinyXML读取XML文件

TinyXML是什么&#xff1f; TinyXML是一个轻量级的C XML解析器&#xff0c;它提供了一种简单的方法来解析和操作XML文档。TinyXML被设计为易于使用和集成到C项目中&#xff0c;并且非常适合处理小型XML文件。 以下是TinyXML的一些主要特点和优点&#xff1a; 轻量级: T…

0基础从前端到Web3 —— Mine Clearance Frontend(二)

在一的基础上继续往下&#xff0c;本篇主要是链上调用部分&#xff0c;让整个项目可以进行最基本的扫雷游戏。 S u i M o v e \mathit {Sui\ Move} Sui Move 链上部署的自主实现的简单扫雷游戏可以点击查看&#xff0c;只不过这里将区域大小扩大为了 10 20 \text {10}\ \tim…

Plesk中如何移除之前添加的域名

我这边想要移除我之前绑定到主机的域名&#xff0c;但是不知道如何在主机上面进行移除&#xff0c;由于我使用的Hostease的Windows虚拟主机产品默认带普通用户权限的Plesk面板&#xff0c;但是不知道如何在Plesk上操作移除域名&#xff0c;因为也是对于Hostease主机产品不是很了…

python给图片加上图片水印

python给图片加上图片水印 作用效果代码 作用 给图片加上图片水印图片水印的透明度&#xff0c;位置可自定义 效果 原始图片&#xff1a; 水印图片&#xff1a; 添加水印后的图片&#xff1a; 代码 from PIL import Image, ImageDraw, ImageFontdef add_watermark(in…

联盟 | 歌者 AIPPT X HelpLook携手,开启企业高效办公新时代

面对日益增长的工作负荷和追求效率优化的压力&#xff0c;企业知识的积累与传播显得愈发重要。如何系统化地沉淀员工与企业的知识精华&#xff1f;如何快速分享内外部知识&#xff1f;更重要的是&#xff0c;如何在获取这些知识后&#xff0c;迅速将其转化为精美的PPT&#xff…

抖店一件代发,从0到1操作全流程

我是王路飞。 先说明一点&#xff0c;新手不需要纠结抖店一件代发&#xff08;即无货源模式&#xff09;还能不能做的问题。 无货源只是前期帮助新手阶段的你进入到这个市场里来的一种方式&#xff0c;不是你长期做店的思路。 入门之后&#xff0c;基本就转型为有货源去玩了…

漫画|基于SprinBoot+vue的漫画网站(源码+数据库+文档)

漫画网站 目录 基于SprinBootvue的漫画网站 一、前言 二、系统设计 三、系统功能设计 1系统功能模块 2管理员功能模块 3用户功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大…

node 版本对应的 node-sass 版本号

当我们在项目中使用 node-sass 时&#xff0c;电脑的 node版本号一定要与 node-sass 版本号对应&#xff0c;不对应时下载就会报错 ❌问题&#xff1f;node-sass: Command failed. ✅解决方案&#xff0c;可能是node 跟 node-sass版本不一致 1、查询node版本 node -v &#…

RabbitMQ - SimpleMessageListenerContainer的实现逻辑

RabbitMQ - SimpleMessageListenerContainer的实现逻辑 Queue&#xff08;队列&#xff09;&#xff1a;在 RabbitMQ 中用于存储消息的数据结构。生产者将消息发送到队列中&#xff0c;而消费者从队列中接收消息。 Connection&#xff08;连接&#xff09;&#xff1a;连接是应…

Unity 实现心电图波形播放(需波形图图片)

实现 在Hierarchy 面板从2D Object 中新建一个Sprite&#xff0c;将波形图图片的赋给Sprite。 修改Sprite 的Sprite Renderer 组件中Draw Mode 为Tiled, 修改Sprite Renderer 的Size 即可实现波形图播放。 在Hierarchy 面板从2D Object 中新建一个Sprite Mask 并赋以遮罩图片…

【学习笔记】Windows GDI绘图(六)图形路径GraphicsPath详解(中)

上一篇【学习笔记】Windows GDI绘图(五)图形路径GraphicsPath详解(上)介绍了GraphicsPath类的构造函数、属性和方法AddArc添加椭圆弧、AddBezier添加贝赛尔曲线、AddClosedCurve添加封闭基数样条曲线、AddCurve添加开放基数样条曲线、基数样条如何转Bezier、AddEllipse添加椭圆…

2024年了, 你还不会使用node.js做压力测试?

前些天刷抖音&#xff0c;看到网传的Java继父&#xff0c;求人攻击压测他的网站&#xff0c;这不得摩拳擦掌。 所以今天来聊聊如何对自己的项目、接口进行压力测试。 压力测试的目的 首先, 绝对不是为了压测、攻击别人的网站为乐。 1、探索线上系统流量承载的极限&#xff…

python批发模块的调试之旅:从新手到专家的蜕变

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、调试技巧的重要性 二、批发模块调试的实战演练 1. 设置断点 2. 逐行执行代码 3. 观察…

安全风险 - 检测Android设备系统是否已Root

在很多app中都禁止 root 后的手机使用相关app功能&#xff0c;这种场景在金融app、银行app更为常见一些&#xff1b;当然针对 root 后的手机&#xff0c;我们也可以做出风险提示&#xff0c;告知用户当前设备已 root &#xff0c;谨防风险&#xff01; 最近在安全检测中提出了一…

【博主推荐】HTML5实现520表白、情人节表白模板源码

文章目录 1.设计来源1.1 表白首页1.2 甜蜜瞬间11.3 甜蜜瞬间21.4 甜蜜瞬间31.5 甜蜜瞬间41.6 甜蜜瞬间51.7 甜蜜瞬间61.8 永久珍藏 2.效果和源码2.1 页面动态效果2.2 页面源代码2.3 源码目录2.4 更多为爱表白源码 3.源码下载地址 作者&#xff1a;xcLeigh 文章地址&#xff1a;…