53AI - 企业AI解决方案
首页 > 教学实践 > 用Neo4j构建数据库语义图谱,优化Text2SQL效果

用Neo4j构建数据库语义图谱,优化Text2SQL效果

发布日期: 2025-11-04
浏览次数: 88

用Neo4j构建数据库语义图谱,优化Text2SQL效果

数据库语义图谱

作者:威辰新创

在大模型驱动的智能数据时代,Text2SQL的准确性严重依赖对表结构表间关系的理解。传统方法依赖Prompt工程或Schema描述,效果不稳定。

今天,我将带你用Neo4j构建"数据库语义图谱",让大模型"看得懂关系",显著提升SQL生成准确率!

核心概念

数据库语义图谱:将MySQL的表结构、字段信息和表间关系,以图数据库的形式进行存储和表示。每个表是一个节点,表之间的关系是连接线,让大模型能够直观地理解数据库的语义关系。

准备工作

在开始之前,请确保准备好以下环境和工具:

必需软件

  • Docker(用于运行Neo4j)
  • Python 3.7+
  • MySQL数据库

Python依赖

pip install pymysql py2neo

数据库配置

# MySQL配置
MYSQL_CONFIG = {
    "host": "localhost",
    "port": 13006,
    "user": "root",
    "password": "your_password",  # 替换为你的密码
    "database": "text2sql_db",
    "charset": "utf8mb4",
}

# Neo4j配置
NEO4J_URI = "bolt://localhost:7687"
NEO4J_USER = "neo4j"
NEO4J_PASSWORD = "your_password"  # 替换为你的密码

步骤详解

步骤一:启动Neo4j服务

首先,我们需要启动Neo4j图数据库服务:

docker run -d \
   --name neo4j-apoc \
   -p 7474:7474 \
   -p 7687:7687 \
   -v ./volume/neo4j/data:/data \
   -v ./volume/neo4j/plugins:/plugins \
   -e apoc.export.file.enabled=true \
   -e apoc.import.file.enabled=true \
   -e apoc.import.file.use_neo4j_config=true \
   -e NEO4J_AUTH=neo4j/neo4j123 \
   neo4j:5.26.11-ubi9

避坑指南:

  • 确保7474和7687端口未被占用
  • 首次启动后,可通过http://localhost:7474访问Neo4j浏览器

步骤二:建立数据库连接

创建数据库连接函数,这是后续所有操作的基础:

from py2neo import Graph
import pymysql

def connect_mysql():
    return pymysql.connect(**MYSQL_CONFIG)

def connect_neo4j():
    return Graph(NEO4J_URI, auth=(NEO4J_USER, NEO4J_PASSWORD))

重要提示:在实际使用前,请务必修改配置中的密码信息。

步骤三:自动提取MySQL表结构

这个函数会自动扫描数据库,提取所有表的结构信息:

def get_tables_from_database(connection):
    """自动扫描数据库,提取表名、字段、主键/外键标记"""
    tables = {}
    with connection.cursor() as cursor:
        cursor.execute("SHOW TABLES")
        table_names = [row[0] for row in cursor.fetchall()]
        
        for table_name in table_names:
            cursor.execute(f"SHOW COLUMNS FROM {table_name}")
            columns = cursor.fetchall()
            fields = []
            for col in columns:
                field_name = col[0]
                key_type = col[3]  # PRI=主键, MUL=外键候选
                if key_type == "PRI":
                    fields.append(f"{field_name} [主键]")
                elif key_type == "MUL":
                    fields.append(f"{field_name} [外键]")
                else:
                    fields.append(field_name)
            tables[table_name] = {"name": table_name, "fields": fields}
    return tables

优势:无需手动维护字段列表,自动感知数据库变更!

步骤四:定义表间业务关系

自动提取无法识别业务逻辑关系,需要人工补充:

RELATIONSHIPS = [
    {
        "from_table": "t_customers",
        "to_table": "t_sales_orders",
        "description": "客户创建销售订单",
        "field_relation": "customer_id → order.customer_id",
    },
    {
        "from_table": "t_sales_orders",
        "to_table": "t_order_details",
        "description": "订单包含多个明细项",
        "field_relation": "order_id → detail.order_id",
    },
    {
        "from_table": "t_products",
        "to_table": "t_order_details",
        "description": "产品属于订单明细",
        "field_relation": "product_id → detail.product_id",
    },
]

技巧:description用自然语言描述,方便大模型理解!

步骤五:构建Neo4j图谱

现在,我们将表结构和关系写入Neo4j:

首先创建约束,防止重复节点:

