5 分钟搭建 CSV 数据问答系统:LangChain + LLM 实战教程

在日常工作中,我们经常需要从 CSV 表格中提取信息 ------ 比如 "泰坦尼克号幸存者的平均年龄是多少?""某产品各地区销量排名如何?"。传统方式需要手动写 Pandas 代码或 Excel 公式,效率低下。本文将教你用 LangChain + 大模型快速搭建 CSV 数据问答系统,让你用自然语言直接查询 CSV 数据,无需编写一行代码。

一、核心思路:为什么用 SQL 连接 CSV?

搭建 CSV 问答系统的核心是让大模型 "读懂" 表格数据,主流方案有两种:

  1. 直接让大模型调用 Pandas 操作 CSV:灵活但风险高(可能执行恶意代码),权限难控制;
  2. 将 CSV 导入 SQL 数据库,让大模型用 SQL 查询:安全可控(限制 SQL 权限),查询逻辑清晰,且大模型对 SQL 的支持更成熟。

本文采用第二种方案,整体流程如下:CSV 文件 → 导入 SQLite 数据库 → 用 LangChain 创建 SQL 智能体 → 自然语言查询 → 返回答案

二、前置准备

  1. 环境依赖:安装必要的 Python 库

bash

运行

复制代码
pip install langchain langchain-openai pandas sqlalchemy python-dotenv
  1. CSV 数据 :准备需要查询的 CSV 文件(本文以经典的 titanic.csv 为例,包含乘客姓名、年龄、存活状态等信息);
  2. 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.csvcustomers.csv),导入 SQL 后可通过 JOIN 查询,智能体同样能自动处理:

python

运行

复制代码
# 示例:查询每个客户的订单数
result5 = agent_executor.invoke({"input": "每个客户的订单数量分别是多少?"})

五、常见问题排查

  1. CSV 编码错误 :读取 CSV 时若报错,添加 encoding 参数(如 pd.read_csv("titanic.csv", encoding="utf-8-sig"));
  2. SQL 语法错误 :不同数据库语法有差异(如 SQLite 用 LIMIT,MySQL 用 LIMIT,PostgreSQL 用 LIMIT),LangChain 会自动适配;
  3. 大模型无法识别表结构 :确保 db.get_tables_list() 能正常输出表名,若不行,重新检查数据库连接;
  4. API Key 无效 :确认 .env 文件中 OPENAI_API_KEY 的值正确,且有足够的余额。

六、总结

本文用不到 50 行代码,实现了 "自然语言查询 CSV 数据" 的核心功能,关键亮点:

  1. 安全可控:通过 SQL 限制操作权限,避免恶意代码执行;
  2. 零代码门槛:用户无需懂 SQL 或 Python,用自然语言即可查询;
  3. 灵活扩展:支持多 CSV、复杂查询,可适配销售数据、用户数据等多种场景。

接下来你可以尝试:

  • 替换为自己的 CSV 数据(如电商订单、运营报表);
  • 集成到 Web 应用(用 FastAPI 封装接口);
  • 改用开源大模型(如 Llama 3、Mistral),摆脱对 OpenAI 的依赖。

这个系统能大幅提升数据查询效率,尤其适合非技术人员快速获取 CSV 中的关键信息,赶紧动手试试吧!

相关推荐
dust_and_stars3 小时前
APT vs Snap vs Flatpak 核心对比表
运维·服务器·数据库
念越4 小时前
MySQL报错:Column count doesn‘t match value count at row 1 解决方案(超详细)
数据库·mysql
SmartBrain4 小时前
FastAPI实战(第二部分):用户注册接口开发详解
数据库·人工智能·python·fastapi
_但为君故_4 小时前
优化Tomcat的JVM内存
java·jvm·tomcat
倔强的石头_5 小时前
一卡通核心交易平台的国产数据库实践解析:架构、迁移与高可用落地
数据库
952365 小时前
MySQL存储过程和触发器
数据库·mysql
x***r1515 小时前
phpstudy_x64_8.1.1.3安装教程(含Apache/MySQL启动与端口修改)
数据库·mysql·apache
笨蛋不要掉眼泪5 小时前
Sentinel 流控规则详解:三种模式与三种效果实战指南
java·jvm·数据库·后端·sentinel
cjl_8520086 小时前
MySQL-递归查询
数据库·windows·mysql