在前四章,我们已经一步步搭建起了LangChain的核心能力:接入大模型(大脑)、添加短期记忆(记住对话)、调用Tool工具(动手做事)、定制专属知识库(记住私有文档)。但还有一个非常实用、新手容易上手,且能直接落地到工作中的能力——用大模型操作数据库,也就是本章的核心:SQL Agent。
很多新手看到“数据库”“SQL”就头疼,觉得这是程序员的专属技能,自己不懂SQL、不会写查询语句,就没法用。但LangChain的SQL Agent,恰恰解决了这个痛点:它能让大模型“读懂你的自然语言问题”,自动转换成SQL语句,去查询数据库,再把查询结果整理成通俗易懂的自然语言反馈给你——你不用写一行SQL,就能轻松查数据库里的数据。
一、先搞懂:SQL Agent到底是什么?(新手必看)
结合前几章的知识,我们用一句大白话总结,瞬间看懂:
SQL Agent,本质是「LangChain专门针对数据库场景,封装的“智能决策者”」——它整合了「大模型(理解问题、写SQL)+ SQL Tool(执行SQL查询)+ 逻辑判断(验证SQL正确性、处理查询结果)」,核心作用就是让不懂SQL的人,也能通过自然语言,快速查询数据库里的数据。
拆解成3个简单步骤,和我们前四章学的逻辑完全一致:
1. 你输入自然语言问题;

