切换语言
中文 English 翻译中 日本語 翻译中
切换主题

LangGraph vs AutoGen 状态追踪对比:checkpoint机制、超时恢复与选型决策

30步科研文献梳理Agent,跑了整整2小时40分钟。

第25步,数据库接口超时崩溃。

前24步全部白跑。API调用成本、等待时间、已生成的文献摘要——全部归零。

这不是个例。我用AutoGen做过复杂工作流,状态不可控,智能体跑飞,排查问题花了3倍开发时间。后来换LangGraph,简单原型写了上百行状态定义代码。两个框架都踩过坑。

LangGraph vs AutoGen的状态管理,设计理念天差地别。一个用显式状态机控制流程,一个用对话式协议让Agent自由协商。选错了框架,80%的Agent项目失败不是因为大模型能力不够——是状态追踪这条路一开始就走歪了。

这篇文章从Checkpoint机制、超时恢复、分布式支持等12个维度对比两个框架,附真实踩坑案例、选型决策树和可运行代码。读完你应该能快速判断:你的项目,到底该用哪个。

状态管理的生死线:为什么Checkpoint是Agent的生命线

我给客户做了一个科研文献梳理Agent,连续调用10次学术数据库API,整理200篇文献摘要,生成综述报告。

执行时间预估3小时。跑到第25步(总步数30步),数据库接口超时崩溃。

传统Agent无状态——前24步全部白跑。已生成的文献摘要、API调用成本、2小时40分钟的等待时间,全部归零。重跑需要从头开始,API成本再烧一遍。

客户问:能不能从第25步接着跑?

答案:不能。传统Agent的状态只存在内存里,进程中断就没了。

传统Agent无状态的5大灾难

我踩过这个坑。当时用AutoGen做复杂售后工单处理流程,状态不可控,智能体跑飞,排查问题花了3倍开发时间。后来用LangGraph定义状态图,简单原型写了上百行代码。

总结下来,传统Agent无状态有5个致命问题:

1. 服务重启后所有对话历史丢失

部署新版本、服务器维护、意外崩溃——任何进程终止都会清空状态。用户正在进行的对话,瞬间断线。

2. 多轮任务中途中断后无法恢复

长流程任务(科研文献梳理、数据处理流水线)一旦失败,只能从头重跑。30步任务第25步崩溃,前24步白跑。

3. 无法支持多用户并发,状态互相干扰

同一个Agent实例服务多个用户,状态混在一起。用户A的对话历史被用户B的操作覆盖,数据污染。

4. 无法审计和回放历史执行过程

生产环境出了问题,想回看当时Agent怎么决策的?没记录。想复现Bug?没历史状态。

5. 长时任务一旦失败全部重来

数小时的任务(数据处理、批量生成)失败成本极高。API费用、时间成本、用户体验,全部损失。

LangGraph vs AutoGen:Checkpoint成熟度对比

LangGraph和AutoGen的Checkpoint能力,差距明显。

维度LangGraphAutoGen
Checkpoint原生支持每个节点自动保存快照Roadmap演进中
生产成熟度⭐⭐⭐⭐⭐(2026事实标准)⭐⭐⭐(仍在演进)
API稳定性LangChain生态稳定v0.2到v0.5大迁移,项目被迫回炉

LangGraph从设计之初就内置Checkpoint机制。每个节点执行完毕,自动保存State快照。崩溃后从中断点恢复,不重复执行已完成节点。

AutoGen的状态管理还在演进。2024年4月微软发布Persistence roadmap,2025年3月才有了Save/Load能力(AgentChat.NET)。用AutoGen v0.2开发的项目,升级到v0.5后API全部失效,代码重写。

Checkpoint不是锦上添花的功能——是Agent的生命线。生产环境没有状态持久化,等于裸奔。

LangGraph Checkpoint机制深度解析

Checkpoint本质:不是”存消息”,是”存图的完整状态”

很多人对Checkpoint有认知偏差——以为它就是”保存对话历史”。

其实不是。

Checkpoint保存的是Graph在某一执行步骤的完整状态快照。包括:

  • 所有Channel(State每个字段)的当前值
  • 当前执行到哪个节点
  • 父检查点ID(形成版本链)
  • 时间戳和元数据

