使用LangGraph构建基于 SQL 数据的问答系统

在这篇博客中,我们将深入探讨如何使用 LangChain 和 LangGraph 构建一个智能的 SQL 查询助手。这个助手能够将自然语言问题转换为 SQL 查询,执行查询,并提供人性化的答案。更重要的是,它支持人机协同工作流程,让用户可以在关键步骤进行干预。

0.初始化sql数据

我们新建文件命名为 create_and_insert.sql

CREATE TABLE users (       姓名 TEXT NOT NULL,       年龄 INTEGER NOT NULL,       爱好 TEXT,       职业 TEXT   );      INSERT INTO users (姓名, 年龄, 爱好, 职业) VALUES   ('张三', 25, '篮球、游泳', '软件工程师'),   ('李四', 30, '阅读、旅行', '教师'),   ('王五', 22, '音乐、游戏', '学生'),   ('赵六', 28, '绘画、摄影', '设计师'),   ('孙七', 35, '足球、跑步', '医生'),   ('周八', 24, '舞蹈、瑜伽', '健身教练'),   ('吴九', 29, '电影、美食', '厨师'),   ('郑十', 27, '写作、书法', '作家'),   ('刘一', 32, '爬山、钓鱼', '销售经理'),   ('陈二', 26, '唱歌、看剧', '行政助理');

然后在本地安装sqlite3后执行:

sqlite3 test.db    .read create_and_insert.sql

1. 基础设置和依赖导入

from langchain_community.utilities import SQLDatabase   from langchain_openai import ChatOpenAI   from langchain import hub   from langchain_community.tools.sql_database.tool import QuerySQLDataBaseTool   from langgraph.graph import START, StateGraph   from langgraph.checkpoint.memory import MemorySaver   from typing_extensions import TypedDict, Annotated      # 初始化数据库连接   db = SQLDatabase.from_uri("sqlite:///test.db")

这段代码导入了必要的依赖并建立了数据库连接。SQLDatabase 是 LangChain 提供的一个实用工具,它能够将数据库操作无缝集成到 LLM 工作流中。

2. 定义应用程序状态

class State(TypedDict):       question: str    # 用户的自然语言问题       query: str       # 生成的 SQL 查询       result: str      # SQL 查询结果       answer: str      # 最终的自然语言答案

使用 TypedDict 定义应用程序状态,这不仅提供了类型提示,还明确了工作流中数据的流动方式。

3. 初始化语言模型

llm = ChatOpenAI(model="gpt-4-mini")   query_prompt_template = hub.pull("langchain-ai/sql-query-system-prompt")

我们使用 OpenAI 的 GPT-4-mini 模型,并从 LangChain Hub 获取预定义的 SQL 查询提示模板。这个模板经过优化,能够生成高质量的 SQL 查询。

4. 核心功能实现

4.1 SQL 查询生成

class QueryOutput(TypedDict):       """Generated SQL query."""       query: Annotated[str, ..., "Syntactically valid SQL query."]      def write_query(state: State):       """将自然语言问题转换为 SQL 查询"""       prompt = query_prompt_template.invoke({           "dialect": db.dialect,           "top_k": 10,           "table_info": db.get_table_info(),           "input": state["question"],       })       structured_llm = llm.with_structured_output(QueryOutput)       result = structured_llm.invoke(prompt)       return {"query": result["query"]}

这个函数负责将用户的自然语言问题转换为有效的 SQL 查询。它使用了:

  • 结构化输出确保生成语法正确的 SQL

  • 数据库模式信息以生成准确的查询

  • 预定义的提示模板优化查询生成

4.2 查询执行

def execute_query(state: State):       """执行 SQL 查询"""       execute_query_tool = QuerySQLDataBaseTool(db=db)       return {"result": execute_query_tool.invoke(state["query"])}

这个函数安全地执行生成的 SQL 查询,使用 LangChain 的 QuerySQLDataBaseTool 确保查询执行的安全性和可靠性。

4.3 答案生成

def generate_answer(state: State):       """使用查询结果生成自然语言答案"""       prompt = (           "Given the following user question, corresponding SQL query, "           "and SQL result, answer the user question.\n\n"           f'Question: {state["question"]}\n'           f'SQL Query: {state["query"]}\n'           f'SQL Result: {state["result"]}'       )       response = llm.invoke(prompt)       return {"answer": response.content}

