资讯动态

# 038 实战项目三:数据分析 Agent —— 自然语言查询、可视化生成与报告输出

发布时间:2026/8/22 8:51:02 来源:尧图企业网站定制
踩坑实录一个SQL注入引发的“血案”去年帮某电商团队搭数据分析Agent上线第三天运维半夜打电话说数据库CPU飙到98%。查了半天发现是某个用户输入了 OR 11; DROP TABLE orders; --作为查询条件。Agent的LLM模块老老实实把这句话拼进了SQL模板然后数据库就差点被“团灭”。这个教训让我意识到数据分析Agent的核心不是“能听懂人话”而是“在听懂人话的同时知道什么该做、什么不该做”。今天这篇笔记就围绕这个实战项目把自然语言转SQL、自动出图、生成报告这三个环节的坑和解决方案掰开了讲清楚。架构设计别把Agent做成“翻译器”很多人一上来就搞“用户说一句话 → LLM生成SQL → 执行 → 出图”的流水线。这种设计在Demo阶段跑得欢一上生产就崩。为什么因为LLM生成的SQL大概率有语法错误、表名拼错、字段不存在更别提权限问题了。我现在的做法是三层隔离第一层NLU解析层。不直接让LLM写SQL而是先让LLM把自然语言转成“意图参数”的结构化数据。比如用户说“上个月销售额最高的三个品类”LLM输出的是{intent:top_n_query,table:sales_summary,metric:revenue,group_by:category,top_n:3,time_range:last_month}这一步的好处是即使LLM抽风输出的JSON格式也是可控的后续可以校验字段名是否合法。第二层SQL生成引擎。根据结构化参数用模板参数填充的方式生成SQL。这里踩过坑——千万别让LLM直接写SQL模板否则会出现SELECT * FROM table WHERE date 2024-13-01这种低级错误。我改用预定义的SQL片段拼接比如defbuild_top_n_query(params):# 这里踩过坑直接拼接字符串会被注入# 别这样写fSELECT {params[metric]} FROM {params[table]}# 正确做法用参数化查询base_sql SELECT {group_by}, SUM({metric}) as total FROM {table} WHERE date {start_date} AND date {end_date} GROUP BY {group_by} ORDER BY total DESC LIMIT {top_n} # 注意表名和字段名不能参数化但可以用白名单校验validate_table_name(params[table])validate_column_name(params[metric])returnbase_sql.format(**params)第三层执行与安全沙箱。SQL执行必须走只读连接且限制单次查询返回行数我设的是10000行超过就报“数据量过大请缩小时间范围”。另外所有查询都走一个独立的数据库用户只有SELECT权限连CREATE TEMPORARY TABLE都不给。自然语言转SQLLLM不是万能的实测下来GPT-4在简单查询上准确率能到85%但一旦涉及多表JOIN、窗口函数、复杂聚合准确率直接掉到60%以下。更坑的是LLM会“编造”不存在的字段名。我的解决方案是给LLM喂数据库Schema时附带字段的示例值。比如表名orders 字段order_id (示例: ORD-2024-001), customer_id (示例: CUST-12345), order_date (示例: 2024-01-15), total_amount (示例: 299.99)这样LLM在生成查询条件时会参考示例值的格式减少“2024-13-01”这种错误。还有一个坑用户说“最近一周”LLM可能理解成“过去7天”也可能理解成“本周一到今天”。我强制要求LLM输出时间范围时必须附带具体的起止日期比如start_date: 2024-11-18, end_date: 2024-11-24。这样即使LLM理解错了用户也能在界面上看到具体日期手动修正。可视化生成从“画图”到“选图”很多人让LLM直接生成Matplotlib代码结果画出来的图要么比例失调要么标签重叠要么颜色辣眼睛。我换了个思路让LLM只决定“用什么图”具体渲染交给专业库。定义好几种图表类型每种对应一个模板趋势分析 → 折线图时间在X轴占比分析 → 饼图或环形图类别不超过10个对比分析 → 柱状图类别不超过20个相关性分析 → 散点图数据点不超过5000个LLM只需要输出{chart_type: bar, x_axis: category, y_axis: total}然后由后端调用ECharts或Plotly渲染。这样生成的图表至少是“能看的”不会出现X轴标签旋转90度还重叠的惨状。这里有个细节饼图的类别数超过10个时自动把“其他”合并。柱状图类别超过20个时自动转成水平柱状图。这些规则写在代码里不依赖LLM判断。报告输出Markdown 动态模板报告生成这块我踩过最大的坑是“LLM写报告太啰嗦”。让GPT-4写一段分析结论它能给你写出800字小作文里面全是“值得注意的是”“综上所述”这种废话。后来我改成结构化报告模板# {report_title} ## 数据概览 - 查询时间范围{start_date} 至 {end_date} - 总数据量{total_rows} 条 - 关键指标{key_metrics} ## 图表分析 {chart_embed} ## 核心发现 {llm_generated_insight} # 这里限制LLM输出不超过3句话LLM只负责生成“核心发现”部分而且我给了明确的prompt约束请用三句话以内总结数据中的关键趋势或异常点。 不要使用“值得注意的是”“需要关注的是”等套话。 直接说结论例如“销售额环比下降15%主要受A品类拖累。”完整流程串起来用户输入“帮我看看上个月哪些产品卖得不好出个报告”NLU解析意图是underperforming_products参数包括时间范围last_month指标sales_volume排序方式ascendingSQL生成SELECT product_name, SUM(quantity) as total_sold FROM orders WHERE order_date BETWEEN 2024-10-01 AND 2024-10-31 GROUP BY product_name ORDER BY total_sold ASC LIMIT 10执行查询返回10行数据每行包含产品名和销量图表选择因为要展示“卖得不好”用柱状图X轴是产品名Y轴是销量按升序排列报告生成模板填充数据LLM生成结论“销量最低的三款产品分别是A、B、C其中A产品月销量仅12件建议检查库存和营销策略”输出Markdown格式报告内嵌Base64编码的图表图片个人经验性建议永远不要信任LLM生成的SQL。哪怕准确率99%那1%的错误在生产环境可能就是灾难。加一层参数校验和模板约束成本很低收益巨大。可视化不是越炫越好。饼图、柱状图、折线图能解决90%的分析需求。3D图、雷达图、桑基图这些除非用户明确要求否则别主动用。报告要“可编辑”。用户拿到报告后大概率会手动修改。所以输出格式别用PDF用Markdown或HTML方便用户复制粘贴。日志记录一切。用户说了什么、LLM解析了什么、生成了什么SQL、返回了什么数据全部记录下来。出问题的时候这是唯一的排查线索。给用户一个“撤回”按钮。数据分析Agent最怕的是“一键生成无法回退”。每次查询都保留历史记录用户可以回退到上一步修改参数重新生成。最后说一句数据分析Agent的本质不是“替代分析师”而是“让分析师从重复劳动中解放出来”。所以设计时多想想哪些步骤是机械的、可自动化的哪些步骤需要人的判断力把前者交给Agent把后者留给用户。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价