Bootstrap

如何使用LangChain库使用大模型与SQL数据库进行交互


前言

在大模型交互的时候,我们有时需要大模型借助已有的数据来作答,通常业务数据会存储在数据库里,需要大模型具备生成正确sql并查询数据库的能力。因此我们一起来练习如何使用LangChain库使用大模型(如GPT-4)与SQL数据库进行交互。


一、手动告知大模型数据库结构

要想大模型生成我们需要的数据首先要解决的重要问题是,大模型(例如GPT-4)如何知道数据库表的结构。为了实现这一点,我们需要在提示中包含关于数据库模式(schema)的信息。这样,模型可以利用这些信息生成正确的SQL查询。

1. 示例

以下是一个完整示例,展示如何将数据库表结构信息包含在提示中:

1)首先,你需要确保安装了相关的Python包。你可以使用以下命令安装:

pip install langchain openai sqlalchemy

2)接下来是示例代码:

import os
from langchain import OpenAI, PromptTemplate
from langchain.chains import LLMChain
from sqlalchemy import create_engine, text

# 设置OpenAI API密钥
os.environ['OPENAI_API_KEY'] = 'your_openai_api_key'

# 创建SQLAlchemy引擎连接到SQLite数据库(或其他数据库)
engine = create_engine('sqlite:///example.db')

# 创建一个示例表和一些数据
with engine.connect() as conn:
    conn.execute(text('''
    CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY,
        name TEXT,
        age INTEGER
    )
    '''))
    conn.execute(text('''
    INSERT INTO users (name, age) VALUES ('Alice', 30), ('Bob', 24), ('Charlie', 29)
    '''))
    conn.execute(text('''
    CREATE TABLE IF NOT EXISTS orders (
        id INTEGER PRIMARY KEY,
        user_id INTEGER,
        amount DECIMAL,
        FOREIGN KEY(user_id) REFERENCES users(id)
    )
    '''))
    conn.execute(text('''
    INSERT INTO orders (user_id, amount) VALUES (1, 99.99), (2, 50.00), (3, 75.50)
    '''))

# 定义一个函数来执行SQL查询
def execute_query(query):
    with engine.connect() as conn:
        result = conn.execute(text(query))
        return result.fetchall()

# 获取数据库的表结构信息
def get_table_schema():
    with engine.connect() as conn:
        result = conn.execute(text("SELECT name FROM sqlite_master WHERE type='table';"))
        tables = result.fetchall()
        schema = {}
        for table in tables:
            table_name = table[0]
            result = conn.execute(text(f"PRAGMA table_info({table_name});"))
            columns = result.fetchall()
            schema[table_name] = [column[1] for column in columns]
        return schema

# 创建一个LangChain模型
llm = OpenAI(model_name='text-davinci-003')

# 定义查询数据库的函数
def query_database(prompt, schema):
    # 将表结构信息包含在提示中
    schema_info = "\n".join([f"Table {table}: {', '.join(columns)}" for table, columns in schema.items()])
    full_prompt = f"""
    以下是数据库的表结构信息:
    {schema_info}

    请根据以下描述生成一个SQL查询:
    描述: {prompt}

    生成的SQL查询:
    """
    chain = LLMChain(llm=llm, prompt=PromptTemplate(full_prompt))
    query = chain.run()
    result = execute_query(query)
    return result

# 获取数据库表结构
schema = get_table_schema()

# 示例:生成一个查询并执行
prompt = "查询所有年龄大于25岁的用户的姓名。"
result = query_database(prompt, schema)
print(result)

2. 解释

1) 获取数据库表结构
- get_table_schema() 函数从数据库中提取表结构信息,并返回一个包含表名和列名的字典。

2) 包含表结构信息的提示
- 在 query_database() 函数中,将表结构信息添加到提示中,使得模型能够了解数据库的模式。

3) 完整的提示模板
- 在生成SQL查询时,包含表结构信息的完整提示会传递给模型,从而帮助其生成正确的SQL查询。

通过这种方式,大模型能够根据提供的表结构信息生成适当的SQL查询。这样可以确保模型能够理解数据库的结构,并生成符合该结构的查询。

二、LangChain 提供了一些内置工具和实用程序来简化与数据库的交互

