langgraph笔记

文章目录

相比于langchain,定制程度更高,按步骤来的。

机制

1、初始化 # builder = StateGraph(AgentState)

2、添加点

3、添加边

4、编译

5、运行 # app.stream()

核心代码是哪些?

AgentState相当于一个共享对象。

python 复制代码
class AgentState(TypedDict):
    messages: Annotated[List[str], operator.add]
    final_answer: str

加入点和边(edge),这样就形成了图。

python 复制代码
builder = StateGraph(AgentState)

# 添加节点
builder.add_node("ai_engine", llm_node)
builder.add_node("human_gate", human_review)

# 定义流程:开始 -> AI -> 人工 -> 结束
builder.add_edge(START, "ai_engine")
builder.add_edge("ai_engine", "human_gate")
builder.add_edge("human_gate", END)

app = builder.compile()
基础示例1

代码:

python 复制代码
import operator
from typing import Annotated, List, TypedDict
from langgraph.graph import StateGraph, START, END


# ==========================================
# 1. 定义状态 (State)
# ==========================================
# 这是整个工作流的"记忆",所有节点都共享这个状态
class AgentState(TypedDict):
    messages: Annotated[List[str], operator.add]  # 消息列表,operator.add 表示新消息会追加到列表
    translation: str  # 存放翻译结果


# ==========================================
# 2. 定义节点 (Nodes)
# ==========================================

def ai_translate(state: AgentState):
    """模拟 AI 翻译节点"""
    print(f"🤖 AI 正在思考: {state['messages'][-1]} ...")

    # 这里模拟一个简单的翻译逻辑(实际项目中你会在这里调用 LLM)
    last_msg = state['messages'][-1]
    if "你好" in last_msg:
        translated = "Hello, how are you doing?"
    else:
        translated = f"Translation of: {last_msg}"

    print(f"🤖 AI 翻译完成: {translated}")

    # 更新状态
    return {
        "messages": ["AI 已生成翻译"],
        "translation": translated
    }


def human_review(state: AgentState):
    """模拟人工审核节点"""
    print("\n--- ⏸️ 暂停:等待人工审核 ---")
    print(f"当前翻译结果是:【 {state['translation']} 】")

    # 在实际应用中,这里会挂起等待 API 回调
    # 这里为了演示,我们直接模拟用户说 "通过"
    print("👤 人类:看起来没问题,通过!(模拟自动通过)")

    return {"messages": ["人类已审核通过"]}


# ==========================================
# 3. 构建图 (Build Graph)
# ==========================================

# 初始化构建器
builder = StateGraph(AgentState)

# 添加节点
builder.add_node("translator", ai_translate)
builder.add_node("reviewer", human_review)

# 定义边(流程控制)
# 流程:开始 -> 翻译 -> 审核 -> 结束
builder.add_edge(START, "translator")
builder.add_edge("translator", "reviewer")
builder.add_edge("reviewer", END)

# 编译成可执行的图
app = builder.compile()

# ==========================================
# 4. 运行
# ==========================================
if __name__ == "__main__":
    print("🚀 启动 LangGraph 工作流...\n")

    # 初始输入
    inputs = {"messages": ["你好"], "translation": ""}

    # 调用 invoke 开始运行
    # stream 模式可以看到每一步的状态变化
    for output in app.stream(inputs):
        # output 是一个字典,key 是节点名,value 是该节点返回的状态更新
        for key, value in output.items():
            print(f"✅ 节点 [{key}] 执行完毕,返回: {value}")

    print("\n🎉 流程结束!")
    print(f"最终结果: {value.get('translation')}")
基础示例2-加入了大模型

代码:

python 复制代码
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from langgraph.graph import StateGraph, START, END
from typing import Annotated, List, TypedDict
import operator

# ==========================================
# 1. 加载本地模型 (Qwen2.5-0.5B)
# ==========================================
print("⏳ 正在加载本地模型 (首次运行需下载)...")
model_name = "Qwen/Qwen2.5-0.5B-Instruct"

# 自动检测是否有 GPU
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"🚀 使用设备: {device}")

tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    torch_dtype=torch.float16 if device == "cuda" else torch.float32,  # 显卡用半精度,CPU用单精度
    device_map="auto"
)


# ==========================================
# 2. 定义 LangGraph 状态
# ==========================================
class AgentState(TypedDict):
    messages: Annotated[List[str], operator.add]
    final_answer: str


