PandasAI连接LLM对MySQL数据库进行数据分析

1. 引言

在之前的文章《PandasAI连接LLM进行智能数据分析》中实现了使用PandasAI连接与DeepSeek模型通过自然语言进行数据分析。不过那个例子中使用的是PandasAI 2.X,并且使用的是本地.csv文件来作为数据。在实际应用的系统中,使用.csv作为库表的情况比较少见。在本文中,就试试使用最新的PandasAI 3.0对MySQL数据库中涉及到多个表的数据进行数据分析。

2. 详述

既然要连接MySQL数据库,那么就要先准备数据了。在MySQL创建一个数据库chinese_retail_data,在数据库中创建两张表customers和orders,并且插入数据。这里模拟的是电商系统重点用户表和订单表。具体的SQL语句如下所示:

sql 复制代码
-- 创建数据库
CREATE DATABASE IF NOT EXISTS chinese_retail_data;
USE chinese_retail_data;

-- 创建客户表 (主表)
CREATE TABLE customers (
    customer_id INT PRIMARY KEY AUTO_INCREMENT,
    customer_name VARCHAR(100) NOT NULL,
    gender VARCHAR(10) NOT NULL,
    age_group VARCHAR(20) NOT NULL,
    city VARCHAR(50) NOT NULL,
    membership_level VARCHAR(20) DEFAULT '普通会员',
    registration_date DATE NOT NULL
);

-- 创建订单表 (从表,通过customer_id关联)
CREATE TABLE orders (
    order_id INT PRIMARY KEY AUTO_INCREMENT,
    customer_id INT,
    product_name VARCHAR(100) NOT NULL,
    category VARCHAR(50) NOT NULL,
    quantity INT NOT NULL,
    unit_price DECIMAL(10,2) NOT NULL,
    order_date DATE NOT NULL,
    payment_method VARCHAR(20) NOT NULL,
    delivery_status VARCHAR(20) NOT NULL,
    FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);

-- 插入客户数据(字段值使用中文)
INSERT INTO customers (customer_name, gender, age_group, city, membership_level, registration_date) VALUES
('张伟', '男', '25-34岁', '北京', '黄金会员', '2023-01-15'),
('李娜', '女', '35-44岁', '上海', '铂金会员', '2022-03-20'),
('王强', '男', '18-24岁', '广州', '普通会员', '2024-01-05'),
('陈静', '女', '45-54岁', '深圳', '黄金会员', '2023-06-12'),
('刘洋', '男', '25-34岁', '杭州', '普通会员', '2024-02-18'),
('赵敏', '女', '35-44岁', '成都', '铂金会员', '2022-11-30'),
('孙浩', '男', '18-24岁', '南京', '普通会员', '2024-03-08'),
('周芳', '女', '45-54岁', '武汉', '黄金会员', '2023-09-25');

-- 插入订单数据(字段值使用中文,关联customer_id)
INSERT INTO orders (customer_id, product_name, category, quantity, unit_price, order_date, payment_method, delivery_status) VALUES
(1, '华为手机', '电子产品', 1, 5999.00, '2024-04-01', '支付宝', '已送达'),
(2, '美的空调', '家用电器', 1, 3200.00, '2024-04-03', '微信支付', '已送达'),
(3, '李宁运动鞋', '服饰鞋帽', 2, 499.00, '2024-04-05', '信用卡', '运输中'),
(1, '小米手环', '电子产品', 1, 299.00, '2024-04-08', '支付宝', '已送达'),
(4, '格力冰箱', '家用电器', 1, 4800.00, '2024-04-10', '微信支付', '已送达'),
(5, '耐克T恤', '服饰鞋帽', 3, 199.00, '2024-04-12', '支付宝', '已送达'),
(2, '苹果平板', '电子产品', 1, 3899.00, '2024-04-15', '微信支付', '已送达'),
(6, '海尔洗衣机', '家用电器', 1, 2800.00, '2024-04-18', '信用卡', '已送达'),
(7, '阿迪达斯运动裤', '服饰鞋帽', 1, 599.00, '2024-04-20', '支付宝', '运输中'),
(1, '戴尔笔记本', '电子产品', 1, 7999.00, '2024-04-25', '微信支付', '已送达'),
(8, '西门子烤箱', '家用电器', 1, 2200.00, '2024-04-28', '信用卡', '已送达'),
(3, '优衣库衬衫', '服饰鞋帽', 4, 199.00, '2024-05-01', '支付宝', '已送达'),
(4, 'OPPO手机', '电子产品', 1, 2999.00, '2024-05-05', '微信支付', '已送达'),
(5, '彪马运动鞋', '服饰鞋帽', 1, 699.00, '2024-05-08', '信用卡', '运输中'),
(2, '索尼耳机', '电子产品', 2, 899.00, '2024-05-12', '支付宝', '已送达');

然后准备PandasAI的环境。注意默认的Python环境pip安装的可能仍然是2.X版本,不过在使用PandasAI官方文档推荐使用Poetry之后,就可以pip安装3.0了。

最后给出具体的Python脚本:

