在这个文章中,主要是根据课程学习到的内容,来实践一下使用链和代理查询学生信息
一、LLM驱动下的查询流程
传统数据库交互的一个主要障碍在于,非技术人员缺乏编写SQL语句的能力。然而,通过结合自然语言处理和数据库查询的功能,我们可以让用户使用自然语言直接与数据库交互。以下是这一过程的简要说明:
- 自然语言提问:用户用自然语言提出问题,例如“有多少学生的GPA超过3.5?”
- LLM解析意图并生成SQL:LLM会解析该问题的意图,然后生成相应的SQL语句,例如
SELECT COUNT(*) FROM Students WHERE GPA > 3.5;。 - 执行SQL查询:生成的SQL语句被执行,数据库处理后返回结果。
- LLM处理并转化结果:LLM将数据库返回的数据解析为自然语言回答。
- 输出结果:最终,LLM生成自然语言答案并返回给用户,如“有120名学生的GPA超过3.5”。
这种流程无需用户具备SQL知识,也无需了解数据的存储结构,极大地提升了用户与数据库的交互体验。
二、学生信息的数据库创建与数据初始化
为了模拟这一流程,我们首先需要构建一个简单的学生信息数据库。在本例中,我们使用SQLite创建一个名为Students的表,来存储学生的基本信息,如姓名、年级、GPA等。
import sqlite3
# 连接到数据库
conn = sqlite3.connect('StudentManagement.db')
cursor = conn.cursor()
# 创建Students表
cursor.execute('''
CREATE TABLE Students (
ID INTEGER PRIMARY KEY,
Name TEXT NOT NULL,
Grade TEXT NOT NULL,
GPA REAL,
EnrollmentDate DATE,
Major TEXT,
CreditsCompleted INTEGER
);
''')
# 插入一些学生数据
students = [
('Alice', 'Freshman', 3.8, '2021-09-01', 'Computer Science', 20),
('Bob', 'Sophomore', 3.2, '2020-09-01', 'Mathematics', 45),
('Charlie', 'Junior', 3.5, '2019-09-01', 'Physics', 60),
('David', 'Senior', 3.9, '2018-09-01', 'Chemistry', 90),
('Eve', 'Sophomore', 2.8, '2020-09-01', 'Biology', 30)
]
for student in students:
cursor.execute('''
INSERT INTO Students (Name, Grade, GPA, EnrollmentDate, Major, CreditsCompleted)
VALUES (?, ?, ?, ?, ?, ?);
''', student)
# 提交更改并关闭连接
conn.commit()
conn.close()
上述代码创建了一个包含学生信息的Students表,并填充了若干示例数据。字段包括ID(学生ID)、Name(姓名)、Grade(年级)、GPA(平均绩点)、EnrollmentDate(入学日期)、Major(专业)、和CreditsCompleted(已完成学分)。
三、使用SQLDatabaseChain实现自然语言查询
为了让系统能够识别自然语言查询并将其转化为SQL语句,我们可以借助LangChain中的SQLDatabaseChain模块来完成。以下代码演示了如何通过SQLDatabaseChain将自然语言问题转换为SQL查询,并将查询结果用自然语言形式返回。
from langchain.utilities import SQLDatabase
from langchain.llms import OpenAI
from langchain_experimental.sql import SQLDatabaseChain
# 连接到StudentManagement数据库
db = SQLDatabase.from_uri("sqlite:///StudentManagement.db")
llm = OpenAI(temperature=0, verbose=True)
# 创建SQL数据库链实例
db_chain = SQLDatabaseChain.from_llm(llm, db, verbose=True)
# 示例查询
response = db_chain.run("有多少学生的GPA高于3.0?")
print(response)
response = db_chain.run("大二学生的平均GPA是多少?")
print(response)
response = db_chain.run("已完成学分最多的学生是谁?")
print(response)
运行上述代码时,SQLDatabaseChain将自然语言问题转化为SQL语句,并自动将结果转换为自然语言回答。例如,对于问题“有多少学生的GPA高于3.0?”,SQLDatabaseChain会将其转化为SELECT COUNT(*) FROM Students WHERE GPA > 3.0;,然后返回结果。
四、使用SQL Agent进行查询
在LangChain中,我们还可以通过SQL Agent来进行数据库查询。SQL Agent提供了额外的能力,可以在查询中结合数据库架构描述,并具有一定的纠错能力。这使得查询过程更具灵活性和鲁棒性,尤其适用于数据库结构复杂、查询较多的应用场景。
from langchain.utilities import SQLDatabase
from langchain.llms import OpenAI
from langchain.agents import create_sql_agent
from langchain.agents.agent_toolkits import SQLDatabaseToolkit
from langchain.agents.agent_types import AgentType
# 连接到StudentManagement数据库
db = SQLDatabase.from_uri("sqlite:///StudentManagement.db")
llm = OpenAI(temperature=0, verbose=True)
# 创建SQL Agent
agent_executor = create_sql_agent(
llm=llm,
toolkit=SQLDatabaseToolkit(db=db, llm=llm),
verbose=True,
agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
)
# 示例问题列表
questions = [
"谁的GPA最高?",
"计算机科学专业的学生有多少人?",
]
for question in questions:
response = agent_executor.run(question)
print(response)
SQL Agent采用了一个分步推理的方法,通常会先调用数据库的描述命令来理解表结构,然后逐步生成查询语句。当遇到错误时,Agent可以重新生成SQL语句,从而进一步提高查询的准确性。
五、Chain和Agent的异同
相同点
- 大语言模型驱动:
Chain和Agent都是基于大语言模型(LLM)来实现自然语言到 SQL 查询的转换。两者在实际操作时,用户可以用自然语言描述查询需求,模型会根据描述自动生成 SQL 语句并执行。 - 自然语言解析与转译:两者均需解析用户输入的自然语言查询意图,将其转译为 SQL 查询,通过 SQL 数据库接口执行并返回结果。
- 支持多样数据库:无论是
Chain还是Agent,都能通过SQLDatabase工具集与多种数据库系统(例如 SQLite、PostgreSQL、MySQL 等)交互。
不同点
-
查询灵活性:
- Chain:
Chain的查询流程通常是直接从自然语言到 SQL 语句的生成,适合于相对简单且明确的查询需求。它在执行查询时,直接将自然语言转化为 SQL 语句并返回结果,不会反复试探和修正生成的 SQL 语句。 - Agent:
Agent采用 ReAct("Reflect, Act, Check, and Try again")机制,允许代理在多轮交互中探索问题答案,支持执行复杂的多步骤查询。这一机制让Agent可以灵活地分步检查表结构、字段内容等信息,从而逐步生成 SQL 代码。
- Chain:
-
纠错能力:
- Chain:
Chain没有内置的错误纠正机制。当生成的 SQL 查询出错时,它通常会直接返回错误信息。 - Agent:
Agent能够在 SQL 查询出错时捕捉错误,并根据错误信息重新生成或调整查询语句。这使得Agent在不确定的查询环境中更加鲁棒,适合应对不完全确定的输入或复杂查询。
- Chain:
-
提示工程复杂度:
- Chain:
Chain生成 SQL 的提示工程较为简单,通常通过直接的上下文提示一次生成完整的 SQL 语句。 - Agent:
Agent的提示工程采用多轮推理策略,动态判断如何生成 SQL。例如,Agent可能会首先调用数据库表结构的描述工具,获得上下文信息后再生成 SQL 代码。
- Chain:
总结
本文通过一个学生信息查询案例,展示了基于LLM的新型数据库查询方式如何简化数据库交互过程。总结来说,这一转变带来了以下优点:
- 更易上手:非技术人员无需SQL知识即可查询数据库,极大地提升了数据查询的可达性。
- 高效与直观:自然语言查询可以让复杂的数据操作更加直观,减少了学习和操作成本。
- 人机协作的进一步提升:通过LLM的强大理解和生成能力,机器不再仅仅是执行者,更逐渐成为了用户的智能助手。