构建AI智能体:四十三、智能数据分析机器人:基于Qwen-Agent与Text2SQL的门票分析方案

构建AI智能体:四十三、智能数据分析机器人:基于Qwen-Agent与Text2SQL的门票分析方案

一、系统概述

        随着企业数字化进程的加速,数据已成为决策的重要依据,但传统数据分析流程存在诸多痛点。业务人员往往需要依赖专业数据团队进行SQL查询和报表制作,这个过程耗时耗力且响应迟缓,沟通成本高、技术门槛也高。特别是在门票销售这样的实时性要求较高的行业,快速获取数据洞察对业务决策至关重要。

        结合昨天我们刚讲过的Qwen-Agent和前期讲过的Text2SQL技术以及Gradio前端展示技术,构建了一个智能化的门票数据分析平台,让业务人员能够通过自然语言直接进行数据查询和分析,大幅降低了技术门槛,提高了决策效率。旨在通过自然语言交互实现数据库查询和可视化分析。

        系统结合了大语言模型、数据库操作和数据可视化技术,为用户提供直观的门票销售数据分析体验。该系统不仅解决了传统数据分析流程的痛点,更为企业级智能数据分析应用提供了新的思路和方案。

系统采用分层架构设计,确保各模块之间的松耦合和高内聚。整体架构包含四个核心层次:

  • 用户交互层:基于Gradio构建的Web界面,提供直观的聊天式交互体验。该层负责捕获用户输入、渲染查询结果,并管理用户会话状态。
  • 智能代理层:系统的"大脑",基于Qwen-Agent框架实现。该层负责自然语言理解、对话管理、工具调用决策和结果整合。
  • 工具执行层:模块化的工具系统,核心包括SQL执行工具和可视化生成工具。该层负责具体的业务逻辑执行和数据处理。
  • 数据服务层:包括MySQL数据库和文件系统,为系统提供数据存储和持久化支持。

二、核心组件

1. Qwen-Agent智能代理

  • 上下文感知:能够理解多轮对话的上下文关系
  • 意图识别:准确识别用户的查询意图和业务需求
  • 工具协调:智能决策何时以及如何调用工具函数
  • 结果整合:将工具执行结果整合成用户友好的格式

2. Text2SQL转换引擎

  • 自然语言理解:解析用户查询的语义结构,识别意图、实体和条件
  • 模式映射:将自然语言中的概念映射到数据库中的表、列和关系
  • SQL生成:构建符合目标数据库方言的正确语法结构
  • 查询优化:确保生成的SQL在执行时具有良好性能

3. Gradio前端展示

  • 简单易用:界面简单、设计友好,几行代码即可创建功能完整的Web界面
  • 多样化组件:支持文本、图像、音频、视频等多种输入输出格式
  • 即时分享:一键生成可公开访问的链接
  • 框架无关:可与TensorFlow、PyTorch、Scikit-learn等任何机器学习框架配合使用
  • 高度可定制:提供灵活的自定义选项满足不同需求和应用场景

三、系统流程

1. 流程图

2. 流程分解

2.1 基础流程

第一步:用户输入与消息传递 (步骤1-2)

  • 用户输入:用户在Web界面输入自然语言问题,如"查询2023年门票销售情况"
  • 消息捕获:WebUI组件捕获用户输入,格式化为标准消息格式
  • 会话管理:根据对话历史生成唯一的session_id,确保多用户隔离

第二步:智能分析与SQL生成 (步骤3-4)

  • 意图理解:Agent结合system_prompt中的业务知识,理解用户查询意图
  • 上下文整合:如果有历史对话,会结合上下文进行更准确的理解
  • SQL生成:基于数据表结构和业务逻辑,生成符合规范的SQL查询语句
  • 工具调用决策:判断需要调用exc_sql工具执行数据查询

第三步:数据查询执行 (步骤5-7)

  • 数据库连接:从连接池获取MySQL数据库连接,设置超时和字符集
  • SQL执行:使用pandas的read_sql方法执行查询,返回DataFrame
  • 结果验证:检查查询结果的有效性,处理空结果或异常情况

第四步:可视化与结果组装 (步骤8-10)

