在日常工作中,我们经常需要从 CSV 表格中提取信息 ------ 比如 "泰坦尼克号幸存者的平均年龄是多少?""某产品各地区销量排名如何?"。传统方式需要手动写 Pandas 代码或 Excel 公式,效率低下。本文将教你用 LangChain + 大模型快速搭建 CSV 数据问答系统,让你用自然语言直接查询 CSV 数据,无需编写一行代码。
一、核心思路:为什么用 SQL 连接 CSV?
搭建 CSV 问答系统的核心是让大模型 "读懂" 表格数据,主流方案有两种:
- 直接让大模型调用 Pandas 操作 CSV:灵活但风险高(可能执行恶意代码),权限难控制;
- 将 CSV 导入 SQL 数据库,让大模型用 SQL 查询:安全可控(限制 SQL 权限),查询逻辑清晰,且大模型对 SQL 的支持更成熟。
本文采用第二种方案,整体流程如下:CSV 文件 → 导入 SQLite 数据库 → 用 LangChain 创建 SQL 智能体 → 自然语言查询 → 返回答案
二、前置准备
- 环境依赖:安装必要的 Python 库
bash
运行
pip install langchain langchain-openai pandas sqlalchemy python-dotenv
- CSV 数据 :准备需要查询的 CSV 文件(本文以经典的
titanic.csv为例,包含乘客姓名、年龄、存活状态等信息); - API Key:获取 OpenAI API Key(需在 OpenAI 官网申请),用于调用大模型。
三、实战步骤:从 CSV 到问答系统
步骤 1:将 CSV 导入 SQLite 数据库
SQLite 是轻量级文件数据库,无需额外部署,适合快速验证。我们用 Pandas 读取 CSV,再导入 SQLite:
python
运行
# 导入依赖库
import pandas as pd
from sqlalchemy import create_engine
from langchain_community.utilities import SQLDatabase
# 1. 读取 CSV 文件
df = pd.read_csv("titanic.csv") # 替换为你的 CSV 文件路径
print("CSV 数据预览:")
print(df.head())
# 2. 创建 SQLite 数据库引擎(数据库文件会保存在本地,名为 titanic.db)
engine = create_engine("sqlite:///titanic.db")
# 3. 将 CSV 数据写入 SQLite 表(表名设为 titanic,与文件名一致)
df.to_sql("titanic", engine, index=False) # index=False 表示不导入索引列
# 4. 连接 SQL 数据库,供 LangChain 使用
db = SQLDatabase(engine)
# 验证连接:查看数据库中的表和表结构
print("\n数据库中的表:", db.get_tables_list())
print("\ntitanic 表结构:")
print(db.run("DESCRIBE titanic;")) # 或用 PRAGMA table_info(titanic);(SQLite 语法)
关键说明:
create_engine("sqlite:///titanic.db"):在当前目录创建titanic.db文件数据库,无需手动启动服务;df.to_sql(...):自动创建表并插入数据,若表已存在,可添加if_exists="replace"参数覆盖。
步骤 2:创建 SQL 智能体(核心步骤)
LangChain 提供了 create_sql_agent 工具,能自动让大模型:
- 分析自然语言问题 → 转化为 SQL 查询;
- 执行 SQL 并获取结果 → 用自然语言解释结果。
代码如下:
python
运行
# 导入依赖
from langchain_openai import ChatOpenAI
from langchain_community.agent_toolkits import create_sql_agent
from dotenv import load_dotenv
import os
# 加载环境变量(从 .env 文件读取 OpenAI API Key,避免硬编码)
load_dotenv()
openai_api_key = os.getenv("OPENAI_API_KEY")
# 1. 初始化大模型(选用 GPT-3.5-turbo,平衡成本和效果)
llm = ChatOpenAI(
model="gpt-3.5-turbo",
temperature=0, # 温度设为 0,保证查询逻辑稳定
api_key=openai_api_key
)
# 2. 创建 SQL 智能体
agent_executor = create_sql_agent(
llm=llm,
db=db,
agent_type="openai-tools", # 适配 OpenAI 函数调用的智能体类型
verbose=True # 开启详细日志,方便查看 SQL 生成过程
)
步骤 3:自然语言查询 CSV 数据
现在可以用中文或英文直接提问,智能体会自动处理查询逻辑:
python
运行
# 示例1:查询幸存者的平均年龄
result1 = agent_executor.invoke({"input": "幸存者的平均年龄是多少?"})
print("\n答案1:", result1["output"])
# 示例2:查询不同舱位(Pclass)的存活人数
result2 = agent_executor.invoke({"input": "一等舱、二等舱、三等舱的存活人数分别是多少?"})
print("\n答案2:", result2["output"])
# 示例3:查询女性幸存者的比例
result3 = agent_executor.invoke({"input": "女性乘客的存活率是多少?"})
print("\n答案3:", result3["output"])
执行日志示例 (开启 verbose=True 后可见):
plaintext
> Entering new AgentExecutor chain...
Invoking: `sql_db_query` with `{'query': 'SELECT AVG(Age) FROM titanic WHERE Survived = 1;'}`
SQL 执行结果:[(28.343689655172415,)]
> Finished chain.
答案1:幸存者的平均年龄约为 28.34 岁。
可以看到,智能体自动完成了 "自然语言 → SQL → 结果解释" 的全流程,无需人工干预。
四、进阶优化:让系统更实用
1. 支持多 CSV 文件
如果需要查询多个 CSV,只需将每个 CSV 导入不同的 SQL 表,智能体会自动识别表名和结构:
python
运行
# 导入第二个 CSV 文件(示例:sales.csv)
df_sales = pd.read_csv("sales.csv")
df_sales.to_sql("sales", engine, index=False) # 表名设为 sales
# 验证表是否存在
print("数据库中的表:", db.get_tables_list()) # 输出:['titanic', 'sales']
# 查询销售数据
result4 = agent_executor.invoke({"input": "2023年1月的总销售额是多少?"})
2. 限制 SQL 权限(安全加固)
为了防止大模型执行删除、修改数据的恶意 SQL,可通过 SQLDatabase 的参数限制权限:
python
运行
# 仅允许查询操作(SELECT),禁止 INSERT/UPDATE/DELETE
db = SQLDatabase(
engine,
include_tables=["titanic", "sales"], # 仅开放指定表
custom_sqlalchemy_url="sqlite:///titanic.db?mode=ro", # 只读模式
)
3. 处理复杂查询(如多表关联)
如果 CSV 之间存在关联关系(如 orders.csv 和 customers.csv),导入 SQL 后可通过 JOIN 查询,智能体同样能自动处理:
python
运行
# 示例:查询每个客户的订单数
result5 = agent_executor.invoke({"input": "每个客户的订单数量分别是多少?"})
五、常见问题排查
- CSV 编码错误 :读取 CSV 时若报错,添加
encoding参数(如pd.read_csv("titanic.csv", encoding="utf-8-sig")); - SQL 语法错误 :不同数据库语法有差异(如 SQLite 用
LIMIT,MySQL 用LIMIT,PostgreSQL 用LIMIT),LangChain 会自动适配; - 大模型无法识别表结构 :确保
db.get_tables_list()能正常输出表名,若不行,重新检查数据库连接; - API Key 无效 :确认
.env文件中OPENAI_API_KEY的值正确,且有足够的余额。
六、总结
本文用不到 50 行代码,实现了 "自然语言查询 CSV 数据" 的核心功能,关键亮点:
- 安全可控:通过 SQL 限制操作权限,避免恶意代码执行;
- 零代码门槛:用户无需懂 SQL 或 Python,用自然语言即可查询;
- 灵活扩展:支持多 CSV、复杂查询,可适配销售数据、用户数据等多种场景。
接下来你可以尝试:
- 替换为自己的 CSV 数据(如电商订单、运营报表);
- 集成到 Web 应用(用 FastAPI 封装接口);
- 改用开源大模型(如 Llama 3、Mistral),摆脱对 OpenAI 的依赖。
这个系统能大幅提升数据查询效率,尤其适合非技术人员快速获取 CSV 中的关键信息,赶紧动手试试吧!