邓立国《LangGraph开发AI Agent实践》1~8章试读_langgraph开发ai agent实践在线阅读-CSDN博客

9.3.1  初始化模型

该程序使用的是DashScope提供的云端API服务(通义千问Qwen-Turbo),属于无状态的远程模型调用。

1. 首先安装必要的依赖

# 安装基础依赖

pip install langgraph==1.0.5 langchain langchain-community gradio dashscope python-dotenv

# 安装LangSmith用于追踪

pip install langsmith

2. 模型初始化相关代码

从功能角度看,模型调用所需的配置与封装可以视为“模型初始化”的逻辑部分。以下是程序中与模型初始化和调用准备相关的核心代码片段。

1)环境配置

# ====================== 1. 环境配置 ======================

import os

from dotenv import load_dotenv

import dashscope

# 加载环境变量

load_dotenv()

# 配置通义千问 API 密钥(这是使用 DashScope 模型的前提)

dashscope.api_key = os.getenv("DASHSCOPE_API_KEY") or ""

2)模型调用函数(封装模型接口)

# ====================== 2. 模型调用函数(封装模型接口) ======================

from dashscope import Generation

def call_qwen_model(prompt: str, temperature: float = 0.3) -> str:

    """调用通义千问模型(带LangSmith追踪)"""

    try:

        response = Generation.call(

            model="qwen-turbo",                # 指定模型

            messages=[{"role": "user", "content": prompt}],

            temperature=temperature,

            result_format='text'

        )

        return response.output.text.strip()

    except Exception as e:

        return f"模型调用出错:{str(e)}"

  • dashscope.api_key=...是使用DashScope API的必要初始化步骤,相当于“认证初始化”。
  • call_qwen_model函数是对模型调用的统一封装,指定了:
  • 模型名称:qwen-turbo。
  • 输入格式:messages(符合聊天格式)。
  • 输出格式:text。
  • 控制参数:temperature。

9.3.2  构建图结构与定义节点的逻辑

构建图结构-定义节点的逻辑包含两个部分:

(1)节点函数的实现(即每个节点的具体逻辑)。

