1. 数据 Agent 的时代来了
2026 年,AI Agent 正在重塑我们和数据交互的方式。你不再需要手动写 SQL 查询或者摆弄 pandas DataFrame,只需要用自然语言告诉 AI Agent 你想要什么,它会自动理解意图、写代码、执行、给你结果。
但大多数 Agent 开发者面临同一个问题:Agent 的数据存在哪?
- 向量数据库?做 RAG 很好,做结构化分析不行。
- 传统数据库?太重了,不能嵌入,交互式查询太慢。
- 内存中的 Python 对象?几百 MB 就扛不住了。
DuckDB 完美解决这个问题。 嵌入式、零配置、列式存储、SQL 原生——它是 AI Agent 最理想的"数据大脑"。
| 需求 | DuckDB | 替代方案 |
|---|---|---|
| 可嵌入(无服务端) | ✅ 单个文件,无守护进程 | ❌ PostgreSQL/MySQL 需要服务器 |
| 快速 ad-hoc 查询 | ✅ 向量化执行引擎 | ❌ Pandas 到 GB 级就慢了 |
| SQL + Python 原生 | ✅ 双向无缝集成 | ⚠️ SQLite 没有向量化引擎 |
| MCP / 工具调用 | ✅ 任意 LLM 框架都兼容 | ⚠️ 多数数据库需要复杂连接器 |
| 可扩展到 100GB+ | ✅ 支持外部 Parquet 文件 | ❌ 内存 Python 做不到 |
接下来 30 分钟,你会用不到 100 行代码搭建一个完整可运行的 AI 数据 Agent。
2. 架构:AI Agent 如何用 DuckDB
┌─────────────────────────┐
│ 用户提问 │
│ "今年Q3销售额最高的 │
│ 城市是哪三个?" │
└─────────┬───────────────┘
▼
┌─────────────────────────┐
│ LLM(GPT-4o / DeepSeek / Claude) │
│ 1. 理解用户意图 │
│ 2. 生成 DuckDB SQL │
│ 3. 总结返回结果 │
└─────────┬───────────────┘
▼
┌─────────────────────────┐
│ Agent 执行层 │
│ ┌───────────────────┐ │
│ │ DuckDB 引擎 │ │
│ │ - 原始数据表 │ │
│ │ - S3上的Parquet │ │
│ │ - 查询缓存 │ │
│ └───────────────────┘ │
└─────────┬───────────────┘
▼
┌─────────────────────────┐
│ 返回结果 │
│ ✅ 表格 + 图表 │
│ ✅ 自然语言解读 │
│ ✅ 可操作洞察 │
└─────────────────────────┘
核心循环只有 5 步:
- 用户用自然语言提问
- LLM 翻译成 DuckDB SQL(带着表结构上下文)
- Agent 在 DuckDB 上执行 SQL
- DuckDB 毫秒级返回结果
- LLM 总结结果给用户
不需要 Web 服务器、不需要 Docker、不需要云服务——只需要 Python + DuckDB + 一个 API Key。
3. 30 分钟搭建 AI 数据 Agent
3.1 安装依赖
pip install duckdb openai # 或 anthropic, deepseek
就这一行。DuckDB 是一个 pip 安装,零配置。
3.2 加载数据
以电商数据为例。DuckDB 加载 1000 万行不到 2 秒:
import duckdb
# 创建内存数据库(或持久化:duckdb.connect('agent.duckdb'))
con = duckdb.connect()
# 加载数据——DuckDB 直接读 CSV/Parquet/JSON
con.execute("""
CREATE TABLE sales AS
SELECT * FROM read_csv_auto('ecommerce_10m.csv');
""")
# 查看结构
schema = con.execute("DESCRIBE sales").fetchdf()
print(schema)
输出:
column_name column_type
0 order_id BIGINT
1 customer_id VARCHAR
2 city VARCHAR
3 product VARCHAR
4 amount DOUBLE
5 quantity INTEGER
6 order_date DATE
7 category VARCHAR
3.3 搭建 Agent
核心逻辑就是一个简单的循环:获取表结构 → 生成 SQL → 执行 → 格式化返回。
import json
from openai import OpenAI
client = OpenAI(api_key="your-key-here")
def ask_agent(question: str) -> str:
"""用自然语言提问,获取 DuckDB 驱动的数据分析结果"""
# 第 1 步:获取数据库结构作为 LLM 上下文
schema_info = con.execute("""
SELECT table_name, column_name, data_type
FROM duckdb_columns()
ORDER BY table_name, column_name
""").fetchdf().to_string()
# 第 2 步:LLM 生成 DuckDB SQL
response = client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "system",
"content": f"""你是 DuckDB SQL 专家。
数据库结构:\n{schema_info}\n
把用户的问题转换成 DuckDB SQL。
只返回有效的 DuckDB SQL,不要解释。
善用 DuckDB 特有语法:
- read_csv_auto, read_parquet 读外部数据
- LIST, UNNEST, STRUCT 处理嵌套数据
- QUALIFY 做窗口函数过滤"""
}, {
"role": "user",
"content": question
}]
)
sql = response.choices[0].message.content.strip()
sql = sql.replace("```sql", "").replace("```", "").strip()
# 第 3 步:在 DuckDB 上执行
try:
result = con.execute(sql).fetchdf()
except Exception as e:
return f"SQL 错误:{e}\n生成的 SQL:{sql}"
# 第 4 步:LLM 总结结果
summary = client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "system",
"content": "用中文总结数据分析结果,简洁明了,突出关键洞察。"
}, {
"role": "user",
"content": f"问题:{question}\n\n结果:\n{result.head(20).to_string()}"
}]
)
return f"```sql\n{sql}\n```\n\n{summary.choices[0].message.content}"
3.4 试试看
print(ask_agent("电子产品里销售额最高的 3 个产品是什么?"))
输出:
SELECT product, SUM(amount) as revenue
FROM sales
WHERE category = 'Electronics'
GROUP BY product
ORDER BY revenue DESC
LIMIT 3;
📊 电子产品 Top 3:
- MacBook Pro 16" — $4,280,000(32.1%)
- Samsung 85" QLED — $2,150,000(16.1%)
- Sony WH-1000XM5 — $1,890,000(14.2%)
🔍 洞察:笔记本电脑占电子产品收入的近三分之一。可以考虑在 MacBook 订单中捆绑销售配件,提升客单价。
4. 进阶:用 Function Calling 集成 DuckDB
生产环境的 Agent 建议使用 LLM 的 Function Calling / 工具调用,而不是纯粹的提示词生成 SQL。这种方式自带安全检查、结构化参数和错误恢复。
4.1 定义 DuckDB 工具
TOOLS = [{
"type": "function",
"function": {
"name": "query_duckdb",
"description": "执行一个 DuckDB SQL 查询,返回 JSON 格式结果",
"parameters": {
"type": "object",
"properties": {
"sql": {
"type": "string",
"description": "要执行的 DuckDB SQL 查询"
}
},
"required": ["sql"]
}
}
}, {
"type": "function",
"function": {
"name": "describe_table",
"description": "获取表的列名和类型",
"parameters": {
"type": "object",
"properties": {
"table_name": {
"type": "string",
"description": "要查看的表名"
}
},
"required": ["table_name"]
}
}
}]
def execute_tool(name: str, args: dict):
if name == "query_duckdb":
df = con.execute(args["sql"]).fetchdf()
return df.head(100).to_json(orient="records")
elif name == "describe_table":
df = con.execute(f"DESCRIBE {args['table_name']}").fetchdf()
return df.to_json(orient="records")
4.2 Agent 主循环(带错误恢复)
def agent_with_tools(question: str, max_steps: int = 5):
messages = [
{"role": "system", "content": "你是一个 DuckDB 数据分析师。使用可用工具来回答问题。"},
{"role": "user", "content": question}
]
for step in range(max_steps):
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=TOOLS,
tool_choice="auto"
)
msg = response.choices[0].message
# 没有工具调用 → 最终答案
if not msg.tool_calls:
return msg.content
# 执行每个工具调用
for tc in msg.tool_calls:
args = json.loads(tc.function.arguments)
try:
result = execute_tool(tc.function.name, args)
messages.append({
"role": "tool",
"tool_call_id": tc.id,
"content": result
})
except Exception as e:
messages.append({
"role": "tool",
"tool_call_id": tc.id,
"content": f"错误:{e}"
})
messages.append(msg)
return "达到最大步骤数"
4.3 多步推理实战
result = agent_with_tools(
"按品类对比月度环比增长。找出哪些品类在下降,分析可能原因。"
)
print(result)
Agent 会这样执行:
- 第一次调用:
DESCRIBE sales了解列结构 - 第二次调用:
SELECT category, date_trunc('month', order_date) AS month, SUM(amount) AS revenue FROM sales GROUP BY ALL ORDER BY category, month - 第三次调用:分析结果,识别下降品类
- 最终回答:输出洞察和建议
这种链式推理方式比一次生成 SQL 准确得多。
5. MCP 模式:把 DuckDB 接入任何 AI Agent
Model Context Protocol(MCP) 让你可以用任何支持 MCP 的 Agent(Claude Desktop、Cursor、VS Code Copilot)直接连接 DuckDB。
5.1 DuckDB MCP Server
20 行代码搞定:
# duckdb_mcp_server.py
from mcp.server import Server
import duckdb
app = Server("duckdb-agent")
con = duckdb.connect(":memory:")
@app.tool()
def query(sql: str) -> str:
"""执行 DuckDB SQL 查询,返回文本格式结果"""
return con.execute(sql).fetchdf().to_string()
@app.tool()
def load_csv(path: str, table: str = "data") -> str:
"""加载 CSV 文件到 DuckDB 作为新表"""
con.execute(f"CREATE TABLE {table} AS SELECT * FROM read_csv_auto('{path}')")
info = con.execute(f"SELECT COUNT(*) AS rows FROM {table}").fetchdf()
cols = con.execute(f"SELECT COUNT(DISTINCT column_name) AS cols FROM duckdb_columns() WHERE table_name = '{table}'").fetchdf()
return f"已加载 {info['rows'][0]} 行,{cols['cols'][0]} 列"
if __name__ == "__main__":
app.run()
5.2 配置 MCP 客户端
加到 claude_desktop_config.json 或 .cursor/mcp.json:
{
"mcpServers": {
"duckdb": {
"command": "python",
"args": ["duckdb_mcp_server.py"],
"env": {}
}
}
}
然后你就可以直接对 Claude Desktop 说:“加载 my_sales.csv 到 DuckDB,然后告诉我哪些产品月度环比增长最大”——Agent 自动完成整个流程。
6. 性能对比:为什么 Agent 就该用 DuckDB
| 操作 | DuckDB | Pandas | SQLite |
|---|---|---|---|
| 加载 1000 万行 CSV | 0.8s | 8.2s | 5.1s |
| GROUP BY 100 万行 | 0.12s | 1.4s | 0.9s |
| 提取 100 万条 JSON | 0.3s | 6.7s | 不支持 |
| 远程 S3 Parquet 读取 | 原生支持 | 需要额外库 | 不支持 |
| 并发 Agent 查询 | 并行 Worker | GIL 阻塞 | 写锁定 |
| 嵌入式体积 | < 100MB | 看环境 | < 5MB |
一个需要以下能力的 AI Agent:
- 交互式回答问题
- 处理多种数据源(CSV、Parquet、JSON、S3)
- 从 KB 扩展到 100GB 不需要改配置
- 本地、Serverless、或在 Claude Desktop 里都能跑
DuckDB 是唯一同时满足这四条的数据引擎。
7. 真实应用场景
📊 自动化报表 Agent
连接 DuckDB 到销售数据库 → 说"生成这周的 KPI 报告" → Agent 自动查询、排版、发邮件。
🔍 客服数据分析 Agent
把客服工单加载到 DuckDB → 说"本月最常出现的 5 个问题是什么" → Agent 发现规律、给出解决方案建议。
📈 金融分析 Agent
DuckDB 读取 3 年交易 Parquet 文件 → 说"按地区展示季节性收入模式" → Agent 运行复杂窗口函数,输出图表数据。
🛠 运维故障 Agent
系统日志存入 DuckDB → 说"Q2 哪些服务故障最多" → Agent 关联时间戳、定位根因。
8. 下一步
- DuckDB + LangChain:用
SQLDatabaseChain对接 DuckDB,实现结构化的 Agent 工作流 - DuckDB + AutoGen:多 Agent 系统共享 DuckDB 作为统一数据层
- DuckDB + 向量搜索:用 DuckDB 的
vss扩展给 Agent 加上向量检索能力 - DuckDB + Delta Lake:直接读取 Delta Lake 表,构建湖仓一体 Agent 架构
AI Agent 领域正在快速进化。有一点是确定的:每个 Agent 都需要一个快速、可嵌入、SQL 原生的数据引擎——而 DuckDB 正是为此而生。
完整代码:https://github.com/pengzz9527/duckdb-ai-agent
更多内容:duckdblab.org
