|
1 | | -# 🧠 SQLAgent |
| 1 | +# SQLAgent |
2 | 2 |
|
3 | | -A lightweight open-source **LLM agent with RAG (Retrieval-Augmented Generation)** capabilities, able to query both its internal model knowledge and a connected **MySQL database**. It allows users to ask natural-language questions that the agent translates into SQL queries and executes automatically. |
| 3 | +SQLAgent is a lightweight learning project that answers natural-language questions about a MySQL database by using an LLM to inspect schema, generate SQL, execute the query, and summarize the result. |
4 | 4 |
|
5 | | -## ⚠️ Disclaimer |
| 5 | +The project now supports two deployment modes: |
6 | 6 |
|
7 | | -This project is intended **for learning purposes only**. |
8 | | -It is **not designed or guaranteed for production use**. Any deployment or usage is done **at your own risk**. |
9 | | -The author assumes **no responsibility** for data loss, security issues, or system failures resulting from the use of this project. |
| 7 | +- Local Docker deployment with a locally hosted Ollama model. |
| 8 | +- Optional AWS deployment with Terraform, where Ollama runs on an EC2 instance. |
10 | 9 |
|
11 | | -## 🚀 Features |
12 | | -- 💡 **RAG-powered reasoning** — Combines generative LLM reasoning with real database retrieval. |
13 | | -- 🗄️ **MySQL integration** — Directly connects to your MySQL data. |
14 | | -- 🐳 **Dockerized setup** — One-command deployment with Docker Compose. |
15 | | -- 🌐 **HTTP API** — Simple API endpoint for natural-language queries. |
| 10 | +## Disclaimer |
16 | 11 |
|
17 | | -## 🧱 Requirements |
| 12 | +This project is intended for learning purposes only. |
| 13 | +It is not designed or guaranteed for production use. |
| 14 | +Any deployment or usage is done at your own risk. |
18 | 15 |
|
19 | | -- 🐳 Docker |
20 | | -- 💻 Basic terminal usage |
| 16 | +## Features |
21 | 17 |
|
22 | | -## 🛠️ Setup Instructions |
| 18 | +- Natural-language to SQL querying against a MySQL database. |
| 19 | +- Docker-based local development workflow. |
| 20 | +- Configurable Ollama endpoint, so the app can target either local or cloud-hosted Ollama. |
| 21 | +- Optional AWS infrastructure managed with Terraform. |
| 22 | +- Health endpoint at `GET /health` for deployment checks. |
| 23 | + |
| 24 | +## Requirements |
| 25 | + |
| 26 | +### Local mode |
| 27 | + |
| 28 | +- Docker |
| 29 | +- Docker Compose |
| 30 | + |
| 31 | +### AWS mode |
| 32 | + |
| 33 | +- Terraform 1.6+ |
| 34 | +- An AWS account |
| 35 | +- AWS CLI credentials configured locally |
| 36 | +- A Git-accessible copy of this repository |
| 37 | + |
| 38 | +## Local Deployment |
23 | 39 |
|
24 | 40 | ### 1. Add your database dump |
25 | | -Place your SQL dump file in `./db/db.sql`. |
26 | 41 |
|
27 | | -This file will be imported into the MySQL container during startup. |
| 42 | +For a quick test, copy the included example dump: |
28 | 43 |
|
29 | | -### 2. Set the MySQL password |
| 44 | +```bash |
| 45 | +cp db/db.sql.example db/db.sql |
| 46 | +``` |
30 | 47 |
|
31 | | -Store your MySQL root password in `./db/passwd.txt`. This value will be read by the container during startup. |
| 48 | +If you want to use your own data instead, place your SQL dump file at `./db/db.sql`. |
| 49 | + |
| 50 | +### 2. Set the MySQL password |
32 | 51 |
|
33 | | -Make sure that `./db/passwd.txt` contains *only* the password and **no trailing newline**. Many editors automatically append a newline at the end of the file, which will cause MySQL authentication to fail. |
| 52 | +Store the MySQL root password in `./db/passwd.txt`. |
34 | 53 |
|
35 | | -To safely create the file without adding a newline, run: |
| 54 | +Make sure the file contains only the password and no trailing newline: |
36 | 55 |
|
37 | 56 | ```bash |
38 | 57 | echo -n "your_password_here" > db/passwd.txt |
39 | 58 | ``` |
40 | 59 |
|
| 60 | +### 3. Optionally choose a local model |
41 | 61 |
|
42 | | -### 3. (Optional) Choose the model |
43 | | - |
44 | | -If you wish to change the default Ollama model (`gpt-oss:20b`), set the `OLLAMA_MODEL` environment variable: |
| 62 | +The default local model is `gpt-oss:20b`. |
45 | 63 |
|
46 | 64 | ```bash |
47 | 65 | export OLLAMA_MODEL=model_identifier |
48 | 66 | ``` |
49 | 67 |
|
50 | | -### 4. Start the agent |
51 | | - |
52 | | -Run the following command from the project root: |
| 68 | +### 4. Start the local stack |
53 | 69 |
|
54 | 70 | ```bash |
55 | 71 | docker compose up |
56 | 72 | ``` |
57 | 73 |
|
58 | | -This will start both the LLM agent and the MySQL database, automatically initializing the schema and data from `./db/db.sql`, and reading the MySQL password from `./db/passwd.txt`. |
| 74 | +This starts: |
59 | 75 |
|
60 | | -> ⚠️ **Note:** If this is your first run or the required Ollama models are not yet downloaded, please wait until the model download completes before sending any queries to the agent. |
| 76 | +- `ollama` for local model hosting |
| 77 | +- `db` for MySQL |
| 78 | +- `agent` for the FastAPI application |
61 | 79 |
|
62 | | -## 💬 Example Usage |
| 80 | +If the model is not downloaded yet, wait for the Ollama container to finish pulling it before sending queries. |
63 | 81 |
|
64 | | -After startup, query the agent via HTTP: |
| 82 | +### 5. Query the agent |
65 | 83 |
|
66 | 84 | ```bash |
67 | 85 | curl -G --data-urlencode "q=Your query" http://localhost:8000 |
68 | 86 | ``` |
69 | 87 |
|
70 | | -The agent will process your question, generate SQL queries, run it on the MySQL database, and return the result in natural language. |
| 88 | +### 6. Check service health |
71 | 89 |
|
72 | | -## 🧩 Project Structure |
| 90 | +```bash |
| 91 | +curl http://localhost:8000/health |
| 92 | +``` |
| 93 | + |
| 94 | +## AWS Deployment |
| 95 | + |
| 96 | +The AWS path is intentionally simple and cost-focused: |
| 97 | + |
| 98 | +- one EC2 instance |
| 99 | +- Docker Compose running `ollama`, `db`, and `agent` |
| 100 | +- Terraform-managed VPC, subnet, security group, IAM role, S3 bootstrap bucket, and SSM parameter |
| 101 | + |
| 102 | +This keeps the app easy to understand, but it is still not a production-grade architecture. |
| 103 | + |
| 104 | +### Important cost note |
| 105 | + |
| 106 | +Running Ollama in AWS is much heavier than calling a managed API. The default cloud deployment therefore uses a much smaller model than local mode: |
73 | 107 |
|
| 108 | +- Local default: `gpt-oss:20b` |
| 109 | +- AWS default: `qwen2.5:0.5b-instruct-q5_0` |
| 110 | + |
| 111 | +Even with that change, AWS free-tier compatibility depends on your AWS account type, your region, your storage usage, and how long the instance runs. Treat the provided Terraform defaults as "lowest practical cost", not "guaranteed free". |
| 112 | + |
| 113 | +### 1. Prepare Terraform variables |
| 114 | + |
| 115 | +Move into the Terraform directory: |
| 116 | + |
| 117 | +```bash |
| 118 | +cd terraform/aws |
74 | 119 | ``` |
| 120 | + |
| 121 | +Create a local variables file from the example: |
| 122 | + |
| 123 | +```bash |
| 124 | +cp terraform.tfvars.example terraform.tfvars |
| 125 | +``` |
| 126 | + |
| 127 | +Update at least these values: |
| 128 | + |
| 129 | +- `project_ref` |
| 130 | +- `db_dump_path` |
| 131 | +- `db_root_password` |
| 132 | +- `app_ingress_cidr_blocks` |
| 133 | + |
| 134 | +For a quick infrastructure smoke test, you can point `db_dump_path` at `../../db/db.sql.example`. |
| 135 | + |
| 136 | +### 2. Review the defaults |
| 137 | + |
| 138 | +The Terraform stack will: |
| 139 | + |
| 140 | +- upload your local SQL dump to a private S3 bucket |
| 141 | +- store the MySQL password in SSM Parameter Store |
| 142 | +- provision an EC2 instance |
| 143 | +- install Docker and Docker Compose on the instance |
| 144 | +- clone this repository on the instance |
| 145 | +- start the AWS-specific Compose stack from `compose.aws.yaml` |
| 146 | + |
| 147 | +### 3. Deploy |
| 148 | + |
| 149 | +```bash |
| 150 | +terraform init |
| 151 | +terraform plan |
| 152 | +terraform apply |
| 153 | +``` |
| 154 | + |
| 155 | +After `apply`, Terraform outputs the public API URL and an AWS Systems Manager command you can use to open a shell on the instance. |
| 156 | + |
| 157 | +### 4. Destroy when you are done |
| 158 | + |
| 159 | +```bash |
| 160 | +terraform destroy |
| 161 | +``` |
| 162 | + |
| 163 | +## Configuration |
| 164 | + |
| 165 | +### LLM configuration |
| 166 | + |
| 167 | +- `OLLAMA_MODEL`: model name to use |
| 168 | +- `OLLAMA_BASE_URL`: full Ollama base URL such as `http://ollama:11434` |
| 169 | + |
| 170 | +### Database configuration |
| 171 | + |
| 172 | +- `MYSQL_HOST` |
| 173 | +- `MYSQL_PORT` |
| 174 | +- `MYSQL_DATABASE` |
| 175 | +- `MYSQL_USER` |
| 176 | +- `MYSQL_ROOT_PASSWORD` |
| 177 | +- `MYSQL_ROOT_PASSWORD_FILE` |
| 178 | + |
| 179 | +The application prefers `MYSQL_ROOT_PASSWORD` if it is set, and otherwise reads from `MYSQL_ROOT_PASSWORD_FILE`. |
| 180 | + |
| 181 | +## Project Structure |
| 182 | + |
| 183 | +```text |
75 | 184 | . |
| 185 | +├── compose.yaml |
| 186 | +├── compose.aws.yaml |
76 | 187 | ├── db/ |
77 | | -│ ├── db.sql # Your MySQL dump file |
78 | | -│ └── passwd.txt # Your MySQL password |
79 | 188 | ├── ollama/ |
80 | | -│ ├── entrypoint.sh # Pulls the Ollama model before launching the agent |
81 | | -│ └── ollama/ # Ollama models assets |
82 | | -│ └── ... |
83 | | -├── src/ |
84 | | -│ └── sqlagent/ # Source code of the agent |
85 | | -│ └── ... |
86 | | -├── tests/ # Unit tests |
87 | | -│ └── ... |
88 | | -├── compose.yaml # Docker configuration |
89 | | -├── Dockerfile # Docker build instructions for the LLM agent |
90 | | -├── LICENSE # License file |
| 189 | +├── src/sqlagent/ |
| 190 | +├── terraform/aws/ |
| 191 | +├── tests/ |
| 192 | +├── Dockerfile |
91 | 193 | ├── README.md |
92 | 194 | ├── pyproject.toml |
93 | | -└── uv.lock # Lockfile generated by uv to ensure deterministic dependency versions |
| 195 | +└── uv.lock |
94 | 196 | ``` |
95 | 197 |
|
96 | | -## 📄 License |
| 198 | +## License |
97 | 199 |
|
98 | 200 | This project is distributed under the [MIT License](./LICENSE). |
0 commit comments