538 lines
12 KiB
Markdown
538 lines
12 KiB
Markdown
# MySQL Agent 请求调用示例
|
|
|
|
## 服务信息
|
|
- **服务名称**: MySQL AI Agent
|
|
- **版本**: 1.0.0
|
|
- **框架**: LangChain + OpenAI
|
|
- **默认端口**: 8080
|
|
|
|
## 概述
|
|
MySQL AI Agent 使用 LangChain 和自然语言处理技术,允许用户使用自然语言查询 MySQL 数据库。
|
|
|
|
---
|
|
|
|
## API 端点
|
|
|
|
### 1. 健康检查
|
|
**端点**: `GET /health`
|
|
|
|
**请求示例** (curl):
|
|
```bash
|
|
curl http://localhost:8080/health
|
|
```
|
|
|
|
**响应示例**:
|
|
```json
|
|
{
|
|
"status": "healthy",
|
|
"pod_name": "mysql-agent",
|
|
"template_type": "mysql_agent",
|
|
"database_connected": true,
|
|
"database_info": "localhost:3306/mydb"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 2. 服务信息
|
|
**端点**: `GET /`
|
|
|
|
**请求示例** (curl):
|
|
```bash
|
|
curl http://localhost:8080/
|
|
```
|
|
|
|
**响应示例**:
|
|
```json
|
|
{
|
|
"name": "MySQL AI Agent",
|
|
"version": "1.0.0",
|
|
"database": "localhost:3306/mydb",
|
|
"endpoints": {
|
|
"health": "/health",
|
|
"query": "/query"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 3. 自然语言查询
|
|
**端点**: `POST /query`
|
|
|
|
使用自然语言查询 MySQL 数据库。
|
|
|
|
**请求体**:
|
|
```json
|
|
{
|
|
"query": "显示所有用户",
|
|
"openai_api_key": "sk-xxx",
|
|
"user_id": "user123",
|
|
"model": "gpt-3.5-turbo"
|
|
}
|
|
```
|
|
|
|
**请求示例** (curl):
|
|
```bash
|
|
curl -X POST http://localhost:8080/query \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"query": "有多少个用户?",
|
|
"openai_api_key": "sk-xxx",
|
|
"user_id": "user123"
|
|
}'
|
|
```
|
|
|
|
**请求示例** (Python):
|
|
```python
|
|
import requests
|
|
|
|
query_data = {
|
|
"query": "显示年龄大于30的所有用户",
|
|
"openai_api_key": "sk-xxx",
|
|
"user_id": "user123",
|
|
"model": "gpt-3.5-turbo"
|
|
}
|
|
|
|
response = requests.post(
|
|
"http://localhost:8080/query",
|
|
json=query_data
|
|
)
|
|
result = response.json()
|
|
|
|
print(f"Query: {result['query']}")
|
|
print(f"Result: {result['result']}")
|
|
print(f"Success: {result['success']}")
|
|
print(f"Timestamp: {result['timestamp']}")
|
|
```
|
|
|
|
**响应示例**:
|
|
```json
|
|
{
|
|
"query": "有多少个用户?",
|
|
"result": "数据库中有 150 个用户",
|
|
"success": true,
|
|
"timestamp": "2026-01-15T10:30:00.000Z"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 查询示例
|
|
|
|
### 基础查询:
|
|
```python
|
|
queries = [
|
|
"显示所有用户",
|
|
"有多少个用户?",
|
|
"列出所有表",
|
|
"显示 users 表的结构",
|
|
"查看最近注册的 10 个用户"
|
|
]
|
|
```
|
|
|
|
### 统计查询:
|
|
```python
|
|
queries = [
|
|
"每个部门有多少员工?",
|
|
"统计每个城市的用户数量",
|
|
"计算订单总金额",
|
|
"找出销售额最高的产品",
|
|
"显示月度销售趋势"
|
|
]
|
|
```
|
|
|
|
### 条件查询:
|
|
```python
|
|
queries = [
|
|
"显示年龄大于30的用户",
|
|
"查找北京的所有客户",
|
|
"列出未支付的订单",
|
|
"显示价格在100到500之间的产品",
|
|
"找出最近一周的订单"
|
|
]
|
|
```
|
|
|
|
### 关联查询:
|
|
```python
|
|
queries = [
|
|
"显示每个用户的订单数量",
|
|
"列出购买了特定产品的用户",
|
|
"显示每个部门的平均工资",
|
|
"查找有订单但未支付的用户"
|
|
]
|
|
```
|
|
|
|
---
|
|
|
|
## 完整使用示例
|
|
|
|
### Python 客户端:
|
|
|
|
```python
|
|
import requests
|
|
from typing import Optional, Dict, Any
|
|
|
|
class MySQLAgentClient:
|
|
"""MySQL Agent 客户端"""
|
|
|
|
def __init__(self, base_url: str, openai_api_key: str):
|
|
self.base_url = base_url.rstrip('/')
|
|
self.openai_api_key = openai_api_key
|
|
|
|
def health_check(self) -> Dict[str, Any]:
|
|
"""健康检查"""
|
|
response = requests.get(f"{self.base_url}/health")
|
|
return response.json()
|
|
|
|
def get_info(self) -> Dict[str, Any]:
|
|
"""获取服务信息"""
|
|
response = requests.get(f"{self.base_url}/")
|
|
return response.json()
|
|
|
|
def query(
|
|
self,
|
|
query: str,
|
|
user_id: Optional[str] = None,
|
|
model: str = "gpt-3.5-turbo"
|
|
) -> Dict[str, Any]:
|
|
"""执行自然语言查询"""
|
|
data = {
|
|
"query": query,
|
|
"openai_api_key": self.openai_api_key,
|
|
"user_id": user_id,
|
|
"model": model
|
|
}
|
|
response = requests.post(f"{self.base_url}/query", json=data)
|
|
return response.json()
|
|
|
|
|
|
# 使用示例
|
|
client = MySQLAgentClient(
|
|
base_url="http://localhost:8080",
|
|
openai_api_key="sk-xxx"
|
|
)
|
|
|
|
# 1. 健康检查
|
|
health = client.health_check()
|
|
print(f"Database Connected: {health['database_connected']}")
|
|
print(f"Database Info: {health['database_info']}")
|
|
|
|
# 2. 执行查询
|
|
queries = [
|
|
"显示所有表",
|
|
"users 表有多少条记录?",
|
|
"显示最近注册的5个用户",
|
|
"统计每个城市的用户数量",
|
|
"找出年龄最大的用户"
|
|
]
|
|
|
|
for query in queries:
|
|
print(f"\n{'='*60}")
|
|
print(f"Query: {query}")
|
|
print('='*60)
|
|
|
|
result = client.query(query, user_id="user123")
|
|
|
|
if result['success']:
|
|
print(f"Result:\n{result['result']}")
|
|
else:
|
|
print(f"Error: Query failed")
|
|
```
|
|
|
|
---
|
|
|
|
### 交互式查询工具:
|
|
|
|
```python
|
|
import requests
|
|
from prompt_toolkit import prompt
|
|
from prompt_toolkit.history import InMemoryHistory
|
|
from rich.console import Console
|
|
from rich.table import Table
|
|
|
|
class InteractiveMySQLClient:
|
|
"""交互式 MySQL 查询客户端"""
|
|
|
|
def __init__(self, base_url: str, openai_api_key: str):
|
|
self.base_url = base_url
|
|
self.openai_api_key = openai_api_key
|
|
self.console = Console()
|
|
self.history = InMemoryHistory()
|
|
|
|
def query(self, query_text: str) -> Dict:
|
|
"""执行查询"""
|
|
response = requests.post(
|
|
f"{self.base_url}/query",
|
|
json={
|
|
"query": query_text,
|
|
"openai_api_key": self.openai_api_key
|
|
}
|
|
)
|
|
return response.json()
|
|
|
|
def display_result(self, result: Dict):
|
|
"""显示查询结果"""
|
|
if result['success']:
|
|
self.console.print(f"[green]✓ Success[/green]")
|
|
self.console.print(f"\n{result['result']}\n")
|
|
else:
|
|
self.console.print(f"[red]✗ Failed[/red]")
|
|
|
|
def run(self):
|
|
"""运行交互式会话"""
|
|
self.console.print("[bold blue]MySQL AI Agent - Interactive Client[/bold blue]")
|
|
self.console.print("Type 'exit' or 'quit' to end session\n")
|
|
|
|
while True:
|
|
try:
|
|
# 获取用户输入
|
|
query_text = prompt(
|
|
"mysql> ",
|
|
history=self.history
|
|
)
|
|
|
|
# 检查退出命令
|
|
if query_text.lower() in ['exit', 'quit']:
|
|
break
|
|
|
|
if not query_text.strip():
|
|
continue
|
|
|
|
# 执行查询
|
|
result = self.query(query_text)
|
|
self.display_result(result)
|
|
|
|
except KeyboardInterrupt:
|
|
continue
|
|
except EOFError:
|
|
break
|
|
|
|
self.console.print("\n[yellow]Goodbye![/yellow]")
|
|
|
|
|
|
# 使用交互式客户端
|
|
if __name__ == "__main__":
|
|
client = InteractiveMySQLClient(
|
|
base_url="http://localhost:8080",
|
|
openai_api_key="sk-xxx"
|
|
)
|
|
client.run()
|
|
```
|
|
|
|
---
|
|
|
|
### 数据分析工具:
|
|
|
|
```python
|
|
import requests
|
|
import pandas as pd
|
|
import matplotlib.pyplot as plt
|
|
from typing import List, Dict
|
|
|
|
class MySQLDataAnalyzer:
|
|
"""MySQL 数据分析工具"""
|
|
|
|
def __init__(self, base_url: str, openai_api_key: str):
|
|
self.base_url = base_url
|
|
self.openai_api_key = openai_api_key
|
|
|
|
def query(self, query: str) -> str:
|
|
"""执行查询"""
|
|
response = requests.post(
|
|
f"{self.base_url}/query",
|
|
json={
|
|
"query": query,
|
|
"openai_api_key": self.openai_api_key
|
|
}
|
|
)
|
|
result = response.json()
|
|
return result.get('result', '') if result.get('success') else ''
|
|
|
|
def get_statistics(self, table: str, column: str) -> Dict:
|
|
"""获取列的统计信息"""
|
|
queries = {
|
|
"count": f"{table} 表的 {column} 列有多少条记录?",
|
|
"avg": f"{table} 表的 {column} 列的平均值是多少?",
|
|
"min": f"{table} 表的 {column} 列的最小值是多少?",
|
|
"max": f"{table} 表的 {column} 列的最大值是多少?"
|
|
}
|
|
|
|
stats = {}
|
|
for stat_name, query in queries.items():
|
|
result = self.query(query)
|
|
stats[stat_name] = result
|
|
|
|
return stats
|
|
|
|
def get_distribution(self, table: str, column: str) -> Dict:
|
|
"""获取数据分布"""
|
|
query = f"统计 {table} 表中 {column} 列的值分布"
|
|
result = self.query(query)
|
|
return {"distribution": result}
|
|
|
|
|
|
# 使用示例
|
|
analyzer = MySQLDataAnalyzer(
|
|
base_url="http://localhost:8080",
|
|
openai_api_key="sk-xxx"
|
|
)
|
|
|
|
# 获取统计信息
|
|
stats = analyzer.get_statistics("users", "age")
|
|
print("Statistics:")
|
|
for stat, value in stats.items():
|
|
print(f" {stat}: {value}")
|
|
|
|
# 获取分布
|
|
distribution = analyzer.get_distribution("users", "city")
|
|
print(f"\nDistribution: {distribution}")
|
|
```
|
|
|
|
---
|
|
|
|
### 批量查询和导出:
|
|
|
|
```python
|
|
import requests
|
|
import csv
|
|
from datetime import datetime
|
|
|
|
class MySQLBatchExporter:
|
|
"""批量查询和导出工具"""
|
|
|
|
def __init__(self, base_url: str, openai_api_key: str):
|
|
self.base_url = base_url
|
|
self.openai_api_key = openai_api_key
|
|
|
|
def execute_queries(self, queries: List[str]) -> List[Dict]:
|
|
"""批量执行查询"""
|
|
results = []
|
|
|
|
for query in queries:
|
|
response = requests.post(
|
|
f"{self.base_url}/query",
|
|
json={
|
|
"query": query,
|
|
"openai_api_key": self.openai_api_key
|
|
}
|
|
)
|
|
result = response.json()
|
|
results.append({
|
|
"query": query,
|
|
"result": result.get('result', ''),
|
|
"success": result.get('success', False),
|
|
"timestamp": result.get('timestamp', '')
|
|
})
|
|
|
|
return results
|
|
|
|
def export_to_csv(self, results: List[Dict], filename: str):
|
|
"""导出结果到 CSV"""
|
|
with open(filename, 'w', newline='', encoding='utf-8') as f:
|
|
writer = csv.DictWriter(f, fieldnames=['query', 'result', 'success', 'timestamp'])
|
|
writer.writeheader()
|
|
writer.writerows(results)
|
|
|
|
print(f"Results exported to {filename}")
|
|
|
|
|
|
# 使用示例
|
|
exporter = MySQLBatchExporter(
|
|
base_url="http://localhost:8080",
|
|
openai_api_key="sk-xxx"
|
|
)
|
|
|
|
# 批量查询
|
|
queries = [
|
|
"统计总用户数",
|
|
"统计每个城市的用户数",
|
|
"显示最近一周的注册用户数",
|
|
"计算平均年龄",
|
|
"显示活跃用户占比"
|
|
]
|
|
|
|
results = exporter.execute_queries(queries)
|
|
|
|
# 导出结果
|
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
exporter.export_to_csv(results, f"mysql_queries_{timestamp}.csv")
|
|
|
|
# 打印摘要
|
|
successful = sum(1 for r in results if r['success'])
|
|
print(f"\nSummary: {successful}/{len(queries)} queries successful")
|
|
```
|
|
|
|
---
|
|
|
|
## 环境变量配置
|
|
|
|
```bash
|
|
# 服务配置
|
|
export SERVICE_HOST="0.0.0.0"
|
|
export SERVICE_PORT="8080"
|
|
export POD_NAME="mysql-agent"
|
|
export TEMPLATE_TYPE="mysql_agent"
|
|
|
|
# MySQL 数据库配置
|
|
export MYSQL_HOST="localhost"
|
|
export MYSQL_PORT="3306"
|
|
export MYSQL_USER="root"
|
|
export MYSQL_PASSWORD="your-password"
|
|
export MYSQL_DATABASE="mydb"
|
|
|
|
# 启动服务
|
|
python mysql_agent.py
|
|
```
|
|
|
|
---
|
|
|
|
## Docker Compose 示例
|
|
|
|
```yaml
|
|
version: '3.8'
|
|
|
|
services:
|
|
mysql:
|
|
image: mysql:8.0
|
|
environment:
|
|
MYSQL_ROOT_PASSWORD: rootpassword
|
|
MYSQL_DATABASE: testdb
|
|
ports:
|
|
- "3306:3306"
|
|
volumes:
|
|
- mysql_data:/var/lib/mysql
|
|
|
|
mysql-agent:
|
|
build:
|
|
context: .
|
|
dockerfile: mysql_agent.Dockerfile
|
|
environment:
|
|
MYSQL_HOST: mysql
|
|
MYSQL_PORT: 3306
|
|
MYSQL_USER: root
|
|
MYSQL_PASSWORD: rootpassword
|
|
MYSQL_DATABASE: testdb
|
|
SERVICE_PORT: 8080
|
|
ports:
|
|
- "8080:8080"
|
|
depends_on:
|
|
- mysql
|
|
|
|
volumes:
|
|
mysql_data:
|
|
```
|
|
|
|
---
|
|
|
|
## 注意事项
|
|
|
|
1. **API Key**: OpenAI API key 从请求传入,确保安全
|
|
2. **数据库连接**: 需要正确配置数据库连接参数
|
|
3. **权限控制**: 建议使用只读用户进行查询
|
|
4. **查询限制**: 设置合理的查询超时和结果限制
|
|
5. **错误处理**: 检查 success 字段确认查询是否成功
|
|
6. **SQL注入**: Agent 会自动处理,但仍需注意安全
|
|
7. **成本控制**: 监控 OpenAI API 使用量
|
|
8. **模型选择**: gpt-4 更准确但成本更高,gpt-3.5-turbo 更经济
|