从零开始:前端转型AI agent直到就业第十四天-第十七天

前言

随着AI技术的飞速发展,前端开发领域受到了前所未有的冲击。许多传统的前端工作已经被AI自动化工具所取代,特别是在常规的页面布局和交互设计方面。对于拥有多年前端经验的开发者来说,如何在新的技术浪潮中找到自己的位置,成为了一个亟待解决的问题。本文将分享一位资深前端开发者在失业期间,通过自学AI技术,成功转型为AI Agent开发者的经历和心得。

心路历程

最近,这位开发者完成了对LangChainLangGraph相关知识点的学习,并准备进入实战阶段。虽然这段时间减少了锻炼,但他意识到身体健康的重要性,计划在接下来的日子里恢复锻炼。他希望通过自己的努力,能够产出一个有价值的智能体项目,并与大家分享项目回顾和总结。

此外,他在学习过程中遇到了一些挑战,特别是如何提高专注力。有时候,学习概念知识时容易分心,尤其是在没有实际编程操作的情况下。为了克服这一问题,他尝试了多种方法,包括定期休息、整理知识文档和阅读伟人的名言,以激励自己继续前进。

时间分配

最近的学习时间安排并不十分规律。早晨有时会晚起,花时间查看股票市场,休息时间也有所增加。尽管如此,他依然坚持每天投入一定的时间进行技术学习。为了更好地管理时间,他建议制定详细的学习计划,并严格执行,以确保学习效果。

知识总结

LangGraph 基础概念

一句话理解 LangGraph

> LangGraph = LangChain 的“图级编排器”
> 把线性流水线变成地铁网,支持分支、循环、回退和模块化。

生活比喻:

  • LangChain 像流水线:A→B→C,顺序固定
  • LangGraph 像地铁图:可分支、循环、折返、换乘

核心四要素

概念作用代码对应
State(状态)节点间传递的数据class StateObj(TypedDict)
Nodes(节点)执行具体任务graph.add_node("model", modelCb)
Edges(边)定义执行顺序graph.add_edge(START, "model")
Graph(图)整体结构容器StateGraph(StateObj)

基本连接LLM代码

from typing import TypedDict, Annotated, List
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv
import os

load_dotenv(encoding='utf-8')

# 关键:Annotated + add_messages 实现消息追加而非覆盖
class StateObj(TypedDict):
    messages: Annotated[List, add_messages]

