在移动互联网时代,我们遵循 "Mobile First" (移动优先)的策略,优先开发手机端体验,再适配 PC 端,因为 80% 的用户都在使用手机。
但现在,时代变了。我们正在进入 "AI First" 的时代。
作为开发者,我们不再只是写死代码(Hard-coding),而是开始探索 "Vibe Coding" ------将自然语言与代码逻辑结合。今天,我们就通过一个 Python 实战案例,教大家如何用大模型(LLM)构建一个 Text-to-SQL 系统。哪怕你不懂 SQL 语法,也能通过"说人话"来查询数据库。
1. 核心理念:为什么需要 AI + SQL?
传统开发中,如果老板想问:"工程部门工资最高的人是谁?",程序员需要手写一条 SQL 语句:
SQL
SELECT name FROM employees WHERE department='工程' ORDER BY salary DESC LIMIT 1;
但在 AI First 的应用中,我们希望实现的是"数据库平权"------无论是小编、业务人员还是老板,都能通过自然语言直接与数据对话。
我们将使用以下技术栈:
- Python 3:胶水语言。
- SQLite:轻量级数据库(Python 内置)。
- OpenAI SDK (调用 DeepSeek) :利用大模型将自然语言"翻译"成 SQL。
2. 实战演练:由零开始
下面是一个基于 Python、SQLite 和 OpenAI SDK 接口(DeepSeek)的 Jupyter Notebook 实验。
第一步:搭建"数字员工"数据库
首先,我们需要一个存放数据的仓库。我们使用 SQLite 创建一个简单的 employees(员工)表。
Python
import sqlite3
# 连接到数据库文件(如果不存在会自动创建)
conn = sqlite3.connect("ai2sql.db")
cursor = conn.cursor()
# 创建表结构:包含ID、姓名、部门、薪资
cursor.execute("""
CREATE TABLE IF NOT EXISTS employees(
id INTEGER PRIMARY KEY,
name TEXT,
department TEXT,
salary INTEGER
)
""")
# 准备一些测试数据
sample_data = [
(6, "黄佳", "销售", 50000),
(7, "宁宁", "工程", 75000),
(8, "谦谦", "销售", 60000),
(9, "悦悦", "工程", 80000),
(10, "红红", "市场", 55000),
(11, "丹丹", "工程", 80000)
]
# 批量插入数据
cursor.executemany("INSERT INTO employees VALUES(?,?,?,?)", sample_data)
conn.commit() # 记得提交事务,否则数据不会保存!
代码解析:这里我们建立了一个包含姓名、部门和薪资的简单表格。
第二步:告诉 AI 你的"家底" (Context)
大模型虽然博学(Gemini/DeepSeek 都是博士级别),但它不知道你数据库里具体有哪些表。我们需要把**表结构(Schema)**提取出来作为"上下文"发给 AI。
Python
# 获取表结构信息
schema_info = cursor.execute("PRAGMA table_info(employees)").fetchall()
# 将结构格式化为 AI 能看懂的 SQL 定义字符串
# 结果类似:CREATE TABLE EMPLOYEES(id INTEGER, name TEXT...)
schema_str = "CREATE TABLE EMPLOYEES(\n" + \
"\n".join([f"{col[1]} {col[2]}" for col in schema_info]) + \
"\n)"
print(schema_str)
这一步至关重要。Text-to-SQL 的本质,就是给大模型提供 Context(表结构),让它利用推理能力生成 SQL。
第三步:AI 魔法师 (Prompt Engineering)
接下来,我们定义一个函数,把"用户的问题"和"表结构"打包发给大模型。这里我们使用 OpenAI 的 SDK 标准,但连接的是 DeepSeek 的模型。
Python
from openai import OpenAI
client = OpenAI(
api_key='YOUR_API_KEY', # 替换为你的 Key
base_url='https://api.deepseek.com/v1' # 指向 DeepSeek
)
def ask_ai_to_sql(query, schema):
prompt = f"""
这是一个数据库的Schema:
{schema}
根据这个Schema,请输出一个SQL查询来回答以下问题。
只输出SQL查询语句本身,不要使用任何Markdown格式,
不要包含反引号、代码块标记或额外说明。
问题:{query}
"""
response = client.chat.completions.create(
model="deepseek-chat",
messages=[{"role": "user", "content": prompt}],
temperature=0 # 设置为0,让 AI 回答更严谨确切
)
return response.choices[0].message.content
第四步:见证奇迹
现在,我们可以像聊天一样查询、增加、删除数据了:
查询数据
Python
question = "工程部门员工的姓名和工资是多少"
sql_query = ask_ai_to_sql(question, schema_str)
print(f"AI 生成的 SQL: {sql_query}")
# 输出: SELECT name, salary FROM EMPLOYEES WHERE department = '工程';
# 执行 AI 生成的语句
results = cursor.execute(sql_query).fetchall()
print(f"查询结果: {results}")
# 输出: [('宁宁', 75000), ('悦悦', 80000), ('丹丹', 80000)]
增加数据
python
question = "在销售部门增加一个新员工,姓名为张三,工资为45000"
sql_question = ask_deepseek(question, schema_str)
results = cursor.execute(sql_query)
conn.commit()
删除数据
python
question = "删除市场部门的黄仁勋"
sql_query = ask_deepseek(question, schema_str)
print(sql_query)
cursor.execute(sql_query)
conn.commit()
注意:在非查询操作中,每次执行完都需要
commit,而查询操作不需要
3. 避坑指南:小白常遇到的 database is locked
在实际操作中,很多新手会遇到 OperationalError: database is locked 的报错。
原因是什么?
SQLite 是一个基于文件的数据库。当一个进程或连接正在"写"数据(比如插入或删除),但还没有 commit()(提交)或者关闭连接时,数据库会被"锁住"。此时如果试图发起新的操作,就会报错。
如何解决?
- 及时 Commit :每次
execute修改数据的语句(INSERT/UPDATE/DELETE)后,立刻执行conn.commit()。 - 管理连接:确保不要在同一个脚本中频繁开启多个连接而不关闭。
- 单线程原则:SQLite 对多线程并发写入支持有限,初学者尽量在一个流程内完成操作。
4. 展望:Agentic AI 的未来
今天的案例只是一个开始。既然 AI 能帮我们写 SQL 查询数据库,它自然也能帮我们在现实世界"执行任务"。
这就引出了 Agent(智能体) 的概念。
想象一下未来的场景:
你对 AI 说:"帮我点一杯奶茶,要少糖热的。你去美团、抖音、淘宝比个价,用上所有优惠券,在最便宜的那家下单。"
这背后的逻辑与我们的 Text-to-SQL 是一样的:
- 意图识别:AI 听懂你要点奶茶。
- 工具调用:AI 像调用 SQL 一样,去调用美团、抖音的 API 接口。
- 决策执行:AI 比较价格数据,执行"下单"操作。
从 Mobile First 到 AI First,我们不再是点击屏幕上的按钮,而是通过自然语言,调度背后的万千服务。
总结
通过 Python 几十行代码,我们打破了 SQL 语言的壁垒。这不仅是技术的进步,更是开发思维的转变。希望这篇教程能让你对 AI 编程(Vibe Coding)有更直观的感受。
下一步建议: 动手把上面的代码跑一遍!如果你在配置 API 环境时遇到问题,欢迎在评论区留言。