第69篇:AI大模型辅助的数据分析应用开发

——零代码自动生成销售洞察报告,10秒搞定你半天的工作

本文包含完整实战代码和运行截图


在这里插入图片描述

1. 引言:大模型如何让数据分析“开挂”

📊 场景故事
小李是某电商公司的运营专员,每周一都要从后台导出上周的销售数据(CSV格式),手动用 Excel 做透视表、画趋势图、写分析小结,再发给老板。
——平均耗时3小时,还经常被老板说“洞察不够深入”。

💡 转折点
上周,他试用了我们刚开发的“大模型销售分析师”工具:上传CSV → 点击运行 → 10秒后自动生成图文并茂的PDF报告,包含趋势总结、异常预警、图表解读。
老板回复:“这才是我要的洞察!”

⚖️ 关键价值

  • 零代码生成洞察:不懂Python也能用,运营、市场、产品都能上手。
  • 提升决策速度:从小时级压缩到秒级,抓住数据黄金时间。
  • 澄清误区:大模型 ≠ 替代 pandas!它不处理原始数据清洗,而是帮你“说人话”解释结果。

🎁 本篇成果预告
你将亲手完成一个 Jupyter Notebook 工具(data_analyzer.ipynb),支持上传任意销售CSV,自动生成带图表+文字洞察的完整报告。
👇 下图是生成的报告样例(PDF截图):

在这里插入图片描述
在这里插入图片描述

▲ 自动生成的销售洞察报告,含趋势图+3点业务建议


2. 核心概念:人机协作分析框架

我们不追求“全自动”,而是构建 “人类指挥 + 大模型执行” 的高效协作模式:

🔄 角色分工图
在这里插入图片描述

▲ 人类负责:数据清洗、提示词设计;大模型负责:文字洞察、图表描述

🧠 提示工程技巧
大模型不是神,输入垃圾,输出也是垃圾。结构化提示模板是成败关键:

你是一名资深电商数据分析师,请基于以下销售数据摘要,用3点总结核心趋势:
{summary_stats}

要求:
1. 使用中文,避免专业术语(如“同比”“环比”请用“比上月增长”)
2. 指出1个潜在风险或异常点
3. 给出1条可执行建议(如“建议增加某品类库存”)

🔐 数据安全第一
大模型API可能记录请求日志,绝不能发送原始行数据!必须脱敏:

# 示例:隐藏客户姓名、手机号
df['customer_name'] = df['customer_name'].mask(df['customer_name'].notna(), '***')
df['phone'] = df['phone'].mask(df['phone'].notna(), '***')
# 只发送聚合统计量给大模型
sales_summary = df['revenue'].describe().to_dict()

3. 实战步骤:开发你的“销售数据分析师”

3.1 环境搭建

📦 安装依赖(推荐Python 3.9+):

pip install pandas>=1.5 matplotlib openai nbformat

✅ 验证安装:

▲ 成功导入库,无报错即准备就绪


3.2 代码实现:核心Notebook (data_analyzer.ipynb)

📥 输入数据示例(CSV前5行):
在这里插入图片描述

# 1. 导入必要的库
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import openai
from datetime import datetime
import os
from dotenv import load_dotenv
import warnings
warnings.filterwarnings('ignore')

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False    # 用来正常显示负号

# 加载环境变量
load_dotenv()

# 设置GLM-4-Plus API (兼容OpenAI格式)
from openai import OpenAI

# 初始化客户端
client = OpenAI(
    api_key=os.getenv('OPENAI_API_KEY'),
    base_url=os.getenv('OPENAI_BASE_URL', 'https://open.bigmodel.cn/api/paas/v4/')
)

# 模型配置
MODEL_NAME = os.getenv('MODEL_NAME', 'glm-4-plus')

print("✅ 环境配置完成!")
print("📦 已导入所有必要库")
print(f"🤖 使用模型:{MODEL_NAME}")
print(f"🔗 API端点:{os.getenv('OPENAI_BASE_URL', 'https://open.bigmodel.cn/api/paas/v4/')}")
print("🔑 API密钥已配置" if os.getenv('OPENAI_API_KEY') else "❌ 请在.env文件中设置OPENAI_API_KEY")

✅ 环境配置完成!
📦 已导入所有必要库
🤖 使用模型:glm-4-plus
🔗 API端点:https://open.bigmodel.cn/api/paas/v4/
🔑 API密钥已配置

