|
| 1 | +# AI插件开发技术问题答复 |
| 2 | + |
| 3 | +基于目前的代码实现(`ai_interface.go` 和 `remote_server.go`),以下是对各技术问题的答复: |
| 4 | + |
| 5 | +## 1. SQL生成与执行的实现方式 |
| 6 | + |
| 7 | +**推荐方案:方案A - 关注点分离** |
| 8 | + |
| 9 | +根据架构设计原则(AI插件不应该是特殊的),建议采用: |
| 10 | +- AI插件通过 `ai.generate` 方法生成SQL → 返回给主程序 → 主程序执行SQL |
| 11 | + |
| 12 | +**理由:** |
| 13 | +- 符合单一职责原则:AI插件负责生成,主程序或数据库插件负责执行 |
| 14 | +- 保持架构一致性:AI插件与其他插件使用相同的Query接口,不涉及数据库操作 |
| 15 | +- 代码实现(`remote_server.go:1790-1792`)显示只传递prompt和model,不包含数据库执行逻辑 |
| 16 | + |
| 17 | +**实现示例:** |
| 18 | +```go |
| 19 | +// AI插件只负责生成SQL |
| 20 | +query := map[string]string{ |
| 21 | + "method": "ai.generate", |
| 22 | + "model": "gpt-4", |
| 23 | + "prompt": "生成查询所有用户的SQL", |
| 24 | + "config": `{"output_format": "sql"}`, |
| 25 | +} |
| 26 | +// 返回: {"content": "SELECT * FROM users;", "success": "true"} |
| 27 | +``` |
| 28 | + |
| 29 | +## 2. 数据库连接信息传递 |
| 30 | + |
| 31 | +**答案:不应该由AI插件管理数据库连接** |
| 32 | + |
| 33 | +根据代码实现和架构原则: |
| 34 | +- AI插件不应该处理数据库连接 |
| 35 | +- 数据库连接应由专门的数据库插件或主程序管理 |
| 36 | +- AI插件只需要在prompt中包含必要的schema信息来生成准确的SQL |
| 37 | + |
| 38 | +**建议方案:** |
| 39 | +```go |
| 40 | +// 主程序提供schema信息,不传递连接信息 |
| 41 | +query := map[string]string{ |
| 42 | + "method": "ai.generate", |
| 43 | + "model": "gpt-4", |
| 44 | + "prompt": "基于以下schema生成SQL: tables: users(id, name, email), orders(id, user_id, amount)", |
| 45 | + "config": `{"db_dialect": "mysql"}`, // 只提供方言信息,不提供连接 |
| 46 | +} |
| 47 | +``` |
| 48 | + |
| 49 | +## 3. 本地模型优先的实现策略 |
| 50 | + |
| 51 | +**答案:在插件内部实现降级逻辑** |
| 52 | + |
| 53 | +根据代码实现(`ai_interface.go:33-34`),model参数是简单字符串: |
| 54 | +- 插件内部实现降级逻辑,对主程序透明 |
| 55 | +- model参数格式建议直接使用模型名:`"llama2"`、`"gpt-4"` |
| 56 | + |
| 57 | +**实现示例:** |
| 58 | +```go |
| 59 | +func (p *AIPlugin) Generate(model, prompt string, config map[string]interface{}) (string, error) { |
| 60 | + // 插件内部处理降级逻辑 |
| 61 | + if isLocalModel(model) { |
| 62 | + result, err := p.callOllama(model, prompt, config) |
| 63 | + if err == nil { |
| 64 | + return result, nil |
| 65 | + } |
| 66 | + // 本地失败,自动降级到在线服务 |
| 67 | + log.Printf("Local model failed, falling back to online: %v", err) |
| 68 | + } |
| 69 | + return p.callOpenAI(mapToOnlineModel(model), prompt, config) |
| 70 | +} |
| 71 | +``` |
| 72 | + |
| 73 | +## 4. 配置文件位置和格式 |
| 74 | + |
| 75 | +**需要进一步决定,但建议方案:** |
| 76 | + |
| 77 | +基于现有代码,配置可通过以下方式: |
| 78 | +1. **环境变量**(推荐用于敏感信息): |
| 79 | + ```bash |
| 80 | + OPENAI_API_KEY=xxx |
| 81 | + OLLAMA_ENDPOINT=http://localhost:11434 |
| 82 | + ``` |
| 83 | + |
| 84 | +2. **插件配置文件**(位于插件目录): |
| 85 | + ```yaml |
| 86 | + # ~/.atest/extensions/ai-plugin/config.yaml |
| 87 | + ai: |
| 88 | + ollama: |
| 89 | + endpoint: "http://localhost:11434" |
| 90 | + openai: |
| 91 | + api_key: "${OPENAI_API_KEY}" # 引用环境变量 |
| 92 | + ``` |
| 93 | +
|
| 94 | +3. **通过config参数动态传递**(用于运行时配置): |
| 95 | + ```json |
| 96 | + { |
| 97 | + "temperature": 0.7, |
| 98 | + "endpoint_override": "http://custom-ollama:11434" |
| 99 | + } |
| 100 | + ``` |
| 101 | + |
| 102 | +## 5. SQL执行结果的返回格式 |
| 103 | + |
| 104 | +**答案:不建议AI插件执行SQL** |
| 105 | + |
| 106 | +如果必须在AI插件中执行SQL(不推荐),返回格式应该是: |
| 107 | +```go |
| 108 | +// 通过content返回JSON格式的结果 |
| 109 | +result.Pairs["content"] = `{ |
| 110 | + "sql": "SELECT * FROM users", |
| 111 | + "rows": [ |
| 112 | + {"id": 1, "name": "Alice"}, |
| 113 | + {"id": 2, "name": "Bob"} |
| 114 | + ], |
| 115 | + "rowCount": 2 |
| 116 | +}` |
| 117 | + |
| 118 | +// 通过meta返回执行元数据 |
| 119 | +result.Pairs["meta"] = `{ |
| 120 | + "executionTime": "15ms", |
| 121 | + "affectedRows": 0, |
| 122 | + "queryType": "SELECT" |
| 123 | +}` |
| 124 | +``` |
| 125 | + |
| 126 | +## 总结建议 |
| 127 | + |
| 128 | +基于当前架构实现,强烈建议: |
| 129 | + |
| 130 | +1. **保持架构简洁**:AI插件只负责生成内容,不执行数据库操作 |
| 131 | +2. **使用现有接口**:通过Query(map[string]string)接口,不创建特殊方法 |
| 132 | +3. **插件内部处理降级**:本地/在线模型切换对主程序透明 |
| 133 | +4. **配置分层管理**:敏感信息用环境变量,其他配置用文件 |
| 134 | +5. **遵循单一职责**:AI生成是AI插件的职责,SQL执行是数据库组件的职责 |
| 135 | + |
| 136 | +这样的设计符合当前代码实现(`remote_server.go:1788-1801`)和架构原则,保持了系统的简洁性和可维护性。 |
0 commit comments