check_analysis_consistency.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. """
  4. 校验 chemistry_question_bank 的解析字段一致性:
  5. - 列 analysis
  6. - JSON 字段 answer_schema.analysis
  7. 用法:
  8. python scripts/check_analysis_consistency.py
  9. python scripts/check_analysis_consistency.py --table chemistry_question_bank_test --limit 50
  10. """
  11. from __future__ import annotations
  12. import argparse
  13. import json
  14. import os
  15. import re
  16. from typing import Any, Dict, Optional
  17. import pymysql
  18. def _mysql_conn_from_uri() -> Dict[str, Any]:
  19. """从 MYSQL_URI 解析连接参数,解析失败时使用默认值。"""
  20. uri = os.getenv("MYSQL_URI", "mysql+pymysql://maple:123456@localhost:3306/ai_system")
  21. m = re.match(
  22. r"^mysql\+pymysql://(?P<user>[^:]+):(?P<pwd>[^@]*)@(?P<host>[^:]+):(?P<port>\d+)/(?P<db>[^?]+)",
  23. uri,
  24. )
  25. if not m:
  26. return {
  27. "host": "localhost",
  28. "port": 3306,
  29. "user": "maple",
  30. "password": "123456",
  31. "database": "ai_system",
  32. }
  33. return {
  34. "host": m.group("host"),
  35. "port": int(m.group("port")),
  36. "user": m.group("user"),
  37. "password": m.group("pwd"),
  38. "database": m.group("db"),
  39. }
  40. def _normalize_text(v: Optional[str]) -> str:
  41. return (v or "").strip()
  42. def _extract_json_analysis(raw: Any) -> str:
  43. if raw is None:
  44. return ""
  45. data: Optional[Dict[str, Any]] = None
  46. if isinstance(raw, dict):
  47. data = raw
  48. elif isinstance(raw, str):
  49. try:
  50. data = json.loads(raw)
  51. except json.JSONDecodeError:
  52. return ""
  53. else:
  54. return ""
  55. val = data.get("analysis") if isinstance(data, dict) else None
  56. return _normalize_text(str(val) if val is not None else "")
  57. def main() -> None:
  58. parser = argparse.ArgumentParser(description="校验题库解析字段一致性")
  59. parser.add_argument(
  60. "--table",
  61. default="chemistry_question_bank",
  62. choices=["chemistry_question_bank", "chemistry_question_bank_test"],
  63. help="要校验的题库表",
  64. )
  65. parser.add_argument("--limit", type=int, default=20, help="展示不一致样本数量上限")
  66. args = parser.parse_args()
  67. conn_cfg = _mysql_conn_from_uri()
  68. conn = pymysql.connect(
  69. **conn_cfg,
  70. charset="utf8mb4",
  71. cursorclass=pymysql.cursors.DictCursor,
  72. autocommit=True,
  73. )
  74. try:
  75. with conn.cursor() as cursor:
  76. cursor.execute(
  77. f"""
  78. SELECT question_id, analysis, answer_schema
  79. FROM `{args.table}`
  80. """
  81. )
  82. rows = cursor.fetchall() or []
  83. finally:
  84. conn.close()
  85. total = len(rows)
  86. both_empty = 0
  87. equal_non_empty = 0
  88. mismatch = []
  89. only_col = 0
  90. only_json = 0
  91. for row in rows:
  92. col_analysis = _normalize_text(row.get("analysis"))
  93. json_analysis = _extract_json_analysis(row.get("answer_schema"))
  94. if not col_analysis and not json_analysis:
  95. both_empty += 1
  96. continue
  97. if col_analysis and json_analysis and col_analysis == json_analysis:
  98. equal_non_empty += 1
  99. continue
  100. if col_analysis and not json_analysis:
  101. only_col += 1
  102. elif (not col_analysis) and json_analysis:
  103. only_json += 1
  104. mismatch.append(
  105. {
  106. "question_id": row.get("question_id"),
  107. "analysis_col": col_analysis,
  108. "analysis_json": json_analysis,
  109. }
  110. )
  111. print(f"[INFO] 表:{args.table}")
  112. print(f"[INFO] 总题数:{total}")
  113. print(f"[INFO] 双空:{both_empty}")
  114. print(f"[INFO] 一致(非空):{equal_non_empty}")
  115. print(f"[INFO] 仅列有值:{only_col}")
  116. print(f"[INFO] 仅JSON有值:{only_json}")
  117. print(f"[INFO] 不一致总数:{len(mismatch)}")
  118. if mismatch:
  119. print(f"[WARN] 以下展示前 {args.limit} 条不一致样本:")
  120. for item in mismatch[: max(args.limit, 0)]:
  121. qid = item["question_id"]
  122. col_preview = item["analysis_col"][:120]
  123. json_preview = item["analysis_json"][:120]
  124. print(
  125. f" - question_id={qid}, "
  126. f"analysis_col='{col_preview}', "
  127. f"analysis_json='{json_preview}'"
  128. )
  129. if __name__ == "__main__":
  130. main()