当LLM遇见 SQL:用自然语言处理彻底改变数据查询

当LLM遇见 SQL:用自然语言处理彻底改变数据查询

使用 Prompt Engineering、SQL Agents 等

img

图片来自作者

介绍:

img

图片来自作者

欢迎来到将大型语言模型 (LLM) 与表格和 SQL 数据库等结构化数据相结合的激动人心的世界!想象一下,拥有一个超级智能助手,可以用数据库自己的语言与数据库对话,让我们能够非常轻松地获取所需的信息。这不仅仅是提出问题并获得答案;而是要创建像魔术一样的工具。

在本文中,我们将深入探讨这些强大的模型如何在许多方面使我们的生活更轻松。我们将探索它们如何通过理解我们的问题来编写数据库查询,帮助我们构建从数据库中了解内容的聊天机器人,并让我们设置自定义仪表板以查看我们最关心的信息。但这还不是全部——当我们将 LLM 的大脑与有组织的结构化数据世界结合起来时,我们还将发现我们可以做的更多令人惊奇的事情。所以,准备好解锁新的可能性,让与数据的交互变得轻而易举吧!

像这样的简单查询

img

图片来自作者

或者像这样的复杂

img

图片来自作者

让我们开始吧。

*第 1 部分 - 选择 SQL 数据库、创建模式并加载数据*

*第 2 部分:代理和 SQL 代理*

*第 3 部分:使用快速工程*

*第 4 部分:SQL 查询验证:*

*第 5 部分:数据库中非描述性或特定于语言的表和字段名称*

*第六部分:挑战*

*第 7 部分 - 文本 2 可视化:*

*第 8 部分 - 使用 Ollama 进行 Text 2 SQL*

*第 9 部分-文本 2 SQL 评估*

*第 10 部分 - 其他参考文章和存储库*

*第 11 部分 - 使用 Llamaindex 进行 Text2SQL*

*第 13 部分 - 使用 SQL 数据集对 LLM 进行微调*

*第 14 部分 - Pandas AI*

*第 15 部分:更多相关论文*

img

图片来自作者

第 1 部分 - 选择 SQL 数据库、创建模式并加载数据

img

图片来自作者

SQL 及其在数据管理中的作用:

  • SQL 代表结构化查询语言,它就像您与数据库对话时使用的魔法词——告诉它们要存储、查找或更改什么数据。
  • 这非常重要,因为几乎每个应用程序都使用数据库,而 SQL 是管理所有数据的首选语言。

img

图片来自作者

选择正确的数据库:

  • 将***PostgreSQL、MySQL 和 SQLAlchemy***视为数据的不同类型工具箱。
  • 这里之所以选择MySQL,是因为它易于使用、速度快,并且适合各种规模的项目。它就像您可靠的菜刀一样 — 非常适合处理许多任务。
  • PostgreSQL 实际上因其强大的功能而受到大家的喜爱,但对于本指南,我们使用 MySQL 保持简单。
  • 如果您直接使用 Jupyter 笔记本进行工作,并且想要更直接的方法,那么 SQLAlchemy 就是您的好帮手。它可以让您使用 Python 代码与数据库对话,无需繁重的工作。

这就是为什么 MySQL 成为该项目的选择 — 简单、快速,并且适合一切,从周末爱好到全面的业务需求!

下载 MySQL:

MySQL :: MySQL 社区下载

编辑描述

dev.mysql.com

为了我们的项目目的,我们将创建一个销售订单模式:

架构:

在关系数据库中,架构就像一份蓝图,定义了数据的结构和组织方式。它包含有关表、关系和数据类型的详细信息,为高效存储和检索数据奠定了基础。

SalesOrder 架构旨在捕捉和反映销售交易的复杂性。它旨在存储从客户信息和库存状态到详细销售订单和供应商数据的所有内容。

该模式包含七个关键表:

  1. **客户:**跟踪客户详细信息、购买历史和联系信息。
  2. **员工:**记录有关员工的信息,包括他们的角色、联系方式和薪水。
  3. **InventoryLog:**监控库存变化,提供库存水平和变动情况的见解。
  4. **LineItem:**详细说明销售订单中的每个项目,包括价格和数量。
  5. **产品:**目录产品、其描述、价格和库存数量。
  6. **SalesOrder:**该表是模式的核心,记录销售交易,包括日期、状态和付款细节。
  7. **供应商:**包含供应产品的供应商的数据,对于管理供应链至关重要。

图片来自作者

从INFORMATION_SCHEMA.COLUMNS中选择TABLE_NAME、COLUMN_NAME、DATA_TYPE、IS_NULLABLE、COLUMN_DEFAULT、CHARACTER_MAXIMUM_LENGTH,
其中TABLE_SCHEMA = 'SalesOrderSchema'按TABLE_NAME、ORDINAL_POSITION
排序; 

图片来自作者

加载数据:

要生成并加载客户、员工和产品等表的数据,可以执行以下操作:

通过 pip 安装 Faker。

使用 Faker 为每个表的字段创建数据,考虑具体需求(例如,姓名、地址、产品详细信息)。

编写 Python 脚本将这些虚假数据插入 MySQL 数据库,利用mysql-connector-python或等库SQLAlchemy进行数据库交互。

该脚本可用于使用示例数据填充数据库以用于测试或开发目的。

**导入必要的库:**该脚本使用 mysql.connector 连接到 MySQL 数据库,并使用 Faker 生成虚假数据。

初始化 Faker: Faker 被设置为创建真实但虚假的数据,如姓名、电子邮件、电话号码、地址和日期。

**连接到 MySQL 数据库:**它与位于 localhost 上的数据库名称为 SalesOrderSchema 的 MySQL 数据库建立连接。用户是 root,您应该将“您的 MySQL 密码”替换为实际密码。

**创建游标对象:**游标用于通过Python执行SQL命令。

**生成并插入数据:**在 100 次迭代中的每次迭代中,它都会为客户生成虚假数据,包括名字、姓氏、电子邮件、电话号码、地址、成为客户的日期以及他们是否是活跃客户。如果生成的电话号码超过 20 个字符,它会截断它以确保它适合数据库列。
帐单地址和送货地址都设置为相同的生成地址。然后,它使用 SQL INSERT 语句将此数据插入数据库的客户表中。
提交事务:插入所有数据后,使用 conn.commit() 将更改保存到数据库。关闭游标和连接:最后,它通过关闭游标和与数据库的连接进行清理。

# 将数据加载到客户表的代码
# 客户表
import mysql.connector 
from faker import Faker 

# 初始化 Faker
 fake = Faker() 

# 连接到 MySQL
 conn = mysql.connector.connect( 
  host= "localhost" , 
  user= "root" , 
  password= "Your MySQL Password" , 
  database= "SalesOrderSchema"
 ) 
cursor = conn.cursor() 

# 生成并插入数据
for _ in  range ( 100 ):   # 假设我们要生成 100 条记录
    first_name = fake.first_name() 
    last_name = fake.last_name() 
    email = fake.email() 
    phone = fake.phone_number() 
    if  len (phone) > 20 :   # 假设 'Phone' 列为 VARCHAR(20)
         phone = phone[: 20 ]   # 截断电话号码以适合列
    address = fake.address() 
    customer_since = fake.date_between(start_date= '-5y' , end_date= 'today' ) 
    is_active = fake.boolean() 
    
    # 插入客户数据
    cursor.execute( """ 
        INSERT INTO Customer (FirstName, LastName, Email, Phone, BillingAddress, ShippingAddress, CustomerSince, IsActive) 
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s) 
    """ , (first_name, last_name, email, phone, address, address, customer_since, is_active)) 

# 提交事务
conn.commit() 

# 关闭游标和连接
cursor.close() 
conn.close()

员工表:使用 Faker 填充

#员工表
导入mysql.connector 
from faker import Faker 

#初始化Faker
 fake = Faker() 

#连接到MySQL
 conn = mysql.connector.connect( 
  host= "localhost" , 
  user= "root" , 
  password= "Your MySQL Password" , 
  database= "SalesOrderSchema"
 ) 
cursor = conn.cursor() 

#生成并插入1000条员工记录
for _ in  range ( 1000 ): 
    first_name = fake.first_name() 
    last_name = fake.last_name() 
    email = fake.email() 
    phone = fake.phone_number() 
    if  len (phone) > 20 :   #如有必要,截断电话号码
        phone = phone[: 20 ] 
    hire_date = fake.date_between(start_date= '-5y' , end_date= 'today' ) 
    position = fake.job() 
    salary = round (fake.random_number(digits= 5 ), 2 )   #生成5位数的工资
    
    #插入员工数据
    cursor.execute( """ 
        INSERT INTO Employee (FirstName, LastName, Email, Phone, HireDate, Position, Salary) 
        VALUES (%s, %s, %s, %s, %s, %s, %s) 
    """ , (first_name, last_name, email, phone, hire_date, position, salary)) 

# 提交事务
conn.commit() 

# 关闭游标和连接
cursor.close() 
conn.close() 

print ( "已成功插入 1000 条员工记录。" )
#产品表
导入mysql.connector 
from faker import Faker 
import random 

# 初始化Faker
 fake = Faker() 

# 连接MySQL
 conn = mysql.connector.connect( 
  host= "localhost" , 
  user= "root" , 
  password= "Your MySQL Password" , 
  database= "SalesOrderSchema"
 ) 
cursor = conn.cursor() 

# 生成数据并插入到产品表中
for _ in  range ( 1000 ):   # 生成1000条产品记录
    product_name = fake.word().capitalize() + " " + fake.word().capitalize() 
    description = fake.sentence(nb_words= 10 ) 
    unit_price = round (random.uniform( 10 , 500 ), 2 )   # 在$10到$500之间随机生成价格
    stock_quantity = random.randint( 10 , 1000 )   # 在10到1000之间随机生成库存数量
    reorder_level = random.randint( 5 , 50 )   # 在 5 和 50 之间随机重新排序级别
    discontinued = random.choice([ 0 , 1 ])   # 在 0(false)和 1(true)之间随机选择

    # 插入产品数据
    cursor.execute( """ 
        INSERT INTO Product (ProductName, Description, UnitPrice, StockQuantity, ReorderLevel, Discontinued) 
        VALUES (%s, %s, %s, %s, %s, %s) 
    """ , (product_name, description, unit_price, stock_quantity, reorder_level, discontinued)) 

# 提交事务
conn.commit() 

# 关闭游标和连接
cursor.close() 
conn.close() 

print ( "产品插入成功。" )
#供应商表
导入mysql.connector 
from faker import Faker 
import random 

#初始化Faker
 fake = Faker() 

#连接到MySQL
 conn = mysql.connector.connect( 
  host= "localhost" , 
  user= "root" , 
  password= "Your MySQL Password" , 
  database= "SalesOrderSchema"
 ) 
cursor = conn.cursor() 

#生成并将数据插入供应商表
for _ in  range ( 1000 ):   #假设要插入1000条记录
    company_name = fake.company() 
    contact_name = fake.name() 
    contact_title = fake.job() 
    #确保ContactTitle不超过列的最大长度,例如VARCHAR(50)
     contact_title = contact_title[: 50 ] if  len (contact_title) > 50  else contact_title 
    address = fake.address().replace( '\n' , ', ' )   #将地址的换行符替换为逗号
    phone = fake.phone_number() 
    # 确保电话不超过列的最大长度,例如 VARCHAR(20)
     phone = phone[: 20 ] if  len (phone) > 20  else phone 
    email = fake.email() 

    # 插入供应商数据
    cursor.execute( """ 
        INSERT INTO Supplier (CompanyName, ContactName, ContactTitle, Address, Phone, Email) 
        VALUES (%s, %s, %s, %s, %s, %s) 
    """ , (company_name, contact_name, contact_title, address, phone, email)) 

# 提交事务
conn.commit() 

# 关闭游标和连接
cursor.close() 
conn.close() 

print ( "供应商插入成功。" )
#销售订单表
import mysql.connector 
from faker import Faker 
from datetime import timedelta 
import random 

fake = Faker() 

conn = mysql.connector.connect( 
  host= "localhost" , 
  user= "root" , 
  password= "Your MySQL Password" , 
  database= "SalesOrderSchema"
 ) 
cursor = conn.cursor(buffered= True ) 

# 获取客户 ID
 cursor.execute( "SELECT CustomerID FROM Customer" ) 
customer_ids = [ id [ 0 ] for  id  in cursor.fetchall()] 

# 将数据插入 SalesOrder 
for _ in  range ( 1000 ):   # 假设我们要生成 1000 份销售订单
    customer_id = random.choice(customer_ids) 
    order_date = fake.date_between(start_date= '-2y' , end_date= 'today' ) 
    required_date = order_date + timedelta(days=random.randint( 1 , 30))
    shipped_date = order_date + timedelta(days=random.randint(1 , 30))if random.choice([ True , False ])else  None
     status = random.choice([ '待处理' , '已完成' , '已发货' ])
    is_paid = random.choice([ True , False ])

    cursor.execute(""" 
        INSERT INTO SalesOrder (CustomerID, OrderDate,RequiredDate, ShippedDate, Status, IsPaid) 
        VALUES (%s, %s, %s, %s, %s, %s) 
    """ , (customer_id, order_date, required_date, shipped_date, status, is_paid)) 

conn.commit()
#销售订单行项目
# 获取产品 ID
 cursor.execute( "SELECT ProductID FROM Product" ) 
product_ids = [ id [ 0 ] for  id  in cursor.fetchall()] 

# 获取销售订单 ID
 cursor.execute( "SELECT SalesOrderID FROM SalesOrder" ) 