类比Git的commit历史:每个节点执行都会产生一个”commit”,可以checkout到任意历史节点重跑。这不是对话历史备份,是整个工作流的状态快照。

Checkpoint v4数据结构详解

LangGraph当前使用Checkpoint v4,包含7个核心字段。据LangChain官方文档定义:

class Checkpoint:
    v: int                  # 版本号(当前为4)
    ts: str                  # 时间戳ISO格式
    id: str                  # UUID,唯一标识快照
    channel_values: dict     # State中每个字段的当前值
    channel_versions: dict   # 每个字段的版本号,用于冲突检测
    versions_seen: dict      # 记录各节点看到的版本,避免重复处理
    pending_sends: list      # 待发送的消息队列

重点解释channel_versions——这不是废字段。

LangGraph用版本号判断”某个节点是否需要重新执行”。这是断点续跑的底层依据:恢复时,检查每个Channel的版本号,跳过已经执行过的节点。

thread_id:多会话隔离的”平行宇宙坐标”

同一个Graph实例可以服务无数个对话线程。

每个线程有独立的Checkpoint序列,互不干扰。通过thread_id区分。

类比游戏存档槽:每个thread_id是一个独立的存档文件。用户A的对话状态不会影响用户B。

config = {"configurable": {"thread_id": "user-001"}}
result = graph.invoke(input, config)

换个thread_id,就是另一个平行宇宙。

Super-Step执行流程

LangGraph的执行流程叫Super-Step。据LangChain官方文档描述:

[读取上一个Checkpoint]

[执行当前节点,更新State]

[写入新Checkpoint(快照)]

[决定下一步:继续/等待/结束]

每个节点执行完毕,自动保存Checkpoint。崩溃后恢复,从中断点继续。

三种Checkpoint存储后端对比

存储类型适用场景特点
MemorySaver开发调试内存存储,重启丢失
SqliteSaver单机生产SQLite持久化,轻量级
PostgresSaver分布式生产PostgreSQL,支持pause/resume、分布式

开发阶段用MemorySaver,方便调试。生产环境用PostgresSaver,天然支持分布式部署。

RedisSaver适合高并发场景,读写速度快。

断点续跑实战

回到开头那个案例:30步科研文献梳理Agent,第25步超时失败。

用LangGraph的Checkpointer,从中断点恢复:

# 第7步失败后恢复
config = {"configurable": {"thread_id": "research-001"}}
recovered_state = compiled_graph.invoke({"step": 7}, config)
# 自动跳过前6步,从第7步继续

同一个thread_id,加载最近的Checkpoint,继续执行。

前24步不会重复执行。API费用、生成的内容,全部保留。

AutoGen状态追踪现状:Roadmap演进的代价

状态管理Roadmap演进历程

AutoGen的状态管理,还在演进中。

据GitHub Issue #2358记录,2024年4月微软发布Persistence and state management roadmap。AutoGen v0.2到v0.5的API大挪移,项目被迫回炉。

我踩过这个坑。用AutoGen v0.2开发的项目,升级到v0.5后API全部失效。ConversableAgent、GroupChat这些核心类,接口变了。代码重写。