1. 智能可视化:

  • 自动分析数据类型(分类变量vs数值变量)
  • 根据数据特征选择图表类型(普通柱状图vs堆积柱状图)
  • 处理中文显示和格式美化
  • 文件保存:将生成的图表保存为PNG文件,使用时间戳确保文件名唯一

2. 结果组装:

  • 将DataFrame转换为Markdown表格格式
  • 生成图片的Markdown引用链接
  • 组合表格和图片为完整响应

第五步:结果返回与显示 (步骤11-12)

  • 结果传递:工具结果逐级返回给Agent和WebUI
  • 界面渲染:WebUI将Markdown内容渲染为美观的显示格式
  • 用户交互:用户可以看到结构化数据和可视化图表,可进行后续交互

2.2 自然语言到SQL的转换流程

  • 意图解析:理解用户查询的业务背景和具体需求
  • 条件提取:识别时间范围、筛选条件、分组维度等关键要素
  • SQL构造:根据数据库schema构建符合语法的SQL语句
  • 优化验证:检查SQL的合理性和执行效率

2.3 Agent创建过程

  • 配置LLM参数:指定模型版本、超时设置、重试策略
  • 实例化Assistant:传入名称、描述、系统提示词等
  • 注册工具函数:将'exc_sql'工具绑定到Agent
  • 返回初始化完成的bot对象

系统运行界面:

查询过程中生成的图示:

此处也可导入echarts的组件,达到动态炫酷的展示效果!

四、核心代码分解

1. Assistant智能代理

llm_cfg = {         'model': 'qwen-turbo',         'timeout': 30,         'retry_count': 3,     } bot = Assistant(     llm=llm_cfg,     name='门票助手',     description='门票查询与订单分析',     system_message=system_prompt,     function_list=['exc_sql'], )
  • 使用qwen-turbo模型作为语言理解核心
  • 通过system_prompt定义专业领域知识
  • 函数调用机制实现工具扩展

2. 系统提示词设计

