DDL_Parse_API修复说明.md 8.5 KB

DDL Parse API 格式修复说明

问题描述

/ddl/parse 接口存在格式不一致的问题:

问题1:提示词冲突

DDLParser.parse_ddl() 方法中存在两个不同的格式要求:

  • System Message 要求单表格式:table_info + columns
  • User Message 使用 _optimize_ddl_prompt() 要求多表格式:{table_name: {name_zh, meta: [...]}}

两个提示词相互冲突,导致LLM返回不确定的格式。

问题2:缺少关键字段

当前格式缺少参考文档中的重要字段:

  • is_primary - 是否主键
  • comment - 注释内容
  • nullable - 是否可为空

修复方案

1. 统一提示词格式

修复前(第86-140行):

def parse_ddl(self, sql_content):
    prompt = self._optimize_ddl_prompt()
    payload = {
        "model": self.model_name,
        "messages": [
            {
                "role": "system",
                "content": """请从上传的SQL DDL文件中提取数据库表的结构信息...
                {
                  "table_info": {...},
                  "columns": [...]
                }
                """
            },
            {
                "role": "user", 
                "content": f"{prompt}\n\n{sql_content}"
            }
        ]
    }

修复后

def parse_ddl(self, sql_content):
    prompt = self._optimize_ddl_prompt()
    payload = {
        "model": self.model_name,
        "messages": [
            {
                "role": "system",
                "content": "你是一个专业的SQL DDL语句解析专家,擅长从DDL语句中提取表结构信息并转换为结构化的JSON格式。"
            },
            {
                "role": "user", 
                "content": f"{prompt}\n\n{sql_content}"
            }
        ]
    }

2. 更新 _optimize_ddl_prompt() 函数

修复前(第251-289行):

def _optimize_ddl_prompt(self):
    return """
    ...
    参考格式如下:
    {
        "users_table": {
            "name_zh": "用户表",
            "schema": "public",
            "meta": [{
                "name_en": "id",
                "data_type": "integer",
                "name_zh": "用户ID"
            }]
        }
    }
    """

修复后

def _optimize_ddl_prompt(self):
    return """
    请解析以下DDL建表语句,并按照指定的JSON格式返回结果:
    
    规则说明:
    1. 从DDL语句中识别所有表,可能会有多个表。每个表作为一个独立条目。
    2. 表的英文名称(name_en)使用原始大小写,不要转换为小写。
    3. 表的中文名称(name_zh)提取规则:
       - 优先从COMMENT ON TABLE语句中提取
       - 如果没有注释,则name_zh为空字符串
    4. 对于每个表,提取所有字段信息到columns数组中,每个字段包含:
       - name_zh: 字段中文名称
       - name_en: 字段英文名称(保持原始大小写)
       - data_type: 数据类型(包含长度信息,如VARCHAR(22))
       - is_primary: 是否主键("是"或"否",从PRIMARY KEY约束判断)
       - comment: 注释内容(从COMMENT ON COLUMN提取完整注释)
       - nullable: 是否可为空("是"或"否",从NOT NULL约束判断)
    
    返回格式(支持多表):
    {
        "TB_JC_KSDZB": {
            "table_info": {
                "name_zh": "科室对照表",
                "name_en": "TB_JC_KSDZB"
            },
            "columns": [
                {
                    "name_zh": "医疗机构代码",
                    "name_en": "YLJGDM",
                    "data_type": "VARCHAR(22)",
                    "is_primary": "是",
                    "comment": "医疗机构代码,复合主键",
                    "nullable": "否"
                }
            ]
        }
    }
    """

修复后的格式

单表示例(符合参考文档)

[
  {
    "table_info": {
      "name_zh": "科室对照表",
      "name_en": "TB_JC_KSDZB"
    },
    "columns": [
      {
        "name_zh": "医疗机构代码",
        "name_en": "YLJGDM",
        "data_type": "VARCHAR(22)",
        "is_primary": "是",
        "comment": "医疗机构代码,复合主键",
        "nullable": "否"
      },
      {
        "name_zh": "HIS科室代码",
        "name_en": "HISKSDM",
        "data_type": "CHAR(20)",
        "is_primary": "是",
        "comment": "HIS科室代码,主键、唯一",
        "nullable": "否"
      }
    ]
  }
]

多表示例

[
  {
    "table_info": {
      "name_zh": "科室对照表",
      "name_en": "TB_JC_KSDZB"
    },
    "columns": [...]
  },
  {
    "table_info": {
      "name_zh": "用户表",
      "name_en": "TB_USER"
    },
    "columns": [...]
  }
]