llm = init_chat_model(
    model="qwen-plus",
    model_provider="openai",
    api_key=os.getenv("aliQwen-api"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)

# 关键:每个节点接收当前状态,返回部分更新
def modelCb(state: StateObj) -> StateObj:
    reply = llm.invoke(state["messages"])
    state["messages"].append({"role": "assistant", "content": reply})
    return state

代码解释

  1. 定义状态(State)

    • 使用 TypedDict 和 Annotated 来定义状态对象 StateObj,其中 messages 是一个列表,用于存储对话消息。
    • add_messages 函数确保消息列表在传递过程中不会被覆盖,而是追加新消息。
  2. 初始化大模型

    • 使用 init_chat_model 函数初始化一个大模型实例 llm,指定模型名称、提供商、API密钥和基础URL。
    • 通过 os.getenv 从环境变量中读取API密钥,确保安全性。
  3. 定义节点函数

    • modelCb 函数接收当前状态 state,调用大模型的 invoke 方法生成回复。
    • 将生成的回复添加到 messages 列表中,并返回更新后的状态对象。

总结

通过本文的分享,希望读者能够对从零开始构建AI Agent的过程有一个清晰的认识。无论是前端开发者还是其他领域的技术人员,都可以借鉴这位开发者的经验和方法,逐步掌握AI技术,实现职业转型。建议在学习过程中注重理论与实践相结合,合理安排时间,保持良好的生活习惯,不断提升自己的技术水平和竞争力。

4. 构建图

graph = StateGraph(StateObj)           # 创建图,绑定状态类型
graph.add_node("model", modelCb)       # 添加节点
graph.add_edge(START, "model")         # 起点 → 模型节点
graph.add_edge("model", END)           # 模型节点 → 终点

在这段代码中,我们首先创建了一个 StateGraph 实例,并绑定了状态类型 StateObj。然后,我们添加了一个名为 "model" 的节点,并定义了从起点 START 到该节点以及从该节点到终点 END 的边。这一步骤构建了图的基本结构,为后续的编译和运行奠定了基础。

5. 编译运行

app = graph.compile()
result = app.invoke({"messages": "请简单说明一下LangGraph的运作流程"})
print(result["messages"][-1].content)

通过调用 graph.compile() 方法,我们将图编译成一个可执行的 Runnable 对象 app。接着,我们使用 app.invoke() 方法传递初始状态,并获取最终结果。这里,我们传递了一个包含消息的字典,并打印出最后一条消息的内容。这一步骤展示了如何实际运行图结构并获取结果。

6. 可视化图结构

1. 打印图的ASCII可视化结构

print(app.get_graph().print_ascii())
print("="*50)

通过 app.get_graph().print_ascii() 方法,我们可以以 ASCII 形式打印图的结构。这对于调试和理解图的拓扑结构非常有帮助。打印结果将以文本形式展示节点和边的关系,便于快速查看。

2. 打印图的Mermaid代码可视化结构

print(app.get_graph().draw_mermaid())

app.get_graph().draw_mermaid() 方法生成图的 Mermaid 代码,可以通过在线工具如 ProcessOn 的 Mermaid 编辑器进行可视化。这种方法提供了更直观的图形展示,有助于更好地理解和分享图结构。

代码中的三个关键机制

1. Annotated[List, add_messages]

  • 作用: 告诉 LangGraph 新消息追加到列表末尾,而不是覆盖。
  • 不加的话: 每次返回 {"messages": [reply]} 会丢掉之前的对话历史。

通过使用 Annotated[List, add_messages],我们可以确保每次返回的消息都会被追加到现有列表中,而不是覆盖原有的对话历史。这对于维护连续的对话上下文非常重要。

2. 节点函数只返回部分状态

  • 作用: LangGraph 自动将返回值合并到当前状态。
  • 好处: 不需要返回整个 StateObj,极大简化代码。

节点函数只需返回需要更新的部分状态,LangGraph 会自动将其合并到当前状态对象中。这种方式不仅简化了代码,还提高了代码的可读性和维护性。

3. graph.compile() 的作用

  • 作用: 验证图结构(无孤立节点、无不可达节点、无非法循环)。
  • 生成: 可执行的 Runnable 对象。
  • 准备: 为后续扩展(如检查点、中断等)做准备。

graph.compile() 方法不仅验证图的结构是否正确,还生成一个可执行的 Runnable 对象。此外,它还为后续的功能扩展(如检查点、中断等)做好了准备,确保图在复杂场景下的稳定性和可靠性。

LangGraph 的重要特性

1. 条件分支(Conditional Edges)

  • 作用: 根据当前状态选择不同路径。
  • 代码示例:
def route(state):
    if state["need_human"]:
        return "human_node"
    return "model_node"

graph.add_conditional_edges("model", route, {"human_node": "human", "model_node": "model"})
  • 生活比喻: 地铁到站后,根据乘客目的地决定换乘哪条线。

条件分支允许我们在图中根据当前状态动态选择不同的路径,增加了图的灵活性和适应性。

2. 循环(Cycles)

  • 作用: 边可以指回之前的节点,形成循环。
  • 典型场景: 信息不足时重复搜索,直到条件满足。
  • 生活比喻: 坐错站了,坐回头车回到上一站。

循环结构使得图可以在某些条件下反复执行特定的节点,直到满足预定的条件,适用于需要多次迭代的场景。

3. 持久化与断点续跑(Persistence & Interrupt)

  • 作用: 使用 checkpointer 保存状态,程序重启后可恢复。
  • 代码示例:
from langgraph.checkpoint import MemorySaver
app = graph.compile(checkpointer=MemorySaver())
  • 生活比喻: 游戏存档,退出后能接着玩。

持久化功能允许我们在程序中断后恢复到之前的状态,确保长时间运行的任务不会因意外中断而丢失进度。

4. 人机协作(Human-in-the-Loop)

  • 作用: 图中插入人工节点,interrupt 暂停等待人工输入。
  • 典型场景: AI 生成内容后人工审核、敏感操作前人工确认。
  • 生活比喻: 自动驾驶遇到复杂路口,让司机接管一下。

人机协作功能使得图可以在需要人工干预的节点暂停执行,等待人工输入后再继续,适用于需要人工审核或确认的场景。

5. 子图(Subgraphs)

  • 作用: 一个节点可以是另一个完整的 StateGraph。
  • 好处: 模块化、可复用、独立测试。
  • 生活比喻: 地铁环线本身是一个完整的图,可以被嵌入全市地铁网。

子图功能允许我们将复杂的图结构分解为多个独立的子图,提高代码的模块化和可复用性,同时也方便独立测试和维护。

6. 时间旅行(Time Travel)

  • 作用: 回退到历史某个状态重新执行。
  • 生活比喻: 游戏中的“读档”功能。

时间旅行功能使得我们可以在图的执行过程中回退到历史状态,重新执行某些步骤,适用于需要调试或纠正错误的场景。

7. 多智能体协作(Multi-Agent)

  • 作用: 多个 Agent 节点在同一图中分工、协调、竞争。
  • 架构模式: 网络式、层级式、监督式等。

多智能体协作功能支持多个 Agent 节点在同一图中协同工作,适用于需要多个智能体共同完成任务的复杂场景。

8. 可观测性(Observability)

  • 作用: get_graph().print_ascii() 直接打印执行路径。
  • 好处: 清晰看到 Agent 的决策路径,快速定位问题。
  • 生活比喻: 地铁线路图贴在墙上,永远不会迷路。

可观测性功能使得我们能够清晰地看到图的执行路径和决策过程,有助于快速定位和解决问题,提高系统的透明度和可维护性。

适用场景速查

✅ 适合❌ 不适合
多步复杂推理简单一次性问答
需要循环/分支的逻辑线性链就够用的场景
长时间运行任务(需持久化)快速原型验证
需要人工介入-
多智能体协作-
追求生产级可观测性-

总结

State 是灵魂,Node 是手脚,Edge 是路线,Graph 是地图。
LangGraph 的核心价值在于:把 AI 工作流从线性锁链变成可控的网络,让你能自由实现分支、循环、持久化、人机协作、模块化复用等复杂逻辑。

目标

成为 AI Agent 工程师并且就业。

帮助

感谢大家的关注和支持,你们的鼓励是我前进的动力。希望未来有机会能与各位技术大牛合作,共同成长。