system_prompt = """我是门票助手,以下是关于门票订单表相关的字段,我可能会编写对应的SQL,对数据进行查询 -- 门票订单表 CREATE TABLE tkt_orders (     order_time DATETIME,             -- 订单日期     ......     quantity INT                     -- 商品数量 ); 一日门票,对应多种SKU: Universal Studios Beijing One-Day Dated Ticket-Standard Universal Studios Beijing One-Day Dated Ticket-Child Universal Studios Beijing One-Day Dated Ticket-Senior
  • 设计原则:明确的角色定义、数据结构说明、SQL查询模式示例、输出格式规范
  • 领域专业化:系统提示词不仅定义了助手角色,更包含了详细的数据表结构说明和业务逻辑,使模型能够理解门票业务的特殊性。
  • 查询模式预置:通过提供常见的SQL查询模板,如一日门票、二日门票的统计方式,引导模型生成符合业务需求的查询语句。
  • 输出规范约束:明确要求原样输出工具返回内容,避免模型过度"聪明"地总结或简化,确保用户获得完整的数据信息。

3. SQLAlchemy引擎配置

engine = create_engine(     f'mysql+mysqlconnector://root:Aa123456!@localhost:3306/{database}?charset=utf8mb4',     connect_args={'connect_timeout': 10}, pool_size=10, max_overflow=20 )

连接参数详解:

  • 连接字符串格式:数据库类型+驱动://用户名:密码@主机:端口/数据库名
  • 连接池配置:pool_size控制连接数,max_overflow控制超额连接
  • 字符集设置:utf8mb4支持完整Unicode字符
  • 并发支持:pool_size=10确保系统能同时处理多个查询请求
  • 弹性扩展:max_overflow=20在高峰期提供额外连接缓冲
  • 故障隔离:超时设置防止单次查询阻塞整个系统

4. 数据查询执行

df = pd.read_sql(sql_input, engine)
  • 使用pandas的read_sql方法直接执行SQL
  • 自动将结果转换为DataFrame格式
  • 支持复杂的SQL查询语句

5. 可视化函数架构

def generate_chart_png(df_sql, save_path):     # 数据类型识别与处理     object_columns = df_sql.select_dtypes(include='O').columns.tolist()     num_columns = df_sql.select_dtypes(exclude='O').columns.tolist()          # 智能图表类型选择     if len(object_columns) > 0:         # 堆积柱状图逻辑         pivot_df = df_sql.pivot_table(...)     else:         # 普通柱状图逻辑         bottom = np.zeros(len(df_sql))

可视化策略:

  • 自动识别数据类型:系统能够区分分类变量和数值变量,这是选择合适图表类型的基础
  • 智能图表选择:根据数据特征选择最佳可视化方式
    • 当数据包含多个分类维度时,自动选择堆积柱状图展示复合关系
    • 单一维度数据使用普通柱状图,保持图表简洁性
  • 透视表自动生成:通过pivot_table实现数据重组,满足复杂多维度的可视化需求

6. 中文显示解决方案

plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'SimSun', 'Arial Unicode MS'] plt.rcParams['axes.unicode_minus'] = False
  • 设置中文字体优先级列表
  • 解决负号显示异常问题
  • 确保图表中文字符正常渲染

7. 函数的调用机制

functions_desc = [     {         "name": "exc_sql",         "description": "对于生成的SQL,进行SQL查询",         # 参数定义确保SQL语句的正确传递     } ]
  • 能力边界清晰:语言模型负责理解意图和生成SQL,专业工具负责执行和可视化
  • 安全性保障:通过参数校验确保输入的SQL符合预期格式
  • 可扩展性强:新的分析功能可以通过添加工具函数快速集成

8. @register_tool装饰器

@register_tool('exc_sql') class ExcSQLTool(BaseTool):     description = '对于生成的SQL,进行SQL查询,并自动可视化'     parameters = [{'name': 'sql_input', 'type': 'string', 'required': True}]
  • 使用装饰器注册工具名称
  • 继承BaseTool基类
  • 定义工具描述和参数规范

9. 工具调用接口

def call(self, params: str, **kwargs) -> str:     args = json.loads(params)     sql_input = args['sql_input']
  • JSON格式参数解析
  • 异常处理与错误返回
  • 统一的返回格式

10. 使用建议与默认提示

chatbot_config = {     'prompt.suggestions': [         '2023年4、5、6月一日门票,二日门票的销量多少?帮我按照周进行统计',         '2023年7月的不同省份的入园人数统计',         '帮我查看2023年10月1-7日销售渠道订单金额排名',     ] }
  • 预置典型查询问题
  • 降低用户学习成本
  • 引导用户使用模式

11. 异常处理机制

try:     df = pd.read_sql(sql_input, engine)     # 正常处理逻辑 except Exception as e:     return f"SQL执行或可视化出错: {str(e)}"
  • 数据库连接异常捕获
  • SQL执行错误处理
  • 可视化过程异常管理

12. 性能优化

dashscope.timeout = 30  # API调用超时设置 connect_args={'connect_timeout': 10}  # 数据库连接超时 pool_size=10, max_overflow=20  # 连接池配置
  • 合理的超时设置
  • 数据库连接池管理
  • 资源释放与清理

五:优化与不足

  • 针对SQL生成可能出现的错误,系统建立了多级校验机制。包括语法检查、执行验证和错误反馈循环,确保生成SQL的准确性和安全性。
  • 通过异步处理、连接池管理和缓存策略优化系统性能。数据库查询使用连接池复用连接,图表生成结果进行缓存,避免重复计算。
  • 采用会话隔离和资源池化技术支持多用户并发访问。每个会话有独立的数据空间,关键资源通过池化管理,确保系统稳定运行。

六、总结

        本项目成功构建了一个基于Qwen-Agent和Text2SQL的智能门票数据分析系统。通过自然语言交互大幅降低了数据分析的技术门槛,提高了业务决策效率,自动化报表生成,减少人工数据处理工作量,让非技术人员也能深度参与数据分析过程。  

        系统展示了大语言模型在企业级应用中的巨大潜力。基于提示工程的Text2SQL方案为类似项目提供了新的技术思路,避免了专门模型训练的复杂性。下一步将扩展系统分析能力,支持预测分析和异常检测等高级功能。同时探索更多应用场景,将这一技术方案推广到其他行业领域。

附录:完整实例代码

import os import asyncio from typing import Optional import dashscope from qwen_agent.agents import Assistant from qwen_agent.gui import WebUI import pandas as pd from sqlalchemy import create_engine from qwen_agent.tools.base import BaseTool, register_tool import matplotlib.pyplot as plt import io import base64 import time import numpy as np # 解决中文显示问题 plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'SimSun', 'Arial Unicode MS'] # 优先使用的中文字体 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 # 定义资源文件根目录 ROOT_RESOURCE = os.path.join(os.path.dirname(__file__), 'resource') # 配置 DashScope dashscope.api_key = os.getenv('DASHSCOPE_API_KEY', '') # 从环境变量获取 API Key dashscope.timeout = 30 # 设置超时时间为 30 秒 # ====== 门票助手 system prompt 和函数描述 ======"我是门票助手,以下是关于门票订单表相关的字段,我可能会编写对应的SQL,对数据进行查询 -- 门票订单表 CREATE TABLE tkt_orders ( order_time DATETIME, -- 订单日期 account_id INT, -- 预定用户ID gov_id VARCHAR(18), -- 商品使用人ID(身份证号) gender VARCHAR(10), -- 使用人性别 age INT, -- 年龄 province VARCHAR(30), -- 使用人省份 SKU VARCHAR(100), -- 商品SKU名 product_serial_no VARCHAR(30), -- 商品ID eco_main_order_id VARCHAR(20), -- 订单ID sales_channel VARCHAR(20), -- 销售渠道 status VARCHAR(30), -- 商品状态 order_value DECIMAL(10,2), -- 订单金额 quantity INT -- 商品数量 ); 一日门票,对应多种SKU: Universal Studios Beijing One-Day Dated Ticket-Standard Universal Studios Beijing One-Day Dated Ticket-Child Universal Studios Beijing One-Day Dated Ticket-Senior 二日门票,对应多种SKU: USB 1.5-Day Dated Ticket Standard USB 1.5-Day Dated Ticket Discounted 一日门票、二日门票查询 SUM(CASE WHEN SKU LIKE 'Universal Studios Beijing One-Day%' THEN quantity ELSE 0 END) AS one_day_ticket_sales, SUM(CASE WHEN SKU LIKE 'USB%' THEN quantity ELSE 0 END) AS two_day_ticket_sales 我将回答用户关于门票相关的问题 每当 exc_sql 工具返回 markdown 表格和图片时,你必须原样输出工具返回的全部内容(包括图片 markdown),不要只总结表格,也不要省略图片。这样用户才能直接看到表格和图片。 """ functions_desc = [ { "name": "exc_sql", "description": "对于生成的SQL,进行SQL查询", "parameters": { "type": "object", "properties": { "sql_input": { "type": "string", "description": "生成的SQL语句", } }, "required": ["sql_input"], }, }, ] # ====== 会话隔离 DataFrame 存储 ====== # 用于存储每个会话的 DataFrame,避免多用户数据串扰 _last_df_dict = {} def get_session_id(kwargs): """根据 kwargs 获取当前会话的唯一 session_id,这里用 messages 的 id""" messages = kwargs.get('messages') if messages is not None: return id(messages) return None # ====== exc_sql 工具类实现 ====== @register_tool('exc_sql') class ExcSQLTool(BaseTool): """ SQL查询工具,执行传入的SQL语句并返回结果,并自动进行可视化。 """ description = '对于生成的SQL,进行SQL查询,并自动可视化' parameters = [{ 'name': 'sql_input', 'type': 'string', 'description': '生成的SQL语句', 'required': True }] def call(self, params: str, **kwargs) -> str: import json import matplotlib.pyplot as plt import io, os, time import numpy as np args = json.loads(params) sql_input = args['sql_input'] database = args.get('database', 'world') engine = create_engine( f'mysql+mysqlconnector://root:Aa123456!@localhost:3306/{database}?charset=utf8mb4', connect_args={'connect_timeout': 10}, pool_size=10, max_overflow=20 ) try: df = pd.read_sql(sql_input, engine) md = df.head(10).to_markdown(index=False) # 自动创建目录 save_dir = os.path.join(os.path.dirname(__file__), 'image_show') os.makedirs(save_dir, exist_ok=True) filename = f'bar_{int(time.time()*1000)}.png' save_path = os.path.join(save_dir, filename) # 生成图表 generate_chart_png(df, save_path) img_path = os.path.join('image_show', filename) img_md = f'![柱状图]({img_path})' return f"{md}\n\n{img_md}" except Exception as e: return f"SQL执行或可视化出错: {str(e)}" # ========== 通用可视化函数 ========== def generate_chart_png(df_sql, save_path): columns = df_sql.columns x = np.arange(len(df_sql)) # 获取object类型 object_columns = df_sql.select_dtypes(include='O').columns.tolist() if columns[0] in object_columns: object_columns.remove(columns[0]) num_columns = df_sql.select_dtypes(exclude='O').columns.tolist() if len(object_columns) > 0: # 对数据进行透视,以便为每个日期和销售渠道创建堆积柱状图 pivot_df = df_sql.pivot_table(index=columns[0], columns=object_columns, values=num_columns, fill_value=0) # 绘制堆积柱状图 fig, ax = plt.subplots(figsize=(10, 6)) # 为每个销售渠道和票类型创建柱状图 bottoms = None for col in pivot_df.columns: ax.bar(pivot_df.index, pivot_df[col], bottom=bottoms, label=str(col)) if bottoms is None: bottoms = pivot_df[col].copy() else: bottoms += pivot_df[col] else: print('进入到else...') bottom = np.zeros(len(df_sql)) for column in columns[1:]: plt.bar(x, df_sql[column], bottom=bottom, label=column) bottom += df_sql[column] plt.xticks(x, df_sql[columns[0]]) plt.legend() plt.title("销售统计") plt.xlabel(columns[0]) plt.ylabel("门票数量") plt.xticks(rotation=45) plt.tight_layout() plt.savefig(save_path) plt.close() # ====== 初始化门票助手服务 ====== def init_agent_service(): """初始化门票助手服务""" llm_cfg = { 'model': 'qwen-turbo-2025-04-28', 'timeout': 30, 'retry_count': 3, } try: bot = Assistant( llm=llm_cfg, name='门票助手', description='门票查询与订单分析', system_message=system_prompt, function_list=['exc_sql'], # 移除绘图工具 ) print("助手初始化成功!") return bot except Exception as e: print(f"助手初始化失败: {str(e)}") raise def app_gui(): """图形界面模式,提供 Web 图形界面""" try: print("正在启动 Web 界面...") # 初始化助手 bot = init_agent_service() # 配置聊天界面,列举3个典型门票查询问题 chatbot_config = { 'prompt.suggestions': [ '2023年4、5、6月一日门票,二日门票的销量多少?帮我按照周进行统计', '2023年7月的不同省份的入园人数统计', '帮我查看2023年10月1-7日销售渠道订单金额排名', ] } print("Web 界面准备就绪,正在启动服务...") # 启动 Web 界面 WebUI( bot, chatbot_config=chatbot_config ).run() except Exception as e: print(f"启动 Web 界面失败: {str(e)}") print("请检查网络连接和 API Key 配置") if __name__ == '__main__': # 运行模式选择 app_gui() # 图形界面模式(默认)

