Skip to main content
Glama

Natural Language MySQL Query System

实验报告.md14.2 kB
# 《数据库实践》期末项目实验报告 ## 基于大模型与 MCP 服务的自然语言数据库查询系统 --- ## 1. 项目概述,包括代码结构说明 ### 1.1 项目概述 本项目实现了一个基于Model Context Protocol (MCP) 和大语言模型的自然语言数据库查询系统。系统采用分层架构设计,将自然语言处理、SQL生成、数据库操作和安全控制有机结合,为用户提供直观、安全、高效的数据库查询体验。 ### 1.2 技术架构 ``` ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ 用户界面层 │ │ AI代理层 │ │ 数据访问层 │ │ │ │ │ │ │ │ • Mastra Web UI │────│ • MySQL Agent │────│ • MCP Server │ │ • 自然语言输入 │ │ • Prompt工程 │ │ • MySQL Tools │ │ • 结果展示 │ │ • 多轮对话 │ │ • 安全控制 │ └─────────────────┘ └─────────────────┘ └─────────────────┘ ↓ ┌─────────────────┐ │ 数据库层 │ │ │ │ • MySQL数据库 │ │ • College数据库 │ │ • 事务管理 │ └─────────────────┘ ``` ### 1.3 代码结构详细说明 #### 1.3.1 MCP服务层 (`src/mysql-mcp/`) **主要职责**: 提供数据库操作的标准化接口,实现安全控制和功能增强 - **`index.js`**: MCP服务器主入口 - 初始化MCP服务器实例 - 注册所有工具集 - 配置服务器元信息和启动参数 - **`config/database.js`**: 数据库连接配置 - MySQL连接参数管理 - 环境变量集成 - 连接池配置 - **`tools/mysql-tools.js`**: 核心工具集实现 - `mysqlQueryTool`: SELECT查询执行器,包含安全过滤 - `mysqlSchemaTool`: 表结构信息获取器,支持按表过滤 - `mysqlDdlTool`: DDL语句生成器 - `paginationTool`: 分页缓存查询,会根据查询结果集大小自动分页 - `queryLogTool`: 查询日志记录和查看器 #### 1.3.2 AI代理层 (`src/mastra/`) **主要职责**: 处理自然语言输入,生成SQL查询,管理对话上下文 - **`index.ts`**: Mastra框架主配置 - 集成AI代理、存储、日志组件 - 配置LibSQL存储用于会话管理 - 设置Pino日志记录器 - **`agents/mysql-agent.ts`**: MySQL智能代理 - 集成通义千问模型 - 配置MCP工具集 - 设置记忆系统支持多轮对话 - **`model/index.ts`**: 模型配置 - 通义千问API配置 - 模型参数设置 - **`prompts/mysql-agent-prompt.ts`**: Prompt工程 - 详细的角色定义和任务说明 - Few-shot示例 - SQL生成规则和优化指导 #### 1.3.3 数据结构设计 **MCP工具标准化接口**: ```javascript { name: string, // 工具名称 description: string, // 工具描述 inputSchema: object, // 输入参数schema handler: async function // 异步处理函数 } ``` **查询日志数据结构**: ```javascript { timestamp: string, // 查询时间戳 sql: string, // 执行的SQL语句 executionTime: number, // 执行时间(ms) rowCount: number, // 返回行数 success: boolean // 执行状态 } ``` ### 1.4 核心流程 1. **用户输入**: 通过Mastra Web界面输入自然语言查询 2. **语言理解**: MySQL Agent分析用户意图 3. **Schema获取**: 通过MCP工具获取数据库表结构 4. **SQL生成**: 基于prompt模板和上下文生成SQL 5. **安全验证**: MCP服务器验证SQL安全性 6. **查询执行**: 执行SQL并记录日志 7. **结果返回**: 格式化结果并提供优化建议 --- ## 2. MCP 功能增强设计说明 ### 2.1 查询日志记录功能 #### 2.1.1 设计目标 - 记录所有SQL执行历史 - 提供查询性能分析数据 - 支持故障排查和审计 #### 2.1.2 实现方案 **日志存储结构**: ```javascript // logs/query_log.json { "logs": [ { "id": "uuid", "timestamp": "2024-01-15T10:30:00.000Z", "sql": "SELECT name FROM courses ORDER BY title, credits", "executionTime": 45, "rowCount": 25, "success": true, "error": null } ] } ``` **核心实现**: ```javascript export const queryLogTool = { name: "query_log", description: "查看和管理查询日志", inputSchema: { type: "object", properties: { action: { type: "string", enum: ["view", "clear"] }, limit: { type: "number", default: 10 }, }, }, async handler(args) { // 日志文件操作逻辑 // 支持查看最近查询、清除日志等操作 }, }; ``` ![](./assets/logs.png) ### 2.2 查询结果分页功能 #### 2.2.1 设计目标 - 优化大结果集的显示性能 - 提供用户友好的浏览体验 - 减少内存占用 #### 2.2.2 实现方案 **分页参数管理**: ```javascript export const paginationTool = { name: "paginated_query", description: "执行分页查询", inputSchema: { type: "object", properties: { sql: { type: "string" }, page: { type: "number", default: 1 }, pageSize: { type: "number", default: 20 }, }, }, async handler(args) { const offset = (args.page - 1) * args.pageSize; const paginatedSql = `${args.sql} LIMIT ${args.pageSize} OFFSET ${offset}`; // 执行分页查询并返回结果 }, }; ``` **分页信息响应**: ```javascript { "data": [...], // 当前页数据 "pagination": { "currentPage": 1, "pageSize": 20, "totalRows": 150, "totalPages": 8, "hasNext": true, "hasPrev": false } } ``` ![](./assets/page0.png) ![](./assets/page.png) ### 2.3 表结构简化输出功能 #### 2.3.1 设计目标 - 按需获取特定表的结构信息 - 减少不必要的数据传输 - 提供更精准的schema信息 #### 2.3.2 实现方案 **增强的Schema工具**: ```javascript export const mysqlSchemaTool = { name: "mysql_schema", description: "获取数据库表结构信息", inputSchema: { type: "object", properties: { tableName: { type: "string", description: "指定表名,为空则返回所有表", }, includeIndexes: { type: "boolean", default: false, description: "是否包含索引信息", }, }, }, async handler(args) { let query = ` SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, COLUMN_DEFAULT, EXTRA FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = ? `; if (args.tableName) { query += ` AND TABLE_NAME = ?`; } // 执行查询并格式化结果 }, }; ``` ![](./assets/schema-filter.png) --- ### 2.4 MCP 字段安全性设计 ![](./assets/protect.png) ## 3. 大模型交互流程与 prompt 优化方法 ### 3.1 大模型交互流程设计 #### 3.1.1 整体交互架构 ``` 用户输入 → Prompt构造 → 模型推理 → 工具调用 → 结果处理 → 响应生成 ↑ ↓ └──────────── 多轮对话上下文管理 ←─────────────────────────┘ ``` #### 3.1.2 详细交互流程 **第一阶段: 输入预处理** 1. 接收用户自然语言输入 2. 检查是否需要上下文信息 3. 构造完整的prompt上下文 **第二阶段: 模型推理** 1. 将处理后的prompt发送给通义千问模型 2. 模型分析用户意图并规划工具调用 3. 生成结构化的响应计划 **第三阶段: 工具执行** 1. 按序执行MCP工具调用 2. 处理工具返回结果 3. 异常处理和重试机制 **第四阶段: 结果综合** 1. 整合所有工具调用结果 2. 生成用户友好的响应 3. 提供SQL优化建议 ### 3.2 Prompt 工程优化 #### 3.2.1 分层Prompt设计 **系统角色定义层**: ``` 你是一个专业的MySQL数据库查询助手,能够将自然语言查询转换为精确的SQL语句。 ``` **任务指令层**: ``` ## 你的主要职责: 1. 理解用户的自然语言查询需求 2. 根据数据库schema生成准确的SQL查询语句 3. 执行查询并解释结果 4. 主动提供SQL优化建议 5. 在多轮对话中,自动利用历史上下文理解用户意图 ``` **规则约束层**: ``` ## SQL生成规则: - 只生成SELECT查询语句,确保数据安全 - 使用适当的JOIN语句连接相关表 - 严格避免复杂的子查询嵌套,优先使用JOIN - 生成SQL后,输出一句简要的SQL优化建议 ``` #### 3.2.2 Few-shot 示例设计 **示例结构**: ``` 用户: "列出所有课程的名称,按标题和学分排序" 助手: 我来为您查询课程信息。首先让我获取数据库结构,然后生成相应的SQL查询。 SQL: SELECT name FROM courses ORDER BY title, credits; 优化建议: 可为ORDER BY字段建立索引提升排序效率。 ``` **多轮对话示例**: ``` 用户: "查找选修了张三同学的所有课程名称" 助手: 正在为您查询张三同学的选课信息。 SQL: SELECT c.name FROM students s JOIN enrollments e ON s.id = e.student_id JOIN courses c ON e.course_id = c.id WHERE s.name = '张三'; 用户: "再帮我查下这些课程的学分" 助手: 根据您的上文需求,补充查询课程学分。 SQL: SELECT c.name, c.credits FROM students s JOIN enrollments e ON s.id = e.student_id JOIN courses c ON e.course_id = c.id WHERE s.name = '张三'; ``` #### 3.2.3 动态Prompt优化策略 **上下文感知优化**: - 自动保留最近10轮对话历史 - 智能识别代词和省略的表名/字段名 - 基于历史查询优化后续SQL生成 **性能导向优化**: - 内置SQL性能最佳实践 - 自动建议索引优化 - 避免N+1查询和复杂子查询 **安全优先优化**: - 强制只读查询约束 - 敏感字段自动过滤 - SQL注入模式识别 ![敏感操作](./assets/protect2.png) ![SQL安全性](./assets/protect3.png) ![SQL安全性2](./assets/protect4.png) ### 3.3 记忆系统与多轮对话 #### 3.3.1 记忆系统架构 ```javascript memory: new Memory({ storage: new LibSQLStore({ url: "file:../mastra.db", }), options: { lastMessages: 10, // 保留最近10条消息 threads: { generateTitle: true, // 自动生成对话标题 }, }, }); ``` ![](./assets/content-memo.png) #### 3.3.2 对话状态管理 **会话信息结构**: ```javascript { threadId: 'uuid', messages: [ { role: 'user', content: '用户输入', timestamp: '2024-01-15T10:30:00.000Z' }, { role: 'assistant', content: '助手回复', tools_called: ['mysql_schema', 'mysql_query'], timestamp: '2024-01-15T10:30:05.000Z' } ], context: { currentDatabase: 'college', recentTables: ['courses', 'students', 'enrollments'], userPreferences: { preferredPageSize: 20 } } } ``` ### 3.4 优化效果评估 #### 3.4.1 准确性提升策略 1. **Schema感知**: 在生成SQL前强制获取表结构 2. **约束驱动**: 通过严格的规则约束减少错误 3. **示例学习**: Few-shot示例提供标准化模板 4. **多轮纠错**: 支持在对话中修正和完善查询 #### 3.4.2 性能优化指导 1. **JOIN优化**: 优先使用JOIN替代子查询 2. **索引建议**: 自动分析查询并建议索引 3. **分页控制**: 大结果集自动分页处理 4. **查询复杂度控制**: 避免过度复杂的嵌套查询 --- ![](./assets/performance.png) ## 4. 测试案例(不少于 5 条)与结果展示 ### 4.1 List the names of all courses ordered by their titles and credits. ![](./assets/query1-1.png) ![](./assets/query1-2.png) ### 4.2 What is the title, credit value, and department name for courses with more than one prerequisite? (medium) ![](./assets/query2-1.png) ![](./assets/query2-2.png) ![](./assets/query2-3.png) ### 4.3 What are the names of students who have more than one advisor? (medium) ![](./assets/query3-1.png) ![](./assets/query3-2.png) ![](./assets/query3-3.png) ### 4.4 What are the titles of courses without prerequisites? (hard) ![](./assets/query4-1.png) ![](./assets/query4-2.png) ![](./assets/query4-3.png) ### 4.5 人数最多的前5门课程是?并显示课程名称、学分、以及授课教师姓名 ![](./assets/query5-1.png) ![](./assets/query5-2.png) ![](./assets/query5-3.png) ## 5. 困难与解决方案 - 回答质量 - 实验初期模型回答时,直接输出简单的md文档,可读性差,有时候会忘记调用工具,或者调用工具后突然显示对话结束。 - **解决方案** 通过优化prompt,给出回答问题的流程模板和对话样例,并对输出格式、生成的SQL的安全要求、回复语言加以限制。 - 模型选择 - 不同模型对MCP的运用能力不同,例如qwen-max会更倾向于自我猜测表结构,当遇到错误时容易逃避纠正错误和避免工具调用,而qwq等响应较慢,对工具调用支持不足。 - **解决方案** 经过反复比较,qwen-plus模型响应速度均衡,一般情况下能够连贯多次调用并自主纠正。 - 分页功能 - 大模型在查询得到结果前,是无法感知数据结果大小的,因此不能提前判断是否需要启用分页,会返回大量数据,造成响应缓慢,token消耗过快 - **解决方案** 设计自动分页和默认页大小,并启用缓存会话ID,在返回结果前过滤数据,辅助大模型在不同会话中呈现分页效果,并提供了多种分页查询函数 满足翻页,跳页功能。

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/floatDreamWithSong/mysql-mcp-server-qwen-manager'

If you have feedback or need assistance with the MCP directory API, please join our Discord server