# 2. 核心功能函数定义

def load_and_clean_data(file_path):
    """
    加载并清洗销售数据
    """
    try:
        df = pd.read_csv(file_path)
        print(f"📁 成功加载数据:{len(df)}行 x {len(df.columns)}列")
        
        # 数据清洗
        df['date'] = pd.to_datetime(df['date'])
        df['revenue'] = pd.to_numeric(df['revenue'], errors='coerce')
        df['quantity'] = pd.to_numeric(df['quantity'], errors='coerce')
        
        # 数据脱敏(隐私保护)
        if 'customer_name' in df.columns:
            df['customer_name'] = df['customer_name'].mask(df['customer_name'].notna(), '***')
        if 'phone' in df.columns:
            df['phone'] = df['phone'].mask(df['phone'].notna(), '***')
            
        print("🔒 敏感数据已脱敏")
        return df
    except Exception as e:
        print(f"❌ 数据加载失败:{str(e)}")
        return None

def generate_summary_stats(df):
    """
    生成数据统计摘要
    """
    stats = {
        'total_revenue': df['revenue'].sum(),
        'avg_revenue': df['revenue'].mean(),
        'total_orders': len(df),
        'avg_order_value': df['revenue'].mean(),
        'date_range': f"{df['date'].min().strftime('%Y-%m-%d')}{df['date'].max().strftime('%Y-%m-%d')}",
        'top_category': df['product_category'].value_counts().index[0],
        'revenue_by_category': df.groupby('product_category')['revenue'].sum().to_dict(),
        'daily_revenue': df.groupby('date')['revenue'].sum().describe().to_dict()
    }
    
    print("📊 统计摘要生成完成")
    return stats

def generate_ai_insight(summary_stats, analysis_type="general"):
    """
    调用GLM-4-Plus大模型生成业务洞察
    """
    if not os.getenv('OPENAI_API_KEY'):
        return "⚠️ 未配置GLM API密钥,无法生成AI洞察"
    
    # 构建提示词
    if analysis_type == "general":
        prompt = f"""
你是一名资深的电商数据分析师,请基于以下销售数据摘要生成3点核心业务洞察:

数据概览:
- 总销售额:{summary_stats['total_revenue']:,.0f}元
- 平均订单金额:{summary_stats['avg_order_value']:,.0f}元
- 订单总数:{summary_stats['total_orders']}单
- 数据时间范围:{summary_stats['date_range']}
- 最热销品类:{summary_stats['top_category']}

各品类销售额分布:
{summary_stats['revenue_by_category']}

要求:
1. 用中文回答,避免专业术语(如"同比""环比"请用"比上月增长")
2. 必须指出1个潜在风险或异常点
3. 给出1条具体可执行的业务建议
4. 控制在150字以内
"""
    elif analysis_type == "trend":
        prompt = f"""
请用一句话描述销售趋势图的核心特征,用于图表注释:

数据摘要:{summary_stats['daily_revenue']}
时间范围:{summary_stats['date_range']}

要求:控制在50字以内,突出关键趋势。
"""
    
    try:
        response = client.chat.completions.create(
            model=MODEL_NAME,  # 使用GLM-4-Plus模型
            messages=[{"role": "user", "content": prompt}],
            max_tokens=200,
            temperature=0.3
        )
        return response.choices[0].message.content.strip()
    except Exception as e:
        return f"❌ GLM分析失败:{str(e)}"

print("🤖 AI分析函数已就绪")


🤖 AI分析函数已就绪

# 3. 加载和预览数据

# 加载示例数据
df = load_and_clean_data('sample_sales_data.csv')

if df is not None:
    print("\n📋 数据预览(前5行):")
    print(df.head())
    
    print("\n📊 基本信息:")
    print(f"数据形状:{df.shape}")
    print(f"时间范围:{df['date'].min()}{df['date'].max()}")
    print(f"品类数量:{df['product_category'].nunique()}")
    print(f"产品数量:{df['product_name'].nunique()}")
    
    print("\n💰 收入概览:")
    print(f"总销售额:¥{df['revenue'].sum():,.0f}")
    print(f"平均订单金额:¥{df['revenue'].mean():,.0f}")
    print(f"最高单笔:¥{df['revenue'].max():,.0f}")
    print(f"最低单笔:¥{df['revenue'].min():,.0f}")
