Files
opsxdb/server/internal/ai/stub.go
T
logan 2c0bfafd8d 同步完整源码至远程:扁平化重构现状 + 未入库源文件
- 补入库:server/internal/db/dump.go、redis 分页/扫描预算测试、opsxdb-mcp main_test、
  packages/opsxdb-mcp package-lock、docs 审计与对比文档等 37 个新文件
- 含结构扁平化进行中的 80 处修改与 155 处旧结构删除(server/ src/ src-tauri/ 为当前有效源)
- 构建产物(bin/target/dist)与签名私钥仍按规则排除
2026-10-16 03:47:33 +08:00

99 lines
3.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package ai
import (
"context"
"fmt"
"strings"
)
// stubProvider 离线占位实现:未配置真实模型时的兜底,内容为字符串模板。
type stubProvider struct{}
func (stubProvider) Name() string { return "stub" }
func (stubProvider) Complete(_ context.Context, req ChatReq) (ChatRes, error) {
return chatStub(req), nil
}
func chatStub(req ChatReq) ChatRes {
driver := req.Driver
if driver == "" {
driver = "mysql"
}
db := req.Database
if db == "" {
db = "your_db"
}
sql := strings.TrimSpace(req.SQL)
prompt := strings.TrimSpace(req.Prompt)
switch strings.ToLower(req.Action) {
case "ask":
if prompt == "" {
prompt = "当前问题"
}
return ChatRes{Content: fmt.Sprintf("离线体验无法回答「%s」。请在设置 → 大模型配置 AI 供应商;如需试写 SQL,可切换为「生成 SQL」。", prompt)}
case "generate":
q := prompt
if q == "" {
q = "示例查询"
}
gen := fmt.Sprintf("-- 根据描述生成(%s / %s)\n-- 需求: %s\nSELECT *\nFROM `%s`.some_table\nWHERE 1=1\nLIMIT 100;", driver, db, q, db)
return ChatRes{
Content: fmt.Sprintf("已根据「%s」生成 SQL(stub,可替换为真实模型)。\n\n```sql\n%s\n```", q, gen),
SQL: gen,
}
case "explain":
if sql == "" {
sql = "SELECT 1"
}
return ChatRes{Content: fmt.Sprintf("## 解释 SQL\n\n```sql\n%s\n```\n\n- 这是一条在 **%s** 上执行的查询。\n- 建议检查 WHERE 条件是否走索引,避免 `SELECT *` 拉取过大结果集。\n- (stub 回复)", sql, driver)}
case "optimize":
opt := sql
if opt == "" {
opt = "SELECT id, name FROM users WHERE status = 1 LIMIT 100;"
} else if strings.Contains(strings.ToUpper(opt), "SELECT *") {
opt = strings.Replace(opt, "*", "id /* TODO: 显式列 */", 1)
}
opt = strings.TrimSpace(opt)
if !strings.Contains(strings.ToUpper(opt), "LIMIT") {
opt = opt + "\nLIMIT 100;"
}
return ChatRes{
Content: fmt.Sprintf("## 优化建议\n\n1. 避免不必要的全表扫描\n2. 显式列出列名\n3. 加合理 LIMIT\n\n```sql\n%s\n```", opt),
SQL: opt,
}
case "fix":
fixed := sql
if fixed == "" {
fixed = "SELECT 1 AS ok;"
}
msg := req.Error
if msg == "" {
msg = "未知错误"
}
return ChatRes{
Content: fmt.Sprintf("## 修复错误\n\n原错误:`%s`\n\n尝试修正后的 SQL:\n\n```sql\n%s\n```\n\n(stub:请结合真实报错继续调整)", msg, fixed),
SQL: fixed,
}
case "dialect":
out := sql
if out == "" {
out = "SELECT * FROM dual"
}
out = strings.ReplaceAll(out, "`", "\"")
return ChatRes{
Content: fmt.Sprintf("## 方言转换 → PostgreSQL 风格(示例)\n\n```sql\n%s\n```", out),
SQL: out,
}
case "sample":
sample := fmt.Sprintf("SELECT id, name, created_at\nFROM `%s`.users\nORDER BY id DESC\nLIMIT 20;", db)
return ChatRes{
Content: fmt.Sprintf("## 样例 SQL(%s)\n\n```sql\n%s\n```", driver, sample),
SQL: sample,
}
default:
return ChatRes{Content: "未知 AI 动作。可用:ask / generate / explain / optimize / fix / dialect / sample"}
}
}