
智能小Q-数据分析
quickbi-smartq-chat
技能简介
超级数据分析技能,用户只需自然语言提问,即可智能匹配并分析 Excel 或 Quick BI 数据集,将洞察即时呈现。支持两种问数模式:1. **数据集问数**:用户未上传文件,对 Quick BI 平台已授权数据集进行自然语言查询。**无需用户提供 cubeId**,脚本会自动智能选表匹配数据集。2. **文件问数**:用户上传了 Excel/CSV 数据文件,对文件数据进行自然语言分析。用户说"问数""智能问数""查下数据""分析这份数据""文件问数"等,都应使用此技能。当用户提到数据分析、数据对比、趋势分析、数据统计、上传了 Excel/CSV 想做分析时,即使未明确说"问数",也应使用此技能。
资源链接
技能详情 (README)
name: quickbi-smartq-chat
description: |
超级数据分析技能,用户只需自然语言提问,即可智能匹配并分析 Excel 或 Quick BI 数据集,将洞察即时呈现。支持两种问数模式:
1. 数据集问数:用户未上传文件,对 Quick BI 平台已授权数据集进行自然语言查询。无需用户提供 cubeId,脚本会自动智能选表匹配数据集。
2. 文件问数:用户上传了 Excel/CSV 数据文件,对文件数据进行自然语言分析
用户说"问数""智能问数""查下数据""分析这份数据""文件问数"等,都应使用此技能。
当用户提到数据分析、数据对比、趋势分析、数据统计、上传了 Excel/CSV 想做分析时,即使未明确说"问数",也应使用此技能。
compatibility:
tools: [python3, pip]
runtime: [requests, pyyaml, matplotlib, numpy]
metadata:
label: 智能小Q-数据分析
小Q问数 — 超级数据分析师
只需自然语言提问,即可智能匹配并分析您的 Excel 或 Quick BI 数据集,将洞察即时呈现。让复杂分析,从未如此简单。问数过程中会自动完成推理分析、SQL 生成、数据计算以及可视化图表输出。
> ⚠️ 核心约束 — 文件问数必须走 Quick BI API
>
> 当用户上传了 Excel/CSV 数据文件,并且意图是对数据进行查询、分析、统计(即「问数」场景),必须按本技能规定的两步流程执行,禁止使用 pandas、openpyxl 等库直接读取文件进行本地分析:
> 1. 调用 upload_file.py 上传文件到 Quick BI 获取 fileId
> 2. 调用 file_stream_query.py 基于 fileId 发起流式问数
>
> 如何判断是否为问数场景:用户的意图是对数据提问、分析趋势、统计汇总、对比排名等数据分析类需求,而非仅查看文件结构、提取特定单元格值或做格式转换等非分析操作。
Scope
Does:
- 对 Quick BI 平台已授权数据集进行自然语言查询分析(数据集问数)
- 对用户上传的 Excel/CSV 文件通过 Quick BI API 进行自然语言分析(文件问数)
- 自动智能选表匹配最合适的数据集,无需用户提供 cubeId
- 渲染 matplotlib 图表并输出可视化结果和分析结论
- 在问数场景下使用 pandas/openpyxl/csv 等库直接读取文件进行本地分析
- 要求用户手动提供 cubeId 或其他内部参数
技能触发与模式选择
模式 A:数据集问数(无文件上传)
- 用户没有上传文件,要查询平台数据集 → 数据集问数
- 触发词示例:"问数""小Q问数""查下xx数据集""数据集提问""自然语言查询"
模式 B:文件问数(有文件上传)
- 用户上传了 Excel/CSV 文件并对数据提问 → 文件问数
- 触发词示例:"帮我分析这份数据""查询xx最多的TOP10""各部门销售额对比""分析下这个文件""文件问数"
- 执行方式:严格按两步脚本执行(upload_file.py → file_stream_query.py),不得用其他方式读取或分析文件
配置
本技能采用 配置分层 架构,用户配置与技能包分离,技能包更新不会覆盖用户配置。
配置加载优先级(高覆盖低)
1. 环境变量 ACCESS_TOKEN(最高优先级,适合容器部署)
2. skill 级用户配置 ~/.qbi/smartq-chat/config.yaml(仅当前 skill,禁止存放 server_domain/api_key/api_secret/user_token)
3. QBI 全局配置 ~/.qbi/config.yaml(所有 skill 共享)
4. 默认配置 技能包内 default_config.yaml(包内默认值,随包更新)
所有配置项(server_domain、api_key、api_secret、user_token)统一放在全局配置 ~/.qbi/config.yaml。
配置项说明
server_domain:Quick BI 服务域名api_key/api_secret:OpenAPI 认证密钥对(未配置时使用内置默认值进入试用)user_token:Quick BI 平台用户 ID,问数接口需传userId(未配置时自动注册并回填)
若启用
use_env_property: true,可通过环境变量 ACCESS_TOKEN JSON 中的 qbi_api_key、qbi_api_secret、qbi_server_domain、qbi_user_token 字段覆盖配置。试用凭证自动注册
当 api_key、api_secret、user_token 三项均未配置时,脚本会:
1. 输出温馨提示,告知用户将自动注册试用凭证并进入试用期
2. 使用内置默认凭证调用 API
3. 自动基于设备唯一标识注册用户,将 userId 回写到 ~/.qbi/config.yaml
试用到期由服务端接口通过错误码 AE0579100004 进行控制,无需本地追踪。
自定义配置指导
当用户希望使用自己的 Quick BI 账号凭证(而非试用凭证)时,请登录 Quick BI 控制台后,点击头像「一键复制 skill 配置」,如图所示:
复制后将配置粘贴给 Agent,Agent 会自动将 server_domain、api_key、api_secret、user_token 写入全局配置 ~/.qbi/config.yaml。
Agent 配置更新操作规范(必读)
新用户零配置初始化:如果用户说"初始化配置"、"我是新用户"等,但未提供任何具体配置值,则无需手动写入任何配置文件。告知用户直接运行问数即可,系统会自动完成试用注册(详见上方「试用凭证自动注册」章节)。
只有当用户明确提供了具体配置值时,才执行以下写入规则。
当用户提供了 api_key、api_secret、user_token、server_domain 中的任意一项或多项配置值时,Agent 必须使用文件编辑工具直接修改对应的用户配置文件,将用户提供的值写入对应字段。
写入位置规则:
server_domain、api_key、api_secret、user_token→ 统一写入 全局配置~/.qbi/config.yaml
1. 从用户消息中提取配置键值对(支持
key: value、key:value、key=value 等常见格式)2. 根据上方写入位置规则,使用文件编辑工具(如 search_replace)直接更新对应配置文件中的字段值
3. 清理高优先级层残留值:检查
~/.qbi/smartq-chat/config.yaml 是否存在且包含 server_domain、api_key、api_secret、user_token 中的任何一项,若存在则必须移除这些条目(因为 skill 级配置优先级高于全局配置,残留旧值会覆盖全局配置的新值)4. 更新完成后,向用户确认已写入的配置项及写入位置(包括是否清理了 skill 级配置中的残留值)
禁止行为:
- ❌ 禁止以「权限受限」「无法修改技能包内文件」等理由拒绝修改
- ❌ 禁止建议用户通过环境变量、手动复制文件等替代方案绕行
- ❌ 禁止仅输出配置内容让用户自行修改
- 全局配置(server_domain / api_key / api_secret / user_token):
~/.qbi/config.yaml
前置条件
- 需安装 Python 依赖:
pip install requests pyyaml matplotlib numpy - 数据集问数:用户需要有目标数据集的问数权限
- 文件问数:文件格式限
xls、xlsx、csv,单文件大小 ≤ 10MB
模式 A — 数据集问数
对 Quick BI 平台上已授权的数据集进行自然语言查询。
工作流程
一步式执行,脚本内部自动完成完整的问数 → 取数 → 渲染流程:
flowchart LR
input["用户问题"] --> hasCubeId{"已指定 cubeId?"}
hasCubeId -- 是 --> streamQuery["SSE 流式问数"]
hasCubeId -- 否 --> queryCubes["查询有权限的数据集"]
queryCubes --> tableSearch["智能选表 POST /tableSearch\\n(带 cubeIds 参数)"]
tableSearch -- 匹配到 --> streamQuery
tableSearch -- 未匹配 --> relevance["按文本相关性选择最相关数据集"]
relevance --> streamQuery
streamQuery --> parseSSE["实时解析 SSE 事件"]
parseSSE --> reasoning["输出推理过程"]
parseSSE --> olapResult["olapResult 事件\\n(取数结果直接内联)"]
olapResult --> chart["matplotlib 图表 或 Markdown 表格"]
parseSSE --> conclusion["输出结论"]> 等待预期:问数分析通常需要 15~60 秒,复杂查询可能更久。建议在发起问数前告知用户正在分析中。
执行命令
默认用法(自动智能选表,无需提供 cubeId):
python scripts/smartq_stream_query.py "分析销售数据集中销量最高的地区TOP3"> cubeId 是可选参数,脚本会自动查询用户有权限的数据集并通过智能选表匹配最合适的数据集,无需用户手动提供。
可选:已知目标数据集 ID 时直接指定(跳过智能选表):
python scripts/smartq_stream_query.py "总销售额是多少" --cube-id "dcbb0f94-4cee-4ba2-9950-927918bdd498"可选:提供候选数据集列表辅助智能选表:
python scripts/smartq_stream_query.py "总销售额是多少" --cube-ids "cubeId1,cubeId2,cubeId3"内部处理流程
1. 智能选表(当未指定 --cube-id 时自动触发):先调用 GET /openapi/v2/smartq/query/llmCubeWithThemeList 查询用户有权限的数据集列表,再将这些 cubeIds 作为参数调用 POST /openapi/v2/smartq/tableSearch 进行智能选表(传入 userQuestion、userId、llmNameForInference 默认 SYSTEM_deepseek-r1-0528、cubeIds),取返回的第一个 cubeId 作为目标数据集。若智能选表未匹配到结果,则按用户问题与数据集名称的文本相关性从权限数据集中选取最相关的一个
2. 调用问数流式接口:POST /openapi/v2/smartq/queryByQuestionStream,请求体为 JSON(userQuestion、cubeId、userId 等),响应为 SSE 事件流
3. 实时解析 SSE 事件(事件格式:event:message\\ndata:{"data":"xxx","type":"xxx","subType":"xxx"}):
- relatedInfo → 输出关联知识(数据集名称、业务定义等)
- reasoning → 输出推理过程(subType MODEL_REASONING 为模型推理)
- text / sql → 输出文本和 SQL 语句
- olapResult → 核心步骤,取数结果直接内联在事件流中
- summary → 输出数据解读(subType MODEL_REASONING 为模型推理)
- conclusion → 输出分析结论
- check → 校验错误信息
- error → 异常错误信息
- finish → 问数结束
4. olapResult 事件处理 :
- 从事件 data 中解析取数结果 JSON,包含 values(行数据)、chartType(图表类型枚举)、metaType(字段元信息)、logicSql(查询 SQL)
- metaType 中 t 字段标识维度(dimension)或度量(measure),type 字段标识 row/column,多维度场景下 colorLegend 标识颜色图例维度
- chartType 枚举:NEW_TABLE(交叉表) / BAR(柱图) / LINE(线图) / PIE(饼图) / SCATTER_NEW(散点图) / INDICATOR_CARD(指标看板) / RANKING_LIST(排行榜) / DETAIL_TABLE(明细表) / MAP_COLOR_NEW(色彩地图) / PROGRESS_NEW(进度条) / FUNNEL_NEW(漏斗图)
- 将数据转换为 chart_renderer 格式并使用 matplotlib 渲染图表(输出到 ~/.qbi/smartq-chat/output/ 目录)
- matplotlib 不可用时回退为 Markdown 表格
输出说明
脚本运行时会实时输出以下内容:
[关联知识]命中的数据集和业务定义[推理过程]AI 的分析推理[SQL]生成的查询 SQL[取数结果]图表类型和取数状态- 图表图片:当 matplotlib 可用时,脚本会以
!标题的 Markdown 图片语法输出渲染好的 PNG 图表;不可用时回退为 Markdown 表格 [结论]最终分析结论[Trace]请求追踪 ID(问题反馈时提供此 ID 可加速排查)[完成]问数结束
图表展示要求
重要:脚本输出中如果包含 !... 格式的图片引用,必须在答复中自然地展示图表。具体要求:
1. 先用 !标题 语法在答复的相应位置展示图表,让用户直接看到可视化结果
2. 紧接图片下方标注图表文件路径,例如:> 图表路径:~/.qbi/smartq-chat/output/chart_xxx.png
3. 不要在图表上方添加「饼图如下」「脚本输出路径」之类的机械化引导文字,分析结论自然衔接即可
4. 如果脚本输出的是 Markdown 表格(matplotlib 不可用时的 fallback),则直接展示表格
模式 B — 文件问数
基于用户上传的 Excel/CSV 结构化数据文件,通过流式问数接口进行智能分析。
工作流程
严格按两步执行,每一步独立运行并输出完整结果。步骤 1 的输出(fileId)作为步骤 2 的输入。
错误处理原则:业务逻辑错误(权限不足、试用到期、格式不支持等)必须立即终止整个流程;网络类瞬态错误(超时、连接中断)可重试 1~2 次(建议指数退避),重试仍失败则终止。
flowchart LR
file["用户数据文件\\n(xls/xlsx/csv)"] --> autoReg{"user_token\\n已配置?"}
autoReg -- 否 --> register["自动注册用户\\n回填 ~/.qbi/config.yaml"]
autoReg -- 是 --> upload
register -- 失败 --> abort["终止流程\\n告知原因"]
register -- 成功 --> upload["步骤1: upload_file.py\\nPOST /copilot/parse"]
upload -- 失败 --> abort
upload -- 成功 --> fileId["输出 fileId\\n+ 文件结构详情"]
fileId --> stream["步骤2: file_stream_query.py\\nPOST /smartq/queryByQuestionStreamByFile"]
stream -- 失败 --> abort
stream -- 成功 --> parseSSE["实时解析 SSE 事件流"]
parseSSE --> reasoning["输出思考/推理过程"]
parseSSE --> code["code 事件 → 拼接完整 Python 代码"]
parseSSE --> result["result 事件 → 解析结构化数据"]
result --> renderChart["matplotlib 渲染图表 PNG\\n保存到 ~/.qbi/smartq-chat/output/"]
parseSSE --> reporter["reporter 事件 → 分析报告"]
parseSSE --> conclusion["输出结论/数据解读"]
parseSSE --> finish["finish 事件 → 结束"]步骤 1 — 上传文件获取 fileId
python scripts/upload_file.py /path/to/data.xlsx| 项目 | 说明 |
|------|------|
| 接口 | POST /openapi/v2/copilot/parse |
| Content-Type | multipart/form-data |
| 功能 | 上传文件并解析各 Sheet 结构详情 |
#### 请求参数
| 参数 | 类型 | 说明 |
|------|------|------|
| file | File | 上传的数据文件(multipart 文件域) |
| fileName | String | 文件名(如 sales_data.xlsx) |
| tableConfigs[0].tableName | String | 表名(默认取文件名去后缀) |
| tableConfigs[0].tableType | String | excel 或 csv |
| isSave | String | 固定 false |
| fileId | String | 留空(首次上传) |
#### 输出内容
脚本会输出:上传进度提示、fileId、完整的响应 JSON(含文件结构详情、各 Sheet 的列名和类型)。
> 关键输出:从输出中提取 fileId 值,作为步骤 2 的第一个参数。
#### 错误处理
步骤 1 出现以下任一情况时,立即终止整个流程,不得继续执行步骤 2:
- 用户自动注册失败
- 文件上传失败(格式不支持、大小超限、服务端解析错误)
- 脚本以非零退出码结束
> 等待预期:文件问数通常需要 15~60 秒,复杂分析可能需要数分钟(最长 10 分钟超时)。建议提前告知用户耐心等待。
步骤 2 — 基于 fileId 发起流式问数
python scripts/file_stream_query.py <fileId> "用户的问题"示例:
python scripts/file_stream_query.py "abc123-def456" "各部门的销售额对比"| 项目 | 说明 |
|------|------|
| 接口 | POST /openapi/v2/smartq/queryByQuestionStreamByFile |
| Content-Type | application/json |
| 响应格式 | SSE (Server-Sent Events) 事件流 |
| 超时时间 | 10 分钟(600 秒) |
#### SSE 核心事件类型
| 事件类型 | 输出标记 | 处理方式 |
|----------|----------|----------|
| text | (直接输出) | 实时拼接输出文本内容 |
| reasoning | (直接输出) | 实时输出 AI 思考推理过程 |
| code | (静默收集) | 静默拼接 → 流结束后保存到 ~/.qbi/smartq-chat/output/ |
| result | [取数结果] | 解析结构化数据 → matplotlib 渲染图表 PNG |
| reporter | (直接输出) | 实时拼接分析报告文本 |
| html | [HTML 图表] | 仅保存原始 HTML 到 ~/.qbi/smartq-chat/output/ |
| html_result | [图表数据] | 解析结构化数据,渲染图表 |
| sql | [SQL] | 输出生成的 SQL 语句 |
| conclusion | [结论] | 输出最终分析结论 |
| summary | [数据解读] | 输出数据解读分析 |
| trace | [Trace] | 请求追踪 ID,问题反馈时提供此 ID 可加速排查 |
| finish | [完成] | 标记事件流结束(终止事件) |
| error | [错误] | 输出错误信息(终止事件) |
图表展示要求
重要:脚本输出中如果包含 !... 格式的图片引用,必须在答复中自然地展示图表。具体要求:
1. 先用 !标题 语法在答复的相应位置展示图表
2. 紧接图片下方标注图表文件路径
3. 不要在图表上方添加机械化引导文字
4. 如果有多张图表,按顺序逐一内联展示
5. 如果 matplotlib 不可用,基于 result 事件数据输出 Markdown 表格
结果总结要求
Agent 在答复用户时,必须基于脚本输出中的 conclusion(结论)和 summary(数据解读)内容,结合 reporter(分析报告)文本,对分析结果进行重新组织和总结。禁止向用户展示分析代码或代码文件路径(详见重要提示第 10 条)。
异常处理(必读)
脚本已内置以下三种异常的检测逻辑,会在控制台自动打印对应提示。Agent 应参考 references/error_messages.md 中的提示文案向用户传达,可根据上下文适当调整措辞,但核心信息(链接、操作建议)不可省略。检测到任一异常时,立即终止流程。
1. 无数据集权限
触发条件:数据集问数模式下,脚本输出包含「您当前没有可用的问数数据集」
检测位置:cube_resolver.py 权限查询
处理方式:提示用户没有可用数据集,建议尝试文件问数或开通服务。详细提示文案见 references/error_messages.md
附加规则:整个回复中只展示一次,不得重复。可自然询问用户是否改用文件问数。
2. 试用到期
触发条件:任何步骤的脚本输出或 API 响应中出现错误码 AE0579100004
检测位置:utils.py 中的 check_trial_expired()
处理方式:告知用户试用已到期,引导开通正式服务。详细提示文案见 references/error_messages.md
3. 数据文件解析失败
触发条件:文件问数模式下,脚本输出包含「数据文件解析失败」
检测位置:file_stream_query.py 中的 _on_error 方法
处理方式:提示用户检查文件格式和内容后重试。详细提示文案见 references/error_messages.md
关键接口汇总
| 接口 | 方法 | Content-Type | 模式 | 说明 |
|------|------|-------------|------|------|
| /openapi/v2/smartq/tableSearch | POST | application/json | A | 智能选表,返回匹配的 cubeId 列表 |
| /openapi/v2/smartq/query/llmCubeWithThemeList | GET | - | A | 查询用户有权限的问数数据集列表 |
| /openapi/v2/smartq/queryByQuestionStream | POST | application/json | A | 数据集问数流式接口,返回 SSE(olapResult 事件直接包含取数结果) |
| /openapi/v2/copilot/parse | POST | multipart/form-data | B | 上传文件并解析结构,返回 fileId |
| /openapi/v2/smartq/queryByQuestionStreamByFile | POST | application/json | B | 文件问数流式接口(SSE) |
| /openapi/v2/organization/user/queryByAccount | GET | - | 通用 | 通过 accountName 查询用户是否在组织中 |
| /openapi/v2/organization/user/addSuer | POST | application/json | 通用 | 添加用户到组织 |
重要提示
1. 文件问数必须走 API:详见顶部「核心约束」,禁止使用 pandas/openpyxl 等库直接分析用户上传的文件
2. 模式选择:根据用户是否上传了文件自动选择数据集问数或文件问数模式
3. 数据集问数无需 cubeId:用户进行数据集问数时,直接执行脚本,不传 --cube-id,脚本会自动智能选表。禁止要求用户提供 cubeId 或提示 cubeId 为必传参数
4. 文件问数必须分步执行:先执行步骤 1 上传文件获取 fileId,再执行步骤 2 传入 fileId 进行问数,不可跳过或合并
5. 错误处理:业务逻辑错误(权限不足、试用到期等)必须立即终止整个流程;网络类瞬态错误(超时、连接中断)可重试 1~2 次后终止。向用户清晰说明报错原因,并提醒:「如需进一步帮助,请联系 Quick BI 产品服务同学获取支持。」
6. 流式超时:默认超时 10 分钟(600 秒),复杂查询可能需要较长时间
7. 文件格式限制:仅支持 xls、xlsx、csv 格式,单文件不超过 10MB
8. userId 自动处理:user_token 未配置时,脚本启动时即自动基于设备唯一标识生成 accountId,通过组织用户接口检查并注册用户,注册成功后将 userId 回写到 ~/.qbi/config.yaml,后续调用不再重复注册
9. 图表展示:PNG 文件保存在 ~/.qbi/smartq-chat/output/ 目录中,脚本会以 Markdown 图片语法输出。Agent 在答复中应自然地内联展示图表
10. 禁止展示代码:文件问数中 code 事件的 Python 代码仅静默保存,禁止在答复中向用户展示代码内容或代码文件路径
Examples
Example 1: 数据集问数(自动智能选表)
Input:
用户: "销量最高的地区TOP3是哪些"Expected:
python scripts/smartq_stream_query.py "销量最高的地区TOP3是哪些"脚本自动智能选表匹配数据集,输出推理过程、图表 PNG 和分析结论。Agent 在答复中内联展示图表并总结结论。
Example 2: 文件问数(上传 Excel 分析)
Input:
用户: 上传了 sales_data.xlsx,提问"各部门的销售额对比"Expected:
# 步骤 1:上传文件获取 fileId
python scripts/upload_file.py /path/to/sales_data.xlsx
输出 fileId=abc123-def456
步骤 2:基于 fileId 发起问数
python scripts/file_stream_query.py "abc123-def456" "各部门的销售额对比"分两步执行,Agent 基于结论和数据解读总结分析结果,内联展示图表,不展示代码。