数据库结构参考:

Read more

AI绘画低成本方案:没显卡别急,2块钱试效果

AI绘画低成本方案:没显卡别急,2块钱试效果 你是不是也遇到过这种情况?作为淘宝店主,想给自家商品拍点高级感十足的主图、详情页,结果一问代运营公司,单张AI生成图报价20元起步,做一套图下来几百块就没了。关键是——你又不是天天要用,花大价钱请人做图,实在不划算。 别急!现在有个超实用的新选择:花2块钱,租用1小时高端GPU服务器,自己动手生成AI商品图。成本直接从20元降到0.2元,省下90%以上!而且操作比你想的简单得多,哪怕你完全不懂技术,也能跟着步骤一步步搞定。 我最近帮几个朋友实测了这个方法,用ZEEKLOG星图平台提供的Stable Diffusion镜像,从部署到出图,全程不到15分钟。生成的商品图清晰、风格可控,还能批量制作不同背景和角度的效果图,完全可以满足日常上新需求。 这篇文章就是为你量身打造的“零基础AI绘画入门指南”。我会手把手带你: * 理解什么是AI绘画,它怎么帮你省钱 * 如何在没有独立显卡的情况下,快速使用高端GPU资源 * 用预置镜像一键启动Stable Diffusion服务 * 输入提示词(prompt)生成高质量商品图 * 调