else:
    print("❌ 数据加载失败,请检查文件路径")

📁 成功加载数据:90行 x 8列
🔒 敏感数据已脱敏

📋 数据预览(前5行):
date product_category product_name customer_name phone revenue
0 2024-01-01 电子产品 iPhone 15 *** *** 6999
1 2024-01-01 服装 羽绒服 *** *** 599
2 2024-01-01 食品 有机蔬菜 *** *** 89
3 2024-01-02 电子产品 MacBook Pro *** *** 12999
4 2024-01-02 服装 运动鞋 *** *** 899

quantity unit_price
0 1 6999.00
1 2 299.50
2 3 29.67
3 1 12999.00
4 1 899.00

📊 基本信息:
数据形状:(90, 8)
时间范围:2024-01-01 00:00:00 到 2024-01-30 00:00:00
品类数量:3
产品数量:90

💰 收入概览:
总销售额:¥304,757
平均订单金额:¥3,386
最高单笔:¥49,999
最低单笔:¥59

🧩 核心函数:调用大模型生成洞察

# 4. 生成统计摘要和AI洞察

if df is not None:
    # 生成统计摘要
    summary_stats = generate_summary_stats(df)
    
    print("📊 详细统计摘要:")
    print(f"总销售额:¥{summary_stats['total_revenue']:,.0f}")
    print(f"订单总数:{summary_stats['total_orders']}单")
    print(f"平均订单金额:¥{summary_stats['avg_order_value']:,.0f}")
    print(f"数据时间范围:{summary_stats['date_range']}")
    print(f"最热销品类:{summary_stats['top_category']}")
    
    print("\n💡 各品类销售额分布:")
    for category, revenue in summary_stats['revenue_by_category'].items():
        print(f"  {category}:¥{revenue:,.0f}")
    
    # 生成AI洞察
    print("\n🤖 AI业务洞察分析:")
    print("=" * 50)
    ai_insight = generate_ai_insight(summary_stats)
    print(ai_insight)
    print("=" * 50)
else:
    print("❌ 无法生成分析,请先加载数据")

🖼️ 输出效果(Notebook截图):

📊 统计摘要生成完成
📊 详细统计摘要:
总销售额:¥304,757
订单总数:90单
平均订单金额:¥3,386
数据时间范围:2024-01-01 到 2024-01-30
最热销品类:电子产品
💡 各品类销售额分布:
服装:¥21,630
电子产品:¥257,930
食品:¥25,197
🤖 AI业务洞察分析:1. 电子产品主导销售:电子产品销售额占比高达84.6%,是主要收入来源。2. 品类失衡风险:服装和食品销售额较低,品类依赖度高,存在市场波动风险。3. 提升弱势品类:建议加大对服装和食品的营销力度,如推出促销活动,平衡品类销售,降低单一依赖风险。


3.3 可视化增强:让图表“会说话”

📈 用 matplotlib 画图 + 大模型自动配文:

# 5. 数据可视化:智能图表生成