API完整响应格式

{
  "code": 200,
  "data": [
    {
      "table_info": {
        "name_zh": "科室对照表",
        "name_en": "TB_JC_KSDZB"
      },
      "columns": [...]
    }
  ],
  "message": "操作成功"
}

关键改进

✅ 1. 统一提示词

  • 删除了冲突的 system message
  • 只使用 _optimize_ddl_prompt() 来定义格式

✅ 2. 添加缺失字段

  • is_primary: 是否主键("是"/"否")
  • comment: 完整的注释内容
  • nullable: 是否可为空("是"/"否")

✅ 3. 使用标准结构

  • table_info: 包含表的基本信息
  • columns: 字段数组,每个字段包含所有必需属性

✅ 4. 保持原始大小写

  • 表名和字段名保持原始大小写(如 TB_JC_KSDZB, YLJGDM

✅ 5. 支持多表

  • 使用JSON数组格式返回多个表
  • 不使用表名作为key,而是将所有表放在数组中
  • 可以一次解析包含多个表的DDL文件

测试用例

输入:科室对照表SQL

CREATE TABLE TB_JC_KSDZB (
    YLJGDM VARCHAR(22) NOT NULL,
    HISKSDM CHAR(20) NOT NULL,
    HISKSMC CHAR(20) NOT NULL,
    PRIMARY KEY (YLJGDM, HISKSDM)
);

COMMENT ON TABLE TB_JC_KSDZB IS '科室对照表';
COMMENT ON COLUMN TB_JC_KSDZB.YLJGDM IS '医疗机构代码,复合主键';
COMMENT ON COLUMN TB_JC_KSDZB.HISKSDM IS 'HIS科室代码,主键、唯一';
COMMENT ON COLUMN TB_JC_KSDZB.HISKSMC IS 'HIS科室名称';

预期输出

[
  {
    "table_info": {
      "name_zh": "科室对照表",
      "name_en": "TB_JC_KSDZB"
    },
    "columns": [
      {
        "name_zh": "医疗机构代码",
        "name_en": "YLJGDM",
        "data_type": "VARCHAR(22)",
        "is_primary": "是",
        "comment": "医疗机构代码,复合主键",
        "nullable": "否"
      },
      {
        "name_zh": "HIS科室代码",
        "name_en": "HISKSDM",
        "data_type": "CHAR(20)",
        "is_primary": "是",
        "comment": "HIS科室代码,主键、唯一",
        "nullable": "否"
      },
      {
        "name_zh": "HIS科室名称",
        "name_en": "HISKSMC",
        "data_type": "CHAR(20)",
        "is_primary": "否",
        "comment": "HIS科室名称",
        "nullable": "否"
      }
    ]
  }
]

格式验证清单

  • 返回数组格式(支持单表和多表)
  • 每个表使用 table_info + columns 结构
  • table_info 包含 name_zhname_en
  • columns 是数组,每个元素包含:
    • name_zh - 字段中文名
    • name_en - 字段英文名
    • data_type - 数据类型(含长度)
    • is_primary - 是否主键
    • comment - 注释内容
    • nullable - 是否可空
  • 使用JSON数组格式,不使用表名作为key
  • 表名和字段名保持原始大小写

使用方法

调用接口

# 方式1:上传SQL文件
curl -X POST http://localhost:5000/api/resource/ddl/parse \
  -F "file=@科室对照表_原始.sql"

# 方式2:JSON请求
curl -X POST http://localhost:5000/api/resource/ddl/parse \
  -H "Content-Type: application/json" \
  -d '{"sql": "CREATE TABLE ..."}'

Python调用

from app.core.llm.ddl_parser import DDLParser

# 读取SQL文件
with open('科室对照表_原始.sql', 'r', encoding='utf-8') as f:
    sql_content = f.read()

# 解析DDL
parser = DDLParser()
result = parser.parse_ddl(sql_content)

# 结果格式(数组)
# [
#   {
#     "table_info": {...},
#     "columns": [...]
#   }
# ]

文件修改清单

  1. app/core/llm/ddl_parser.py

    • 修改 parse_ddl() 方法(第86-140行)
    • 修改 _optimize_ddl_prompt() 方法(第251-289行)
  2. 接口路由

    • app/api/data_resource/routes.py - /ddl/parse 接口(第602行)

更新时间

2024-11-27