1. 项目概述
在医疗设备采购数据分析场景中,我们构建了一套从自然语言提问到BI页面自动生成的完整工程链路。与传统的ChatBI系统不同,这套方案的核心价值不在于NL2SQL(自然语言转SQL)能力本身,而在于实现了分析结果的直接交付——用户输入一个问题,系统返回的不再是SQL语句或原始数据行,而是一个可直接访问、分享的BI页面链接。
1.1 传统ChatBI的局限性
当前大多数智能问数系统存在一个共同痛点:它们止步于"把数据查出来"。无论是返回SQL语句、原始数据行,还是附带简单图表和文字总结,这些本质上都是中间结果,而非最终交付物。业务人员拿到这些结果后,仍需进行大量后续工作:
- 判断关键指标
- 整理分析摘要
- 选择合适的图表类型
- 设计页面布局
- 最终才能形成可分享的分析报告
这种"半成品"交付模式使得系统的实用价值大打折扣,也限制了AI在数据分析场景中的真正潜力。
1.2 本方案的创新点
我们的解决方案通过三层架构实现了质的飞跃:
- 问题理解层:使用openClaw将自然语言问题转化为结构化查询意图
- 数据获取层:通过受控的sql_runner执行精确的SQL查询
- 结果交付层:利用EdgeOne Pages将查询结果直接渲染为可分享的BI页面
这种架构设计使得系统输出从"会回答问题"升级为"能交付结果",真正满足了业务人员的核心需求——获得可直接使用的分析产品,而非需要二次加工的数据原料。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 架构设计与核心组件
2.1 三层架构解析
2.1.1 openClaw:智能任务编排引擎
openClaw在本方案中扮演"大脑"角色,主要负责:
- 判断用户输入是否为有效的数据分析请求
- 将自然语言问题分解为结构化查询意图
- 生成符合业务口径的SQL语句
- 协调后续组件完成查询和页面生成
关键设计原则:
- 职责单一:仅负责问题理解和任务编排,不涉及具体执行
- 输出标准化:生成的结构化意图包含明确的分析类型、指标口径、维度、过滤条件等
python复制# 示例:结构化查询意图
{
"analysis_type": "group_stat",
"metric": "公告数量",
"dimension": "city",
"filters": {
"province": "江西",
"device_name": "CT"
},
"time_range": {
"start": "2025-01-01",
"end": "2025-12-31"
},
"limit": 20
}
2.1.2 sql_runner:受控查询执行器
sql_runner的设计强调安全性和稳定性:
- 仅允许执行单条SELECT语句
- 严格限制可访问的表和字段(白名单机制)
- 对非聚合查询强制添加LIMIT子句
- 返回统一的JSON结构(包含status、sql、rows等字段)
python复制# SQL执行器核心逻辑
def execute_sql(sql: str):
# 安全检查
if not is_valid_select(sql):
raise Exception("只允许执行SELECT语句")
# 添加LIMIT(非聚合查询)
if not is_aggregate_query(sql):
sql = apply_limit(sql)
# 执行查询
try:
with connection.cursor() as cursor:
cursor.execute(sql)
rows = cursor.fetchall()
return {
"status": "success",
"sql": sql,
"rows": rows,
"row_count": len(rows),
"error": None
}
except Exception as e:
return {
"status": "error",
"sql": sql,
"rows": None,
"row_count": 0,
"error": str(e)
}
2.1.3 EdgeOne Pages:BI页面生成平台
EdgeOne Pages实现了从数据到产品的最后一公里转化:
- 接收结构化数据对象
- 自动选择适当的可视化形式(柱状图、折线图等)
- 生成包含摘要卡片、图表和数据表的完整页面
- 发布为可公开访问的URL
页面数据对象示例:
json复制{
"title": "2025年江西省CT设备采购公告统计",
"summary_cards": [
{"label": "公告数", "value": 128},
{"label": "涉及城市数", "value": 11}
],
"chart": {
"type": "bar",
"x_field": "city",
"y_field": "notice_cnt",
"data": [
{"city": "南昌", "notice_cnt": 28},
{"city": "赣州", "notice_cnt": 19}
]
},
"table": {
"columns": ["city", "notice_cnt"],
"rows": [
{"city": "南昌", "notice_cnt": 28},
{"city": "赣州", "notice_cnt": 19}
]
}
}
2.2 分层设计的工程价值
这种明确的分层架构带来了多重优势:
- 问题定位清晰:当链路出现问题时,可以快速定位到具体层级
- 独立演进:各层可以单独优化而不影响其他部分
- 稳定性保障:通过限制每层的职责范围,减少了不可控因素
- 逐步验证:可以从底层开始逐层验证,确保整体可靠性
3. 关键实现细节
3.1 数据语义标准化
确保系统可靠运行的前提是统一数据语义。我们建立了完整的语义字典:
| 业务术语 | 数据库表示 | 计算逻辑 |
|---|---|---|
| 公告数量 | notice_id | COUNT(DISTINCT notice_id) |
| 明细行数 | * | COUNT(*) |
| 总金额 | total_price | SUM(COALESCE(total_price, 0)) |
| 总数量 | quantity | SUM(COALESCE(quantity, 0)) |
同时定义了四种核心文档:
schema.md:表结构和字段说明metrics.md:指标口径定义query_patterns.md:常见问题模式page_schema.json:页面数据对象规范
3.2 SQL生成与执行
3.2.1 SQL生成策略
基于结构化查询意图,系统采用模板化方式生成SQL:
python复制def generate_sql(intent: dict) -> str:
# 确定SELECT部分
if intent['analysis_type'] == 'group_stat':
select = f"SELECT {intent['dimension']}, COUNT(DISTINCT notice_id) AS notice_cnt"
elif intent['analysis_type'] == 'trend':
select = f"SELECT date, SUM(COALESCE(total_price, 0)) AS total_amount"
# 构建WHERE条件
filters = []
for field, value in intent['filters'].items():
filters.append(f"{field} = '{value}'")
# 添加时间范围
if 'time_range' in intent:
filters.append(
f"publish_date BETWEEN '{intent['time_range']['start']}' AND '{intent['time_range']['end']}'"
)
# 组合完整SQL
where_clause = " AND ".join(filters) if filters else "1=1"
group_by = f"GROUP BY {intent['dimension']}" if 'dimension' in intent else ""
order_by = f"ORDER BY notice_cnt DESC" if intent['analysis_type'] == 'group_stat' else ""
limit = f"LIMIT {intent['limit']}" if 'limit' in intent else ""
return f"{select} FROM procurement {where_clause} {group_by} {order_by} {limit};"
3.2.2 执行安全机制
sql_runner实现了多重安全防护:
- SQL注入检测
- 语句类型验证(仅允许SELECT)
- 表级访问控制
- 结果行数限制
- 执行超时控制
3.3 页面生成逻辑
3.3.1 自动可视化选择
系统根据数据特征自动选择最佳图表类型:
| 数据类型 | 推荐图表 | 适用场景 |
|---|---|---|
| 分类对比 | 柱状图 | 城市间采购量对比 |
| 时间趋势 | 折线图 | 月度采购金额变化 |
| 占比分析 | 饼图 | 设备类型分布 |
| 相关性 | 散点图 | 价格与数量的关系 |
3.3.2 页面模板系统
EdgeOne Pages提供多种预置模板,可根据分析类型自动匹配:
- 概览型模板:突出关���指标卡片
- 对比型模板:强调多维度比较图表
- 明细型模板:以数据表格为主体
- 综合型模板:包含摘要、图表和明细
4. 工程实践与优化
4.1 开发流程
采用分阶段实施策略:
- 数据层验证:确保SQL生成和执行准确
- 页面层验证:确认数据到页面的转换可靠
- 端到端测试:验证完整链路功能
- 性能优化:针对高频查询进行缓存和索引优化
4.2 稳定性保障措施
- 输入校验:对自然语言问题进行有效性检查
- 回退机制:当自动生成失败时,提供简化结果
- 执行监控:记录各环节耗时和成功率
- 限流保护:防止系统过载
4.3 性能优化
针对医疗设备采购场景的特点,我们实施了多项优化:
-
查询优化:
- 为常用过滤条件(省份、设备类型)创建索引
- 对大型表进行分区(按年份)
- 使用物化视图预计算常用指标
-
缓存策略:
- 高频查询结果缓存(TTL 5分钟)
- 页面模板预加载
- 数据字典内存缓存
-
异步处理:
- 复杂查询异步执行
- 页面生成任务队列化
- 结果通知机制
5. 应用效果与案例
5.1 典型用户旅程
用户输入:
"请统计2024年江西省各地市CT设备采购情况,按公告数量降序排列,生成包含摘要卡片和柱状图的BI页面"
系统处理流程:
- 识别为分组统计请求
- 确定指标为"公告数量",维度为"城市"
- 添加过滤条件:省份=江西,设备类型=CT
- 时间范围:2024年全年
- 生成SQL并执行
- 构建页面数据对象
- 选择"对比型"模板渲染
- 返回页面链接
5.2 实际效果对比
| 维度 | 传统ChatBI | 本方案 |
|---|---|---|
| 输出形式 | SQL/原始数据 | 完整BI页面 |
| 使用门槛 | 需要技术知识 | 业务人员直接使用 |
| 交付速度 | 需人工加工 | 即时可用 |
| 分享便利性 | 需导出文件 | 直接分享链接 |
| 一致性 | 依赖人工操作 | 自动标准化 |
5.3 扩展应用场景
- 采购监控大屏:实时展示各地区采购动态
- 供应商分析报告:自动生成供应商绩效评估
- 预算执行看板:对比预算与实际支出
- 异常检测预警:识别采购异常模式
6. 经验总结与展望
6.1 关键成功因素
- 语义一致性:严格定义业务术语与技术实现的映射关系
- 架构清晰度:明确划分各层职责边界
- 交付完整性:坚持将结果推进到可直接使用的形式
- 工程严谨性:重视每一环节的可靠性和可验证性
6.2 未来优化方向
- 意图理解增强:支持更复杂的问题表述
- 模板多样化:增加更多专业分析模板
- 交互式探索:在生成的页面上支持下钻分析
- 多数据源整合:对接更多业务系统数据
这套方案证明了AI在数据分析领域可以超越简单的问答模式,直接参与分析产品的生产。当技术架构与业务需求深度结合时,AI不仅能理解问题,更能交付真正有价值的解决方案。这种从"回答问题"到"生产BI"的转变,或许正是智能数据分析进化的下一个里程碑。
