Python + Jinja2 + Matplotlib:AI回答采集报告自动化生成实现

问题背景

在一次AI回答采集项目中,需要每周生成一份报告,汇总模型响应时间、回答长度、评分等指标。手动从数据库导出数据、用Excel做图表、再排版,每次耗时约2小时,且容易遗漏指标或格式不一致。因此需要一套自动化报告生成系统,能够从数据库读取数据、聚合指标、生成图表并输出HTML报告。

环境说明

  • Python 3.9+
  • Jinja2 模板引擎
  • Matplotlib 用于图表生成
  • Pandas 用于数据聚合
  • 数据存储在PostgreSQL中(以下为通用实现思路,具体表结构和字段请根据实际项目调整)

整体流程

报告生成分为四个阶段:

  1. 数据读取:从数据库查询原始采集记录。
  2. 指标聚合:按报告周期(日/周/月)计算平均响应时间、回答长度、评分等。
  3. 模板渲染:使用Jinja2将聚合结果和图表嵌入HTML模板。
  4. 输出归档:生成HTML文件并保存。

选择先聚合再渲染的原因是:聚合后的数据量小,模板渲染更快;不同周期(如日、周)对聚合的影响主要体现在SQL的GROUP BY粒度上,周报需要按周聚合,日报按天。

报告模板设计

使用Jinja2模板引擎,将报告结构抽象为模板,支持动态插入图表、表格和文本。模板分为三部分:

  • 头部:报告标题、时间范围、生成时间
  • 主体:指标卡片、趋势图、对比表格
  • 尾部:备注、数据来源说明

示例模板片段(report_template.html):

html 复制代码
<!DOCTYPE html>
<html>
<head><title>{{ title }}</title></head>
<body>
  <h1>{{ title }}</h1>
  <p>时间范围:{{ start_date }} ~ {{ end_date }}</p>
  <p>生成时间:{{ generated_at }}</p>
  
  <h2>核心指标</h2>
  <div class="cards">
    {% for metric in metrics %}
    <div class="card">
      <h3>{{ metric.name }}</h3>
      <p>{{ metric.value }}</p>
    </div>
    {% endfor %}
  </div>
  
  <h2>趋势图</h2>
  <img src="{{ trend_chart_path }}" alt="趋势图">
  
  <h2>详细数据</h2>
  <table>
    <tr><th>日期</th><th>指标A</th><th>指标B</th></tr>
    {% for row in detail_rows %}
    <tr><td>{{ row.date }}</td><td>{{ row.metric_a }}</td><td>{{ row.metric_b }}</td></tr>
    {% endfor %}
  </table>
</body>
</html>

数据聚合

从数据库查询原始数据,使用Pandas进行聚合。以下代码为示例,实际使用时需替换数据库连接信息和表名。

python 复制代码
import pandas as pd
from sqlalchemy import create_engine

def aggregate_data(start_date, end_date):
    # 请替换为实际数据库连接信息
    engine = create_engine('postgresql://your_user:your_password@your_host/your_db')
    query = f"""
        SELECT 
            DATE(created_at) as date,
            AVG(response_time_ms) as avg_response_time,
            AVG(LENGTH(answer_text)) as avg_answer_length,
            AVG(score) as avg_score
        FROM ai_responses
        WHERE created_at >= '{start_date}' AND created_at < '{end_date}'
        GROUP BY DATE(created_at)
        ORDER BY date
    """
    df = pd.read_sql(query, engine)
    return df

可视化图表生成

使用Matplotlib生成趋势图,保存为图片嵌入报告。注意Matplotlib默认字体不支持中文,需指定中文字体。

python 复制代码
import matplotlib.pyplot as plt

def generate_trend_chart(df, metric_col, output_path):
    plt.figure(figsize=(10, 4))
    plt.plot(df['date'], df[metric_col], marker='o')
    plt.title(f'{metric_col} 趋势')
    plt.xlabel('日期')
    plt.ylabel(metric_col)
    plt.grid(True)
    plt.tight_layout()
    plt.savefig(output_path)
    plt.close()

报告生成主流程

python 复制代码
from jinja2 import Environment, FileSystemLoader
import datetime

