init_database.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. """
  2. 数据库表初始化脚本
  3. 运行: python init_database.py
  4. """
  5. import asyncio
  6. import aiomysql
  7. from config import settings
  8. import sys
  9. # 用户表
  10. CREATE_USERS_TABLE = """
  11. CREATE TABLE IF NOT EXISTS users (
  12. id BIGINT PRIMARY KEY AUTO_INCREMENT,
  13. user_id VARCHAR(64) UNIQUE NOT NULL COMMENT '用户唯一标识(UUID)',
  14. -- 基本信息
  15. username VARCHAR(100) NOT NULL COMMENT '用户名/昵称',
  16. user_type ENUM('guest', 'registered') DEFAULT 'guest' COMMENT '用户类型',
  17. bot_name VARCHAR(100) COMMENT '用户给机器人取的名字',
  18. -- 注册信息(可选)
  19. phone VARCHAR(20) UNIQUE COMMENT '手机号',
  20. wechat_openid VARCHAR(100) UNIQUE COMMENT '微信OpenID',
  21. google_email VARCHAR(200) UNIQUE COMMENT 'Google邮箱',
  22. -- 认证信息
  23. is_verified BOOLEAN DEFAULT FALSE COMMENT '是否已认证',
  24. registered_at TIMESTAMP NULL COMMENT '注册时间',
  25. -- 统计信息
  26. total_messages INT DEFAULT 0 COMMENT '总消息数',
  27. total_rounds INT DEFAULT 0 COMMENT '总对话轮次',
  28. total_speech_duration_ms BIGINT DEFAULT 0 COMMENT '累积说话时长(毫秒)',
  29. last_active_at TIMESTAMP NULL COMMENT '最后活跃时间',
  30. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  31. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  32. INDEX idx_user_id (user_id),
  33. INDEX idx_phone (phone),
  34. INDEX idx_wechat_openid (wechat_openid),
  35. INDEX idx_google_email (google_email),
  36. INDEX idx_user_type (user_type)
  37. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  38. COMMENT='用户表'
  39. """
  40. # 消息表
  41. CREATE_MESSAGES_TABLE = """
  42. CREATE TABLE IF NOT EXISTS messages (
  43. id BIGINT PRIMARY KEY AUTO_INCREMENT,
  44. message_id VARCHAR(64) UNIQUE NOT NULL COMMENT '消息ID',
  45. user_id VARCHAR(64) NOT NULL COMMENT '用户ID',
  46. -- 消息内容
  47. role ENUM('user', 'assistant', 'system') NOT NULL COMMENT '角色',
  48. content TEXT NOT NULL COMMENT '消息内容',
  49. -- 轮次信息
  50. round_number INT NOT NULL COMMENT '对话轮次(从1开始)',
  51. -- 扩展信息
  52. emotion VARCHAR(50) COMMENT '情感标签',
  53. metadata JSON COMMENT '扩展信息(音频路径、识别耗时等)',
  54. token_count INT COMMENT 'Token数量',
  55. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  56. INDEX idx_user_id (user_id),
  57. INDEX idx_user_round (user_id, round_number),
  58. INDEX idx_created_at (created_at)
  59. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  60. COMMENT='消息表'
  61. """
  62. # 对话总结表
  63. CREATE_SUMMARIES_TABLE = """
  64. CREATE TABLE IF NOT EXISTS conversation_summaries (
  65. id BIGINT PRIMARY KEY AUTO_INCREMENT,
  66. summary_id VARCHAR(64) UNIQUE NOT NULL COMMENT '总结ID',
  67. user_id VARCHAR(64) NOT NULL COMMENT '用户ID',
  68. -- 总结范围
  69. start_round INT NOT NULL COMMENT '起始轮次',
  70. end_round INT NOT NULL COMMENT '结束轮次',
  71. -- 总结内容
  72. summary_text TEXT NOT NULL COMMENT '总结内容',
  73. summary_type ENUM('auto', 'manual') DEFAULT 'auto' COMMENT '总结类型',
  74. -- 统计信息
  75. message_count INT COMMENT '总结的消息数量',
  76. token_count INT COMMENT '总结文本Token数',
  77. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  78. INDEX idx_user_id (user_id),
  79. INDEX idx_user_end_round (user_id, end_round),
  80. UNIQUE KEY uk_user_round_range (user_id, start_round, end_round)
  81. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  82. COMMENT='对话总结表'
  83. """
  84. async def init_tables():
  85. """初始化数据库表"""
  86. try:
  87. # 创建数据库连接
  88. conn = await aiomysql.connect(
  89. host=settings.MYSQL_HOST,
  90. port=settings.MYSQL_PORT,
  91. user=settings.MYSQL_USER,
  92. password=settings.MYSQL_PASSWORD,
  93. db=settings.MYSQL_DATABASE,
  94. charset='utf8mb4'
  95. )
  96. async with conn.cursor() as cursor:
  97. # 创建用户表
  98. await cursor.execute(CREATE_USERS_TABLE)
  99. # 创建消息表
  100. await cursor.execute(CREATE_MESSAGES_TABLE)
  101. # 创建总结表
  102. await cursor.execute(CREATE_SUMMARIES_TABLE)
  103. await conn.commit()
  104. conn.close()
  105. return True
  106. except Exception as e:
  107. import traceback
  108. traceback.print_exc()
  109. return False
  110. async def check_tables():
  111. """检查表是否存在"""
  112. try:
  113. conn = await aiomysql.connect(
  114. host=settings.MYSQL_HOST,
  115. port=settings.MYSQL_PORT,
  116. user=settings.MYSQL_USER,
  117. password=settings.MYSQL_PASSWORD,
  118. db=settings.MYSQL_DATABASE,
  119. charset='utf8mb4'
  120. )
  121. async with conn.cursor() as cursor:
  122. await cursor.execute("SHOW TABLES")
  123. tables = await cursor.fetchall()
  124. conn.close()
  125. except Exception as e:
  126. pass
  127. if __name__ == "__main__":
  128. # 确认是否继续
  129. if len(sys.argv) > 1 and sys.argv[1] == "--force":
  130. confirm = "y"
  131. else:
  132. confirm = input("\n是否继续初始化数据库表? (y/n): ")
  133. if confirm.lower() != 'y':
  134. sys.exit(0)
  135. # 执行初始化
  136. success = asyncio.run(init_tables())
  137. if success:
  138. # 检查创建的表
  139. asyncio.run(check_tables())
  140. else:
  141. sys.exit(1)