1. 案例目标本案例是LlamaIndex的Text-to-SQL功能基础指南主要目标包括展示如何使用自然语言查询SQL数据库演示如何构建表索引以在查询时动态检索相关表介绍如何使用查询时行和列检索器来增强Text-to-SQL上下文展示如何单独定义Text-to-SQL检索器安全提示任何Text-to-SQL应用都应注意执行任意SQL查询可能存在安全风险。建议采取必要的预防措施如使用受限角色、只读数据库、沙箱等。2. 技术栈与核心依赖llama-index-corellama-index-llms-openaillama-index-embeddings-openaiSQLAlchemyOpenAI APIVectorStoreIndex本案例主要使用LlamaIndex框架结合OpenAI的语言模型和嵌入模型以及SQLAlchemy作为SQL数据库工具包。通过这些技术组合实现了自然语言到SQL查询的转换和执行。3. 环境配置步骤1安装必要的库%pip install llama-index-core llama-index-llms-openai llama-index-embeddings-openai步骤2设置OpenAI API密钥import osimport openaios.environ[OPENAI_API_KEY] sk-..步骤3初始化语言模型from llama_index.llms.openai import OpenAIllm OpenAI(temperature0.1, modelgpt-4.1-mini)注意确保已正确设置OpenAI API密钥并且有足够的API额度。温度参数设置为较低值(0.1)以确保输出的一致性。4. 案例实现4.1 创建数据库架构使用SQLAlchemy创建一个内存中的SQLite数据库并定义一个名为city_stats的表from sqlalchemy import (create_engine,MetaData,Table,Column,String,Integer,select,)engine create_engine(sqlite:///:memory:)metadata_obj MetaData()# 创建城市SQL表table_name city_statscity_stats_table Table(table_name,metadata_obj,Column(city_name, String(16), primary_keyTrue),Column(population, Integer),Column(country, String(16), nullableFalse),)metadata_obj.create_all(engine)4.2 添加测试数据向数据库中添加一些城市数据from sqlalchemy import insertrows [{city_name: Toronto, population: 2930000, country: Canada},{city_name: Tokyo, population: 13960000, country: Japan},{city_name: Chicago, population: 2679000, country: United States},{city_name: New York, population: 8258000, country: United States},{city_name: Seoul, population: 9776000, country: South Korea},{city_name: Busan, population: 3334000, country: South Korea},]for row in rows:stmt insert(city_stats_table).values(**row)with engine.begin() as connection:cursor connection.execute(stmt)4.3 Text-to-SQL查询引擎使用NLSQLTableQueryEngine创建自然语言到SQL的查询引擎from llama_index.core.query_engine import NLSQLTableQueryEnginequery_engine NLSQLTableQueryEngine(sql_databasesql_database, tables[city_stats], llmllm)query_str Which city has the highest population?response query_engine.query(query_str)4.4 查询时表检索当表模式大小超出上下文窗口时使用SQLTableRetrieverQueryEngine动态检索相关表from llama_index.core.indices.struct_store.sql_query import (SQLTableRetrieverQueryEngine,)from llama_index.core.objects import (SQLTableNodeMapping,ObjectIndex,SQLTableSchema,)from llama_index.core import VectorStoreIndexfrom llama_index.core.embeddings.openai import OpenAIEmbeddingtable_node_mapping SQLTableNodeMapping(sql_database)table_schema_objs [(SQLTableSchema(table_namecity_stats))]obj_index ObjectIndex.from_objects(table_schema_objs,table_node_mapping,VectorStoreIndex,embed_modelOpenAIEmbedding(modeltext-embedding-3-small),)query_engine SQLTableRetrieverQueryEngine(sql_database, obj_index.as_retriever(similarity_top_k1))4.5 查询时行和列检索使用行和列检索器增强Text-to-SQL上下文提高查询准确性行检索将表的每一行嵌入为每个表创建一个索引列检索为表中的每个列的不同值创建索引# 行检索示例city_nodes [TextNode(textstr(t)) for t in results]city_rows_index VectorStoreIndex(city_nodes, embed_modelOpenAIEmbedding(modeltext-embedding-3-small))city_rows_retriever city_rows_index.as_retriever(similarity_top_k1)# 列检索示例city_cols_retrievers {}for column_name in [city_name, country]:stmt select(city_stats_table.c[column_name]).distinct()with engine.connect() as connection:values connection.execute(stmt).fetchall()nodes [TextNode(textt[0]) for t in values]column_index VectorStoreIndex(nodes, embed_modelOpenAIEmbedding(modeltext-embedding-3-small))column_retriever column_index.as_retriever(similarity_top_k1)city_cols_retrievers[column_name] column_retriever4.6 Text-to-SQL检索器使用NLSQLRetriever单独实现Text-to-SQL检索功能from llama_index.core.retrievers import NLSQLRetriever# 默认检索(return_rawTrue)nl_sql_retriever NLSQLRetriever(sql_database, tables[city_stats], llmllm, return_rawTrue)# 将检索器与RetrieverQueryEngine组合from llama_index.core.query_engine import RetrieverQueryEnginequery_engine RetrieverQueryEngine.from_args(nl_sql_retriever, llmllm)5. 案例效果本案例实现了以下效果能够将自然语言问题转换为SQL查询并执行能够处理复杂的查询场景如美国有多少个城市通过行和列检索器增强了查询的准确性解决了语义相似但表达不同的问题提供了灵活的检索和查询组合方式适应不同应用场景示例查询Which city has the highest population?结果Tokyo has the highest population among all cities, with a population of 13,960,000.示例查询How many cities are in the US?结果There are 2 cities in the United States according to the data in the city_stats table.6. 案例实现思路本案例的实现思路可以分为以下几个关键步骤数据库设置使用SQLAlchemy创建内存数据库和表结构并填充测试数据基础Text-to-SQL使用NLSQLTableQueryEngine实现基本的自然语言到SQL的转换表模式检索当表数量多或模式复杂时使用ObjectIndex对表模式进行索引查询时动态检索相关表上下文增强通过行检索和列检索提供更多上下文信息提高SQL生成的准确性灵活组合提供单独的检索器组件可以与其他查询引擎组合使用这种分层设计使得系统能够适应不同规模和复杂度的数据库查询需求同时保持良好的可扩展性和灵活性。7. 扩展建议安全增强实现SQL查询白名单、权限控制和沙箱执行环境性能优化添加查询缓存机制减少重复查询的开销多数据库支持扩展支持更多数据库类型如PostgreSQL、MySQL等复杂查询处理增强对多表连接、子查询等复杂SQL操作的支持查询结果可视化添加查询结果的可视化展示功能错误处理增强对SQL语法错误和执行错误的处理和反馈机制自然语言理解集成更先进的NLP技术提高对复杂自然语言查询的理解能力8. 总结本案例展示了LlamaIndex框架中Text-to-SQL功能的强大能力通过多种检索和查询引擎的组合实现了灵活、高效的自然语言数据库查询。案例的核心价值在于提供了从简单到复杂的Text-to-SQL解决方案通过检索器设计解决了大规模数据库的模式管理问题通过行和列检索增强了查询的准确性和上下文理解提供了灵活的组件化设计便于扩展和定制这种Text-to-SQL技术可以广泛应用于数据分析、商业智能、报表生成等场景大大降低了非技术人员访问和分析数据库的门槛提高了数据驱动决策的效率。