(2)在图中注册这些节点(通过graph.add_node()

定义节点的逻辑,我们聚焦于节点函数本身的实现逻辑,即每个节点做了什么。节点定义逻辑代码(不含图注册、路由或边连接代码):

def identify_intent_node(state: SupportState) -> SupportState:

    """节点1:识别用户意图"""

    prompt = """

    你是一个客户支持意图识别助手,请分析用户的问题并归类到以下类别之一:

    - faq: 常见问题(账户、产品使用、价格等)

    - technical: 技术问题(故障、报错、功能异常等)

    - complaint: 投诉(服务不满、产品质量、退款等)

    - other: 无法分类的其他问题

   

    只需要返回类别名称,不要返回其他内容。

   

    用户问题:{user_input}

    """.format(user_input=state["user_input"])

   

    intent = call_qwen_model(prompt).lower()

    valid_intents = ["faq", "technical", "complaint", "other"]

    state["intent"] = intent if intent in valid_intents else "other"

    return state

def answer_faq_node(state: SupportState) -> SupportState:

    """节点2:回答常见问题"""

    prompt = """

    你是一个专业的客户支持助手,请友好、简洁地回答用户的常见问题。

    回答要准确、易懂,避免使用专业术语。

   

    聊天历史:{chat_history}

    用户问题:{user_input}

   

    请给出你的回答:

    """.format(

        chat_history=state["chat_history"],

        user_input=state["user_input"]

    )

   

    state["response"] = call_qwen_model(prompt)

    return state

def handle_technical_node(state: SupportState) -> SupportState:

    """节点3:处理技术问题"""

    prompt = """

    你是一位技术支持专家,请详细解答用户的技术问题。

    步骤要清晰,先给出解决方案概述,再分步骤说明。

   

    聊天历史:{chat_history}

    用户问题:{user_input}

   

    请给出你的回答:

    """.format(

        chat_history=state["chat_history"],

        user_input=state["user_input"]

    )

   

    state["response"] = call_qwen_model(prompt)

    return state

def handle_complaint_node(state: SupportState) -> SupportState:

    """节点4:处理投诉问题"""

    prompt = """

    你是一名客户投诉处理专员,请先表达歉意,然后记录投诉内容,

    并给出具体的解决措施和时间承诺。保持语气诚恳、专业。

   

    聊天历史:{chat_history}

    用户问题:{user_input}

   

    请给出你的回复:

    """.format(

        chat_history=state["chat_history"],

        user_input=state["user_input"]

    )

   

    state["response"] = call_qwen_model(prompt)

    return state

def transfer_to_human_node(state: SupportState) -> SupportState:

    """节点5:转接人工客服"""

    state["response"] = """

    非常抱歉,我暂时无法解答你的问题。

    正在为你转接人工客服,请稍候...

   

    人工客服工作时间:9:00~18:00

    你也可以通过以下方式联系我们:

    - 客服热线:400-123-4567

    - 邮箱:support@example.com

    """

    return state

说明:

  • 每个节点函数接收SupportState类型的状态对象,处理后原地更新并返回。
  • 所有节点均为纯函数式设计:无副作用,仅依赖输入状态,输出更新后的状态。
  • 除transfer_to_human_node外,其余节点均通过call_qwen_model调用大模型生成响应。
  • 节点职责明确:
  • 意图识别→分类。
  • FAQ/技术/投诉→领域化生成。
  • 转人工→静态兜底回复。

注意:call_qwen_model和 SupportState类型定义虽未在此段落内,但属于节点逻辑的必要依赖,在实际使用中需一并保留。

9.3.3  连接节点与转向边缘

“连接节点-转向边缘”(即定义节点之间如何连接,特别是基于条件的动态路由)主要体现在以下两个部分:

(1)使用条件路由函数(route_by_intent)决定从意图识别节点转向哪个处理节点。

(2)使用add_conditional_edges添加条件边。

(3)使用add_edge添加静态终止边(所有处理节点→END)。

以下是完整抽取的“连接节点-转向边缘”逻辑代码:

# 定义条件路由函数:根据意图状态动态选择下一个节点

def route_by_intent(state: SupportState) -> str:

    """根据意图转向不同节点"""

    intent = state["intent"]

    routing_map = {

        "faq": "answer_faq",

        "technical": "handle_technical",

        "complaint": "handle_complaint",

        "other": "transfer_to_human"

    }

    return routing_map.get(intent, "transfer_to_human")

# 添加从意图识别节点出发的条件边(动态路由)

graph.add_conditional_edges(

    source="identify_intent",

    path=route_by_intent,

    path_map={

        "answer_faq": "answer_faq",

        "handle_technical": "handle_technical",

        "handle_complaint": "handle_complaint",

        "transfer_to_human": "transfer_to_human"

    }

)

# 所有处理节点执行完毕后直接结束(静态边,无循环)

graph.add_edge("answer_faq", END)

graph.add_edge("handle_technical", END)

graph.add_edge("handle_complaint", END)

graph.add_edge("transfer_to_human", END)

说明:

  • add_conditional_edges:实现动态分支,根据state["intent"]的值在运行时决定流向哪个节点。
  • path_map:显式声明所有可能的返回值与目标节点的映射关系(LangGraph 1.x 推荐写法,增强可读性和校验)。
  • add_edge(..., END):确保每个处理路径单向终止,符合“无递归、单次执行”的设计目标。
  • 该逻辑位于build_support_graph()函数内部,依赖已添加的节点(如"identify_intent""answer
    _faq" 等)。

9.3.4  LangSmith追踪

LangSmith 是一个用于调试、测试、评估和监控大型语言模型应用的开发平台,特别适合与 LangChain 等框架配合使用。本节将讲解LangSmith API密钥的申请和使用方法。

1. LangSmith API密钥的申请

首先到LangSmith网站https://smith.langchain.com申请LangSmith API密钥,步骤说明如下:

(1)访问LangSmith官网:打开浏览器,访问网址https://smith.langchain.com。

(2)登录或注册账号:如果你已经有LangChain账号(例如通过GitHub或邮箱注册过),直接登录。如果没有,请点击Sign Up注册一个新账号(支持GitHub、Google或邮箱注册)。

(3)进入API密钥管理页面:点击右上角你的头像或用户名,在下拉菜单中选择“API Keys”(或访问:https://smith.langchain.com/settings/api_keys)。

(4)创建新API密钥:点击“Create API Key”按钮,为密钥添加一个描述(如My LangGraph Project),再点击Create按钮,系统会生成一个形如lsk_abc123def456...的密钥。

(5)使用API密钥,在你的代码或环境变量中设置:

  • export LANGCHAIN_API_KEY=lsk_abc123def456...
  • export LANGCHAIN_TRACING_V2=true
  • export LANGCHAIN_PROJECT=YourProjectName  # 可选,指定项目名

启用LANGCHAIN_TRACING_V2=true后,LangChain会自动将trace数据发送到LangSmith网站,方便读者调试和分析。简单说,使用LangSmith可以:

  • 查看每个节点的执行过程。
  • 监控模型调用的耗时和成本。
  • 调试对话流程中的问题。
  • 记录用户对话历史。
  • 分析意图识别的准确性。

LangSmith追踪(LangSmith Tracing)的配置与使用主要体现在两个部分:

  • 在系统环境变量LANGSMITH_API_KEY中配置(启用追踪并设置项目信息)。
  • 在Gradio接口中使用tracing_v2_enabled上下文管理器包裹图的执行。

2. LangSmith追踪相关代码

以下是完整抽取的LangSmith追踪相关代码。

(1)环境配置(启用LangSmith追踪):

# ====================== 1. 环境配置(启用 LangSmith 追踪) ======================

import os

from dotenv import load_dotenv

from langchain_core.tracers.context import tracing_v2_enabled

load_dotenv()

# 启用 LangSmith 追踪

os.environ["LANGCHAIN_TRACING_V2"] = "true"

os.environ["LANGCHAIN_API_KEY"] = os.getenv("LANGCHAIN_API_KEY") or ""

os.environ["LANGCHAIN_PROJECT"] = "客户支持聊天机器人-无递归版"

os.environ["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com"

(2)在图执行时启用追踪上下文:

# ====================== 2. 在图执行时启用追踪上下文 ======================

def chat_interface(message, history):

    # ...(构建 initial_state

    # 使用 tracing_v2_enabled 上下文管理器包裹图的invoke调用

    with tracing_v2_enabled(project_name="客户支持聊天机器人"):

        result = support_graph.invoke(initial_state)

   

return result["response"]

说明:

  • LANGCHAIN_TRACING_V2="true":全局开启LangChain v2追踪功能。
  • LANGCHAIN_API_KEY:用于认证LangSmith服务(需在LangSmith获取)。
  • LANGCHAIN_PROJECT:指定追踪数据归属的项目名称(用于LangSmith控制台分组)。
  • LANGCHAIN_ENDPOINT:LangSmith API地址(默认官方地址)。
  • tracing_v2_enabled(project_name=...):上下文级追踪控制,确保本次invoke的完整执行链(包括所有节点)被记录到指定项目。

该代码通过“环境变量全局启用+上下文管理器精细控制”的方式,实现了对LangGraph工作流执行过程的端到端可观测性,所有节点输入/输出、模型调用、状态变更均可在LangSmith控制台中查看、调试和评估。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