def create_constraints(graph):
    graph.run("CREATE CONSTRAINT IF NOT EXISTS FOR (t:Table) REQUIRE t.name IS UNIQUE")
    print("✅ 节点唯一约束已创建")

然后创建表节点:

def create_table_nodes(graph, tables):
    for table_name, info in tables.items():
        graph.run(
            """
            MERGE (t:Table {name: $name})
            SET t.label = $label, t.fields = $fields
            """,
            name=info["name"],
            label=table_name,
            fields=info["fields"]
        )
    print("✅ 表节点创建完成!共创建 %d 个表节点" % len(tables))

最后创建表关系:

def create_table_relationships(graph):
    for rel in RELATIONSHIPS:
        graph.run(
            """
            MATCH (from:Table {name: $from_table})
            MATCH (to:Table {name: $to_table})
            MERGE (from)-[r:REFERENCES {
                description: $description,
                field_relation: $field_relation
            }]->(to)
            """,
            from_table=rel["from_table"],
            to_table=rel["to_table"],
            description=rel["description"],
            field_relation=rel["field_relation"]
        )
    print("✅ 表关系创建完成!共创建 %d 条关系" % len(RELATIONSHIPS))

步骤六:一键运行主函数

将所有功能整合到主函数中,实现一键构建:

def main():
    print("🚀 开始构建Text2SQL语义图谱...")
    
    mysql_conn = connect_mysql()
    neo4j_graph = connect_neo4j()
    
    try:
        # 步骤1:获取表结构
        tables = get_tables_from_database(mysql_conn)
        print(f"📊 检测到 {len(tables)} 张数据表")
        
        # 步骤2:清空旧数据(谨慎操作!)
        print("🗑️ 清空Neo4j中的旧数据...")
        neo4j_graph.delete_all()
        
        # 步骤3:创建约束
        create_constraints(neo4j_graph)
        
        # 步骤4:创建表节点
        create_table_nodes(neo4j_graph, tables)
        
        # 步骤5:创建表关系
        create_table_relationships(neo4j_graph)
        
        print("🎉 图谱构建完成!现在可用Cypher查询或供大模型调用")
        
    except Exception as e:
        print(f"❌ 构建失败: {str(e)}")
        raise
    finally:
        mysql_conn.close()
        print("🔌 数据库连接已关闭")

if __name__ == "__main__":
    main()

成果验证

构建完成后,我们可以查询图谱来验证结果:

def test_get_table_relationships():
    """从Neo4j图数据库中查询预定义表之间的REFERENCES关系"""
    graph = connect_neo4j()
    table_names = ["t_customers", "t_sales_orders", "t_products", "t_order_details"]
    
    query = """
    MATCH (t1:Table)-[r:REFERENCES]-(t2:Table)
    WHERE t1.name IN $table_names
      AND t2.name IN $table_names
      AND t1.name < t2.name
    RETURN 
      t1.name AS from_table,
      r.field_relation AS relationship,
      t2.name AS to_table
    """
    
    result = graph.run(query, table_names=table_names).data()
    print("查询结果:", result)
    return result

如果一切正常,你应该能看到类似这样的输出:

查询结果: [
    {'from_table': 't_customers', 'relationship': 'customer_id → order.customer_id', 'to_table': 't_sales_orders'},
    {'from_table': 't_order_details', 'relationship': 'order_id → detail.order_id', 'to_table': 't_sales_orders'},
    {'from_table': 't_order_details', 'relationship': 'product_id → detail.product_id', 'to_table': 't_products'}
]

下一步学习建议

恭喜你成功构建了数据库语义图谱!接下来可以:

  • 集成到大模型应用:将Neo4j图谱作为知识库,增强Text2SQL的准确性
  • 学习Cypher查询语言:更深入地查询和操作图数据
  • 探索高级功能:如图算法、路径查找等

动手实践

现在轮到你啦!按照上面的步骤动手试试看,相信你会收获满满。如果在实践中遇到任何问题,或者有成功的经验想要分享,欢迎在评论区留言交流!

记住:最好的学习方式就是动手实践。开始你的图数据库之旅吧!

最简分享示例(仅 Alpine.js)
企业微信二维码
扫码在企业微信中分享
微信二维码
扫码在微信中分享
飞书二维码
扫码在飞书中分享
钉钉二维码
扫码在钉钉中分享
点击分享到 QQ
点击复制链接

热点资讯

联系我们

售前咨询

186 6662 7370

预约演示

185 8882 0121

WeChat QR Code

微信扫码

添加专属顾问

回到顶部