2025年3月,Save/Load for AgentChat.NET PR (#5841)发布。AgentChat agents和teams可以回滚到snapshots(Issue #4100)。SingleThreadedAgentRuntime state serialization文档化(Issue #4108)。

状态管理能力有了,但成熟度不如LangGraph。

终止条件控制:四类熔断机制

AutoGen有个痛点:两Agent就”单引号还是双引号”争论50轮,烧掉$5 API费用。

或者夜间自动任务因对话未终止持续运行8小时,第二天发现账单爆了。

AutoGen v0.4采用事件驱动架构,消息循环持续监听。若无终止条件,形成资源黑洞。

据AutoGen官方文档,提供四类终止条件:

终止类型控制维度适用场景
MaxMessageTermination轮次控制限制总消息数不超过10条
TextMentionTermination内容控制检测”TERMINATE”关键词
TimeoutTermination时间控制防止长时挂起占用连接
TokenUsageTermination成本控制防止预算超限

组合使用:

from autogen_agentchat.conditions import (
    MaxMessageTermination,
    TimeoutTermination,
    TokenUsageTermination
)

# 组合终止条件
termination = (
    MaxMessageTermination(max_messages=20)
    | TimeoutTermination(timeout_seconds=3600)
    | TokenUsageTermination(max_tokens=10000)
)

达到任一条件,对话终止。熔断机制防止无限循环。

对话式协议vs状态机:隐式vs显式的哲学差异

AutoGen和LangGraph的设计哲学,完全不同。

AutoGen用对话式协议(Conversational Programming):

  • ConversableAgent:可对话的智能体基类
  • GroupChat:多个Agent扔进群聊
  • GroupChatManager:决定下一个谁发言(轮询、自动选人、自定义策略)

Agent是会聊天的实体,通过自然语言对话协作。状态隐式嵌入对话流,不如LangGraph显式管理。

LangGraph用状态机(State Machine):

  • State TypedDict:显式定义状态结构
  • Node:每个节点的处理逻辑
  • Edge:节点间的连接和条件分支

每一步执行,状态如何变化,下一步去哪,全部显式定义。

AutoGen适合灵活对话流——不确定下一步谁发言,让Agent自由协商。

LangGraph适合精确控制——条件分支明确,流程路径可预测。

Checkpoint序列化能力(AgentChat.NET)

AutoGen的Checkpoint能力,通过序列化实现。

据GitHub PR #5841,AgentChat.NET支持保存/加载Agent状态:

# 保存状态到文件
team.save_state("checkpoint.json")

# 从文件恢复
team.load_state("checkpoint.json")

这是文件序列化,不是数据库持久化。适合单机场景,分布式部署需要额外适配。

可观测性方面,AutoGen用OpenTelemetry三大支柱:Logs、Metrics、Traces。事件流监控+Replay重放调试,问题定位方便。

核心对比与技术选型:12维度量化对比

选框架就像选结婚对象——没有最好的,只有最适合你的。

LangGraph和AutoGen代表了Agent框架的两大技术路线:状态机优先的工作流编排,对话优先的多角色协作。

12维度量化对比表格

维度LangGraphAutoGen评分差异
状态管理模型显式State TypedDict隐式对话流LangGraph +2
Checkpoint机制原生支持,每个节点自动保存Roadmap演进,依赖序列化LangGraph +3
恢复能力Super-Step级别恢复对话回滚(发展中)LangGraph +2
终止控制条件边(Conditional Edge)TerminationCondition类平手
持久化介质Memory/SQLite/Postgres/Redis文件序列化LangGraph +2
时间旅行支持任意历史回滚Replay重放LangGraph +1
Human-in-the-Loopinterrupt() + Command(resume=)UserProxyAgent人工代理LangGraph +1
分布式支持PostgresSaver天然支持事件驱动架构适配分布式LangGraph +1
开发灵活性细粒度控制,需定义State+Edge对话驱动,快速原型AutoGen +1
学习曲线高,需理解图状态机中,需理解对话模式AutoGen +1
API稳定性LangChain生态稳定v0.2到v0.5大迁移LangGraph +2
生产成熟度⭐⭐⭐⭐⭐⭐⭐⭐LangGraph +2

总评:LangGraph状态管理能力领先(+14分),AutoGen对话灵活性优势(+2分)。

这不是说LangGraph更好——是说LangGraph更适合需要精确状态控制的场景。AutoGen更适合需要灵活对话流协作的场景。

适用场景决策流程图

怎么选?看你的需求。

需求分析

是否有明确的条件分支流程?
  ├─ 是 → LangGraph
  └─ 否 → 是否需要多Agent自由协商?
      ├─ 是 → AutoGen
      └─ 否 → 是否需要长流程任务容错?
          ├─ 是 → LangGraph
          └─ 否 → 是否是快速原型?
              ├─ 是 → AutoGen
              └─ 否 → 默认LangGraph(生产级)

LangGraph优势场景

LangGraph适合这些场景:

1. 复杂条件分支工作流

售后工单处理流程:判断问题类型 → 分流到不同处理路径 → 汇总结果。条件分支明确,LangGraph的Conditional Edge精确控制。

2. 需要精确状态控制的长流程任务

科研文献梳理Agent:连续调用10次数据库、整理200篇文献、生成综述。执行时间3小时,中途崩溃需从Checkpoint恢复。LangGraph的Super-Step级别恢复,不重复执行已完成节点。

3. 生产级Human-in-the-Loop审核流程

合同审核、敏感邮件审核——生成初稿后暂停,等待人工确认。LangGraph的interrupt() + Command(resume=),优雅暂停恢复。

4. 需要时间旅行调试的场景

Bug复现、A/B测试——回滚到任意历史版本,分支探索。LangGraph的Checkpoint序列可checkout到任意节点。

5. 分布式部署的高并发Agent系统

客服系统:多实例部署,状态共享。PostgresSaver天然支持分布式,无状态竞争。

AutoGen优势场景

AutoGen适合这些场景:

1. 多Agent自由对话协商

剧本杀推理、辩论场景——不确定下一步谁发言,让Agent自由协商。GroupChat自动选人策略,灵活对话流。

2. 快速原型开发

概念验证Demo——快速搭建,无需定义State+Edge。对话驱动,上手快。

3. 角色扮演型协作

文案+设计+运营讨论——不同角色Agent协作,模拟真实团队对话。

4. 代码生成+执行闭环

Code Executor + UserProxyAgent——生成代码、执行、反馈、修正。AutoGen原生支持代码执行闭环。

5. 需要灵活对话流的场景

下一步不确定——GroupChatManager决定谁发言,无需预设流程。

实战代码示例:同一需求两个框架实现

用同一个需求,对比两个框架的实现差异。

需求定义:长流程科研文献梳理Agent

任务描述

  • 连续调用10次学术数据库API
  • 整理200篇文献摘要
  • 生成综述报告

执行时间:约3小时

容错需求

  • 第7步数据库接口超时失败
  • 需从Checkpoint恢复,不重复前6步

Human-in-the-Loop

  • 生成初稿后暂停
  • 等待人工确认后生成终稿

LangGraph实现

from langgraph.checkpoint.sqlite import SqliteSaver
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated
from operator import add

# 定义State结构
class ResearchState(TypedDict):
    papers: Annotated[list, add]  # 累加,不覆盖
    summaries: Annotated[list, add]
    draft: str
    final_report: str
    step: int
    human_approved: bool

# 定义节点函数
def fetch_papers(state: ResearchState):
    """调用学术数据库API"""
    step = state["step"]
    papers = call_database_api(step)  # 假设的API调用
    return {"papers": papers, "step": step + 1}

def summarize_papers(state: ResearchState):
    """生成文献摘要"""
    papers = state["papers"]
    summaries = generate_summaries(papers)  # 假设的摘要生成
    return {"summaries": summaries}

def generate_draft(state: ResearchState):
    """生成初稿"""
    summaries = state["summaries"]
    draft = generate_report(summaries)  # 假设的报告生成
    return {"draft": draft}

def human_review(state: ResearchState):
    """人工审核节点(interrupt后等待resume)"""
    return {"human_approved": True}

def generate_final(state: ResearchState):
    """生成终稿"""
    draft = state["draft"]
    final_report = refine_report(draft)
    return {"final_report": final_report}

# 构建Graph
graph = StateGraph(ResearchState)

# 添加节点
graph.add_node("fetch", fetch_papers)
graph.add_node("summarize", summarize_papers)
graph.add_node("draft", generate_draft)
graph.add_node("review", human_review)
graph.add_node("final", generate_final)

# 定义边
graph.add_edge("fetch", "summarize")
graph.add_edge("summarize", "draft")
graph.add_edge("draft", "review")
graph.add_edge("review", "final")
graph.add_edge("final", END)

# 设置入口
graph.set_entry_point("fetch")

# 添加Checkpointer(核心)
checkpointer = SqliteSaver.from_conn_string("research_checkpoints.db")
compiled_graph = graph.compile(
    checkpointer=checkpointer,
    interrupt_before=["review"]  # 在review节点前暂停
)

# 执行任务
config = {"configurable": {"thread_id": "research-session-001"}}
result = compiled_graph.invoke({"step": 0}, config)

# 第7步失败后恢复
# 使用相同thread_id,自动跳过前6步
recovered_state = compiled_graph.invoke({"step": 7}, config)

# Human-in-the-Loop恢复
# 初稿生成后暂停,人工确认后继续
compiled_graph.invoke(
    Command(resume={"human_approved": True}),
    config
)

关键特性

  • SqliteSaver自动保存每个节点执行后的State
  • thread_id隔离不同会话
  • 恢复时自动跳过已执行节点(通过channel_versions判断)
  • interrupt_before实现Human-in-the-Loop暂停

AutoGen实现

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.conditions import (
    MaxMessageTermination,
    TimeoutTermination,
    TokenUsageTermination
)
from autogen_core.models import ChatCompletionClient

# 定义Agent
research_agent = AssistantAgent(
    name="researcher",
    model_client=ChatCompletionClient(model="gpt-4"),
    system_message="你是一个科研文献梳理助手。\
        连续调用数据库、整理摘要、生成报告。\
        完成后说'TERMINATE'。"
)

human_agent = AssistantAgent(
    name="human_reviewer",
    model_client=ChatCompletionClient(model="gpt-4"),
    system_message="你是审核人员。审核初稿后说'APPROVED'或'REJECT'。"
)

# 设置终止条件(防止无限循环)
termination = (
    MaxMessageTermination(max_messages=50)
    | TimeoutTermination(timeout_seconds=10800)  # 3小时
    | TokenUsageTermination(max_tokens=50000)
    | TextMentionTermination(text="TERMINATE")
)

# 构建Team
team = RoundRobinGroupChat(
    participants=[research_agent, human_agent],
    termination_condition=termination
)

# 执行任务
async def run_research():
    result = await team.run(
        task="梳理200篇文献摘要,生成综述报告"
    )
    return result

# Checkpoint保存(AgentChat.NET)
team.save_state("research_checkpoint.json")

# 从Checkpoint恢复
team.load_state("research_checkpoint.json")

# 继续执行
async def resume_research():
    result = await team.run()
    return result

关键特性

  • TerminationCondition防止无限循环(熔断机制)
  • Save/Load状态到文件(序列化方式)
  • 事件驱动架构适配分布式
  • 对话式协议:Agent通过自然语言协作

两者对比总结

特性LangGraphAutoGen
状态定义显式TypedDict隐式对话流
Checkpoint节点自动保存(数据库)文件序列化
恢复机制Super-Step级别跳过已执行节点对话回滚
Human-in-the-Loopinterrupt暂停 + resume恢复UserProxyAgent介入
终止控制条件边路由TerminationCondition熔断
代码量约60行(需定义State+Edge)约30行(对话驱动)

LangGraph:细粒度控制,适合精确状态管理。

AutoGen:快速原型,适合灵活对话协作。

生产级部署建议:从开发到生产的完整路径

LangGraph生产部署要点

持久化方案

PostgresSaver + RedisSaver组合。

PostgreSQL做持久化存储,天然支持分布式部署。Redis做缓存层,高并发场景读写快。

from langgraph.checkpoint.postgres import PostgresSaver
from langgraph.checkpoint.redis import RedisSaver

# 生产级配置
postgres_saver = PostgresSaver.from_conn_string(
    "postgresql://user:pass@host:5432/db"
)
redis_saver = RedisSaver.from_conn_string(
    "redis://host:6379/0"
)

# 组合使用:Redis缓存 + Postgres持久化
compiled_graph = graph.compile(
    checkpointer=postgres_saver
)

可观测性

LangSmith tracing + OpenTelemetry集成。

LangSmith看调用链路追踪——哪个节点慢、哪个Token消耗多。OpenTelemetry对接现有监控体系。

性能优化

流式输出——用户立即看到第一个token,延迟感知<1秒。

并行Tool调用——LangGraph原生支持,多工具同时执行。

Prompt预编译——减少LLM推理时间约30%。

成本优化

策略成本降幅适用场景
Prompt压缩30-50%通用场景
多Provider路由40-60%生产环境failover
Cache机制50-80%重复查询场景

多Provider路由是生产级标配。API Gateway实现failover:GPT-4挂了自动切换Claude,成本还能降40%。

AutoGen生产部署要点

可观测性

OpenTelemetry三大支柱——Logs、Metrics、Traces。

  • EventLogger + 结构化日志:问题定位、审计追溯
  • OpenTelemetry Meter:性能监控、容量规划
  • OpenTelemetry Tracer:调用链路分析、延迟优化
from autogen_core.telemetry import (
    enable_telemetry,
    EventLogger
)

# 启用可观测性
enable_telemetry(
    logger=EventLogger(),
    meter=OpenTelemetryMeter(),
    tracer=OpenTelemetryTracer()
)

事件流监控

Replay重放调试技术——所有Agent行为产生事件流,可回放复现问题。

分布式适配

事件驱动架构天然支持分布式。Agent间消息通过事件传递,无状态竞争。

成本控制

TokenUsageTermination熔断——达到预算上限自动终止。

from autogen_agentchat.conditions import TokenUsageTermination

# 设置成本熔断
termination = TokenUsageTermination(max_tokens=10000)

结构化日志分析Token消耗——哪些对话消耗多、哪个Agent成本高。

生产部署对比表

维度LangGraphAutoGen
持久化PostgresSaver分布式支持文件序列化(需适配)
可观测性LangSmith tracingOpenTelemetry三大支柱
成本控制多Provider路由TokenUsageTermination熔断
性能优化流式输出+并行Tool事件流监控
分布式PostgresSaver天然支持事件驱动适配

核心教训:生产环境必须有AI Gateway

不管选LangGraph还是AutoGen,生产环境必须加AI Gateway。

为什么?

1. 多Provider failover

API挂了自动切换。GPT-4宕机?切换Claude。单点故障消除。

2. 成本监控

哪个Agent消耗多、哪个对话成本高——实时监控。预算超限自动熔断。

3. 速率限制

防止API被限流。请求排队、自动重试。

4. 日志追踪

所有调用集中记录。问题定位、审计追溯。

AI Gateway不是可选功能——是生产级Agent的必选项。

结论

LangGraph和AutoGen代表了Agent框架的两大技术路线。

LangGraph:状态机优先的工作流编排。显式定义State+Node+Edge,每步可控。Checkpoint原生支持,崩溃恢复不重复执行。适合复杂条件分支、长流程任务、分布式部署。

AutoGen:对话优先的多角色协作。Agent通过自然语言协商,灵活对话流。终止条件熔断防止无限循环。适合快速原型、多Agent自由协商、角色扮演型场景。

选型不是”哪个更好”,是”哪个更适合你的场景”。

有明确的条件分支流程?LangGraph。需要多Agent自由协商?AutoGen。长流程任务需容错?LangGraph。快速原型验证?AutoGen。

两个框架我都踩过坑。AutoGen状态不可控、API迁移重写代码。LangGraph定义状态图写了上百行。

核心教训:生产环境必须加AI Gateway。多Provider failover、成本监控、速率限制——这三个功能是Agent稳定运行的底线。

下一步:如果你的项目是复杂工作流,选LangGraph。如果想快速搭个多Agent原型,选AutoGen。然后去读”LangGraph状态管理实战”(系列序号39),深入Checkpoint机制实践。

常见问题

LangGraph的Checkpoint机制和传统对话历史保存有什么区别?
Checkpoint保存的是Graph在某一执行步骤的完整状态快照,包括所有Channel的当前值、当前执行节点、父检查点ID等,类比Git的commit历史。传统对话历史只保存消息文本,无法支持断点续跑和时间旅行调试。
为什么AutoGen需要终止条件控制?
AutoGen v0.4采用事件驱动架构,消息循环持续监听。若无终止条件,两个Agent可能就细枝末节争论50轮,烧掉大量API费用。终止条件(MaxMessage、Timeout、TokenUsage)提供熔断机制,防止无限循环和预算超限。
生产环境为什么必须配置AI Gateway?
AI Gateway提供四个核心能力:多Provider failover(API挂了自动切换)、成本监控(实时追踪Token消耗)、速率限制(防止API限流)、日志追踪(问题定位和审计追溯)。这是Agent稳定运行的底线保障。
如何根据项目需求选择LangGraph或AutoGen?
有明确条件分支流程、需要长流程任务容错、精确状态控制 → 选LangGraph。需要多Agent自由协商、快速原型验证、角色扮演型协作 → 选AutoGen。生产级长流程任务推荐LangGraph,其Checkpoint成熟度领先(+14分)。

15 分钟阅读 · 发布于: 2026年5月26日 · 修改于: 2026年5月26日

相关文章

BetterLink

想持续收到这个主题的更新?

你可以直接关注作者更新、订阅 RSS,或者继续沿着系列入口往下读,避免下次又回到搜索结果重新找。

关注公众号

评论

使用 GitHub 账号登录后即可评论