# ==========================================
# 3. 定义节点
# ==========================================

def llm_node(state: AgentState):
    """调用本地 Qwen 模型进行推理"""
    user_input = state['messages'][-1]
    print(f"🤖 [LLM] 收到输入: {user_input}")

    # 构造 Qwen 的对话提示词格式
    messages = [
        {"role": "system", "content": "你是一个聪明的助手,请简短回答问题。"},
        {"role": "user", "content": user_input}
    ]

    # 应用聊天模板
    text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
    model_inputs = tokenizer([text], return_tensors="pt").to(device)

    # 生成回答
    generated_ids = model.generate(
        model_inputs.input_ids,
        max_new_tokens=512,
        do_sample=True,
        temperature=0.7
    )

    # 解码输出
    generated_ids = [
        output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
    ]
    response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

    print(f"🤖 [LLM] 回答: {response}")
    return {"messages": ["AI已回复"], "final_answer": response}


def human_review(state: AgentState):
    """人工审核节点"""
    print("\n--- ⏸️ 暂停:等待人工审核 ---")
    print(f"👀 AI 生成的回答是:【 {state['final_answer']} 】")

    # 模拟人工确认
    confirm = input("👤 是否满意?(输入 y 继续,其他退出): ")
    if confirm.lower() == 'y':
        return {"messages": ["用户确认通过"]}
    else:
        print("❌ 用户拒绝,流程终止。")
        # 这里简单处理,实际可以跳转到重写节点
        exit()


# ==========================================
# 4. 构建并运行图
# ==========================================
builder = StateGraph(AgentState)

# 添加节点
builder.add_node("ai_engine", llm_node)
builder.add_node("human_gate", human_review)

# 定义流程:开始 -> AI -> 人工 -> 结束
builder.add_edge(START, "ai_engine")
builder.add_edge("ai_engine", "human_gate")
builder.add_edge("human_gate", END)

app = builder.compile()

if __name__ == "__main__":
    print("\n🚀 === LangGraph + Qwen 本地智能体启动 ===\n")
    while True:
        query = input("👤 请输入问题 (输入 'quit' 退出): ")
        if query == 'quit': break

        inputs = {"messages": [query], "final_answer": ""}

        # 运行工作流
        for output in app.stream(inputs):
            for node_name, values in output.items():
                if values.get('final_answer'):
                    print(f"✅ 最终结果: {values['final_answer']}")
        print("-" * 30)
为什么叫边不叫线?

点和边是图中两个核心概念。

之所以不叫线,是因为线是没有方向的,但是边有方向(图概念里面的边和平行四边形的边可不一样)。

相关推荐
惊鸿一博3 分钟前
自动驾驶与大模型相关VLA4AD
人工智能·机器学习·自动驾驶
qq7590353663 分钟前
docker一键部署SQLynx,轻量级数据库管理平台
数据库·docker·容器
xixixi777774 分钟前
Gartner 2026核心趋势:前置式主动安全(PCS)成为安全战略新范式,量子安全+国密算法构筑政企纵深防御底座
网络·人工智能·安全·web安全·ai·量子计算
Rubin智造社4 分钟前
04月20日AI每日参考:华为AI眼镜今日发布,Meta裁员8000人押注AI文件格式
人工智能·claude code·ai硬件·华为ai眼镜·meta裁员·cerebras ipo·字节跳动seedance
m0_515098425 分钟前
如何实现SQL数据分片规则更新_利用触发器同步元数据
jvm·数据库·python
qq_330037995 分钟前
uni-app怎么实现App端蓝牙搜索与连接 uni-app低功耗蓝牙开发【代码】
jvm·数据库·python
三品吉他手会点灯6 分钟前
C语言学习笔记 - 2.C概述 - HelloWorld程序举例
c语言·笔记·学习
带娃的IT创业者6 分钟前
深度解析 Qwen3.6-35B-A3B:重塑 AI 编程代理的开源新标杆
人工智能·python·ai·开源·大模型·qwen·编程代理
qq_654366986 分钟前
SQL中如何通过JOIN实现级联删除_利用外键约束与JOIN辅助
jvm·数据库·python
2301_764150567 分钟前
layui form禁用表单元素 layui如何disable一个输入框
jvm·数据库·python