这个函数将技术性的 SQL 结果转换为用户友好的自然语言答案。

5. 工作流编排与人工干预机制

5.1 基础工作流设置

memory = MemorySaver()   graph_builder = StateGraph(State).add_sequence([       write_query,       execute_query,       generate_answer   ])   graph_builder.add_edge(START, "write_query")

5.2 人工干预点配置

graph = graph_builder.compile(       checkpointer=memory,       interrupt_before=["execute_query"]  # 关键配置:在执行查询前中断   )

人工干预机制的实现主要依赖于以下几个关键点:

  1. 中断点设置
  • 使用 interrupt_before=["execute_query"] 参数指定在执行查询前进行中断

  • 这确保了在执行可能影响数据库的操作前,用户有机会审查和确认

  1. 状态管理
  • MemorySaver 用于保存工作流的状态

  • 这使得工作流可以在中断后继续执行,不会丢失之前的处理结果

  1. 流式执行
config = {"configurable": {"thread_id": "1"}}      # 第一阶段:执行到中断点   for step in graph.stream(       {"question": "请问有多少用户?"},       config,       stream_mode="updates",   ):       print(step)  # 显示每个步骤的执行结果
  1. 用户交互
try:       user_approval = input("Do you want to go to execute query? (yes/no): ")   except Exception:       user_approval = "no"  # 异常情况下默认拒绝执行
  1. 条件继续执行
if user_approval.lower() == "yes":       # 继续执行剩余的工作流       for step in graph.stream(None, config, stream_mode="updates"):           print(step)   else:       print("Operation cancelled by user.")

5.3 工作流执行过程

完整的执行流程如下:

1. 首先执行 write_query 步骤,生成 SQL 查询

2. 到达 execute_query 前自动中断

3. 显示生成的查询并等待用户确认

4. 根据用户的选择:

  • 如果确认,继续执行查询和生成答案

  • 如果拒绝,终止操作

5.4 示例输出

{'write_query': {'query': 'SELECT COUNT(*) as 用户数量 FROM users;'}}   {'__interrupt__': ()}   Do you want to go to execute query? (yes/no): yes   {'execute_query': {'result': '[(10,)]'}}   {'generate_answer': {'answer': '根据SQL查询的结果,用户数量为10。'}}

这种人工干预机制的优势在于:

  • 安全性:防止未经审查的查询直接执行

  • 可控性:用户可以在关键节点进行干预

  • 透明性:清晰展示每个步骤的执行结果

  • 灵活性:可以根据需要在不同节点添加中断点

6.总结

这个项目展示了如何将多个强大的工具(LangChain、LangGraph、GPT-4)组合起来,构建一个智能且安全的 SQL 查询助手。通过分层设计和人机协同,我们既保证了系统的自动化程度,又确保了操作的安全性。

关键特点:

  • 自然语言理解和 SQL 生成

  • 类型安全和错误处理

  • 人机协同的工作流程

  • 可扩展的模块化设计

这个方案可以作为构建其他 AI 驱动的数据库工具的参考架构。

7.完整代码

from langchain_community.utilities import SQLDatabase   from langchain_openai import ChatOpenAI   from langchain import hub   from langchain_community.tools.sql_database.tool import QuerySQLDataBaseTool   from langgraph.graph import START, StateGraph   from langgraph.checkpoint.memory import MemorySaver   from typing_extensions import TypedDict, Annotated         db = SQLDatabase.from_uri("sqlite:///test.db")         # 应用程序状态   class State(TypedDict):       question: str       query: str       result: str       answer: str      llm = ChatOpenAI(model="gpt-4o-mini")      query_prompt_template = hub.pull("langchain-ai/sql-query-system-prompt")         # 将问题转换为 SQL 查询   class QueryOutput(TypedDict):       """Generated SQL query."""          query: Annotated[str, ..., "Syntactically valid SQL query."]      def write_query(state: State):       """Generate SQL query to fetch information."""       prompt = query_prompt_template.invoke(           {               "dialect": db.dialect,               "top_k": 10,               "table_info": db.get_table_info(),               "input": state["question"],           }       )       structured_llm = llm.with_structured_output(QueryOutput)       result = structured_llm.invoke(prompt)       return {"query": result["query"]}         # 执行查询   def execute_query(state: State):       """Execute SQL query."""       execute_query_tool = QuerySQLDataBaseTool(db=db)       return {"result": execute_query_tool.invoke(state["query"])}         # 生成答案   def generate_answer(state: State):       """Answer question using retrieved information as context."""       prompt = (           "Given the following user question, corresponding SQL query, "           "and SQL result, answer the user question.\n\n"           f'Question: {state["question"]}\n'           f'SQL Query: {state["query"]}\n'           f'SQL Result: {state["result"]}'       )       response = llm.invoke(prompt)       return {"answer": response.content}         # 编排   memory = MemorySaver()   graph_builder = StateGraph(State).add_sequence(       [write_query, execute_query, generate_answer]   )   graph_builder.add_edge(START, "write_query")   # 人机协同   graph = graph_builder.compile(checkpointer=memory, interrupt_before=["execute_query"])      config = {"configurable": {"thread_id": "1"}}      for step in graph.stream(       {"question": "请问有多少用户?"},       config,       stream_mode="updates",   ):       print(step)      try:       user_approval = input("Do you want to go to execute query? (yes/no): ")   except Exception:       user_approval = "no"      if user_approval.lower() == "yes":       # If approved, continue the graph execution       for step in graph.stream(None, config, stream_mode="updates"):           print(step)   else:       print("Operation cancelled by user.")   '''   {'write_query': {'query': 'SELECT COUNT(*) as 用户数量 FROM users;'}}   {'__interrupt__': ()}   Do you want to go to execute query? (yes/no): yes   {'execute_query': {'result': '[(10,)]'}}   {'generate_answer': {'answer': '根据SQL查询的结果,用户数量为10。'}}   '''

如何学习大模型 AI ?

由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。

但是具体到个人,只能说是:

“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。

这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

  • 大模型 AI 能干什么?
  • 大模型是怎样获得「智能」的?
  • 用好 AI 的核心心法
  • 大模型应用业务架构
  • 大模型应用技术架构
  • 代码示例:向 GPT-3.5 灌入新知识
  • 提示工程的意义和核心思想
  • Prompt 典型构成
  • 指令调优方法论
  • 思维链和思维树
  • Prompt 攻击和防范

第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

  • 为什么要做 RAG
  • 搭建一个简单的 ChatPDF
  • 检索的基础概念
  • 什么是向量表示(Embeddings)
  • 向量数据库与向量检索
  • 基于向量检索的 RAG
  • 搭建 RAG 系统的扩展知识
  • 混合检索与 RAG-Fusion 简介
  • 向量模型本地部署

第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

  • 为什么要做 RAG
  • 什么是模型
  • 什么是模型训练
  • 求解器 & 损失函数简介
  • 小实验2:手写一个简单的神经网络并训练它
  • 什么是训练/预训练/微调/轻量化微调
  • Transformer结构简介
  • 轻量化微调
  • 实验数据集的构建

第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

  • 硬件选型
  • 带你了解全球大模型
  • 使用国产大模型服务
  • 搭建 OpenAI 代理
  • 热身:基于阿里云 PAI 部署 Stable Diffusion
  • 在本地计算机运行大模型
  • 大模型的私有化部署
  • 基于 vLLM 部署大模型
  • 案例:如何优雅地在阿里云私有部署开源大模型
  • 部署一套开源 LLM 项目
  • 内容安全
  • 互联网信息服务算法备案

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

在这里插入图片描述

<think>好的,我需要比较LangGraph和LangChain这两个库在AI语言模型中的特点、差异以及使用场景。首先,我应该先了解这两个库的基本信息,看看它们各自的功能和设计目标是什么。 LangChain我之前有所接触,它是一个用于构建基于语言模型的应用程序的框架,支持链式调用、代理、内存管理等。它帮助开发者将不同的模块组合起来,比如连接数据库、调用API或者使用工具集,适合复杂的应用开发。而LangGraph这个名字听起来可能和图形结构有关,可能更侧重于流程控制或者任务编排,比如用图结构来表示工作流,处理多步骤任务或者并行处理。 接下来需要查找两者的具体功能差异。LangChain的核心是链(Chain),允许用户将多个组件连接成序列化的流程,适用于需要逐步处理信息的场景。而LangGraph可能更强调用图来定义复杂的工作流,节点代表处理步骤,边代表流程方向,这样可以处理更复杂的依赖关系,比如分支、循环等结构,这在需要动态决策的应用中可能更有优势。 然后考虑使用场景。LangChain可能更适合需要模块化组合各种工具的应用,比如聊天机器人、问答系统,需要调用外部数据源或工具的情况。而LangGraph可能适用于需要复杂流程控制的场景,比如自动化工作流、多步骤决策系统,或者是需要并行处理任务的情况。 另外,技术架构上的差异也很重要。LangChain可能基于链式结构,而LangGraph基于有向无环图(DAG),这会影响它们处理任务的方式和效率。例如,DAG可以更灵活地管理任务之间的依赖,提高并行处理能力。 还要注意社区支持和集成生态。LangChain作为一个较为成熟的库,可能有更多的集成工具和社区资源,而LangGraph可能在特定领域如复杂工作流管理上有更深入的支持。 最后,结合用户提供的引用内容,比如引用[1]中提到CLIP训练的简化细节,可能在对比库的时候需要注意两者的实现细节是否影响了实际应用中的效率和效果。例如,LangGraph是否采用了某些优化策略,或者LangChain在模块化设计上的优势如何影响开发效率。 总结下来,我需要整理两者的功能特点、架构差异、适用场景,并举例说明它们在不同应用中的表现,确保回答结构清晰,符合用户要求的中文回答和格式规范。</think>### LangGraph vs LangChain 对比分析 #### 一、核心定位差异 1. **LangChain** 面向**模块化语言模型应用开发**,提供链式结构(Chains)整合工具、记忆系统、外部数据源。其核心设计允许开发者通过组合预定义组件(如检索器、提示模板)快速构建复杂应用,例如问答系统需连接向量数据库时,可直接调用`RetrievalQA`链[^1]。 2. **LangGraph** 专注于**基于图结构的任务编排**,通过有向无环图(DAG)定义节点与边的关系。适用于需要动态分支判断的场景(如根据用户输入切换处理路径),支持循环与状态传递,在自动化客服工单处理流程中可精准控制多步骤依赖。 #### 二、技术架构对比 | 特性 | LangChain | LangGraph | |---------------------|------------------------------------|------------------------------------| | **数据结构** | 链式结构(线性/分支) | 图结构(节点+边) | | **状态管理** | 通过Memory模块实现会话记忆 | 内置全局状态对象贯穿工作流 | | **并行处理** | 依赖外部异步框架 | 原生支持节点级并行执行 | | **典型应用** | 检索增强生成(RAG)、工具调用 | 多智能体协作、复杂决策流程 | #### 三、使用场景示例 1. **LangChain适用场景** - **客户服务机器人**:结合`ConversationalRetrievalChain`实现历史对话感知的响应生成 - **数据分析助手**:用`SQLDatabaseChain`直接解析自然语言查询并执行SQL ```python from langchain.chains import SQLDatabaseChain db_chain = SQLDatabaseChain(llm=llm, database=db) db_chain.run("Q3销售额最高的产品是什么?") ``` 2. **LangGraph适用场景** - **临床试验审批流程**:定义审批节点与条件分支(如伦理审查→数据验证→自动生成报告) - **多智能体辩论系统**:多个LLM智能体通过边连接进行论点交锋与共识达成 ```python from langgraph.graph import StateGraph workflow = StateGraph(initial_state={"query": "药物副作用报告"}) workflow.add_node("safety_check", safety_validator) workflow.add_edge("safety_check", "report_gen") ``` #### 四、关键差异总结 1. **流程复杂度** LangChain单个链通常处理<5个步骤,而LangGraph构建超过20个节点的医药研发流程(如化合物筛选→毒性预测→专利检索)。 2. **动态适应性** LangGraph支持实时修改图结构(如插入紧急审核节点),而LangChain需重构整个链。 3. **调试可视化** LangGraph提供图结构可视化工具(见官方Graph Explorer),直接显示节点状态流转,LangChain依赖日志追踪。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值