sales_order_ids = [ id [ 0 ] for  id  in cursor.fetchall()] 

# 将数据插入行项目
for _ in  range ( 5000 ):   # 假设每个订单有多个行项目
    sales_order_id = random.choice(sales_order_ids) 
    product_id = random.choice(product_ids) 
    quantity = random.randint( 1 , 10 ) 
    unit_price = round (random.uniform( 10 , 100 ), 2 )   # 假设您有此信息或从产品表中获取
    total_price = quantity * unit_price 

    cursor.execute( """ 
        INSERT INTO LineItem (销售订单 ID、产品 ID、数量、单价、总价)
        值 (%s、%s、%s、%s、%s) 
    """,(销售订单 ID、产品 ID、数量、单价、总价)) 

conn.commit()
游标.close () 
conn.close ( )
# 库存表
导入 mysql.connector 
from faker import Faker 
import random 

# 初始化 Faker
 fake = Faker() 

# 连接到 MySQL
 conn = mysql.connector.connect( 
  host= "localhost" , 
  user= "root" , 
  password= "您的 MySQL 密码" , 
  database= "SalesOrderSchema"
 ) 
cursor = conn.cursor() 

# 获取产品 ID
 cursor.execute( "SELECT ProductID FROM Product" ) 
product_ids = [row[0] for row in cursor.fetchall()]
# 假设要插入 1000 条库存日志记录
for _ in  range ( 1000 ): 
    product_id = random.choice(product_ids)   # 随机选择一个产品 ID
     change_date = fake.date_between(start_date= "-1y" , end_date= "today" ) 
    quantify_change = random.randint(- 100 , 100 )   # 假设库存可以增加或减少
    notes = "Inventory " + ( "increased"  if quantify_change > 0  else  "decreased" ) 

    # 插入库存日志数据
    cursor.execute( """ 
        INSERT INTO InventoryLog (ProductID, ChangeDate, QuantityChange, Notes) 
        VALUES (%s, %s, %s, %s) 
    """ , (product_id, change_date, quantify_change, notes)) 

# 提交事务
conn.commit() 

# 关闭游标和连接
cursor.close() 
conn.close() 

print ( "库存日志插入成功。" )

img

图片来自作者

文本 2 SQL 流程

第 2 部分:代理和 SQL 代理:

让我们首先使用 SQL Agent 创建 text2SQL。

什么是 AI 代理?

定义: AI 代理是一种计算机程序,旨在通过模拟人类智能的某些方面来执行任务。它可以做出决策、与环境互动或解决问题,而无需持续的人工指导。

**能力:**决策:人工智能代理可以根据其掌握的数据或编入其中的规则评估情况并做出选择。

**解决问题:**他们能够在复杂场景中导航以实现特定目标或找到问题的解决方案。

**学习:**一些人工智能代理能够从数据或过去的经验中学习,随着时间的推移提高其性能。这通常被称为机器学习。

AI代理的类型:

**简单反射代理:**根据预定义规则对当前情况或环境做出反应,而不考虑过去或未来。
**基于模型的反射代理:**考虑世界的当前状态以及它如何响应动作而变化,从而实现更明智的决策过程。
**基于目标的代理:**通过考虑未来动作及其结果来实现特定目标。
**基于效用的代理:**根据效用函数评估其动作的成功性,旨在最大限度地提高其满意度或收益。
**学习型代理:**通过从环境和过去的行为中学习来提高其性能并适应新情况。

应用:

**虚拟助手:**例如 Siri 或 Alexa,可以为个人执行任务或服务。
**自动驾驶汽车:**无需人工干预即可导航和操作的汽车或无人机。
**推荐系统:**例如 Netflix 或 Amazon 使用的推荐系统,可根据您的偏好推荐产品或电影。
医疗保健: AI 代理可以帮助诊断疾病、预测患者结果或个性化治疗计划。

好处:

**效率:**在许多情况下,它们可以比人类更快、更准确地自动化执行任务。
**可用性:**人工智能代理全天候可用,提供一致的服务,无需休息或睡眠。
**个性化:**能够根据个人喜好定制体验、建议和互动。

挑战:

道德和隐私问题:关于人工智能代理如何使用和共享数据的决定需要谨慎做出。
依赖性:过度依赖人工智能代理可能会影响人类的技能和就业。
开发和维护的复杂性:创建和更新人工智能代理需要大量的专业知识和资源。

img

图片来自作者

img

图片来自作者

SQL 代理:

功能:

**自然语言查询:**允许用户通过自然语言与数据库交互,使非技术用户无需了解 SQL 语法即可更轻松地提取信息。AI
**辅助数据库交互:**增强数据库与 AI 的交互,通过对话界面实现更复杂的查询、数据分析和见解提取。
**与语言模型的集成:**将 AI 语言模型与 SQL 数据库相结合,促进从自然语言输入自动生成 SQL 查询并为用户解释结果。

成分:

**语言模型:**能够理解和生成类似人类文本的预训练 AI 模型。
**查询生成:**将自然语言请求转换为 SQL 查询的机制。
**结果解释:**将 SQL 查询结果转换回人类可读的格式或摘要。

应用:

**数据探索:**让没有深厚技术知识的用户能够更直观地进行数据探索和分析。
**商业智能:**通过对话界面促进报告和见解的生成。
**自动化:**简化用户和数据库之间的交互,自动化查询生成和数据检索过程。

让我们看看如何使用 SQL 代理并进行文本到 SQL 的转换。

img

图片来自作者

代码如下。

导入操作系统
导入streamlit作为st
从langchain_openai导入ChatOpenAI
从langchain_community.utilities导入SQLDatabase
从langchain_community.agent_toolkits导入create_sql_agent 

# 在此处设置您的 OpenAI API 密钥
os.environ[ "OPENAI_API_KEY" ] = "您的 OpenAI API 密钥" 

# 直接使用数据库连接详细信息
host = "localhost"
 user = "root"
 password = "您的 MySQL 密码"
 database = "SalesOrderSchema" 

# 设置数据库连接
db_uri = f"mysql+mysqlconnector:// {user} : {password} @ {host} / {database} "
 db = SQLDatabase.from_uri(db_uri) 
llm = ChatOpenAI(model= "gpt-4" ,temperature= 0 ) 
agent_executor = create_sql_agent(llm,db=db, agent_type= "openai-tools" ,verbose= True ) 

# Streamlit 应用程序布局
st.title( 'SQL Chatbot' ) 

# 用户输入
user_query = st.text_area( "输入与 SQL 相关的查询:" , "按薪水列出前 10 名员工?" ) 

if st.button( 'Submit' ): 
    #try: 
        # 处理用户输入
        #response = agent_executor.invoke(user_query) 
        #response = agent_executor.invoke({"query": user_query}) 
        #if st.button('Submit'): 
    try : 
        # 处理用户输入
        response = agent_executor.invoke({ 
            "agent_scratchpad" : "" ,   # 假设如果不使用,则需要为空字符串
            "input" : user_query   # 从 "query" 更改为 "input"
         }) 
        st.write( "Response:" ) 
        st.json(response)   # 如果是,则使用 st.json 漂亮地打印响应JSON 
    except Exception as e:
        st.error( f“发生错误:{e} ” ) 

        #st.write(“响应:”) 
        #st.write(response) 
    #except Exception as e:
        #st.error(f“发生错误:{e}”)

关于脚本:

**导入库和模块:**脚本首先导入必要的库,例如 os、streamlit(作为 st)以及来自 langchain_openai 和 langchain_community 的特定模块,以创建和管理 SQL 聊天机器人。

**设置 OpenAI API 密钥:**它使用您的 OpenAI API 密钥设置环境变量 OPENAI_API_KEY,这对于访问 OpenAI 的语言模型是必要的。

**数据库连接详细信息:**该脚本定义数据库连接详细信息的变量,包括连接到 MySQL 数据库的主机、用户、密码和数据库名称。

**设置数据库连接:**使用提供的凭据创建与指定 MySQL 数据库的连接并构造 SQLDatabase 对象。

**初始化语言模型和 SQL 代理:**它从 OpenAI 的 GPT-4 初始化语言模型并创建 SQL 代理。此代理可以解释与 SQL 相关的查询并使用自然语言处理与数据库交互。

img

图片来源 Streamlit 文档

Streamlit应用程序界面:

  1. 设置一个简单的 Web 界面标题为“SQL 聊天机器人”。
    提供一个文本区域供用户输入与 SQL 相关的查询。
    包括一个提交按钮供用户执行查询。
    处理并显示响应:
  2. 单击提交按钮后,应用程序会尝试使用 SQL 代理处理用户的查询。
    它会在 Streamlit 界面中将 SQL 代理的响应格式化并显示为 JSON。
  3. 如果在此过程中出现错误,则会显示错误消息。
    错误处理:脚本包含一个 try-except 块,用于捕获和显示查询处理或响应生成阶段可能发生的错误。

如何运行Streamlit Python脚本:

安装 Streamlit:
如果尚未安装 Streamlit,请打开终端
(或 Windows 中的命令提示符/PowerShell)并运行以下命令:

pip install streamlit

保存脚本:确保 Streamlit 脚本(例如,app.py)
保存在计算机上的已知目录中。

打开终端:导航到保存 Streamlit 脚本的目录。您可以使用 cd 命令后跟目录路径来执行此操作。例如:

cd path/to/your/script
运行 Streamlit 脚本:在终端中,执行以下命令
来运行 Streamlit 脚本:

streamlit run app.py
如果 app.py 与您的 Streamlit 脚本文件的名称不同,请将其替换为该文件的名称。

访问 Web 界面:运行命令后,Streamlit 将
启动服务器并为您提供本地URL,通常
类似于http: // localhost : 8501。 在Web 浏览器中打开此 URL以查看您的 Streamlit 应用程序。与您的应用程序交互:使用 Web 界面与您的 Streamlit 应用程序交互。您可以输入输入、按下按钮并实时查看脚本的输出。停止 Streamlit 服务器:完成后,您可以在运行服务器的终端中按 Ctrl+C 来停止 Streamlit服务器。这些步骤将允许您运行并与任何 Streamlit 脚本交互,从而轻松地将您的 Python 脚本转变为交互式 Web 应用程序。  


 

 

查询:1

生成一份报告,显示当前库存水平、重新订购水平以及每种产品是否低于重新 订购
水平,执行查询并显示结果。 

img

图片来自作者

查询:2

计算过去三年内进行过购买的每个客户的终身价值(总销售额),按最高价值排序并显示前5 名? 
   

img

图片来自作者

img

图片来自作者

第 3 部分:使用快速工程:

img

图片来自作者

及时工程涉及精心设计模型的输入,以引导模型生成所需的输出。这对于文本到 SQL 的任务特别有用,因为该任务的目标是将自然语言查询转换为精确的 SQL 语句。

怎么运行的:

**以示例为指导:**通过在提示中包含自然语言查询的示例及其正确的 SQL 翻译,您实际上为模型提供了一个可遵循的模板。此方法使用少量学习的原理,其中模型使用提供的示例来理解和概括手头的任务。

**上下文信息:**添加有关数据库架构的信息(例如表名和关系)可以帮助模型生成更准确的 SQL 查询。此上下文背景可帮助模型将自然语言术语映射到数据库中的相应实体。

**任务描述:**以清晰的任务描述开始提示(例如,“将以下自然语言查询翻译成 SQL:”),表明模型的预期任务,使其能够在指定任务上获得更好的性能。

示例提示:

我是一个 SQL 助手,旨在将自然语言查询转换为 SQL。我是一个 SQL 助手,旨在将自然语言查询转换为 SQL。
给定一个销售数据库模式,其中包含客户、员工、库存日志、
行项目、产品、销售订单和供应商表,以下是一些示例:

- 自然语言查询:“显示所有价格高于 100 美元的产品。”
 - SQL 翻译:SELECT * FROM Product WHERE price > 100 ; 

- 自然语言查询:“列出客户 ID 123 在 2023 年下的所有订单。”
 - SQL 翻译:SELECT * FROM SalesOrder WHERE CustomerID = 123  AND YEAR(OrderDate) = 2023 ;

翻译以下查询:
“查找 2024 年 3 月每种产品的总销售额。”

例如:系统提示符将是

给定以下数据库架构,生成与用户请求相对应的 SQL 查询的请求。

表格及其相关字段:
-产品(ProductID、ProductName)
-行项目(ProductID、TotalPrice)
-销售订单(SalesOrderID、OrderDate)

用户对上一日历年中每种产品的总销售额感兴趣。查询应返回每种产品的名称以及该期间所有销售的总价总和。确保查询仅考虑与去年销售订单相关的那些行项目。供参考的示例 SQL 模板:“SELECT [columns] FROM [table] JOIN [other_table] ON [condition] WHERE [condition] GROUP BY [column];”请记住在适当的位置使用表名的别名以提高可读性,并在查询结构中保持SQL 最佳实践。 

 


 



 

以及用户提示:

“显示去年每种产品的总销量。”

LLM 产生以下输出:

SELECT 
   P.ProductName, 
  SUM(L.TotalPrice) AS TotalSales 
FROM 
   Product P 
  JOIN LineItem L ON P.ProductID = L.ProductID 
  JOIN SalesOrder S ON L.SalesOrderID = S.SalesOrderID 
WHERE 
   YEAR(S.OrderDate) = YEAR(CURDATE()) - 1 
GROUP  BY 
   P.ProductName;

img

图片来自作者

选择方言特定提示-Langchain

从 langchain.chains.sql_database.prompt 导入 SQL_PROMPTS导入SQL_PROMPTS