LangChain 提供了一些内置工具和实用程序来简化与数据库的交互,包括自动获取表结构信息并生成相应的SQL查询。create_sql_query_chainSQLDatabase 类确实可以用来实现这一功能。

以下是一个更完整的示例,演示如何使用这两个类与数据库交互:

1. 安装所需的包

确保安装了所需的包:

pip install langchain openai sqlalchemy langchain_community

2. 示例代码

import os
from langchain import OpenAI
from langchain.chains import create_sql_query_chain
from langchain_community.utilities import SQLDatabase
from sqlalchemy import create_engine, text

# 设置OpenAI API密钥
os.environ['OPENAI_API_KEY'] = 'your_openai_api_key'

# 创建SQLAlchemy引擎连接到SQLite数据库(或其他数据库)
engine = create_engine('sqlite:///example.db')

# 创建一个示例表和一些数据
with engine.connect() as conn:
    conn.execute(text('''
    CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY,
        name TEXT,
        age INTEGER
    )
    '''))
    conn.execute(text('''
    INSERT INTO users (name, age) VALUES ('Alice', 30), ('Bob', 24), ('Charlie', 29)
    '''))
    conn.execute(text('''
    CREATE TABLE IF NOT EXISTS orders (
        id INTEGER PRIMARY KEY,
        user_id INTEGER,
        amount DECIMAL,
        FOREIGN KEY(user_id) REFERENCES users(id)
    )
    '''))
    conn.execute(text('''
    INSERT INTO orders (user_id, amount) VALUES (1, 99.99), (2, 50.00), (3, 75.50)
    '''))

# 使用SQLDatabase连接到数据库
db = SQLDatabase(engine)

# 创建一个LangChain模型
llm = OpenAI(model_name='text-davinci-003')

# 创建SQL查询链
sql_chain = create_sql_query_chain(llm, db)

# 定义查询数据库的函数
def query_database(prompt):
    result = sql_chain.run(prompt)
    return result

# 示例:生成一个查询并执行
prompt = "查询所有年龄大于25岁的用户的姓名。"
result = query_database(prompt)
print(result)

3. 解释

1)环境设置:确保你有一个OpenAI API密钥,并将其设置为环境变量。这里假设你使用的是OpenAI的API。

2) 数据库设置:使用SQLAlchemy连接到SQLite数据库,并创建一个示例表 usersorders

3) 连接数据库:使用 SQLDatabase 类连接到数据库。SQLDatabase 将帮助获取数据库的表结构信息。

4) 创建LangChain模型:使用 OpenAI 类创建一个模型实例。

5) 创建SQL查询链:使用 create_sql_query_chain 创建一个SQL查询链,这个链会根据提供的自然语言提示生成SQL查询。

6) 定义查询函数
- query_database(prompt):通过SQL查询链生成SQL查询并执行。

7) 示例用法
- 提供一个描述性提示,如“查询所有年龄大于25岁的用户的姓名”。
- 通过LangChain模型生成SQL查询,并执行查询。

通过这种方式,LangChain的工具将自动处理数据库的表结构信息,并生成符合该结构的SQL查询。这大大简化了与数据库交互的过程,并减少了手动编码的需求。

三、create_sql_query_chainSQLDatabase 的原理是什么

create_sql_query_chain 是 LangChain 提供的一个便利工具,用于简化与SQL数据库的交互。它结合了自然语言处理和SQL查询生成的能力,使得用户能够使用自然语言指令查询数据库。让我们深入探讨一下它的工作原理。

数据库模式提取:
SQLDatabase 会自动连接数据库并提取其模式信息。这包括查询数据库元数据以获取所有表和列的详细信息。
提示生成:
create_sql_query_chain 使用数据库模式信息和用户提供的自然语言查询,自动生成一个适合的SQL查询提示。
查询生成和执行:
大模型根据提示生成SQL查询,SQL查询链负责执行该查询并返回结果。

通过这种自动化流程,用户可以直接使用自然语言查询数据库,而无需手动编写SQL查询或提取数据库结构信息。这极大地简化了与数据库的交互,并使得非技术用户也能方便地进行复杂的数据查询。

四、mysql数据库示例

使用MySQL代替SQLite进行数据库连接和查询只需要进行少量修改。主要是在创建数据库连接时要使用MySQL的连接字符串,并确保安装了MySQL的Python连接器(如 mysql-connector-pythonpymysql)。

