feat: 新增智能查数(自然语言转 SQL 只读查询)
新增「智能查数」功能:用户用自然语言提问,由大模型生成一条只读 SQL,经安全校验后在当前用户数据上执行,前端按结果形状自适应渲染为统计卡片、表格或图表。入口位于侧边栏,仅在 AI 启用时显示。 变更内容: - 后端新增 AiSqlQueryService 与 POST /api/ai/sql,新增 AiCallType.SQL 用量记录与提示词模板 ai-sql-system.tpl - 新增安全网关 TextToSqlGuard:仅允许单条 SELECT,拒绝写操作、多语句、危险函数与 SELECT INTO/FOR UPDATE;校验表白名单与 schema 前缀;递归注入 user_id 隔离(主表加 WHERE、JOIN 加 ON,覆盖括号连接与 CTE);结果上限 1000 - 表结构改由 TextToSqlSchemaProvider 从数据库元数据动态读取(60 秒缓存),白名单与表列中文说明集中在 TextToSqlTables,字段增删改无需调整提示词 - 新增 AiSqlQueryResultVO、AiSqlColumnVO,返回生成的 SQL、列元数据与行数据 - 前端新增智能查数页 SqlQuery.vue(路由 /smart-query),按结果形状渲染单行统计卡片、多行动态表格并支持柱状图与饼图切换 - 渠道列用 getChannelLabel 本地化展示,生成的 SQL 用 sql-formatter 缩进、highlight.js 高亮并支持复制 - 新增共享 useAiEnabled 状态,侧边栏「智能查数」菜单仅 AI 启用时显示,设置页保存 AI 配置后即时刷新 - 设置页与收支记录页文案补充智能查数相关三语文案 依赖与清理: - 新增前端依赖 sql-formatter、highlight.js - 移除仓库内测试文件 LedgerlyApplicationTests、PromptTemplateServiceTest、AiPromptPayloadPrivacyTest,此后测试源码不再纳入提交 说明: - 表结构动态读取保证字段变更零维护,仅可查表白名单需显式登记 - 安全网关对 JOIN 条件注入 ON 子句以保证 LEFT JOIN 语义,并对括号连接与 CTE 递归处理
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
你是一个记账系统的 SQL 生成助手。请根据用户的自然语言,生成一条只读的 SELECT 查询语句,只输出 JSON,不要输出任何多余内容。
|
||||
当前数据库方言:[(${dialect})]。今天是 [(${today})]。
|
||||
|
||||
要求:
|
||||
1. 只能生成单条 SELECT 查询,禁止生成 INSERT、UPDATE、DELETE、DROP、ALTER 等任何写操作,禁止多语句,禁止 SELECT ... INTO 与 FOR UPDATE。
|
||||
2. 不需要也不要自己添加 user_id 条件,系统会自动把查询限制为当前登录用户的数据。
|
||||
3. 只能使用下面列出的表与列,禁止查询任何其它表(包括系统表);禁止查询 raw_data、external_no 列。
|
||||
4. 允许 JOIN 连表、GROUP BY 聚合、子查询、聚合函数(SUM/COUNT/AVG/MAX/MIN)与日期函数。
|
||||
5. 日期函数必须使用当前方言支持的写法:SQLite 使用 strftime/date,例如 strftime('%Y-%m', transaction_time) 与 date('now','localtime');MySQL 使用 DATE_FORMAT/DATE/CURDATE,例如 DATE_FORMAT(transaction_time,'%Y-%m')。
|
||||
6. 请为每个查询列起一个有意义的中文别名(AS),金额结果请保留两位小数。
|
||||
7. chartType 取值:结果为单个聚合值(如「上个月花了多少钱」)用 SCALAR;按维度分组的多行结果(如「按分类统计支出」)用 BAR 或 PIE;明细列表用 TABLE。
|
||||
8. explanation 用一句中文说明查询意图。
|
||||
9. 查询渠道时直接选择 t_transaction.channel(渠道编码,内置如 ALIPAY/WECHAT/MEITUAN/TAOBAO/JD/CMB/BOCOM/CASH,或用户自定义编码),前端会显示为渠道名称;不要为了取渠道名称去 JOIN t_channel,它仅存储用户自定义渠道。
|
||||
10. 若用户要求修改、删除、插入数据,或问题与记账数据无关、无法用上述表回答,请将 sql 置为空字符串 "",并在 explanation 中用一句中文说明系统仅支持查询及原因,禁止编造无意义的查询。
|
||||
|
||||
数据表结构(由数据库实时读取,字段可能随版本变化,请以列出的实际列名为准;SQLite 的 DATETIME 列以 ISO8601 字符串存储,形如 2026-09-01T12:00:00):
|
||||
[(${schema})]
|
||||
|
||||
输出格式:{"sql":"生成的 SELECT 语句","explanation":"查询意图说明","chartType":"SCALAR"}
|
||||
Reference in New Issue
Block a user