python 复制代码
import pandasai
from pandasai_litellm import LiteLLM

llm_url = "https://dashscope.aliyuncs.com/compatible-mode/v1"
llm_key = "sk-xxxxx"
llm_model_name = "deepseek-r1"

mysql_host = "127.0.0.1"
mysql_port = 3306
mysql_user = "root"
mysql_password = "test"

def init_dataset(table_names):
    pandasai.create(
        path = table_names[0],
        description = "电商系统客户的基本信息,包括个人属性、地理位置和会员等级等静态特征。",
        source={
            "type": "mysql",
            "connection": {
                "host": mysql_host,
                "port": mysql_port,
                "user": mysql_user,           
                "password": mysql_password,
                "database": "chinese_retail_data"
            },
            "table": "customers",            
        },
        columns = [
            {"name": "customer_id", "type": "integer", "description": "客户的唯一标识符,用于关联订单数据。"},
            {"name": "customer_name", "type": "string", "description": "客户的姓名,用于识别和沟通。"},
            {"name": "gender", "type": "string", "description": "客户的性别,用于人口统计分析。"},
            {"name": "age_group", "type": "string", "description": "客户所属的年龄段,用于年龄相关的市场细分。"},
            {"name": "city", "type": "string", "description": "户所在的城市,用于地域性销售分析。"},
            {"name": "membership_level", "type": "string", "description": "客户的会员等级,反映客户价值和忠诚度。"},
            {"name": "registration_date", "type": "datetime", "description": "客户的注册日期,用于计算客户生命周期。"},
        ]
    )

    pandasai.create(
        path = table_names[1],
        description = "电商系统客户的订单交易详情,包括购买的商品、数量、价格、时间和状态等动态行为。",
        source={
            "type": "mysql",
            "connection": {
                "host": mysql_host,
                "port": mysql_port,
                "user": mysql_user,
                "password": mysql_password,
                "database": "chinese_retail_data"
            },
            "table": "orders",
        },
        columns = [
            {"name": "order_id", "type": "integer", "description": "订单的唯一标识符,用于追踪和管理订单。"},
            {"name": "customer_id", "type": "integer", "description": "关联到客户的外键,建立与客户表的联系。"},
            {"name": "product_name", "type": "string", "description": "所购商品的名称,用于产品销售分析。"},
            {"name": "category", "type": "string", "description": "商品所属的类别,用于分类统计和趋势分析。"},
            {"name": "quantity", "type": "integer", "description": "购买的商品数量,影响总销售额和库存。"},
            {"name": "unit_price", "type": "float", "description": "商品的单价,用于计算订单金额和利润。"},
            {"name": "order_date", "type": "datetime", "description": "订单创建的日期,用于时间序列和趋势分析。"},
            {"name": "payment_method", "type": "string", "description": "客户使用的支付方式,反映支付偏好。"},
            {"name": "delivery_status", "type": "string", "description": "订单的配送状态,用于监控物流和客户满意度。"},
        ]
    )

def ai_chat(table_names):
    llm = LiteLLM(model=llm_model_name, api_base=llm_url, api_key=llm_key, custom_llm_provider="openai", temperature=0.0, seed=10080)

    pandasai.config.set({"llm": llm, "save_logs": True, "verbose": False, "max_retries": 3})

    # 加载所有相关的表   
    tables = [pandasai.load(name) for name in table_names]

    chat_content = "统计一下目前电商系统中会员类型的占比,以及每种会员类型购买商品的数额在销售额总量的占比。请使用中文回答。"

    result = pandasai.chat(chat_content, *tables)

    print(result)

if __name__ == "__main__":    
    table_names = ["example/ecommerce-customers", "example/ecommerce-orders"]

    #init_dataset(table_names) #初始化只能一次

    ai_chat(table_names)