def create_visualizations(df, summary_stats):
    """
    生成多种图表并配上AI解读
    """
    fig, axes = plt.subplots(2, 2, figsize=(15, 12))
    fig.suptitle('销售数据分析仪表板', fontsize=16, fontweight='bold')
    
    # 1. 销售趋势图
    daily_sales = df.groupby('date')['revenue'].sum()
    axes[0,0].plot(daily_sales.index, daily_sales.values, marker='o', linewidth=2, color='#2E86AB')
    axes[0,0].set_title('日销售额趋势', fontsize=14)
    axes[0,0].set_xlabel('日期')
    axes[0,0].set_ylabel('销售额(元)')
    axes[0,0].grid(True, alpha=0.3)
    axes[0,0].tick_params(axis='x', rotation=45)
    
    # 2. 品类销售占比饼图
    category_sales = df.groupby('product_category')['revenue'].sum()
    colors = ['#A23B72', '#F18F01', '#C73E1D']
    axes[0,1].pie(category_sales.values, labels=category_sales.index, autopct='%1.1f%%', 
                  colors=colors, startangle=90)
    axes[0,1].set_title('各品类销售占比', fontsize=14)
    
    # 3. 订单金额分布直方图
    axes[1,0].hist(df['revenue'], bins=20, color='#4ECDC4', alpha=0.7, edgecolor='black')
    axes[1,0].set_title('订单金额分布', fontsize=14)
    axes[1,0].set_xlabel('订单金额(元)')
    axes[1,0].set_ylabel('订单数量')
    axes[1,0].grid(True, alpha=0.3)
    
    # 4. 各品类平均订单金额对比
    avg_order_by_category = df.groupby('product_category')['revenue'].mean()
    bars = axes[1,1].bar(avg_order_by_category.index, avg_order_by_category.values, 
                         color=['#FFE66D', '#FF6B6B', '#4ECDC4'])
    axes[1,1].set_title('各品类平均订单金额', fontsize=14)
    axes[1,1].set_xlabel('产品品类')
    axes[1,1].set_ylabel('平均金额(元)')
    
    # 添加数值标签
    for bar in bars:
        height = bar.get_height()
        axes[1,1].text(bar.get_x() + bar.get_width()/2., height,
                       f'¥{height:.0f}', ha='center', va='bottom')
    
    plt.tight_layout()
    plt.savefig('sales_dashboard.png', dpi=150, bbox_inches='tight')
    plt.show()
    
    # 生成图表AI解读
    trend_insight = generate_ai_insight(summary_stats, "trend")
    print(f"\n📈 图表AI解读:{trend_insight}")

if df is not None:
    create_visualizations(df, summary_stats)
else:
    print("❌ 无法生成图表,请先加载数据")

输出效果:图表下方自动生成人性化解读,如:
“销售额在月中达到峰值后回落,建议检查月末促销活动效果。”
在这里插入图片描述
📈 图表AI解读:“1月销售波动大,均值10158元,最大值51197元,中位数6747元,呈上升趋势。”

# 6. 生成完整的分析报告

def generate_full_report(df, summary_stats, ai_insight):
    """
    生成完整的文字分析报告
    """
    report = f"""
# 销售数据分析报告
生成时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}

## 📊 数据概览
- **分析期间**:{summary_stats['date_range']}
- **总销售额**:¥{summary_stats['total_revenue']:,.0f}
- **订单总数**:{summary_stats['total_orders']:,}单
- **平均订单金额**:¥{summary_stats['avg_order_value']:,.0f}
- **最热销品类**:{summary_stats['top_category']}

## 💰 各品类表现
"""
    
    for category, revenue in summary_stats['revenue_by_category'].items():
        percentage = (revenue / summary_stats['total_revenue']) * 100
        report += f"- **{category}**:¥{revenue:,.0f} ({percentage:.1f}%)\n"
    
    report += f"""
## 🤖 AI智能洞察
{ai_insight}

## 📈 关键指标
- **日均销售额**:¥{summary_stats['total_revenue'] / len(df['date'].unique()):,.0f}
- **最高单日销售**:¥{df.groupby('date')['revenue'].sum().max():,.0f}
- **最低单日销售**:¥{df.groupby('date')['revenue'].sum().min():,.0f}
- **销售波动性**:{df.groupby('date')['revenue'].sum().std() / df.groupby('date')['revenue'].sum().mean() * 100:.1f}%

## 📋 数据质量检查
- **缺失值检查**:{'✅ 无缺失值' if df.isnull().sum().sum() == 0 else f'⚠️ 发现{df.isnull().sum().sum()}个缺失值'}
- **异常值检查**:{'✅ 数据正常' if df['revenue'].min() > 0 else '⚠️ 发现异常订单金额'}
- **数据完整性**:✅ 所有必要字段完整

---
*本报告由AI数据分析助手自动生成*
"""
    
    # 保存报告到文件
    with open('sales_analysis_report.txt', 'w', encoding='utf-8') as f:
        f.write(report)
    
    print("📄 完整分析报告:")
    print("=" * 60)
    print(report)
    print("=" * 60)
    print("✅ 报告已保存到 'sales_analysis_report.txt'")

if df is not None:
    generate_full_report(df, summary_stats, ai_insight)
else:
    print("❌ 无法生成报告,请先加载数据")


📄 完整分析报告:

销售数据分析报告

生成时间:2025-09-08 22:39:50

📊 数据概览

  • 分析期间:2024-01-01 到 2024-01-30
  • 总销售额:¥304,757
  • 订单总数:90单
  • 平均订单金额:¥3,386
  • 最热销品类:电子产品

