找回密码
 立即注册
首页 业界区 业界 PandasAI连接LLM对MySQL数据库进行数据分析

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

汤流婉 昨天 21:07
1. 引言

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

既然要连接MySQL数据库,那么就要先准备数据了。在MySQL创建一个数据库chinese_retail_data,在数据库中创建两张表customers和orders,并且插入数据。这里模拟的是电商系统重点用户表和订单表。具体的SQL语句如下所示:
  1. -- 创建数据库
  2. CREATE DATABASE IF NOT EXISTS chinese_retail_data;
  3. USE chinese_retail_data;
  4. -- 创建客户表 (主表)
  5. CREATE TABLE customers (
  6.     customer_id INT PRIMARY KEY AUTO_INCREMENT,
  7.     customer_name VARCHAR(100) NOT NULL,
  8.     gender VARCHAR(10) NOT NULL,
  9.     age_group VARCHAR(20) NOT NULL,
  10.     city VARCHAR(50) NOT NULL,
  11.     membership_level VARCHAR(20) DEFAULT '普通会员',
  12.     registration_date DATE NOT NULL
  13. );
  14. -- 创建订单表 (从表,通过customer_id关联)
  15. CREATE TABLE orders (
  16.     order_id INT PRIMARY KEY AUTO_INCREMENT,
  17.     customer_id INT,
  18.     product_name VARCHAR(100) NOT NULL,
  19.     category VARCHAR(50) NOT NULL,
  20.     quantity INT NOT NULL,
  21.     unit_price DECIMAL(10,2) NOT NULL,
  22.     order_date DATE NOT NULL,
  23.     payment_method VARCHAR(20) NOT NULL,
  24.     delivery_status VARCHAR(20) NOT NULL,
  25.     FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
  26. );
  27. -- 插入客户数据(字段值使用中文)
  28. INSERT INTO customers (customer_name, gender, age_group, city, membership_level, registration_date) VALUES
  29. ('张伟', '男', '25-34岁', '北京', '黄金会员', '2023-01-15'),
  30. ('李娜', '女', '35-44岁', '上海', '铂金会员', '2022-03-20'),
  31. ('王强', '男', '18-24岁', '广州', '普通会员', '2024-01-05'),
  32. ('陈静', '女', '45-54岁', '深圳', '黄金会员', '2023-06-12'),
  33. ('刘洋', '男', '25-34岁', '杭州', '普通会员', '2024-02-18'),
  34. ('赵敏', '女', '35-44岁', '成都', '铂金会员', '2022-11-30'),
  35. ('孙浩', '男', '18-24岁', '南京', '普通会员', '2024-03-08'),
  36. ('周芳', '女', '45-54岁', '武汉', '黄金会员', '2023-09-25');
  37. -- 插入订单数据(字段值使用中文,关联customer_id)
  38. INSERT INTO orders (customer_id, product_name, category, quantity, unit_price, order_date, payment_method, delivery_status) VALUES
  39. (1, '华为手机', '电子产品', 1, 5999.00, '2024-04-01', '支付宝', '已送达'),
  40. (2, '美的空调', '家用电器', 1, 3200.00, '2024-04-03', '微信支付', '已送达'),
  41. (3, '李宁运动鞋', '服饰鞋帽', 2, 499.00, '2024-04-05', '信用卡', '运输中'),
  42. (1, '小米手环', '电子产品', 1, 299.00, '2024-04-08', '支付宝', '已送达'),
  43. (4, '格力冰箱', '家用电器', 1, 4800.00, '2024-04-10', '微信支付', '已送达'),
  44. (5, '耐克T恤', '服饰鞋帽', 3, 199.00, '2024-04-12', '支付宝', '已送达'),
  45. (2, '苹果平板', '电子产品', 1, 3899.00, '2024-04-15', '微信支付', '已送达'),
  46. (6, '海尔洗衣机', '家用电器', 1, 2800.00, '2024-04-18', '信用卡', '已送达'),
  47. (7, '阿迪达斯运动裤', '服饰鞋帽', 1, 599.00, '2024-04-20', '支付宝', '运输中'),
  48. (1, '戴尔笔记本', '电子产品', 1, 7999.00, '2024-04-25', '微信支付', '已送达'),
  49. (8, '西门子烤箱', '家用电器', 1, 2200.00, '2024-04-28', '信用卡', '已送达'),
  50. (3, '优衣库衬衫', '服饰鞋帽', 4, 199.00, '2024-05-01', '支付宝', '已送达'),
  51. (4, 'OPPO手机', '电子产品', 1, 2999.00, '2024-05-05', '微信支付', '已送达'),
  52. (5, '彪马运动鞋', '服饰鞋帽', 1, 699.00, '2024-05-08', '信用卡', '运输中'),
  53. (2, '索尼耳机', '电子产品', 2, 899.00, '2024-05-12', '支付宝', '已送达');
