Summary: This project demonstrates a Text-to-SQL agent using LangChain 1.2. It converts natural language queries into safe MySQL queries via a custom toolset (ListTablesTool, TableSchemaTool, etc.), enforcing a workflow: list tables, check schema, generate/validate SELECT queries, and execute. Code covers agent setup, security checks, and database utilities.
langchain更新了1.2版本,最近学习langchain1.2,为此写了一个小项目--text2sql智能体项目,将自然语言转成sql,感觉还是做项目才能更加深刻的理解学习的知识,本次将项目分享给大家,大家可以共同学习一下,废话不多说,直接上干活,建议大家,手动敲一下。
项目概述
项目名称:text-to-sql 示例工程 目标:展示如何将自然语言查询转换为安全的 MySQL 查询并执行,使用 LangChain 的 agent 模式与自定义工具集实现。 主要文件: text_to_sql_agent.py、tools/text_to_sql_tools.py、utils/db_utils.py、sql.db
数据模型(5 张表)
company_department:公司部门信息(dept_id、dept_name、dept_code、parent_dept_id 等) permission_info:权限说明(perm_id、perm_code、perm_type 等) user_role:角色定义(role_id、role_code 等) role_permission:角色与权限的多对多关系(role_id ↔ perm_id) user_register:用户注册信息,关联部门与角色(dept_id, role_id)
具体建表语句与示例数据见 sql.db,这个数据库的创建文件是我用大模型生成,现在构造数据真的很方便。
架构与工作流程
在 text_to_sql_agent.py中通过 LangChain 的create_agent将 LLM 与一组工具(tools)连接。工具由get_tools()创建并注入 agent:ListTablesTool、TableSchemaTool、SQLQueryTool、SQLQueryCheckerTool。数据库相关操作封装在 utils/db_utils.py的MySQLDatabaseManager,提供获取表名、表注释、表结构、执行查询和校验 SQL 的方法。交互流程(由 system prompt 强制): 列出数据库表(工具: sql_db_list_tables)。查看相关表的 schema(工具: sql_db_schema)。LLM 生成 SQL(仅允许 SELECT/WITH),使用 sql_db_query_checker校验。使用 sql_db_query执行查询并返回 JSON 格式结果。
关键实现要点与代码片段
agent 注册工具(节选自 text_to_sql_agent.py):
def get_tools(host: str, port: int, username: str, password: str, database: str):connection_string = f"mysql+pymysql://{username}:{password}@{host}:{port}/{database}?charset=utf8mb4"manager = MySQLDatabaseManager(connection_string)return [ListTablesTool(db_manager=manager),TableSchemaTool(db_manager=manager),SQLQueryTool(db_manager=manager),SQLQueryCheckerTool(db_manager=manager),]
执行查询时的安全性检查(节选自 utils/db_utils.py):
forbidden_keywords = ['insert','update','delete','drop','truncate','alter','create','grant']query_lower = query.lower()if not query_lower.startswith(("select", 'with')) and any(k in query_lower for k in forbidden_keywords):raise ValueError("出于安全考虑,只允许执行select查询和with查询")
列出表工具(节选自 tools/text_to_sql_tools.py):
class ListTablesTool(BaseTool):name = "sql_db_list_tables"description = "列出 MySQL 数据库中的所有表名及描述"def _run(self) -> str:tables_info = self.db_manager.get_tables_with_comments()result = f"数据库中共有 {len(tables_info)} 个表:\n\n"for i, t in enumerate(tables_info):result += f"{i}. 表名:{t['table_name']}\n 描述:{t['table_comment'] or '(暂无描述)'}\n\n"return result
运行与快速上手
在 MySQL 中执行 sql.db中的 SQL,导入示例表与数据。在 text_to_sql_agent.py中调整get_tools()的数据库连接参数(host/port/username/password/database)。运行 agent 示例:
python text_to_sql_agent.py
注意:示例代码中可能包含示范性的模型/密钥设置,请在生产中使用环境变量或安全配置存储 API Key 与数据库凭据,切勿硬编码。
示例场景
问:"赵六属于哪个部门,他有哪些权限?"
流程示例:
agent 首先调用 sql_db_list_tables查看有哪些表;agent 调用 sql_db_schema获取user_register/role_permission/permission_info的字段信息;LLM 基于 schema 生成 SELECT查询(限制列与返回行数),并使用sql_db_query_checker校验;最终执行 sql_db_query并将查询结果(JSON)和自然语言总结返回给用户。
这个查询需要关联三个表,结果正确,整体代码逻辑还没有做太多优化,大家可以自己做一下优化。
代码和数据都打包好放在了网盘里,获取代码私信回复【tq】