imglink1\]: 有以下几点需要注意: 1. PandasAI 3.0比PandasAI 2.X方便的一点可以不用自定义`LLM`类来连接自定义的大模型了,使用内置的`LiteLLM`就可以了。另外PandasAI官方还提供大模型可以使用,不过需要申请key。这里笔者连接的还是阿里云百炼平台的DeepSeek。 2. PandasAI设计的数据接口笔者觉得有点奇怪,主要有两点: * `pandasai.create`创建的表格数据只能使用一次,如果数据存在第二次再调用这个函数(在`init_dataset`函数中)就会报错。 * PandasAI对创建的数据集名称还有要求,比如多个单词必须以"-"进行连接。 3. PandasAI官网创建MySQL数据集的案例代码^[\[1\]](#[1])^是: ```python sql_table = pai.create( path="example/mysql-dataset", description="Heart disease dataset from MySQL database", source={ "type": "mysql", "connection": { "host": "database.example.com", "port": 3306, "user": "${DB_USER}", "password": "${DB_PASSWORD}", "database": "medical_data" }, "table": "heart_data", "columns": [ {"name": "Age", "type": "integer", "description": "Age of the patient in years"}, {"name": "Sex", "type": "string", "description": "Gender of the patient (M = male, F = female)"}, {"name": "ChestPainType", "type": "string", "description": "Type of chest pain (ATA, NAP, ASY, TA)"}, {"name": "RestingBP", "type": "integer", "description": "Resting blood pressure in mm Hg"}, {"name": "Cholesterol", "type": "integer", "description": "Serum cholesterol in mg/dl"}, {"name": "FastingBS", "type": "integer", "description": "Fasting blood sugar > 120 mg/dl (1 = true, 0 = false)"}, {"name": "RestingECG", "type": "string", "description": "Resting electrocardiogram results (Normal, ST, LVH)"}, {"name": "MaxHR", "type": "integer", "description": "Maximum heart rate achieved"}, {"name": "ExerciseAngina", "type": "string", "description": "Exercise-induced angina (Y = yes, N = no)"}, {"name": "Oldpeak", "type": "float", "description": "ST depression induced by exercise relative to rest"}, {"name": "ST_Slope", "type": "string", "description": "Slope of the peak exercise ST segment (Up, Flat, Down)"}, {"name": "HeartDisease", "type": "integer", "description": "Heart disease diagnosis (1 = present, 0 = absent)"} ] } ) ``` 但是笔者这里尝试的正确的用法是: ```cpp pandasai.create( path = table_names[0], description = "电商系统客户的基本信息,包括个人属性、地理位置和会员等级等静态特征。", source={ "type": "mysql", "connection": { "host": mysql_host, "port": mysql_port, "user": mysql_user, "password": mysql_password, "database": "chinese_retail_data" }, "table": "customers", }, columns = [ {"name": "customer_id", "type": "integer", "description": "客户的唯一标识符,用于关联订单数据。"}, {"name": "customer_name", "type": "string", "description": "客户的姓名,用于识别和沟通。"}, {"name": "gender", "type": "string", "description": "客户的性别,用于人口统计分析。"}, {"name": "age_group", "type": "string", "description": "客户所属的年龄段,用于年龄相关的市场细分。"}, {"name": "city", "type": "string", "description": "户所在的城市,用于地域性销售分析。"}, {"name": "membership_level", "type": "string", "description": "客户的会员等级,反映客户价值和忠诚度。"}, {"name": "registration_date", "type": "datetime", "description": "客户的注册日期,用于计算客户生命周期。"}, ] ) ``` 关键不同点就在于columns属性值的位置。使用前者实际上是会丢失表格字段描述的。表格字段描述非常重要,PandasAI会将其传递给LLM来理解表格数据。如果创建成功的话,可以在Python脚本所在目录的datasets文件夹中,找到创建好的.yaml文件,其中有表格数据的字段表述值: # 3. 结果 最终运行结果如下所示: ```bash membership_level 会员占比(%) 销售额占比(%) 0 普通会员 37.5 9.30 1 铂金会员 25.0 29.48 2 黄金会员 37.5 61.23 ``` 本例中还有一点值得注意的是这里进行的数据分析是跨表数据分析,而不是像[《PandasAI连接LLM进行智能数据分析》](https://charlee44.com/post.html?id=3c460752261142b9885c40fada237dc7)中那样使用的是单表。其实这就是个很有趣的问题,我们都知道业务系统的核心就是CURD,那么如果跨表查询可以实现,是不是意味着以后就可以通过自然语言来进行业务呢?现在语音的正确识别率也不低,通过语言来进行业务操作也不难吧?这就回到了笔者在之前的文章[《行业思考:不是前端不行,是只会前端不行》](https://charlee44.com/post.html?id=95575bda5ab54e10bcc208a000395f12)中的讨论:也许AI可能会对传统Web前端方向带来革命性的影响。 *** ** * ** *** 1. [PandasAI官方文档](https://docs.pandas-ai.com/v3/data-ingestion) [↩︎](#↩︎)

相关推荐
hqxstudying22 分钟前
MyBatis 和 MyBatis-Plus对比
java·数据库·mysql·mybatis
数据智能老司机23 分钟前
Snowflake 快速入门——使用 Snowpipe 与动态表实现持续数据加载
大数据·数据分析·saas
数据智能老司机24 分钟前
面向网络安全的数据工程——数据工程基础
安全·架构·数据分析
数据智能老司机28 分钟前
Snowflake 快速入门——Snowflake 管理与 RBAC
大数据·数据分析·saas
数据智能老司机29 分钟前
Snowflake 快速入门——快速上手云分析
大数据·数据分析·saas
好奇的菜鸟1 小时前
使用 Apache Flink CDC 3.0 实现 MySQL 到 Elasticsearch 的数据同步
mysql·flink·apache
DemonAvenger2 小时前
高效JOIN操作:多表关联查询技巧与实战经验分享
数据库·mysql·性能优化
、水水水水水3 小时前
RAG学习(五)——查询构建、Text2SQL、查询重构与分发
人工智能·python·深度学习·nlp
浩瀚蓝天dep12 小时前
使用Ollama部署自己的本地模型
ai大模型·ollama·deepseek
计算机编程小咖12 小时前
《基于大数据的农产品交易数据分析与可视化系统》选题不当,毕业答辩可能直接挂科
java·大数据·hadoop·python·数据挖掘·数据分析·spark