在之前的文章里(点击跳转),我们讲了输入针对本地MySQL的相关问题,通过OpenAI分析,返回我们想要的结果。
比如输入的是
student_info中name是d的,score是多少
返回的是:
The score for the student with the name “d” is 92
但是有人担心这个会泄露数据,仍然偏向使用SQL语句来实现查询。
这一节内容,就来讲一下,我们输入需求描述,直接返回SQL语句。
1 创建测试表并写入数据
创建一张商品销售表,并写入一些商品的销售信息。
use martin;
CREATE TABLE product_sales (
id int auto_increment PRIMARY KEY comment '主键',
product_name varchar(255) comment '商品名',
price DECIMAL(10,2) comment '商品单价',
quantity int comment '销售量',
sale_date date comment '销售日期',
key idx_product_name(product_name)
);
INSERT INTO product_sales (product_name, price, quantity, sale_date)
VALUES
('iPhone 12', 8999, 10, '2023-04-21'),
('iPad Pro', 7999, 5, '2023-04-21'),
('MacBook Pro', 14999, 3, '2023-04-22'),
('AirPods Pro', 2199, 20, '2023-04-22'),
('Apple Watch Series 7', 3299, 8, '2023-04-22'),
('iPhone 11', 5999, 15, '2023-04-23'),
('iPad Air', 4699, 7, '2023-04-23'),
('MacBook Air', 9999, 4, '2023-04-24'),
('AirPods 2', 1299, 25, '2023-04-24'),
('Apple Watch SE', 2599, 12, '2023-04-25');
2 编写代码
设置环境变量 OPENAI_API_KEY,openai的 aip key 获取方法可点击跳转:
代码如下:
from langchain import OpenAI, SQLDatabase, SQLDatabaseChain
db = SQLDatabase.from_uri("mysql+pymysql://martin:uqatcdaT12@127.0.0.1/martin")
llm = OpenAI(temperature=0)
db_chain = SQLDatabaseChain(llm=llm, database=db, verbose=True)
db_chain.run("2023年4月21日全天的销售额")
3 测试
运行上面的代码,结果如下:
输入的是:
2023年4月21日全天的销售额
生成的SQL是:
SELECT SUM(price * quantity) AS total_sales FROM product_sales WHERE sale_date = '2023-04-21'
SQL和结果没问题。
4 生成更复杂的SQL
再来测试生成更为复杂的SQL场景
查询每个产品的销售额占比和销售量占比,按照销售额占比从高到低排列
生成的SQL语句如下:
SELECT product_name, (price * quantity) (SELECT SUM(price * quantity) FROM product_sales) AS sales_ratio, quantity (SELECT SUM(quantity) FROM product_sales) AS quantity_ratio FROM product_sales ORDER BY sales_ratio DESC LIMIT 5;
SQL和结果也没问题,唯一的问题就是加了limit 5,不过我们在实际使用的时候注意就行。
找出所有销售日期中,哪些日期的销售总额超过了平均销售总额
生成的SQL语句如下:
SELECT sale_date, SUM(price * quantity) AS total_sales FROM product_sales GROUP BY sale_date HAVING total_sales > (SELECT AVG(total_sales) FROM (SELECT SUM(price * quantity) AS total_sales FROM product_sales GROUP BY sale_date) AS avg_sales) LIMIT 5;
除了私自加limit 5,SQL和结果都没问题。
5 做成一个页面
既然效果还可以,那做个页面出来岂不是更方便,那就继续。
import gradio as gr
from langchain import OpenAI, SQLDatabase, SQLDatabaseChain
db = SQLDatabase.from_uri("mysql+pymysql://martin:uqatcdaT12@127.0.0.1/martin")
llm = OpenAI(temperature=0)
db_chain = SQLDatabaseChain(llm=llm, database=db, verbose=True, return_intermediate_steps=True)
def generate_and_execute_sql(query):
result = db_chain(query)
return result["intermediate_steps"][0],result['result']
input_text = gr.inputs.Textbox(lines=5,label="请输入查询描述")
output_text_1 = gr.outputs.Textbox(label="生成的SQL语句")
output_text_2 = gr.outputs.Textbox(label="结果")
gr.Interface(fn=generate_and_execute_sql, inputs=input_text, outputs=[output_text_1,output_text_2], title="生成SQL语句并执行查询").launch()
下图是测试结果,左边是输入的需求,右边是生成的SQL以及结果
6 实战应用的一些思考
类似这篇文章的方式,如果要用在实际应用,可以将代码连到测试环境,测试环境表结构和生产环境一样,数据完全是自己造的,在测试环境生产SQL,再去生产环境查询,这样就可以避免数据泄露了。
最后介绍一下我们的AI星球:
星球目前已经有30多篇高质量的内容,其中包括分析使用AI工具能做MySQL的哪些事情,比如我们创建了专栏《ChatGPT和MySQL结合》,专栏还在持续更新中。
当然星球还包括其他AI内容,比如AI画图、个人或者企业怎么基于ChatGPT的API开发应用。以及围绕AI工具有哪些副业或者创业的思路。
因为价格已经非常便宜了,五一之后会进行第一次涨价。
之前在推广的时候,有朋友说我们是割韭菜,其实朋友们可以先进星球看一下,看一下我们写的内容是否适合你,如果觉得不满意,星球支持三天内全额退款的,你也不会有任何损失。
再送一张28元的优惠券,券后40元年费(相当于每天0.1096元),限量20张,先到先得。