Llama-3.2-3B部署实录:Ollama本地大模型从下载到生成仅需90秒

Llama-3.2-3B部署实录:Ollama本地大模型从下载到生成仅需90秒 想体验最新的大语言模型,但又担心复杂的部署流程和漫长的等待时间?今天,我要分享一个极其简单的方案:使用Ollama在本地部署Meta最新发布的Llama-3.2-3B模型。整个过程从下载模型到生成第一段文字,最快只需要90秒,而且完全免费,不需要任何复杂的配置。 Llama-3.2-3B是Meta推出的轻量级多语言大模型,虽然只有30亿参数,但在很多任务上的表现已经相当出色。更重要的是,它非常“亲民”,对普通电脑配置要求不高,通过Ollama这个工具,你可以像安装一个普通软件一样把它装到自己的电脑上,随时随地调用。 这篇文章,我将带你走一遍完整的部署流程,从零开始,手把手教你如何用最简单的方法,在自己的电脑上跑起这个强大的AI助手。 1. 准备工作:认识我们的工具和模型 在开始动手之前,我们先花一分钟了解一下今天要用到的两个核心:Ollama和Llama-3.2-3B模型。了解它们是什么,能帮你更好地理解后面的每一步操作。 1.1 Ollama:你的本地大模型管家 你可以把Ollama想象成

