RAG 每日一技(十八):手写SQL-RAG太累?LangChain的SQL智能体(Agent)前来救驾!

前情回顾

在上一篇文章中,我们亲手实现了一个Text-to-SQL的完整流程。这是一个很棒的学习经历,但它也暴露了我们"手工作坊"模式的脆弱性。想象一下,一个稍有歧义的用户问题,一个微不足道的SQL语法错误,整个系统就会因为一次执行失败而彻底崩溃。它没有第二次机会,也缺乏应对复杂情况的智慧。

我们需要一个更强大的存在。它不仅仅是一个被动的"代码生成器",更应该是一个主动的"数据分析师"。它需要能够思考 ,能够选择工具 ,甚至能够在犯错后自我纠正

这个更强大的存在,就是智能体(Agent)

从"链"到"智能体":一次智能的飞跃

在我们之前的学习中,我们接触了LangChain的"链(Chain)"。"链"的工作模式是固定且线性的,就像一条预设好的流水线,每一步都严格按照顺序执行。

而"智能体(Agent)"则完全不同。它是一个动态的、循环的 执行单元。它的核心是一个由LLM驱动的推理引擎。它的工作遵循一个"思考-行动-观察"的循环:

思考(Thought) :根据用户目标和当前情况,分析下一步该做什么。 行动(Action) :从它拥有的"工具箱"中选择一个工具,并决定如何使用它。 观察(Observation):查看工具执行后的结果,这个结果会成为下一轮"思考"的输入。

这个循环会一直持续,直到它认为已经达成了用户的最终目标为止。

SQL智能体:你的专属数据库分析师

LangChain为我们提供了一个专门用于数据库交互的、预置好的专家------SQL智能体(SQL Agent)

我们可以把它想象成一个虚拟的数据库分析师。它的"工具箱"里装满了与数据库交互所需的各种工具,比如检查所有表名的工具、查询某个表结构的工具、执行SQL语句的工具等等。

它最强大的能力,就是自我纠错 。如果它生成的SQL语句在执行时报错了,它不会直接放弃。它会"观察"到数据库返回的错误信息,然后在下一轮"思考"中分析错误原因("哦,原来employees表里没有name字段,应该是employee_name"),然后生成一个修正后的SQL语句,再次尝试。

上手实战:释放SQL智能体的威力

让我们看看,用LangChain构建一个如此强大的Agent需要多少代码。你会惊讶于它的简洁。

首先,确保相关库已安装:

bash 复制代码
pip install langchain langchain-openai langchain_community sqlalchemy
准备阶段:连接数据库

我们将使用和上一篇完全相同的数据库。但这次,我们用LangChain推荐的方式来连接它。

python 复制代码
from langchain_community.utilities import SQLDatabase
from langchain_openai import ChatOpenAI
from langchain_community.agent_toolkits import create_sql_agent
import sqlite3
import os

# 设置你的OpenAI API Key
# os.environ["OPENAI_API_KEY"] = "sk-..."

# --- 准备数据库 ---
# 创建并填充数据库,与上一篇的代码完全相同
conn = sqlite3.connect('company.db')
cursor = conn.cursor()
cursor.execute("DROP TABLE IF EXISTS employees;")
cursor.execute("DROP TABLE IF EXISTS departments;")
cursor.execute('''
CREATE TABLE departments (
    department_id INTEGER PRIMARY KEY,
    department_name TEXT NOT NULL
);
''')
cursor.execute('''
CREATE TABLE employees (
    employee_id INTEGER PRIMARY KEY,
    employee_name TEXT NOT NULL,
    department_id INTEGER,
    salary INTEGER,
    FOREIGN KEY (department_id) REFERENCES departments(department_id)
);
''')
cursor.execute("INSERT INTO departments VALUES (1, '技术部'), (2, '市场部');")
cursor.execute("INSERT INTO employees VALUES (101, '张三', 1, 8000), (102, '李四', 1, 9500), (103, '王五', 2, 6000);")
conn.commit()
conn.close()

# 使用LangChain的SQLDatabase类来连接数据库
# 这会为Agent提供一个标准化的数据库接口
db = SQLDatabase.from_uri("sqlite:///company.db")
print("数据库连接成功,方言:", db.dialect)
创建并运行智能体