💰 各品类表现

  • 服装:¥21,630 (7.1%)
  • 电子产品:¥257,930 (84.6%)
  • 食品:¥25,197 (8.3%)

🤖 AI智能洞察

  1. 电子产品主导销售:电子产品销售额占比高达84.6%,是主要收入来源。
  2. 品类失衡风险:服装和食品销售额较低,品类依赖度高,存在市场波动风险。
  3. 提升弱势品类:建议加大对服装和食品的营销力度,如推出促销活动,平衡品类销售,降低单一依赖风险。

📈 关键指标

  • 日均销售额:¥10,159

    本报告由AI数据分析助手自动生成

============================================================
✅ 报告已保存到 ‘sales_analysis_report.txt’

# 7. 生成PDF报告(带格式)- 完美解决中文字体问题
def register_chinese_fonts():
    """
    智能注册中文字体,支持多种字体文件和系统
    """
    try:
        from reportlab.pdfbase import pdfmetrics
        from reportlab.pdfbase.ttfonts import TTFont
        from reportlab.pdfbase.cidfonts import UnicodeCIDFont
        import os
        import platform
        
        # 定义多个中文字体候选路径
        font_candidates = []
        
        # Windows系统字体路径
        if platform.system() == "Windows":
            font_candidates.extend([
                "C:/Windows/Fonts/simhei.ttf",      # 黑体
                "C:/Windows/Fonts/simsun.ttc",      # 宋体
                "C:/Windows/Fonts/msyh.ttc",        # 微软雅黑
                "C:/Windows/Fonts/simkai.ttf",      # 楷体
                "C:/Windows/Fonts/simfang.ttf",     # 仿宋
            ])
        
        # macOS系统字体路径
        elif platform.system() == "Darwin":
            font_candidates.extend([
                "/System/Library/Fonts/PingFang.ttc",
                "/Library/Fonts/Arial Unicode.ttf",
                "/System/Library/Fonts/Helvetica.ttc"
            ])
        
        # Linux系统字体路径
        else:
            font_candidates.extend([
                "/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf",
                "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",
                "/usr/share/fonts/truetype/arphic/uming.ttc"
            ])
        
        # 尝试注册字体
        registered_fonts = []
        
        for i, font_path in enumerate(font_candidates):
            if os.path.exists(font_path):
                try:
                    font_name = f"ChineseFont{i}"
                    
                    # 根据文件扩展名选择注册方式
                    if font_path.lower().endswith('.ttf'):
                        pdfmetrics.registerFont(TTFont(font_name, font_path))
                    elif font_path.lower().endswith('.ttc'):
                        # TTC文件需要指定字体索引
                        pdfmetrics.registerFont(TTFont(font_name, font_path, subfontIndex=0))
                    
                    registered_fonts.append((font_name, font_path))
                    print(f"✅ 成功注册字体: {font_name} -> {font_path}")
                    
                except Exception as e:
                    print(f"⚠️  字体注册失败 {font_path}: {e}")
                    continue
        
        # 如果没有成功注册任何字体,尝试使用内置的CID字体
        if not registered_fonts:
            try:
                pdfmetrics.registerFont(UnicodeCIDFont('STSong-Light'))
                registered_fonts.append(('STSong-Light', 'Built-in CID Font'))
                print("✅ 使用内置CID字体: STSong-Light")
            except:
                try:
                    pdfmetrics.registerFont(UnicodeCIDFont('HeiseiMin-W3'))
                    registered_fonts.append(('HeiseiMin-W3', 'Built-in CID Font'))
                    print("✅ 使用内置CID字体: HeiseiMin-W3")
                except:
                    print("❌ 无法注册任何中文字体")
                    return None
        
        return registered_fonts[0][0] if registered_fonts else None
        
    except Exception as e:
        print(f"❌ 字体注册过程失败: {e}")
        return None

# 注册中文字体
chinese_font_name = register_chinese_fonts()
if chinese_font_name:
    print(f"🎯 将使用字体: {chinese_font_name}")
else:
    print("⚠️  将使用默认字体,可能无法正确显示中文")

