news 2026/5/1 18:50:24

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
探索LangGraph:如何创建一个既智能又可控的航空客服AI

探索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大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

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

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

三、AI大模型经典PDF籍

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

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

阶段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扫描下方二维码免费领取🆓

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/19 11:41:47

火山引擎智能客服接入豆包全流程指南:从零搭建到生产环境部署

背景痛点&#xff1a;跨平台对接的三座大山 把火山引擎智能客服接到豆包&#xff0c;听起来只是“调几个接口”&#xff0c;真动手才发现坑比想象深。认证失败、消息延迟、协议兼容性这三座大山&#xff0c;90% 的团队都会踩一遍。 认证失败 火山引擎用 OAuth2.0 临时 AK/SK …

作者头像 李华
网站建设 2026/4/18 8:53:06

CMI码解析:如何优化PCM数字设备间的传输接口效率

CMI码解析&#xff1a;如何优化PCM数字设备间的传输接口效率 1. 背景&#xff1a;CMI码到底是个啥 第一次把示波器探头夹到2 Mbit/s同轴口上&#xff0c; 看到那一串“0 1 0 0 1 1”的方波时&#xff0c;我还以为设备坏了。老工程师拍拍我&#xff1a;别慌&#xff0c;这就是C…

作者头像 李华
网站建设 2026/5/1 10:55:00

嵌入式硬件毕设避坑指南:从选型到部署的全链路技术解析

嵌入式硬件毕设避坑指南&#xff1a;从选型到部署的全链路技术解析 摘要&#xff1a;许多本科生在完成嵌入式硬件毕设时&#xff0c;常因缺乏系统性工程经验而陷入开发效率低、调试困难、功耗失控等问题。本文从真实项目痛点出发&#xff0c;对比主流MCU与开发框架&#xff08;…

作者头像 李华
网站建设 2026/5/1 11:44:37

从蝴蝶效应到信号处理:二维FFT在图像压缩中的艺术与科学

二维FFT在图像压缩中的艺术与科学&#xff1a;从频域视角重塑视觉信息 当一张照片从手机传输到云端&#xff0c;或在网页上快速加载时&#xff0c;背后隐藏着一场数学与工程的精妙舞蹈。图像压缩技术在这场舞蹈中扮演着关键角色&#xff0c;而二维快速傅里叶变换&#xff08;F…

作者头像 李华
网站建设 2026/4/23 11:44:01

智能客服知识库的AI辅助开发实战:从架构设计到性能优化

背景痛点&#xff1a;知识库的三座大山 做智能客服的同学都懂&#xff0c;知识库一旦上线&#xff0c;最怕的不是用户问得难&#xff0c;而是“没数据、没上下文、没覆盖”。我把它总结成三座大山&#xff1a; 冷启动数据不足 新项目启动时&#xff0c;历史工单只有几千条&…

作者头像 李华