{"id":123472,"date":"2026-11-07T11:33:11","date_gmt":"2026-11-07T03:33:11","guid":{"rendered":"https:\/\/www.wsisp.com\/helps\/123472.html"},"modified":"2026-11-07T11:33:11","modified_gmt":"2026-11-07T03:33:11","slug":"langgraph-%e4%bf%9d%e5%a7%86%e7%ba%a7%e5%85%a5%e9%97%a8%ef%bc%9astate%e3%80%81node%e3%80%81edge-%e4%b8%89%e5%a4%a7%e4%bb%b6%ef%bc%8c%e5%8a%a0%e4%b8%8a%e6%a3%80%e6%9f%a5%e7%82%b9%e3%80%81%e6%b5%81","status":"publish","type":"post","link":"https:\/\/www.wsisp.com\/helps\/123472.html","title":{"rendered":"LangGraph \u4fdd\u59c6\u7ea7\u5165\u95e8\uff1aState\u3001Node\u3001Edge \u4e09\u5927\u4ef6\uff0c\u52a0\u4e0a\u68c0\u67e5\u70b9\u3001\u6d41\u5f0f\u8f93\u51fa\u4e0e\u4eba\u5de5\u5ba1\u6838"},"content":{"rendered":"<p>\u8bf4\u660e&#xff1a;\u672c\u6587\u7cfb\u7edf\u68b3\u7406 LangGraph \u7684\u6838\u5fc3\u6982\u5ff5\u4e0e\u5de5\u7a0b\u7528\u6cd5&#xff0c;\u53c2\u8003 LangGraph \u5b98\u65b9\u6587\u6863\u4e0e\u793e\u533a\u5b9e\u8df5\u7ecf\u9a8c\u6574\u7406\u800c\u6210&#xff0c;\u9762\u5411&#034;\u4f1a\u4e00\u70b9 Python\u3001\u4f46\u5b8c\u5168\u6ca1\u63a5\u89e6\u8fc7 LangGraph&#034;\u7684\u540c\u5b66\u3002\u5168\u6587\u6309&#034;\u662f\u4ec0\u4e48 \u2192 \u4e3a\u4ec0\u4e48 \u2192 \u600e\u4e48\u8dd1 \u2192 \u6bcf\u4e2a\u6982\u5ff5\u62c6\u5f00\u8bb2 \u2192 \u8e29\u5751\u6e05\u5355&#034;\u7684\u987a\u5e8f\u5c55\u5f00&#xff0c;\u5efa\u8bae\u6309\u987a\u5e8f\u9605\u8bfb\u3002<\/p>\n<h3>\u76ee\u5f55<\/h3>\n<ul>\n<li>\u4e00\u3001\u5148\u8bb2\u4eba\u8bdd&#xff1a;\u4e3a\u4ec0\u4e48\u9700\u8981 LangGraph<\/li>\n<li>\u4e8c\u3001LangGraph \u5230\u5e95\u662f\u4ec0\u4e48<\/li>\n<li>\u4e09\u3001LangGraph \u548c LangChain \u5230\u5e95\u5dee\u5728\u54ea<\/li>\n<li>\u56db\u3001\u628a\u73af\u5883\u8dd1\u8d77\u6765<\/li>\n<li>\u4e94\u3001\u5feb\u901f\u5165\u95e8&#xff1a;20 \u884c\u4ee3\u7801\u8dd1\u901a\u7b2c\u4e00\u4e2a\u56fe<\/li>\n<li>\u516d\u3001State&#xff1a;\u6574\u4e2a\u5e94\u7528\u7684\u6570\u636e\u4e2d\u67a2<\/li>\n<li>\u4e03\u3001\u72b6\u6001\u5b58\u50a8&#xff1a;Checkpointer \u4e0e thread_id<\/li>\n<li>\u516b\u3001\u63ed\u5f00\u5e95\u724c&#xff1a;Pregel \u662f\u600e\u4e48\u628a\u56fe\u8dd1\u8d77\u6765\u7684<\/li>\n<li>\u4e5d\u3001\u68c0\u67e5\u70b9\u5feb\u7167&#xff1a;\u600e\u4e48\u628a\u5386\u53f2\u72b6\u6001\u7ffb\u51fa\u6765\u770b<\/li>\n<li>\u5341\u3001Node&#xff1a;\u8282\u70b9\u600e\u4e48\u5199\u624d\u4e0d\u51fa\u9519<\/li>\n<li>\u5341\u4e00\u3001\u56fe\u5185\u5916\u6570\u636e\u4f20\u9012&#xff1a;\u6d41\u5f0f\u8f93\u51fa\u516d\u79cd\u6a21\u5f0f<\/li>\n<li>\u5341\u4e8c\u3001Human-in-the-Loop&#xff1a;\u8ba9\u7528\u6237\u53c2\u4e0e\u5173\u952e\u51b3\u7b56<\/li>\n<li>\u5341\u4e09\u3001Edge&#xff1a;\u8fb9\u548c\u4e24\u79cd\u6d41\u8f6c\u65b9\u5f0f<\/li>\n<li>\u5341\u56db\u3001\u8e29\u5751\u6e05\u5355&#xff1a;\u8fd9\u4e9b\u5751\u6211\u5e2e\u4f60\u5148\u8e29\u4e86<\/li>\n<li>\u5341\u4e94\u3001\u5b66\u4e60\u8def\u7ebf\u5efa\u8bae<\/li>\n<li>\u5341\u516d\u3001\u603b\u7ed3<\/li>\n<\/ul>\n<hr \/>\n<h3>\u4e00\u3001\u5148\u8bb2\u4eba\u8bdd&#xff1a;\u4e3a\u4ec0\u4e48\u9700\u8981 LangGraph<\/h3>\n<p>\u5982\u679c\u4f60\u7528\u8fc7 LangChain&#xff0c;\u5927\u6982\u7387\u5199\u8fc7\u8fd9\u6837\u7684\u4ee3\u7801&#xff1a;<\/p>\n<p>chain &#061; prompt | llm | output_parser<br \/>\nresult &#061; chain.invoke({&#034;question&#034;: &#034;\u4ec0\u4e48\u662f LangGraph&#034;})<\/p>\n<p>\u8fd9\u6761&#034;\u94fe&#034;\u5c31\u50cf\u5de5\u5382\u91cc\u7684\u6d41\u6c34\u7ebf&#xff1a;\u539f\u6599\u8fdb\u53bb&#xff0c;\u6309\u56fa\u5b9a\u987a\u5e8f\u7ecf\u8fc7\u51e0\u9053\u5de5\u5e8f&#xff0c;\u6210\u54c1\u51fa\u6765\u3002\u505a\u7ffb\u8bd1\u3001\u6458\u8981\u3001\u5355\u8f6e\u95ee\u7b54\u8fd9\u7c7b\u4efb\u52a1&#xff0c;\u975e\u5e38\u987a\u624b\u3002<\/p>\n<p>\u4f46\u771f\u5b9e\u7684 Agent \u9700\u6c42&#xff0c;\u5f80\u5f80\u4e0d\u662f\u4e00\u6761\u7b14\u76f4\u7684\u6d41\u6c34\u7ebf&#xff0c;\u800c\u662f\u4e00\u5f20\u4f1a\u62d0\u5f2f\u7684\u6d41\u7a0b\u56fe&#xff1a;<\/p>\n<ul>\n<li>\u6a21\u578b\u8bf4&#034;\u6211\u8981\u67e5\u4e00\u4e0b\u5929\u6c14&#034;&#xff0c;\u7a0b\u5e8f\u5c31\u5f97\u5148\u53bb\u8c03\u5de5\u5177&#xff0c;\u62ff\u5230\u7ed3\u679c\u518d\u56de\u5230\u6a21\u578b \u2014\u2014 \u8fd9\u662f\u5faa\u73af&#xff1b;<\/li>\n<li>\u7528\u6237\u95ee&#034;\u6211\u8ba2\u5355\u5230\u54ea\u4e86&#034;\u5c31\u8d70\u8ba2\u5355\u5206\u652f&#xff0c;\u95ee&#034;\u8fd9\u4e2a\u5546\u54c1\u6709\u8d27\u5417&#034;\u5c31\u8d70\u5546\u54c1\u5206\u652f \u2014\u2014 \u8fd9\u662f\u6761\u4ef6\u5206\u652f&#xff1b;<\/li>\n<li>\u8981\u8f6c\u51fa 8000 \u5143&#xff0c;\u5f97\u5148\u505c\u4e0b\u6765&#xff0c;\u7b49\u4eba\u70b9\u4e00\u4e0b&#034;\u540c\u610f&#034; \u2014\u2014 \u8fd9\u662f\u4eba\u5de5\u4ecb\u5165&#xff1b;<\/li>\n<li>\u8dd1\u5230\u7b2c 3 \u6b65\u670d\u52a1\u5668\u5d29\u4e86&#xff0c;\u91cd\u542f\u540e\u5e0c\u671b\u80fd\u4ece\u7b2c 3 \u6b65\u7ee7\u7eed&#xff0c;\u800c\u4e0d\u662f\u4ece\u5934\u518d\u7b97\u4e00\u904d \u2014\u2014 \u8fd9\u662f\u6301\u4e45\u5316 \/ \u65ad\u70b9\u7eed\u8dd1\u3002<\/li>\n<\/ul>\n<p>\u8fd9\u56db\u4ef6\u4e8b&#xff0c;\u7528\u4e00\u6761 A | B | C \u7684\u94fe\u53bb\u786c\u5199&#xff0c;\u4f1a\u975e\u5e38\u522b\u626d\u3002LangGraph \u5c31\u662f\u4e3a\u4e86\u89e3\u51b3\u8fd9\u7c7b\u95ee\u9898\u800c\u751f\u7684\u3002\u4e00\u53e5\u8bdd\u6982\u62ec\u4e24\u8005\u7684\u5206\u5de5&#xff1a;<\/p>\n<p>\u5f53 LLM \u5e94\u7528\u9700\u8981\u300c\u6709\u72b6\u6001\u3001\u53ef\u5faa\u73af\u3001\u53ef\u5206\u652f\u7684\u591a\u6b65\u9aa4\u63a7\u5236\u6d41&#xff08;\u50cf\u4e00\u4e2a\u53ef\u56de\u6eaf\u7684\u6d41\u7a0b\u56fe \/ \u72b6\u6001\u673a&#xff09;\u300d\u65f6&#xff0c;LangChain \u5f88\u96be\u4f18\u96c5\u5b8c\u6210&#xff0c;\u800c\u5fc5\u987b\u7528 LangGraph\u3002<\/p>\n<p>\u6362\u4e2a\u6bd4\u65b9&#xff1a;LangChain \u662f\u96f6\u4ef6\u5e93 &#043; \u6d41\u6c34\u7ebf&#xff0c;LangGraph \u662f\u8f66\u95f4\u7684\u8c03\u5ea6\u4e2d\u5fc3\u3002 \u5b98\u65b9\u4e5f\u662f\u8fd9\u4e48\u5b9a\u4f4d\u7684\u2014\u2014LangChain \u63d0\u4f9b\u6a21\u578b\u3001\u5de5\u5177\u3001\u5411\u91cf\u5e93\u8fd9\u4e9b&#034;\u96f6\u4ef6&#034;&#xff0c;LangGraph \u8d1f\u8d23\u628a\u8fd9\u4e9b\u96f6\u4ef6\u7f16\u6392\u6210\u4e00\u53f0\u80fd\u8dd1\u3001\u80fd\u505c\u3001\u80fd\u6062\u590d\u7684\u673a\u5668\u3002<\/p>\n<h3>\u4e8c\u3001LangGraph \u5230\u5e95\u662f\u4ec0\u4e48<\/h3>\n<h4>2.1 \u5b98\u65b9\u5b9a\u4e49\u7ffb\u8bd1\u6210\u4eba\u8bdd<\/h4>\n<p>LangGraph \u662f\u4e00\u4e2a\u4f4e\u7ea7\u7f16\u6392\u6846\u67b6\u548c\u8fd0\u884c\u65f6\u73af\u5883&#xff0c;\u7528\u4e8e\u6784\u5efa\u3001\u7ba1\u7406\u548c\u90e8\u7f72\u957f\u671f\u8fd0\u884c\u7684\u6709\u72b6\u6001\u667a\u80fd\u4f53&#xff08;Agent&#xff09;\u3002\u5b83\u7684\u6838\u5fc3\u7406\u5ff5\u662f\u628a Agent \u5de5\u4f5c\u6d41\u5efa\u6a21\u6210\u4e00\u5f20\u56fe&#xff08;Graph&#xff09;\u3002<\/p>\n<p>\u65e2\u7136\u662f\u4e00\u5f20\u56fe&#xff0c;\u90a3\u5c31\u53ea\u6709\u4e09\u6837\u4e1c\u897f&#xff0c;\u8bb0\u4f4f\u8fd9\u4e09\u4e2a\u8bcd&#xff0c;\u540e\u9762\u7684\u5185\u5bb9\u90fd\u80fd\u6302\u4e0a\u53bb&#xff1a;<\/p>\n<table>\n<tr>\u6982\u5ff5\u662f\u4ec0\u4e48\u5927\u767d\u8bdd\u7c7b\u6bd4<\/tr>\n<tbody>\n<tr>\n<td>\u8282\u70b9 Nodes<\/td>\n<td>\u8ba1\u7b97\u5355\u5143&#xff0c;\u53ef\u4ee5\u662f LLM \u8c03\u7528\u3001\u5de5\u5177\u6267\u884c\u3001\u6216\u4efb\u4f55\u81ea\u5b9a\u4e49\u903b\u8f91<\/td>\n<td>\u6d41\u6c34\u7ebf\u4e0a\u7684\u4e00\u4e2a\u5de5\u4f4d&#xff0c;\u6bcf\u4e2a\u5de5\u4f4d\u53ea\u5e72\u4e00\u4ef6\u5177\u4f53\u7684\u4e8b<\/td>\n<\/tr>\n<tr>\n<td>\u8fb9 Edges<\/td>\n<td>\u8282\u70b9\u4e4b\u95f4\u7684\u8f6c\u6362\u903b\u8f91&#xff0c;\u51b3\u5b9a\u6267\u884c\u6d41\u7a0b<\/td>\n<td>\u5de5\u4f4d\u4e4b\u95f4\u7684\u4f20\u9001\u5e26&#xff0c;\u51b3\u5b9a\u4e0b\u4e00\u4e2a\u96f6\u4ef6\u9001\u53bb\u54ea\u4e2a\u5de5\u4f4d<\/td>\n<\/tr>\n<tr>\n<td>\u72b6\u6001 State<\/td>\n<td>\u6574\u4e2a\u56fe\u6267\u884c\u8fc7\u7a0b\u4e2d\u5171\u4eab\u3001\u4f20\u9012\u7684\u6570\u636e<\/td>\n<td>\u4e00\u4e2a\u6240\u6709\u5de5\u4f4d\u90fd\u80fd\u8bfb\u5199\u7684&#034;\u5171\u4eab\u8bb0\u4e8b\u672c&#034;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u6240\u4ee5\u5199\u4e00\u4e2a LangGraph \u5e94\u7528&#xff0c;\u672c\u8d28\u5c31\u662f\u5728\u753b\u4e00\u5f20\u5e26\u65b9\u5411\u7684\u6d41\u7a0b\u56fe&#xff0c;\u518d\u7ed9\u8fd9\u5f20\u56fe\u914d\u4e00\u4e2a\u5171\u4eab\u8bb0\u4e8b\u672c\u3002<\/p>\n<h4>2.2 LangGraph \u63d0\u4f9b\u7684\u4e94\u5927\u6838\u5fc3\u80fd\u529b<\/h4>\n<p>\u5b98\u65b9\u5f3a\u8c03\u5b83\u6709\u4e94\u6837\u4e1c\u897f&#xff0c;\u6b63\u597d\u5bf9\u5e94\u751f\u4ea7\u73af\u5883\u7684\u4e94\u4e2a\u75db\u70b9&#xff1a;<\/p>\n<ul>\n<li>\u6301\u4e45\u5316\u6267\u884c&#xff1a;\u80fd\u4ece\u6545\u969c\u4e2d\u6062\u590d&#xff0c;\u652f\u6301\u957f\u65f6\u95f4\u8fd0\u884c&#xff1b;<\/li>\n<li>\u4eba\u673a\u534f\u4f5c&#xff1a;\u53ef\u4ee5\u5728\u4efb\u610f\u65f6\u523b\u68c0\u67e5\u3001\u751a\u81f3\u4fee\u6539\u667a\u80fd\u4f53\u7684\u72b6\u6001&#xff1b;<\/li>\n<li>\u8bb0\u5fc6\u7ba1\u7406&#xff1a;\u540c\u65f6\u652f\u6301&#034;\u77ed\u671f\u5de5\u4f5c\u8bb0\u5fc6&#034;\u548c&#034;\u8de8\u4f1a\u8bdd\u7684\u957f\u671f\u8bb0\u5fc6&#034;&#xff1b;<\/li>\n<li>\u6d41\u5f0f\u5904\u7406&#xff1a;\u5929\u751f\u4e3a\u6d41\u5f0f\u5de5\u4f5c\u6d41\u8bbe\u8ba1&#xff08;\u80fd\u8fb9\u8dd1\u8fb9\u5f80\u5916\u5410\u6570\u636e&#xff09;&#xff1b;<\/li>\n<li>\u751f\u4ea7\u7ea7\u90e8\u7f72&#xff1a;\u4e3a\u6709\u72b6\u6001\u3001\u957f\u671f\u8fd0\u884c\u7684\u5de5\u4f5c\u6d41\u63d0\u4f9b\u53ef\u6269\u5c55\u7684\u57fa\u7840\u8bbe\u65bd\u3002<\/li>\n<\/ul>\n<p>\u5b98\u65b9\u5730\u5740&#xff0c;\u5efa\u8bae\u6536\u85cf&#xff1a;<\/p>\n<ul>\n<li>GitHub&#xff1a;&lt;https:\/\/github.com\/langchain-ai\/langgraph&gt;<\/li>\n<li>\u5b98\u65b9\u6587\u6863&#xff1a;&lt;https:\/\/docs.langchain.com\/oss\/python\/langgraph\/overview&gt;<\/li>\n<\/ul>\n<h3>\u4e09\u3001LangGraph \u548c LangChain \u5230\u5e95\u5dee\u5728\u54ea<\/h3>\n<h4>3.1 \u4e00\u5f20\u8868\u770b\u6e05\u533a\u522b<\/h4>\n<table>\n<tr>\u7279\u6027LangGraphLangChain<\/tr>\n<tbody>\n<tr>\n<td>\u62bd\u8c61\u7ea7\u522b<\/td>\n<td>\u4f4e\u7ea7&#xff0c;\u63d0\u4f9b\u7ec6\u7c92\u5ea6\u63a7\u5236<\/td>\n<td>\u9ad8\u7ea7&#xff0c;\u5f00\u7bb1\u5373\u7528<\/td>\n<\/tr>\n<tr>\n<td>\u72b6\u6001\u7ba1\u7406<\/td>\n<td>\u5185\u7f6e\u72b6\u6001\u673a\u548c\u68c0\u67e5\u70b9<\/td>\n<td>\u9700\u8981\u81ea\u884c\u7ba1\u7406\u72b6\u6001<\/td>\n<\/tr>\n<tr>\n<td>\u6267\u884c\u6a21\u578b<\/td>\n<td>\u57fa\u4e8e\u56fe\u7684\u5e76\u884c\u6267\u884c<\/td>\n<td>\u7ebf\u6027\u94fe\u5f0f\u6267\u884c<\/td>\n<\/tr>\n<tr>\n<td>\u6301\u4e45\u5316<\/td>\n<td>\u539f\u751f\u652f\u6301<\/td>\n<td>\u9700\u8981\u989d\u5916\u5b9e\u73b0<\/td>\n<\/tr>\n<tr>\n<td>\u9002\u7528\u573a\u666f<\/td>\n<td>\u590d\u6742\u3001\u6709\u72b6\u6001\u7684\u667a\u80fd\u4f53\u5e94\u7528\u5f00\u53d1<\/td>\n<td>\u7b80\u5355\u7684\u94fe\u5f0f\u8c03\u7528<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>3.2 \u56e0\u4e3a\u8fd9\u79cd\u533a\u522b&#xff0c;LangGraph \u5728\u8fd9\u4e9b\u573a\u666f\u66f4\u5403\u9999<\/h4>\n<ul>\n<li>\u590d\u6742\u7684\u591a\u667a\u80fd\u4f53\u7cfb\u7edf&#xff08;\u4e00\u4e2a\u4e3b Agent \u5e26\u4e00\u5806\u5b50 Agent&#xff09;&#xff1b;<\/li>\n<li>\u9700\u8981\u957f\u671f\u8bb0\u5fc6\u7684\u5e94\u7528&#xff08;\u8de8\u5929\u3001\u8de8\u4f1a\u8bdd\u8bb0\u5f97\u4f60\u662f\u8c01&#xff09;&#xff1b;<\/li>\n<li>\u9700\u8981\u4eba\u5de5\u5ba1\u6838\u7684\u5de5\u4f5c\u6d41&#xff08;\u5ba1\u6279\u3001\u8f6c\u8d26\u3001\u53d1\u90ae\u4ef6\u3001\u6539\u6570\u636e\u5e93&#xff09;&#xff1b;<\/li>\n<li>\u540e\u53f0\u5904\u7406\u4efb\u52a1\u548c\u5b9e\u65f6\u4ea4\u4e92\u5e76\u5b58\u7684\u7cfb\u7edf&#xff1b;<\/li>\n<li>\u9700\u8981\u7cbe\u7ec6\u63a7\u5236\u7684\u5b9a\u5236\u5316\u667a\u80fd\u4f53\u7f16\u6392\u3002<\/li>\n<\/ul>\n<h4>3.3 \u4e09\u4e2a\u5e38\u89c1\u8bef\u533a&#xff0c;\u5148\u5e2e\u4f60\u6392\u6389<\/h4>\n<li>\u8bef\u533a\u4e00&#xff1a;\u5b66\u4e86 LangGraph \u5c31\u4e0d\u7528\u5b66 LangChain\u3002 \u4e0d\u5bf9\u3002LangGraph \u91cc\u7684\u6a21\u578b\u3001\u5de5\u5177\u3001\u6d88\u606f\u7c7b\u578b&#xff0c;\u57fa\u672c\u90fd\u6765\u81ea LangChain \u751f\u6001&#xff0c;\u4e24\u8005\u662f&#034;\u7f16\u6392\u5c42 &#043; \u7ec4\u4ef6\u5c42&#034;\u7684\u5173\u7cfb&#xff0c;\u5b98\u65b9\u63a8\u8350\u7684\u5199\u6cd5\u5c31\u662f\u6df7\u7740\u7528\u3002<\/li>\n<li>\u8bef\u533a\u4e8c&#xff1a;\u7b80\u5355\u4efb\u52a1\u7528 LangGraph \u662f\u6740\u9e21\u7528\u725b\u5200\u3002 \u7b80\u5355\u4efb\u52a1\u786e\u5b9e\u7528 LangChain \u66f4\u5feb&#xff1b;\u4f46\u5982\u679c\u4f60\u9884\u671f\u8fd9\u4e2a\u5e94\u7528\u4f1a\u4e0d\u65ad\u52a0\u5206\u652f\u3001\u52a0\u5faa\u73af\u3001\u52a0\u4eba\u5de5\u5ba1\u6279&#xff0c;\u4e00\u5f00\u59cb\u5c31\u4e0a LangGraph&#xff0c;\u540e\u671f\u6539\u9020\u6210\u672c\u53cd\u800c\u66f4\u4f4e\u3002<\/li>\n<li>\u8bef\u533a\u4e09&#xff1a;LangChain \u4e5f\u6709 Agent \u5faa\u73af&#xff0c;\u591f\u7528\u4e86\u3002 \u90a3\u4e2a\u5faa\u73af\u4e0d\u592a\u53ef\u63a7\u2014\u2014\u4e0d\u597d\u4eba\u5de5\u5e72\u9884\u3001\u4e0d\u597d\u65ad\u70b9\u3001\u72b6\u6001\u5bb9\u6613\u4e71\u3002\u751f\u4ea7\u73af\u5883\u66f4\u63a8\u8350\u628a\u63a7\u5236\u6d41\u663e\u5f0f\u753b\u51fa\u6765\u3002<\/li>\n<h3>\u56db\u3001\u628a\u73af\u5883\u8dd1\u8d77\u6765<\/h3>\n<p>\u5148\u51c6\u5907\u4e00\u4e2a\u5e72\u51c0\u7684 Python \u73af\u5883&#xff0c;\u907f\u514d\u6c61\u67d3\u4f60\u7535\u8111\u4e0a\u5df2\u6709\u7684\u5305\u3002\u672c\u6587\u5bf9\u5e94 langgraph 1.0.5\u3001Python 3.12\u3002<\/p>\n<p># 1. \u521b\u5efa\u5e76\u6fc0\u6d3b\u865a\u62df\u73af\u5883&#xff08;\u540d\u5b57\u968f\u4fbf\u8d77&#xff09;<br \/>\nconda create &#8211;name&#061;langgraph_venv python&#061;3.12<br \/>\nconda activate langgraph_venv<\/p>\n<p># 2. \u5b89\u88c5 langgraph<br \/>\npip install langgraph&#061;&#061;1.0.5<\/p>\n<p># 3. \u786e\u8ba4\u88c5\u4e0a\u4e86<br \/>\npip show langgraph<\/p>\n<p>\u5982\u679c\u4f60\u8fd8\u60f3\u628a\u56fe\u7ed3\u6784\u6253\u5370\u6210 ASCII \u56fe\u770b&#xff0c;\u518d\u88c5\u4e00\u4e2a\u5c0f\u4f9d\u8d56&#xff1a;<\/p>\n<p>pip install grandalf<\/p>\n<h3>\u4e94\u3001\u5feb\u901f\u5165\u95e8&#xff1a;20 \u884c\u4ee3\u7801\u8dd1\u901a\u7b2c\u4e00\u4e2a\u56fe<\/h3>\n<h4>5.1 \u8bb0\u4f4f\u8fd9\u4e94\u6b65&#xff0c;\u6240\u6709 LangGraph \u4ee3\u7801\u90fd\u662f\u8fd9\u4e2a\u5957\u8def<\/h4>\n<li>\u5b9a\u4e49\u72b6\u6001&#xff08;State&#xff09;&#xff1a;\u8bf4\u6e05\u695a\u8fd9\u672c&#034;\u5171\u4eab\u8bb0\u4e8b\u672c&#034;\u4e0a\u6709\u54ea\u4e9b\u5b57\u6bb5&#xff1b;<\/li>\n<li>\u5b9a\u4e49\u8282\u70b9\u51fd\u6570&#xff08;Node&#xff09;&#xff1a;\u6bcf\u4e2a\u51fd\u6570\u63a5\u6536 state&#xff0c;\u8fd4\u56de&#034;\u8981\u6539\u54ea\u4e9b\u5b57\u6bb5&#034;&#xff1b;<\/li>\n<li>\u521b\u5efa builder&#xff1a;\u7528\u72b6\u6001\u521b\u5efa StateGraph \u5b9e\u4f8b&#xff0c;\u628a\u8282\u70b9\u548c\u8fb9\u52a0\u8fdb\u53bb&#xff1b;<\/li>\n<li>\u7f16\u8bd1&#xff08;compile&#xff09;&#xff1a;\u628a\u56fe\u7eb8\u53d8\u6210\u53ef\u6267\u884c\u5bf9\u8c61&#xff1b;<\/li>\n<li>\u8c03\u7528&#xff08;invoke&#xff09;&#xff1a;\u4f20\u521d\u59cb\u72b6\u6001&#xff0c;\u62ff\u6700\u7ec8\u7ed3\u679c\u3002<\/li>\n<p>\u4e0b\u9762\u8fd9\u4e2a\u4f8b\u5b50\u505a\u4e00\u4e2a&#034;RAG &#043; \u8054\u7f51\u641c\u7d22&#034;\u7684\u95ee\u7b54\u7cfb\u7edf&#xff1a;\u6536\u5230\u95ee\u9898\u540e&#xff0c;\u540c\u65f6\u53bb\u77e5\u8bc6\u5e93\u68c0\u7d22\u3001\u53bb\u7f51\u4e0a\u641c\u7d22&#xff0c;\u4e24\u8def\u7ed3\u679c\u90fd\u56de\u6765\u4e4b\u540e&#xff0c;\u518d\u4ea4\u7ed9\u5927\u6a21\u578b\u603b\u7ed3\u6210\u4e00\u53e5\u8bdd\u56de\u7b54\u3002<\/p>\n<p>\u6ce8\u610f\u8fd9\u91cc\u7684&#034;\u540c\u65f6&#034;\u2014\u2014\u8fd9\u5c31\u662f\u56fe\u7684\u529b\u91cf&#xff0c;\u4e24\u6761\u8fb9\u4ece START \u4e00\u8d77\u51fa\u53d1&#xff0c;\u5929\u7136\u5e76\u884c\u3002<\/p>\n<h4>5.2 \u5b8c\u6574\u4ee3\u7801<\/h4>\n<p>from typing import TypedDict<\/p>\n<p>from pydantic import BaseModel<br \/>\nfrom langgraph.constants import START, END<br \/>\nfrom langgraph.graph import StateGraph<br \/>\nfrom langgraph.types import Send, Command<\/p>\n<p># \u7b2c\u4e00\u6b65&#xff1a;\u5b9a\u4e49\u72b6\u6001&#xff08;\u5171\u4eab\u8bb0\u4e8b\u672c\u4e0a\u8981\u8bb0\u54ea\u4e9b\u4e1c\u897f&#xff09;<br \/>\nclass MyState(TypedDict):<br \/>\n    rag_result: str          # \u77e5\u8bc6\u5e93\u68c0\u7d22\u7ed3\u679c<br \/>\n    web_search_result: str   # \u8054\u7f51\u641c\u7d22\u7ed3\u679c<br \/>\n    query: str               # \u7528\u6237\u95ee\u9898<br \/>\n    final_answer: str        # \u6700\u7ec8\u56de\u7b54<\/p>\n<p># \u7b2c\u4e09\u6b65\u7684\u51c6\u5907&#xff1a;\u7528\u72b6\u6001\u521b\u5efa builder<br \/>\ngraph &#061; StateGraph(state_schema&#061;MyState)<\/p>\n<p># \u7b2c\u4e8c\u6b65&#xff1a;\u5b9a\u4e49\u8282\u70b9\u51fd\u6570<br \/>\ndef rag_search_node(state: MyState):<br \/>\n    query &#061; state[&#034;query&#034;]<br \/>\n    rag_result &#061; f&#034;\u5173\u4e8e{query}\u7684rag_result&#034;<br \/>\n    return {&#034;rag_result&#034;: rag_result}      # \u53ea\u8fd4\u56de\u81ea\u5df1\u66f4\u65b0\u7684\u5b57\u6bb5<\/p>\n<p>def web_search_node(state: MyState):<br \/>\n    query &#061; state[&#034;query&#034;]<br \/>\n    web_search_result &#061; f&#034;\u5173\u4e8e{query}\u7684web_search_result&#034;<br \/>\n    return {&#034;web_search_result&#034;: web_search_result}<\/p>\n<p>def final_answer_node(state: MyState):<br \/>\n    rag_result &#061; state[&#034;rag_result&#034;]<br \/>\n    web_search_result &#061; state[&#034;web_search_result&#034;]<br \/>\n    final_answer &#061; f&#034;LLM\u57fa\u4e8e{rag_result}\u548c{web_search_result}\u7684\u6700\u7ec8\u56de\u590d&#034;<br \/>\n    return {&#034;final_answer&#034;: final_answer}<\/p>\n<p># \u6ce8\u518c\u8282\u70b9<br \/>\ngraph.add_node(rag_search_node)<br \/>\ngraph.add_node(web_search_node)<br \/>\ngraph.add_node(final_answer_node)<\/p>\n<p># \u8fde\u8fb9&#xff1a;START \u540c\u65f6\u6307\u5411\u4e24\u4e2a\u68c0\u7d22\u8282\u70b9 &#061;&gt; \u5e76\u884c<br \/>\ngraph.add_edge(START, &#034;rag_search_node&#034;)<br \/>\ngraph.add_edge(START, &#034;web_search_node&#034;)<br \/>\n# \u4e24\u8def\u90fd\u6c47\u5408\u5230\u603b\u7ed3\u8282\u70b9 &#061;&gt; \u7b49\u4e24\u8def\u90fd\u5b8c\u6210\u624d\u6267\u884c<br \/>\ngraph.add_edge(&#034;rag_search_node&#034;, &#034;final_answer_node&#034;)<br \/>\ngraph.add_edge(&#034;web_search_node&#034;, &#034;final_answer_node&#034;)<br \/>\ngraph.add_edge(&#034;final_answer_node&#034;, END)<\/p>\n<p># \u7b2c\u56db\u6b65&#xff1a;\u7f16\u8bd1<br \/>\ncompiled_graph &#061; graph.compile()<\/p>\n<p># \u7b2c\u4e94\u6b65&#xff1a;\u8c03\u7528<br \/>\nres &#061; compiled_graph.invoke({&#034;query&#034;: &#034;\u5982\u4f55\u4f7f\u7528LangGraph&#034;})<br \/>\nprint(res)<\/p>\n<h4>5.3 \u9010\u884c\u62c6\u89e3\u51e0\u4e2a\u5173\u952e\u70b9<\/h4>\n<ul>\n<li>class MyState(TypedDict)&#xff1a;\u8fd9\u4e0d\u662f\u666e\u901a\u7c7b&#xff0c;\u662f\u7528\u7c7b\u578b\u6ce8\u89e3\u63cf\u8ff0\u5b57\u5178\u7ed3\u6784\u7684&#034;\u534f\u8bae&#034;\u3002\u5b83\u544a\u8bc9 LangGraph&#xff1a;\u8fd9\u672c\u8bb0\u4e8b\u672c\u4e0a\u6709 4 \u4e2a\u5b57\u6bb5&#xff0c;\u5404\u81ea\u662f\u4ec0\u4e48\u7c7b\u578b\u3002<\/li>\n<li>graph &#061; StateGraph(state_schema&#061;MyState)&#xff1a;\u628a\u534f\u8bae\u4ea4\u7ed9\u56fe&#xff0c;\u56fe\u4ece\u6b64\u77e5\u9053\u81ea\u5df1\u7684\u5b8c\u6574\u72b6\u6001\u7a7a\u95f4\u3002<\/li>\n<li>\u8282\u70b9\u51fd\u6570\u8fd4\u56de\u7684\u662f\u5b57\u5178&#xff0c;\u4e0d\u662f\u6574\u4e2a state\u3002\u8fd9\u4e00\u70b9\u6781\u5176\u91cd\u8981&#xff0c;\u540e\u9762\u7b2c\u5341\u8282\u4f1a\u4e13\u95e8\u8bb2\u9519\u8bef\u793a\u8303\u3002<\/li>\n<li>START \u548c END \u662f\u4e24\u4e2a\u7279\u6b8a\u5b57\u7b26\u4e32\u5e38\u91cf&#xff0c;\u5206\u522b\u4ee3\u8868&#034;\u56fe\u5f00\u59cb&#034;\u548c&#034;\u56fe\u7ed3\u675f&#034;&#xff0c;\u7528\u5b83\u4eec\u6765\u6807\u8bb0\u5165\u53e3\u548c\u51fa\u53e3\u3002<\/li>\n<li>.compile() \u662f\u5fc5\u987b\u7684\u4e00\u6b65&#xff0c;\u7f16\u8bd1\u4e4b\u540e\u624d\u80fd invoke&#xff1b;\u7f16\u8bd1\u65f6\u8fd8\u53ef\u4ee5\u987a\u4fbf\u6302\u4e0a\u68c0\u67e5\u70b9\u3001\u7f13\u5b58\u7b49\u80fd\u529b\u3002<\/li>\n<\/ul>\n<h4>5.4 \u628a\u56fe&#034;\u753b&#034;\u51fa\u6765\u770b\u4e00\u773c<\/h4>\n<p>\u5149\u770b\u4ee3\u7801\u6ca1\u611f\u89c9&#xff1f;\u7f16\u8bd1\u540e\u7684\u5bf9\u8c61\u53ef\u4ee5\u5bfc\u51fa\u56fe\u7ed3\u6784&#xff0c;\u76f4\u63a5\u6253\u5370\u6210 ASCII \u56fe&#xff1a;<\/p>\n<p># \u9700\u8981\u5148 pip install grandalf<br \/>\ngraph_structure &#061; compiled_graph.get_graph()<br \/>\nprint(graph_structure.draw_ascii())<\/p>\n<p>\u4f60\u4f1a\u770b\u5230\u4e00\u5f20\u6e05\u695a\u7684&#034;\u4e24\u8def\u5e76\u884c\u518d\u6c47\u5408&#034;\u7684\u56fe\u3002\u8fd9\u79cd\u53ef\u89c6\u5316\u5728\u8c03\u8bd5\u590d\u6742\u5de5\u4f5c\u6d41\u65f6\u975e\u5e38\u6709\u7528\u2014\u2014\u4f60\u753b\u7684\u56fe\u548c\u4f60\u8111\u5b50\u91cc\u60f3\u7684\u56fe\u662f\u5426\u4e00\u81f4&#xff0c;\u4e00\u773c\u5c31\u80fd\u770b\u51fa\u6765\u3002<\/p>\n<h3>\u516d\u3001State&#xff1a;\u6574\u4e2a\u5e94\u7528\u7684\u6570\u636e\u4e2d\u67a2<\/h3>\n<p>\u7528 LangGraph \u5efa\u5e94\u7528&#xff0c;\u7b2c\u4e00\u6b65\u6c38\u8fdc\u662f\u5b9a\u4e49 State\u3002\u56e0\u4e3a State \u51b3\u5b9a\u4e86&#034;\u8fd9\u5f20\u56fe\u7684\u4ea7\u51fa\u76ee\u6807\u662f\u4ec0\u4e48&#034;&#xff0c;\u4e5f\u51b3\u5b9a\u4e86&#034;\u6bcf\u4e2a\u8282\u70b9\u53ef\u4ee5\u6539\u54ea\u4e9b\u6570\u636e&#034;\u3002<\/p>\n<h4>6.1 \u5b9a\u4e49\u72b6\u6001\u7684\u4e09\u79cd\u5199\u6cd5<\/h4>\n<p>State \u7684 schema \u6709\u4e09\u79cd\u5b9a\u4e49\u65b9\u5f0f&#xff0c;\u590d\u6742\u5ea6\u9012\u589e&#xff0c;\u6309\u9700\u9009\u62e9&#xff0c;\u522b\u8fc7\u5ea6\u8bbe\u8ba1\u3002<\/p>\n<p>\u5199\u6cd5\u4e00&#xff1a;TypedDict&#xff08;\u63a8\u8350&#xff0c;\u6700\u7b80\u5355&#xff09;<\/p>\n<p>TypedDict \u662f Python \u81ea\u5e26\u7684\u7c7b\u578b\u63d0\u793a\u5de5\u5177&#xff0c;\u7528\u6765\u7ed9\u5b57\u5178\u7684\u952e\u548c\u503c\u6307\u5b9a\u7cbe\u786e\u7c7b\u578b\u3002\u96f6\u4f9d\u8d56\u3001\u5199\u8d77\u6765\u6700\u77ed\u3002<\/p>\n<p>from typing import TypedDict<\/p>\n<p>class MyStateFull(TypedDict):<br \/>\n    rag_result: str<br \/>\n    web_search_result: str<br \/>\n    final_answer: str<br \/>\n    query: str<br \/>\n    a_new_key: str<\/p>\n<p>\u5199\u6cd5\u4e8c&#xff1a;Pydantic BaseModel&#xff08;\u5e26\u8fd0\u884c\u65f6\u6821\u9a8c&#xff09;<\/p>\n<p>Pydantic \u4f1a\u5728\u8fd0\u884c\u65f6\u68c0\u67e5\u6570\u636e\u7c7b\u578b\u5bf9\u4e0d\u5bf9&#xff0c;\u5b57\u6bb5\u8fd8\u80fd\u5e26\u9ed8\u8ba4\u503c\u548c\u8bf4\u660e\u6587\u6863&#xff0c;IDE \u63d0\u793a\u4e5f\u66f4\u53cb\u597d\u3002\u9879\u76ee\u91cc\u6700\u5e38\u7528\u3002<\/p>\n<p>from pydantic import BaseModel<\/p>\n<p>class MyStateFull(BaseModel):<br \/>\n    rag_result: str<br \/>\n    web_search_result: str<br \/>\n    final_answer: str<br \/>\n    query: str<br \/>\n    a_new_key: str<\/p>\n<p>\u5199\u6cd5\u4e09&#xff1a;dataclass&#xff08;\u6807\u51c6\u5e93\u98ce\u683c&#xff09;<\/p>\n<p>dataclass \u662f Python \u6807\u51c6\u5e93\u7684\u88c5\u9970\u5668&#xff0c;\u4f1a\u81ea\u52a8\u5e2e\u4f60\u751f\u6210 __init__\u3001__repr__\u3001__eq__ \u7b49\u65b9\u6cd5&#xff0c;\u9002\u5408\u5f53\u7eaf\u6570\u636e\u5bb9\u5668\u7528\u3002<\/p>\n<p>from dataclasses import dataclass<\/p>\n<p>&#064;dataclass<br \/>\nclass MyStateFullTwo:<br \/>\n    rag_result: str<br \/>\n    web_search_result: str<br \/>\n    final_answer: str<br \/>\n    query: str<br \/>\n    a_new_key: str<\/p>\n<h4>6.2 \u8f93\u5165\u8f93\u51fa\u6570\u636e\u9694\u79bb&#xff1a;\u4e09\u4e2a schema<\/h4>\n<p>\u8fd9\u662f\u5f88\u591a\u65b0\u624b\u4f1a\u5ffd\u7565\u3001\u4f46\u505a\u4f01\u4e1a\u9879\u76ee\u65f6\u5fc5\u987b\u4f1a\u7684\u6280\u5de7&#xff1a;\u4f60\u53ef\u4ee5\u7cbe\u786e\u63a7\u5236&#034;\u5916\u9762\u80fd\u4f20\u8fdb\u6765\u4ec0\u4e48&#034;\u548c&#034;\u6700\u540e\u80fd\u62ff\u5230\u4ec0\u4e48&#034;\u3002<\/p>\n<p>\u505a\u6cd5\u662f\u5728\u521d\u59cb\u5316 StateGraph \u65f6\u4f20\u4e09\u4e2a\u53c2\u6570&#xff1a;<\/p>\n<table>\n<tr>\u53c2\u6570\u4f5c\u7528\u662f\u5426\u5fc5\u586b\u8bf4\u660e<\/tr>\n<tbody>\n<tr>\n<td>state_schema<\/td>\n<td>\u56fe\u7684\u5b8c\u6574\u5185\u90e8\u72b6\u6001<\/td>\n<td>\u5fc5\u586b&#xff0c;\u4e0d\u80fd\u4e3a\u7a7a<\/td>\n<td>\u6240\u6709\u8282\u70b9\u80fd\u8bfb\u5199\u7684\u5168\u90e8\u5b57\u6bb5&#xff0c;\u662f&#034;\u5168\u5c40\u72b6\u6001\u7a7a\u95f4&#034;<\/td>\n<\/tr>\n<tr>\n<td>input_schema<\/td>\n<td>\u56fe\u63a5\u53d7\u4ec0\u4e48\u8f93\u5165<\/td>\n<td>\u53ef\u9009&#xff0c;\u9ed8\u8ba4\u7b49\u4e8e state_schema<\/td>\n<td>\u9650\u5236\u5165\u53e3\u53ea\u80fd\u4f20\u8fd9\u4e9b\u5b57\u6bb5&#xff0c;\u662f state_schema \u7684\u5b50\u96c6<\/td>\n<\/tr>\n<tr>\n<td>output_schema<\/td>\n<td>\u56fe\u8fd4\u56de\u4ec0\u4e48\u8f93\u51fa<\/td>\n<td>\u53ef\u9009&#xff0c;\u9ed8\u8ba4\u7b49\u4e8e state_schema<\/td>\n<td>\u9650\u5236\u51fa\u53e3\u53ea\u8fd4\u56de\u8fd9\u4e9b\u5b57\u6bb5&#xff0c;\u662f state_schema \u7684\u5b50\u96c6<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u4e3a\u4ec0\u4e48\u8981\u8fd9\u4e48\u8bbe\u8ba1&#xff1f;\u6253\u4e2a\u6bd4\u65b9&#xff1a;\u53a8\u623f\u5185\u90e8\u53ef\u80fd\u6709\u4e09\u5341\u79cd\u8c03\u6599&#xff08;state_schema&#xff09;&#xff0c;\u4f46\u987e\u5ba2\u70b9\u5355\u65f6\u53ea\u9700\u8981\u8bf4&#034;\u8981\u4e00\u4efd\u756a\u8304\u7092\u86cb&#034;&#xff08;input_schema&#xff09;&#xff0c;\u7aef\u4e0a\u684c\u65f6\u4e5f\u53ea\u9700\u8981\u90a3\u76d8\u83dc&#xff08;output_schema&#xff09;\u3002\u4e2d\u95f4\u8fc7\u7a0b\u5bf9\u8c03\u7528\u65b9\u4e0d\u53ef\u89c1&#xff0c;\u63a5\u53e3\u5c31\u5e72\u51c0\u4e86\u3002<\/p>\n<p>from typing import TypedDict<br \/>\nfrom langgraph.constants import START, END<br \/>\nfrom langgraph.graph import StateGraph<\/p>\n<p>class MyStateFull(TypedDict):<br \/>\n    rag_result: str<br \/>\n    web_search_result: str<br \/>\n    final_answer: str<br \/>\n    query: str<br \/>\n    a_new_key: str<\/p>\n<p>class InputSchema(TypedDict):<br \/>\n    query: str            # \u53ea\u5141\u8bb8\u5916\u90e8\u4f20 query<\/p>\n<p>class OutputSchema(TypedDict):<br \/>\n    final_answer: str     # \u53ea\u628a final_answer \u4ea4\u51fa\u53bb<\/p>\n<p>graph &#061; StateGraph(<br \/>\n    state_schema&#061;MyStateFull,<br \/>\n    input_schema&#061;InputSchema,<br \/>\n    output_schema&#061;OutputSchema,<br \/>\n)<\/p>\n<p>def rag_search_node(state: MyStateFull):<br \/>\n    print(state)<br \/>\n    query &#061; state[&#034;query&#034;]<br \/>\n    rag_result &#061; f&#034;\u5173\u4e8e{query}\u7684rag_result&#034;<br \/>\n    return {&#034;rag_result&#034;: rag_result, &#034;a_new_key&#034;: &#034;a_new_key_value&#034;}<\/p>\n<p>def web_search_node(state: MyStateFull):<br \/>\n    print(state)<br \/>\n    query &#061; state[&#034;query&#034;]<br \/>\n    web_search_result &#061; f&#034;\u5173\u4e8e{query}\u7684web_search_result&#034;<br \/>\n    return {&#034;web_search_result&#034;: web_search_result}<\/p>\n<p>def final_answer_node(state: MyStateFull):<br \/>\n    print(&#034;\u5728final_answer_node\u5f53\u4e2d\u7684state&#034;, state)<br \/>\n    rag_result &#061; state[&#034;rag_result&#034;]<br \/>\n    web_search_result &#061; state[&#034;web_search_result&#034;]<br \/>\n    final_answer &#061; f&#034;LLM\u57fa\u4e8e{rag_result}\u548c{web_search_result}\u7684\u6700\u7ec8\u56de\u590d&#034;<br \/>\n    return {&#034;final_answer&#034;: final_answer}<\/p>\n<p>graph.add_node(rag_search_node)<br \/>\ngraph.add_node(web_search_node)<br \/>\ngraph.add_node(final_answer_node)<\/p>\n<p>graph.add_edge(START, &#034;rag_search_node&#034;)<br \/>\ngraph.add_edge(START, &#034;web_search_node&#034;)<br \/>\ngraph.add_edge(&#034;rag_search_node&#034;, &#034;final_answer_node&#034;)<br \/>\ngraph.add_edge(&#034;web_search_node&#034;, &#034;final_answer_node&#034;)<br \/>\ngraph.add_edge(&#034;final_answer_node&#034;, END)<\/p>\n<p>compiled_graph &#061; graph.compile()<br \/>\nres &#061; compiled_graph.invoke({&#034;query&#034;: &#034;\u5982\u4f55\u4f7f\u7528LangGraph&#034;, &#034;a_new_key&#034;: &#034;a_new_key_value&#034;})<br \/>\nprint(&#034;\u6700\u7ec8\u7ed3\u679c\u4e3a&#034;, res)<\/p>\n<p>\u5b9e\u6218\u5c0f\u63d0\u793a&#xff1a;\u5982\u679c\u4f60\u5728 input_schema \u91cc\u6ca1\u6709\u58f0\u660e a_new_key&#xff0c;\u90a3\u4e48\u8c03\u7528\u65f6\u4f20\u5b83\u8fdb\u53bb\u662f\u4e0d\u751f\u6548\u7684&#xff08;\u4f1a\u88ab\u8fc7\u6ee4&#xff09;\u3002\u8fd9\u6b63\u597d\u53ef\u4ee5\u7528\u6765\u9632\u6b62\u8c03\u7528\u65b9\u4e71\u585e\u6570\u636e\u3002<\/p>\n<h4>6.3 \u8282\u70b9\u95f4\u6570\u636e\u9694\u79bb&#xff1a;\u6bcf\u4e2a\u8282\u70b9\u4e5f\u80fd\u6709\u81ea\u5df1\u7684&#034;\u79c1\u6709\u72b6\u6001&#034;<\/h4>\n<p>\u9664\u4e86\u56fe\u7ea7\u522b\u7684\u72b6\u6001&#xff0c;LangGraph \u8fd8\u5141\u8bb8\u67d0\u4e2a\u8282\u70b9\u53ea\u770b\u5230\u81ea\u5df1\u5173\u5fc3\u7684\u4e00\u90e8\u5206\u5b57\u6bb5\u3002\u505a\u6cd5\u662f\u7ed9\u8fd9\u4e2a\u8282\u70b9\u51fd\u6570\u6362\u4e2a state \u7c7b\u578b\u6ce8\u89e3&#xff1a;<\/p>\n<p>from typing import TypedDict<br \/>\nfrom langgraph.constants import START, END<br \/>\nfrom langgraph.graph import StateGraph<\/p>\n<p>class MyState(TypedDict):<br \/>\n    query: str<br \/>\n    final_answer: str<\/p>\n<p>class SearchState(TypedDict):<br \/>\n    rag_result: str<br \/>\n    web_search_result: str<\/p>\n<p>graph &#061; StateGraph(state_schema&#061;MyState)<\/p>\n<p>def rag_search_node(state: MyState):<br \/>\n    query &#061; state[&#034;query&#034;]<br \/>\n    return {&#034;rag_result&#034;: f&#034;\u5173\u4e8e{query}\u7684rag_result&#034;}<\/p>\n<p>def web_search_node(state: MyState):<br \/>\n    query &#061; state[&#034;query&#034;]<br \/>\n    return {&#034;web_search_result&#034;: f&#034;\u5173\u4e8e{query}\u7684web_search_result&#034;}<\/p>\n<p>def final_answer_node(state: SearchState):   # \u6ce8\u610f&#xff1a;\u8fd9\u4e2a\u8282\u70b9\u53ea\u5173\u5fc3\u68c0\u7d22\u7ed3\u679c<br \/>\n    print(&#034;\u5728final_answer_node\u5f53\u4e2d\u7684state&#034;, state)<br \/>\n    rag_result &#061; state[&#034;rag_result&#034;]<br \/>\n    web_search_result &#061; state[&#034;web_search_result&#034;]<br \/>\n    final_answer &#061; f&#034;LLM\u57fa\u4e8e{rag_result}&#xff0c;\u548c{web_search_result}\u7684\u6700\u7ec8\u56de\u590d&#034;<br \/>\n    return {&#034;final_answer&#034;: final_answer}<\/p>\n<p>graph.add_node(rag_search_node)<br \/>\ngraph.add_node(web_search_node)<br \/>\ngraph.add_node(final_answer_node)<\/p>\n<p>graph.add_edge(START, &#034;rag_search_node&#034;)<br \/>\ngraph.add_edge(START, &#034;web_search_node&#034;)<br \/>\ngraph.add_edge(&#034;rag_search_node&#034;, &#034;final_answer_node&#034;)<br \/>\ngraph.add_edge(&#034;web_search_node&#034;, &#034;final_answer_node&#034;)<br \/>\ngraph.add_edge(&#034;final_answer_node&#034;, END)<\/p>\n<p>compiled_graph &#061; graph.compile()<br \/>\nres &#061; compiled_graph.invoke({&#034;query&#034;: &#034;\u5982\u4f55\u4f7f\u7528LangGraph&#034;})<br \/>\nprint(&#034;\u6700\u7ec8\u7ed3\u679c\u4e3a&#034;, res)<\/p>\n<p>\u4e3a\u4ec0\u4e48\u6709\u7528&#xff1f; \u4e24\u4e2a\u597d\u5904&#xff1a;\u4e00\u662f\u8fd9\u4e2a\u8282\u70b9\u770b\u4e0d\u5230\u4e5f\u4e0d\u9700\u8981\u770b\u4e0d\u5230\u65e0\u5173\u6570\u636e&#xff0c;\u903b\u8f91\u66f4\u7eaf\u7cb9&#xff1b;\u4e8c\u662f\u5f53\u72b6\u6001\u5b57\u6bb5\u5f88\u591a&#xff08;\u51e0\u5341\u4e2a&#xff09;\u65f6&#xff0c;\u8282\u70b9\u53ea\u4f1a\u6536\u5230\u5b83\u58f0\u660e\u7684\u90a3\u51e0\u4e2a&#xff0c;\u80fd\u51cf\u5c11\u610f\u5916\u6539\u9519\u5b57\u6bb5\u7684\u98ce\u9669\u3002\u8fd9\u6709\u70b9\u50cf\u51fd\u6570\u53ea\u63a5\u6536\u81ea\u5df1\u9700\u8981\u7684\u53c2\u6570&#xff0c;\u800c\u4e0d\u662f\u628a\u6574\u4e2a\u5168\u5c40\u53d8\u91cf\u90fd\u585e\u8fdb\u53bb\u3002<\/p>\n<h4>6.4 Reducer&#xff1a;\u72b6\u6001\u5230\u5e95\u600e\u4e48&#034;\u5408\u5e76&#034;<\/h4>\n<p>\u8fd9\u662f LangGraph \u91cc\u6700\u5bb9\u6613\u8e29\u5751\u3001\u4e5f\u6700\u7cbe\u9ad3\u7684\u673a\u5236&#xff0c;\u8bf7\u52a1\u5fc5\u770b\u61c2\u3002<\/p>\n<p>\u524d\u9762\u53cd\u590d\u8bf4&#034;\u8282\u70b9\u8fd4\u56de\u7684\u53ea\u662f\u589e\u91cf&#034;\u3002\u90a3\u4e48\u95ee\u9898\u6765\u4e86&#xff1a;\u589e\u91cf\u62ff\u5230\u4e4b\u540e&#xff0c;\u600e\u4e48\u548c\u5168\u5c40\u72b6\u6001\u5408\u5e76&#xff1f; \u7b54\u6848\u5c31\u662f\u6bcf\u4e2a\u5b57\u6bb5\u90fd\u6709\u81ea\u5df1\u7684 Reducer&#xff08;\u5f52\u7ea6\u51fd\u6570&#xff09;\u3002<\/p>\n<p>Reducer \u5c31\u662f\u4e00\u4e2a\u51fd\u6570&#xff1a;\u63a5\u6536&#034;\u5de6\u8fb9\u7684\u65e7\u503c&#034;\u548c&#034;\u53f3\u8fb9\u7684\u589e\u91cf&#034;&#xff0c;\u8fd4\u56de\u5408\u5e76\u540e\u7684\u65b0\u503c\u3002<\/p>\n<p>\u60c5\u51b5\u4e00&#xff1a;\u4e0d\u5199 Reducer &#061; \u9ed8\u8ba4\u8986\u76d6<\/p>\n<p>\u8fd9\u662f\u9ed8\u8ba4\u884c\u4e3a\u3002\u65b0\u503c\u76f4\u63a5\u628a\u65e7\u503c\u76d6\u6389&#xff0c;\u5c31\u50cf\u7ed9\u53d8\u91cf\u91cd\u65b0\u8d4b\u503c\u3002<\/p>\n<p>from typing import List<br \/>\nfrom typing_extensions import TypedDict<br \/>\nfrom langgraph.graph import StateGraph, START, END<\/p>\n<p>class DefaultReducerState(TypedDict):<br \/>\n    foo: int<br \/>\n    bar: List[str]<\/p>\n<p>def node_default_1(state: DefaultReducerState) -&gt; dict:<br \/>\n    return {&#034;foo&#034;: 2}          # foo: 1 -&gt; 2<\/p>\n<p>def node_default_2(state: DefaultReducerState) -&gt; dict:<br \/>\n    return {&#034;bar&#034;: [&#034;bye&#034;]}    # bar: [&#034;hi&#034;] -&gt; [&#034;bye&#034;]&#xff0c;\u6ce8\u610f &#034;hi&#034; \u6ca1\u4e86&#xff01;<\/p>\n<p>builder &#061; StateGraph(DefaultReducerState)<br \/>\nbuilder.add_node(&#034;node1&#034;, node_default_1)<br \/>\nbuilder.add_node(&#034;node2&#034;, node_default_2)<br \/>\nbuilder.add_edge(START, &#034;node1&#034;)<br \/>\nbuilder.add_edge(&#034;node1&#034;, &#034;node2&#034;)<br \/>\nbuilder.add_edge(&#034;node2&#034;, END)<\/p>\n<p>graph &#061; builder.compile()<br \/>\nresult &#061; graph.invoke({&#034;foo&#034;: 1, &#034;bar&#034;: [&#034;hi&#034;]})<br \/>\nprint(f&#034;\u521d\u59cb\u72b6\u6001: {{&#039;foo&#039;: 1, &#039;bar&#039;: [&#039;hi&#039;]}}&#034;)<br \/>\nprint(f&#034;\u6267\u884c\u7ed3\u679c: {result}&#034;)<\/p>\n<p>\u8dd1\u4e00\u4e0b\u4f60\u4f1a\u53d1\u73b0&#xff0c;bar \u6700\u7ec8\u662f [&#034;bye&#034;]&#xff0c;\u539f\u6765\u7684 &#034;hi&#034; \u88ab\u8986\u76d6\u6389\u4e86\u3002\u5982\u679c\u4f60\u60f3\u8981\u7684\u662f&#034;\u8ffd\u52a0&#034;&#xff0c;\u5c31\u5fc5\u987b\u81ea\u5df1\u6307\u5b9a Reducer\u3002<\/p>\n<p>\u60c5\u51b5\u4e8c&#xff1a;\u81ea\u5b9a\u4e49 Reducer&#xff08;\u6700\u5e38\u7528&#xff1a;\u6d88\u606f\u8ffd\u52a0&#xff09;<\/p>\n<p>\u7528 Annotated[\u7c7b\u578b, \u51fd\u6570] \u7684\u8bed\u6cd5\u628a Reducer \u6302\u5230\u5b57\u6bb5\u4e0a\u3002\u4e0b\u9762\u8fd9\u4e2a add_message \u5c31\u662f\u628a\u65e7\u6d88\u606f\u5217\u8868\u548c\u65b0\u6d88\u606f\u5217\u8868\u62fc\u8d77\u6765&#xff1a;<\/p>\n<p>from typing import Annotated, TypedDict, List<br \/>\nfrom langgraph.graph import StateGraph<br \/>\nfrom langgraph.constants import START<br \/>\nfrom langchain_core.messages import ToolMessage, HumanMessage, AIMessage, BaseMessage<\/p>\n<p># \u81ea\u5b9a\u4e49 Reducer&#xff1a;\u5de6\u8fb9 &#043; \u53f3\u8fb9<br \/>\ndef add_message(message_list_left: list, message_list_right: list):<br \/>\n    print(&#034;&#061;&#034; * 20)<br \/>\n    print(&#034;\u6b63\u5728\u6267\u884cadd_message&#034;)<br \/>\n    print(&#034;\u5de6\u8fb9\u7684&#034;, message_list_left)<br \/>\n    print(&#034;\u53f3\u8fb9\u7684&#034;, message_list_right)<br \/>\n    print(&#034;&#061;&#034; * 20)<br \/>\n    return message_list_left &#043; message_list_right<\/p>\n<p>class MyAgent(TypedDict):<br \/>\n    # \u5173\u952e&#xff1a;\u7528 Annotated \u6302\u4e0a\u81ea\u5b9a\u4e49 reducer<br \/>\n    messages: Annotated[List[BaseMessage], add_message]<\/p>\n<p>def tool_node(state: MyAgent):<br \/>\n    return {&#034;messages&#034;: [ToolMessage(content&#061;&#034;\u6765\u81eatool_node\u7684\u5185\u5bb9&#034;, tool_call_id&#061;&#034;xxx&#034;)]}<\/p>\n<p>def llm_node(state: MyAgent):<br \/>\n    return {&#034;messages&#034;: [AIMessage(content&#061;&#034;\u6765\u81eallm_node\u7684\u5185\u5bb9&#034;)]}<\/p>\n<p>builder &#061; StateGraph(state_schema&#061;MyAgent)<br \/>\nbuilder.add_node(tool_node)<br \/>\nbuilder.add_node(llm_node)<br \/>\nbuilder.add_edge(START, &#034;tool_node&#034;)<br \/>\nbuilder.add_edge(&#034;tool_node&#034;, &#034;llm_node&#034;)<\/p>\n<p>graph &#061; builder.compile()<br \/>\ngraph.invoke({&#034;messages&#034;: [HumanMessage(content&#061;&#034;\u4f60\u597d&#034;)]})<\/p>\n<p>\u8dd1\u5b8c\u4f60\u4f1a\u770b\u5230 messages \u91cc\u4f9d\u6b21\u662f&#xff1a;\u7528\u6237\u8bf4\u7684&#034;\u4f60\u597d&#034; \u2192 \u5de5\u5177\u7684\u8fd4\u56de \u2192 \u6a21\u578b\u7684\u56de\u590d\u3002\u4e09\u6761\u90fd\u5728&#xff0c;\u4e00\u6761\u6ca1\u4e22\u3002\u8fd9\u4e5f\u662f\u4e3a\u4ec0\u4e48\u5bf9\u8bdd\u7c7b\u5e94\u7528\u51e0\u4e4e\u90fd\u7528\u8ffd\u52a0\u578b Reducer\u2014\u2014\u804a\u5929\u8bb0\u5f55\u5fc5\u987b\u662f\u7d2f\u52a0\u7684&#xff0c;\u4e0d\u80fd\u4e92\u76f8\u8986\u76d6\u3002<\/p>\n<p>\u60c5\u51b5\u4e09&#xff1a;\u4f7f\u7528\u5185\u7f6e Reducer<\/p>\n<p>LangGraph \u5df2\u7ecf\u5185\u7f6e\u4e86\u4e00\u4e9b\u5e38\u7528 Reducer&#xff0c;\u6bd4\u5982 langgraph.graph.messages \u91cc\u7684 add_messages&#xff0c;\u4ee5\u53ca\u505a\u5217\u8868\u76f8\u52a0\u7684 operator.add\u3002\u540e\u8005\u5728\u5e76\u884c\u573a\u666f\u7279\u522b\u597d\u7528&#xff1a;<\/p>\n<p>import operator<br \/>\nfrom typing import Annotated<br \/>\nfrom typing_extensions import TypedDict<\/p>\n<p>class State(TypedDict):<br \/>\n    aggregate: Annotated[list, operator.add]   # \u591a\u4e2a\u8282\u70b9\u540c\u65f6\u5199&#xff0c;\u7ed3\u679c\u4f1a\u62fc\u63a5\u8d77\u6765<\/p>\n<p>\u6ce8\u610f&#xff1a;\u5f53\u4e00\u4e2a\u5b57\u6bb5\u6709\u591a\u4e2a\u5e76\u884c\u8282\u70b9\u540c\u65f6\u5199&#xff0c;\u53c8\u6ca1\u6709\u914d\u7f6e Reducer \u65f6&#xff0c;LangGraph \u4f1a\u56e0\u4e3a&#034;\u4e0d\u77e5\u9053\u8be5\u4ee5\u8c01\u4e3a\u51c6&#034;\u800c\u62a5\u9519\u3002\u8fd9\u662f\u65b0\u624b\u6700\u5e38\u89c1\u7684\u62a5\u9519\u6765\u6e90\u4e4b\u4e00&#xff0c;\u770b\u5230 InvalidUpdateError \u4e4b\u7c7b\u7684\u63d0\u793a&#xff0c;\u5148\u68c0\u67e5\u662f\u4e0d\u662f\u5e76\u884c\u7684\u8282\u70b9\u5199\u4e86\u540c\u4e00\u4e2a\u952e\u5374\u6ca1\u914d Reducer\u3002<\/p>\n<h3>\u4e03\u3001\u72b6\u6001\u5b58\u50a8&#xff1a;Checkpointer \u4e0e thread_id<\/h3>\n<h4>7.1 \u5148\u8bf4\u4e24\u4e2a\u771f\u5b9e\u573a\u666f&#xff0c;\u4f60\u5c31\u77e5\u9053\u4e3a\u4ec0\u4e48\u9700\u8981\u5b83<\/h4>\n<p>\u5728\u524d\u9762\u6240\u6709\u4f8b\u5b50\u91cc&#xff0c;\u6bcf\u6b21 invoke&#xff0c;LangGraph \u90fd\u4f1a\u521d\u59cb\u5316\u4e00\u4e2a\u7a7a\u72b6\u6001&#xff0c;\u7136\u540e\u628a\u4f60\u7684\u521d\u59cb\u72b6\u6001\u5408\u8fdb\u53bb&#xff0c;\u8dd1\u5b8c\u5c31\u4e22\u3002\u7b80\u5355\u4efb\u52a1\u6ca1\u95ee\u9898&#xff0c;\u4f46\u9047\u5230\u4e0b\u9762\u4e24\u79cd\u60c5\u51b5\u5c31\u5e9f\u4e86\u3002<\/p>\n<p>\u573a\u666f\u4e00&#xff1a;\u540c\u4e00\u4e2a\u4f1a\u8bdd\u91cc\u8981\u8bb0\u4f4f\u4e0a\u4e00\u8f6e<\/p>\n<p>\u7528\u6237\u7b2c\u4e00\u53e5\u8bf4&#034;\u5e2e\u6211\u67e5\u4e00\u4e0b\u5317\u4eac\u660e\u5929\u5929\u6c14&#034;&#xff0c;\u7b2c\u4e8c\u53e5\u95ee&#034;\u9002\u5408\u51fa\u53bb\u73a9\u5417&#034;\u3002\u7b2c\u4e8c\u6b21\u8c03\u7528\u65f6&#xff0c;\u72b6\u6001\u88ab\u91cd\u7f6e&#xff0c;messages \u662f\u7a7a\u7684&#xff0c;\u6a21\u578b\u6839\u672c\u4e0d\u77e5\u9053&#034;\u5b83&#034;\u6307\u4ec0\u4e48\u2014\u2014\u4e0a\u4e0b\u6587\u65ad\u4e86\u3002<\/p>\n<p>\u573a\u666f\u4e8c&#xff1a;\u8dd1\u5230\u4e00\u534a\u62a5\u9519\u4e86&#xff0c;\u4e0d\u60f3\u4ece\u5934\u518d\u6765<\/p>\n<p>\u5047\u8bbe Node2 \u56e0\u4e3a\u67d0\u4e2a bug \u629b\u5f02\u5e38\u3002\u4f60\u4fee\u597d\u4ee3\u7801\u540e\u60f3&#034;\u4ece Node2 \u7ee7\u7eed&#034;&#xff0c;\u4f46\u5185\u5b58\u91cc\u7684\u72b6\u6001\u5df2\u7ecf\u968f\u8fdb\u7a0b\u9000\u51fa\u6d88\u5931\u4e86&#xff0c;Node1 \u7684\u7ed3\u679c\u5f97\u91cd\u65b0\u7b97\u4e00\u904d\u3002\u5982\u679c Node1 \u521a\u521a\u82b1\u4e86\u4e24\u6bdb\u94b1\u8c03\u7528\u5927\u6a21\u578b&#xff0c;\u4f60\u4f1a\u5f88\u5fc3\u75bc\u3002<\/p>\n<h4>7.2 \u89e3\u51b3\u65b9\u6848&#xff1a;Checkpointer &#043; thread_id<\/h4>\n<p>\u601d\u8def\u5f88\u6734\u7d20&#xff1a;\u628a\u6bcf\u4e00\u6b65\u6267\u884c\u5b8c\u7684\u72b6\u6001\u5b58\u8d77\u6765&#xff0c;\u4e0b\u6b21\u7528\u7684\u65f6\u5019\u6309 id \u53d6\u56de\u6765&#xff0c;\u800c\u4e0d\u662f\u8ba9 LangGraph \u6bcf\u6b21\u90fd\u4ece\u7a7a\u767d\u5f00\u59cb\u3002<\/p>\n<p>LangGraph \u63d0\u4f9b\u7684\u5b58\u50a8\u673a\u5236\u53eb Checkpointer&#xff08;\u68c0\u67e5\u70b9&#xff09;&#xff0c;\u76f8\u5173\u7684\u7c7b\u90fd\u5728 langgraph.checkpointer \u5305\u4e0b&#xff0c;\u53ef\u4ee5\u5b58\u5230\u5185\u5b58\u3001SQLite\u3001Postgres \u7b49\u5730\u65b9\u3002<\/p>\n<p>\u540c\u65f6&#xff0c;\u56e0\u4e3a\u4e00\u4e2a\u5e94\u7528\u53ef\u80fd\u540c\u65f6\u670d\u52a1\u5f88\u591a\u7528\u6237\u3001\u6bcf\u4e2a\u7528\u6237\u53c8\u6709\u5f88\u591a\u4f1a\u8bdd&#xff0c;\u6240\u4ee5\u9700\u8981\u7ed9\u72b6\u6001\u6253\u4e2a&#034;\u7f16\u53f7&#034;\u6765\u9694\u79bb\u3002\u8fd9\u4e2a\u7f16\u53f7\u5c31\u662f thread_id\u3002<\/p>\n<p>\u5212\u91cd\u70b9&#xff1a;thread_id \u548c\u7f16\u7a0b\u91cc\u7684&#034;\u7ebf\u7a0b&#034;\u6ca1\u6709\u534a\u70b9\u5173\u7cfb&#xff01; \u5b83\u53ea\u662f\u4e00\u4e2a\u7528\u6765\u9694\u79bb\u72b6\u6001\u7a7a\u95f4\u7684\u5b57\u7b26\u4e32&#xff0c;\u4f60\u53ef\u4ee5\u628a\u5b83\u7406\u89e3\u6210&#034;\u4f1a\u8bdd\u7f16\u53f7&#034;\u3002\u53eb\u5f20\u4e09\u7684\u7f16\u53f7 user_1_session_1&#xff0c;\u53eb\u674e\u56db\u7684\u7f16\u53f7 user_2_session_1&#xff0c;\u4e24\u4eba\u7684\u8bb0\u5fc6\u4e92\u4e0d\u5e72\u6270\u3002<\/p>\n<p>\u7f16\u7801\u4e0a\u5c31\u4e09\u6b65&#xff1a;<\/p>\n<li>\u521b\u5efa checkpointer \u5b9e\u4f8b&#xff1b;<\/li>\n<li>\u7f16\u8bd1\u56fe\u65f6\u628a checkpointer \u4f20\u8fdb\u53bb&#xff1b;<\/li>\n<li>\u8c03\u7528\u65f6\u5728 config \u91cc\u4f20 thread_id\u3002\u60f3\u8981\u5ef6\u7eed\u4e0a\u4e0b\u6587\u5c31\u4f20\u540c\u4e00\u4e2a id&#xff0c;\u60f3\u5f00\u65b0\u4f1a\u8bdd\u5c31\u6362\u4e00\u4e2a\u65b0 id\u3002<\/li>\n<h4>7.3 \u5b9e\u6218\u4e00&#xff1a;\u7528 InMemorySaver \u505a&#034;\u77ed\u671f\u8bb0\u5fc6&#034;<\/h4>\n<p>\u4e0b\u9762\u8fd9\u6bb5\u4ee3\u7801\u7528 create_agent \u6f14\u793a&#xff08;\u5b83\u5e95\u5c42\u4e5f\u662f LangGraph \u56fe&#xff09;&#xff0c;\u91cd\u70b9\u662f\u770b\u6ce8\u91ca\u91cc\u6807\u4e86\u5e8f\u53f7\u7684\u56db\u6b65&#xff1a;<\/p>\n<p>def scenario_1_demo():<br \/>\n    from langchain.agents import create_agent<br \/>\n    from langchain.tools import tool<br \/>\n    from langchain_openai import ChatOpenAI<\/p>\n<p>    # 1\u3001\u5f15\u5165 checkpointer<br \/>\n    from langgraph.checkpoint.memory import InMemorySaver<\/p>\n<p>    llm &#061; ChatOpenAI(model&#061;&#034;gpt-4o-mini&#034;)<\/p>\n<p>    # 2\u3001\u5b9a\u4e49 checkpointer \u5b9e\u4f8b<br \/>\n    checkpointer &#061; InMemorySaver()<\/p>\n<p>    &#064;tool<br \/>\n    def weather_tool(city: str, date: str) -&gt; str:<br \/>\n        &#034;&#034;&#034;\u67e5\u5929\u6c14\u7684\u5de5\u5177&#034;&#034;&#034;<br \/>\n        return f&#034;{city}\u5728{date}\u7684\u5929\u6c14\u662f\u6674\u6717\u7684&#034;<\/p>\n<p>    # 3\u3001\u6784\u5efa Agent \u65f6\u5f15\u5165 checkpointer<br \/>\n    agent &#061; create_agent(<br \/>\n        model&#061;llm,<br \/>\n        tools&#061;[weather_tool],<br \/>\n        checkpointer&#061;checkpointer,<br \/>\n    )<\/p>\n<p>    # 4\u3001\u7528\u6237\u7b2c\u4e00\u6b21\u8c03\u7528<br \/>\n    user1_res &#061; agent.invoke(<br \/>\n        {&#034;messages&#034;: &#034;\u5317\u4eac2026-01-14\u5929\u6c14\u600e\u4e48\u6837&#034;},<br \/>\n        config&#061;{&#034;configurable&#034;: {&#034;thread_id&#034;: &#034;user_1_session_1&#034;}},<br \/>\n    )<br \/>\n    print(&#034;\u7b2c\u4e00\u6b21\u8c03\u7528&#034;, user1_res[&#034;messages&#034;][-1])<\/p>\n<p>    # 5\u3001\u540c\u4e00\u4e2a\u4f1a\u8bdd\u91cc&#xff0c;\u7b2c\u4e8c\u6b21\u8c03\u7528&#xff08;thread_id \u76f8\u540c&#xff01;&#xff09;<br \/>\n    user1_res_2 &#061; agent.invoke(<br \/>\n        {&#034;messages&#034;: &#034;\u9002\u5408\u51fa\u53bb\u73a9\u5417&#034;},<br \/>\n        config&#061;{&#034;configurable&#034;: {&#034;thread_id&#034;: &#034;user_1_session_1&#034;}},<br \/>\n    )<br \/>\n    print(&#034;\u7b2c\u4e8c\u6b21\u8c03\u7528&#034;, user1_res_2[&#034;messages&#034;][-1])<\/p>\n<p>\u7b2c\u4e8c\u6b21\u63d0\u95ee&#034;\u9002\u5408\u51fa\u53bb\u73a9\u5417&#034;&#xff0c;\u6a21\u578b\u80fd\u7b54\u4e0a\u6765&#xff0c;\u56e0\u4e3a\u5b83\u4ece checkpointer \u91cc\u8bfb\u5230\u4e86\u4e0a\u4e00\u8f6e\u7684&#034;\u5317\u4eac\u3001\u6674\u5929&#034;\u3002\u8fd9\u5c31\u662f\u6240\u8c13\u7684 Agent \u77ed\u671f\u8bb0\u5fc6\u3002<\/p>\n<h4>7.4 \u5b9e\u6218\u4e8c&#xff1a;\u7528 SqliteSaver \u505a&#034;\u65ad\u70b9\u7eed\u8dd1&#034;<\/h4>\n<p>InMemorySaver \u53ea\u5b58\u5728\u5185\u5b58\u91cc&#xff0c;\u8fdb\u7a0b\u4e00\u6302\u5c31\u5168\u6ca1\u4e86&#xff0c;\u6240\u4ee5\u5b83\u89e3\u51b3\u4e0d\u4e86\u573a\u666f\u4e8c\u3002\u751f\u4ea7\u73af\u5883\u8981\u843d\u5230\u6570\u636e\u5e93&#xff0c;\u672c\u5730\u5f00\u53d1\u6700\u65b9\u4fbf\u7684\u662f SQLite\u3002<\/p>\n<p>\u7b2c\u4e00\u6b21\u8fd0\u884c&#xff1a;Node2 \u6545\u610f\u62a5\u9519<\/p>\n<p>def scenario_2_demo():<br \/>\n    &#034;&#034;&#034;\u573a\u666f\u4e8c&#xff1a;\u5982\u4f55\u4ece checkpointer \u4e2d\u6062\u590d\u72b6\u6001&#034;&#034;&#034;<br \/>\n    from langgraph.graph import StateGraph, START<br \/>\n    from typing import TypedDict<\/p>\n<p>    # 1\u3001\u5f15\u5165 sqlite3 \u548c SqliteSaver<br \/>\n    import sqlite3<br \/>\n    from langgraph.checkpoint.sqlite import SqliteSaver<\/p>\n<p>    # 2\u3001\u6784\u5efa Connection \u5bf9\u8c61<br \/>\n    conn &#061; sqlite3.connect(database&#061;&#034;.\/sqlite_data\/langgraph_sqlite&#034;, check_same_thread&#061;False)<br \/>\n    # 3\u3001\u901a\u8fc7 connection \u5bf9\u8c61\u6784\u5efa checkpointer \u5b9e\u4f8b<br \/>\n    memory &#061; SqliteSaver(conn)<\/p>\n<p>    class MyState(TypedDict):<br \/>\n        key_1: str<br \/>\n        key_2: str<br \/>\n        key_3: str<\/p>\n<p>    def node_1(state: MyState) -&gt; MyState:<br \/>\n        print(&#034;node_1\u521d\u59cb\u72b6\u6001\u4e3a&#034;, state)<br \/>\n        return {&#034;key_1&#034;: &#034;value_1&#034;}<\/p>\n<p>    def node_2(state: MyState) -&gt; MyState:<br \/>\n        # 5\u3001\u6a21\u62df\u751f\u4ea7\u73af\u5883\u4e0b\u7684 bug \u6216\u4e0d\u53ef\u9884\u89c1\u60c5\u51b5<br \/>\n        raise Exception(&#034;node_2\u8282\u70b9\u6267\u884c\u62a5\u9519&#034;)<br \/>\n        return {&#034;key_2&#034;: &#034;value_2&#034;}<\/p>\n<p>    def node_3(state: MyState) -&gt; MyState:<br \/>\n        return {&#034;key_3&#034;: &#034;value_3&#034;}<\/p>\n<p>    builder &#061; StateGraph(MyState)<br \/>\n    builder.add_node(node_1)<br \/>\n    builder.add_node(node_2)<br \/>\n    builder.add_node(node_3)<br \/>\n    builder.add_edge(START, &#034;node_1&#034;)<br \/>\n    builder.add_edge(&#034;node_1&#034;, &#034;node_2&#034;)<br \/>\n    builder.add_edge(&#034;node_1&#034;, &#034;node_3&#034;)<\/p>\n<p>    config &#061; {&#034;configurable&#034;: {&#034;thread_id&#034;: &#034;123&#034;}}<\/p>\n<p>    # 6\u3001compile \u65f6\u4f20\u5165 checkpointer<br \/>\n    graph &#061; builder.compile(checkpointer&#061;memory)<\/p>\n<p>    # 7\u3001\u8c03\u7528\u65f6\u4f20\u5165 config<br \/>\n    graph.invoke({}, config&#061;config)<\/p>\n<p>\u8fd9\u4e00\u8dd1&#xff0c;\u7a0b\u5e8f\u4f1a\u5728 Node2 \u629b\u5f02\u5e38\u4e2d\u65ad\u3002\u4f46\u56e0\u4e3a\u6302\u4e86 checkpointer&#xff0c;node_1 \u7684\u7ed3\u679c\u5df2\u7ecf\u843d\u76d8\u4e86\u3002<\/p>\n<p>\u7b2c\u4e8c\u6b21\u8fd0\u884c&#xff1a;\u4fee\u597d bug&#xff0c;\u4ece\u65ad\u70b9\u7ee7\u7eed<\/p>\n<p>\u628a Node2 \u91cc\u90a3\u884c raise \u6ce8\u91ca\u6389&#xff0c;\u7136\u540e\u53ea\u6539\u4e24\u4e2a\u5730\u65b9&#xff1a;<\/p>\n<li>invoke \u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u4f20 None&#xff08;\u8868\u793a&#034;\u4e0d\u8981\u65b0\u7684\u521d\u59cb\u72b6\u6001&#xff0c;\u7528\u5b58\u597d\u7684&#034;&#xff09;&#xff1b;<\/li>\n<li>thread_id \u4fdd\u6301\u548c\u4e0a\u6b21\u4e00\u6837&#xff08;&#034;123&#034;&#xff09;\u3002<\/li>\n<p>    def node_2(state: MyState) -&gt; MyState:<br \/>\n        # 1\u3001\u4fee\u590d\u9519\u8bef&#xff0c;\u6ce8\u91ca\u6389\u62a5\u9519\u4ee3\u7801<br \/>\n        # raise Exception(&#034;node_2\u8282\u70b9\u6267\u884c\u62a5\u9519&#034;)<br \/>\n        return {&#034;key_2&#034;: &#034;value_2&#034;}<\/p>\n<p>    # &#8230;&#xff08;\u5176\u4ed6\u90e8\u5206\u4e0e\u4e0a\u9762\u5b8c\u5168\u76f8\u540c&#xff09;<\/p>\n<p>    # 2\u3001\u6ce8\u610f&#xff01;\u4ece\u6545\u969c\u4e2d\u6062\u590d&#xff0c;\u7b2c\u4e00\u4e2a\u53c2\u6570\u4f20 None<br \/>\n    graph.invoke(None, config&#061;config)<\/p>\n<p>\u6b64\u65f6\u4f60\u4f1a\u53d1\u73b0&#xff0c;node_1 \u91cc\u7684\u6253\u5370\u8bed\u53e5\u6ca1\u6709\u518d\u6267\u884c\u4e00\u6b21\u2014\u2014\u5b83\u662f\u4ece Node2 \u63a5\u7740\u8dd1\u7684\u3002\u8fd9\u5c31\u662f&#034;\u65ad\u70b9\u7eed\u8dd1&#034;\u3002<\/p>\n<p>\u4e00\u4e2a\u5fc5\u987b\u8bb0\u4f4f\u7684\u5751&#xff1a;\u6062\u590d\u6267\u884c\u65f6&#xff0c;\u88ab\u4e2d\u65ad\u7684\u90a3\u4e2a\u8282\u70b9\u51fd\u6570\u4f1a\u4ece\u51fd\u6570\u5f00\u5934\u91cd\u65b0\u8dd1\u4e00\u904d&#xff0c;\u800c\u4e0d\u662f\u4ece interrupt \u90a3\u4e00\u884c\u63a5\u7740\u8dd1\u3002\u6240\u4ee5\u5982\u679c\u8282\u70b9\u91cc\u6709&#034;\u53d1\u90ae\u4ef6&#034;&#034;\u6263\u6b3e&#034;&#034;\u5199\u6570\u636e\u5e93&#034;\u8fd9\u7c7b\u64cd\u4f5c&#xff0c;\u4e00\u5b9a\u4fdd\u8bc1\u5e42\u7b49&#xff0c;\u6216\u8005\u628a\u5b83\u62c6\u6210\u5355\u72ec\u8282\u70b9\u3002\u8fd9\u4e2a\u5751\u5728\u7b2c\u5341\u4e8c\u8282\u8bb2 interrupt \u65f6\u8fd8\u4f1a\u518d\u5f3a\u8c03\u4e00\u6b21\u3002<\/p>\n<h3>\u516b\u3001\u63ed\u5f00\u5e95\u724c&#xff1a;Pregel \u662f\u600e\u4e48\u628a\u56fe\u8dd1\u8d77\u6765\u7684<\/h3>\n<p>\u524d\u9762\u8bf4&#034;\u56fe\u4f1a\u5e76\u884c&#034;&#034;\u4f1a\u5faa\u73af&#034;&#xff0c;\u90a3\u5b83\u5185\u90e8\u5230\u5e95\u600e\u4e48\u8c03\u5ea6\u7684&#xff1f;\u7406\u89e3\u8fd9\u4e00\u5c42&#xff0c;\u4f60\u8c03\u8bd5\u590d\u6742\u56fe\u65f6\u4f1a\u8f7b\u677e\u5f88\u591a\u3002<\/p>\n<h4>8.1 \u4e24\u4e2a\u4e3b\u89d2&#xff1a;Actor \u548c Channel<\/h4>\n<p>LangGraph \u5e95\u5c42\u6709\u4e2a\u53eb Pregel \u7684\u7c7b&#xff0c;\u8d1f\u8d23\u7ba1\u7406\u6574\u4e2a\u56fe\u4ece\u5f00\u59cb\u5230\u7ed3\u675f\u7684\u8fed\u4ee3\u6267\u884c\u3002\u5b83\u91cc\u9762\u53ea\u6709\u4e24\u5927\u7ec4\u4ef6&#xff1a;<\/p>\n<ul>\n<li>Actors&#xff08;\u8282\u70b9&#xff09;&#xff1a;\u5bf9\u5e94\u4f60\u5199\u7684 Node&#xff0c;\u5728\u5e95\u5c42\u53eb PregelNode\u3002\u5b83\u8ba2\u9605\u67d0\u4e9b\u901a\u9053&#xff08;\u4ece\u901a\u9053\u8bfb\u6570\u636e&#xff09;&#xff0c;\u4e5f\u4f1a\u5199\u5165\u67d0\u4e9b\u901a\u9053\u3002<\/li>\n<li>Channels&#xff08;\u901a\u9053&#xff09;&#xff1a;Actor \u4e4b\u95f4\u901a\u4fe1\u7684\u7ba1\u9053\u3002\u6bcf\u4e2a\u901a\u9053\u90fd\u6709\u503c\u7c7b\u578b\u3001\u66f4\u65b0\u7c7b\u578b\u3001\u4ee5\u53ca\u4e00\u4e2a\u66f4\u65b0\u51fd\u6570&#xff08;\u63a5\u6536\u4e00\u6279\u66f4\u65b0&#xff0c;\u4fee\u6539\u5b58\u50a8\u7684\u503c&#xff09;\u3002<\/li>\n<\/ul>\n<p>\u56e0\u4e3a\u8fd9\u79cd\u8bbe\u8ba1&#xff0c;LangGraph \u7684\u56fe\u4e0d\u662f\u4f20\u7edf\u610f\u4e49\u4e0a\u7684\u6709\u5411\u65e0\u73af\u56fe&#xff08;DAG&#xff09;\u3002\u5728\u4f20\u7edf DAG \u91cc&#xff0c;\u4e00\u4e2a\u8282\u70b9\u5fc5\u987b\u7b49\u5b83\u6240\u6709\u4e0a\u6e38\u90fd\u8dd1\u5b8c\u624d\u80fd\u8dd1&#xff0c;\u9760&#034;\u8fb9&#034;\u6765\u51b3\u5b9a\u987a\u5e8f\u3002<\/p>\n<p>\u800c\u5728 LangGraph \u91cc&#xff0c;\u8282\u70b9\u4ec0\u4e48\u65f6\u5019\u6267\u884c&#xff0c;\u662f\u7531\u4e00\u4e2a\u4e2a \u8d85\u6b65&#xff08;SuperStep&#xff09; \u51b3\u5b9a\u7684\u3002<\/p>\n<h4>8.2 \u4e00\u4e2a\u8d85\u6b65\u5206\u4e09\u4e2a\u9636\u6bb5<\/h4>\n<table>\n<tr>\u9636\u6bb5\u505a\u4ec0\u4e48<\/tr>\n<tbody>\n<tr>\n<td>Plan<\/td>\n<td>\u786e\u5b9a\u8fd9\u4e00\u6b65\u8981\u6267\u884c\u54ea\u4e9b Actor\u3002\u7b2c\u4e00\u6b65\u9009&#034;\u8ba2\u9605\u4e86\u7279\u6b8a\u8f93\u5165\u901a\u9053&#034;\u7684 Actor&#xff0c;\u540e\u7eed\u6b65\u9aa4\u9009&#034;\u8ba2\u9605\u4e86\u4e0a\u4e00\u6b65\u88ab\u66f4\u65b0\u7684\u901a\u9053&#034;\u7684 Actor<\/td>\n<\/tr>\n<tr>\n<td>Execute<\/td>\n<td>\u5e76\u884c\u6267\u884c\u6240\u6709\u88ab\u9009\u4e2d\u7684 Actor&#xff0c;\u76f4\u5230\u5168\u90e8\u5b8c\u6210\u3001\u6216\u5176\u4e2d\u4e00\u4e2a\u5931\u8d25\u3001\u6216\u8d85\u65f6<\/td>\n<\/tr>\n<tr>\n<td>Update<\/td>\n<td>\u7528\u8fd9\u4e00\u6b65 Actor \u5199\u5165\u7684\u503c&#xff0c;\u53bb\u66f4\u65b0\u5bf9\u5e94\u7684 Channel<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u8fd9\u4e09\u4e2a\u9636\u6bb5\u7ec4\u6210\u7684\u4e00\u4e2a&#034;\u8d85\u6b65&#034;\u4f1a\u4e0d\u65ad\u91cd\u590d&#xff0c;\u76f4\u5230\u6ca1\u6709 Actor \u88ab\u9009\u4e2d&#xff0c;\u6216\u8005\u8fbe\u5230\u6700\u5927\u6b65\u6570\u3002<\/p>\n<p>\u6362\u53e5\u8bdd\u8bf4&#xff1a;\u4e0d\u662f&#034;\u8fb9\u901a\u5411\u8c01&#034;\u51b3\u5b9a\u6267\u884c\u987a\u5e8f&#xff0c;\u800c\u662f&#034;\u8c01\u5199\u4e86\u8fd9\u4e2a\u901a\u9053\u3001\u8c01\u8ba2\u9605\u4e86\u8fd9\u4e2a\u901a\u9053&#034;\u51b3\u5b9a\u4e0b\u4e00\u6279\u8dd1\u8c01\u3002 \u8fb9\u53ea\u662f\u5e2e\u4f60\u628a&#034;\u8ba2\u9605\u5173\u7cfb&#034;\u81ea\u52a8\u751f\u6210\u51fa\u6765\u7684\u8bed\u6cd5\u7cd6\u3002<\/p>\n<h4>8.3 \u8ddf\u7740\u4e00\u4e2a\u4f8b\u5b50\u6570\u4e00\u904d Step<\/h4>\n<p>\u5047\u8bbe\u56fe\u662f\u8fd9\u6837\u7684&#xff1a;START \u2192 a \u2192 (b, c)&#xff1b;b \u2192 b_2 \u2192 d&#xff1b;c \u2192 d&#xff1b;d \u2192 END\u3002<\/p>\n<p>\u7f16\u8bd1\u65f6&#xff0c;builder.compile() \u4f1a\u628a\u8fd9\u5f20\u903b\u8f91\u56fe\u8f6c\u6362\u6210 Pregel \u5b9e\u4f8b&#xff1a;\u8282\u70b9\u53d8\u6210 Actors&#xff0c;\u8fb9\u53d8\u6210 Channels\u3002<\/p>\n<p>\u6267\u884c\u8fc7\u7a0b&#xff08;Step \u4ece 0 \u5f00\u59cb\u6570&#xff09;&#xff1a;<\/p>\n<ul>\n<li>Step -1&#xff1a;__START__ \u8282\u70b9\u6267\u884c&#xff08;\u56fe\u4e2d\u770b\u4e0d\u89c1&#xff09;&#xff0c;\u628a\u72b6\u6001\u5199\u8fdb branch:to:a&#xff1b;<\/li>\n<li>Step 0&#xff1a;\u8282\u70b9 a \u6267\u884c&#xff0c;\u628a\u72b6\u6001\u5199\u8fdb branch:to:b \u548c branch:to:c&#xff1b;<\/li>\n<li>Step 1&#xff1a;\u8282\u70b9 b \u548c c \u5e76\u884c\u6267\u884c&#xff0c;\u5206\u522b\u5199\u8fdb branch:to:b_2 \u548c branch:to:d&#xff1b;<\/li>\n<li>Step 2&#xff1a;\u8282\u70b9 b_2 \u548c\u8282\u70b9 d \u6267\u884c\u3002\u6ce8\u610f d \u8fd9\u65f6\u5019\u5df2\u7ecf\u88ab\u89e6\u53d1\u8fc7\u4e00\u6b21&#xff08;\u56e0\u4e3a c \u5199\u4e86\u5b83&#xff09;&#xff0c;b_2 \u53c8\u5f80 branch:to:d \u5199\u4e86\u4e00\u6b21&#xff1b;<\/li>\n<li>Step 3&#xff1a;\u8282\u70b9 d \u518d\u6267\u884c\u4e00\u6b21&#xff0c;\u8fd9\u6b21\u6ca1\u6709\u65b0\u7684\u72b6\u6001\u66f4\u65b0&#xff0c;\u56fe\u7684\u6267\u884c\u7ed3\u675f\u3002<\/li>\n<\/ul>\n<p>\u8fd9\u4e2a\u4f8b\u5b50\u8bf4\u660e\u4e86\u4e00\u4ef6\u91cd\u8981\u7684\u4e8b&#xff1a;\u540c\u4e00\u4e2a\u8282\u70b9\u53ef\u4ee5\u5728\u591a\u4e2a Step \u91cc\u88ab\u591a\u6b21\u6267\u884c&#xff08;d \u8dd1\u4e86\u4e24\u6b21&#xff09;\u3002\u8fd9\u5c31\u662f\u4e3a\u4ec0\u4e48&#034;\u5faa\u73af&#034;\u5bf9 LangGraph \u6765\u8bf4\u662f\u5929\u7136\u7684&#xff0c;\u800c\u4e0d\u662f\u9760\u7279\u6b8a\u8bed\u6cd5\u5b9e\u73b0\u3002<\/p>\n<p>import operator<br \/>\nfrom typing import Annotated<br \/>\nfrom typing_extensions import TypedDict<br \/>\nfrom langgraph.graph import StateGraph, START, END<\/p>\n<p>class State(TypedDict):<br \/>\n    aggregate: Annotated[list, operator.add]<\/p>\n<p>def a(state: State, config):<br \/>\n    print(f&#039;Adding &#034;A&#034; to {state[&#034;aggregate&#034;]}&#039;)<br \/>\n    return {&#034;aggregate&#034;: [&#034;A&#034;]}<\/p>\n<p>def b(state: State, config):<br \/>\n    print(f&#039;Adding &#034;B&#034; to {state[&#034;aggregate&#034;]}&#039;)<br \/>\n    return {&#034;aggregate&#034;: [&#034;B&#034;]}<\/p>\n<p>def b_2(state: State, config):<br \/>\n    print(f&#039;Adding &#034;B_2&#034; to {state[&#034;aggregate&#034;]}&#039;)<br \/>\n    return {&#034;aggregate&#034;: [&#034;B_2&#034;]}<\/p>\n<p>def c(state: State, config):<br \/>\n    print(f&#039;Adding &#034;C&#034; to {state[&#034;aggregate&#034;]}&#039;)<br \/>\n    return {&#034;aggregate&#034;: [&#034;C&#034;]}<\/p>\n<p>def d(state: State, config):<br \/>\n    print(f&#039;Adding &#034;D&#034; to {state[&#034;aggregate&#034;]}&#039;)<br \/>\n    return {&#034;aggregate&#034;: [&#034;D&#034;]}<\/p>\n<p>builder &#061; StateGraph(State)<br \/>\nbuilder.add_node(&#034;a&#034;, a)<br \/>\nbuilder.add_node(&#034;b&#034;, b)<br \/>\nbuilder.add_node(&#034;b_2&#034;, b_2)<br \/>\nbuilder.add_node(&#034;c&#034;, c)<br \/>\nbuilder.add_node(&#034;d&#034;, d)<\/p>\n<p>builder.add_edge(START, &#034;a&#034;)<br \/>\nbuilder.add_edge(&#034;a&#034;, &#034;b&#034;)<br \/>\nbuilder.add_edge(&#034;a&#034;, &#034;c&#034;)<br \/>\nbuilder.add_edge(&#034;b&#034;, &#034;b_2&#034;)<br \/>\nbuilder.add_edge(&#034;b_2&#034;, &#034;d&#034;)<br \/>\nbuilder.add_edge(&#034;c&#034;, &#034;d&#034;)<br \/>\nbuilder.add_edge(&#034;d&#034;, END)<\/p>\n<p>graph &#061; builder.compile()<\/p>\n<p># 1\u3001\u67e5\u770b\u5f53\u524d\u56fe\u7684 channels<br \/>\nprint(&#034;\u5f53\u524d\u56fe\u7684channels\u4e3a&#034;, graph.channels)<br \/>\n# 2\u3001\u67e5\u770b\u5f53\u524d\u56fe\u7684\u8282\u70b9<br \/>\nprint(&#034;\u5f53\u524d\u56fe\u7684\u8282\u70b9\u4e3a&#034;, graph.nodes)<br \/>\n# 3\u3001\u67e5\u770b a \u8282\u70b9\u7684\u89e6\u53d1\u6761\u4ef6&#xff08;\u8ba2\u9605&#xff09;\u548c\u5199\u5165\u76ee\u6807<br \/>\nprint(&#034;\u8282\u70b9a\u7684triggers\u4e3a&#034;, graph.nodes[&#034;a&#034;].triggers)<br \/>\nprint(&#034;\u8282\u70b9a\u7684writers\u4e3a&#034;, graph.nodes[&#034;a&#034;].writers)<br \/>\n# 4\u3001\u67e5\u770b d \u8282\u70b9\u7684\u89e6\u53d1\u6761\u4ef6\u548c\u5199\u5165\u76ee\u6807<br \/>\nprint(&#034;\u8282\u70b9d\u7684triggers\u4e3a&#034;, graph.nodes[&#034;d&#034;].triggers)<br \/>\nprint(&#034;\u8282\u70b9d\u7684writers\u4e3a&#034;, graph.nodes[&#034;d&#034;].writers)<\/p>\n<p># 5\u3001\u6267\u884c\u56fe&#xff0c;\u67e5\u770b\u7ed3\u679c<br \/>\noutput_state &#061; graph.invoke({&#034;aggregate&#034;: []})<br \/>\nprint(&#034;\u6267\u884c\u56fe\u540e\u7684\u72b6\u6001\u4e3a&#034;, output_state)<\/p>\n<p>\u6253\u5370\u51fa\u6765\u7684 triggers \u5c31\u662f&#034;\u8fd9\u4e2a\u8282\u70b9\u8ba2\u9605\u4e86\u54ea\u4e9b\u901a\u9053&#034;&#xff0c;writers \u5c31\u662f&#034;\u8fd9\u4e2a\u8282\u70b9\u4f1a\u5199\u54ea\u4e9b\u901a\u9053&#034;\u3002\u770b\u61c2\u8fd9\u4e24\u884c\u8f93\u51fa&#xff0c;\u4f60\u5c31\u80fd\u9884\u6d4b\u4efb\u4f55\u4e00\u5f20\u56fe\u7684\u6267\u884c\u987a\u5e8f\u4e86\u3002<\/p>\n<h3>\u4e5d\u3001\u68c0\u67e5\u70b9\u5feb\u7167&#xff1a;\u600e\u4e48\u628a\u5386\u53f2\u72b6\u6001\u7ffb\u51fa\u6765\u770b<\/h3>\n<p>\u6709\u4e86 checkpointer&#xff0c;LangGraph \u4f1a\u5728\u6bcf\u4e2a\u8d85\u6b65\u7ed3\u675f\u65f6\u5b58\u4e00\u4efd\u5feb\u7167\u3002\u90a3\u600e\u4e48\u8bfb\u51fa\u6765&#xff1f;\u4e24\u4e2a\u65b9\u6cd5&#xff1a;<\/p>\n<ul>\n<li>graph.get_state(config)&#xff1a;\u62ff\u6700\u8fd1\u4e00\u6b21\u7684\u72b6\u6001&#xff1b;<\/li>\n<li>graph.get_state_history(config)&#xff1a;\u62ff\u6240\u6709\u5386\u53f2\u72b6\u6001&#xff0c;\u8fd4\u56de\u4e00\u4e2a\u8fed\u4ee3\u5668&#xff0c;\u6309\u65f6\u95f4\u6b65\u5012\u5e8f\u6392\u5217&#xff08;\u6700\u65b0\u7684\u5728\u6700\u524d&#xff09;\u3002<\/li>\n<\/ul>\n<p>\u6bcf\u4e2a\u5feb\u7167\u662f\u4e00\u4e2a StateSnapshot \u5bf9\u8c61&#xff0c;\u5b57\u6bb5\u5982\u4e0b&#xff1a;<\/p>\n<table>\n<tr>\u540d\u79f0\u7c7b\u578b\u63cf\u8ff0<\/tr>\n<tbody>\n<tr>\n<td>values<\/td>\n<td>dict[str, Any]<\/td>\n<td>\u5f53\u524d\u72b6\u6001\u4fe1\u606f<\/td>\n<\/tr>\n<tr>\n<td>next<\/td>\n<td>tuple[str, &#8230;]<\/td>\n<td>\u672c\u8d85\u6b65\u4e2d\u6bcf\u4e2a\u4efb\u52a1\u8981\u6267\u884c\u7684\u8282\u70b9\u540d\u79f0<\/td>\n<\/tr>\n<tr>\n<td>config<\/td>\n<td>RunnableConfig<\/td>\n<td>\u7528\u4e8e\u83b7\u53d6\u6b64\u5feb\u7167\u7684\u914d\u7f6e<\/td>\n<\/tr>\n<tr>\n<td>metadata<\/td>\n<td>CheckpointMetadata<\/td>\n<td>\u4e0e\u6b64\u5feb\u7167\u76f8\u5173\u8054\u7684\u5143\u6570\u636e<\/td>\n<\/tr>\n<tr>\n<td>parent_config<\/td>\n<td>RunnableConfig<\/td>\n<td>\u7528\u4e8e\u83b7\u53d6\u7236\u5feb\u7167\u7684\u914d\u7f6e&#xff08;\u5982\u679c\u6709&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>interrupts<\/td>\n<td>tuple[Interrupt, &#8230;]<\/td>\n<td>\u6b64\u8d85\u6b65\u4e2d\u53d1\u751f\u4e14\u6709\u5f85\u89e3\u51b3\u7684\u4e2d\u65ad<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u8fd9\u91cc\u6700\u503c\u5f97\u5173\u6ce8\u7684\u662f next&#xff1a;\u5b83\u4e0d\u4ec5\u544a\u8bc9\u4f60&#034;\u73b0\u5728\u6570\u636e\u662f\u4ec0\u4e48&#034;&#xff0c;\u8fd8\u544a\u8bc9\u4f60&#034;\u63a5\u4e0b\u6765\u8be5\u8dd1\u8c01&#034;\u3002\u65ad\u70b9\u7eed\u8dd1\u80fd\u5b9e\u73b0&#xff0c;\u9760\u7684\u6b63\u662f\u8fd9\u4e2a\u4fe1\u606f\u3002<\/p>\n<p>import operator<br \/>\nfrom typing import Annotated<br \/>\nfrom typing_extensions import TypedDict<br \/>\nfrom langgraph.graph import StateGraph, START, END<br \/>\nfrom langgraph.checkpoint.sqlite import SqliteSaver<br \/>\nimport sqlite3<\/p>\n<p>connection &#061; sqlite3.connect(&#034;checkpointer.db&#034;, check_same_thread&#061;False)<br \/>\ncheckpointer &#061; SqliteSaver(connection)<\/p>\n<p>class State(TypedDict):<br \/>\n    aggregate: Annotated[list, operator.add]<\/p>\n<p>def a(state: State, config):<br \/>\n    print(f&#039;Adding &#034;A&#034; to {state[&#034;aggregate&#034;]}&#039;)<br \/>\n    return {&#034;aggregate&#034;: [&#034;A&#034;]}<\/p>\n<p>def b(state: State, config):<br \/>\n    print(f&#039;Adding &#034;B&#034; to {state[&#034;aggregate&#034;]}&#039;)<br \/>\n    return {&#034;aggregate&#034;: [&#034;B&#034;]}<\/p>\n<p>def b_2(state: State, config):<br \/>\n    print(f&#039;Adding &#034;B_2&#034; to {state[&#034;aggregate&#034;]}&#039;)<br \/>\n    return {&#034;aggregate&#034;: [&#034;B_2&#034;]}<\/p>\n<p>def c(state: State, config):<br \/>\n    print(f&#039;Adding &#034;C&#034; to {state[&#034;aggregate&#034;]}&#039;)<br \/>\n    return {&#034;aggregate&#034;: [&#034;C&#034;]}<\/p>\n<p>def d(state: State, config):<br \/>\n    print(f&#039;Adding &#034;D&#034; to {state[&#034;aggregate&#034;]}&#039;)<br \/>\n    return {&#034;aggregate&#034;: [&#034;D&#034;]}<\/p>\n<p>builder &#061; StateGraph(State)<br \/>\nbuilder.add_node(&#034;a&#034;, a)<br \/>\nbuilder.add_node(&#034;b&#034;, b)<br \/>\nbuilder.add_node(&#034;b_2&#034;, b_2)<br \/>\nbuilder.add_node(&#034;c&#034;, c)<br \/>\nbuilder.add_node(&#034;d&#034;, d)<\/p>\n<p>builder.add_edge(START, &#034;a&#034;)<br \/>\nbuilder.add_edge(&#034;a&#034;, &#034;b&#034;)<br \/>\nbuilder.add_edge(&#034;a&#034;, &#034;c&#034;)<br \/>\nbuilder.add_edge(&#034;b&#034;, &#034;b_2&#034;)<br \/>\nbuilder.add_edge(&#034;b_2&#034;, &#034;d&#034;)<br \/>\nbuilder.add_edge(&#034;c&#034;, &#034;d&#034;)<br \/>\nbuilder.add_edge(&#034;d&#034;, END)<\/p>\n<p>graph &#061; builder.compile(checkpointer&#061;checkpointer)<\/p>\n<p>config &#061; {&#034;configurable&#034;: {&#034;thread_id&#034;: &#034;1&#034;}}<br \/>\nres &#061; graph.invoke({}, config&#061;config)<\/p>\n<p># 1\u3001\u6700\u7ec8\u72b6\u6001<br \/>\nprint(res)<\/p>\n<p># 2\u3001\u67e5\u770b\u5386\u53f2\u6240\u6709\u72b6\u6001<br \/>\nall_states &#061; graph.get_state_history(config&#061;config)<br \/>\nall_states_list &#061; list(all_states)<br \/>\nprint(&#034;\u5386\u53f2\u6240\u6709\u72b6\u6001\u5982\u4e0b&#xff1a;&#034;)<br \/>\nfor state in all_states_list:<br \/>\n    print(state)<br \/>\n    print(&#034;&#061;&#034; * 30)<\/p>\n<p># 3\u3001\u6700\u8fd1\u4e00\u6b21\u72b6\u6001<br \/>\nprint(&#034;\\\\n\u6700\u8fd1\u4e00\u6b21\u72b6\u6001\u5982\u4e0b&#xff1a;&#034;)<br \/>\nprint(graph.get_state(config&#061;config))<\/p>\n<p>\u8dd1\u5b8c\u8fd9\u6bb5&#xff0c;\u4f60\u4f1a\u770b\u5230\u4e00\u4e32\u5feb\u7167&#xff0c;\u6bcf\u4e2a\u91cc\u90fd\u6709 values \u548c next\u3002\u987a\u7740\u770b\u4e0b\u53bb&#xff0c;\u5c31\u76f8\u5f53\u4e8e\u7ed9\u56fe\u88c5\u4e86\u4e00\u4e2a&#034;\u884c\u8f66\u8bb0\u5f55\u4eea&#034;\u2014\u2014\u51fa\u4e86\u95ee\u9898\u80fd\u7cbe\u786e\u77e5\u9053\u5728\u54ea\u4e00\u6b65\u3001\u5f53\u65f6\u7684\u6570\u636e\u957f\u4ec0\u4e48\u6837\u3002<\/p>\n<h3>\u5341\u3001Node&#xff1a;\u8282\u70b9\u600e\u4e48\u5199\u624d\u4e0d\u51fa\u9519<\/h3>\n<h4>10.1 \u8282\u70b9\u80fd\u63a5\u6536\u54ea\u4e9b\u53c2\u6570<\/h4>\n<p>\u8282\u70b9\u4e00\u822c\u662f Python \u51fd\u6570&#xff08;\u540c\u6b65\u5f02\u6b65\u90fd\u884c&#xff09;&#xff0c;LangGraph \u4f1a\u5728\u8fd0\u884c\u65f6\u81ea\u52a8\u6ce8\u5165\u4e09\u4e2a\u53ef\u9009\u53c2\u6570&#xff1a;<\/p>\n<table>\n<tr>\u53c2\u6570\u5185\u5bb9<\/tr>\n<tbody>\n<tr>\n<td>state<\/td>\n<td>\u56fe\u7684\u72b6\u6001&#xff0c;\u4e5f\u5c31\u662f\u4e1a\u52a1\u6570\u636e<\/td>\n<\/tr>\n<tr>\n<td>config<\/td>\n<td>RunnableConfig&#xff0c;\u5305\u542b thread_id \u7b49&#xff1b;\u8c03\u7528\u65f6\u4f60\u4e5f\u53ef\u4ee5\u585e\u81ea\u5b9a\u4e49\u914d\u7f6e\u8fdb\u53bb<\/td>\n<\/tr>\n<tr>\n<td>runtime<\/td>\n<td>Runtime \u5bf9\u8c61&#xff0c;\u5305\u542b\u8fd0\u884c\u65f6 context&#xff08;\u53ef\u81ea\u5b9a\u4e49&#xff0c;\u8c03\u7528\u56fe\u65f6\u4f20\u5165&#xff09;\u3001store\u3001stream_writer \u7b49<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u8fd9\u4e09\u4e2a\u53c2\u6570\u662f\u6309\u5173\u952e\u5b57\u4f20\u7684&#xff0c;\u6240\u4ee5\u987a\u5e8f\u53ef\u4ee5\u968f\u4fbf\u8c03\u3002\u4e0b\u9762\u7684\u4f8b\u5b50\u6f14\u793a\u4e00\u4e2a\u5f88\u5b9e\u7528\u7684\u6280\u5de7&#xff1a;\u4f9d\u8d56\u6ce8\u5165\u2014\u2014\u628a LLM \u548c\u6570\u636e\u5e93\u5bf9\u8c61\u901a\u8fc7 runtime.context \u4f20\u8fdb\u8282\u70b9&#xff0c;\u800c\u4e0d\u662f\u5199\u6b7b\u5728\u5168\u5c40\u53d8\u91cf\u91cc\u3002\u8fd9\u6837\u6d4b\u8bd5\u65f6\u53ef\u4ee5\u8f7b\u677e\u66ff\u6362\u6210 mock\u3002<\/p>\n<p>import time<br \/>\nfrom typing import TypedDict, List<br \/>\nfrom langchain_core.runnables import RunnableConfig<br \/>\nfrom langgraph.graph import StateGraph, START, END<br \/>\nfrom langgraph.runtime import Runtime<\/p>\n<p>class MockLLM:<br \/>\n    def invoke(self, prompt: str):<br \/>\n        return f&#034;AI Generated: Answer for &#039;{prompt}&#039;&#034;<\/p>\n<p>class MockDatabase:<br \/>\n    def get_user_info(self, user_id: str):<br \/>\n        return {&#034;id&#034;: user_id, &#034;role&#034;: &#034;vip&#034; if &#034;vip&#034; in user_id else &#034;standard&#034;}<\/p>\n<p>class CustomerSupportState(TypedDict):<br \/>\n    query: str          # \u7528\u6237\u95ee\u9898<br \/>\n    response: str       # \u5ba2\u670d\u56de\u590d<br \/>\n    log: List[str]      # \u5904\u7406\u65e5\u5fd7<\/p>\n<p>def node_customer_service(<br \/>\n    state: CustomerSupportState,<br \/>\n    config: RunnableConfig,<br \/>\n    runtime: Runtime,<br \/>\n) -&gt; dict:<br \/>\n    &#034;&#034;&#034;\u5ba2\u670d\u8282\u70b9&#xff1a;\u4ece config \u53d6\u914d\u7f6e&#xff0c;\u4ece runtime.context \u53d6\u6ce8\u5165\u7684\u4f9d\u8d56&#xff0c;\u5e76\u5f80\u5916\u63a8\u8fdb\u5ea6\u3002&#034;&#034;&#034;<br \/>\n    user_query &#061; state[&#034;query&#034;]<\/p>\n<p>    # 1\u3001\u4ece runtime \u91cc\u53d6\u51fa\u4f9d\u8d56<br \/>\n    llm &#061; runtime.context[&#034;llm&#034;]<br \/>\n    db &#061; runtime.context[&#034;db&#034;]<\/p>\n<p>    configurable &#061; config.get(&#034;configurable&#034;, {})<br \/>\n    user_id &#061; configurable.get(&#034;user_id&#034;, &#034;guest&#034;)<br \/>\n    print(f&#034;\\\\n[Node] \u5f00\u59cb\u5904\u7406&#xff0c;User ID: {user_id}&#034;)<\/p>\n<p>    # 2\u3001\u6821\u9a8c\u4f9d\u8d56\u662f\u5426\u5b58\u5728<br \/>\n    if not llm or not db:<br \/>\n        return {&#034;response&#034;: &#034;System Error: Dependencies not injected!&#034;, &#034;log&#034;: [&#034;Error&#034;]}<\/p>\n<p>    # 3\u3001\u7528 db \u67e5\u7528\u6237\u89d2\u8272<br \/>\n    user_info &#061; db.get_user_info(user_id)<br \/>\n    user_tier &#061; user_info.get(&#034;role&#034;)<br \/>\n    print(f&#034;[Node] \u4ece DB \u83b7\u53d6\u7528\u6237\u89d2\u8272: {user_tier}&#034;)<\/p>\n<p>    # 4\u3001\u7528 runtime.stream_writer \u5411\u56fe\u5916\u63a8\u81ea\u5b9a\u4e49\u8fdb\u5ea6&#xff08;\u5bf9\u5e94 custom \u6d41\u5f0f\u6a21\u5f0f&#xff09;<br \/>\n    writer &#061; runtime.stream_writer<br \/>\n    writer({&#034;status&#034;: &#034;thinking&#034;, &#034;message&#034;: f&#034;\u6b63\u5728\u8c03\u7528 LLM \u4e3a {user_tier} \u7528\u6237\u751f\u6210\u56de\u590d&#8230;&#034;})<br \/>\n    time.sleep(0.5)<\/p>\n<p>    # 5\u3001\u6309\u89d2\u8272\u6784\u9020\u4e0d\u540c Prompt&#xff0c;\u6a21\u62df LLM \u8c03\u7528<br \/>\n    prompt &#061; f&#034;User({user_tier}) asks: {user_query}&#034;<br \/>\n    llm_response &#061; llm.invoke(prompt)<\/p>\n<p>    return {<br \/>\n        &#034;response&#034;: llm_response,<br \/>\n        &#034;log&#034;: [f&#034;Processed by {llm.__class__.__name__}&#034;],<br \/>\n    }<\/p>\n<p>def run_demo():<br \/>\n    builder &#061; StateGraph(CustomerSupportState)<br \/>\n    builder.add_node(&#034;customer_service&#034;, node_customer_service)<br \/>\n    builder.add_edge(START, &#034;customer_service&#034;)<br \/>\n    builder.add_edge(&#034;customer_service&#034;, END)<br \/>\n    graph &#061; builder.compile()<\/p>\n<p>    my_llm &#061; MockLLM()<br \/>\n    my_db &#061; MockDatabase()<\/p>\n<p>    initial_state &#061; {&#034;query&#034;: &#034;\u5982\u4f55\u5347\u7ea7\u4f1a\u5458&#xff1f;&#034;}<br \/>\n    config &#061; {&#034;configurable&#034;: {&#034;user_id&#034;: &#034;vip_user_999&#034;}}<br \/>\n    context &#061; {&#034;llm&#034;: my_llm, &#034;db&#034;: my_db}<\/p>\n<p>    print(&#034;[System] \u5f00\u59cb\u8fd0\u884c\u56fe&#xff0c;\u5e76\u6ce8\u5165\u4f9d\u8d56\u5bf9\u8c61&#8230;&#034;)<br \/>\n    result &#061; graph.invoke(initial_state, config&#061;config, context&#061;context)<br \/>\n    print(result)<\/p>\n<p>\u6ce8\u610f\u6700\u540e\u4e00\u884c graph.invoke(initial_state, config&#061;config, context&#061;context)\u2014\u2014context \u5c31\u662f&#034;\u5916\u6302\u4f9d\u8d56\u5305&#034;&#xff0c;\u8282\u70b9\u91cc\u901a\u8fc7 runtime.context \u53d6\u7528\u3002\u8fd9\u4e2a\u6a21\u5f0f\u5728\u771f\u5b9e\u9879\u76ee\u91cc\u975e\u5e38\u63a8\u8350&#xff1a;\u6570\u636e\u5e93\u8fde\u63a5\u3001HTTP \u5ba2\u6237\u7aef\u3001\u914d\u7f6e\u5bf9\u8c61\u90fd\u8d70\u8fd9\u6761\u8def&#xff0c;\u8282\u70b9\u51fd\u6570\u5c31\u6210\u4e86\u7eaf\u903b\u8f91&#xff0c;\u597d\u6d4b\u3001\u597d\u6362\u3002<\/p>\n<h4>10.2 \u8282\u70b9\u8f93\u51fa&#xff1a;\u53ea\u80fd\u8fd4\u56de&#034;\u589e\u91cf&#034;&#xff0c;\u5343\u4e07\u522b\u8fd4\u56de\u6574\u4e2a state<\/h4>\n<p>\u8fd9\u662f\u65b0\u624b\u6700\u5bb9\u6613\u72af\u7684\u9519&#xff0c;\u800c\u4e14\u62a5\u9519\u4fe1\u606f\u4e0d\u4e00\u5b9a\u76f4\u89c2&#xff0c;\u503c\u5f97\u5355\u72ec\u7528\u4e00\u8282\u8bb2\u3002<\/p>\n<p>\u89c4\u5219&#xff1a;\u8282\u70b9\u7684\u8fd4\u56de\u503c\u8868\u793a&#034;\u672c\u8282\u70b9\u5bf9\u72b6\u6001\u7684\u589e\u91cf\u4fee\u6539&#034;&#xff0c;\u4e0d\u80fd\u628a\u6536\u5230\u7684\u6574\u4e2a state \u539f\u6837\u8fd4\u56de\u3002<\/p>\n<p>\u4e3a\u4ec0\u4e48&#xff1f;\u56e0\u4e3a LangGraph \u4f1a\u628a\u6bcf\u4e2a\u8282\u70b9\u7684\u8fd4\u56de\u503c\u5f53\u4f5c\u589e\u91cf&#xff0c;\u53bb\u548c\u5168\u5c40\u72b6\u6001\u505a\u4e00\u6b21\u5408\u5e76\u3002\u5982\u679c\u4f60\u8fd4\u56de\u4e86\u6574\u4e2a state&#xff1a;<\/p>\n<ul>\n<li>\u90a3\u4e9b\u6ca1\u6709\u914d Reducer \u7684\u952e&#xff0c;LangGraph \u4e0d\u77e5\u9053\u8be5\u4ee5\u8c01\u4e3a\u51c6&#xff0c;\u4f1a\u76f4\u63a5\u629b\u5f02\u5e38&#xff1b;<\/li>\n<li>\u90a3\u4e9b\u914d\u4e86 Reducer \u7684\u952e&#xff0c;\u56e0\u4e3a\u4f60\u628a\u6ca1\u6539\u52a8\u7684\u65e7\u503c\u4e5f\u4e00\u8d77\u8fd4\u56de\u4e86&#xff0c;\u5408\u5e76\u540e\u53ef\u80fd\u4ea7\u751f\u91cd\u590d\u6570\u636e&#xff08;\u6bd4\u5982\u6d88\u606f\u88ab\u590d\u5236\u4e00\u904d&#xff09;\u3002<\/li>\n<\/ul>\n<p>\u4e0b\u9762\u5c31\u662f\u9519\u8bef\u793a\u8303&#xff1a;<\/p>\n<p>from typing import TypedDict<br \/>\nfrom langgraph.constants import START, END<br \/>\nfrom langgraph.graph import StateGraph<\/p>\n<p>class MyState(TypedDict):<br \/>\n    query: str<br \/>\n    file_result: str<br \/>\n    web_result: str<br \/>\n    final_answer: str<\/p>\n<p>def query_web(state: MyState) -&gt; dict:<br \/>\n    # \u9519\u8bef\u6f14\u793a&#xff1a;\u76f4\u63a5 return \u6574\u4e2a state&#xff0c;\u800c\u4e0d\u662f\u5f53\u524d\u8282\u70b9\u589e\u91cf\u4fee\u6539\u7684\u90e8\u5206<br \/>\n    query &#061; state[&#034;query&#034;]<br \/>\n    state[&#034;web_result&#034;] &#061; f&#034;{query}\u7684\u7f51\u7edc\u641c\u7d22\u7ed3\u679c&#034;<br \/>\n    return state          # &lt;&#8211; \u8fd9\u91cc\u9519\u4e86<\/p>\n<p>def query_file(state: MyState) -&gt; dict:<br \/>\n    query &#061; state[&#034;query&#034;]<br \/>\n    state[&#034;file_result&#034;] &#061; f&#034;{query}\u7684\u6587\u4ef6\u641c\u7d22\u7ed3\u679c&#034;<br \/>\n    return state          # &lt;&#8211; \u8fd9\u91cc\u9519\u4e86<\/p>\n<p>def answer(state: MyState) -&gt; dict:<br \/>\n    web_result &#061; state[&#034;web_result&#034;]<br \/>\n    file_result &#061; state[&#034;file_result&#034;]<br \/>\n    state[&#034;final_answer&#034;] &#061; f&#034;LLM\u57fa\u4e8e{web_result}&#xff0c;{file_result} \u7684\u6700\u7ec8\u7ed3\u679c&#034;<br \/>\n    return state          # &lt;&#8211; \u8fd9\u91cc\u9519\u4e86<\/p>\n<p>graph &#061; StateGraph(state_schema&#061;MyState)<br \/>\ngraph.add_node(answer)<br \/>\ngraph.add_node(query_web)<br \/>\ngraph.add_node(query_file)<br \/>\ngraph.add_edge(START, &#034;query_web&#034;)<br \/>\ngraph.add_edge(START, &#034;query_file&#034;)<br \/>\ngraph.add_edge(&#034;query_web&#034;, &#034;answer&#034;)<br \/>\ngraph.add_edge(&#034;query_file&#034;, &#034;answer&#034;)<\/p>\n<p>compiled_graph &#061; graph.compile()<br \/>\nres &#061; compiled_graph.invoke({&#034;query&#034;: &#034;\u4ec0\u4e48\u662fLanggraph&#034;})<br \/>\nprint(res[&#034;final_answer&#034;])<\/p>\n<p>\u6b63\u786e\u5199\u6cd5\u53ea\u6709\u4e00\u884c\u4e4b\u5dee&#xff1a;return {&#034;web_result&#034;: &#8230;}&#xff0c;\u53ea\u5199\u4f60\u6539\u52a8\u7684\u90a3\u4e2a\u952e\u3002<\/p>\n<h4>10.3 START \u548c END&#xff1a;\u4e24\u4e2a\u865a\u62df\u8282\u70b9<\/h4>\n<p>\u5b83\u4eec\u672c\u8d28\u4e0a\u5c31\u662f\u4e24\u4e2a\u5b57\u7b26\u4e32&#xff0c;\u6e90\u7801\u91cc\u5199\u5f97\u5f88\u6e05\u695a&#xff1a;<\/p>\n<p>END &#061; sys.intern(&#034;__end__&#034;)<br \/>\n&#034;&#034;&#034;The last (maybe virtual) node in graph-style Pregel.&#034;&#034;&#034;<\/p>\n<p>START &#061; sys.intern(&#034;__start__&#034;)<br \/>\n&#034;&#034;&#034;The first (maybe virtual) node in graph-style Pregel.&#034;&#034;&#034;<\/p>\n<ul>\n<li>START \u4ee3\u8868&#034;\u628a\u7528\u6237\u8f93\u5165\u9001\u8fdb\u56fe\u91cc\u7684\u90a3\u4e2a\u70b9&#034;\u3002\u5f15\u7528\u5b83\u7684\u76ee\u7684\u662f\u58f0\u660e\u54ea\u4e9b\u8282\u70b9\u662f\u5165\u53e3\u3002\u5982\u679c\u4f60\u5199\u4e86\u591a\u6761 add_edge(START, &#8230;)&#xff0c;\u8fd9\u4e9b\u8282\u70b9\u5c31\u4f1a\u5e76\u884c\u5f00\u59cb\u3002<\/li>\n<li>END \u4ee3\u8868\u7ec8\u6b62\u3002\u54ea\u6761\u8fb9\u6307\u5411\u5b83&#xff0c;\u5c31\u8868\u793a\u90a3\u6761\u8def\u8d70\u5230\u5934\u4e86&#xff0c;\u540e\u9762\u6ca1\u6709\u52a8\u4f5c\u3002<\/li>\n<\/ul>\n<p>\u4e00\u4e2a\u5c0f\u7ec6\u8282&#xff1a;START \u8fd9\u4e2a&#034;\u7279\u6b8a\u8282\u70b9&#034;\u6267\u884c\u5b8c\u4e4b\u540e&#xff0c;\u4e5f\u4f1a\u4ea7\u751f\u4e00\u4e2a checkpoint\u3002\u6240\u4ee5\u4f60\u5728\u5386\u53f2\u5feb\u7167\u91cc\u5f80\u5f80\u4f1a\u770b\u5230\u7b2c\u4e00\u6b65\u7684 values \u662f\u7a7a\u7684\u2014\u2014\u90a3\u5c31\u662f START \u7559\u4e0b\u7684\u3002<\/p>\n<h4>10.4 \u8282\u70b9\u7f13\u5b58&#xff1a;\u540c\u6837\u7684\u8f93\u5165&#xff0c;\u522b\u7b97\u7b2c\u4e8c\u904d<\/h4>\n<p>\u6709\u4e9b\u8282\u70b9\u5f88\u8d35&#xff1a;\u8c03\u4e00\u6b21\u5927\u6a21\u578b\u51e0\u6bdb\u94b1&#xff0c;\u8dd1\u4e00\u6b21\u590d\u6742\u8ba1\u7b97\u8981 5 \u79d2\u3002\u5982\u679c\u8f93\u5165\u6ca1\u53d8&#xff0c;\u7ed3\u679c\u5e94\u8be5\u76f4\u63a5\u590d\u7528\u3002LangGraph \u652f\u6301\u6309\u8282\u70b9\u8f93\u5165\u505a\u7f13\u5b58\u3002<\/p>\n<p>\u4e24\u6b65\u641e\u5b9a&#xff1a;<\/p>\n<li>\u7f16\u8bd1\u65f6\u6307\u5b9a\u7f13\u5b58\u540e\u7aef&#xff08;langgraph.cache \u5305\u91cc\u6709\u5185\u5b58\u3001Redis\u3001SQLite \u7b49\u5b9e\u73b0&#xff09;&#xff1b;<\/li>\n<li>\u6dfb\u52a0\u8282\u70b9\u65f6\u6307\u5b9a\u7f13\u5b58\u7b56\u7565 CachePolicy\u3002<\/li>\n<p>CachePolicy \u6709\u4e24\u4e2a\u53c2\u6570&#xff1a;<\/p>\n<ul>\n<li>key_func&#xff1a;\u600e\u4e48\u6839\u636e\u8f93\u5165\u751f\u6210\u7f13\u5b58\u952e\u3002\u9ed8\u8ba4\u5bf9\u8f93\u5165\u505a pickle \u518d hash&#xff1b;<\/li>\n<li>ttl&#xff1a;\u7f13\u5b58\u6d3b\u591a\u4e45&#xff08;\u79d2&#xff09;\u3002\u4e0d\u5199\u5c31\u6c38\u4e0d\u8fc7\u671f\u3002<\/li>\n<\/ul>\n<p>import time<br \/>\nfrom typing_extensions import TypedDict<br \/>\nfrom langgraph.graph import StateGraph<br \/>\nfrom langgraph.cache.memory import InMemoryCache<br \/>\nfrom langgraph.types import CachePolicy<br \/>\nfrom langgraph.constants import START<br \/>\nfrom langgraph.checkpoint.memory import InMemorySaver<\/p>\n<p>class State(TypedDict):<br \/>\n    x: int<br \/>\n    result: int<\/p>\n<p>builder &#061; StateGraph(State)<br \/>\ncheckpointer &#061; InMemorySaver()<\/p>\n<p># 1\u3001\u5b9a\u4e49\u8282\u70b9&#xff1a;\u6a21\u62df\u6709\u8017\u65f6\u7684\u8ba1\u7b97<br \/>\ndef expensive_node(state: State) -&gt; dict:<br \/>\n    print(&#034;expensive_node \u88ab\u8c03\u7528&#034;)<br \/>\n    time.sleep(5)<br \/>\n    print(&#034;expensive_node \u8ba1\u7b97\u5b8c\u6210&#034;)<br \/>\n    return {&#034;result&#034;: state[&#034;x&#034;] * 2}<\/p>\n<p># 2\u3001\u6dfb\u52a0\u8282\u70b9\u65f6\u914d\u7f6e\u7f13\u5b58\u7b56\u7565&#xff1a;\u7f13\u5b58 10 \u79d2<br \/>\nbuilder.add_node(&#034;expensive_node&#034;, expensive_node, cache_policy&#061;CachePolicy(ttl&#061;10))<br \/>\nbuilder.add_edge(START, &#034;expensive_node&#034;)<\/p>\n<p># 3\u3001\u7f16\u8bd1\u65f6\u4f20\u5165\u7f13\u5b58\u5668<br \/>\ngraph &#061; builder.compile(cache&#061;InMemoryCache(), checkpointer&#061;checkpointer)<\/p>\n<p># 4\u3001\u7b2c\u4e00\u6b21\u8c03\u7528&#xff0c;x&#061;5&#xff0c;\u4f1a\u771f\u7684\u7b97 5 \u79d2<br \/>\nprint(graph.invoke({&#034;x&#034;: 5}, config&#061;{&#034;configurable&#034;: {&#034;thread_id&#034;: &#034;1&#034;}}))<\/p>\n<p># 5\u3001\u7b2c\u4e8c\u6b21\u8c03\u7528&#xff0c;x \u8fd8\u662f 5&#xff0c;10 \u79d2\u5185 &#061;&gt; \u76f4\u63a5\u547d\u4e2d\u7f13\u5b58&#xff0c;\u79d2\u56de<br \/>\nprint(graph.invoke({&#034;x&#034;: 5}, config&#061;{&#034;configurable&#034;: {&#034;thread_id&#034;: &#034;2&#034;}}))<\/p>\n<p>\u8dd1\u4e00\u4e0b\u4f60\u80fd\u660e\u663e\u611f\u89c9\u5230&#xff1a;\u7b2c\u4e8c\u6b21\u51e0\u4e4e\u662f\u77ac\u95f4\u8fd4\u56de\u7684\u3002\u6ce8\u610f\u8fd9\u91cc\u7528\u4e86\u4e0d\u540c\u7684 thread_id&#xff0c;\u8bf4\u660e\u7f13\u5b58\u662f\u8de8\u4f1a\u8bdd\u5171\u4eab\u7684&#xff08;\u56e0\u4e3a\u5b83\u53ea\u4f9d\u8d56\u8f93\u5165&#xff0c;\u4e0d\u4f9d\u8d56\u4f1a\u8bdd&#xff09;\u3002<\/p>\n<h4>10.5 \u8282\u70b9\u91cd\u8bd5&#xff1a;\u8c03 API\u3001\u8c03\u6a21\u578b\u5fc5\u5907<\/h4>\n<p>\u8c03\u5916\u90e8\u63a5\u53e3\u603b\u4f1a\u5076\u53d1\u5931\u8d25&#xff1a;\u7f51\u7edc\u6296\u4e00\u4e0b\u3001\u9650\u6d41\u3001\u8d85\u65f6\u3002\u7ed9\u8282\u70b9\u914d\u4e00\u4e2a\u91cd\u8bd5\u7b56\u7565&#xff0c;\u6bd4\u81ea\u5df1\u5728\u51fd\u6570\u91cc\u5199 for i in range(3) \u4f18\u96c5\u5f97\u591a\u3002<\/p>\n<p>\u5728 add_node \u65f6\u4f20 retry_policy&#xff0c;\u5b83\u63a5\u53d7\u4e00\u4e2a RetryPolicy \u5bf9\u8c61&#xff0c;\u4e24\u4e2a\u5173\u952e\u5c5e\u6027&#xff1a;<\/p>\n<ul>\n<li>max_attempts&#xff1a;\u6700\u591a\u5c1d\u8bd5\u51e0\u6b21&#xff1b;<\/li>\n<li>retry_on&#xff1a;\u9047\u5230\u54ea\u4e9b\u5f02\u5e38\u7c7b\u578b\u624d\u91cd\u8bd5\u3002<\/li>\n<\/ul>\n<p>from typing import Dict, Any<br \/>\nfrom typing_extensions import TypedDict<br \/>\nfrom langgraph.graph import StateGraph, START, END<br \/>\nfrom langgraph.types import RetryPolicy<\/p>\n<p>class State(TypedDict):<br \/>\n    result: str<\/p>\n<p>attempt_counter &#061; 0<\/p>\n<p>def unstable_api_call(state: State) -&gt; Dict[str, Any]:<br \/>\n    &#034;&#034;&#034;\u6a21\u62df\u4e00\u4e2a\u4e0d\u7a33\u5b9a\u7684 API \u8c03\u7528&#xff0c;\u524d\u4e24\u6b21\u5931\u8d25&#xff0c;\u7b2c\u4e09\u6b21\u6210\u529f&#034;&#034;&#034;<br \/>\n    global attempt_counter<br \/>\n    attempt_counter &#043;&#061; 1<br \/>\n    print(f&#034;\u5c1d\u8bd5\u8c03\u7528API&#xff0c;\u8fd9\u662f\u7b2c {attempt_counter} \u6b21\u5c1d\u8bd5&#034;)<\/p>\n<p>    if attempt_counter &lt; 3:<br \/>\n        raise Exception(f&#034;\u6a21\u62dfAPI\u8c03\u7528\u5931\u8d25 (\u5c1d\u8bd5 {attempt_counter})&#034;)<br \/>\n    else:<br \/>\n        return {&#034;result&#034;: f&#034;API\u8c03\u7528\u6210\u529f&#xff0c;\u7ecf\u8fc7 {attempt_counter} \u6b21\u5c1d\u8bd5&#034;}<\/p>\n<p>def value_error_call(state: State) -&gt; Dict[str, Any]:<br \/>\n    &#034;&#034;&#034;\u629b\u51fa ValueError&#xff0c;\u9ed8\u8ba4\u7b56\u7565\u4e0d\u4f1a\u91cd\u8bd5\u5b83&#034;&#034;&#034;<br \/>\n    print(&#034;\u8c03\u7528\u4f1a\u629b\u51fa ValueError \u7684\u8282\u70b9&#034;)<br \/>\n    raise ValueError(&#034;\u6a21\u62df ValueError \u5f02\u5e38&#034;)<\/p>\n<p>def run_demo():<br \/>\n    global attempt_counter<\/p>\n<p>    # \u6f14\u793a1&#xff1a;\u9ed8\u8ba4\u91cd\u8bd5\u7b56\u7565<br \/>\n    attempt_counter &#061; 0<br \/>\n    builder1 &#061; StateGraph(State)<br \/>\n    builder1.add_node(<br \/>\n        &#034;unstable_call&#034;,<br \/>\n        unstable_api_call,<br \/>\n        retry_policy&#061;RetryPolicy(max_attempts&#061;5),<br \/>\n    )<br \/>\n    builder1.add_edge(START, &#034;unstable_call&#034;)<br \/>\n    builder1.add_edge(&#034;unstable_call&#034;, END)<br \/>\n    graph1 &#061; builder1.compile()<\/p>\n<p>    try:<br \/>\n        print(&#034;\u6700\u7ec8\u7ed3\u679c:&#034;, graph1.invoke({&#034;result&#034;: &#034;&#034;}))<br \/>\n    except Exception as e:<br \/>\n        print(f&#034;\u6700\u7ec8\u5931\u8d25: {type(e).__name__}: {e}&#034;)<\/p>\n<p>    # \u6f14\u793a2&#xff1a;\u4e0d\u4f1a\u88ab\u91cd\u8bd5\u7684\u5f02\u5e38<br \/>\n    builder3 &#061; StateGraph(State)<br \/>\n    builder3.add_node(<br \/>\n        &#034;value_error_call&#034;,<br \/>\n        value_error_call,<br \/>\n        retry_policy&#061;RetryPolicy(max_attempts&#061;3),<br \/>\n    )<br \/>\n    builder3.add_edge(START, &#034;value_error_call&#034;)<br \/>\n    builder3.add_edge(&#034;value_error_call&#034;, END)<br \/>\n    graph3 &#061; builder3.compile()<\/p>\n<p>    try:<br \/>\n        print(&#034;\u6700\u7ec8\u7ed3\u679c:&#034;, graph3.invoke({&#034;result&#034;: &#034;&#034;}))<br \/>\n    except Exception as e:<br \/>\n        print(f&#034;\u6700\u7ec8\u5931\u8d25: {type(e).__name__}: {e}&#034;)<\/p>\n<p>\u91cd\u70b9&#xff1a;\u9ed8\u8ba4\u7b56\u7565\u5e76\u4e0d\u4f1a\u91cd\u8bd5\u6240\u6709\u5f02\u5e38\u3002 \u4e0b\u9762\u8fd9\u4e9b&#034;\u660e\u663e\u662f\u4ee3\u7801\u5199\u9519\u4e86&#034;\u7684\u5f02\u5e38&#xff0c;\u91cd\u8bd5\u4e00\u4e07\u6b21\u4e5f\u6ca1\u7528&#xff0c;\u6240\u4ee5\u9ed8\u8ba4\u8df3\u8fc7&#xff1a;<\/p>\n<p>ValueError\u3001TypeError\u3001ArithmeticError\u3001ImportError\u3001LookupError\u3001NameError\u3001SyntaxError\u3001RuntimeError\u3001ReferenceError\u3001StopIteration\u3001StopAsyncIteration\u3001OSError\u3002<\/p>\n<p>\u6240\u4ee5\u6f14\u793a 2 \u91cc&#xff0c;ValueError \u53ea\u4f1a\u6267\u884c\u4e00\u6b21\u5c31\u5931\u8d25\u9000\u51fa&#xff0c;\u4e0d\u4f1a\u5c1d\u8bd5 3 \u6b21\u3002\u53cd\u8fc7\u6765&#xff0c;\u5982\u679c\u4f60\u60f3\u8ba9\u67d0\u4e2a\u5f02\u5e38\u91cd\u8bd5&#xff08;\u6bd4\u5982\u81ea\u5b9a\u4e49\u7684 RateLimitError&#xff09;&#xff0c;\u5c31\u5728 retry_on \u91cc\u663e\u5f0f\u6307\u5b9a\u3002<\/p>\n<h3>\u5341\u4e00\u3001\u56fe\u5185\u5916\u6570\u636e\u4f20\u9012&#xff1a;\u6d41\u5f0f\u8f93\u51fa\u516d\u79cd\u6a21\u5f0f<\/h3>\n<h4>11.1 \u4e3a\u4ec0\u4e48\u9700\u8981\u6d41\u5f0f<\/h4>\n<p>\u9ed8\u8ba4\u60c5\u51b5\u4e0b&#xff0c;graph.invoke \u8981\u7b49\u6574\u5f20\u56fe\u8dd1\u5b8c\u624d\u8fd4\u56de\u3002\u5bf9 Agent \u6765\u8bf4\u8fd9\u4f53\u9a8c\u5f88\u7cdf&#xff1a;<\/p>\n<ul>\n<li>\u6a21\u578b\u6b63\u5728\u9010\u5b57\u751f\u6210\u7b54\u6848&#xff0c;\u7528\u6237\u5374\u76ef\u7740\u8f6c\u5708\u5708\u7b49 10 \u79d2&#xff1b;<\/li>\n<li>\u6d41\u7a0b\u5f88\u957f&#xff0c;\u7528\u6237\u4e0d\u77e5\u9053\u73b0\u5728\u8dd1\u5230\u54ea\u4e00\u6b65\u4e86\u3002<\/li>\n<\/ul>\n<p>\u597d\u5728 LangGraph \u5b9e\u73b0\u4e86 langchain_core \u7684 Runnable \u63a5\u53e3&#xff0c;\u6240\u4ee5\u81ea\u5e26 stream \/ astream \u65b9\u6cd5&#xff0c;\u53ef\u4ee5\u8fb9\u8dd1\u8fb9\u628a\u5185\u90e8\u6570\u636e\u5410\u51fa\u6765\u3002<\/p>\n<h4>11.2 \u516d\u79cd\u6a21\u5f0f\u5bf9\u7167\u8868<\/h4>\n<table>\n<tr>\u6a21\u5f0f\u8f93\u51fa\u4ec0\u4e48\u5178\u578b\u7528\u9014<\/tr>\n<tbody>\n<tr>\n<td>values<\/td>\n<td>\u6bcf\u4e00\u6b65\u6267\u884c\u540e\u7684\u5b8c\u6574\u72b6\u6001<\/td>\n<td>\u60f3\u770b\u6574\u4f53\u72b6\u6001\u5982\u4f55\u6f14\u8fdb<\/td>\n<\/tr>\n<tr>\n<td>updates<\/td>\n<td>\u6bcf\u4e00\u6b65\u7684\u589e\u91cf\u66f4\u65b0&#xff1b;\u540c\u4e00\u6b65\u5185\u591a\u4e2a\u66f4\u65b0\u4f1a\u5206\u522b\u8f93\u51fa<\/td>\n<td>\u5c55\u793a&#034;\u5f53\u524d\u5904\u7406\u5230\u54ea\u4e2a\u8282\u70b9&#034;<\/td>\n<\/tr>\n<tr>\n<td>custom<\/td>\n<td>\u8282\u70b9\u5185\u90e8\u7528 writer() \u53d1\u51fa\u7684\u81ea\u5b9a\u4e49\u6570\u636e<\/td>\n<td>\u5c55\u793a\u8fdb\u5ea6\u63d0\u793a\u3001\u601d\u8003\u8fc7\u7a0b<\/td>\n<\/tr>\n<tr>\n<td>messages<\/td>\n<td>\u6240\u6709\u8c03\u7528\u4e86 LLM \u7684\u8282\u70b9&#xff0c;\u6d41\u5f0f\u8f93\u51fa (LLM Token, metadata) \u4e8c\u5143\u7ec4<\/td>\n<td>\u6253\u5b57\u673a\u6548\u679c<\/td>\n<\/tr>\n<tr>\n<td>debug<\/td>\n<td>\u6240\u6709\u80fd\u8f93\u51fa\u7684\u4fe1\u606f&#xff08;\u4efb\u52a1\u8c03\u5ea6\u3001\u8f93\u5165\u8f93\u51fa\u7b49&#xff09;<\/td>\n<td>\u6392\u67e5&#034;\u4e3a\u4ec0\u4e48\u6ca1\u8d70\u8fd9\u6761\u8def&#034;<\/td>\n<\/tr>\n<tr>\n<td>\u6df7\u5408\u6a21\u5f0f<\/td>\n<td>\u4f20\u4e00\u4e2a\u5217\u8868&#xff0c;\u540c\u65f6\u62ff\u591a\u79cd\u6d41<\/td>\n<td>\u751f\u4ea7\u524d\u7aef\u6700\u5e38\u7528<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>11.3 \u5b8c\u6574\u6f14\u793a<\/h4>\n<p>import time<br \/>\nfrom typing import TypedDict, Annotated, List<br \/>\nimport operator<br \/>\nfrom langchain_core.messages import BaseMessage, HumanMessage<br \/>\nfrom langchain_openai import ChatOpenAI<br \/>\nfrom langgraph.graph import StateGraph, START, END<br \/>\nfrom langgraph.runtime import Runtime<\/p>\n<p>llm &#061; ChatOpenAI(model&#061;&#034;gpt-4o-mini&#034;)<\/p>\n<p># &#8212; 1. \u5b9a\u4e49\u72b6\u6001 &#8212;<br \/>\nclass State(TypedDict):<br \/>\n    messages: Annotated[List[BaseMessage], operator.add]<br \/>\n    current_step: str<\/p>\n<p># &#8212; 2. \u5b9a\u4e49\u8282\u70b9 &#8212;<br \/>\ndef node_input(state: State):<br \/>\n    &#034;&#034;&#034;\u6a21\u62df\u63a5\u6536\u7528\u6237\u8f93\u5165&#034;&#034;&#034;<br \/>\n    return {<br \/>\n        &#034;messages&#034;: [HumanMessage(content&#061;&#034;\u8bf7\u5e2e\u6211\u5199\u4e00\u6bb5Python\u4ee3\u7801&#034;)],<br \/>\n        &#034;current_step&#034;: &#034;input_received&#034;,<br \/>\n    }<\/p>\n<p>def node_processing(state: State, runtime: Runtime):<br \/>\n    &#034;&#034;&#034;\u4e2d\u95f4\u5904\u7406\u8fc7\u7a0b&#xff0c;\u7528 writer \u8f93\u51fa\u81ea\u5b9a\u4e49\u6d41\u5f0f\u6570\u636e&#xff08;\u5bf9\u5e94 custom \u6a21\u5f0f&#xff09;&#034;&#034;&#034;<br \/>\n    steps &#061; [&#034;\u6b63\u5728\u5206\u6790\u610f\u56fe&#8230;&#034;, &#034;\u6b63\u5728\u68c0\u7d22\u77e5\u8bc6\u5e93&#8230;&#034;, &#034;\u6b63\u5728\u6784\u5efaPrompt&#8230;&#034;]<br \/>\n    writer &#061; runtime.stream_writer<br \/>\n    for i, step in enumerate(steps):<br \/>\n        time.sleep(0.5)<br \/>\n        writer({<br \/>\n            &#034;step_index&#034;: i &#043; 1,<br \/>\n            &#034;description&#034;: step,<br \/>\n            &#034;timestamp&#034;: time.time(),<br \/>\n        })<br \/>\n    return {&#034;current_step&#034;: &#034;processing_complete&#034;}<\/p>\n<p>def node_generation(state: State):<br \/>\n    &#034;&#034;&#034;LLM \u751f\u6210&#xff1b;messages \u6a21\u5f0f\u4f1a\u81ea\u52a8\u6355\u83b7\u5b83\u7684\u6d41\u5f0f\u8f93\u51fa&#034;&#034;&#034;<br \/>\n    response &#061; llm.invoke(state[&#034;messages&#034;])<br \/>\n    return {&#034;messages&#034;: [response], &#034;current_step&#034;: &#034;generation_complete&#034;}<\/p>\n<p># &#8212; 3. \u6784\u5efa\u56fe &#8212;<br \/>\nbuilder &#061; StateGraph(State)<br \/>\nbuilder.add_node(&#034;input&#034;, node_input)<br \/>\nbuilder.add_node(&#034;process&#034;, node_processing)<br \/>\nbuilder.add_node(&#034;generate&#034;, node_generation)<br \/>\nbuilder.add_edge(START, &#034;input&#034;)<br \/>\nbuilder.add_edge(&#034;input&#034;, &#034;process&#034;)<br \/>\nbuilder.add_edge(&#034;process&#034;, &#034;generate&#034;)<br \/>\nbuilder.add_edge(&#034;generate&#034;, END)<br \/>\ngraph &#061; builder.compile()<\/p>\n<p># &#8212; 4. \u6f14\u793a\u4e0d\u540c\u6a21\u5f0f &#8212;<br \/>\ndef run_demo():<br \/>\n    initial_state &#061; {&#034;messages&#034;: [], &#034;current_step&#034;: &#034;start&#034;}<\/p>\n<p>    print(&#034;\\\\n&#061;&#061;&#061;&#061;&#061; 1. Mode: values&#xff08;\u5b8c\u6574\u72b6\u6001&#xff09;&#061;&#061;&#061;&#061;&#061;&#034;)<br \/>\n    for event in graph.stream(initial_state, stream_mode&#061;&#034;values&#034;):<br \/>\n        print(f&#034;State: keys&#061;{list(event.keys())}, step&#061;{event.get(&#039;current_step&#039;)}&#034;)<\/p>\n<p>    print(&#034;\\\\n&#061;&#061;&#061;&#061;&#061; 2. Mode: updates&#xff08;\u589e\u91cf\u66f4\u65b0&#xff09;&#061;&#061;&#061;&#061;&#061;&#034;)<br \/>\n    for event in graph.stream(initial_state, stream_mode&#061;&#034;updates&#034;):<br \/>\n        print(f&#034;Update: {event}&#034;)<\/p>\n<p>    print(&#034;\\\\n&#061;&#061;&#061;&#061;&#061; 3. Mode: custom&#xff08;\u8282\u70b9\u5185\u81ea\u5b9a\u4e49\u6570\u636e&#xff09;&#061;&#061;&#061;&#061;&#061;&#034;)<br \/>\n    for event in graph.stream(initial_state, stream_mode&#061;&#034;custom&#034;):<br \/>\n        print(f&#034;Custom Data: {event}&#034;)<\/p>\n<p>    print(&#034;\\\\n&#061;&#061;&#061;&#061;&#061; 4. Mode: messages&#xff08;LLM Token&#xff09;&#061;&#061;&#061;&#061;&#061;&#034;)<br \/>\n    for chunk, metadata in graph.stream(initial_state, stream_mode&#061;&#034;messages&#034;):<br \/>\n        node_name &#061; metadata.get(&#034;langgraph_node&#034;, &#034;unknown&#034;)<br \/>\n        print(f&#034;[{node_name}] Token: {chunk.content!r}&#034;)<\/p>\n<p>    print(&#034;\\\\n&#061;&#061;&#061;&#061;&#061; 5. Mode: debug&#xff08;\u8c03\u8bd5&#xff09;&#061;&#061;&#061;&#061;&#061;&#034;)<br \/>\n    count &#061; 0<br \/>\n    for event in graph.stream(initial_state, stream_mode&#061;&#034;debug&#034;):<br \/>\n        if count &lt; 3:<br \/>\n            print(f&#034;Debug Event: {event[&#039;type&#039;]} &#8211; {event.get(&#039;payload&#039;, {}).get(&#039;name&#039;)}&#034;)<br \/>\n        count &#043;&#061; 1<br \/>\n    print(&#034;&#8230; (\u7701\u7565\u540e\u7eed debug \u4fe1\u606f)&#034;)<\/p>\n<p>    print(&#034;\\\\n&#061;&#061;&#061;&#061;&#061; 6. Mixed Mode&#xff08;\u6df7\u5408\u6a21\u5f0f&#xff09;&#061;&#061;&#061;&#061;&#061;&#034;)<br \/>\n    for mode, data in graph.stream(initial_state, stream_mode&#061;[&#034;updates&#034;, &#034;custom&#034;]):<br \/>\n        if mode &#061;&#061; &#034;updates&#034;:<br \/>\n            print(f&#034;[Updates] \u6765\u81ea\u8282\u70b9 {list(data.keys())[0]}&#034;)<br \/>\n        elif mode &#061;&#061; &#034;custom&#034;:<br \/>\n            print(f&#034;[Custom] {data[&#039;description&#039;]}&#034;)<\/p>\n<p>run_demo()<\/p>\n<p>\u600e\u4e48\u9009&#xff1f; \u4e00\u4e2a\u5b9e\u7528\u7684\u7ec4\u5408\u662f&#xff1a;\u524d\u7aef\u8981&#034;\u6253\u5b57\u673a\u6548\u679c &#043; \u5f53\u524d\u6b65\u9aa4\u63d0\u793a&#034;&#xff0c;\u5c31\u7528 stream_mode&#061;[&#034;messages&#034;, &#034;custom&#034;]&#xff1b;\u8981\u8c03\u8bd5&#034;\u4e3a\u4ec0\u4e48\u6ca1\u8d70\u90a3\u6761\u5206\u652f&#034;&#xff0c;\u4e34\u65f6\u6362\u6210 debug&#xff0c;\u4e00\u773c\u5c31\u80fd\u770b\u5230\u8def\u7531\u51fd\u6570\u7684\u8fd4\u56de\u503c\u3002<\/p>\n<h3>\u5341\u4e8c\u3001Human-in-the-Loop&#xff1a;\u8ba9\u7528\u6237\u53c2\u4e0e\u5173\u952e\u51b3\u7b56<\/h3>\n<h4>12.1 \u4e3a\u4ec0\u4e48\u9700\u8981\u4eba\u5de5\u5ba1\u6838<\/h4>\n<p>Agent \u518d\u806a\u660e&#xff0c;\u6709\u4e9b\u51b3\u5b9a\u4e5f\u4e0d\u8be5\u5b83\u81ea\u5df1\u62cd\u677f&#xff1a;\u8f6c\u8d26\u3001\u4e0b\u5355\u3001\u53d1\u516c\u544a\u3001\u6539\u751f\u4ea7\u6570\u636e\u5e93\u3002\u8fd9\u65f6\u5019\u9700\u8981&#034;\u8dd1\u5230\u4e00\u534a\u6682\u505c&#xff0c;\u7b49\u4eba\u786e\u8ba4&#xff0c;\u518d\u7ee7\u7eed&#034;\u3002<\/p>\n<p>LangGraph \u4e3a\u6b64\u63d0\u4f9b\u4e86\u4e00\u4e2a\u539f\u8bed&#xff1a;interrupt\u3002\u5b83\u53ef\u4ee5\u5728\u8282\u70b9\u5185\u90e8\u4efb\u610f\u4f4d\u7f6e\u63d2\u5165&#xff0c;\u6267\u884c\u5230\u90a3\u91cc\u5c31\u505c\u4e0b\u6765&#xff0c;\u540c\u65f6\u628a&#034;\u9700\u8981\u4eba\u770b\u7684\u6570\u636e&#034;\u5e26\u51fa\u56fe\u5916&#xff1b;\u7528\u6237\u5904\u7406\u5b8c\u4e4b\u540e&#xff0c;\u518d\u8ba9\u56fe\u7ee7\u7eed\u5f80\u4e0b\u8dd1\u3002<\/p>\n<h4>12.2 \u5b8c\u6574\u793a\u4f8b&#xff1a;\u8f6c\u8d26\u524d\u4eba\u5de5\u5ba1\u6838<\/h4>\n<p>&#034;&#034;&#034;<br \/>\nLangGraph interrupt \u6f14\u793a&#xff1a;\u8ba9\u7528\u6237\u53c2\u4e0e\u5173\u952e\u51b3\u7b56<br \/>\n\u573a\u666f&#xff1a;\u51c6\u5907\u6267\u884c\u4e00\u7b14&#034;\u8f6c\u8d26&#034;&#xff0c;\u5728\u771f\u6b63\u6267\u884c\u524d\u8ba9\u7528\u6237\u5ba1\u6838\/\u4fee\u6539\u8f6c\u8d26\u4fe1\u606f\u3002<br \/>\n&#034;&#034;&#034;<br \/>\nfrom __future__ import annotations<br \/>\nfrom typing import Any<br \/>\nfrom typing_extensions import TypedDict<br \/>\nfrom langgraph.checkpoint.memory import InMemorySaver<br \/>\nfrom langgraph.graph import END, START, StateGraph<br \/>\nfrom langgraph.types import Command, interrupt<\/p>\n<p>class TransferState(TypedDict):<br \/>\n    recipient: str<br \/>\n    amount: int<br \/>\n    memo: str<br \/>\n    approved: bool<br \/>\n    final_status: str<\/p>\n<p>def review_transfer(state: TransferState) -&gt; dict[str, Any]:<br \/>\n    print(&#034;\\\\n[Node] review_transfer&#xff1a;\u751f\u6210\u5f85\u6267\u884c\u7684\u8f6c\u8d26\u8bf7\u6c42&#034;)<br \/>\n    pending_transfer &#061; {<br \/>\n        &#034;recipient&#034;: state[&#034;recipient&#034;],<br \/>\n        &#034;amount&#034;: state[&#034;amount&#034;],<br \/>\n        &#034;memo&#034;: state[&#034;memo&#034;],<br \/>\n    }<\/p>\n<p>    # \u5173\u952e&#xff1a;\u6267\u884c\u5230\u8fd9\u91cc\u4f1a\u6682\u505c&#xff0c;payload \u88ab\u9001\u5230\u56fe\u5916<br \/>\n    user_review &#061; interrupt({<br \/>\n        &#034;title&#034;: &#034;\u8f6c\u8d26\u5ba1\u6838&#034;,<br \/>\n        &#034;pending_transfer&#034;: pending_transfer,<br \/>\n        &#034;instruction&#034;: &#034;\u8bf7\u8fd4\u56de bool(\u662f\u5426\u6279\u51c6) \u6216 dict(\u53ef\u6539 recipient\/amount\/memo&#xff0c;\u5e76\u5e26 approved \u5b57\u6bb5)\u3002&#034;,<br \/>\n    })<\/p>\n<p>    approved &#061; False<br \/>\n    updated_transfer &#061; dict(pending_transfer)<\/p>\n<p>    if isinstance(user_review, bool):<br \/>\n        approved &#061; user_review<br \/>\n    elif isinstance(user_review, dict):<br \/>\n        approved &#061; bool(user_review.get(&#034;approved&#034;, True))<br \/>\n        for k in (&#034;recipient&#034;, &#034;amount&#034;, &#034;memo&#034;):<br \/>\n            if k in user_review:<br \/>\n                updated_transfer[k] &#061; user_review[k]<\/p>\n<p>    print(f&#034;[Node] review_transfer&#xff1a;\u7528\u6237\u5ba1\u6838\u7ed3\u679c approved&#061;{approved}&#xff0c;transfer&#061;{updated_transfer}&#034;)<br \/>\n    return {<br \/>\n        &#034;approved&#034;: approved,<br \/>\n        &#034;recipient&#034;: updated_transfer[&#034;recipient&#034;],<br \/>\n        &#034;amount&#034;: updated_transfer[&#034;amount&#034;],<br \/>\n        &#034;memo&#034;: updated_transfer[&#034;memo&#034;],<br \/>\n    }<\/p>\n<p>def execute_transfer(state: TransferState) -&gt; dict[str, str]:<br \/>\n    if not state[&#034;approved&#034;]:<br \/>\n        print(&#034;\\\\n[Node] execute_transfer&#xff1a;\u7528\u6237\u672a\u6279\u51c6&#xff0c;\u53d6\u6d88\u8f6c\u8d26&#034;)<br \/>\n        return {&#034;final_status&#034;: &#034;\u5df2\u53d6\u6d88&#xff1a;\u7528\u6237\u672a\u6279\u51c6\u8f6c\u8d26&#034;}<\/p>\n<p>    print(&#034;\\\\n[Node] execute_transfer&#xff1a;\u6a21\u62df\u6267\u884c\u8f6c\u8d26&#034;)<br \/>\n    return {<br \/>\n        &#034;final_status&#034;: (<br \/>\n            f&#034;\u5df2\u8f6c\u8d26&#xff1a;\u6536\u6b3e\u4eba&#061;{state[&#039;recipient&#039;]}&#xff0c;&#034;<br \/>\n            f&#034;\u91d1\u989d&#061;{state[&#039;amount&#039;]}&#xff0c;\u5907\u6ce8&#061;{state[&#039;memo&#039;]}&#034;<br \/>\n        )<br \/>\n    }<\/p>\n<p>def build_graph():<br \/>\n    builder &#061; StateGraph(TransferState)<br \/>\n    builder.add_node(&#034;review_transfer&#034;, review_transfer)<br \/>\n    builder.add_node(&#034;execute_transfer&#034;, execute_transfer)<br \/>\n    builder.add_edge(START, &#034;review_transfer&#034;)<br \/>\n    builder.add_edge(&#034;review_transfer&#034;, &#034;execute_transfer&#034;)<br \/>\n    builder.add_edge(&#034;execute_transfer&#034;, END)<br \/>\n    return builder.compile(checkpointer&#061;InMemorySaver())<\/p>\n<p>def run_demo():<br \/>\n    graph &#061; build_graph()<br \/>\n    config &#061; {&#034;configurable&#034;: {&#034;thread_id&#034;: &#034;interrupt-demo-1&#034;}}<\/p>\n<p>    initial_state &#061; {<br \/>\n        &#034;recipient&#034;: &#034;Alice&#034;,<br \/>\n        &#034;amount&#034;: 100,<br \/>\n        &#034;memo&#034;: &#034;\u5348\u996dAA&#034;,<br \/>\n        &#034;approved&#034;: False,<br \/>\n        &#034;final_status&#034;: &#034;&#034;,<br \/>\n    }<\/p>\n<p>    # \u7b2c\u4e00\u6b21 invoke&#xff1a;\u4f1a\u505c\u5728 interrupt<br \/>\n    first &#061; graph.invoke(initial_state, config&#061;config)<br \/>\n    interrupt_payload &#061; first[&#034;__interrupt__&#034;][0].value<br \/>\n    print(&#034;\\\\n[System] \u56fe\u5df2\u6682\u505c&#xff0c;\u7b49\u5f85\u7528\u6237\u5ba1\u6838\u3002\u53ef\u7ed9\u7528\u6237\u5c55\u793a\u7684\u6570\u636e\u5982\u4e0b&#xff1a;&#034;)<br \/>\n    print(interrupt_payload)<\/p>\n<p>    # \u7528\u6237\u5ba1\u6838\u5b8c\u4e86&#xff0c;\u5e26\u7740\u51b3\u5b9a\u6062\u590d<br \/>\n    user_resume_value &#061; {&#034;approved&#034;: True, &#034;amount&#034;: 80, &#034;memo&#034;: &#034;\u6539\u4e3a80\u5143&#xff08;\u5b9e\u9645\u5e94\u4ed8&#xff09;&#034;}<br \/>\n    final &#061; graph.invoke(Command(resume&#061;user_resume_value), config&#061;config)<br \/>\n    print(&#034;\\\\n[System] \u5df2\u6062\u590d\u6267\u884c&#xff0c;\u6700\u7ec8\u7ed3\u679c&#xff1a;&#034;)<br \/>\n    print(final[&#034;final_status&#034;])<\/p>\n<p>run_demo()<\/p>\n<h4>12.3 \u4e09\u4e2a\u5fc5\u987b\u77e5\u9053\u7684\u7ec6\u8282<\/h4>\n<li>\u5fc5\u987b\u6709 checkpointer\u3002 \u56e0\u4e3a\u56fe\u8981&#034;\u6682\u505c&#034;&#xff0c;\u6682\u505c\u671f\u95f4\u72b6\u6001\u5f97\u5b58\u5728\u67d0\u4e2a\u5730\u65b9&#xff0c;\u6240\u4ee5\u4e0d\u6302 checkpointer \u7684\u56fe\u7528\u4e0d\u4e86 interrupt\u3002<\/li>\n<li>\u5fc5\u987b\u7528\u540c\u4e00\u4e2a thread_id \u6062\u590d\u3002 \u6362\u4e86 id&#xff0c;\u5c31\u627e\u4e0d\u5230\u521a\u624d\u90a3\u4efd\u73b0\u573a\u4e86\u3002<\/li>\n<li>\u6062\u590d\u65f6\u6574\u4e2a\u8282\u70b9\u51fd\u6570\u4f1a\u4ece\u5934\u91cd\u8dd1\u3002 \u8fd9\u662f\u6700\u5bb9\u6613\u51fa\u4e8b\u6545\u7684\u5730\u65b9\u3002\u4e5f\u5c31\u662f\u8bf4&#xff0c;review_transfer \u91cc interrupt \u4e4b\u524d\u7684\u90a3\u4e9b\u4ee3\u7801&#xff0c;\u4f1a\u518d\u6267\u884c\u4e00\u904d\u3002\u6240\u4ee5&#xff1a;\n<li>\u5982\u679c interrupt \u4e4b\u524d\u6709&#034;\u53d1\u77ed\u4fe1&#034;&#034;\u6263\u5e93\u5b58&#034;&#034;\u5199\u65e5\u5fd7&#034;\u8fd9\u7c7b\u526f\u4f5c\u7528\u64cd\u4f5c&#xff0c;\u4f1a\u9020\u6210\u91cd\u590d&#xff1b;<\/li>\n<li>\u89e3\u6cd5\u6709\u4e24\u4e2a&#xff1a;\u4fdd\u8bc1\u8fd9\u4e9b\u64cd\u4f5c\u5e42\u7b49&#xff0c;\u6216\u8005\u628a\u5b83\u4eec\u632a\u5230 interrupt \u4e4b\u540e\u7684\u72ec\u7acb\u8282\u70b9\u91cc\u3002<\/li>\n<\/li>\n<h3>\u5341\u4e09\u3001Edge&#xff1a;\u8fb9\u548c\u4e24\u79cd\u6d41\u8f6c\u65b9\u5f0f<\/h3>\n<h4>13.1 \u8fb9\u7684\u672c\u8d28<\/h4>\n<p>\u524d\u9762\u8bb2 Pregel \u65f6\u5df2\u7ecf\u57cb\u4e86\u4f0f\u7b14&#xff1a;\u5b9a\u4e49\u8fb9&#xff0c;\u672c\u8d28\u4e0a\u662f\u5728\u5b9a\u4e49&#034;\u8282\u70b9\u7684\u8ba2\u9605\u901a\u9053&#034;\u548c&#034;\u8282\u70b9\u6267\u884c\u540e\u8981\u66f4\u65b0\u7684\u901a\u9053&#034;\u3002<\/p>\n<p>\u8fb9\u7684\u7c7b\u578b\u4e3b\u8981\u6709\u4e24\u79cd&#xff1a;<\/p>\n<ul>\n<li>\u666e\u901a\u8fb9&#xff08;Normal Edges&#xff09;&#xff1a;\u4ece\u4e00\u4e2a\u8282\u70b9\u76f4\u63a5\u8fde\u5230\u4e0b\u4e00\u4e2a\u8282\u70b9&#xff0c;\u65e0\u6761\u4ef6\u3002<\/li>\n<li>\u6761\u4ef6\u8fb9&#xff08;Conditional Edges&#xff09;&#xff1a;\u8c03\u7528\u4e00\u4e2a\u51fd\u6570\u6765\u5224\u65ad\u63a5\u4e0b\u6765\u53bb\u54ea&#xff08;\u54ea\u4e9b&#xff09;\u8282\u70b9\u3002<\/li>\n<\/ul>\n<h4>13.2 \u6761\u4ef6\u8fb9&#xff1a;\u672c\u8d28\u662f\u4e00\u4e2a\u8def\u7531\u51fd\u6570<\/h4>\n<p>\u6761\u4ef6\u8fb9\u5c31\u662f\u4e00\u4e2a\u666e\u901a Python \u51fd\u6570&#xff1a;\u63a5\u6536 state&#xff0c;\u8fd4\u56de&#034;\u4e0b\u4e00\u4e2a&#xff08;\u6216\u4e0b\u4e00\u6279&#xff09;\u8282\u70b9\u540d&#034;\u3002\u5b83\u51b3\u5b9a\u4e86\u6d41\u7a0b\u7684\u5206\u53c9\u3002<\/p>\n<p>from typing import Literal<br \/>\nfrom typing_extensions import TypedDict<br \/>\nfrom langgraph.graph import StateGraph, START, END<\/p>\n<p>class GraphState(TypedDict):<br \/>\n    value: int<br \/>\n    step: str<\/p>\n<p>def node_a(state: GraphState) -&gt; dict:<br \/>\n    print(&#034;\u6267\u884c\u8282\u70b9A&#034;)<br \/>\n    return {&#034;value&#034;: state[&#034;value&#034;], &#034;step&#034;: &#034;A\u6267\u884c\u5b8c\u6bd5&#034;}<\/p>\n<p>def node_b(state: GraphState) -&gt; dict:<br \/>\n    print(&#034;\u6267\u884c\u8282\u70b9B&#034;)<br \/>\n    return {&#034;value&#034;: state[&#034;value&#034;] * 2, &#034;step&#034;: &#034;B\u6267\u884c\u5b8c\u6bd5&#034;}<\/p>\n<p>def node_c(state: GraphState) -&gt; dict:<br \/>\n    print(&#034;\u6267\u884c\u8282\u70b9C&#034;)<br \/>\n    return {&#034;value&#034;: state[&#034;value&#034;] &#8211; 1, &#034;step&#034;: &#034;C\u6267\u884c\u5b8c\u6bd5&#034;}<\/p>\n<p># \u8def\u7531\u51fd\u6570&#xff1a;\u6839\u636e value \u7684\u5947\u5076\u6027\u51b3\u5b9a\u53bb\u54ea<br \/>\ndef route_condition(state: GraphState) -&gt; Literal[&#034;node_b_alias&#034;, &#034;node_c_alias&#034;]:<br \/>\n    if state[&#034;value&#034;] % 2 &#061;&#061; 0:<br \/>\n        return &#034;node_b_alias&#034;   # \u5076\u6570\u53bb B<br \/>\n    else:<br \/>\n        return &#034;node_c_alias&#034;   # \u5947\u6570\u53bb C<\/p>\n<p>def main():<br \/>\n    builder &#061; StateGraph(GraphState)<\/p>\n<p>    builder.add_node(&#034;node_a&#034;, node_a)<br \/>\n    builder.add_node(&#034;node_b&#034;, node_b)<br \/>\n    builder.add_node(&#034;node_c&#034;, node_c)<\/p>\n<p>    builder.add_edge(START, &#034;node_a&#034;)<\/p>\n<p>    # \u6761\u4ef6\u8fb9&#xff1a;\u6e90\u8282\u70b9 &#043; \u8def\u7531\u51fd\u6570 &#043; \u8def\u7531\u6620\u5c04\u8868<br \/>\n    builder.add_conditional_edges(<br \/>\n        &#034;node_a&#034;,<br \/>\n        route_condition,<br \/>\n        {<br \/>\n            &#034;node_b_alias&#034;: &#034;node_b&#034;,<br \/>\n            &#034;node_c_alias&#034;: &#034;node_c&#034;,<br \/>\n        },<br \/>\n    )<\/p>\n<p>    builder.add_edge(&#034;node_b&#034;, END)<br \/>\n    builder.add_edge(&#034;node_c&#034;, END)<\/p>\n<p>    graph &#061; builder.compile()<\/p>\n<p>    print(&#034;\u8f93\u5165\u503c\u4e3a\u5076\u6570:&#034;)<br \/>\n    print(f&#034;\u6267\u884c\u7ed3\u679c: {graph.invoke({&#039;value&#039;: 2})}&#034;)<\/p>\n<p>    print(&#034;\\\\n\u8f93\u5165\u503c\u4e3a\u5947\u6570:&#034;)<br \/>\n    print(f&#034;\u6267\u884c\u7ed3\u679c: {graph.invoke({&#039;value&#039;: 1})}&#034;)<\/p>\n<p>main()<\/p>\n<p>\u4e3a\u4ec0\u4e48\u8981\u6709&#034;\u8def\u7531\u6620\u5c04\u8868&#034;\u8fd9\u7b2c\u4e09\u4e2a\u53c2\u6570&#xff1f; \u56e0\u4e3a\u8def\u7531\u51fd\u6570\u8fd4\u56de\u7684\u53ea\u662f\u4e00\u4e2a&#034;\u6807\u8bb0\u540d&#034;&#xff08;alias&#xff09;&#xff0c;\u6620\u5c04\u8868\u8d1f\u8d23\u628a\u5b83\u7ffb\u8bd1\u6210\u771f\u5b9e\u8282\u70b9\u540d\u3002\u8fd9\u6837\u505a\u7684\u597d\u5904\u662f&#xff1a;\u8def\u7531\u51fd\u6570\u4e0d\u9700\u8981\u77e5\u9053\u771f\u5b9e\u8282\u70b9\u53eb\u4ec0\u4e48&#xff0c;\u89e3\u8026\u5f97\u66f4\u5f7b\u5e95&#xff0c;\u4e5f\u65b9\u4fbf\u4e00\u4e2a\u51fd\u6570\u590d\u7528\u5230\u591a\u5f20\u56fe\u91cc\u3002<\/p>\n<p>\u5982\u679c\u4f60\u5acc\u9ebb\u70e6&#xff0c;\u4e5f\u53ef\u4ee5\u8ba9\u8def\u7531\u51fd\u6570\u76f4\u63a5\u8fd4\u56de\u771f\u5b9e\u8282\u70b9\u540d&#xff0c;\u7701\u7565\u6620\u5c04\u8868\u3002\u5c0f\u9879\u76ee\u91cc\u8fd9\u4e48\u5199\u66f4\u7701\u4e8b\u3002<\/p>\n<h4>13.3 \u53ef\u63a7\u5faa\u73af&#xff1a;\u7528\u6761\u4ef6\u8fb9\u8f6c\u5708&#xff0c;\u7528 recursion_limit \u5239\u8f66<\/h4>\n<p>\u628a&#034;\u6761\u4ef6\u8fb9&#034;\u548c&#034;\u56de\u8fb9&#034;\u7ec4\u5408\u8d77\u6765&#xff0c;\u5c31\u6709\u4e86\u5faa\u73af\u3002\u6700\u5178\u578b\u7684\u5c31\u662f ReAct \u6a21\u5f0f&#xff1a;\u6a21\u578b\u601d\u8003 \u2192 \u8c03\u5de5\u5177 \u2192 \u7ed3\u679c\u56de\u6a21\u578b \u2192 \u518d\u601d\u8003\u2026\u2026\u76f4\u5230\u6a21\u578b\u8bf4&#034;\u4e0d\u7528\u8c03\u5de5\u5177\u4e86&#034;\u624d\u7ed3\u675f\u3002<\/p>\n<p>\u4f46\u8fd9\u91cc\u57cb\u7740\u4e00\u9897\u96f7&#xff1a;\u5982\u679c\u8def\u7531\u6761\u4ef6\u6c38\u8fdc\u4e0d\u6ee1\u8db3&#xff0c;\u56fe\u4f1a\u4e00\u76f4\u8f6c\u5708&#xff0c;\u628a\u4f60\u7684 token \u548c\u94b1\u4e00\u8d77\u70e7\u6389\u3002<\/p>\n<p>LangGraph \u7ed9\u7684\u5239\u8f66\u662f recursion_limit&#xff1a;\u5b83\u9650\u5236\u56fe\u5728\u629b\u5f02\u5e38\u4e4b\u524d\u5141\u8bb8\u6267\u884c\u7684\u8d85\u6b65\u6570\u91cf&#xff0c;\u9ed8\u8ba4 25&#xff0c;\u5728 graph.invoke \u7684 config \u91cc\u6307\u5b9a\u3002\u8d85\u4e86\u5c31\u4f1a\u629b GraphRecursionError\u3002<\/p>\n<p>from typing import Literal<br \/>\nfrom typing_extensions import TypedDict<br \/>\nfrom langgraph.graph import StateGraph, START, END<br \/>\nfrom langgraph.errors import GraphRecursionError<\/p>\n<p>class LoopState(TypedDict):<br \/>\n    count: int<br \/>\n    result: str<br \/>\n    max_count: int<\/p>\n<p>def node_a(state: LoopState) -&gt; dict:<br \/>\n    print(f&#034;\u6267\u884c\u8282\u70b9a&#xff0c;\u5f53\u524d\u8ba1\u6570: {state[&#039;count&#039;]}&#034;)<br \/>\n    return {<br \/>\n        &#034;count&#034;: state[&#034;count&#034;] &#043; 1,<br \/>\n        &#034;result&#034;: f&#034;\u5df2\u5904\u7406{state[&#039;count&#039;]}\u6b21&#034;,<br \/>\n    }<\/p>\n<p>def node_b(state: LoopState) -&gt; dict:<br \/>\n    print(f&#034;\u6267\u884c\u8282\u70b9b&#xff0c;\u5f53\u524d\u8ba1\u6570: {state[&#039;count&#039;]}&#034;)<br \/>\n    return {&#034;result&#034;: f&#034;\u5df2\u5904\u7406{state[&#039;count&#039;]}\u6b21 &#8211; \u8f85\u52a9\u5904\u7406&#034;}<\/p>\n<p>def route(state: LoopState) -&gt; Literal[&#034;b&#034;, END]:<br \/>\n    &#034;&#034;&#034;\u6761\u4ef6\u8def\u7531&#xff1a;\u51b3\u5b9a\u7ee7\u7eed\u5faa\u73af\u8fd8\u662f\u7ec8\u6b62&#034;&#034;&#034;<br \/>\n    if state[&#034;count&#034;] &gt;&#061; state[&#034;max_count&#034;]:<br \/>\n        print(f&#034;\u6ee1\u8db3\u7ec8\u6b62\u6761\u4ef6&#xff0c;\u8ba1\u6570 {state[&#039;count&#039;]} &gt;&#061; {state[&#039;max_count&#039;]}&#xff0c;\u8fd4\u56deEND&#034;)<br \/>\n        return END<br \/>\n    else:<br \/>\n        print(f&#034;\u672a\u6ee1\u8db3\u7ec8\u6b62\u6761\u4ef6&#xff0c;\u8ba1\u6570 {state[&#039;count&#039;]} &lt; {state[&#039;max_count&#039;]}&#xff0c;\u8fd4\u56deb&#034;)<br \/>\n        return &#034;b&#034;<\/p>\n<p>builder &#061; StateGraph(LoopState)<br \/>\nbuilder.add_node(&#034;a&#034;, node_a)<br \/>\nbuilder.add_node(&#034;b&#034;, node_b)<br \/>\nbuilder.add_edge(START, &#034;a&#034;)<br \/>\nbuilder.add_conditional_edges(&#034;a&#034;, route)<br \/>\nbuilder.add_edge(&#034;b&#034;, &#034;a&#034;)          # \u56de\u8fb9&#xff0c;\u5f62\u6210\u5faa\u73af<\/p>\n<p>graph &#061; builder.compile()<\/p>\n<p>print(&#034;&#061;&#061;&#061; \u5f00\u59cb\u6267\u884c\u5de5\u4f5c\u6d41 &#061;&#061;&#061;&#034;)<br \/>\ntry:<br \/>\n    result &#061; graph.invoke(<br \/>\n        input&#061;{&#034;count&#034;: 0, &#034;result&#034;: &#034;&#034;, &#034;max_count&#034;: 300},<br \/>\n        config&#061;{&#034;recursion_limit&#034;: 6},    # \u5239\u8f66&#xff1a;\u6700\u591a 6 \u4e2a\u8d85\u6b65<br \/>\n    )<br \/>\n    print(&#034;&#061;&#061;&#061; \u6267\u884c\u7ed3\u679c &#061;&#061;&#061;&#034;)<br \/>\n    print(result)<br \/>\nexcept GraphRecursionError as e:<br \/>\n    print(f&#034;\u9012\u5f52\u9519\u8bef: {e}&#034;)<\/p>\n<p>\u8fd9\u4e2a\u4f8b\u5b50\u91cc max_count \u8bbe\u6210 300&#xff0c;\u4f46 recursion_limit \u53ea\u6709 6&#xff0c;\u6240\u4ee5\u56fe\u4f1a\u5728\u7b2c 6 \u4e2a\u8d85\u6b65\u88ab\u5f3a\u5236\u4e2d\u65ad&#xff0c;\u629b\u51fa GraphRecursionError\u3002\u8fd9\u6b63\u662f\u4f60\u60f3\u8981\u7684\u4fdd\u62a4\u2014\u2014\u5b81\u53ef\u62a5\u9519&#xff0c;\u4e5f\u522b\u65e0\u9650\u5faa\u73af\u3002<\/p>\n<p>\u4e00\u4e2a\u6613\u6df7\u70b9&#xff1a;recursion_limit \u7684\u5355\u4f4d\u662f&#034;\u8d85\u6b65&#034;&#xff0c;\u4e0d\u662f&#034;\u8282\u70b9\u6267\u884c\u6b21\u6570&#034;\u3002 \u56e0\u4e3a\u4e00\u4e2a\u8d85\u6b65\u91cc\u53ef\u80fd\u6709\u591a\u4e2a\u8282\u70b9\u5e76\u884c\u6267\u884c&#xff0c;\u6240\u4ee5 limit&#061;6 \u4e0d\u4ee3\u8868\u53ea\u8dd1 6 \u4e2a\u8282\u70b9\u3002\u8c03\u8bd5\u65f6\u5982\u679c\u53d1\u73b0&#034;\u660e\u660e\u53ea\u8bbe\u4e86 6 \u5374\u8dd1\u4e86\u5341\u51e0\u4e2a\u8282\u70b9&#034;&#xff0c;\u5c31\u662f\u8fd9\u4e2a\u539f\u56e0\u3002<\/p>\n<h3>\u5341\u56db\u3001\u8e29\u5751\u6e05\u5355&#xff1a;\u8fd9\u4e9b\u5751\u6211\u5e2e\u4f60\u5148\u8e29\u4e86<\/h3>\n<p>\u4e0b\u9762\u8fd9\u4e9b\u662f\u793e\u533a\u91cc\u53cd\u590d\u88ab\u63d0\u5230\u7684\u771f\u5b9e\u95ee\u9898&#xff0c;\u6309&#034;\u6700\u5bb9\u6613\u8e29&#034;\u6392\u5e8f\u3002<\/p>\n<h4>14.1 State \u4e0d\u662f\u5783\u573e\u6876<\/h4>\n<ul>\n<li>\u53ea\u653e\u8282\u70b9\u4e4b\u95f4\u9700\u8981\u5171\u4eab\u4f20\u9012\u7684\u6570\u636e&#xff0c;\u8282\u70b9\u5185\u90e8\u7684\u4e34\u65f6\u53d8\u91cf\u5c31\u7559\u5728\u51fd\u6570\u91cc&#xff1b;<\/li>\n<li>\u5b57\u6bb5\u540d\u8981\u6709\u8bed\u4e49&#xff1a;\u7528 messages\u3001user_input\u3001tool_result&#xff0c;\u522b\u7528 data\u3001info&#xff1b;<\/li>\n<li>\u5d4c\u5957\u522b\u8d85\u8fc7\u4e24\u5c42&#xff0c;\u590d\u6742\u7ed3\u6784\u5c3d\u91cf\u6241\u5e73\u5316&#xff0c;\u5426\u5219\u8bfb\u5199\u5fc3\u667a\u8d1f\u62c5\u4f1a\u7206\u70b8\u3002<\/li>\n<\/ul>\n<p>\u8bb0\u4f4f\u4e00\u53e5\u8bdd&#xff1a;State \u7684\u8bbe\u8ba1\u8d28\u91cf\u51b3\u5b9a\u4e86\u7cfb\u7edf\u7684\u53ef\u7ef4\u62a4\u6027\u3002\u591a\u82b1\u5341\u5206\u949f\u8bbe\u8ba1&#xff0c;\u5c11\u82b1\u5341\u5c0f\u65f6\u8c03\u8bd5\u3002<\/p>\n<h4>14.2 thread_id \u7684\u547d\u540d\u65b9\u5f0f&#xff0c;\u51b3\u5b9a\u4e86\u4f60\u7684\u8bb0\u5fc6\u4f1a\u4e0d\u4f1a\u4e32<\/h4>\n<p>\u5982\u679c\u6bcf\u6b21\u7528\u6237\u5237\u65b0\u9875\u9762\u5c31\u751f\u6210\u4e00\u4e2a\u65b0 thread_id&#xff0c;\u77ed\u671f\u8bb0\u5fc6\u7acb\u523b\u65ad\u6389\u3002\u63a8\u8350\u7528&#034;\u7528\u6237\u6807\u8bc6-\u4f1a\u8bdd\u6807\u8bc6&#034;\u7684\u7ec4\u5408&#xff0c;\u4f8b\u5982 user_1021-session_0003\u3002\u8fd9\u6837\u65e2\u80fd\u533a\u5206\u4f1a\u8bdd&#xff0c;\u53c8\u80fd\u9760\u524d\u7f00\u505a\u7528\u6237\u7ea7\u805a\u5408\u3002<\/p>\n<h4>14.3 \u5386\u53f2\u6d88\u606f\u4e0d\u80fd\u65e0\u9650\u589e\u957f<\/h4>\n<p>\u628a\u51e0\u5341\u8f6e\u5bf9\u8bdd\u5168\u585e\u7ed9\u6a21\u578b&#xff0c;token \u4f1a\u88ab\u5403\u5149&#xff0c;\u800c\u4e14\u6a21\u578b\u8fd8\u4f1a&#034;\u8bb0\u6df7&#034;\u3002\u5efa\u8bae\u8bbe\u4e00\u4e2a\u9608\u503c&#xff08;\u6bd4\u5982\u8d85\u8fc7 30 \u8f6e\u6216\u63a5\u8fd1 token \u4e0a\u9650&#xff09;&#xff0c;\u89e6\u53d1\u4e00\u4e2a\u6458\u8981\u8282\u70b9&#xff0c;\u628a\u65e9\u671f\u5bf9\u8bdd\u538b\u7f29\u6210\u4e00\u6bb5\u6458\u8981\u5b58\u8fdb State\u3002<\/p>\n<h4>14.4 \u4eba\u5de5\u5ba1\u6279\u8981\u505a\u6210\u72b6\u6001\u673a&#xff0c;\u4e0d\u662f\u4e00\u6761\u8fb9<\/h4>\n<p>\u5ba1\u6279\u5176\u5b9e\u6709\u56db\u4e2a\u72b6\u6001&#xff1a;\u7b49\u5f85\u3001\u901a\u8fc7\u3001\u62d2\u7edd\u3001\u8d85\u65f6\u3002\u5efa\u8bae\u5728 State \u91cc\u663e\u5f0f\u653e\u4e00\u4e2a approval_state \u5b57\u6bb5&#xff0c;\u8fdb\u5ba1\u6279\u8282\u70b9\u5148\u68c0\u67e5\u72b6\u6001&#xff0c;\u53ea\u5904\u7406 waiting \u7684\u8bf7\u6c42\u3002\u5426\u5219\u53ef\u80fd\u51fa\u73b0&#034;\u4e24\u4e2a\u4eba\u540c\u65f6\u6536\u5230\u5ba1\u6279\u3001\u5404\u70b9\u4e00\u6b21&#xff0c;\u4e1a\u52a1\u88ab\u6267\u884c\u4e24\u904d&#034;\u7684\u4e8b\u6545\u3002<\/p>\n<h4>14.5 \u751f\u4ea7\u73af\u5883\u522b\u7528 InMemorySaver<\/h4>\n<p>InMemorySaver \u53ea\u9002\u5408\u672c\u5730\u8c03\u8bd5\u3002\u751f\u4ea7\u8bf7\u6362 SqliteSaver \/ PostgresSaver \/ RedisSaver&#xff0c;\u5426\u5219\u670d\u52a1\u4e00\u91cd\u542f&#xff0c;\u6240\u6709\u4f1a\u8bdd\u8bb0\u5fc6\u548c\u65ad\u70b9\u5168\u90e8\u84b8\u53d1\u3002<\/p>\n<h4>14.6 \u65e5\u5fd7\u548c\u6307\u6807\u522b\u585e\u8fdb State<\/h4>\n<p>\u6709\u4eba\u559c\u6b22\u628a&#034;\u6bcf\u4e00\u6b65\u7684\u6267\u884c\u65e5\u5fd7&#034;\u7d2f\u79ef\u5230 State \u91cc\u3002\u95ee\u9898\u662f\u6bcf\u6b21\u72b6\u6001\u53d8\u66f4\u90fd\u8981\u5b58\u4e00\u4efd\u5feb\u7167&#xff0c;State \u8d8a\u80d6&#xff0c;checkpoint \u8d8a\u6162&#xff0c;\u6210\u672c\u8d8a\u9ad8\u3002\u65e5\u5fd7\u8be5\u8d70\u65e5\u5fd7\u7cfb\u7edf&#xff0c;\u522b\u8d70\u56fe\u72b6\u6001\u3002<\/p>\n<h4>14.7 \u4e0d\u8981\u5728 interrupt \u4e4b\u524d\u505a\u6709\u526f\u4f5c\u7528\u7684\u64cd\u4f5c<\/h4>\n<p>\u6062\u590d\u65f6\u8282\u70b9\u4f1a\u4ece\u5934\u91cd\u8dd1&#xff0c;\u524d\u9762\u5df2\u7ecf\u8bf4\u8fc7&#xff0c;\u4f46\u503c\u5f97\u518d\u5f3a\u8c03\u4e00\u6b21\u3002\u8f6c\u8d26\u3001\u53d1\u90ae\u4ef6\u3001\u6263\u79ef\u5206\u8fd9\u7c7b\u64cd\u4f5c&#xff0c;\u52a1\u5fc5\u653e\u5230 interrupt \u4e4b\u540e&#xff0c;\u6216\u8005\u505a\u6210\u5e42\u7b49\u3002<\/p>\n<h3>\u5341\u4e94\u3001\u5b66\u4e60\u8def\u7ebf\u5efa\u8bae<\/h3>\n<p>\u5982\u679c\u770b\u5230\u8fd9\u91cc\u4f60\u5df2\u7ecf\u6709\u70b9\u6655&#xff0c;\u522b\u614c&#xff0c;\u8fd9\u662f\u6b63\u5e38\u7684\u3002\u5efa\u8bae\u6309\u4e0b\u9762\u8fd9\u4e2a\u987a\u5e8f\u52a8\u624b&#xff0c;\u6bcf\u4e00\u9636\u6bb5\u90fd\u5199\u4ee3\u7801&#xff0c;\u522b\u53ea\u8bfb&#xff1a;<\/p>\n<li>\u7b2c\u4e00\u6b65&#xff08;1 \u5929&#xff09;&#xff1a;\u8dd1\u901a\u7b2c\u4e94\u8282\u7684\u5e76\u884c RAG \u4f8b\u5b50&#xff0c;\u7136\u540e\u81ea\u5df1\u6539\u6210&#034;\u5148\u68c0\u7d22\u518d\u603b\u7ed3&#034;\u7684\u4e32\u884c\u7248\u672c&#xff0c;\u4f53\u4f1a\u8fb9\u7684\u5dee\u522b&#xff1b;\u518d\u6253\u5370\u4e00\u6b21 draw_ascii()\u3002<\/li>\n<li>\u7b2c\u4e8c\u6b65&#xff08;1 \u5929&#xff09;&#xff1a;\u628a\u7b2c\u516d\u8282\u4e09\u79cd State \u5b9a\u4e49\u90fd\u5199\u4e00\u904d&#xff0c;\u91cd\u70b9\u73a9\u900f Reducer\u2014\u2014\u5206\u522b\u8bd5\u9ed8\u8ba4\u8986\u76d6\u548c operator.add&#xff0c;\u89c2\u5bdf\u7ed3\u679c\u5dee\u5f02\u3002<\/li>\n<li>\u7b2c\u4e09\u6b65&#xff08;1 \u5929&#xff09;&#xff1a;\u7528 InMemorySaver \u505a\u4e00\u4e2a&#034;\u8bb0\u5f97\u6211\u540d\u5b57&#034;\u7684\u804a\u5929\u673a\u5668\u4eba&#xff0c;\u7136\u540e\u6545\u610f\u8ba9\u5b83\u5d29\u4e00\u6b21&#xff0c;\u6362\u6210 SqliteSaver \u4f53\u9a8c\u65ad\u70b9\u7eed\u8dd1\u3002<\/li>\n<li>\u7b2c\u56db\u6b65&#xff08;2 \u5929&#xff09;&#xff1a;\u5199\u4e00\u4e2a\u771f\u6b63\u7684 ReAct \u5faa\u73af&#xff08;\u6a21\u578b &#043; \u5de5\u5177 &#043; \u6761\u4ef6\u8fb9&#xff09;&#xff0c;\u7ed9\u5faa\u73af\u52a0 recursion_limit&#xff0c;\u7ed9\u5de5\u5177\u8282\u70b9\u52a0 RetryPolicy\u3002<\/li>\n<li>\u7b2c\u4e94\u6b65&#xff08;1 \u5929&#xff09;&#xff1a;\u7ed9\u8fd9\u4e2a Agent \u52a0\u4eba\u5de5\u5ba1\u6838&#xff08;interrupt &#043; Command(resume&#061;&#8230;)&#xff09;&#xff0c;\u5e76\u7528 stream_mode&#061;[&#034;messages&#034;, &#034;custom&#034;] \u505a\u4e00\u4e2a\u80fd\u770b\u5230&#034;\u6253\u5b57\u673a &#043; \u5f53\u524d\u6b65\u9aa4&#034;\u7684\u524d\u7aef\u3002<\/li>\n<p>\u8d70\u5b8c\u8fd9\u4e94\u6b65&#xff0c;\u4f60\u5df2\u7ecf\u80fd\u8986\u76d6 80% \u7684\u5b9e\u9645\u9700\u6c42\u4e86\u3002\u518d\u5f80\u540e\u5c31\u662f\u8fdb\u9636\u8bdd\u9898&#xff1a;\u5b50\u56fe&#xff08;\u628a\u4e00\u5f20\u56fe\u5f53\u6210\u53e6\u4e00\u4e2a\u8282\u70b9\u7684\u5185\u90e8&#xff09;\u3001Send \u505a\u52a8\u6001\u6247\u51fa&#xff08;Map-Reduce \u98ce\u683c&#xff09;\u3001\u591a\u667a\u80fd\u4f53\u534f\u4f5c&#xff08;Supervisor \u67b6\u6784&#xff09;\u2014\u2014\u8fd9\u4e9b\u7b49\u4f60\u628a\u57fa\u7840\u6253\u7262\u518d\u770b&#xff0c;\u4f1a\u987a\u5f88\u591a\u3002<\/p>\n<h3>\u5341\u516d\u3001\u603b\u7ed3<\/h3>\n<p>\u6700\u540e\u7528\u4e00\u6bb5\u8bdd\u628a\u5168\u6587\u4e32\u8d77\u6765&#xff1a;<\/p>\n<ul>\n<li>LangGraph \u662f\u5e72\u4ec0\u4e48\u7684&#xff1a;\u628a Agent \u5de5\u4f5c\u6d41\u753b\u6210\u56fe&#xff0c;\u4ece\u800c\u652f\u6301\u5206\u652f\u3001\u5faa\u73af\u3001\u5e76\u884c\u3001\u6682\u505c\u3001\u6062\u590d\u3002\u5b83\u6bd4 LangChain \u66f4\u5e95\u5c42\u3001\u66f4\u53ef\u63a7\u3002<\/li>\n<li>\u4e09\u5927\u4ef6&#xff1a;State&#xff08;\u5171\u4eab\u8bb0\u4e8b\u672c&#xff09;\u3001Node&#xff08;\u5de5\u4f4d&#xff09;\u3001Edge&#xff08;\u4f20\u9001\u5e26&#xff09;\u3002\u5199\u5e94\u7528\u5c31\u662f&#034;\u5b9a\u4e49\u8bb0\u4e8b\u672c \u2192 \u5199\u5de5\u4f4d \u2192 \u8fde\u4f20\u9001\u5e26 \u2192 \u7f16\u8bd1 \u2192 \u8c03\u7528&#034;\u3002<\/li>\n<li>Reducer&#xff1a;\u51b3\u5b9a\u589e\u91cf\u600e\u4e48\u5408\u5e76\u3002\u4e0d\u914d\u5c31\u8986\u76d6&#xff0c;\u914d\u4e86\u624d\u80fd\u8ffd\u52a0\u3002\u5e76\u884c\u5199\u540c\u4e00\u4e2a\u952e\u53c8\u6ca1\u914d Reducer&#xff0c;\u5fc5\u62a5\u9519\u3002<\/li>\n<li>Checkpointer &#043; thread_id&#xff1a;\u8fd9\u662f&#034;\u8bb0\u5fc6&#034;\u548c&#034;\u65ad\u70b9\u7eed\u8dd1&#034;\u7684\u5730\u57fa\u3002invoke(None) \u52a0\u540c\u4e00\u4e2a thread_id \u5c31\u80fd\u4ece\u65ad\u70b9\u7ee7\u7eed\u3002<\/li>\n<li>Pregel&#xff1a;\u5e95\u5c42\u662f&#034;\u8d85\u6b65&#034;\u9a71\u52a8\u7684&#xff0c;Plan \u2192 Execute \u2192 Update \u4e0d\u65ad\u5faa\u73af&#xff0c;\u76f4\u5230\u6ca1\u6709\u8282\u70b9\u88ab\u9009\u4e2d\u3002\u6240\u4ee5\u540c\u4e00\u4e2a\u8282\u70b9\u53ef\u4ee5\u88ab\u6267\u884c\u591a\u6b21&#xff0c;\u5faa\u73af\u662f\u5929\u7136\u7684\u3002<\/li>\n<li>\u8282\u70b9\u8f93\u51fa\u5fc5\u987b\u662f\u589e\u91cf&#xff0c;\u8fd4\u56de\u6574\u4e2a state \u662f\u6700\u5e38\u89c1\u7684\u9519\u8bef\u3002<\/li>\n<li>\u6d41\u5f0f\u8f93\u51fa\u6709\u516d\u79cd\u6a21\u5f0f&#xff0c;messages \u7ed9\u6253\u5b57\u673a\u6548\u679c&#xff0c;custom \u7ed9\u8fdb\u5ea6\u63d0\u793a&#xff0c;debug \u7ed9\u6392\u9519\u3002<\/li>\n<li>interrupt \u8ba9\u4eba\u53c2\u4e0e\u51b3\u7b56&#xff0c;\u4f46\u6062\u590d\u65f6\u6574\u4e2a\u8282\u70b9\u4f1a\u91cd\u8dd1&#xff0c;\u52a1\u5fc5\u4fdd\u8bc1\u5e42\u7b49\u6216\u62c6\u5206\u8282\u70b9\u3002<\/li>\n<li>\u5faa\u73af\u4e00\u5b9a\u8981\u6709\u5239\u8f66&#xff1a;recursion_limit \u6570\u7684\u662f\u8d85\u6b65&#xff0c;\u4e0d\u662f\u8282\u70b9\u3002<\/li>\n<\/ul>\n<p>LangGraph \u7684\u5b66\u4e60\u66f2\u7ebf\u4e3b\u8981\u4e0d\u5728 API&#xff0c;\u800c\u5728\u601d\u7ef4\u65b9\u5f0f\u2014\u2014\u4ece&#034;\u5199\u4e00\u4e32\u51fd\u6570\u8c03\u7528&#034;\u5207\u6362\u5230&#034;\u8bbe\u8ba1\u4e00\u5f20\u72b6\u6001\u673a&#034;\u3002\u4e00\u65e6\u8fd9\u4e2a\u601d\u7ef4\u5efa\u7acb\u8d77\u6765&#xff0c;\u4f60\u4f1a\u53d1\u73b0\u5f88\u591a\u4ee5\u524d\u5199\u5f97\u5f88\u522b\u626d\u7684 Agent \u903b\u8f91&#xff0c;\u7a81\u7136\u53d8\u5f97\u6e05\u6670\u53ef\u63a7\u3002<\/p>\n<p>\u5e0c\u671b\u8fd9\u7bc7\u80fd\u5e2e\u4f60\u5c11\u8d70\u70b9\u5f2f\u8def\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u8bf4\u660e&#xff1a;\u672c\u6587\u7cfb\u7edf\u68b3\u7406 LangGraph \u7684\u6838\u5fc3\u6982\u5ff5\u4e0e\u5de5\u7a0b\u7528\u6cd5&#xff0c;\u53c2\u8003 LangGraph \u5b98\u65b9\u6587\u6863\u4e0e\u793e\u533a\u5b9e\u8df5\u7ecf\u9a8c\u6574\u7406\u800c\u6210&#xff0c;\u9762\u5411\\&#8221;\u4f1a\u4e00\u70b9 Python\u3001\u4f46\u5b8c\u5168\u6ca1\u63a5\u89e6\u8fc7 LangGraph\\&#8221;\u7684\u540c\u5b66\u3002\u5168\u6587\u6309\\&#8221;\u662f\u4ec0\u4e48 \u2192 \u4e3a\u4ec0\u4e48 \u2192 \u600e\u4e48\u8dd1 \u2192 \u6bcf\u4e2a\u6982\u5ff5\u62c6\u5f00\u8bb2 \u2192 \u8e29\u5751\u6e05\u5355\\&#8221;\u7684\u987a\u5e8f\u5c55\u5f00&#xff0c;\u5efa\u8bae\u6309\u987a\u5e8f\u9605\u8bfb\u3002\u76ee\u5f55\u4e00\u3001\u5148\u8bb2\u4eba\u8bdd&#xff1a;\u4e3a\u4ec0\u4e48\u9700\u8981 LangGraph\u4e8c\u3001LangGraph \u5230\u5e95\u662f\u4ec0\u4e48\u4e09\u3001LangGraph \u548c Lan<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[74,997,3503,81,292],"topic":[],"class_list":["post-123472","post","type-post","status-publish","format-standard","hentry","category-server","tag-agent","tag-langchain","tag-langgraph","tag-python","tag-292"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>LangGraph \u4fdd\u59c6\u7ea7\u5165\u95e8\uff1aState\u3001Node\u3001Edge \u4e09\u5927\u4ef6\uff0c\u52a0\u4e0a\u68c0\u67e5\u70b9\u3001\u6d41\u5f0f\u8f93\u51fa\u4e0e\u4eba\u5de5\u5ba1\u6838 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.wsisp.com\/helps\/123472.html\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"LangGraph \u4fdd\u59c6\u7ea7\u5165\u95e8\uff1aState\u3001Node\u3001Edge \u4e09\u5927\u4ef6\uff0c\u52a0\u4e0a\u68c0\u67e5\u70b9\u3001\u6d41\u5f0f\u8f93\u51fa\u4e0e\u4eba\u5de5\u5ba1\u6838 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"og:description\" content=\"\u8bf4\u660e&#xff1a;\u672c\u6587\u7cfb\u7edf\u68b3\u7406 LangGraph \u7684\u6838\u5fc3\u6982\u5ff5\u4e0e\u5de5\u7a0b\u7528\u6cd5&#xff0c;\u53c2\u8003 LangGraph \u5b98\u65b9\u6587\u6863\u4e0e\u793e\u533a\u5b9e\u8df5\u7ecf\u9a8c\u6574\u7406\u800c\u6210&#xff0c;\u9762\u5411&quot;\u4f1a\u4e00\u70b9 Python\u3001\u4f46\u5b8c\u5168\u6ca1\u63a5\u89e6\u8fc7 LangGraph&quot;\u7684\u540c\u5b66\u3002\u5168\u6587\u6309&quot;\u662f\u4ec0\u4e48 \u2192 \u4e3a\u4ec0\u4e48 \u2192 \u600e\u4e48\u8dd1 \u2192 \u6bcf\u4e2a\u6982\u5ff5\u62c6\u5f00\u8bb2 \u2192 \u8e29\u5751\u6e05\u5355&quot;\u7684\u987a\u5e8f\u5c55\u5f00&#xff0c;\u5efa\u8bae\u6309\u987a\u5e8f\u9605\u8bfb\u3002\u76ee\u5f55\u4e00\u3001\u5148\u8bb2\u4eba\u8bdd&#xff1a;\u4e3a\u4ec0\u4e48\u9700\u8981 LangGraph\u4e8c\u3001LangGraph \u5230\u5e95\u662f\u4ec0\u4e48\u4e09\u3001LangGraph \u548c Lan\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.wsisp.com\/helps\/123472.html\" \/>\n<meta property=\"og:site_name\" content=\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"article:published_time\" content=\"2026-11-07T03:33:11+00:00\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"27 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/123472.html\",\"url\":\"https:\/\/www.wsisp.com\/helps\/123472.html\",\"name\":\"LangGraph \u4fdd\u59c6\u7ea7\u5165\u95e8\uff1aState\u3001Node\u3001Edge \u4e09\u5927\u4ef6\uff0c\u52a0\u4e0a\u68c0\u67e5\u70b9\u3001\u6d41\u5f0f\u8f93\u51fa\u4e0e\u4eba\u5de5\u5ba1\u6838 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"isPartOf\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\"},\"datePublished\":\"2026-11-07T03:33:11+00:00\",\"dateModified\":\"2026-11-07T03:33:11+00:00\",\"author\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/123472.html#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.wsisp.com\/helps\/123472.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/123472.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.wsisp.com\/helps\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"LangGraph \u4fdd\u59c6\u7ea7\u5165\u95e8\uff1aState\u3001Node\u3001Edge \u4e09\u5927\u4ef6\uff0c\u52a0\u4e0a\u68c0\u67e5\u70b9\u3001\u6d41\u5f0f\u8f93\u51fa\u4e0e\u4eba\u5de5\u5ba1\u6838\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\",\"url\":\"https:\/\/www.wsisp.com\/helps\/\",\"name\":\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"description\":\"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"contentUrl\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"caption\":\"admin\"},\"sameAs\":[\"http:\/\/wp.wsisp.com\"],\"url\":\"https:\/\/www.wsisp.com\/helps\/author\/admin\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"LangGraph \u4fdd\u59c6\u7ea7\u5165\u95e8\uff1aState\u3001Node\u3001Edge \u4e09\u5927\u4ef6\uff0c\u52a0\u4e0a\u68c0\u67e5\u70b9\u3001\u6d41\u5f0f\u8f93\u51fa\u4e0e\u4eba\u5de5\u5ba1\u6838 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.wsisp.com\/helps\/123472.html","og_locale":"zh_CN","og_type":"article","og_title":"LangGraph \u4fdd\u59c6\u7ea7\u5165\u95e8\uff1aState\u3001Node\u3001Edge \u4e09\u5927\u4ef6\uff0c\u52a0\u4e0a\u68c0\u67e5\u70b9\u3001\u6d41\u5f0f\u8f93\u51fa\u4e0e\u4eba\u5de5\u5ba1\u6838 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","og_description":"\u8bf4\u660e&#xff1a;\u672c\u6587\u7cfb\u7edf\u68b3\u7406 LangGraph \u7684\u6838\u5fc3\u6982\u5ff5\u4e0e\u5de5\u7a0b\u7528\u6cd5&#xff0c;\u53c2\u8003 LangGraph \u5b98\u65b9\u6587\u6863\u4e0e\u793e\u533a\u5b9e\u8df5\u7ecf\u9a8c\u6574\u7406\u800c\u6210&#xff0c;\u9762\u5411\"\u4f1a\u4e00\u70b9 Python\u3001\u4f46\u5b8c\u5168\u6ca1\u63a5\u89e6\u8fc7 LangGraph\"\u7684\u540c\u5b66\u3002\u5168\u6587\u6309\"\u662f\u4ec0\u4e48 \u2192 \u4e3a\u4ec0\u4e48 \u2192 \u600e\u4e48\u8dd1 \u2192 \u6bcf\u4e2a\u6982\u5ff5\u62c6\u5f00\u8bb2 \u2192 \u8e29\u5751\u6e05\u5355\"\u7684\u987a\u5e8f\u5c55\u5f00&#xff0c;\u5efa\u8bae\u6309\u987a\u5e8f\u9605\u8bfb\u3002\u76ee\u5f55\u4e00\u3001\u5148\u8bb2\u4eba\u8bdd&#xff1a;\u4e3a\u4ec0\u4e48\u9700\u8981 LangGraph\u4e8c\u3001LangGraph \u5230\u5e95\u662f\u4ec0\u4e48\u4e09\u3001LangGraph \u548c Lan","og_url":"https:\/\/www.wsisp.com\/helps\/123472.html","og_site_name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","article_published_time":"2026-11-07T03:33:11+00:00","author":"admin","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"27 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.wsisp.com\/helps\/123472.html","url":"https:\/\/www.wsisp.com\/helps\/123472.html","name":"LangGraph \u4fdd\u59c6\u7ea7\u5165\u95e8\uff1aState\u3001Node\u3001Edge \u4e09\u5927\u4ef6\uff0c\u52a0\u4e0a\u68c0\u67e5\u70b9\u3001\u6d41\u5f0f\u8f93\u51fa\u4e0e\u4eba\u5de5\u5ba1\u6838 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","isPartOf":{"@id":"https:\/\/www.wsisp.com\/helps\/#website"},"datePublished":"2026-11-07T03:33:11+00:00","dateModified":"2026-11-07T03:33:11+00:00","author":{"@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41"},"breadcrumb":{"@id":"https:\/\/www.wsisp.com\/helps\/123472.html#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.wsisp.com\/helps\/123472.html"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.wsisp.com\/helps\/123472.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.wsisp.com\/helps"},{"@type":"ListItem","position":2,"name":"LangGraph \u4fdd\u59c6\u7ea7\u5165\u95e8\uff1aState\u3001Node\u3001Edge \u4e09\u5927\u4ef6\uff0c\u52a0\u4e0a\u68c0\u67e5\u70b9\u3001\u6d41\u5f0f\u8f93\u51fa\u4e0e\u4eba\u5de5\u5ba1\u6838"}]},{"@type":"WebSite","@id":"https:\/\/www.wsisp.com\/helps\/#website","url":"https:\/\/www.wsisp.com\/helps\/","name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","description":"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41","name":"admin","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/","url":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","contentUrl":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","caption":"admin"},"sameAs":["http:\/\/wp.wsisp.com"],"url":"https:\/\/www.wsisp.com\/helps\/author\/admin"}]}},"_links":{"self":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/123472","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/comments?post=123472"}],"version-history":[{"count":0,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/123472\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media?parent=123472"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/categories?post=123472"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/tags?post=123472"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/topic?post=123472"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}