def generate_pdf_report(df, summary_stats, ai_insight):
    """
    生成格式化的PDF报告
    """
    try:
        from reportlab.lib.pagesizes import letter, A4
        from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, Image
        from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
        from reportlab.lib.units import inch
        from reportlab.pdfbase import pdfmetrics
        from reportlab.pdfbase.ttfonts import TTFont
        from reportlab.lib import colors
        from reportlab.lib.enums import TA_CENTER, TA_LEFT
        import matplotlib.pyplot as plt
        import os
        
        print("📄 开始生成PDF报告...")
        
        # 创建PDF文档
        pdf_filename = f'sales_analysis_report_{datetime.now().strftime("%Y%m%d_%H%M%S")}.pdf'
        doc = SimpleDocTemplate(pdf_filename, pagesize=A4)
        story = []
        
        # 获取样式
        styles = getSampleStyleSheet()
        
        # 确定要使用的字体
        font_name = chinese_font_name if chinese_font_name else 'Helvetica'
        font_name_bold = chinese_font_name if chinese_font_name else 'Helvetica-Bold'
        
        print(f"📝 PDF将使用字体: {font_name}")
        
        # 自定义样式 - 使用中文字体
        title_style = ParagraphStyle(
            'CustomTitle',
            parent=styles['Heading1'],
            fontSize=18,
            spaceAfter=30,
            alignment=TA_CENTER,
            textColor=colors.darkblue,
            fontName=font_name_bold
        )
        
        heading_style = ParagraphStyle(
            'CustomHeading',
            parent=styles['Heading2'],
            fontSize=14,
            spaceAfter=12,
            spaceBefore=12,
            textColor=colors.darkgreen,
            fontName=font_name_bold
        )
        
        # 普通文本样式
        normal_style = ParagraphStyle(
            'CustomNormal',
            parent=styles['Normal'],
            fontSize=11,
            fontName=font_name,
            leading=14
        )
        
        # 标题
        story.append(Paragraph("销售数据分析报告", title_style))
        story.append(Spacer(1, 12))
        
        # 生成时间
        story.append(Paragraph(f"<b>生成时间:</b>{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", normal_style))
        story.append(Paragraph(f"<b>分析工具:</b>GLM-4-Plus AI数据分析助手", normal_style))
        story.append(Spacer(1, 20))
        
        # 数据概览
        story.append(Paragraph("📊 数据概览", heading_style))
        overview_data = [
            ['指标', '数值'],
            ['分析期间', summary_stats['date_range']],
            ['总销售额', f"¥{summary_stats['total_revenue']:,.0f}"],
            ['订单总数', f"{summary_stats['total_orders']:,}单"],
            ['平均订单金额', f"¥{summary_stats['avg_order_value']:,.0f}"],
            ['最热销品类', summary_stats['top_category']]
        ]
        
        overview_table = Table(overview_data, colWidths=[2*inch, 2*inch])
        overview_table.setStyle(TableStyle([
            ('BACKGROUND', (0, 0), (-1, 0), colors.grey),
            ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
            ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
            ('FONTNAME', (0, 0), (-1, 0), font_name_bold),
            ('FONTNAME', (0, 1), (-1, -1), font_name),
            ('FONTSIZE', (0, 0), (-1, 0), 12),
            ('FONTSIZE', (0, 1), (-1, -1), 11),
            ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
            ('BACKGROUND', (0, 1), (-1, -1), colors.beige),
            ('GRID', (0, 0), (-1, -1), 1, colors.black)
        ]))
        story.append(overview_table)
        story.append(Spacer(1, 20))
        
        # 各品类表现
        story.append(Paragraph("💰 各品类表现", heading_style))
        category_data = [['品类', '销售额', '占比']]
        for category, revenue in summary_stats['revenue_by_category'].items():
            percentage = (revenue / summary_stats['total_revenue']) * 100
            category_data.append([category, f"¥{revenue:,.0f}", f"{percentage:.1f}%"])
        
        category_table = Table(category_data, colWidths=[1.5*inch, 1.5*inch, 1*inch])
        category_table.setStyle(TableStyle([
            ('BACKGROUND', (0, 0), (-1, 0), colors.grey),
            ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
            ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
            ('FONTNAME', (0, 0), (-1, 0), font_name_bold),
            ('FONTNAME', (0, 1), (-1, -1), font_name),
            ('FONTSIZE', (0, 0), (-1, 0), 12),
            ('FONTSIZE', (0, 1), (-1, -1), 11),
            ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
            ('BACKGROUND', (0, 1), (-1, -1), colors.beige),
            ('GRID', (0, 0), (-1, -1), 1, colors.black)
        ]))
        story.append(category_table)
        story.append(Spacer(1, 20))
        
        # AI智能洞察
        story.append(Paragraph("🤖 AI智能洞察", heading_style))
        # 将AI洞察按行分割并格式化
        insight_lines = ai_insight.split('\n')
        for line in insight_lines:
            if line.strip():
                # 处理粗体标记 - 修复配对问题
                formatted_line = line
                # 计算**的数量,确保配对
                bold_count = formatted_line.count('**')
                if bold_count > 0 and bold_count % 2 == 0:
                    # 偶数个**,可以正确配对
                    parts = formatted_line.split('**')
                    new_line = ""
                    for i, part in enumerate(parts):
                        if i % 2 == 0:
                            new_line += part
                        else:
                            new_line += f"<b>{part}</b>"
                    formatted_line = new_line
                else:
                    # 奇数个**或没有**,移除所有**
                    formatted_line = formatted_line.replace('**', '')
                
                story.append(Paragraph(formatted_line, normal_style))
        story.append(Spacer(1, 20))
        
        # 关键指标
        story.append(Paragraph("📈 关键指标", heading_style))
        daily_avg = summary_stats['total_revenue'] / len(df['date'].unique())
        daily_max = df.groupby('date')['revenue'].sum().max()
        daily_min = df.groupby('date')['revenue'].sum().min()
        volatility = df.groupby('date')['revenue'].sum().std() / df.groupby('date')['revenue'].sum().mean() * 100
        
        metrics_data = [
            ['指标', '数值'],
            ['日均销售额', f"¥{daily_avg:,.0f}"],
            ['最高单日销售', f"¥{daily_max:,.0f}"],
            ['最低单日销售', f"¥{daily_min:,.0f}"],
            ['销售波动性', f"{volatility:.1f}%"]
        ]
        
        metrics_table = Table(metrics_data, colWidths=[2*inch, 2*inch])
        metrics_table.setStyle(TableStyle([
            ('BACKGROUND', (0, 0), (-1, 0), colors.grey),
            ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
            ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
            ('FONTNAME', (0, 0), (-1, 0), font_name_bold),
            ('FONTNAME', (0, 1), (-1, -1), font_name),
            ('FONTSIZE', (0, 0), (-1, 0), 12),
            ('FONTSIZE', (0, 1), (-1, -1), 11),
            ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
            ('BACKGROUND', (0, 1), (-1, -1), colors.beige),
            ('GRID', (0, 0), (-1, -1), 1, colors.black)
        ]))
        story.append(metrics_table)
        story.append(Spacer(1, 20))
        
        # 数据质量检查
        story.append(Paragraph("📋 数据质量检查", heading_style))
        quality_checks = [
            f"✅ 缺失值检查:{'无缺失值' if df.isnull().sum().sum() == 0 else f'发现{df.isnull().sum().sum()}个缺失值'}",
            f"✅ 异常值检查:{'数据正常' if df['revenue'].min() > 0 else '发现异常订单金额'}",
            "✅ 数据完整性:所有必要字段完整"
        ]
        
        for check in quality_checks:
            story.append(Paragraph(check, normal_style))
        story.append(Spacer(1, 20))
        
        # 添加图表(如果存在)
        if os.path.exists('sales_dashboard.png'):
            story.append(Paragraph("📊 数据可视化", heading_style))
            # 调整图片大小以适应页面
            img = Image('sales_dashboard.png', width=6*inch, height=4.5*inch)
            story.append(img)
            story.append(Spacer(1, 20))
        
        # 页脚
        story.append(Spacer(1, 30))
        footer_style = ParagraphStyle(
            'Footer',
            parent=styles['Normal'],
            fontSize=10,
            alignment=TA_CENTER,
            textColor=colors.grey,
            fontName=font_name
        )
        story.append(Paragraph("本报告由GLM-4-Plus AI数据分析助手自动生成", footer_style))
        story.append(Paragraph(f"生成时间:{datetime.now().strftime('%Y年%m月%d日 %H:%M:%S')}", footer_style))
        
        # 生成PDF
        doc.build(story)
        
        print(f"✅ PDF报告生成成功:{pdf_filename}")
        return pdf_filename
        
    except ImportError:
        print("❌ 缺少reportlab库,正在安装...")
        import subprocess
        import sys
        subprocess.check_call([sys.executable, "-m", "pip", "install", "reportlab"])
        print("✅ reportlab安装完成,请重新运行此cell")
        return None
    except Exception as e:
        print(f"❌ PDF生成失败:{str(e)}")
        return None