2. SQL Agent(决策者):让大模型理解问题,自动转换成正确的SQL语句,同时验证SQL是否合法(避免报错);
3. SQL Agent调用SQL Tool,执行SQL语句,查询数据库,再把查询到的冰冷数据(比如“125800”),整理成自然语言(比如“11月份总销售额为125800元”)反馈给你。
关键区分:SQL Agent 和 普通SQL查询(新手别搞混)
很多新手会把SQL Agent和“手动写SQL查询”搞混,这里用一张通俗对比,快速分清核心差异:
- 手动写SQL:需要你懂SQL语法、知道数据库表结构(比如表名、字段名),写错一个符号就会查询失败;
- SQL Agent:你不用懂SQL、不用记表结构,只要用自然语言提问,Agent会自动搞定“写SQL、查数据、整理结果”,容错率高,适合新手和非技术人员。
补充:SQL Agent还能衔接第四章的定制知识库——如果把数据库表结构、字段说明导入知识库,Agent会更精准地写SQL,避免因不懂表结构而报错。
二、为什么要学SQL Agent?3个核心价值(贴合工作场景)
对于新手来说,SQL Agent不是“锦上添花”,而是“能直接提升工作效率”的实用技能,尤其是职场人,学会后能省大量时间,核心价值有3个:
1. 非技术人员也能“查数据库”,不用求程序员
很多职场人(比如运营、财务、行政),工作中需要查数据库里的数据(比如销量、营收、员工考勤),但自己不懂SQL,每次都要找程序员帮忙写SQL、查数据,耗时又麻烦。学会SQL Agent后,自己用自然语言提问,就能快速拿到结果,不用再求人。
2. 节省时间,不用写SQL、不用调试报错
哪怕是懂一点SQL的人,写复杂查询语句(比如多表关联、条件筛选、统计计算),也要反复调试,避免语法错误。SQL Agent能自动写SQL、验证SQL正确性,不用你调试,几秒就能拿到结果。
3. 衔接前四章,搭建“完整数据查询助手”
结合前四章的内容,SQL Agent能和「大模型+短期记忆+Tool+知识库」完美衔接:比如你连续提问“查11月份总销售额”“再查10月份的,对比一下两者差异”,Agent会记住你的上下文(短期记忆),自动对比两次查询结果,不用你再重复提问。
三、新手入门:SQL Agent的核心组件(不用记复杂原理)
LangChain实现SQL Agent,不用复杂配置,核心靠3个组件,和前四章的组件逻辑一致,新手只要记住它们的作用,后续实操会更轻松:
1. 数据库连接(Database Connection)——“连接你的数据库”
作用:相当于“桥梁”,让LangChain能连接到你的数据库(不管是本地数据库,还是线上数据库)。新手入门,我们用「本地SQLite数据库」(不用安装、不用配置,自带Python,直接能用),避免复杂的数据库搭建。
2. SQL Tool ——“执行SQL语句、查询数据”
作用:和第三章学的Tool本质一样,是SQL Agent的“手脚”,负责执行Agent生成的SQL语句,从数据库里查询数据,再把数据返回给Agent。LangChain已经内置了SQL Tool,不用你自己开发,直接调用即可。
3. SQL Agent(智能体)——“核心决策者”
作用:相当于“大脑的延伸”,负责理解你的自然语言问题、生成SQL语句、验证SQL是否正确、处理Tool返回的数据、整理成自然语言回答。LangChain提供了现成的SQL Agent,我们只要把“数据库连接+SQL Tool+大模型”交给它,它就能自动工作。
先贴上今天的完整代码:
import osfrom langchain_community.utilities import SQLDatabasefrom langchain.agents import create_agentfrom langchain_openai import ChatOpenAIfrom langgraph.checkpoint.memory import InMemorySaver from config import API_KEY, BASE_URL, MODEL_NAME, DB_USER, DB_PASSWORD, DB_HOST, DB_PORT, DB_NAMEfrom langchain_community.agent_toolkits import SQLDatabaseToolkit# 系统提示词模板SYSTEM_PROMPT = """ 您是一个专业的MySQL数据库交互专家,专注于处理与数据库操作相关的问题。 **核心能力:** - 直接执行SQL语句(查询、插入、更新、删除、建表等) - 自动进行数据验证和结果检查 **重要规则(必须遵守):** 1. 必须完全信任和尊重工具查询结果,即使结果为空或与预期不符 2. 如果sql_db_list_tables工具返回空列表[],说明数据库确实没有表 3. 绝对不要基于训练数据中的常见模式来编造表信息 4. 工具返回什么就回答什么,不要添加、修改或忽略工具结果 当前已知信息: - 数据库类型: MySQL - 工具查询结果是最权威的信息源 **工作流程:** 1. **需求分析**:理解用户要执行的操作类型 2. **结构探查**:查看相关表结构和数据 3. **SQL构建**:构建合适的SQL语句 4. **执行验证**:执行SQL并验证结果 要求: 1,表和字段,都应该有中文注释 2,表名和字段名都应该是英文,下划线分割,如果创建表时用户提供的属性是中文,你应该翻译为对应英文创建字段,用户的中文作为字段注释。如果用户给的是英文字段,那么就用这个作为字段名称,对应的翻译作为字段注释。 请用中文回复,操作结果要清晰易懂。"""def setup_database(): """初始化数据库连接""" db_uri = f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}" try: db = SQLDatabase.from_uri(db_uri, sample_rows_in_table_info=3) print("数据库连接成功") print(f"可用表: {db.get_usable_table_names()}") return db except Exception as e: print(f"数据库连接失败: {e}") return Nonedef create_sql_agent(): """创建SQL代理""" # 1. 初始化数据库 db = setup_database() if not db: return None # 2. 初始化模型 llm = ChatOpenAI( model=MODEL_NAME, openai_api_key=API_KEY, openai_api_base=BASE_URL, temperature=0, max_tokens=262144 ) # 3. 创建工具集 toolkit = SQLDatabaseToolkit(db=db, llm=llm) tools = toolkit.get_tools() # 4. 创建代理 agent = create_agent( llm, tools, checkpointer=InMemorySaver(), system_prompt=SYSTEM_PROMPT ) return agentdef main(): """主函数""" agent = create_sql_agent() if not agent: print("代理初始化失败,程序退出") return print("SQL代理已就绪,请输入数据库操作需求(输入quit退出)") while True: try: user_input = input("请输入需求:").strip() if user_input.lower() in ["quit", "exit"]: print("程序退出!") break if not user_input: print("请输入有效需求!") continue # 执行查询 inputs = {"messages": [{"role": "user", "content": user_input}]} response = agent.invoke(inputs,{"configurable": {"thread_id": "1"}}) # 输出结果 if response and "messages" in response: content = response["messages"][-1].content print(f"回复: {content}") except KeyboardInterrupt: print("用户中断,程序退出!") break except Exception as e: print(f"执行出错: {e}")if __name__ == "__main__": main()然后咱们把今天的步骤分解一下1,准备环境,今日的案例使用到的数据库为mysql
2,添加配置文件,在config.py中,我们加入数据库的连接信息,这里我换了一个参数更多的模型,小参数的模型,效果不太好。不过参数多了,调用的时长也变长了
# 1. 数据库配置DB_USER = "root" # 数据库用户名DB_PASSWORD = "root123" # 数据库密码DB_HOST = "10.10.18.91" # 数据库IP DB_PORT = "3306" # 数据库端口DB_NAME = "ai_agent" # 数据库名MODEL_NAME="moonshotai/Kimi-K2-Instruct-0905"3,连接数据库,这里咱们只用最简单的配置
def setup_database(): """初始化数据库连接""" db_uri = f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}" try: db = SQLDatabase.from_uri(db_uri, sample_rows_in_table_info=3) print("数据库连接成功") print(f"可用表: {db.get_usable_table_names()}") return db except Exception as e: print(f"数据库连接失败: {e}") return Nonesample_rows_in_table_info=3 这个参数配置的是提供给ai大模型的示列数据行数在这个初始化连接的方法中,还有一个比较重要的参数engine_args @classmethod def from_uri( cls, database_uri: Union[str, URL], engine_args: Optional[dict] = None, **kwargs: Any, ) -> SQLDatabase: """Construct a SQLAlchemy engine from URI.""" _engine_args = engine_args or {} return cls(create_engine(database_uri, **_engine_args), **kwargs)这个参数可以配置连接池相关信息,在这里咱们先不用4,初始化模型,这里咱们设置大模型
llm = ChatOpenAI( model=MODEL_NAME, openai_api_key=API_KEY, openai_api_base=BASE_URL, temperature=0, max_tokens=262144 )temperature=0, # 温度参数(0-2),控制输出的随机性 # 0 = 确定性输出,2 = 最大随机性这里因为使用数据库,为防止幻觉限制为05,使用langchain提供的sql工具
# 3. 创建工具集 toolkit = SQLDatabaseToolkit(db=db, llm=llm) tools = toolkit.get_tools()如果想看看都有哪些tool,可以在这下面打印出来
for tool in tools: print(f"{tool.name}: {tool.description}\n")tools中的工具
6,创建agent
跟到这里的同学能够发现我的提示词变了,而且比之前的要复杂很多。这里就涉及到提示词工程了,感兴趣的小伙伴可以继续使用原来提示词对比一下效果
# 系统提示词模板SYSTEM_PROMPT = """ 您是一个专业的MySQL数据库交互专家,专注于处理与数据库操作相关的问题。 **核心能力:** - 直接执行SQL语句(查询、插入、更新、删除、建表等) - 自动进行数据验证和结果检查 **重要规则(必须遵守):** 1. 必须完全信任和尊重工具查询结果,即使结果为空或与预期不符 2. 如果sql_db_list_tables工具返回空列表[],说明数据库确实没有表 3. 绝对不要基于训练数据中的常见模式来编造表信息 4. 工具返回什么就回答什么,不要添加、修改或忽略工具结果 当前已知信息: - 数据库类型: MySQL - 工具查询结果是最权威的信息源 **工作流程:** 1. **需求分析**:理解用户要执行的操作类型 2. **结构探查**:查看相关表结构和数据 3. **SQL构建**:构建合适的SQL语句 4. **执行验证**:执行SQL并验证结果 要求: 1,表和字段,都应该有中文注释 2,表名和字段名都应该是英文,下划线分割,如果创建表时用户提供的属性是中文,你应该翻译为对应英文创建字段,用户的中文作为字段注释。如果用户给的是英文字段,那么就用这个作为字段名称,对应的翻译作为字段注释。 请用中文回复,操作结果要清晰易懂。""" agent = create_agent( llm, tools, checkpointer=InMemorySaver(), system_prompt=SYSTEM_PROMPT )普通AI(简短提示词)
# 就像普通助手 - 灵活但有创意SYSTEM_PROMPT = "你是一个有用的助手"- 工作方式:基于训练数据生成回答
- 风险:可能"编造"信息,但影响不大
- 例子:问"法国的首都是什么?" - 即使记错了也问题不大
数据库AI(严格提示词)
# 就像银行柜员 - 必须严格按系统操作SYSTEM_PROMPT = """严格的操作规则..."""- 工作方式:必须100%基于真实数据
- 风险:如果"编造"会导致严重后果
- 例子:问"我的账户余额多少?" - 绝对不能猜!
接下来就是要测试了
我这边先创建两个有关联关系的表,创建表这部分还要对关系型数据库有一些了解。
创建公司表:
帮我创建一个公司表,属性有Id,公司名称,公司位置,法人名称,注册资本创建公司表
创建员工表:
创建一个员工表,和公司表关联,属性有Id,姓名,手机号,薪水,职位,公司Id创建员工表与公司表关联
插入测试数据:
给公司表插入两条测试数据,给员工表插入10条测试数据插入测试数据
开始查询:
我输入了需求:这里我还打错字了[捂脸]
统计一下,这些公司的月薪数量,从小打到排序,查询结果
这里能看到,我打了错字,但是他还是从语义中理解了我的意图,并且还做了一部分我要求的额外的工作,比如平均月薪、员工数量、两家公司对比,如果是自己玩的话,我觉得还是挺好的,但是在工作中遇到这样的问题,可能还有点麻烦。想要去除他这种发挥,还需要做工作。
第二个问题:
为啥的月薪更高呢?