接下来就是最核心的部分了。我们只需要调用一个"工厂函数",就能瞬间创造出我们的SQL智能体。

python 复制代码
# 初始化LLM
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)

# 使用工厂函数create_sql_agent创建智能体
# 它会自动将LLM和数据库工具包(toolkit)组合起来
agent_executor = create_sql_agent(llm, db=db, agent_type="openai-tools", verbose=True)

# 让我们来问一个比昨天更复杂的问题
question = "技术部有多少名员工?他们的平均工资是多少?"
response = agent_executor.invoke({"input": question})

print("\n--- 最终回答 ---")
print(response["output"])
深入智能体的"内心世界"

由于我们设置了 verbose=True,在运行代码时,你将看到一段非常精彩的输出,它完整地展示了Agent的"思考-行动-观察"链条。

你会看到类似这样的输出:

vbnet 复制代码
> Entering new AgentExecutor chain...

Thought: The user is asking for the number of employees and the average salary for the '技术部' department.
I need to query the `employees` and `departments` tables.
I will first find the `department_id` for '技术部'.
Then I will use this `department_id` to filter the `employees` table to count the number of employees and calculate the average salary.

Action: sql_db_query
Action Input: SELECT department_id FROM departments WHERE department_name = '技术部'
Observation: [(1,)]
Thought: The department_id for '技术部' is 1.
Now I can query the `employees` table to get the count of employees and their average salary for this department.

Action: sql_db_query
Action Input: SELECT COUNT(employee_id), AVG(salary) FROM employees WHERE department_id = 1
Observation: [(2, 8750.0)]
Thought: I have the final answer. The count of employees is 2 and the average salary is 8750.0. I will now formulate the final response to the user.

> Finished chain.

--- 最终回答 ---
技术部有2名员工,他们的平均工资是8750.0。

这段日志完美地展示了Agent的智能:它将一个复杂问题,自主地分解成了两个步骤,并且像一个真正的数据分析师一样,一步步地推理,最终得出了正确的答案。这就是Agent的魅力!

总结与预告

今日小结: 今天我们完成了从"链"到"智能体"的认知飞跃。我们了解到,智能体(Agent)是一个由LLM驱动的、能够进行"思考-行动-观察"循环的动态推理引擎。LangChain的SQL智能体封装了强大的数据库交互工具和自我纠错能力,让我们无需编写复杂的Prompt和错误处理逻辑,就能构建出极其鲁棒的数据库问答机器人。

我们已经分别征服了非结构化的"文本世界"和结构化的"表格世界"。但是,真实世界的数据,往往是两者的混合体。

想象一下,一份公司的PDF年报,里面既有大段大段的管理层分析(非结构化文本),又嵌有密密麻麻的财务数据表(结构化表格)。对于这样的"半结构化"文档,我们该怎么办?

明天预告:RAG 每日一技(十九):当文本遇上表格,如何处理"半结构化"的复杂文档?

明天,我们将挑战这个极具现实意义的难题。我们将探索如何构建一个"多模态"的RAG系统,它能够智能地判断用户的问题是关于文本还是表格,并将问题路由给不同的处理引擎,最终实现对复杂混合文档的深度理解和问答。

相关推荐
Hello123网站1 分钟前
多墨智能-AI一键生成工作文档/流程图/思维导图
人工智能·流程图·ai工具
用户466537015051 分钟前
如何在 IntelliJ IDEA 中可视化压缩提交到生产分支
后端·github
星空下的曙光4 分钟前
mysql 命令语法操作篇 数据库约束有哪些 怎么使用
数据库·mysql
小楓12017 分钟前
MySQL數據庫開發教學(一) 基本架構
数据库·后端·mysql
天天摸鱼的java工程师9 分钟前
Java 解析 JSON 文件:八年老开发的实战总结(从业务到代码)
java·后端·面试
白仑色10 分钟前
Spring Boot 全局异常处理
java·spring boot·后端·全局异常处理·统一返回格式
染落林间色14 分钟前
达梦数据库-实时主备集群部署详解(附图文)手工搭建一主一备数据守护集群DW
数据库·sql
之诺16 分钟前
MySQL通信过程字符集转换
后端·mysql
喵手17 分钟前
反射机制:你真的了解它的“能力”吗?
java·后端·java ee
用户4665370150518 分钟前
git代码压缩合并
后端·github