# 生成PDF报告
if df is not None and 'summary_stats' in locals() and 'ai_insight' in locals():
    pdf_file = generate_pdf_report(df, summary_stats, ai_insight)
    if pdf_file:
        print(f"🎉 PDF报告已生成:{pdf_file}")
        print("📄 报告包含:数据概览、品类分析、AI洞察、关键指标、数据质量检查和可视化图表")
else:
    print("❌ 请先运行前面的cells生成数据和分析结果")



✅ 成功注册字体: ChineseFont0 -> C:/Windows/Fonts/simhei.ttf
✅ 成功注册字体: ChineseFont1 -> C:/Windows/Fonts/simsun.ttc
✅ 成功注册字体: ChineseFont2 -> C:/Windows/Fonts/msyh.ttc
✅ 成功注册字体: ChineseFont3 -> C:/Windows/Fonts/simkai.ttf
✅ 成功注册字体: ChineseFont4 -> C:/Windows/Fonts/simfang.ttf
🎯 将使用字体: ChineseFont0
📄 开始生成PDF报告…
📝 PDF将使用字体: ChineseFont0
✅ PDF报告生成成功:sales_analysis_report_20250908_223951.pdf
🎉 PDF报告已生成:sales_analysis_report_20250908_223951.pdf
📄 报告包含:数据概览、品类分析、AI洞察、关键指标、数据质量检查和可视化图表