Whisper-large-v3保姆级教程:语音转文字so easy

Whisper-large-v3保姆级教程:语音转文字so easy 1. 引言 1.1 语音识别的实际价值 想象一下这样的场景:你需要整理一场多语言会议的录音,或者想把外语视频的字幕提取出来,又或者需要将语音笔记转为文字。传统方法要么费时费力,要么需要专业软件。现在,有了Whisper-large-v3,这些都能轻松搞定。 这个教程要介绍的镜像,基于OpenAI Whisper Large v3模型,能自动识别99种语言,支持音频上传和实时录音,还有Web界面让你点点鼠标就能用。无论你是开发者还是普通用户,都能快速上手。 1.2 教程能带给你什么 看完这篇教程,你将学会: * 怎么快速部署这个语音识别服务 * 怎么通过Web界面使用各种功能 * 怎么用代码调用API进行二次开发 * 遇到问题怎么解决 最重要的是,整个过程非常简单,不需要深厚的技术背景,跟着步骤做就行。 2. 环境准备与快速部署 2.1 硬件和系统要求 想要顺畅运行这个服务,你的设备最好满足这些条件: 资源类型推荐配置最低要求GPUNVIDIA RTX 4090

Stable Diffusion 3.5 FP8量化版安装全攻略:CUDA+PyTorch环境从0搭建

Stable Diffusion 3.5 FP8量化版部署实战:从CUDA环境搭建到高效推理 在生成式AI的浪潮中,Stable Diffusion 3.5 的发布再次刷新了文生图模型的质量上限。更强的提示理解能力、更合理的构图逻辑和更精细的纹理还原,让创作者们跃跃欲试。但随之而来的,是动辄12GB以上的显存占用和数秒级的单图生成延迟——这对大多数消费级GPU用户而言,几乎是一道无法逾越的门槛。 幸运的是,FP8低精度量化技术的引入,为这一困局提供了优雅的解决方案。通过将模型权重与激活值压缩至8位浮点表示,SD3.5 FP8版本在几乎不损失视觉质量的前提下,实现了显存占用下降35%、推理速度提升近50%的惊人表现。这意味着你手中的RTX 4080或4090,终于可以流畅运行1024×1024分辨率的高阶生成任务。 但这背后有一个关键前提:你的系统必须构建一个精准匹配的CUDA + PyTorch运行时环境。任何版本错配都可能导致“明明有卡却跑不动”的尴尬局面。本文将带你从零开始,一步步搭建出稳定支持SD3.5-FP8的本地推理平台,并深入剖析其底层机制与优化逻辑。 现代深度学习