以下是如何使用MySQL进行相同操作的示例:

1. 安装所需的包

首先,确保安装了MySQL连接器,例如 mysql-connector-python

pip install mysql-connector-python langchain openai sqlalchemy langchain_community

2. 示例代码

import os
from langchain import OpenAI
from langchain.chains import create_sql_query_chain
from langchain_community.utilities import SQLDatabase
from sqlalchemy import create_engine, text

# 设置OpenAI API密钥
os.environ['OPENAI_API_KEY'] = 'your_openai_api_key'

# 创建SQLAlchemy引擎连接到MySQL数据库
# 请根据您的MySQL数据库信息填写连接字符串
engine = create_engine('mysql+mysqlconnector://username:password@host:port/database')

# 创建一个示例表和一些数据(可选,如果数据库已经有表结构则跳过此部分)
with engine.connect() as conn:
    conn.execute(text('''
    CREATE TABLE IF NOT EXISTS users (
        id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(255),
        age INT
    )
    '''))
    conn.execute(text('''
    INSERT INTO users (name, age) VALUES ('Alice', 30), ('Bob', 24), ('Charlie', 29)
    '''))
    conn.execute(text('''
    CREATE TABLE IF NOT EXISTS orders (
        id INT AUTO_INCREMENT PRIMARY KEY,
        user_id INT,
        amount DECIMAL(10, 2),
        FOREIGN KEY(user_id) REFERENCES users(id)
    )
    '''))
    conn.execute(text('''
    INSERT INTO orders (user_id, amount) VALUES (1, 99.99), (2, 50.00), (3, 75.50)
    '''))

# 使用SQLDatabase连接到数据库
db = SQLDatabase(engine)

# 创建一个LangChain模型
llm = OpenAI(model_name='text-davinci-003')

# 创建SQL查询链
sql_chain = create_sql_query_chain(llm, db)

# 定义查询数据库的函数
def query_database(prompt):
    result = sql_chain.run(prompt)
    return result

# 示例:生成一个查询并执行
prompt = "查询所有年龄大于25岁的用户的姓名。"
result = query_database(prompt)
print(result)

3. 详细解释

1) 环境设置

  • 设置OpenAI API密钥,并连接到MySQL数据库。这里需要提供MySQL数据库的连接字符串。

2) 数据库连接

  • 使用SQLAlchemy的 create_engine 方法连接到MySQL数据库。连接字符串格式为:mysql+mysqlconnector://username:password@host:port/database

3) 创建表和插入数据(可选):

  • 如果数据库已经存在表结构和数据,这一步可以跳过。否则,创建示例表和数据。

4) 连接数据库

  • 使用 SQLDatabase 类连接到MySQL数据库。SQLDatabase 类会自动提取数据库的模式信息。

5) 创建LangChain模型

  • 使用 OpenAI 类实例化一个大模型(例如GPT-4)。

6) 创建SQL查询链

  • create_sql_query_chain 函数将大模型和 SQLDatabase 实例结合在一起,生成SQL查询链。

7) 定义查询函数

  • query_database(prompt) 函数接收自然语言查询,通过SQL查询链生成SQL查询并执行,返回结果。

8) 执行查询

  • 通过自然语言提示,例如“查询所有年龄大于25岁的用户的姓名”,使用 query_database 函数生成并执行SQL查询,并返回结果。

4. 注意事项

  • MySQL连接器:确保已安装MySQL连接器库,例如 mysql-connector-pythonpymysql。在连接字符串中使用相应的连接器,如 mysql+mysqlconnector://mysql+pymysql://
  • 数据库信息:根据实际的MySQL数据库信息填写连接字符串中的用户名、密码、主机、端口和数据库名称。
  • 权限:确保提供的MySQL用户具有创建表和插入数据的权限,特别是在示例代码中创建表和插入数据的部分。

通过这些修改,你就可以使用MySQL数据库进行相同的操作,自动提取数据库结构并生成对应的SQL查询。

总结

以上的例子,大家可以一起练习一下,当然今天的例子应该是业务使用中的一环,并不是所有的问答都需要查询数据库。那么如何自定义一个agent 然后把sql的这部分包装进去呢?请看 如何使用LangChain自定义agent的制作(1) - 自定义一个可以执行 SQL 查询的 Agent

;