4. 疑难点解析:避坑指南

🚫 坑1:提示词模糊 → 结果天马行空
错误示例: “分析一下数据” → 模型可能写小说。
✅ 解决方案:用结构化模板 + 案例对比:

💸 坑2:API成本失控
GPT-4 按token收费,长文本+高频调用=账单爆炸。
✅ 优化方案

  • 设置 max_tokens=200
  • 缓存结果:相同数据摘要不重复调用
  • 成本估算表:
调用次数 平均Token/次 预估费用($0.03/1K token)
100 150 $0.45
1000 150 $4.5

⚠️ 陷阱警告:大模型会“编造”数据!
模型可能虚构“某产品销量暴涨200%”,但数据中根本无此产品。
✅ 验证方法:在提示词中强制要求:
“仅基于提供的数据摘要分析,不得推测或虚构未提及的信息。”


5. 部署指南:从Notebook到生产工具

🚀 方案1:封装为Streamlit Web应用(推荐给非技术人员)
3步部署到 Streamlit Cloud:

  1. 新建 app.py,封装上传+分析逻辑
  2. streamlit run app.py 本地测试
  3. 推送到GitHub → Streamlit Cloud自动部署
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

⏱️ 方案2:定时自动生成报告(适合日报/周报)
cron + Python脚本:

# 每周一上午9点自动生成周报
0 9 * * 1 /usr/bin/python3 /path/to/auto_report.py

🏢 企业安全方案:内网Docker部署
Dockerfile 关键配置:

FROM python:3.9-slim
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 禁用外网访问,只允许内网调用大模型API
ENV OPENAI_API_BASE="http://internal-llm-gateway:8000/v1"

6. 总结与扩展

🎯 关键收获

  • 你已掌握 “pandas清洗 + 大模型解读” 的黄金组合。
  • 积累你的 提示词模板库,适配不同场景:
场景 提示词要点
金融 强调风险、合规、波动率
电商 关注转化率、爆款、库存预警
医疗 避免绝对化结论,强调“建议复核”

🚀 进阶方向

  • LangChain 实现多步骤分析:先问“哪个品类增长最快?” → 再问“为什么?”
  • 接入 多模态模型:自动分析图表图片 + 生成报告。

📢 行动号召
立即用本工具分析公开数据集,练手+出成果!
🔗 推荐数据集:Kaggle 电商销售数据

你的下一个报告,不该再手动写了。
10秒,让大模型替你打工。


附录:完整代码 & 图表清单


下期预告:第70篇《用大模型自动生成PPT——从数据报告到老板汇报,一键转换》
👉 关注我,告别加班!

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