复制代码
然后准备PandasAI的环境。注意默认的Python环境pip安装的可能仍然是2.X版本,不过在使用PandasAI官方文档推荐使用Poetry之后,就可以pip安装3.0了。
最后给出具体的Python脚本:
  1. import pandasai
  2. from pandasai_litellm import LiteLLM
  3. llm_url = "https://dashscope.aliyuncs.com/compatible-mode/v1"
  4. llm_key = "sk-xxxxx"
  5. llm_model_name = "deepseek-r1"
  6. mysql_host = "127.0.0.1"
  7. mysql_port = 3306
  8. mysql_user = "root"
  9. mysql_password = "test"
  10. def init_dataset(table_names):
  11.     pandasai.create(
  12.         path = table_names[0],
  13.         description = "电商系统客户的基本信息,包括个人属性、地理位置和会员等级等静态特征。",
  14.         source={
  15.             "type": "mysql",
  16.             "connection": {
  17.                 "host": mysql_host,
  18.                 "port": mysql_port,
  19.                 "user": mysql_user,           
  20.                 "password": mysql_password,
  21.                 "database": "chinese_retail_data"
  22.             },
  23.             "table": "customers",            
  24.         },
  25.         columns = [
  26.             {"name": "customer_id", "type": "integer", "description": "客户的唯一标识符,用于关联订单数据。"},
  27.             {"name": "customer_name", "type": "string", "description": "客户的姓名,用于识别和沟通。"},
  28.             {"name": "gender", "type": "string", "description": "客户的性别,用于人口统计分析。"},
  29.             {"name": "age_group", "type": "string", "description": "客户所属的年龄段,用于年龄相关的市场细分。"},
  30.             {"name": "city", "type": "string", "description": "户所在的城市,用于地域性销售分析。"},
  31.             {"name": "membership_level", "type": "string", "description": "客户的会员等级,反映客户价值和忠诚度。"},
  32.             {"name": "registration_date", "type": "datetime", "description": "客户的注册日期,用于计算客户生命周期。"},
  33.         ]
  34.     )
  35.     pandasai.create(
  36.         path = table_names[1],
  37.         description = "电商系统客户的订单交易详情,包括购买的商品、数量、价格、时间和状态等动态行为。",
  38.         source={
  39.             "type": "mysql",
  40.             "connection": {
  41.                 "host": mysql_host,
  42.                 "port": mysql_port,
  43.                 "user": mysql_user,
  44.                 "password": mysql_password,
  45.                 "database": "chinese_retail_data"
  46.             },
  47.             "table": "orders",
  48.         },
  49.         columns = [
  50.             {"name": "order_id", "type": "integer", "description": "订单的唯一标识符,用于追踪和管理订单。"},
  51.             {"name": "customer_id", "type": "integer", "description": "关联到客户的外键,建立与客户表的联系。"},
  52.             {"name": "product_name", "type": "string", "description": "所购商品的名称,用于产品销售分析。"},
  53.             {"name": "category", "type": "string", "description": "商品所属的类别,用于分类统计和趋势分析。"},
  54.             {"name": "quantity", "type": "integer", "description": "购买的商品数量,影响总销售额和库存。"},
  55.             {"name": "unit_price", "type": "float", "description": "商品的单价,用于计算订单金额和利润。"},
  56.             {"name": "order_date", "type": "datetime", "description": "订单创建的日期,用于时间序列和趋势分析。"},
  57.             {"name": "payment_method", "type": "string", "description": "客户使用的支付方式,反映支付偏好。"},
  58.             {"name": "delivery_status", "type": "string", "description": "订单的配送状态,用于监控物流和客户满意度。"},
  59.         ]
  60.     )
  61. def ai_chat(table_names):
  62.     llm = LiteLLM(model=llm_model_name, api_base=llm_url, api_key=llm_key, custom_llm_provider="openai", temperature=0.0, seed=10080)
  63.     pandasai.config.set({"llm": llm, "save_logs": True, "verbose": False, "max_retries": 3})
  64.     # 加载所有相关的表   
  65.     tables = [pandasai.load(name) for name in table_names]
  66.     chat_content = "统计一下目前电商系统中会员类型的占比,以及每种会员类型购买商品的数额在销售额总量的占比。请使用中文回答。"
  67.     result = pandasai.chat(chat_content, *tables)
  68.     print(result)
  69. if __name__ == "__main__":   
  70.     table_names = ["example/ecommerce-customers", "example/ecommerce-orders"]
  71.     #init_dataset(table_names) #初始化只能一次
  72.     ai_chat(table_names)