列表(SQL_PROMPTS)
['crate'、'crate' , 
 'duckdb' , 
 'googlesql' , 
 'mssql' , 
 'mysql' , 
 'mariadb' , 
 'oracle' , 
 'postgresql' , 
 'sqlite' , 
 'clickhouse' , 
 'prestodb' ]

由于我们使用的是 MySQL,因此它将像

从langchain.chains导入create_sql_query_chain从langchain_openai 导入ChatOpenAI llm = ChatOpenAI (model= " gpt -3.5-turbo" ,temperature= "0" ) chain = create_sql_query_chain (llm, db) chain.get_prompts ()[ 0 ]. pretty_print ( )
 

提示将是

您是 MySQL 专家。给定一个输入问题,首先创建一个语法
正确的 MySQL 查询来检索答案,然后执行查询并返回检索答案,然后执行查询并 返回 输入问题的答案
。- 使用 LIMIT 子句查询最多5 个结果,除非用户  指定不同的数字。- 切勿从表查询所有列。仅选择回答问题所需的列。-将每个列名括在反引号 (`)中,以防止由于保留关键字或特殊字符而导致语法错误。   -注意列名及其各自的表。-如果问题涉及“今天”,请使用CURDATE ()表示当前日期。像这样组织您的响应:问题: [用户的问题] MySQL 查询:[您生成的 SQL 查询]结果: [ SQL 查询的结果(如果可用)]答案: [基于查询结果的最终答案] 仅使用SalesOrder 模式中的以下表:客户、员工、 InventoryLog、LineItem、产品、SalesOrder、供应商。以下是这些表中的一些示例数据供您参考:[包括示例数据]。问题: [用户输入]




  
 


 

要获取表名、其模式以及每个表中的行样本,请使用以下命令:

从langchain_community.utilities导入SQLDatabase 

# 调整 MySQL 的连接 URI
 db = SQLDatabase.from_uri( "mysql+mysqlconnector://'user_id':'password'@localhost/SalesOrderSchema" ) 

# 打印 SQL 方言(现在应该反映 MySQL)
print (db.dialect) 

# 打印 MySQL 数据库中可用的表名
print (db.get_usable_table_names()) 

# 运行示例查询 - 根据您的模式调整表名
# 这是一个例子;将 `Artist` 替换为您模式中的实际表名,例如 `Customer`
 db.run( "SELECT * FROM Customer LIMIT 10;" )
mysql 
['客户', '员工', 'InventoryLog', 'LineItem', '产品', '销售订单', '客户', '员工', ' InventoryLog ', ' LineItem ', '产品', ' SalesOrder ', '
供应商'] 
"[(1, 'Sandra', 'Cruz', 'rhonda24@example.net', '511-949-6987x21174', 
'18018 Kyle Streets Apt. 606 \\ nShaneville, AZ 85788', '18018 Kyle Streets Apt. 
606 \\ nShaneville, AZ 85788', datetime.date(2023, 5, 2), 0), (2, 'Robert', 
'Williams', 'traciewall@example.net', '944-649-2491x60774', '926 Mitchell 
Pass 公寓 342 \\ nBrianside, SC 83374', '926 Mitchell Pass 公寓 342 \\ nBrianside, 
SC 83374', datetime.date(2020, 9, 1), 0), (3, 'John', 'Greene', 
'travis92@example.org', '279.334.1551', '36019 Bill Manors 公寓
219 \\ nDominiquefort, AK 55904', '36019 Bill Manors 公寓 219 \\ nDominiquefort, 
AK 55904', datetime.date(2021, 3, 15), 0), (4, 'Steven', 'Riley', 
'greennathaniel@example.org', '+1-700-682-7696x189', '76545 Hebert 
Crossing Suite 235 \\ nForbesbury, MH 14227', '76545 Hebert Crossing Suite 
235 \\ nForbesbury, MH 14227', datetime.date(2022, 12, 5), 0), (5, 'Christina', 
'Blake', 'christopher87@example.net', '584.263.4429', '8342 Shelly Fork \\ nWest 
Chasemouth, CT 81799', '8342 Shelly Fork \\ nWest Chasemouth, CT 81799', 
datetime.date(2019, 11, 12), 0), (6, 'Michael', 'Stevenson', 
'lynnwilliams@example.org', '328-637-4320x7025', '7503 Mallory Mountains Apt. 
199 \\ nMeganport, MI 81064', '7503 Mallory Mountains Apt. 199 \\ nMeganport, MI 
81064', datetime.date(2024, 1, 1), 1), (7, 'Anna', 'Kramer', 'steven23@example 
.org', '+1-202-719-6886x844', '295 Mcgee Fort \\ nManningberg, PR 93309', '295 
Mcgee Fort \\ nManningberg, PR 93309', datetime.date(2022, 3, 6), 1), (8, 
'Michael', 'Sullivan', 'bbailey@example.com', '988.368.5033', '772 Bruce 
Motorway Suite 583 \\ nPowellbury, MH 42611', '772布鲁斯高速公路套房 583 \\
 nPowellbury, MH 42611', datetime.date(2019, 3, 23), 1), (9,'Kevin', 'Moody', 
'yoderjennifer@example.org', '3425196543', '371 Lee Lake \\ nNew Michaelport, 
CT 99382', '371 Lee Lake \\ nNew Michaelport, CT 99382', datetime.date(2023, 12, 3), 1), (10, 'Jeremy', 'Mejia', 'spencersteven@example.org', '449.324.7097', '90137 Harris Garden \\nMatthewville, IA 39321','90137 Harris Garden \\ nMatthewville, IA 39321',datetime.date(2019, 5, 20), 1)]”
context = db.get_context()
打印(列表(上下文))
打印(上下文[ “table_info” ])

输出:

图片来自作者

我们可以使用上述内容来更新我们的提示或传递所有内容。Chatgpt4 上下文大小为 128K,这很好。

prompt_with_context = chain.get_prompts()[0].partial(table_info=context["table_info"])复制代码

有关提示的更多详细信息,请查看

如何提示 LLM 进行文本到 SQL 转换:零样本、单域和跨域设置中的研究

img

图片来自作者

img

图片来自作者

一些镜头示例:

这里有些例子:

图片来自作者

从 langchain_core.prompts 导入 FewShotPromptTemplate,PromptTemplate 


example_prompt = PromptTemplate.from_template("用户输入:{input}\nSQL 查询:{query}")"用户输入:{input}\nSQL 查询:{query}" ) 

prompt = FewShotPromptTemplate( 
    examples=examples[:15],   
    example_prompt=example_prompt, 
    prefix= "您是 MySQL 专家。给定一个输入问题,创建一个
    语法正确的 MySQL 查询来运行。除非另有说明,否则
    不要返回超过 {top_k} 行。\n\n这是相关的表信息:
    {table_info}\n\n下面是一些问题示例及其对应的 SQL 查询。" , 
    suffix= "用户输入:{input}\nSQL 查询: " , 
    input_variables=[ "input" , "top_k" , "table_info" ], 
) 


table_info = "" " 
- Customer (CustomerID INT, FirstName VARCHAR(100), LastName VARCHAR(100), Email VARCHAR(255), Phone VARCHAR(20), BillingAddress TEXT,发货地址 TEXT、客户自 DATE、IsActive TINYINT) 
- 员工 (EmployeeID INT、FirstName VARCHAR(100)、LastName VARCHAR(100)、Email VARCHAR(255)、Phone VARCHAR(20)、HireDate DATE、Position VARCHAR(100)、Salary DECIMAL) 
- InventoryLog (LogID INT、ProductID INT、ChangeDate DATE、QuantityChange INT、Notes TEXT) 
- LineItem (LineItemID INT、SalesOrderID INT、ProductID INT、Quantity INT、UnitPrice DECIMAL、Discount DECIMAL、TotalPrice DECIMAL) 
- 产品 (ProductID INT、ProductName VARCHAR(255)、Description TEXT、UnitPrice DECIMAL、StockQuantity INT、ReorderLevel INT、Discontinued TINYINT) 
- SalesOrder (SalesOrderID INT、CustomerID INT、OrderDate DATE、RequiredDate DATE、ShippedDate DATE、Status VARCHAR(50)、Comments TEXT、PaymentMethod VARCHAR(50)、IsPaid TINYINT) 
- 供应商 (SupplierID INT、CompanyName VARCHAR(255)、ContactName VARCHAR(100)、ContactTitle VARCHAR(50)、Address TEXT、Phone VARCHAR(20)、Email VARCHAR(255)) 
" "" 

# 示例用法
input_example = "列出所有当前有库存的产品。"
 top_k = 10 
formatted_prompt = prompt.format(input=input_example, top_k=top_k, table_info=table_info) 
print(formatted_prompt)

输出:

您是MySQL 专家。给定一个输入问题,创建一个语法
正确的 MySQL 查询来运行。除非另有说明,否则不要返回 超过10行。以下是相关的表信息:-客户(CustomerID INT、FirstName VARCHAR(100)、LastName VARCHAR(100)、Email VARCHAR(255)、Phone VARCHAR(20)、BillingAddress TEXT、ShippingAddress TEXT、CustomerSince DATE、IsActive TINYINT)-员工(EmployeeID INT、FirstName VARCHAR(100)、LastName VARCHAR(100)、Email VARCHAR(255)、Phone VARCHAR(20)、HireDate DATE、Position VARCHAR(100)、Salary DECIMAL)- InventoryLog(LogID INT、ProductID INT、ChangeDate DATE、QuantityChange INT、Notes TEXT)- LineItem(LineItemID INT、SalesOrderID INT、ProductID INT、Quantity INT、UnitPrice DECIMAL、折扣DECIMAL、总价DECIMAL)-产品(产品 ID INT、产品名称VARCHAR(255)、说明 TEXT、单价DECIMAL、库存数量INT、重新订购级别INT、停产 TINYINT)-销售订单(销售订单 ID INT、客户 ID INT、订购日期DATE、所需日期DATE、发货日期DATE、状态VARCHAR(50)、注释 TEXT、付款方式VARCHAR(50)、已付款 TINYINT)-供应商(供应商 ID INT、公司名称VARCHAR(255)、联系人姓名VARCHAR(100









), ContactTitle VARCHAR ( 50 ), Address TEXT, Phone VARCHAR ( 20 ), Email VARCHAR ( 255 ))


下面是一些问题示例及其对应的SQL查询。用户输入:列出所有客户。SQL查询:SELECT * FROM Customer;用户输入:查找ID为1的客户下的所有订单。SQL查询:SELECT * FROM SalesOrder WHERE CustomerID = 1 ;用户输入:列出目前有库存的所有产品。SQL查询: SELECT * FROM Product WHERE StockQuantity > 0 ;用户输入:查找ID为10 的产品的供应商。SQL查询:SELECT s.CompanyName FROM Supplier s JOIN Product p ON s.SupplierID = p.SupplierID WHERE p.ProductID = 10 ;用户输入:列出尚未发货的销售订单。 SQL查询:SELECT * FROM SalesOrder WHERE Status = 'Pending' ;用户输入:销售部门有多少名员工?SQL查询: SELECT COUNT ( * ) FROM Employee WHERE Position LIKE ' %sales%' ;用户输入:列出销量最高的5种产品。 SQL查询:SELECT ProductID, SUM (Quantity) AS TotalQuantity FROM LineItem GROUP BY ProductID ORDER BY TotalQuantity DESC LIMIT 


  


   


   


 


   


  


  5 ;

用户输入:找出今年完成的订单的总销售金额。 
SQL查询:SELECT  SUM (TotalPrice) FROM SalesOrder WHERE  YEAR (OrderDate) =  YEAR (CURDATE()) AND Status =  'Completed' ;

用户输入:列出来自“纽约”的所有供应商。SQL查询:SELECT * FROM Supplier WHERE Address LIKE '%New York%' ;用户输入:有多少产品库存不足(低于重新订购水平)?SQL查询:SELECT COUNT ( * ) FROM Product WHERE StockQuantity < ReorderLevel;用户输入:列出名为“John Doe”的客户下的所有订单。SQL查询:SELECT so. * FROM SalesOrder so JOIN Customer c ON so.CustomerID = c.CustomerID WHERE c.FirstName = 'John' AND c.LastName = 'Doe' ;用户输入:显示ID为20 的产品的库存日志。SQL查询:SELECT * FROM InventoryLog WHERE ProductID = 20 ;用户输入:列出当前有库存的所有产品。SQL查询: 
   


 


    


   

img

图片来自作者

动态少量镜头示例:

想象一下,您有一大盒工具,但只想拿出对当前工作最有用的工具。SemanticSimilarityExampleSelector 可以做类似的事情。它会查看您的问题并从集合中挑选出最相似的示例,以帮助模型理解您的问题。

#pip 安装 faiss-cpu
来自langchain_community.vectorstores导入FAISS来自langchain_core.example_selectors导入SemanticSimilarityExampleSelector来自langchain_openai导入OpenAIEmbeddings example_selector = SemanticSimilarityExampleSelector .from_examples ( examples     , OpenAIEmbeddings (), FAISS , k     = 5  ,     input_keys=[ "input" ] , ) 
  
 



    
    
example_selector.select_examples({"input": "列出所有客户?"}).select_examples ({"输入": "列出所有客户?" })

输出:

[{'input': '列出所有客户。', 'query': 'SELECT * FROM Customer;'},'input' : '列出所有客户。' , 'query' : 'SELECT * FROM Customer;' }, 
{ 'input' : "列出名为 'John Doe' 的客户下的所有订单。" , 
  'query' : "SELECT so.* FROM SalesOrder so JOIN Customer c ON so.CustomerID = c.CustomerID WHERE c.FirstName = 'John' AND c.LastName = 'Doe';" }, 
{ 'input' : '列出所有当前有库存的产品。' , 
  'query' : 'SELECT * FROM Product WHERE StockQuantity > 0;' }, 
{ 'input' : '查找 ID 为 1 的客户下的所有订单。' , 
  'query' : 'SELECT * FROM SalesOrder WHERE CustomerID = 1;' }, 
{ 'input' : "列出来自 '纽约' 的所有供应商。" , 
  'query' : "SELECT * FROM Supplier WHERE Address LIKE '%New York%';" }]
prompt = FewShotPromptTemplate(=  FewShotPromptTemplate ( 
    example_selector = example_selector, 
    example_prompt = example_prompt, 
    prefix = "您是 MySQL 专家。给定一个输入问题,创建一个语法正确的 MySQL 查询来运行。除非另有说明,否则不要返回超过 {top_k} 行。\n \n这是相关的表信息:{table_info} \n \n以下是一些问题示例及其对应的 SQL 查询。" , 
    suffix = "用户输入:{input} \n SQL 查询:" , 
    input_variables = [ "input" , "top_k" , "table_info" ], 
)
# 使用调整后的参数创建 SQL 查询链
chain = create_sql_query_chain ( llm, db, prompt ) 

# 使用与数据库相关的问题调用该链
chain.invoke ( { "question" :  "目前有多少产品有库存?" } )

输出:

'从产品中选择 COUNT(*),其中 StockQuantity > 0;

img

图片来自作者

增强大型语言模型的少样本文本到 SQL功能:一项关于快速设计策略的研究。

如何提示 LLM 进行文本到 SQL:零样本、单域和跨域设置中的研究要记住的关键点。

ChatGPT零样本文本到 SQL 能力的全面评估

探索文本到 SQL 的思路链式提示

img

图片来自作者

img

图片来自 Gemini

要记住的要点:

**了解模式:**熟悉数据库结构,了解表、表之间的关系以及每列的数据类型。

**清晰的用户提示:**鼓励用户在查询中提供清晰、具体的详细信息。例如,他们不应该问“给我销售数字”,而应该问“上个季度产品 X 的总销售额是多少?”

**制定系统提示:**设计系统提示,指导 LLM 如何解释用户问题和构建 SQL 查询。这可以包括指定 SQL 方言、输出格式以及任何约束(例如日期范围或特定字段)。

**处理多个表:**处理复杂架构时,请包含有关连接表和管理表间关系的说明。例如,如果用户想要了解销售情况,您可能需要连接销售、客户和产品表。

**结合示例:**包括一些将自然语言查询转换为 SQL 查询的示例。这为 LLM 提供了一个可遵循的模式。

**测试和迭代:**使用各种查询测试您的提示,以确保它们生成正确的 SQL 语句。准备根据这些测试完善您的提示。

用户提示:“去年每种产品对销售额的贡献是多少?”

系统提示:“要回答这个问题,请连接 Product 和 SalesOrder 表,筛选
去年的订单,然后计算每种产品的销售额总和。”
示例SQL:“SELECT Product.ProductName, SUM(SalesOrder.TotalSales) 
FROM Product JOIN SalesOrder ON Product.ProductID = SalesOrder.ProductID 
WHERE YEAR(SalesOrder.OrderDate) = YEAR(CURDATE()) - 1 GROUP BY Product.ProductName 
;”
用户提示:“按销售量列出前 5 名客户。”

系统
提示:“通过连接 Customer 和 SalesOrder 表、按客户分组并按
销售总额排序,找出销售量最高的客户。”
示例SQL:“SELECT Customer.FirstName, Customer.LastName, 
SUM(SalesOrder.TotalSales) AS TotalSales FROM Customer JOIN SalesOrder 
ON Customer.CustomerID = SalesOrder.CustomerID GROUP BY Customer.CustomerID 
ORDER BY TotalSales DESC LIMIT 5;”
用户提示:“上个月每个产品类别的平均销售额是多少?”

系统提示:“通过连接产品表、销售订单表和可能的类别表来计算平均销售额
,按上个月的日期进行过滤,然后按
类别分组。”
示例SQL:“假设您有一个 Category 表,则查询可能类似于
‘SELECT Category.Name, AVG(SalesOrder.TotalSales) FROM SalesOrder 
JOIN Product ON SalesOrder.ProductID = Product.ProductID JOIN Category ON 
Product.CategoryID = Category.CategoryID WHERE MONTH(SalesOrder.OrderDate) = 
MONTH(CURRENT_DATE - INTERVAL 1 MONTH) GROUP BY Category.Name;’”

img

图片来自作者

如何生成动态提示:

**1. 分析用户提示:**从用户的问题中确定意图和所需数据。2
**. 选择相关表:**根据意图,确定需要数据库中的哪些表和字段。3
**. 生成系统提示:**使用模板或预定义模式创建系统提示,引导 LLM 生成正确的 SQL 查询。这可能涉及指定任务、所涉及的表以及应使用的任何特定 SQL 语法或函数。

# 定义用户意图和数据库架构元素之间的映射
intent_to_tables = { 
    "去年总销售额" : { 
        "tables" : [ "SalesOrder" , "LineItem" , "Product" ], 
        "fields" : [ "ProductName" , "SUM(TotalPrice)" ], 
        "conditions" : [ "YEAR(OrderDate) = YEAR(CURDATE()) - 1" ] 
    } 
    # 在此处添加更多意图和相应的架构元素
} 

def  generate_system_prompt ( user_prompt ): 
    # 分析用户提示以确定意图
    # 为简单起见,假设直接提供意图
    intent = user_prompt   # 在实践中,使用 NLP 技术来确定意图
    
    # 根据意图检索相关的表、字段和条件
    schema_info = intent_to_tables.get(intent, {}) 
    
    # 生成系统提示
    system_prompt = f"生成 SQL 查询以计算{intent}。 "
     system_prompt += f"使用表格:{ ',' .join(schema_info.get( 'tables',[]))}。"
     system_prompt += f"选择字段:{ ',' .join(schema_info.get( 'fields',[]))}。"
     system_prompt += f"在条件下:{ ',' .join(schema_info.get( 'conditions',[]))}。" 
    
    return system_prompt 

# 示例用法
user_prompt = "去年总销售额"
 system_prompt = generate_system_prompt(user_prompt) 
print (system_prompt)
生成 SQL 查询以计算去年的总销售额。使用表:一个SQL 查询,用于计算去年的总销售额。使用表:
SalesOrder、LineItem、Product。选择字段:ProductName、SUM (TotalPrice)。
条件:YEAR (OrderDate) = YEAR ( CURDATE ()) - 1。

全面的系统提示:

图片来自作者

数据库模式概述:详细介绍SalesOrder 数据库模式的结构,列出表格及其用途。SQL查询生成指南:提供创建高效、准确的SQL查询的原则,涵盖 JOIN、WHERE子句和聚合函数。处理特定案例:管理NULL值和确保日期范围包含在内。每个表的示例记录:提供来自供应商、产品、员工、客户、InventoryLog、LineItem和SalesOrder 表的示例,以说明存储的数据类型。适应性说明:鼓励根据特定分析需求定制查询,并提供常见查询及其原理的示例。

  
  

img

图片来自作者

第 4 部分:SQL 查询验证:

查询验证:

要求 LLM 通过在系统提示中添加验证规则来验证生成的查询。

仔细检查用户的 {dialect} 查询是否存在常见错误,包括:
 -将NOT IN与NULL 值一起使用 -应使用 UNION ALL时却使用UNION -将BETWEEN用于排他范围-谓词中的数据类型不匹配- 正确引用标识符-为函数使用正确数量的参数- 转换为正确的数据类型-为连接使用正确的列如果存在上述任何错误,请重写查询。如果没有错误,只需重新生成原始查询。  
从langchain_core.output_parsers导入StrOutputParser
从langchain_core.prompts导入ChatPromptTemplate 

system = """给定以下数据库模式,根据用户的问题生成 MySQL 查询。记得根据需要计算行项目的总数,并确保所有日期范围都包括在内,除非另有说明。正确汇总数据以进行汇总,例如平均订单总额。
- 客户 (CustomerID INT、FirstName VARCHAR(100)、LastName VARCHAR(100)、Email VARCHAR(255)、Phone VARCHAR(20)、BillingAddress TEXT、ShippingAddress TEXT、CustomerSince DATE、IsActive TINYINT) 
- 员工 (EmployeeID INT、FirstName VARCHAR(100)、LastName VARCHAR(100)、Email VARCHAR(255)、Phone VARCHAR(20)、HireDate DATE、Position VARCHAR(100)、Salary DECIMAL) 
- InventoryLog(LogID INT、ProductID INT、ChangeDate DATE、QuantityChange INT、Notes TEXT)
-LineItem(LineItemID INT、SalesOrderID INT、ProductID INT、Quantity INT、UnitPrice DECIMAL、Discount DECIMAL、TotalPrice DECIMAL)
-Product(ProductID INT、ProductName VARCHAR(255)、Description TEXT、UnitPrice DECIMAL、StockQuantity INT、ReorderLevel INT、Discontinued TINYINT)
-SalesOrder(SalesOrderID INT、CustomerID INT、OrderDate DATE、RequiredDate DATE、ShippedDate DATE、Status VARCHAR(50)、Comments TEXT、PaymentMethod VARCHAR(50)、IsPaid TINYINT)
-SupplierID INT、CompanyName VARCHAR(255)、ContactName VARCHAR(100)、ContactTitle VARCHAR(50)、Address TEXT, Phone VARCHAR(20), Email VARCHAR(255))

示例任务:计算特定时间段内未注册电话号码的客户的订单平均总价。
示例查询:"SELECT AVG(sum_li.TotalPrice) FROM SalesOrder JOIN (SELECT SalesOrderID, SUM(TotalPrice) AS TotalPrice FROM LineItem GROUP BY SalesOrderID) sum_li ON SalesOrder.SalesOrderID = sum_li.SalesOrderID JOIN Customer ON SalesOrder.CustomerID = Customer.CustomerID WHERE Customer.Phone IS NULL AND SalesOrder.OrderDate BETWEEN '2003-01-01' AND '2009-12-31';"
仔细检查用户的 {dialect} 查询是否存在常见错误,包括:
- 将 NOT IN 与 NULL 值一起使用
- 应使用 UNION ALL 时却使用 UNION 
- 将 BETWEEN 用于排他范围
- 谓词中的数据类型不匹配
- 正确引用标识符
- 为函数使用正确数量的参数
- 转换为正确的数据类型
- 使用正确的列进行连接

如果存在上述任何错误,请重写查询。如果没有错误,只需重现原始查询。

仅输出最终的 SQL 查询。无文本,请仅输出 SQL 查询"""
prompt = ChatPromptTemplate.from_messages( 
    [( “system” , system), ( “human” , “{query}” )] 
).partial(dialect=db.dialect) 
validation_chain = prompt | llm | StrOutputParser() 

full_chain = { “query” : chain} | validation_chain

img

图片来自作者

第 5 部分:数据库中非描述性或特定于语言的表和字段名称:

对于具有非描述性或特定于语言的表和字段名称的数据库,创建一个全面的映射或词典,将这些技术标识符转换为更易于理解的术语会非常有帮助。此映射可以作为用户的自然语言查询与实际数据库模式之间的桥梁,使 LLM 能够生成准确的 SQL 查询。

**创建翻译映射:**开发全面的映射,将技术标识符(表名、字段名)翻译成更易理解的英语术语。这有助于弥合自然语言查询和实际数据库模式之间的差距。

**将映射合并到 LLM 输入中:**将此映射直接集成到系统提示中或使用它来预处理用户查询,使 LLM 更容易理解和生成正确的 SQL 查询。

**使用自定义数据对 LLM 进行微调:**考虑对包含技术标识符及其翻译的示例进行 LLM 微调,以提高其直接处理此类情况的能力。

**使用带注释的示例:**在提示中或作为训练数据的一部分,包括在自然语言问题及其相应的 SQL 查询中使用技术标识符的示例,为 LLM 提供上下文。

# 将技术标识符映射到可理解的术语的示例
映射 = { 
    "kunnr" : "customer" , 
    "lifnr" : "vendor" , 
    # 根据需要添加更多映射
} 

def Translation_query(user_query, Mapping): 
    for Technical_term, Common_term in Mapping.items(): 
        user_query = user_query.replace(common_term, Technical_term) 
    return user_query 

# 示例用法
user_query = "显示供应商去年的销售额"
 Translation_query = Translation_query(user_query, Mapping) 
# 现在,translated_query 可以传递给 LLM 进行 SQL 生成

img

图片来自作者

第六部分:大型企业挑战

img

图片来自作者

大型企业数据库面临几个挑战:

**复杂模式:**企业通常具有包含数百个表和关系的复杂数据库模式,如果没有广泛的领域知识,LLM 很难生成准确的 SQL 查询。

**非标准命名约定:**如上所述,数据库可能使用非直观的命名约定或不同的语言,需要映射或额外的上下文才能有效地生成查询。

**安全和隐私:**直接在真实数据库上执行生成的 SQL 查询可能会带来安全风险,包括潜在的数据暴露或注入攻击。

**性能问题:**在大型数据库上生成和执行 SQL 查询可能会耗费大量资源,从而影响数据库性能。

**数据新鲜度:**企业需要实时数据,但 LLM 可能会生成不考虑最新数据更新的查询,从而导致见解过时。

img

图片来自作者

第 7 部分 - 文本 2 可视化:

img

图片来自 Gemini

使用 LLM 设计文本到可视化工具包括:

**理解用户查询:**解析自然语言输入以辨别用户的意图和他们想要可视化的数据。
**映射到数据库查询:**将解析的意图转换为 SQL 查询以从数据库中获取相关数据。
**选择可视化类型:**根据查询结果和用户意图,选择合适的可视化类型(条形图、折线图、饼图)。
**生成可视化:**使用 Python 中的数据可视化库(例如 Matplotlib、Plotly)创建查询数据的可视化表示。
**与 LLM 集成:**利用 LLM 来完善查询理解、建议可视化类型并通过反馈循环改善用户交互。
**用户界面设计:**创建一个用户友好的界面,允许轻松输入文本查询并有效显示可视化。

伪代码:

从your_llm_library导入LLM   # 假设的 LLM 库
导入matplotlib.pyplot作为plt
导入pandas作为pd
导入sql_connector   # 假设的模块用于连接和执行 SQL 查询

# 初始化你的 LLM
 llm = LLM(api_key= "your_api_key" ) 

def  query_database ( sql_query ): 
    # 连接到你的数据库并执行 SQL 查询
    # 以 DataFrame 形式返回结果
    connection = sql_connector.connect(host= "your_host" , database= "your_db" , user= "your_user" , password= "your_password" ) 
    return pd.read_sql(sql_query, connection) 

def  generate_visualization ( data, visual_type ): 
    # 根据类型和数据生成可视化
    if visual_type == "bar" : 
        data.plot(kind= "bar" ) 
        plt.show() 
    # 根据需要添加更多可视化类型

def  text_to_sql ( text_input ): 
    # 使用LLM 将文本输入转换为 SQL 查询
    sql_query = llm.generate_sql_query(text_input) 
    return sql_query 

def  text_to_visualization ( text_input ): 
    # 将文本输入转换为 SQL 查询
    sql_query = text_to_sql(text_input) 
    
    # 查询数据库
    data = query_database(sql_query) 
    
    # 根据数据或用户输入确定可视化类型
    visual_type = "bar"   # 这可以动态确定
    
    # 生成可视化
    generate_visualization(data, visual_type) 

# 示例用法
text_input = "显示去年每种产品的总销售额"
 text_to_visualization(text_input)

此伪代码概述了获取用户的自然语言输入、将其转换为 SQL 查询、从数据库获取数据以及根据获取的数据生成可视化效果的步骤。实际实现取决于您使用的 LLM 库、数据库设置以及您喜欢的 Python 数据可视化库。

这是一个 poc 代码,您可以在其基础上不断改进。

从langchain_community.utilities导入SQLDatabase 

# 调整 MySQL 的连接 URI
 db = SQLDatabase.from_uri( "mysql+mysqlconnector://'your user id':'your password@localhost/SalesOrderSchema" )
将pandas导入为pd

从langchain.chains导入create_sql_query_chain
从langchain_openai导入ChatOpenAI
从langchain_core.output_parsers导入StrOutputParser
从langchain_core.prompts导入ChatPromptTemplate将pandas
导入为pd 

# 假设 'db' 是你的 SQLDatabase 实例 从 langchain_community.utilities 
# 并且 execute_query 是一个执行 SQL 并返回 pandas DataFrame 的函数

# 使用 GPT-4 初始化 LLM
 llm = ChatOpenAI(model= "gpt-4" ,temperature= 0 ) 

# 使用 LLM 和你的数据库配置创建 SQL 查询链
chain = create_sql_query_chain(llm,db) 

# 定义一条系统消息,用于根据架构生成 SQL 查询
system = """
给定下面的数据库架构,根据用户的问题生成 MySQL 查询。记得根据需要从行项目计算总数,并确保所有日期范围都包含在内除非另有说明。正确汇总数据以进行汇总,例如平均订单总额。
- 客户 (CustomerID INT、FirstName VARCHAR(100)、LastName VARCHAR(100)、Email VARCHAR(255)、Phone VARCHAR(20)、BillingAddress TEXT、ShippingAddress TEXT、CustomerSince DATE、IsActive TINYINT) 
- 员工 (EmployeeID INT、FirstName VARCHAR(100)、LastName VARCHAR(100)、Email VARCHAR(255)、Phone VARCHAR(20)、HireDate DATE、Position VARCHAR(100)、Salary DECIMAL) 
- InventoryLog (LogID INT、ProductID INT、ChangeDate DATE、QuantityChange INT、Notes TEXT) 
- LineItem (LineItemID INT、SalesOrderID INT、ProductID INT、Quantity INT、UnitPrice DECIMAL、Discount DECIMAL、TotalPrice DECIMAL) 
- 产品(ProductID INT、ProductName VARCHAR(255)、说明 TEXT、UnitPrice DECIMAL、StockQuantity INT、ReorderLevel INT、Discontinued TINYINT)
- 销售订单(SalesOrderID INT、CustomerID INT、OrderDate DATE、RequiredDate DATE、ShippedDate DATE、状态 VARCHAR(50)、注释 TEXT、PaymentMethod VARCHAR(50)、IsPaid TINYINT)
- 供应商(SupplierID INT、CompanyName VARCHAR(255)、ContactName VARCHAR(100)、ContactTitle VARCHAR(50)、地址 TEXT、电话 VARCHAR(20)、电子邮件 VARCHAR(255))
“””

 prompt = ChatPromptTemplate.from_messages(
    [("system",system)] 
)。partial(dialect=db.dialect)

# 假设'execute_query'是一个执行生成 SQL 查询并返回 DataFrame 
def  execute_query ( sql_query ):
    # 执行 SQL 查询并返回 pandas DataFrame 的实现
    pass 

# 使用链根据自然语言输入生成 SQL 查询
query_input = "Show me the total sales for each product last year"
 query_response = chain.invoke({ "question" : query_input}) 

# 执行生成的 SQL 查询
#df = execute_query(query_response)
 query_results = db.run(query_response) 



import pandas as pd 
from decimal import Decimal 

# 用于说明的虚拟数据;将其替换为您的实际的 query_results 
#query_results_str = "[('Reflect Sea', Decimal('25.31')), ('Avoid American', Decimal('514.63'))]"
 query_results_str = query_results 
query_results_str = query_results_str.replace( "Decimal('" , "" ).replace( "')" , "" ) 

# 尝试安全地将字符串评估为元组列表
try : 
    query_results_evaluated = eval (query_results_str, { 'Decimal' : Decimal}) 
except Exception as e: 
    print ( f"Error during evaluation: {e} " ) 
    query_results_evaluated = [] 

# 将 Decimal 转换为浮点数并准备 DataFrame
 query_results_converted = [(name, float (total)) if  isinstance (total, Decimal) else (name, total) for name, total in query_results_evaluated] 

# 创建 DataFrame
 df = pd.DataFrame(query_results_converted, columns=[ 'ProductName' , 'TotalSales' ]) 

df_json = df.to_json(orient= 'split' , index= False ) 

# 继续您的工作流程... 
# 准备用于生成 Matplotlib 可视化代码的提示模板
# 准备用于生成 Matplotlib 可视化代码的提示模板
prompt_template = ChatPromptTemplate.from_template( 
    "给定以下数据,使用 Matplotlib 生成 Python 代码以创建合适的可视化效果,以最能代表数据洞察。确定最能显示数据的图表类型(例如,条形图、饼图、折线图)。简要说明您选择这种可视化类型的原因。以下是数据:
{data}" ) 


# 使用 GPT-4 初始化模型
model = ChatOpenAI(model= "gpt-4") 

# 初始化输出解析器以提取字符串响应
output_parser = StrOutputParser() 

# 创建链:prompt + model + 输出解析器
visualization_chain = prompt_template | model | output_parser 

# 使用 DataFrame JSON 作为输入调用链
visualization_code = visualization_chain.invoke({ "data" : df_json}) 

# 打印生成的代码以供审查
#print(visualization_code)


 hybrid_text = visualization_code 
code_start = hybrid_text.find( "python" ) + len ( "python" ) 
code_end = hybrid_text.find( "```" , code_start) 
generated_code = hybrid_text[code_start:code_end].strip() 

#print(generated_code) 
exec (generated_code)

输出 — 如果您启用所有打印语句,您就可以看到输出。

选择 `产品`.`产品名称`, SUM(`LineItem`.`总价`) 作为 `总销售额`
从 `产品
` 加入 `LineItem` 在 `产品`.`产品ID` = `LineItem`.`产品ID`
加入 `销售订单` 在 `LineItem`.`销售订单ID` = `销售订单`.`销售订单ID`
其中 YEAR(`销售订单`.`订单日期`) = YEAR(CURDATE()) - 11
 GROUP BY `Product`.`ProductName` 
LIMIT 5 ; 
[( 'Reflect Sea' , Decimal( '25.31' )), ( 'Avoid American' , Decimal( '514.63' )), ( 'Certain Identity' , Decimal( '1260.98' )), ( 'Impact Agreement' , Decimal( '518.32' )), ( 'Million Agreement' , Decimal( '250.02' ))]提供的数据
可以使用条形图表示。条形图很合适,因为我们正在比较不同产品名称的总销售额。下面是使用 Matplotlib 可视化这些数据的 Python 代码:```python import matplotlib.pyplot as plt import pandas as pd #数据data_dict = { "columns" :[ "ProductName" , "TotalSales" ], "data" :[[ "Reflect Sea" , 25.31 ],[ "Avoid American" , 514.63 ],[ "Certain Identity" , 1260.98 ],[ "Impact Agreement" , 518.32 ],[ "Million Agreement" , 250.02 ]]} # 将数据转换为 pandas DataFrame df = pd.DataFrame(data_dict[ 'data' ], columns=data_dict[ 'columns' ]) # 创建条形图plt.figure(figsize=( 10 , 6 )) plt.barh(df[ 'ProductName' ], df[ 'TotalSales' ], color= 'blue' ) plt.xlabel( 'Total Sales' ) plt.ylabel( 'Product Name' ) plt.title( 'Total Sales by Product Name' ) plt.show() ```此代码首先将数据转换为 pandas DataFrame,这使其更易于操作和绘图。然后,它创建一个水平条形图,其中y 轴为'ProductName'列, x 轴为'TotalSales'列。为了更清晰,将图形尺寸设置为10x6 ,并添加标签和标题以提供上下文。条形图的颜色设置为 




















  为蓝色,但您可以将其更改为您喜欢的任何颜色。
导入matplotlib.pyplot作为plt
导入pandas作为pd 

#数据
data_dict = { "columns" :[ "ProductName" , "TotalSales" ], "data" :[[ "Reflect Sea" , 25.31 ],[ "Avoid American" , 514.63 ],[ "Certain Identity" , 1260.98 ],[ "Impact Agreement" , 518.32 ],[ "Million Agreement" , 250.02 ]]} 

# 将数据转换为 pandas DataFrame 
df = pd.DataFrame(data_dict[ 'data' ], columns=data_dict[ 'columns' ]) 

# 创建条形图
plt.figure(figsize=( 10 , 6 )) 
plt.barh(df[ 'ProductName' ], df[ 'TotalSales' ], color= 'blue' ) 
plt.xlabel( '总销售额' ) 
plt.ylabel( '产品名称' ) 
plt.title( '按产品名称划分的总销售额' ) 
plt.show()

img

代码概述:

**初始化 LLM:**使用 GPT-4,你可以设置一个随时可以处理输入的实例。
**创建 SQL 查询链:**将 LLM 与数据库相结合,此链旨在将自然语言问题转换为 SQL 查询。
**定义系统消息:**这提供了有关数据库模式的上下文,以帮助生成准确的 SQL 查询。
**生成 SQL 查询:**将用户的自然语言输入(“显示去年每种产品的总销售额”)转换为可执行的 SQL 查询。
**执行 SQL 查询:**对数据库运行生成的查询以获取所需的数据。
**准备可视化数据:**将查询结果转换为适合可视化的格式。
**生成可视化代码:**编写 Python 代码以创建表示数据洞察的可视化效果(例如,使用 Matplotlib)。
**执行可视化代码:**运行生成的 Python 代码以生成可视化效果。

img

图片来自作者

第 8 部分 - 使用 Ollama 进行文本 2 SQL:

您还可以使用 Ollama 将模型下载到您自己的机器上并进行试用。在使用以下命令之前,请在您的机器上安装 Ollama。

欧拉玛

在本地启动并运行大型语言模型。

ollama.com

我尝试了 Google Gemma 模型。

!ollama 拉动 gemma
!ollama 运行 gemma

系统提示:

v_sys = """
您是 MySQL 专家,您将针对用户问题生成 MySQL 查询。
给定以下数据库模式,根据用户的问题生成 MySQL 查询。确保考虑行项目的总计、包含日期范围和正确的数据聚合以进行汇总。记住要有效地处理连接、分组和排序。数据库模式

:
- 客户(客户 ID、名字、姓氏、电子邮件、电话、账单地址、发货地址、客户自、是否活跃)
- 员工(员工 ID、名字、姓氏、电子邮件、电话、雇用日期、职位、薪水)
- 库存日志(日志 ID、产品 ID、更改日期、数量更改、注释)
- 行项目(行项目 ID、销售订单 ID、产品 ID、数量、单价、折扣、总价)
- 产品(产品 ID、产品名称、说明、单价、库存数量、重新订购级别、停产)
- 销售订单(销售订单 ID、客户 ID、订单日期、所需日期、发货日期、状态、评论、付款方式、已付款)
- 供应商(供应商 ID、公司名称、联系人姓名、联系人头衔、地址、电话、电子邮件)

SQL 查询生成指南:
1. **确保效率和性能**:尽可能选择 JOIN 而不是子查询,有效使用索引,并提及需要牢记的任何具体性能注意事项。2 
. **适应特定的分析需求**:定制 WHERE 子句、JOIN 操作和聚合函数,以精确满足所提出的分析问题。3 
. **复杂性和变化**:包括从简单到复杂的查询范围,说明不同的 SQL 功能,如聚合函数、字符串操作和条件逻辑。4 
. **处理具体情况**:提供有关管理 NULL 值、确保日期范围包含在内以及处理特殊数据完整性问题或边缘情况的明确说明。
5. **解释和理由**:每次生成查询后,简要
解释为什么选择这种查询结构以及它如何满足
分析需求,以增强理解并确保与
要求保持一致。"""
导入ollama 

r = ollama.generate(
    模型= 'gemma',
    系统=v_sys,
    提示= “按薪水列出前 10 名员工?”“”
)

打印(r [ 'response' ])
##按薪水列出前10 名员工` `` sql SELECT * FROM Employee ORDER BY Salary DESC LIMIT 10 ; ```* *原因:* *此查询选择所有员工并根据他们的薪水按降序排列。` ORDER BY `子句指定排序条件,` LIMIT 10 `子句将结果限制为前10 名员工。* *注意事项:* * *此查询假定`Employee`表中的`Salary`列包含代表薪水的数值。*该查询不会根据任何特定条件过滤员工。要将结果限制为特定的一组员工,您可以向` WHERE `子句添加其他条件。 * *其他注意事项:* * *在`Salary`列上建立索引以提高查询性能。*适当处理`Salary`列中的NULL值。


   




 



   
 
    
  



 
  

他们还有一些针对文本到 SQL 的微调模型

img

图片来源 Ollama Respository

img

图片来自作者

第 9 部分 - 文本 2 SQL 评估:

img

图片来自 Gemini

  1. Bird-大型数据库文本转 SQL 的大平台

BIRD 长凳

BIRD 长凳

BIRD-benchbird-bench.github.io

img

图片来源 Bird Benchmark

  1. Spider 1.0——耶鲁语义解析和文本到 SQL 挑战赛

Spider:耶鲁语义解析和文本到 SQL 挑战

Yale Spider 是我们推出的用于复杂和跨域语义解析和文本到 SQL 任务的大型数据集……

yale-lily.github.io

  1. WikiSQL

GitHub - salesforce/WikiSQL:用于开发自然的大型带注释语义解析语料库……

用于开发自然语言界面的大型带注释语义解析语料库。 - salesforce/WikiSQL

github.com

  1. Defog- SQL 评估

sql-eval,评估 LLM 生成输出的准确性,下载sql-eval的源码_GitHub_帮酷

评估 LLM 生成输出的准确性。通过创建账户为 defog-ai/sql-eval 开发做出贡献……

github.com

他们如何评估:

我们的测试程序包括以下步骤。对于每个问题/查询对于 每个问题/查询
对:

我们生成一个 SQL 查询(可能来自LLM)。
我们在各自的数据库上运行“黄金”查询和生成的查询,以获得2 个包含结果的数据框。我们使用“精确”和“子集”匹配比较2 个数据框。TODO添加博客文章链接。我们将这些与其他感兴趣的指标(例如使用的令牌、延迟)一起记录,并汇总结果以供报告。

 


 

你可以查看一下。

img

图片来自作者

第 10 部分 - 其他参考文章和存储库:

这里有几篇文章。

从企业数据中创造价值:Text2SQL 和生成式 AI 的最佳实践 | 亚马逊网络……

生成式人工智能在人工智能领域开辟了巨大的潜力。我们看到了许多用途,包括文本……

亚马逊

构建一个强大的文本到 SQL 解决方案,生成复杂的查询、自我纠正和查询……

结构化查询语言 (SQL) 是一种复杂的语言,需要了解数据库和元数据。如今…

亚马逊

使用实体提取、SQL 查询等功能增强基于 RAG 的智能文档助手……

近年来,得益于生成式人工智能的快速发展,对话式人工智能取得了长足的进步,尤其是……

亚马逊

GitHub - vanna-ai/vanna:🤖 与你的 SQL 数据库聊天📊。通过… 实现准确的文本到 SQL 生成

🤖 与您的 SQL 数据库聊天 📊。使用 RAG 通过 LLM 实现准确的文本到 SQL 生成 🔄。- vanna-ai/vanna

github.com

根据您的企业数据调整我们的法学硕士课程

这个面向公众的演示运行具有贪婪搜索的 SQLCoder 的有限版本,并且性能会比我们的更差……

defog.ai

嘎嘎叫的人工智能:介绍 DuckDB-NSQL-7B,DuckDB SQL 的法学硕士

我们的第一个 Text2SQL 模型发布!

motherduck.com

文本到 SQL 的架构模式:利用 LLM 增强 BigQuery 交互

TLDR:本文深入探讨了文本到 SQL 领域,展示了对大型语言模型日益增长的依赖……

medium.com

img

图片来自作者

第 11 部分 - 使用 Llamaindex 的 Text2SQL。

让我们看看如何使用 Llamaindex 进行 text2SQL。

img

图片来源 Llamaindex Documentation

让我们在同一个数据库上工作

  • *MySQL 数据库。*
  • *销售订单架构*
  • *之前已创建 7 张表。*
  1. pip 安装所有必需的库。
!pip install mysql-connector-python SQLAlchemy pandas 

%pip install llama-index-embeddings-openaiindex -embeddings-openai 

!pip install llama- index -llms-openai   # 这是假设的;如果不同,请用正确的库名替换。
 !pip install pyvis networkx

2.提供 OpenAi 密钥:

import osos 

os .environ[ "OPENAI_API_KEY" ] = "您的 API 密钥"

3.连接MySQL数据库:

从 sqlalchemy 导入 create_engine

# SQLAlchemy 连接 MySQL 的字符串
database_url = "mysql+mysqlconnector://"你的用户 ID ":"密码"@localhost/SalesOrderSchema" 

# 创建引擎
mysql_engine = create_engine(database_url)

**从 SQLAlchemy 导入 create_engine:**此行从 SQLAlchemy 库导入 create_engine 函数,该函数用于创建到数据库的连接引擎。
定义数据库 URL: database_url 是一个字符串,用于指定 MySQL 数据库的连接详细信息。它包括数据库适配器 (mysql+mysqlconnector)、用户名 (root)、密码 (‘Your Password’)、主机 (localhost) 和数据库名称 (SalesOrderSchema)。
此 URL 的格式为:dialect+driver://username:password@host/database。
创建引擎: mysql_engine = create_engine(database_url) 使用 create_engine 函数创建 SQLAlchemy 引擎。此引擎是一个使用 database_url 中提供的连接详细信息来管理与数据库的连接的对象。引擎负责在需要连接时连接到数据库,但不会在创建时建立连接。
目的和用法: create_engine 创建的引擎是 SQLAlchemy 的 SQL 表达式语言和 ORM(对象关系映射)功能的核心组件。它可用于执行原始 SQL 查询、使用 ORM 与数据库交互等。
此设置允许您使用 SQLAlchemy 强大而灵活的工具进行数据库操作,从而消除直接数据库访问的许多复杂性。

4.表格信息:

table_infos = [ 
    { "table_name" : "客户" , "table_summary" : "保存客户信息,包括联系方式和地址。" }, 
    { "table_name" : "员工" , "table_summary" : "包含员工记录、职位和薪资信息。" }, 
    { "table_name" : "InventoryLog" , "table_summary" : "跟踪库存变化,包括产品数量和相关说明。" }, 
    { "table_name" : "LineItem" , "table_summary" : "详细说明销售订单中的每一件商品,包括价格和数量。" }, 
    { "table_name" : "产品" , "table_summary" : "列出可用产品、其描述、价格和库存水平。" }, 
    { "table_name" : "销售订单" , "table_summary" : "记录客户订单,包括订单日期、发货信息和付款状态。" }, 
    { "table_name" : "供应商" , "table_summary" : "存储有关供应商的信息,包括公司和联系方式。" } 
]

字典列表: table_infos 是一个列表,一个有序且可更改的集合。列表中的每个项目都是一个字典,代表数据库中的表。
**字典结构:**列表中的每个字典都有两个键:table_name 和 table_summary。table_name 是一个字符串,包含数据库中表的名称。这是在 SQL 查询中识别表的方式。table_summary
是一个字符串,它提供了表包含或代表的内容的简要描述。此摘要提供了有关表在数据库中的作用的背景信息,这对于文档、代码可读性或为可能使用这些描述来更好地理解数据库模式的系统提供见解很有帮助。
**目的:**此结构旨在以结构化格式提供有关数据库中表的元数据。它可用于文档目的、帮助生成动态查询或与需要数据库模式描述的系统交互。
**示例用例:**如果您使用的系统将自然语言查询转换为 SQL 查询(如前面讨论的文本到 SQL 功能),table_infos 可以为系统提供有关每个表的必要上下文。例如,当用户询问客户联系信息时,了解 Customer 表包含客户信息(包括联系方式和地址)可能有助于系统生成更准确的查询。可
**扩展性:**这种方法很容易扩展。如果您的数据库架构发生变化(例如,添加新表或更改现有表的用途),您只需更新 table_infos 列表以反映这些变化即可。

5. 对象索引 + 检索器用于存储表模式:

从llama_index.core.objects导入(SQLTableNodeMapping、ObjectIndex、SQLTableSchema、)从llama_index.core导入SQLDatabase 、VectorStoreIndex sql_database = SQLDatabase(engine=mysql_engine)table_node_mapping = SQLTableNodeMapping(sql_database)table_schema_objs = [ SQLTableSchema(table_name=t[ ' table_name' ],context_str=t[ 'table_summary' ])for t in table_infos ] obj_index = ObjectIndex.from_objects(    table_schema_objs、    table_node_mapping、VectorStoreIndex、)obj_retriever = obj_index.as_retriever(similarity_top_k = 3) 
    
    
    

  





    
    




    

**导入语句:**代码首先从 llama_index.core 包导入各种类。这些类包括 SQLTableNodeMapping、ObjectIndex、SQLTableSchema、SQLDatabase 和 VectorStoreIndex。每个类都在创建数据库模式的索引表示以供在 LlamaIndex 框架内使用方面发挥着作用。
创建 SQLDatabase 实例: sql_database = SQLDatabase(engine=mysql_engine) 使用您之前定义的 mysql_engine 创建 SQLDatabase 实例。此 SQLDatabase 对象旨在提供与 LlamaIndex 系统内的 MySQL 数据库交互的接口,从而抽象出直接的 SQL 操作。
初始化表节点映射: table_node_mapping = SQLTableNodeMapping(sql_database) 初始化一个对象,该对象负责在数据库表的逻辑结构(作为节点)和 sql_database 所表示的物理数据库之间进行映射。此映射对于需要理解数据库模式的操作至关重要,例如从自然语言输入生成 SQL 查询。
**创建表架构对象:**列表推导式 [SQLTableSchema(table_name=t[‘table_name’], context_str=t[‘table_summary’]) for t in table_infos] 遍历您定义的 table_infos 列表。对于每个条目,它都会创建一个 SQLTableSchema 实例,该实例表示数据库中表的架构,包括其名称和上下文摘要。这构成了理解和与 LlamaIndex 系统内每个表交互的基础。
创建对象索引: obj_index = ObjectIndex.from_objects(table_schema_objs, table_node_mapping, VectorStoreIndex,) 创建数据库架构的索引表示。它使用表架构对象 (table_schema_objs)、表节点映射 (table_node_mapping) 和向量存储索引 (VectorStoreIndex) 来促进基于与自然语言查询的相似性或相关性高效检索和查询架构信息。
初始化检索器: obj_retriever = obj_index.as_retriever(similarity_top_k=3) 从对象索引初始化检索器对象。此检索器配置为根据给定查询获取前 k 个(在本例中为 3 个)最相关的表架构对象。此功能可能用于根据查询与表的上下文摘要的相似性,动态识别在将自然语言查询转换为 SQL 时应考虑哪些表。

6. SQLDatabase 对象连接到上述表 + SQLRetriever:

从llama_index.core.retrievers导入SQLRetriever
从typing导入 列表
从llama_index.core.query_pipeline导入FnComponent 

sql_retriever = SQLRetriever(sql_database) 


def  get_table_context_str ( table_schema_objs: List [SQLTableSchema] ): 
    """获取表上下文字符串。"""
     context_strs = [] 
    for table_schema_obj in table_schema_objs: 
        table_info = sql_database.get_single_table_info( 
            table_schema_obj.table_name 
        ) 
        if table_schema_obj.context_str: 
            table_opt_context = " 表描述为: "
             table_opt_context += table_schema_obj.context_str 
            table_info += table_opt_context 

        context_strs.append(table_info) 
    return  "\n\n" .join(context_strs) 


table_parser_component = Fn组件(fn=get_table_context_str)

SQLRetriever 初始化: sql_retriever = SQLRetriever(sql_database) 使用先前初始化的 sql_database 对象创建 SQLRetriever 实例。这表明 sql_retriever 能够执行数据库检索,可能利用 sql_database 封装的架构信息。
定义函数以获取表上下文字符串: get_table_context_str 是一个函数,它接受 SQLTableSchema 对象 (table_schema_objs) 列表并为每个表生成一个上下文字符串。此上下文字符串可能用于提供有关每个表的其他信息,这些信息在生成或理解从自然语言输入派生的 SQL 查询时很有用。在函数内部,它遍历 table_schema_objs,从 sql_database 获取每个表架构对象 (table_schema_obj) 的其他表信息。如果 table_schema_obj 包含 context_str(表格的摘要或描述),它会将其附加到表格信息中,以增强每个表格的详细信息。
生成的字符串被收集到 context_strs 列表中,然后将其合并为一个字符串,使用双换行符 (\n\n) 作为分隔符,使最终输出更易于阅读或进一步处理。
创建表格解析器组件: table_parser_component = FnComponent(fn=get_table_context_str) 将 get_table_context_str 函数包装在 FnComponent 中,使其成为可以集成到查询处理管道中的组件。在 LlamaIndex 上下文中,此组件可用于动态生成与给定自然语言查询相关的表格的上下文丰富描述,支持将该查询转换为准确的 SQL 语句。

7.文本到SQL提示:

从llama_index .core .prompts .default_prompts导入 DEFAULT_TEXT_TO_SQL_PROMPT
从llama_index .core导入 PromptTemplate
从llama_index .core .query_pipeline导入 FnComponent
从llama_index .core .llms导入 ChatResponse 


def parse_response_to_sql(response: ChatResponse) -> str: 
    "" "解析对 SQL 的响应。" ""
     response = response.message.content 
    sql_query_start = response.find ( " SQLQuery:" )
    如果 sql_query_start != - 1 : 
        response = response[sql_query_start:] # TODO:在 Python 3.9
        之后移至 removeprefix +        如果 response.startswith ( "SQLQuery:" ):             response = response[ len ( "SQLQuery:" ) :]     sql_result_start = response.查找(“SQLResult:”)    如果sql_result_start!= - 1:        响应=响应[:sql_result_start]    返回响应。剥离()。剥离(“```”)。剥离()sql_parser_component = FnComponent(fn = parse_response_to_sql)text2sql_prompt = DEFAULT_TEXT_TO_SQL_PROMPT。partial_format (    dialect = mysql_engine.dialect.name )打印(text2sql_prompt.template)

解析模型的响应: parse_response_to_sql 是一个函数,它从聊天或语言模型(封装在 ChatResponse 对象中)获取响应并从中提取 SQL 查询。这是必要的,因为模型的响应可能包含除 SQL 查询之外的其他信息或格式。它在响应中搜索特定标记(SQLQuery: 和 SQLResult:)以隔离文本的 SQL 查询部分。这种解析策略意味着语言模型的响应应该遵循结构化格式,其中 SQL 查询及其结果被明确划分。
创建 SQL 解析器组件: sql_parser_component = FnComponent(fn=parse_response_to_sql) 将 parse_response_to_sql 函数包装在 FnComponent 中,允许将其集成到查询处理管道中。此设置有助于自动从模型响应中提取 SQL 查询,然后可以针对数据库执行或进一步处理。
设置文本到 SQL 提示: text2sql_prompt = DEFAULT_TEXT_TO_SQL_PROMPT.partial_format(dialect=mysql_engine.dialect.name) 初始化用于根据自然语言问题生成 SQL 查询的提示模板。该模板针对数据库(在本例中为 MySQL)的特定 SQL 方言进行定制,由 SQLAlchemy 引擎 (mysql_engine) 的方言属性决定。此定制确保为语言模型生成的提示适合 MySQL 支持的 SQL 语法,从而增加生成的 SQL 查询在语法上正确且可执行的可能性。
打印提示模板: print(text2sql_prompt.template) 将格式化的提示模板打印到控制台。这对于调试或了解发送到语言模型的提示很有用。

给定一个输入问题,首先创建一个语法正确的 {dialect} 查询来运行,然后查看查询结果并返回答案。您可以按相关列对结果进行排序,以返回数据库中最有趣的示例。输入问题,首先创建一个语法正确的 {dialect} 查询来运行,然后查看查询结果并返回答案。您可以按相关列对结果进行排序,以返回数据库中最有趣的示例。切勿查询特定表中的所有列,仅针对问题询问几个相关列。注意仅使用您可以在模式描述中看到的列名。注意不要查询不存在的列。注意哪列在哪个表中。此外,在需要时使用表名限定列名。您需要使用以下格式,每行占一行:问题:问题此处SQLQuery:要运行的 SQL 查询SQLResult:SQLQuery 的结果答案:最终答案此处仅使用下面列出的表。{schema}问题:{query_str} SQLQuery:

  

8. 反应综合提示:

从 llama_index.core.program 导入 LLMTextCompletionProgram导入LLMTextCompletionProgram
从 llama_index.core.bridge.pydantic导入BaseModel、Field
从 llama_index.llms.openai导入OpenAI 


response_synthesis_prompt_str = ( 
    "给定一个输入问题,从查询结果中合成一个响应。\n " 
    "查询:{query_str} \n " 
    "SQL:{sql_query} \n " 
    "SQL 响应:{context_str} \n " 
    "响应:"
 ) 
response_synthesis_prompt =  PromptTemplate ( 
    response_synthesis_prompt_str, 
)

定义响应合成提示模板: response_synthesis_prompt_str 是一个字符串,它定义用于生成要发送到语言模型的提示的模板。该模板包括输入问题 ({query_str})、基于该问题生成的 SQL 查询 ({sql_query}) 以及执行查询的 SQL 响应或结果 ({context_str}) 的占位符。该模板的结构旨在指导语言模型根据此信息合成人类可读的响应。此提示结构的目的是为语言模型提供生成信息性响应所需的所有必要上下文。它构建问题,显示代表问题意图的 SQL 查询,并提供查询的结果,要求模型将这些组件合成为连贯的答案。
创建 PromptTemplate 实例: response_synthesis_prompt 是使用 response_synthesis_prompt_str 初始化的 PromptTemplate 实例。此对象封装了提示模板,通过在占位符中填充特定查询字符串、SQL 查询和查询结果,可以轻松动态生成提示。
此设置表明,response_synthesis_prompt 将用于为语言模型(如 OpenAI 的 GPT-3)生成提示,以生成基于从数据库检索到的实际数据的答案,但其格式和表述方式对人类来说是可理解且有用的。

9. 法学硕士:

llm = OpenAI(模型= “gpt-4”)

10.定义查询管道:

从llama_index.core.query_pipeline导入(
    QueryPipeline作为QP、
    Link、
    InputComponent、
    CustomQueryComponent,
)

qp = QP(
    模块={ 
        “input”:InputComponent(),
        “table_retriever”:obj_retriever,
        “table_output_parser”:table_parser_component,
        “text2sql_prompt”:text2sql_prompt,
        “text2sql_llm”:llm,
        “sql_output_parser”:sql_parser_component,
        “sql_retriever”:sql_retriever,
        “response_synthesis_prompt”:response_synthesis_prompt,
        “response_synthesis_llm”:llm,
    },
    verbose= True,
)

查询管道的组件

  • QueryPipeline(QP):这是组织系统中数据流和操作的主要结构。它定义了如何通过各个阶段或组件处理输入查询以产生输出。该verbose=True参数表示管道应提供有关其处理阶段的详细日志或输出,这有助于调试或了解管道的行为。
  • 模块:
  • 字典中的每个键值对modules代表管道的一个组件:
  • "input"InputComponent可能处理初始接收的查询。
  • "table_retriever":使用obj_retriever(先前定义)根据查询识别相关的数据库表。
  • "table_output_parser":处理表检索器的输出,可能对其进行格式化或进一步细化。
  • "text2sql_prompt":管理将文本查询转换为 SQL 查询的提示的生成。
  • "text2sql_llm":表示负责处理文本到 SQL 提示的语言模型 (LLM) 组件。
  • "sql_output_parser":解析 SQL 查询的输出,提取相关信息或准备进一步处理。
  • "sql_retriever":对数据库执行 SQL 查询并检索结果。
  • "response_synthesis_prompt":处理从 SQL 查询结果合成人类可读的响应的提示的创建。
  • "response_synthesis_llm":处理响应合成提示的语言模型组件。

管道如何工作

  1. 输入处理:管道首先通过组件接收自然语言查询input
  2. 表检索:然后使用来table_retriever确定哪些数据库表与查询相关。
  3. 输出解析:table_output_parser可能从表检索步骤中格式化或提取有用的信息以通知下一阶段。
  4. 提示生成和 LLM 处理:
  • text2sql_prompt根据输入的查询和可能的表信息创建一个结构化的提示,然后由该提示处理以生成text2sql_llmSQL 查询。
  • 执行 SQL 查询并检索结果 ( sql_retriever) 后,该response_synthesis_prompt组件会创建另一个提示,旨在合成人性化响应。此提示由 处理response_synthesis_llm,它使用 SQL 结果和原始查询上下文来生成最终答案。
  • 链接:QueryPipeline对象的设置意味着这些组件之间存在已定义的链接,尽管代码片段中未明确显示具体链接(LinkCustomQueryComponent)。这些链接决定了组件之间的数据流和控制流,确保根据管道的逻辑,一个组件的输出可作为下一个组件的输入。
qp.add_chain(["input", "table_retriever", "table_output_parser"])“输入”,“table_retriever”,“table_output_parser” ])
qp.add_link(“输入”,“text2sql_prompt”,目标键= “query_str”)
qp.add_link(“table_output_parser”,“text2sql_prompt”,目标键= “schema”)
qp.add_chain(
    [ “text2sql_prompt”,“text2sql_llm”,“sql_output_parser”,“sql_retriever” ] 
)
qp.add_link(
    “sql_output_parser”,“response_synthesis_prompt”,目标键= “sql_query”
)
qp.add_link(
    “sql_retriever”,“response_synthesis_prompt”,目标键= “context_str”
)
qp.add_link( “输入”,“response_synthesis_prompt”,目标键= “query_str” ) 
qp.add_link( “response_synthesis_prompt”,“response_synthesis_llm” )

11.管道可视化:

从pyvis.network导入网络

net = 网络(笔记本 = True,cdn_resources = “in_line”,定向 = True)
net.from_nx(qp.dag)
net.show(“text2sql_dag.html”)

img

图片来自作者

12.执行一些查询:

查询:1

response = qp.run( 
    query= “按薪水列出前 10 名员工?”
 ) 
print ( str (response))
> 使用输入运行模块输入:模块输入带有输入:
查询:按薪水列出前10 名员工? > 运行模块table_retriever带有输入:输入:按薪水列出前10 名员工? >使用以下输入运行模块table_output_parser :table_schema_objs: [SQLTableSchema(table_name= 'Employee', context_str='包含员工记录、职位和薪资信息。'), SQLTableSchema(table_name='Customer', context_str='保存客户信息... >使用以下输入运行模块text2sql_prompt :query_str:根据薪资列出前10 名员工?schema:表'Employee' 包含以下列: EmployeeID (INTEGER), FirstName (VARCHAR(100)), LastName (VARCHAR(100)), Email (VARCHAR(255)), Phone (VARCHAR(20)), HireDate (DATE), Position (VARCHAR(100)), Salary (DECI... >使用以下输入运行模块text2sql_llm :messages:给定一个输入问题,首先创建一个语法正确的 mysql 查询来运行,然后查看查询结果并返回答案。您可以按以下方式对结果进行排序:返回相关列... > 使用输入运行模块sql_output_parser :响应:助理:SELECT EmployeeID、FirstName、LastName、Salary FROM Employee ORDER BY Salary DESC LIMIT 10 SQLResult: EmployeeID | FirstName | LastName | Salary 1           | John | Doe | 100000 ... >使用输入运行模块sql_retriever :输入:SELECT EmployeeID、FirstName、LastName、Salary FROM Employee ORDER BY Salary DESC LIMIT 10 >使用输入运行模块response_synthesis_prompt :query_str:按薪水列出前10 名员工?sql_query:SELECT












  


 
 





  



 EmployeeID、FirstName、LastName、Salary FROM Employee ORDER  BY Salary DESC LIMIT 10 
context_str: [NodeWithScore(node=TextNode(id_= '02c6e159-d328-4bab-8911-eef1daf06bb2', embedding=None, metadata={}, excluded_embed_metadata_keys=[], excluded_llm_metadata_keys=[], relationships={}, text="[(959, 'Je...

 > 运行模块response_synthesis_llm并使用输入:
messages:给定一个输入问题,从查询结果中合成一个响应。
查询:按薪水列出前10 名员工?SQL: SELECT EmployeeID, FirstName, LastName, Salary FROM Employee ORDER BY Salary DESC LI... assistant:按薪水排名前10位的员工是:1. Jessica Marsh ,薪水为99美元,846.00 2. Mary Clarke,工资为$ 99,607.00 3. Shelby Cochran,工资为$ 99,463.00 4. Christine Mason,工资为$ 99,100.00 5. Henry Robinson ,工资为$ 99,090.00 6. Donald Morris,工资为$ 99,086.00 7. Ruth White,工资为$ 99,065.00其余员工的详细信息未在查询响应中提供完整信息。
  

查询:2

response = qp.run( 
    query= """计算去年发货的所有订单从下单到发货的平均天数,
并找出平均发货延迟最长的客户?""" ) 
print ( str (response))
> 使用输入运行模块输入:模块输入与输入:
查询:计算去年发货的所有订单下订单和发货之间的平均天数,并确定平均运输延迟最长的客户? >运行模块table_retriever与输入:输入:计算去年发货的所有订单下订单和发货之间的平均天数,并确定平均运输延迟最长的客户? >使用输入运行模块table_output_parser :table_schema_objs: [SQLTableSchema(table_name= 'SalesOrder', context_str='记录客户订单,包括订单日期、发货信息和付款状态。'), SQLTableSchema(table_name='客户', context_str='Ho... >使用输入运行模块text2sql_prompt :query_str:计算去年发货的所有订单下单和发货之间的平均天数,并确定平均发货延迟最长的客户?schema :表' SalesOrder' 包含列: SalesOrderID (INTEGER), CustomerID (INTEGER), OrderDate (DATE),RequiredDate (DATE), ShippedDate (DATE), Status (VARCHAR(50)), Comments (TEXT), PaymentMethod (VARCHAR(5... >使用输入运行模块text2sql_llm :messages:给定一个输入问题,首先创建一个语法正确的 mysql 查询来运行,然后查看查询结果并返回答案。您可以按相关列对结果进行排序以返回... > 使用输入运行模块sql_output_parser:响应:助手:SELECT AVG(DATEDIFF(SalesOrder.ShippedDate, SalesOrder.OrderDate)) AS AverageDays, Customer.FirstName, Customer.LastName FROM SalesOrder JOIN Customer ON















  




SalesOrder.CustomerID = Customer.... 

> 运行模块sql_retriever并输入:
输入: SELECT AVG(DATEDIFF(SalesOrder.ShippedDate, SalesOrder.OrderDate)) AS AverageDays, Customer.FirstName, Customer.LastName 
FROM SalesOrder 
JOIN Customer ON SalesOrder.CustomerID = Customer.CustomerID ... 

> 运行模块response_synthesis_prompt并输入:
query_str:计算去年所有订单下单和发货之间的平均天数,并确定平均运输延迟最长的客户?sql_query:SELECT AVG(DATEDIFF(SalesOrder.ShippedDate, SalesOrder.OrderDate)) AS AverageDays, Customer.FirstName, Customer.LastName FROM SalesOrder JOIN Customer ON SalesOrder.CustomerID = Customer.CustomerID ... context_str: [NodeWithScore(node=TextNode(id_= '1e988d3f-4019-451b-8b84-62144e09d15a', embedding=None, metadata={}, excluded_embed_metadata_keys=[], excluded_llm_metadata_keys=[], relationships={}, text="[(Decimal(... > 运行模块response_synthesis_llm使用输入:消息:给定一个输入问题,从查询结果中合成一个响应。查询:计算去年所有订单下单和发货之间的平均天数,并确定...助理:去年所有订单下单到发货的平均天数为30天。平均发货延迟时间最长的客户是 Jonathan Burke。

 

查询:3

response = qp.run( 
    query= """计算       过去三年内进行过购买的每个客户的终身价值(总销售额)
 ,按最高值排序并显示前 5 名?""" ) 
print ( str (response))
> 运行模块输入:模块输入带有输入:
查询:计算       过去三年内进行过购买的每个客户的 终身价值(总销售额) ,按最高值排序并显示前5 名?> 运行模块table_retriever带有输入:输入:计算       过去三年内进行过购买的每个客户的终身价值(总销售额) ,按最高值排序并显示前5名? >使用输入运行模块table_output_parser :table_schema_objs: [SQLTableSchema(table_name= 'SalesOrder', context_str='记录客户订单,包括订单日期、发货信息和付款状态。'), SQLTableSchema(table_name='客户', context_str='客户... >使用输入运行模块text2sql_prompt :query_str:计算       过去三年内进行过购买的每个客户的终身价值(总销售额) ,按最高值排序并显示前5 名?模式:表“SalesOrder”包含列:SalesOrderID(INTEGER)、CustomerID(INTEGER)、OrderDate(DATE)、RequiredDate(DATE)、ShippedDate(DATE)、Status(VARCHAR(50))、Comments(TEXT)、PaymentMethod(VARCHAR(5... >使用输入运行模块text2sql_llm :消息:给定一个输入问题,首先创建一个语法正确的 mysql 查询来运行,然后查看查询结果并返回答案。您可以按相关列对结果进行排序以返回... > 使用输入运行模块sql_output_parser:响应:助手:SELECT Customer.CustomerID、Customer.FirstName、Customer.LastName、SUM(LineItem.TotalPrice) as LifetimeValue FROM Customer JOIN SalesOrder ON Customer.CustomerID = SalesOrder.CustomerID JOI...



 






 




  







> 运行模块sql_retriever并输入:
输入: SELECT Customer.CustomerID, Customer.FirstName, Customer.LastName, SUM(LineItem.TotalPrice) as LifetimeValue 
FROM Customer 
JOIN SalesOrder ON Customer.CustomerID = SalesOrder.CustomerID 
JOIN LineItem ... 

> 运行模块response_synthesis_prompt并输入:
query_str:计算       过去三年内进行过购买的每个客户的 终身价值(总销售额) ,按最高值排序并显示前5 名?sql_query:SELECT Customer.CustomerID, Customer.FirstName, Customer.LastName, SUM(LineItem.TotalPrice) as LifetimeValue FROM Customer JOIN SalesOrder ON Customer.CustomerID = SalesOrder.CustomerID JOIN LineItem ... context_str: [NodeWithScore(node=TextNode(id_= 'c37b8a16-0132-48d5-9425-5eba1281d7a5', embedding=None, metadata={}, excluded_embed_metadata_keys=[], excluded_llm_metadata_keys=[], relationships={}, text="[(61, 'Bra... > 运行模块response_synthesis_llm使用输入:消息:给定一个输入问题,从查询结果中合成一个响应。查询:计算       过去三年内进行过购买的每个客户的终身价值(总销售额) , s...助理:过去三年内生命周期价值(总销售额)最高的前五名客户如下:1. Bradley Quinn,总销售额为34,389.10美元2. Laura Mueller,总销售额为33,312.42美元3. Michael Jordan ,总销售额为24,295.07美元4. Don Lowery ,总销售额为24,055.13美元5. Jerry Haas ,

 







 







总销售额为23,851.82美元

img

图片来自作者

第 13 部分 - 使用 SQL 数据集微调 LLM:

img

图片来源 Google 博客

请查看 colab 笔记本。我为大多数单元格提供了注释。这只是为了展示如何微调模型。

  • 安装 Gemma 模型、数据处理和微调所需的 Python 库。
  • 通过 Hugging Face 进行身份验证以访问模型和数据集。
  • 加载针对高效推理进行优化的 Gemma 模型。
  • 准备并格式化数据集以进行微调。
  • 配置 LoRA 以进行参数高效的微调。
  • 初始化并配置微调训练器。
  • 执行微调过程。
  • 使用微调模型根据自然语言提示生成 SQL 查询。

请参阅有关微调 gemma 模型的更多信息。

Gemma:推出全新最先进的开放式模型

Gemma 是一个轻量级、最先进的开放式模型系列,采用相同的研究和技术构建而成……

博客网

img

图片来源:pandas 文档

第十四部分:Pandas AI:

img

图片来自作者

查看他们的文档:

PandasAI

PandasAI 是一个 Python 库,它将生成人工智能功能集成到 Pandas 中,使得……

docs.pandas-ai.com

根据他们的文件:

PandasAI 是一个 Python 库,可以很容易地用自然语言向你的数据(CSV、XLSX、PostgreSQL、MySQL、BigQuery、Databrick、Snowflake 等)提问。它可以帮助你使用生成式 AI 探索、清理和分析你的数据。

除了查询之外,PandasAI 还提供通过图形可视化数据、通过解决缺失值清理数据集以及通过特征生成提高数据质量的功能,使其成为数据科学家和分析师的综合工具。

请检查:

谷歌合作实验室

编辑描述

colab.research.google.com

熊猫人工智能:

# 使用 poetry (推荐)
 poetry add pandasai 

# 使用 pip
 pip install pandasai
将pandas导入为pd
从pandasai导入SmartDataframe 

# 示例 DataFrame
 products_data = pd.DataFrame({ 
    "category" : [ "电子产品" , "服装" , "玩具" , "电子产品" , "服装" , "玩具" , "电子产品" , "服装" , "玩具" , "电子产品" ], 
    "product" : [ "笔记本电脑" , "牛仔裤" , "泰迪熊" , "智能手机" , "T 恤" , "拼图" , "平板电脑" , "连衣裙" , "棋盘游戏" , "相机" ], 
    "price" : [ 1200 , 80 , 20 , 800 , 25 , 15 , 500 , 100 , 30 , 450 ], 
    "units_sold" : [ 300 , 1500 , 800 , 500 , 2000 , 1500 , 400 , 1200 , 1000 , 350 ] 
}) 

# 实例化 LLM 
from pandasai.llm import OpenAI 
llm = OpenAI(api_token= "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" ) 

# 转换为 SmartDataframe
 df = SmartDataframe(products_data, config={ "llm" : llm}) 

# 向 LLM 提问
df.chat( '最赚钱的产品类别是什么?' )
# 问题 1:找出每个类别产品的平均价格。
 response = df.chat( '每个类别产品的平均价格是多少?' ) 
print (response)
   类别   价格
0     服装   500.0 
1  电子产品    15.0 
2         玩具  1200.0
# 问题2:确定每个类别产生的总收入。2 :确定每个类别产生的 总收入。response = df.chat( '每个产品类别产生了多少总收入?') print(response)
      类别收入
0     服装   500000 
1  电子产品    12000 
2         玩具   600000
# 问题 3:要求比较两个类别的销售单位。response
 = df.chat( '就销售单位而言,电子产品的销售额与玩具的销售额相比如何?' ) 
print (response)
从销售量来看,电子产品的销量高于玩具。
# 问题 4:查询数据集中最昂贵的产品。
 response = df.chat( '列出的最昂贵的产品是什么?' ) 
print (response)
列出的最昂贵的产品是智能手机。是智能手机。
df.chat('绘制每个产品类别产生的总收入,“绘制每个产品类别产生的总收入,每个类别
使用不同的颜色”) 

img

  • 准备并格式化数据集以进行微调。
  • 配置 LoRA 以进行参数高效的微调。
  • 初始化并配置微调训练器。
  • 执行微调过程。
  • 使用微调模型根据自然语言提示生成 SQL 查询。

请参阅有关微调 gemma 模型的更多信息。

Gemma:推出全新最先进的开放式模型

Gemma 是一个轻量级、最先进的开放式模型系列,采用相同的研究和技术构建而成……

博客网

[外链图片转存中…(img-iUhfXgUB-1722504698678)]

图片来源:pandas 文档

第十四部分:Pandas AI:

[外链图片转存中…(img-4pAqrBEQ-1722504698678)]

图片来自作者

查看他们的文档:

PandasAI

PandasAI 是一个 Python 库,它将生成人工智能功能集成到 Pandas 中,使得……

docs.pandas-ai.com

根据他们的文件:

PandasAI 是一个 Python 库,可以很容易地用自然语言向你的数据(CSV、XLSX、PostgreSQL、MySQL、BigQuery、Databrick、Snowflake 等)提问。它可以帮助你使用生成式 AI 探索、清理和分析你的数据。

除了查询之外,PandasAI 还提供通过图形可视化数据、通过解决缺失值清理数据集以及通过特征生成提高数据质量的功能,使其成为数据科学家和分析师的综合工具。

请检查:

谷歌合作实验室

编辑描述

colab.research.google.com

熊猫人工智能:

# 使用 poetry (推荐)
 poetry add pandasai 

# 使用 pip
 pip install pandasai
将pandas导入为pd
从pandasai导入SmartDataframe 

# 示例 DataFrame
 products_data = pd.DataFrame({ 
    "category" : [ "电子产品" , "服装" , "玩具" , "电子产品" , "服装" , "玩具" , "电子产品" , "服装" , "玩具" , "电子产品" ], 
    "product" : [ "笔记本电脑" , "牛仔裤" , "泰迪熊" , "智能手机" , "T 恤" , "拼图" , "平板电脑" , "连衣裙" , "棋盘游戏" , "相机" ], 
    "price" : [ 1200 , 80 , 20 , 800 , 25 , 15 , 500 , 100 , 30 , 450 ], 
    "units_sold" : [ 300 , 1500 , 800 , 500 , 2000 , 1500 , 400 , 1200 , 1000 , 350 ] 
}) 

# 实例化 LLM 
from pandasai.llm import OpenAI 
llm = OpenAI(api_token= "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" ) 

# 转换为 SmartDataframe
 df = SmartDataframe(products_data, config={ "llm" : llm}) 

# 向 LLM 提问
df.chat( '最赚钱的产品类别是什么?' )
# 问题 1:找出每个类别产品的平均价格。
 response = df.chat( '每个类别产品的平均价格是多少?' ) 
print (response)
   类别   价格
0     服装   500.0 
1  电子产品    15.0 
2         玩具  1200.0
# 问题2:确定每个类别产生的总收入。2 :确定每个类别产生的 总收入。response = df.chat( '每个产品类别产生了多少总收入?') print(response)
      类别收入
0     服装   500000 
1  电子产品    12000 
2         玩具   600000
# 问题 3:要求比较两个类别的销售单位。response
 = df.chat( '就销售单位而言,电子产品的销售额与玩具的销售额相比如何?' ) 
print (response)
从销售量来看,电子产品的销量高于玩具。
# 问题 4:查询数据集中最昂贵的产品。
 response = df.chat( '列出的最昂贵的产品是什么?' ) 
print (response)
列出的最昂贵的产品是智能手机。是智能手机。
df.chat('绘制每个产品类别产生的总收入,“绘制每个产品类别产生的总收入,每个类别
使用不同的颜色”) 

图片来自作者
博客原文:专业人工智能技术社区

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值