AI实践: 链和代理查询数据库 | 豆包MarsCode AI刷题

128 阅读6分钟

在这个文章中,主要是根据课程学习到的内容,来实践一下使用链和代理查询学生信息

一、LLM驱动下的查询流程

传统数据库交互的一个主要障碍在于,非技术人员缺乏编写SQL语句的能力。然而,通过结合自然语言处理和数据库查询的功能,我们可以让用户使用自然语言直接与数据库交互。以下是这一过程的简要说明:

  1. 自然语言提问:用户用自然语言提出问题,例如“有多少学生的GPA超过3.5?”
  2. LLM解析意图并生成SQL:LLM会解析该问题的意图,然后生成相应的SQL语句,例如 SELECT COUNT(*) FROM Students WHERE GPA > 3.5;
  3. 执行SQL查询:生成的SQL语句被执行,数据库处理后返回结果。
  4. LLM处理并转化结果:LLM将数据库返回的数据解析为自然语言回答。
  5. 输出结果:最终,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的异同

相同点

  • 大语言模型驱动ChainAgent 都是基于大语言模型(LLM)来实现自然语言到 SQL 查询的转换。两者在实际操作时,用户可以用自然语言描述查询需求,模型会根据描述自动生成 SQL 语句并执行。
  • 自然语言解析与转译:两者均需解析用户输入的自然语言查询意图,将其转译为 SQL 查询,通过 SQL 数据库接口执行并返回结果。
  • 支持多样数据库:无论是 Chain 还是 Agent,都能通过 SQLDatabase 工具集与多种数据库系统(例如 SQLite、PostgreSQL、MySQL 等)交互。

不同点

  • 查询灵活性

    • ChainChain 的查询流程通常是直接从自然语言到 SQL 语句的生成,适合于相对简单且明确的查询需求。它在执行查询时,直接将自然语言转化为 SQL 语句并返回结果,不会反复试探和修正生成的 SQL 语句。
    • AgentAgent 采用 ReAct("Reflect, Act, Check, and Try again")机制,允许代理在多轮交互中探索问题答案,支持执行复杂的多步骤查询。这一机制让 Agent 可以灵活地分步检查表结构、字段内容等信息,从而逐步生成 SQL 代码。
  • 纠错能力

    • ChainChain 没有内置的错误纠正机制。当生成的 SQL 查询出错时,它通常会直接返回错误信息。
    • AgentAgent 能够在 SQL 查询出错时捕捉错误,并根据错误信息重新生成或调整查询语句。这使得 Agent 在不确定的查询环境中更加鲁棒,适合应对不完全确定的输入或复杂查询。
  • 提示工程复杂度

    • ChainChain 生成 SQL 的提示工程较为简单,通常通过直接的上下文提示一次生成完整的 SQL 语句。
    • AgentAgent 的提示工程采用多轮推理策略,动态判断如何生成 SQL。例如,Agent 可能会首先调用数据库表结构的描述工具,获得上下文信息后再生成 SQL 代码。

总结

本文通过一个学生信息查询案例,展示了基于LLM的新型数据库查询方式如何简化数据库交互过程。总结来说,这一转变带来了以下优点:

  • 更易上手:非技术人员无需SQL知识即可查询数据库,极大地提升了数据查询的可达性。
  • 高效与直观:自然语言查询可以让复杂的数据操作更加直观,减少了学习和操作成本。
  • 人机协作的进一步提升:通过LLM的强大理解和生成能力,机器不再仅仅是执行者,更逐渐成为了用户的智能助手。