复制代码
有以下几点需要注意:

  • PandasAI 3.0比PandasAI 2.X方便的一点可以不用自定义LLM类来连接自定义的大模型了,使用内置的LiteLLM就可以了。另外PandasAI官方还提供大模型可以使用,不过需要申请key。这里笔者连接的还是阿里云百炼平台的DeepSeek。
  • PandasAI设计的数据接口笔者觉得有点奇怪,主要有两点:

    • pandasai.create创建的表格数据只能使用一次,如果数据存在第二次再调用这个函数(在init_dataset函数中)就会报错。
    • PandasAI对创建的数据集名称还有要求,比如多个单词必须以"-"进行连接。

  • PandasAI官网创建MySQL数据集的案例代码[1]是:
    1. sql_table = pai.create(
    2.     path="example/mysql-dataset",
    3.     description="Heart disease dataset from MySQL database",
    4.     source={
    5.         "type": "mysql",
    6.         "connection": {
    7.             "host": "database.example.com",
    8.             "port": 3306,
    9.             "user": "${DB_USER}",
    10.             "password": "${DB_PASSWORD}",
    11.             "database": "medical_data"
    12.         },
    13.         "table": "heart_data",
    14.         "columns": [
    15.             {"name": "Age", "type": "integer", "description": "Age of the patient in years"},
    16.             {"name": "Sex", "type": "string", "description": "Gender of the patient (M = male, F = female)"},
    17.             {"name": "ChestPainType", "type": "string", "description": "Type of chest pain (ATA, NAP, ASY, TA)"},
    18.             {"name": "RestingBP", "type": "integer", "description": "Resting blood pressure in mm Hg"},
    19.             {"name": "Cholesterol", "type": "integer", "description": "Serum cholesterol in mg/dl"},
    20.             {"name": "FastingBS", "type": "integer", "description": "Fasting blood sugar > 120 mg/dl (1 = true, 0 = false)"},
    21.             {"name": "RestingECG", "type": "string", "description": "Resting electrocardiogram results (Normal, ST, LVH)"},
    22.             {"name": "MaxHR", "type": "integer", "description": "Maximum heart rate achieved"},
    23.             {"name": "ExerciseAngina", "type": "string", "description": "Exercise-induced angina (Y = yes, N = no)"},
    24.             {"name": "Oldpeak", "type": "float", "description": "ST depression induced by exercise relative to rest"},
    25.             {"name": "ST_Slope", "type": "string", "description": "Slope of the peak exercise ST segment (Up, Flat, Down)"},
    26.             {"name": "HeartDisease", "type": "integer", "description": "Heart disease diagnosis (1 = present, 0 = absent)"}
    27.         ]
    28.     }
    29. )
    复制代码
    但是笔者这里尝试的正确的用法是:
    1. pandasai.create(
    2.     path = table_names[0],
    3.     description = "电商系统客户的基本信息,包括个人属性、地理位置和会员等级等静态特征。",
    4.     source={
    5.         "type": "mysql",
    6.         "connection": {
    7.             "host": mysql_host,
    8.             "port": mysql_port,
    9.             "user": mysql_user,           
    10.             "password": mysql_password,
    11.             "database": "chinese_retail_data"
    12.         },
    13.         "table": "customers",            
    14.     },
    15.     columns = [
    16.         {"name": "customer_id", "type": "integer", "description": "客户的唯一标识符,用于关联订单数据。"},
    17.         {"name": "customer_name", "type": "string", "description": "客户的姓名,用于识别和沟通。"},
    18.         {"name": "gender", "type": "string", "description": "客户的性别,用于人口统计分析。"},
    19.         {"name": "age_group", "type": "string", "description": "客户所属的年龄段,用于年龄相关的市场细分。"},
    20.         {"name": "city", "type": "string", "description": "户所在的城市,用于地域性销售分析。"},
    21.         {"name": "membership_level", "type": "string", "description": "客户的会员等级,反映客户价值和忠诚度。"},
    22.         {"name": "registration_date", "type": "datetime", "description": "客户的注册日期,用于计算客户生命周期。"},
    23.     ]
    24. )
    复制代码
    关键不同点就在于columns属性值的位置。使用前者实际上是会丢失表格字段描述的。表格字段描述非常重要,PandasAI会将其传递给LLM来理解表格数据。如果创建成功的话,可以在Python脚本所在目录的datasets文件夹中,找到创建好的.yaml文件,其中有表格数据的字段表述值:
    1.png

3. 结果

最终运行结果如下所示:
  1. membership_level  会员占比(%)  销售额占比(%)
  2. 0             普通会员     37.5      9.30
  3. 1             铂金会员     25.0     29.48
  4. 2             黄金会员     37.5     61.23
复制代码
本例中还有一点值得注意的是这里进行的数据分析是跨表数据分析,而不是像《PandasAI连接LLM进行智能数据分析》中那样使用的是单表。其实这就是个很有趣的问题,我们都知道业务系统的核心就是CURD,那么如果跨表查询可以实现,是不是意味着以后就可以通过自然语言来进行业务呢?现在语音的正确识别率也不低,通过语言来进行业务操作也不难吧?这就回到了笔者在之前的文章《行业思考:不是前端不行,是只会前端不行》中的讨论:也许AI可能会对传统Web前端方向带来革命性的影响。


  • PandasAI官方文档 ↩︎

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册