<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>LangGraph Capabilities on On My Way</title>
    <link>https://tuanzi-wow.cn/frameworks/langgraph/capabilities/</link>
    <description>Recent content in LangGraph Capabilities on On My Way</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <atom:link href="https://tuanzi-wow.cn/frameworks/langgraph/capabilities/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Checkpointers</title>
      <link>https://tuanzi-wow.cn/frameworks/langgraph/capabilities/checkpointers/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://tuanzi-wow.cn/frameworks/langgraph/capabilities/checkpointers/</guid>
      <description>Checkpointers相关学习笔记与实践要点。</description>
      <content:encoded><![CDATA[<p>Checkpointer在每个super-step之后保存图状态的 snapshot(快照),并且按照thread进行组织</p>
<h1 id="why-use-checkpointers">Why use checkpointers</h1>
<p>适用于以下的场景:</p>
<ul>
<li>Human-in-the-loop:从interrupt中恢复运行</li>
<li>Memory:在交互之间保存memory,说直白点就是conversation history</li>
<li>Time travel:重放之前的图执行来调试或者审批;从外,允许fork(分叉)图状态</li>
<li>Fault-tolerance:从错误中恢复</li>
<li>Pending writes:在super-step中途失败时,可以恢复到之前成功的checkpoints</li>
</ul>
<h1 id="core-concepts">Core concepts</h1>
<h2 id="thread">Thread</h2>
<p>是分配给每个检查点的唯一ID或者标识符
包含一次运行的累计状态;当执行运行时,graph state会被持久化到这个线程中</p>
<p>当适用checkpointer调用graph 时,必须要在configurable中指明thread_id</p>
<p>线程的现状和历史状态都可以被检索.为了持久化,在执行运行之前必须创建一个线程</p>
<p>thread_id是存储和查询 checkpoints的主键</p>
<h1 id="checkpoints">Checkpoints</h1>
<p>线程中特定时间的state叫做checkpoint
是对每个super-step保存的graph state snapshot,由StateSnapshot对象表示</p>
<h2 id="super-steps">Super-steps</h2>
<p>LangGraph会在每个super-step边界常见checkpoint
resume只能从checkpoint执行</p>
<p>除了超级步骤检查点外，LangGraph 还会持久化<strong>节点（任务）级别</strong>的写入。随着超级步骤中的每个节点完成，其输出将作为链接到进行中检查点的任务条目写入检查点保存器的 <code>checkpoint_writes</code> 表中。这些按任务进行的写入支持了<a href="https://docs.langchain.org.cn/oss/python/langgraph/checkpointers#pending-writes">待处理写入</a>恢复：如果同一超级步骤中的另一个节点失败，已成功节点的写入已经是持久化的，在恢复时无需重新运行。超级步骤完成后，将提交完整的状态快照。</p>
<p>LangGraph 还会持久化超级步骤内单个节点执行的写入。这些写入以任务形式存储并用于容错：如果同一超级步骤中的另一个节点失败，恢复时无需重新计算成功的节点写入。这些任务写入不是完整的 <code>StateSnapshot</code> 检查点，因此时间旅行会从超级步骤边界的完整检查点恢复。</p>
<h2 id="checkpoints-namespace">checkpoints namespace</h2>
<p>每个检查点都有一个namespace_ns字段,来标识属于哪个图或者子图</p>
<ul>
<li>&ldquo;&quot;(空字符串):属于父(根)图</li>
<li>&ldquo;node_name: uuid&rdquo;: 属于给定节点调用的子图;对于嵌套子图，命名空间使用 <code>|</code> 分隔符连接（例如 <code>&quot;outer_node:uuid|inner_node:uuid&quot;</code>）</li>
</ul>
<p>你可以在node内部通过config访问checkpoint namespace</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-py" data-lang="py"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">langchain_core.runnables</span> <span class="kn">import</span> <span class="n">RunnableConfig</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">my_node</span><span class="p">(</span><span class="n">state</span><span class="p">:</span> <span class="n">State</span><span class="p">,</span> <span class="n">config</span><span class="p">:</span> <span class="n">RunnableConfig</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">checkpoint_ns</span> <span class="o">=</span> <span class="n">config</span><span class="p">[</span><span class="s2">&#34;configurable&#34;</span><span class="p">][</span><span class="s2">&#34;checkpoint_ns&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># &#34;&#34; for the parent graph, &#34;node_name:uuid&#34; for a subgraph</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h1 id="get-and-update-state">Get and update state</h1>
<h2 id="get-state">Get state</h2>
<p>调用graph.get_state(config)查看图的最新状态,会返回一个<code>StateSnapshot</code>对象,对应提供的线程ID所关联的最新checkpoint,或者提供特定的checkpoint_id访问特定的checkpoint</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># get the latest state snapshot
</span></span><span class="line"><span class="cl">config = {&#34;configurable&#34;: {&#34;thread_id&#34;: &#34;1&#34;}}
</span></span><span class="line"><span class="cl">graph.get_state(config)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"># get a state snapshot for a specific checkpoint_id
</span></span><span class="line"><span class="cl">config = {&#34;configurable&#34;: {&#34;thread_id&#34;: &#34;1&#34;, &#34;checkpoint_id&#34;: &#34;1ef663ba-28fe-6528-8002-5a559208592c&#34;}}
</span></span><span class="line"><span class="cl">graph.get_state(config)
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="statesnapshot-fields">StateSnapshot fields</h3>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Field</th>
					<th style="text-align: left">Type</th>
					<th style="text-align: left">Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left"><code>values</code></td>
					<td style="text-align: left"><code>dict</code></td>
					<td style="text-align: left">State channel values at this checkpoint.</td>
			</tr>
			<tr>
					<td style="text-align: left"><code>next</code></td>
					<td style="text-align: left"><code>tuple[str, ...]</code></td>
					<td style="text-align: left">Node names to execute next. Empty <code>()</code> means the graph is complete.</td>
			</tr>
			<tr>
					<td style="text-align: left"><code>config</code></td>
					<td style="text-align: left"><code>dict</code></td>
					<td style="text-align: left">Contains <code>thread_id</code>, <code>checkpoint_ns</code>, and <code>checkpoint_id</code>.</td>
			</tr>
			<tr>
					<td style="text-align: left"><code>metadata</code></td>
					<td style="text-align: left"><code>dict</code></td>
					<td style="text-align: left">Execution metadata. Contains <code>source</code> (<code>&quot;input&quot;</code>, <code>&quot;loop&quot;</code>, or <code>&quot;update&quot;</code>), <code>writes</code> (node outputs), and <code>step</code> (super-step counter).</td>
			</tr>
			<tr>
					<td style="text-align: left"><code>created_at</code></td>
					<td style="text-align: left"><code>str</code></td>
					<td style="text-align: left">ISO 8601 timestamp of when this checkpoint was created.</td>
			</tr>
			<tr>
					<td style="text-align: left"><code>parent_config</code></td>
					<td style="text-align: left">`dict</td>
					<td style="text-align: left">None`</td>
			</tr>
			<tr>
					<td style="text-align: left"><code>tasks</code></td>
					<td style="text-align: left"><code>tuple[PregelTask, ...]</code></td>
					<td style="text-align: left">Tasks to execute at this step. Each task has <code>id</code>, <code>name</code>, <code>error</code>, <code>interrupts</code>, and optionally <code>state</code> (subgraph snapshot, when using <code>subgraphs=True</code>).</td>
			</tr>
	</tbody>
</table>
<h2 id="get-state-history">Get state history</h2>
<p>通过调用 <a href="https://reference.langchain.org.cn/python/langgraph/graphs/#langgraph.graph.state.CompiledStateGraph.get_state_history"><code>graph.get_state_history(config)</code></a>获得对应thread_id的完整图执行历史记录,返回<code>StateSnapshot</code>对象列表,按照时间和顺序排序,最新的检查点为第一个元素</p>
<h3 id="find-a-specific-checkpoint">Find a specific checkpoint</h3>
<p>通过筛选过滤满足特定条件的checkpoints</p>
<h2 id="replay">Replay</h2>
<p>适用chexkpoint_id可以重新运行该检查点之后的节点,跳过之前的节点</p>
<h2 id="update-state">Update state</h2>
<p>适用<code>update_state</code>编辑graph state,这会创建一个包含更新值新的checkpoint:如果规定了reducer函数,值会通过reducer函数传递
可以指定as_node来控制更新被视为来自哪个node,这会影响接下来执行哪个node</p>
<h1 id="durabilty-modes持久化模式">Durabilty modes(持久化模式)</h1>
<p>提供了三种模式来在性能和数据一致性之间取得平衡</p>
<ul>
<li>&ldquo;exit&rdquo;:只在退出时持久化变更</li>
<li>&ldquo;async&rdquo;:在执行下一步的同时异步持久化变更</li>
<li>&ldquo;sync&rdquo;:在下一步开始之前同步持久化变更</li>
</ul>
<h1 id="optimize-checkpoint-storage">Optimize checkpoint storage</h1>
<p><a href="https://reference.langchain.org.cn/python/langgraph/channels/delta/DeltaChannel"><code>DeltaChannel</code></a> 仅存储增量变更（deltas）而非完整的累积值，大幅降低了对于追加频繁的通道的检查点大小</p>
<h1 id="checkpointer-libraries">Checkpointer libraries</h1>
<ul>
<li><code>langgraph-checkpoint</code>：检查点保存器基础接口（<a href="https://reference.langchain.org.cn/python/langgraph/checkpoints/#langgraph.checkpoint.base.BaseCheckpointSaver"><code>BaseCheckpointSaver</code></a>）和序列化/反序列化接口（<a href="https://reference.langchain.org.cn/python/langgraph/checkpoints/#langgraph.checkpoint.serde.base.SerializerProtocol"><code>SerializerProtocol</code></a>）。包含用于实验的内存中检查点保存器实现（<a href="https://reference.langchain.org.cn/python/langgraph/checkpoints/#langgraph.checkpoint.memory.InMemorySaver"><code>InMemorySaver</code></a>）。LangGraph 自带包含 <code>langgraph-checkpoint</code>。</li>
<li><code>langgraph-checkpoint-sqlite</code>：使用 SQLite 数据库的 LangGraph 检查点保存器实现（<a href="https://reference.langchain.org.cn/python/langgraph/checkpoints/#langgraph.checkpoint.sqlite.SqliteSaver"><code>SqliteSaver</code></a> / <a href="https://reference.langchain.org.cn/python/langgraph/checkpoints/#langgraph.checkpoint.sqlite.aio.AsyncSqliteSaver"><code>AsyncSqliteSaver</code></a>）。非常适合实验和本地工作流。需要单独安装。</li>
<li><code>langgraph-checkpoint-postgres</code>：使用 Postgres 数据库的高级检查点保存器（<a href="https://reference.langchain.org.cn/python/langgraph/checkpoints/#langgraph.checkpoint.postgres.PostgresSaver"><code>PostgresSaver</code></a> / <a href="https://reference.langchain.org.cn/python/langgraph/checkpoints/#langgraph.checkpoint.postgres.aio.AsyncPostgresSaver"><code>AsyncPostgresSaver</code></a>），在 LangSmith 中使用。非常适合在生产环境中使用。需要单独安装。</li>
<li><code>langchain-azure-cosmosdb</code>：使用 Azure Cosmos DB for NoSQL 的 LangGraph 检查点保存器实现（<a href="https://reference.langchain.org.cn/python/langchain-azure-cosmosdb/"><code>CosmosDBSaverSync</code></a> / <a href="https://reference.langchain.org.cn/python/langchain-azure-cosmosdb/"><code>CosmosDBSaver</code></a>）。非常适合与 Azure 一起在生产环境中使用。支持同步和异步操作，并支持 Microsoft Entra ID 身份验证。需要单独安装。</li>
</ul>
<h2 id="checkpointer-interface">Checkpointer interface</h2>
<ul>
<li><code>.put</code> - 存储包含配置和元数据的检查点。</li>
<li><code>.put_writes</code> - 存储链接到检查点的中间写入（即<a href="https://docs.langchain.org.cn/oss/python/langgraph/checkpointers#pending-writes">待处理写入</a>）。</li>
<li><code>.get_tuple</code> - 获取用于给定配置（<code>thread_id</code> 和 <code>checkpoint_id</code>）的检查点元组。这用于填充 <code>graph.get_state()</code> 中的 <code>StateSnapshot</code>。</li>
<li><code>.list</code> - 列出匹配给定配置和筛选条件的检查点。这用于填充 <code>graph.get_state_history()</code> 中的状态历史。</li>
</ul>
<p>如果检查点保存器与异步图执行一起使用（即通过 <code>.ainvoke</code>、<code>.astream</code>、<code>.abatch</code> 执行图），将使用上述方法的异步版本（<code>.aput</code>、<code>.aput_writes</code>、<code>.aget_tuple</code>、<code>.alist</code>）。</p>
]]></content:encoded>
    </item>
    <item>
      <title>Persistence</title>
      <link>https://tuanzi-wow.cn/frameworks/langgraph/capabilities/persistence/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://tuanzi-wow.cn/frameworks/langgraph/capabilities/persistence/</guid>
      <description>Persistence相关学习笔记与实践要点。</description>
      <content:encoded><![CDATA[<p>需求:continue a conversation, resume from a interrupt, recover from a failure, remember information across conversations
LangGraph提供了两个互补的持久化系统:</p>
<p><code>Checkpointer</code>将线程的graph state持久化为checkpoints
适用场景:short-term memory,thread -scoped memory</p>
<p><code>Stores:</code>将程序规定的数据持久化到graph state之外
适用场景:long-term memory,across-thread memory</p>
<h1 id="quickstart">Quickstart</h1>
<p>编译你的 graph with a checkpointer ,a store ,or both</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-py" data-lang="py"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">langgraph.checkpoint.memory</span> <span class="kn">import</span> <span class="n">InMemorySaver</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">langgraph.store.memory</span> <span class="kn">import</span> <span class="n">InMemoryStore</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">checkpointer</span> <span class="o">=</span> <span class="n">InMemorySaver</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">store</span> <span class="o">=</span> <span class="n">InMemoryStore</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">graph</span> <span class="o">=</span> <span class="n">builder</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="n">checkpointer</span><span class="o">=</span><span class="n">checkpointer</span><span class="p">,</span> <span class="n">store</span><span class="o">=</span><span class="n">store</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">result</span> <span class="o">=</span> <span class="n">graph</span><span class="o">.</span><span class="n">invoke</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="s2">&#34;messages&#34;</span><span class="p">:</span> <span class="p">[{</span><span class="s2">&#34;role&#34;</span><span class="p">:</span> <span class="s2">&#34;user&#34;</span><span class="p">,</span> <span class="s2">&#34;content&#34;</span><span class="p">:</span> <span class="s2">&#34;Hi, my name is Bob.&#34;</span><span class="p">}]},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span><span class="s2">&#34;configurable&#34;</span><span class="p">:</span> <span class="p">{</span><span class="s2">&#34;thread_id&#34;</span><span class="p">:</span> <span class="s2">&#34;thread-1&#34;</span><span class="p">}},</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h1 id="checkpointer-vs-store">Checkpointer vs store</h1>
<table>
	<thead>
			<tr>
					<th style="text-align: left"></th>
					<th style="text-align: left">Checkpointer</th>
					<th style="text-align: left">Store</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left">Persists</td>
					<td style="text-align: left">Graph state snapshots</td>
					<td style="text-align: left">Application-defined key-value data</td>
			</tr>
			<tr>
					<td style="text-align: left">Scope</td>
					<td style="text-align: left">A single thread</td>
					<td style="text-align: left">Across threads</td>
			</tr>
			<tr>
					<td style="text-align: left">Memory type</td>
					<td style="text-align: left">Short-term, thread-scoped memory</td>
					<td style="text-align: left">Long-term, cross-thread memory</td>
			</tr>
			<tr>
					<td style="text-align: left">Use for</td>
					<td style="text-align: left">Conversation continuity, human-in-the-loop, time travel, and fault tolerance</td>
					<td style="text-align: left">User preferences, facts, and shared knowledge</td>
			</tr>
			<tr>
					<td style="text-align: left">Access pattern</td>
					<td style="text-align: left">Pass a <code>thread_id</code> in graph config</td>
					<td style="text-align: left">Read and write items from nodes or application code</td>
			</tr>
			<tr>
					<td style="text-align: left">Full guide</td>
					<td style="text-align: left"><a href="https://docs.langchain.com/oss/python/langgraph/checkpointers">Checkpointers</a></td>
					<td style="text-align: left"><a href="https://docs.langchain.com/oss/python/langgraph/stores">Stores</a></td>
			</tr>
	</tbody>
</table>
<h1 id="troubleshooting-common-issues">Troubleshooting common issues</h1>
<h2 id="postgressaverthread_idtoo-long">PostgresSaver:<code>thread_id</code>too long</h2>
<p>使用(Async)PostgresSaver,<code>thread_id</code>存储在一个长度受限的列中,如果长度超出限制,则会报错</p>
<p>解决办法:将thread_id保持在255字符之内</p>
<h2 id="memorysaver-does-not-persist-between-restarts">MemorySaver does not persist between restarts</h2>
<p>MemorySaver和InMemorySaver 把checkpoints保存在RAM中,重启时,所有的checkpoints会丢失</p>
<p>解决方法:生产环境中使用可持久化的checkpointer</p>
<h2 id="checkpoints-growing-unboundedly">Checkpoints growing unboundedly</h2>
<p>checkpoints无休止增长可能导致延迟和存储的开销</p>
<p>解决方法:定期清理旧的checkpoints或者设置保留策略</p>
<h2 id="state-access-from-parent-graph-to-subgraph">State access from parent graph to subgraph</h2>
<p>子图的state更新时,父图不会立马看到这些更新:因为子图管理自己的checkpoint namespace</p>
<p>解决方法:需要跨图边界的数据,使用Store共享状态,或者配置你的子图谢图父checkpoints</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
