{"id":1114,"date":"2025-04-15T14:50:57","date_gmt":"2025-04-15T06:50:57","guid":{"rendered":"https:\/\/www.linyinghao.cn\/wordpress\/?p=1114"},"modified":"2025-04-15T14:54:22","modified_gmt":"2025-04-15T06:54:22","slug":"langgraph-agent-for-interacting-with-a-sql-database","status":"publish","type":"post","link":"https:\/\/www.linyinghao.cn\/wordpress\/?p=1114","title":{"rendered":"Langgraph Agent for Interacting with a SQL Database"},"content":{"rendered":"\n<p>This is a practice of Langgraph agent, which is used to interact with a sqlite database. It is referring to Langgraph tutorial <a href=\"https:\/\/langchain-ai.github.io\/langgraph\/tutorials\/sql-agent\/\">sql-agent<\/a>, with replacing the LLM by Tongyi Qwen. This article is used to document the learning during the practice.<\/p>\n\n\n\n<p>\u672c\u6587\u662f\u5bf9\u4e8eLanggraph\u4e2dagent\u7684\u4e00\u6b21\u5b9e\u8df5\uff0c\u662f\u7528\u6765\u4e0eSqlite\u6570\u636e\u5e93\u8fdb\u884c\u4ea4\u4e92\u3002\u672c\u6587\u53c2\u7167\u4e86Langgraph\u7684\u6559\u7a0b\uff0c\u4ec5\u4f7f\u7528\u901a\u4e49\u5343\u95ee\u66ff\u6362\u4e86\u5176\u4e2d\u7684LLM\u6a21\u578b\u3002\u672c\u6587\u7528\u6765\u8bb0\u5f55\u5b9e\u8df5\u8fc7\u7a0b\u4e2d\u7684\u5b66\u4e60\u5fc3\u5f97\u3002<\/p>\n\n\n\n<p>Source code is uploaded <a href=\"https:\/\/linyinghao.cn\/gitlab\/clark\/ai-agent\/-\/blob\/development\/05.database-query.ipynb\">here<\/a> and would possibly be updated with time being.<\/p>\n\n\n\n<p>\u6e90\u4ee3\u7801\u5df2\u4e0a\u4f20\uff0c\u53ef\u80fd\u4f1a\u4e0d\u5b9a\u671f\u66f4\u65b0\u3002<\/p>\n\n\n\n<p><\/p>\n\n\n\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_74 ez-toc-wrap-left counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.linyinghao.cn\/wordpress\/?p=1114\/#Overall_Architecture\" >Overall Architecture<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.linyinghao.cn\/wordpress\/?p=1114\/#Detail_Explanation\" >Detail Explanation<\/a><ul class='ez-toc-list-level-2' ><li class='ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.linyinghao.cn\/wordpress\/?p=1114\/#Node_1_first_tool_node\" >Node 1: first_tool_node<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.linyinghao.cn\/wordpress\/?p=1114\/#Node_2_list_tables_tool\" >Node 2: list_tables_tool<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.linyinghao.cn\/wordpress\/?p=1114\/#Node_3_model_get_schema\" >Node 3: model_get_schema<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.linyinghao.cn\/wordpress\/?p=1114\/#Node_4_get_schema_tool\" >Node 4: get_schema_tool<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.linyinghao.cn\/wordpress\/?p=1114\/#Node_5_query_gen\" >Node 5: query_gen<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.linyinghao.cn\/wordpress\/?p=1114\/#Node_6_correct_query\" >Node 6: correct_query<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/www.linyinghao.cn\/wordpress\/?p=1114\/#Node_7_execute_query\" >Node 7: execute_query<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/www.linyinghao.cn\/wordpress\/?p=1114\/#Node_8_END\" >Node 8: END<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/www.linyinghao.cn\/wordpress\/?p=1114\/#Summary\" >Summary<\/a><\/li><\/ul><\/nav><\/div>\n<h1 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Overall_Architecture\"><\/span>Overall Architecture<span class=\"ez-toc-section-end\"><\/span><\/h1>\n\n\n\n<p>The overall architecture is depicted as following image. It is a combination of multiple tools and LLM invocations. It is designed to provide robust support to natural language query to RDBMS.<\/p>\n\n\n\n<p>\u4e0b\u56fe\u662f\u8be5Agent\u7684\u6574\u4f53\u7ed3\u6784\u3002\u8be5\u7ed3\u6784\u6574\u5408\u4e86\u591a\u4e2a\u5de5\u5177\u548cLLM\u6a21\u578b\u7684\u4f7f\u7528\uff0c\u7528\u4ee5\u63d0\u4f9b\u81ea\u7136\u8bed\u8a00\u8fdb\u884cRDBMS\u67e5\u8be2\u7684\u6709\u529b\u652f\u6301\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"621\" height=\"732\" src=\"https:\/\/www.linyinghao.cn\/wordpress\/wp-content\/uploads\/2025\/04\/20250409100108462.png\" alt=\"\" class=\"wp-image-1116\"\/><\/figure>\n\n\n\n<p>The responsibility of each node is described in following table:<\/p>\n\n\n\n<p>\u5176\u4e2d\u7684\u6bcf\u4e2a\u8282\u70b9\u7684\u529f\u80fd\u6982\u62ec\u89c1\u4e0b\u56fe\uff1a<\/p>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<figure class=\"wp-block-table is-style-regular\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Node<\/strong><\/td><td><strong>Next<\/strong><\/td><td><strong>Function<\/strong><\/td><td><strong>Use LLM<\/strong><\/td><td><strong>LLM Tool<\/strong><\/td><\/tr><tr><td>first_tool_call<\/td><td>Fix: list_table_tool<\/td><td>first_tool_call<\/td><td>No<\/td><td><\/td><\/tr><tr><td>list_tables_tool<\/td><td>Fix: model_get_schema<\/td><td>list_tables_tool(sql_db_list_tables)<\/td><td>No<\/td><td><\/td><\/tr><tr><td>model_get_schema<\/td><td>Fix: get_schema_tool<\/td><td><\/td><td>Yes<\/td><td>get_schema_tool<\/td><\/tr><tr><td>get_schema_tool<\/td><td>Fix: query_gen<\/td><td>get_schema_tool<\/td><td>No<\/td><td><\/td><\/tr><tr><td>query_gen<\/td><td>Condition: correct_query<br>Condition: END<\/td><td>query_gen_node<\/td><td>Yes<\/td><td>SubmitFinalAnswer<\/td><\/tr><tr><td>correct_query<\/td><td>Fix: execute_query<\/td><td>model_check_query<\/td><td>Yes<\/td><td>db_query_tool<\/td><\/tr><tr><td>execute_query<\/td><td>Fix: query_gen<\/td><td>db_query_tool<\/td><td>No<\/td><td><\/td><\/tr><tr><td>END<\/td><td><\/td><td><\/td><td><\/td><td><\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div><\/div>\n\n\n\n<h1 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Detail_Explanation\"><\/span>Detail Explanation<span class=\"ez-toc-section-end\"><\/span><\/h1>\n\n\n\n<p>Following section is detail explanation of each step.<\/p>\n\n\n\n<p>\u63a5\u4e0b\u6765\u662f\u5bf9\u6bcf\u4e00\u90e8\u5206\u7684\u8be6\u7ec6\u89e3\u8bfb\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Node_1_first_tool_node\"><\/span>Node 1: first_tool_node<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>\u8be5\u8282\u70b9\u4f7f\u7528\u4e86\u540c\u540d\u5de5\u5177\u51fd\u6570first_tool_call\u3002\u9996\u5148\u5b9a\u4e49\u51fd\u6570first_tool_call\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># \u5b9a\u4e49\u5de5\u5177\u51fd\u6570first_tool_call\ndef first_tool_call(state: State) -&gt; dict&#91;str, list&#91;AIMessage]]:\n    return {\n        \"messages\": &#91;\n            AIMessage(\n                content=\"\",\n                tool_calls=&#91;\n                    {\n                        \"name\": \"<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">sql_db_list_tables<\/mark>\",\n                        \"args\": {},\n                        \"id\": \"tool_abcd123\",\n                    }\n                ],\n            )\n        ]\n    }\n\n# \u7ed1\u5b9a\u5de5\u5177\u51fd\u6570\u5230\u8282\u70b9\nworkflow.add_node(\"<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">first_tool_call<\/mark>\", <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">first_tool_call<\/mark>)<\/code><\/pre>\n\n\n\n<p>\u53ef\u4ee5\u770b\u5230\uff0c\u8be5\u51fd\u6570\u56fa\u5b9a\u76f4\u63a5\u8fd4\u56de\u4e86\u4e00\u4e2aMessage\u5b57\u5178\uff0c\u662fhardcode\u5904\u7406\u7684\u3002\u5982\u679c\u8981\u8fdb\u884c\u62bd\u8c61\u5316\u5904\u7406\uff0c\u53ef\u4ee5\u8ba4\u4e3aLLM\u7ecf\u8fc7\u51b3\u7b56\uff0c\u53d1\u73b0\u9996\u5148\u9700\u8981\u5217\u4e3e\u51fa\u6570\u636e\u5e93\u4e2d\u7684\u6240\u6709\u8868\u5bf9\u8c61\uff0c\u90a3\u4e48\u9700\u8981\u8fdb\u884c\u4e00\u4e2a\u5de5\u5177\u8c03\u7528\uff0csql_db_list_tables\u5c31\u662f\u5408\u9002\u7684\u5de5\u5177\u3002\u56e0\u6b64\uff0c\u8be5\u8282\u70b9\u8fd4\u56de\u4e86\u51b3\u7b56\u7ed3\u679c\uff0cAIMessage\u4e2d\u5305\u542b\u4e86\u5de5\u5177\u540d\u79f0\uff0c\u8c03\u7528\u9700\u8981\u7684\u53c2\u6570\uff08sql_db_list_tables\u4e0d\u9700\u8981\u8f93\u5165\u53c2\u6570\uff0c\u6240\u4ee5args\u662f\u7a7a\u7684\uff09\uff0c\u4ee5\u53ca\u552f\u4e00\u7684id\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Node_2_list_tables_tool\"><\/span>Node 2: list_tables_tool<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>\u8be5\u8282\u70b9\u4f9d\u8d56\u540c\u540d\u5de5\u5177\u51fd\u6570list_tables_tool\uff0c\u4e0d\u8fc7\u5728\u5176\u57fa\u7840\u4e0a\u5305\u88f9\u4e86\u4e00\u5c42\u5f02\u5e38\u5904\u7406\u3002<\/p>\n\n\n\n<p>\u9996\u5148\u770b\u4e00\u4e0b\u5305\u88f9\u7684\u5f02\u5e38\u5904\u7406\u51fd\u6570create_tool_node_with_fallback\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def create_tool_node_with_fallback(tools: list) -&gt; RunnableWithFallbacks&#91;Any, dict]:\n    \"\"\"\n    Create a ToolNode with a fallback to handle errors and surface them to the agent.\n    \"\"\"\n    return ToolNode(tools).with_fallbacks(\n        &#91;RunnableLambda(handle_tool_error)], exception_key=\"error\"\n    )\n\n\ndef handle_tool_error(state) -&gt; dict:\n    error = state.get(\"error\")\n    tool_calls = state&#91;\"messages\"]&#91;-1].tool_calls\n    return {\n        \"messages\": &#91;\n            ToolMessage(\n                content=f\"Error: {repr(error)}\\n please fix your mistakes.\",\n                tool_call_id=tc&#91;\"id\"],\n            )\n            for tc in tool_calls\n        ]\n    }<\/code><\/pre>\n\n\n\n<p>\u8be5\u51fd\u6570\u6307\u5b9a\u4e86\u5f02\u5e38\u53d1\u751f\u7684\u60c5\u51b5\uff0c\u901a\u8fc7fallback\u5904\u7406\uff0c\u8c03\u7528handle_tool_error\u6765\u8fd4\u56de\u4e00\u4e2aToolMessage\uff0c\u5176\u4e2d\u5305\u542b\u4e86\u5f02\u5e38\u63d0\u793a\uff0c\u4ece\u800c\u9632\u6b62\u6574\u4e2aworkflow\u9677\u5165\u5f02\u5e38\u79cd\u690d\u3002<\/p>\n\n\n\n<p>\u63a5\u4e0b\u6765\u5b9a\u4e49\u5de5\u5177\u51fd\u6570list_tables_tool\u7684\u5b9a\u4e49\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from langchain_community.agent_toolkits import SQLDatabaseToolkit\n\ntoolkit = SQLDatabaseToolkit(db=db, llm=llm_chat_tongyi)\ntools = toolkit.get_tools()\n\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">list_tables_tool = next(tool for tool in tools if tool.name == \"sql_db_list_tables\")<\/mark><\/code><\/pre>\n\n\n\n<p>\u8fd9\u4e2a\u5b9a\u4e49\u770b\u8d77\u6765\u6bd4\u8f83\u7b80\u5355\uff0c\u4f7f\u7528\u5230\u4e86Langchain\u7684SQLDatabaseToolkit\u5de5\u5177\u4e2d\u9884\u5b9a\u4e49\u7684<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">sql_db_list_tables<\/mark>\u3002\u7136\u540eworkflow\u5c06\u8fd9\u4e2a\u5de5\u5177\u5305\u88f9\u4e86\u5f02\u5e38\u5904\u7406\u4e4b\u540e\uff0c\u7ed1\u5b9a\u7ed9\u4e86\u8be5\u8282\u70b9\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Add nodes for the first two tools\nworkflow.add_node(\n    \"<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">list_tables_tool<\/mark>\", create_tool_node_with_fallback(&#91;<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">list_tables_tool<\/mark>])\n)<\/code><\/pre>\n\n\n\n<p><strong>\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c\u8fd9\u4e00\u6b65\u53ea\u662f\u5c06\u5de5\u5177\u7ed1\u5b9a\u5230\u8282\u70b9\u4e0a\uff0c\u5e76\u4e0d\u4ee3\u8868\u5de5\u5177\u4e00\u5b9a\u4f1a\u88ab\u6267\u884c\u3002Langsmith\u6d4b\u8bd5\u7ed3\u679c\u63d0\u793a\uff0c\u5b9e\u9645\u5c1d\u8bd5\u6267\u884c\u7684\u5de5\u5177\uff0c\u662f\u53d6\u51b3\u4e8e\u524d\u4e00\u6b65\u7684AIMessage\u4e2d\u6307\u5b9a\u7684tool_calls\u4e2d\u7684\u5de5\u5177\u540d\u3002<\/strong><\/p>\n\n\n\n<p>\u5982\u679c\u524d\u4e00\u6b65\u6307\u5b9a\u7684\u5de5\u5177\u540d\u5728\u8fd9\u4e00\u6b65\u6ca1\u6709\u7ed1\u5b9a\u7684\u8bdd\uff0c\u8fd9\u91cc\u4f1a\u629b\u51fa\u7c7b\u4f3c&#8221;Error: sql_db_list_tables123 is not a valid tool, try one of [sql_db_list_tables].&#8221;\u7684\u9519\u8bef\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Node_3_model_get_schema\"><\/span>Node 3: model_get_schema<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>\u8fd9\u4e00\u6b65\u4f7f\u7528\u5230\u4e86LLM\u7684\u80fd\u529b\uff0c\u7ed3\u5408\u7528\u6237\u7684\u8f93\u5165\uff0c\u4ece\u6240\u6709\u7684\u8868\u5bf9\u8c61\u4e2d\u9009\u53d6\u76f8\u5173\u7684\u8868\uff0c\u5e76\u4e14\u6309\u7167\u5de5\u5177sql_db_schema\u7684\u8981\u6c42\u751f\u6210\u8c03\u7528\u53c2\u6570\u3002<\/p>\n\n\n\n<p>\u9996\u5148\uff0c\u4eceSQLDatabaseToolkit\u5de5\u5177\u96c6\u4e2d\u5f15\u7528\u4e86\u5de5\u5177sql_db_schema\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">get_schema_tool<\/mark> = next(tool for tool in tools if tool.name == \"<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">sql_db_schema<\/mark>\")<\/code><\/pre>\n\n\n\n<p>\u63a5\u4e0b\u6765\uff0c\u5c06\u8be5\u5de5\u5177\u7ed1\u5b9a\u7ed9\u4e86LLM\uff0c\u5e76\u5c06LLM\u7ed1\u5b9a\u7ed9\u4e86\u5f53\u524d\u8282\u70b9\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Add a node for a model to choose the relevant tables based on the question and available tables\n<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">model_get_schema<\/mark> = llm_chat_tongyi.bind_tools(\n    &#91;<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">get_schema_tool<\/mark>]\n)\nworkflow.add_node(\n    \"<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">model_get_schema<\/mark>\",\n    lambda state: {\n        \"messages\": &#91;model_get_schema.invoke(state&#91;\"messages\"])],\n    },\n)<\/code><\/pre>\n\n\n\n<p>\u8fd9\u6837\uff0cmodel_get_schema\u8fd9\u4e2a\u8282\u70b9\u5c31\u6709\u4e86LLM\u7684\u80fd\u529b\uff0c\u5e76\u4e14\u5b83\u77e5\u9053\u53ef\u4ee5\u9009\u7528get_schema_tool\u8fd9\u4e2a\u5de5\u5177\u3002<\/p>\n\n\n\n<p>\u5b9e\u9645\u6267\u884c\u7684\u8fc7\u7a0b\u4e2d\uff0c\u53ef\u4ee5\u89c2\u5bdf\u5230\u9488\u5bf9\u8fd9\u4e2aLLM\u7684\u8c03\u7528\uff0c\u63d0\u793a\u548c\u751f\u6210\u7ed3\u679c\u5206\u522b\u662f\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>LLM \u5f00\u59cb\u8c03\u7528:\nPrompts:\n&#91;\n  \"Human: Which sales agent made the most in sales in 2009?\\nAI: \\nTool: Album, Artist, Customer, Employee, Genre, Invoice, InvoiceLine, MediaType, Playlist, PlaylistTrack, Track\"\n]<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>LLM \u8c03\u7528\u7ed3\u675f:\n\"generations=&#91;&#91;ChatGeneration(generation_info={'finish_reason': 'tool_calls', 'logprobs': None}, message=AIMessage(content='', additional_kwargs={'tool_calls': &#91;{'id': 'call_a2612321b7ba4cef894766', 'function': {'arguments': '{\\\"table_names\\\": \\\"Invoice, Employee\\\"}', 'name': 'sql_db_schema'}, 'type': 'function', 'index': 0}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 23, 'prompt_tokens': 299, 'total_tokens': 322, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_name': 'qwen-plus', 'system_fingerprint': None, 'id': 'chatcmpl-57b00381-d313-9e23-bf89-0f34a77b7624', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-aa02fe70-a2aa-45a7-91e1-17c315da3c9b-0', tool_calls=&#91;{'name': 'sql_db_schema', 'args': {'table_names': 'Invoice, Employee'}, 'id': 'call_a2612321b7ba4cef894766', 'type': 'tool_call'}], usage_metadata={'input_tokens': 299, 'output_tokens': 23, 'total_tokens': 322, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}))]] llm_output={'token_usage': {'completion_tokens': 23, 'prompt_tokens': 299, 'total_tokens': 322, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_name': 'qwen-plus', 'system_fingerprint': None, 'id': 'chatcmpl-57b00381-d313-9e23-bf89-0f34a77b7624'} run=None type='LLMResult'\"<\/code><\/pre>\n\n\n\n<p>\u8be5\u8282\u70b9\u8fd4\u56de\u7684\u4fe1\u606f\u4e2d\uff0c\u53ef\u4ee5\u770b\u5230finish_reason\u662ftool_calls\uff0c\u8868\u660e\u6a21\u578b\u7ed9\u51fa\u4e86\u5904\u7406\u5efa\u8bae\uff0c\u662f\u5bf9\u5de5\u5177\u7684\u8c03\u7528\u3002\u5177\u4f53\u7684\u8c03\u7528\u65b9\u5f0f\uff0c\u662ftool_calls=[{&#8216;name&#8217;: &#8216;sql_db_schema&#8217;, &#8216;args&#8217;: {&#8216;table_names&#8217;: &#8216;Invoice, Employee&#8217;}, &#8216;id&#8217;: &#8216;call_a2612321b7ba4cef894766&#8217;, &#8216;type&#8217;: &#8216;tool_call&#8217;}]\u3002<\/p>\n\n\n\n<p>\u5728\u89e3\u8bfb\u5b9e\u9645\u884c\u4e3a\u7684\u65f6\u5019\uff0c\u6709\u4e00\u4e9b\u601d\u8003\u548c\u731c\u60f3\uff0c\u8bb0\u5f55\u4e0b\u6765\u4ee5\u4f9b\u65e5\u540e\u6709\u673a\u4f1a\u8fdb\u4e00\u6b65\u9a8c\u8bc1\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u4e3a\u4ec0\u4e48LLM\u4f1a\u4ea7\u751f\u8fd9\u6837\u7684\u8f93\u51fa\u683c\u5f0f\uff1f<\/strong>\u57fa\u4e8e\u5bf9\u4ee5\u4e0a\u89c2\u5bdf\u7ed3\u679c\u7684\u7406\u89e3\uff0c\u4e00\u4e2a\u731c\u60f3\u662f\uff0cLangchain\/Langgraph\u6846\u67b6\u5bf9\u4e8e\u6a21\u578b\u7684\u8c03\u7528\u505a\u4e86\u5c01\u88c5\uff0c\u5728\u5b9e\u9645\u8c03\u7528\u8fc7\u7a0b\u4e2d\uff0c\u5f15\u5bfc\u6a21\u578b\u6839\u636e\u63d0\u793a\uff0c\u751f\u6210\u4e86\u7279\u5b9a\u683c\u5f0f\u7684\u8f93\u51fa\u3002<\/li>\n\n\n\n<li><strong>\u4e3a\u4ec0\u4e48\u5728\u8f93\u51fa\u4e2d\uff0c\u53ef\u4ee5\u5f97\u5230\u8c03\u7528\u5de5\u5177\u7684\u5177\u4f53\u8868\u8fbe\u5f0f\uff1f<\/strong>Langchain\u6846\u67b6\u5b9e\u73b0\u4e86\u5bf9\u4e8e\u5de5\u5177\u51fd\u6570\u7684\u81ea\u52a8\u8bfb\u53d6\u548c\u89e3\u6790\u3002\u6846\u67b6\u5047\u5b9a\u5de5\u5177\u51fd\u6570\u7684\u51fd\u6570\u8bf4\u660e\uff0c\u4ee5\u53ca\u5185\u90e8\u53d8\u91cf\u4e2d\u7684name, description, args_schema\uff0c\u5305\u542b\u4e86\u51fd\u6570\u7684\u529f\u80fd\u63cf\u8ff0\u548c\u53c2\u6570\u63cf\u8ff0\u3002\u901a\u8fc7\u5c06\u8fd9\u4e9b\u4fe1\u606f\u8f6c\u5316\u4e3a\u683c\u5f0f\u5316\u7684\u4fe1\u606f\uff0c\u5e76\u63d0\u4f9b\u7ed9LLM\u9605\u8bfb\u548c\u7406\u89e3\uff0c\u5e2e\u52a9LLM\u6b63\u786e\u7406\u89e3\u51fd\u6570\u4f5c\u7528\uff0c\u5e76\u8fd4\u56de\u53ef\u4ee5\u8c03\u7528\u51fd\u6570\u7684\u8868\u8fbe\u5f0f\u3002<\/li>\n<\/ol>\n\n\n\n<p>\u8fd9\u4e00\u6b65\u5b9e\u9645\u4e0a\u662f\u501f\u7528\u4e86LLM\u7684\u7406\u89e3\u548c\u5224\u65ad\u80fd\u529b\uff0c\u5c06\u975e\u7ed3\u6784\u5316\u7684\u8981\u6c42\uff08\u7528\u6237\u81ea\u7136\u8bed\u8a00\u8f93\u51fa\uff09\uff0c\u7ed3\u5408\u7ed3\u6784\u5316\u7684\u5de5\u5177\u4fe1\u606f\uff0c\u751f\u6210\u4e86\u7ed3\u6784\u5316\u5de5\u5177\u8c03\u7528\u8868\u8fbe\u5f0f\uff0c\u4e3a\u4e0b\u4e00\u6b65\u5b9e\u9645\u6267\u884c\u63d0\u4f9b\u8f93\u5165\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Node_4_get_schema_tool\"><\/span>Node 4: get_schema_tool<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>\u8fd9\u4e00\u6b65\u975e\u5e38\u76f4\u63a5\uff0c\u5c31\u662f\u5c06\u540c\u540d\u5de5\u5177<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">get_schema_tool<\/mark>\u7ed1\u5b9a\u7ed9\u4e86<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">get_schema_tool<\/mark>\u8282\u70b9\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>workflow.add_node(\n    \"<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">get_schema_tool<\/mark>\",\n    create_tool_node_with_fallback(&#91;<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">get_schema_tool<\/mark>])\n)<\/code><\/pre>\n\n\n\n<p>\u5728\u524d\u4e00\u4e2a\u8282\u70b9\uff0c\u6211\u4eec\u901a\u8fc7LLM\u7684\u5224\u65ad\uff0c\u751f\u6210\u4e86tool_calls\u7684\u5177\u4f53\u6267\u884c\u8868\u8fbe\u5f0f\u3002\u5728\u8fd9\u4e00\u6b65\uff0c\u6846\u67b6\u4f1a\u5bfb\u627e\u53ef\u4ee5\u6267\u884c\u8868\u8fbe\u5f0f\u7684\u5de5\u5177\u3002\u6211\u4eec\u5728\u8fd9\u91cc\u5c06\u5de5\u5177\u7ed1\u5b9a\u540e\uff0c\u6846\u67b6\u5c31\u4f1a\u5b9e\u9645\u8c03\u7528\u5de5\u5177\u51fd\u6570\u8fdb\u884c\u5904\u7406\u4e86\u3002<\/p>\n\n\n\n<p>\u4e0b\u56fe\u7684Langsmith\u7684\u7ed3\u679c\u63d0\u793a\uff0c\u8fd9\u4e00\u6b65\u7684Input\u4e2d\u7684\u6700\u540e\u4e00\u9879\u662fAIMessage\uff0c\u5185\u5bb9\u662f\u524d\u4e00\u6b65\u4ea7\u751f\u7684\u8c03\u7528\u8868\u8fbe\u5f0f\uff1b\u800cOutput\u5219\u662f\u8868\u7ed3\u6784\u68c0\u67e5\u7684\u7ed3\u679c\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"2372\" height=\"1406\" src=\"https:\/\/www.linyinghao.cn\/wordpress\/wp-content\/uploads\/2025\/04\/20250411071750210.png\" alt=\"\" class=\"wp-image-1129\" style=\"width:840px;height:auto\" srcset=\"https:\/\/www.linyinghao.cn\/wordpress\/wp-content\/uploads\/2025\/04\/20250411071750210.png 2372w, https:\/\/www.linyinghao.cn\/wordpress\/wp-content\/uploads\/2025\/04\/20250411071750210-1536x910.png 1536w, https:\/\/www.linyinghao.cn\/wordpress\/wp-content\/uploads\/2025\/04\/20250411071750210-2048x1214.png 2048w\" sizes=\"auto, (max-width: 2372px) 100vw, 2372px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Node_5_query_gen\"><\/span>Node 5: query_gen<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>query_gen\u8282\u70b9\u662f\u8fd9\u4e2a\u5de5\u4f5c\u6d41\u4e2d\u6700\u590d\u6742\u7684\u4e00\u4e2a\uff0c\u4e3b\u8981\u4f53\u73b0\u5728\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u540c\u6837\u7ed1\u5b9a\u4e86LLM<\/li>\n\n\n\n<li>\u5305\u542b\u4e86\u51b3\u7b56\u8def\u5f84<\/li>\n<\/ul>\n\n\n\n<p>\u9996\u5148\uff0c\u7531\u4e8e\u5b83\u8981\u4f7f\u7528\u5230\u4e86LLM\u7684SQL\u751f\u6210\u529f\u80fd\uff0c\u9700\u8981\u901a\u8fc7\u590d\u6742\u7684\u63d0\u793a\u6765\u5c3d\u91cf\u63d0\u9ad8LLM\u7684\u751f\u6210\u51c6\u786e\u5ea6\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># \u5b9a\u4e49\u63d0\u793a\u4fe1\u606f\nquery_gen_system = \"\"\"You are a SQL expert with a strong attention to detail.\n...\nDO NOT make any DML statements (INSERT, UPDATE, DELETE, DROP etc.) to the database.\"\"\"\n\n# \u5b9a\u4e49\u63d0\u793a\u6a21\u677f\nquery_gen_prompt = ChatPromptTemplate.from_messages(\n    &#91;(\"system\", query_gen_system), (\"placeholder\", \"{messages}\")]\n)\n\nquery_gen = query_gen_prompt | llm_chat_tongyi.bind_tools(\n    &#91;SubmitFinalAnswer]\n)<\/code><\/pre>\n\n\n\n<p>\u5982\u679c\u8fd9\u4e00\u6b65\u6267\u884c\u6210\u529f\uff0c\u6211\u4eec\u5e0c\u671bLLM\u5c06\u6700\u7ec8\u5b8c\u6210\u7684\u6d88\u606f\u4f20\u9012\u7ed9END\u8282\u70b9\uff0c\u6240\u4ee5\u8fd9\u91cc\u6211\u4eec\u4e5f\u8981\u544a\u8bc9LLM\u6700\u7ec8\u5b8c\u6210\u6d88\u606f\u7684\u683c\u5f0f\u3002\u56e0\u6b64\uff0c\u6211\u4eec\u8981\u7ed9LLM\u7ed1\u5b9a\u4e00\u4e2a\u6700\u7ec8\u5b8c\u6210\u6d88\u606f\u7684\u683c\u5f0f\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># \u5b9a\u4e49\u6700\u7ec8\u5b8c\u6210\u6d88\u606f\u7684\u683c\u5f0f\nclass SubmitFinalAnswer(BaseModel):\n    \"\"\"Submit the final answer to the user based on the query results.\"\"\"\n\n    final_answer: str = Field(..., description=\"The final answer to the user\")\n\n# \u5c06\u63d0\u793a\u6a21\u677f\u548cLLM\u96c6\u5408\u8d77\u6765\uff0c\u5e76\u7ed1\u5b9a\u5de5\u5177\u7528\u4e8e\u6307\u5b9a\u6700\u7ec8\u5b8c\u6210\u6d88\u606f\u7684\u683c\u5f0f\nquery_gen = query_gen_prompt | llm_chat_tongyi.bind_tools(\n    &#91;SubmitFinalAnswer]\n)<\/code><\/pre>\n\n\n\n<p>LLM\u5b9a\u4e49\u5b8c\u6210\uff0c\u63a5\u4e0b\u6765\u8981\u5b9a\u4e49\u8282\u70b9\u7684\u51fd\u6570\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def query_gen_node(state: State):\n    message = query_gen.invoke(state)\n\n    # Sometimes, the LLM will hallucinate and call the wrong tool. We need to catch this and return an error message.\n    tool_messages = &#91;]\n    if message.tool_calls:\n        for tc in message.tool_calls:\n            if tc&#91;\"name\"] != \"SubmitFinalAnswer\":\n                tool_messages.append(\n                    ToolMessage(\n                        content=f\"Error: The wrong tool was called: {tc&#91;'name']}. Please fix your mistakes. Remember to only call SubmitFinalAnswer to submit the final answer. Generated queries should be outputted WITHOUT a tool call.\",\n                        tool_call_id=tc&#91;\"id\"],\n                    )\n                )\n    else:\n        tool_messages = &#91;]\n    return {\"messages\": &#91;message] + tool_messages}<\/code><\/pre>\n\n\n\n<p>\u8fd9\u91cc\u901a\u8fc7\u7684query_gen.invoke\u6267\u884c\u4e86LLM\uff0c\u7136\u540e\u5bf9\u4e8e\u8fd4\u56de\u7684Message\u8fdb\u884c\u4e86\u89e3\u6790\u3002\u5982\u679cToolMessage\u7684tool_calls\u4e2d\u5305\u542b\u4e86SubmitFinalAnswer\u7684\u5b57\u6837\uff0c\u610f\u5473\u7740LLM\u5224\u65ad\u8f93\u5165\u662f\u7b26\u5408\u9884\u671f\uff0c\u53ef\u4ee5\u4f5c\u4e3a\u6700\u7ec8\u7b54\u6848\u63d0\u4ea4\u7684\u3002\u53cd\u4e4b\u5219\u53ef\u80fdLLM\u4ea7\u751f\u4e86\u610f\u6599\u5916\u7684\u8f93\u51fa\uff0c\u8fd9\u79cd\u60c5\u51b5\u4e0b\u8981\u629b\u51fa\u7ea0\u6b63\u6d88\u606f\uff0c\u63d0\u793a\u53ea\u80fd\u4f7f\u7528SubmitFinalAnswer\u4f5c\u4e3a\u56de\u7b54\u3002<\/p>\n\n\n\n<p>\u7136\u540e\u5c06\u51fd\u6570query_gen_node\u7ed1\u5b9a\u7ed9\u5f53\u524d\u8282\u70b9\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>workflow.add_node(\"query_gen\", query_gen_node)<\/code><\/pre>\n\n\n\n<p>\u5f53\u524d\u8282\u70b9\u5305\u542b\u4e86\u51b3\u7b56\u8def\u5f84\uff0c\u4f1a\u4ea7\u751f\u5206\u652f\u5904\u7406\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Define a conditional edge to decide whether to continue or end the workflow\ndef should_continue(state: State) -&gt; Literal&#91;END, \"correct_query\", \"query_gen\"]:\n    messages = state&#91;\"messages\"]\n    last_message = messages&#91;-1]\n    # If there is a tool call, then we finish\n    if getattr(last_message, \"tool_calls\", None):\n        return END\n    if last_message.content.startswith(\"Error:\"):\n        return \"query_gen\"\n    else:\n        return \"correct_query\"\n\n# Specify the edges between the nodes\nworkflow.add_conditional_edges(\n    \"query_gen\",\n    should_continue,\n)<\/code><\/pre>\n\n\n\n<p>\u4ece\u4e0a\u9762\u7684\u4ee3\u7801\u53ef\u89c1\uff0c\u5f53\u524d\u8282\u70b9\u7684\u8f93\u51faMessage\u4e2d\uff0c\u6709\u4ee5\u4e0b\u51e0\u79cd\u53ef\u80fd\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Message\u4e2d\u5305\u542btool_call\uff0c\u5e76\u4e14\u662fSubmitFinalAnswer\u3002\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0cLLM\u5224\u65ad\u4e0b\u4e00\u6b65\u5408\u9002\u7684\u505a\u6cd5\u662fSubmitFinalAnswer\uff0c\u53ef\u4ee5\u6b63\u5e38\u8fd4\u56de\u7b54\u6848\u3002<\/li>\n\n\n\n<li>Message\u4e2d\u5305\u542bError\u7684\u5b57\u6837\u3002\u8fd9\u79cd\u60c5\u51b5\u5c31\u662f\u521a\u624d\u5904\u7406\u7684\u9884\u671f\u5916\u8f93\u5165\uff0c\u7ecf\u8fc7\u4f8b\u5916\u5904\u7406\u540eMessage\u88ab\u7ea0\u6b63\u4e3a\u5305\u542b\u4e86Error\u5b57\u6837\u7684\u4fe1\u606f\u3002\u8fd9\u79cd\u60c5\u51b5\u4e0b\u9700\u8981\u91cd\u65b0\u6267\u884c\u5f53\u524d\u8282\u70b9query_gen\u3002<\/li>\n\n\n\n<li>Message\u4e2d\u5305\u542bcorrect_query\u3002\u8fd9\u79cd\u60c5\u51b5\u610f\u5473\u7740LLM\u5224\u65ad\u4e0b\u4e00\u6b65\u5408\u9002\u7684\u505a\u6cd5\u662fcorrect_query\uff0c\u5e76\u4e14\u6ca1\u6709\u6307\u5b9atool_calls\u3002\u8fd9\u662f\u7b26\u5408\u6b63\u5e38\u5904\u7406\u7684\u9884\u671f\u3002<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Node_6_correct_query\"><\/span>Node 6: correct_query<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>\u8fd9\u4e2a\u8282\u70b9\u540c\u6837\u4f7f\u7528\u5230\u4e86LLM\u3002\u9996\u5148\u5b9a\u4e49\u5de5\u5177\u51fd\u6570db_query_tool\uff0c\u8fd9\u4e2a\u51fd\u6570\u5c1d\u8bd5\u6267\u884c\u67e5\u8be2\uff0c\u5982\u679c\u5931\u8d25\u4e86\uff0c\u5c31\u8fd4\u56de\u5e26\u6709Error\u5b57\u6837\u7684\u5b57\u7b26\u4e32\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def db_query_tool(query: str) -&gt; str:\n    \"\"\"\n    Execute a SQL query against the database and get back the result.\n    If the query is not correct, an error message will be returned.\n    If an error is returned, rewrite the query, check the query, and try again.\n    \"\"\"\n    result = db.run_no_throw(query)\n    if not result:\n        return \"Error: Query failed. Please rewrite your query and try again.\"\n    return result<\/code><\/pre>\n\n\n\n<p>\u63a5\u4e0b\u6765\u5b9a\u4e49LLM\u7684\u63d0\u793a\u6a21\u677f\uff0c\u5e76\u4e14\u5c06\u5de5\u5177db_query_tool\u7ed1\u5b9a\u7ed9LLM\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>query_check_system = \"\"\"You are a SQL expert with a strong attention to detail.\nDouble check the SQLite ...\n\nIf there are any of the above mistakes, rewrite the query. If there are no mistakes, just reproduce the original query.\n\nYou will call the appropriate tool to execute the query after running this check.\"\"\"\n\nquery_check_prompt = ChatPromptTemplate.from_messages(\n    &#91;(\"system\", query_check_system), (\"placeholder\", \"{messages}\")]\n)\nquery_check = query_check_prompt | llm_chat_tongyi.bind_tools(\n    &#91;db_query_tool], tool_choice=\"required\"\n)<\/code><\/pre>\n\n\n\n<p>\u63a5\u4e0b\u6765\uff0c\u5b9a\u4e49\u5de5\u5177\u51fd\u6570model_check_query\uff0c\u8fd9\u4e2a\u5de5\u5177\u51fd\u6570\u4f1a\u6267\u884cLLM\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def model_check_query(state: State) -&gt; dict&#91;str, list&#91;AIMessage]]:\n    \"\"\"\n    Use this tool to double-check if your query is correct before executing it.\n    \"\"\"\n    return {\"messages\": &#91;query_check.invoke({\"messages\": &#91;state&#91;\"messages\"]&#91;-1]]})]}<\/code><\/pre>\n\n\n\n<p>\u6700\u540e\u5c06\u5de5\u5177\u51fd\u6570model_check_query\u7ed1\u5b9a\u7ed9\u8282\u70b9\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Add a node for the model to check the query before executing it\nworkflow.add_node(\"correct_query\", model_check_query)<\/code><\/pre>\n\n\n\n<p>\u5728\u8fd0\u884c\u65f6\uff0c\u8fd9\u4e2a\u8282\u70b9\u4f1a\u4f7f\u7528LLM\u68c0\u67e5SQL\u3002\u5982\u679cSQL\u770b\u8d77\u6765\u8bed\u6cd5\u6b63\u786e\uff0c\u90a3\u4e48LLM\u4f1a\u8fd4\u56deAIMessage\uff0c\u5185\u5bb9\u5305\u542b\u5982\u4f55\u8c03\u7528db_query_tool\u6765\u6267\u884c\u67e5\u8be2\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"2372\" height=\"1406\" src=\"https:\/\/www.linyinghao.cn\/wordpress\/wp-content\/uploads\/2025\/04\/20250415062616354.png\" alt=\"\" class=\"wp-image-1135\" srcset=\"https:\/\/www.linyinghao.cn\/wordpress\/wp-content\/uploads\/2025\/04\/20250415062616354.png 2372w, https:\/\/www.linyinghao.cn\/wordpress\/wp-content\/uploads\/2025\/04\/20250415062616354-1536x910.png 1536w, https:\/\/www.linyinghao.cn\/wordpress\/wp-content\/uploads\/2025\/04\/20250415062616354-2048x1214.png 2048w\" sizes=\"auto, (max-width: 2372px) 100vw, 2372px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Node_7_execute_query\"><\/span>Node 7: execute_query<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>\u8fd9\u4e2a\u8282\u70b9\u975e\u5e38\u76f4\u89c2\uff0c\u76f4\u63a5\u5c06\u67e5\u8be2\u5de5\u5177\u7ed1\u5b9a\u5230\u8282\u70b9\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Add node for executing the query\nworkflow.add_node(\"execute_query\", create_tool_node_with_fallback(&#91;db_query_tool]))<\/code><\/pre>\n\n\n\n<p>\u901a\u8fc7\u8c03\u7528db_query_tool\u5de5\u5177\uff0c\u53ef\u4ee5\u5c06\u67e5\u8be2\u7ed3\u679c\u8fd4\u56de\u7ed9\u5de5\u4f5c\u6d41\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"2372\" height=\"1406\" src=\"https:\/\/www.linyinghao.cn\/wordpress\/wp-content\/uploads\/2025\/04\/20250415063125424.png\" alt=\"\" class=\"wp-image-1137\" srcset=\"https:\/\/www.linyinghao.cn\/wordpress\/wp-content\/uploads\/2025\/04\/20250415063125424.png 2372w, https:\/\/www.linyinghao.cn\/wordpress\/wp-content\/uploads\/2025\/04\/20250415063125424-1536x910.png 1536w, https:\/\/www.linyinghao.cn\/wordpress\/wp-content\/uploads\/2025\/04\/20250415063125424-2048x1214.png 2048w\" sizes=\"auto, (max-width: 2372px) 100vw, 2372px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Node_8_END\"><\/span>Node 8: END<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>\u7ed3\u675f\u5904\u7406<\/p>\n\n\n\n<h1 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Summary\"><\/span>Summary<span class=\"ez-toc-section-end\"><\/span><\/h1>\n\n\n\n<p>\u6574\u4e2a\u7684\u667a\u80fd\u4f53\u5904\u7406\u6d41\u7a0b\uff0c\u7ed3\u5408\u4e86Langgraph\u7684\u5de5\u5177\uff08\u4e3b\u8981\u662fSQLDatabaseToolkit\uff09\u548cLLM\uff0c\u5206\u522b\u5b9e\u73b0\u4e86\u5177\u4f53\u6570\u636e\u5e93\u64cd\u4f5c\u548c\u51b3\u7b56\u652f\u6301\u3002\u667a\u80fd\u4f53\u5de5\u4f5c\u6d41\u76f8\u6bd4\u5e38\u89c4\u5de5\u4f5c\u6d41\uff0c\u66f4\u52a0\u7a81\u51fa\u5176\u4e2dLLM\u7684\u53c2\u4e0e\u51b3\u7b56\u7684\u7279\u70b9\u3002\u5728\u6267\u884c\u7684\u8fc7\u7a0b\u4e2d\uff0c\u6839\u636eLLM\u7684\u5b9e\u9645\u5224\u65ad\uff0c\u4f1a\u4ea7\u751f\u4e0d\u540c\u7684\u5904\u7406\u5206\u652f\u3002<\/p>\n\n\n\n<p>\u7531\u4e8e\u4e0d\u786e\u5b9a\u6027\u7684\u5b58\u5728\uff0c\u5728\u667a\u80fd\u5de5\u4f5c\u6d41\u4e2d\u9488\u5bf9\u4f7f\u7528\u5230LLM\u7684\u8282\u70b9\uff0c\u9700\u8981\u7740\u91cd\u8003\u8651\u5404\u79cd\u610f\u5916\u7684\u573a\u666f\uff0c\u7ed3\u5408\u5f3a\u58ee\u7684fallback\u673a\u5236\uff0c\u786e\u4fdd\u667a\u80fd\u4f53\u603b\u662f\u53ef\u4ee5\u7ed9\u51fa\u5408\u7406\u7684\u6700\u7ec8\u5904\u7406\u7ed3\u679c\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a practice of Langgraph agent, which is used to interact with a sqlite database.<\/p>\n","protected":false},"author":3,"featured_media":921,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[25,2],"tags":[],"class_list":["post-1114","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai","category-2"],"_links":{"self":[{"href":"https:\/\/www.linyinghao.cn\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/1114","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.linyinghao.cn\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.linyinghao.cn\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.linyinghao.cn\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.linyinghao.cn\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1114"}],"version-history":[{"count":23,"href":"https:\/\/www.linyinghao.cn\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/1114\/revisions"}],"predecessor-version":[{"id":1142,"href":"https:\/\/www.linyinghao.cn\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/1114\/revisions\/1142"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.linyinghao.cn\/wordpress\/index.php?rest_route=\/wp\/v2\/media\/921"}],"wp:attachment":[{"href":"https:\/\/www.linyinghao.cn\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1114"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.linyinghao.cn\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1114"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.linyinghao.cn\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1114"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}