def generate_report(start_date, end_date):
    # 1. 聚合数据
    df = aggregate_data(start_date, end_date)
    
    # 2. 计算核心指标
    metrics = [
        {'name': '平均响应时间(ms)', 'value': round(df['avg_response_time'].mean(), 2)},
        {'name': '平均回答长度(字符)', 'value': round(df['avg_answer_length'].mean(), 2)},
        {'name': '平均评分', 'value': round(df['avg_score'].mean(), 2)},
    ]
    
    # 3. 生成趋势图
    chart_path = '/tmp/trend.png'
    generate_trend_chart(df, 'avg_response_time', chart_path)
    
    # 4. 渲染模板
    env = Environment(loader=FileSystemLoader('templates'))
    template = env.get_template('report_template.html')
    html_content = template.render(
        title='AI回答采集周报',
        start_date=start_date,
        end_date=end_date,
        generated_at=datetime.datetime.now().strftime('%Y-%m-%d %H:%M'),
        metrics=metrics,
        trend_chart_path=chart_path,
        detail_rows=df.to_dict('records')
    )
    
    # 5. 输出HTML文件
    output_path = f'report_{start_date}_{end_date}.html'
    with open(output_path, 'w') as f:
        f.write(html_content)
    
    return output_path

支持自定义指标

通过配置文件定义指标名称、SQL聚合表达式和单位,系统动态加载。

yaml 复制代码
# metrics_config.yaml
metrics:
  - name: 平均响应时间
    sql: AVG(response_time_ms)
    unit: ms
  - name: 最大响应时间
    sql: MAX(response_time_ms)
    unit: ms
  - name: 回答接受率
    sql: SUM(CASE WHEN accepted=1 THEN 1 ELSE 0 END) * 1.0 / COUNT(*)
    unit: '%'

代码中读取配置并动态生成SQL和图表。

验证结果

正常情况下,运行脚本后会生成一个HTML文件,打开可看到:

  • 报告标题和时间范围
  • 核心指标卡片(数值正确)
  • 趋势图(折线图显示日期和指标值)
  • 数据表格(与数据库查询结果一致)

常见问题与避坑

  1. 图表中文乱码 :Matplotlib默认字体不支持中文,需指定中文字体,如plt.rcParams['font.sans-serif'] = ['SimHei']
  2. 模板路径问题:Jinja2的FileSystemLoader需要正确设置模板目录,建议使用绝对路径或项目相对路径。
  3. 大数据量性能:如果数据量过大,聚合查询可能慢,可考虑预聚合表或使用数据库物化视图。
  4. 图表保存路径:生成图表时确保输出目录存在,否则保存失败。

总结

本文提供了一个基于Python的AI回答采集报告自动生成方案,核心思路是:用Pandas聚合数据,用Matplotlib生成图表,用Jinja2渲染HTML模板。方案支持通过YAML配置文件自定义指标,易于扩展。当前限制:仅输出HTML格式,如需PDF可借助wkhtmltopdf或WeasyPrint转换。适用于需要定期输出采集评估结果的场景,但具体数据库表结构和字段需根据实际项目调整。

相关推荐
circuitsosk1 小时前
大模型驱动的AI产品后端架构设计与实践
人工智能·python
飞凌嵌入式1 小时前
性能翻倍·功耗减半!RK3572八核核心板,重构嵌入式计算新标杆
人工智能·嵌入式硬件·飞凌嵌入式
gnhpc11 小时前
深耕工业智造!飞腾主板,让智慧城市发展更高效
人工智能·智慧城市
JackSparrow4142 小时前
前端安全之JS混淆+请求加密+请求签名以提升爬虫难度
前端·javascript·后端·爬虫·python·安全
人工智能AI技术2 小时前
从Prompt到Graph Engineering:企业多Agent五层AI工程演进全解析
人工智能
西西弗Sisyphus2 小时前
部署模型的优化:图像标准化预处理从三步到一步乘加(2)
人工智能·机器学习·分类·训练·推理·imagenet
软糖姐姐2 小时前
python eureka服务发现_python与consul 实现gRPC服务注册-发现
python·consul·grpc·服务注册·发现
zandy10112 小时前
2026年,AI Agent搜索Skill推荐已经离不开底层架构
大数据·人工智能·架构
听雨入夜2 小时前
zero.zhang
开发语言·python
小弥儿2 小时前
GitHub今日热榜 | 2026-07-31:AI Agent工作流共享赛道升温
人工智能·学习·github