1. 页面概览
「智能查询」是 LightAIP 的核心 NLQ(自然语言查询)页面(action/web/src/views/ChatWindow.vue,约 1030 行)。用户用自然语言提问(如「查询订单总金额」),前端调用 /chat 接口,后端完成意图识别 → RAG 检索 → SQL 生成(Text2SQL)→ 安全执行,一次返回 SQL、查询结果、图表建议、RAG 上下文与 OAG 命中信息,以聊天气泡呈现。一句话总结:本页是把「问数据」变成「聊天」的入口,AI 回复里可展开看 SQL、结果表格/图表、反馈评分与证据上下文。
2. 访问入口
2.1 路由与菜单
路由 path: /chat、name: Chat、meta 标题「智能查询」、requiresAuth;顶部导航栏(App.vue)首个菜单「智能查询」即指向本页。源码 action/web/src/views/ChatWindow.vue。
2.2 认证与权限
需要登录(aip_token Bearer);401 时 aipClient 拦截器清 token 跳 /login。普通登录用户即可访问,无需管理员。
2.3 端口与 API 前缀
AIP 后端 18080;客户端 action/web/src/api/aipClient.js,baseURL /aip-api/v1。
3. 界面布局
左右分栏:左侧为主聊天区,右侧为 AI 自动化经营助手面板(固定 440px)。
┌────────────────────────────┬─────────────────┐
│ 智能查询(用自然语言提问…)[DSL 试调]│ AI 自动化经营助手 │
├────────────────────────────┤ (CopilotChat, │
│ 消息区:示例 chips + 气泡 │ 固定 440px) │
│ AI 气泡 = 意图/SQL/结果/反馈/RAG│ │
├────────────────────────────┤ │
│ 输入区 [输入自然语言查询…] [发送] │ │
└────────────────────────────┴─────────────────┘
- 页头:标题「智能查询」+ 副标题「用自然语言提问,AI 为您生成 SQL 并执行查询」+「DSL 试调」按钮。
- 消息区:空状态展示示例问题;用户气泡(蓝底右对齐)与 AI 气泡(白底左对齐)交替。
- AI 气泡内容:意图识别 → 本体语义(OAG)命中 → 消息文本 → SQL 查询语句 → 查询结果(图表/表格)→ 反馈评星 → RAG 上下文(均支持折叠)。
- 输入区:数据源下拉 + NLQ 输入框 + 发送按钮(下拉在输入框上方另起一行)。
4. 交互元素
| 控件 | 位置 | 含义与作用 |
|---|---|---|
| 示例问题 chips | 消息区空状态 | 「查询所有订单」等 3 个示例,点击即发送该问题 |
| 输入框「输入自然语言查询...」 | 底部输入区 | 输入 NLQ 问题;waiting 时禁用 |
| 数据源下拉「自动(按问题路由)」 | 底部输入区(输入框上方一行) | 选择本次查询的数据源:默认「自动」由后端按「问题点名表/列 → 元数据投票 → 默认源」三级路由(不传 data_source,行为与历史一致);选中具体活跃源则 POST /chat 附带 data_source 强制路由到该源,气泡内「数据源 xxx」回显即为该源。选项来自 GET /datasources 中 connection_config.active === true 的源(拉取失败静默降级为仅「自动」项);waiting 时禁用 |
| 按钮「发送」 | 输入区右侧 | 提交 POST /chat {query} 或 {query, data_source} |
| 按钮「DSL 试调」 | 页头右侧 | 基于最近一次成功查询结果调 /dsl/recommend-chart,展示推荐图表;无结果时禁用 |
| 可折叠标题(▶) | AI 气泡内 | 展开/收起「SQL 查询语句」「查询结果」「反馈」「RAG 检索上下文」 |
| 反馈星星(1-5) | AI 气泡「反馈」区 | 评星 → 选反馈类型 → 填备注 → 「提交」,调 POST /feedback |
| OAG 动作 chips + 「校验并执行」「查询状态」 | AI 气泡「本体语义(OAG)」区 | 对命中的可执行动作填对象类型 ID 与参数 JSON,执行或轮询运行状态 |
次要:QueryResultPanel 内置「图表/表格」Tab、图表类型下拉、下载图片、全屏查看。
5. 后端关联
5.1 API 客户端
action/web/src/api/aipClient.js:baseURL /aip-api/v1,timeout 30s;请求拦截器附 Bearer aip_token。
5.2 端点表
| 方法 | 路径 | 请求体 | 页面触发点 |
|---|---|---|---|
| POST | /chat | {query, data_source?} | 发送问题(data_source 可选:省略/空串 = 自动三级路由,与历史请求体一致;取值 = 强制路由到该数据源,不存在时返回 400 数据源不存在: xxx) |
| POST | /dsl/recommend-chart | {columns, rows, question} | DSL 试调 |
| POST | /feedback | {question, sql_query, rating, feedback_type, comment} | 反馈提交 |
| POST | /oag/actions/:name/execute | {action_name, object_type_id, params, idempotency_key, mode:"VALIDATE_AND_EXECUTE"} | OAG 动作执行 |
| GET | /oag/actions/runs/:id | — | 动作运行状态轮询 |
5.3 关键机制
- NLQ 链路:
/chat一次返回message / intent / confidence / data_source_name / sql_query / fix_attempts / query_result{columns,rows} / dsl / rag_context / oag等;fix_attempts > 0时气泡显示「已自动修复 N 次」徽标。 - OAG 动作闭环:
/chat响应oag.actions命中时展示可执行动作(action_name+ 对象类型名);执行请求带前端生成的幂等键idempotency_key(crypto.randomUUID,不可用时兜底genUUID);响应validation_result.result为 VALID/INVALID 时直接提示,否则视为异步提交并凭operation_id轮询GET /oag/actions/runs/:id。 - 安全注入:后端
/chat前先过安全护栏CheckChatInput(提示注入关键词命中或超长直接拒绝);执行 SQL 按数据源注入 RLS/CLS,响应回显rls_injected/cls_injected。 - OAG 鉴权透传:AIP 只做 Foundry 动作契约代理,请求的 Bearer JWT 透传给 Foundry,未配置 OAG/Foundry 时返回 404。
6. 权限与安全
- 全部接口走 aip_token Bearer(
protected分组)。 /chat有 AI 护栏输入检测(TAD-12 §5.1),命中注入关键词拒绝请求。- 反馈(
/feedback)由普通用户提交;统计/趋势接口挂管理员组。OAG 动作执行是 AIP → Foundry 的契约代理,透传当前用户 JWT 鉴权。
7. 常见问题与排错
- 查询返回「查询失败:...」:原因是
/chat调用异常(后端未启动、SQL 安全拒绝、数据源未就绪)。处理:确认后端 18080 已启动并看 Network 状态码;提示注入拦截时改写提问措辞。 - 图表/表格区无数据:原因是
query_result为 null 或 rows 为空,或该轮仅完成意图识别未执行 SQL。处理:确认数据源已导入元数据(demo SQLite 需 bootstrap 重建);改用表明确的问法重试。 - 「DSL 试调」按钮置灰:原因是
lastQueryResult为空(本轮还没有成功的查询结果)。处理:先执行一次查询再点试调。 - 操作任意按钮后跳回 /login:原因是 token 过期,aipClient 401 拦截。处理:重新登录;检查系统时钟与 SECRET_KEY 稳定性。
8. 已知缺陷与边界
- OAG 动作面板参数 JSON 由用户手填,前端仅校验是合法 JSON,业务合法性由后端 validate 决定。
- 右侧 Copilot 面板与左侧 NLQ 查询是两套独立对话(Automation Copilot 走 SSE)。
- DSL 试调基于「最近一次成功查询结果」,图表推荐为纯规则推荐(不调 LLM)。
注:会话仅内存、刷新即清空(对话消息无聊天记录持久化)已于 2026-09-06 修复(localStorage 按用户快照 + 恢复 + 新会话/清空入口)。
9. 2026-09-14 数据源选择器修订
- 新增数据源下拉:输入区新增「数据源选择器」,可在「自动(按问题路由)」与具体活跃源之间切换;仅在选中具体源时随
POST /chat发送data_source,选「自动」时不发送该字段(请求体与历史逐字节一致)。 - 选项来源与降级:
GET /datasources过滤connection_config.active === true得到选项(取不到 active 字段时兜底全部列出);接口异常时静默降级为仅「自动」项,不阻塞提问。选择结果仅存组件内部状态(不走 localStorage)。 - 错误口径:指定源不存在时后端返回 400
{"code":"INVALID_REQUEST","error":"数据源不存在: xxx"},气泡沿用既有err.response.data.error口径展示该文案。