init_image_translation.py 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. """
  2. 图像翻译模块数据库迁移脚本
  3. 功能:
  4. 1. 创建 image_translation 表
  5. 2. 插入模型配置(model 和 model_price)
  6. 3. 插入百宝箱应用数据(toolbox_apps)
  7. 4. 验证数据完整性
  8. 从 .env 文件读取数据库连接信息
  9. """
  10. import os
  11. import sys
  12. from pathlib import Path
  13. from dotenv import load_dotenv
  14. import psycopg2
  15. from psycopg2 import sql
  16. # 添加项目根目录到路径
  17. sys.path.insert(0, str(Path(__file__).parent.parent))
  18. # 加载环境变量
  19. env_path = Path(__file__).parent.parent / '.env'
  20. load_dotenv(dotenv_path=env_path)
  21. def get_db_connection():
  22. """从环境变量获取数据库连接"""
  23. try:
  24. conn = psycopg2.connect(
  25. host=os.getenv("DB_HOST", "localhost"),
  26. port=int(os.getenv("DB_PORT", "5432")),
  27. database=os.getenv("DB_NAME", "aigcspace"),
  28. user=os.getenv("DB_USER", "postgres"),
  29. password=os.getenv("DB_PASSWORD", "")
  30. )
  31. return conn
  32. except Exception as e:
  33. print(f"❌ 数据库连接失败: {e}")
  34. sys.exit(1)
  35. def execute_sql_file(cursor, file_path: Path):
  36. """执行SQL文件"""
  37. try:
  38. with open(file_path, 'r', encoding='utf-8') as f:
  39. sql_content = f.read()
  40. # 执行SQL
  41. cursor.execute(sql_content)
  42. print(f"✓ 执行成功: {file_path.name}")
  43. return True
  44. except Exception as e:
  45. print(f"❌ 执行失败: {file_path.name}")
  46. print(f" 错误信息: {e}")
  47. return False
  48. def insert_model_data(cursor):
  49. """插入模型配置数据"""
  50. try:
  51. # 检查模型是否已存在
  52. cursor.execute("""
  53. SELECT id FROM aigcspace.model WHERE title = 'qwen-mt-image' LIMIT 1;
  54. """)
  55. existing_model = cursor.fetchone()
  56. if existing_model:
  57. print(f"✓ 模型 qwen-mt-image 已存在 (ID: {existing_model[0]})")
  58. model_id = existing_model[0]
  59. else:
  60. # 插入模型记录
  61. cursor.execute("""
  62. INSERT INTO aigcspace.model (
  63. title, description, provider, model_type,
  64. status, created_at, updated_at
  65. ) VALUES (
  66. 'qwen-mt-image',
  67. '通义千问图像翻译模型,支持多语种图像文字翻译',
  68. 'Alibaba',
  69. 'image-translation',
  70. 'active',
  71. NOW(),
  72. NOW()
  73. ) RETURNING id;
  74. """)
  75. model_id = cursor.fetchone()[0]
  76. print(f"✓ 模型 qwen-mt-image 插入成功 (ID: {model_id})")
  77. # 检查价格配置是否已存在
  78. cursor.execute("""
  79. SELECT id FROM aigcspace.model_price WHERE model_id = %s LIMIT 1;
  80. """, (model_id,))
  81. existing_price = cursor.fetchone()
  82. if existing_price:
  83. print(f"✓ 模型价格配置已存在 (ID: {existing_price[0]})")
  84. else:
  85. # 插入价格配置
  86. cursor.execute("""
  87. INSERT INTO aigcspace.model_price (
  88. model_id, input_price, output_price,
  89. created_at, updated_at
  90. ) VALUES (
  91. %s, 0.0000, 0.0200, NOW(), NOW()
  92. );
  93. """, (model_id,))
  94. print(f"✓ 模型价格配置插入成功(每张图片 0.02 元)")
  95. return True
  96. except Exception as e:
  97. print(f"❌ 模型数据插入失败: {e}")
  98. return False
  99. def insert_toolbox_app(cursor):
  100. """插入百宝箱应用数据"""
  101. try:
  102. # 检查应用是否已存在
  103. cursor.execute("""
  104. SELECT id FROM aigcspace.toolbox_apps
  105. WHERE app_key = 'qwen-image-translate' LIMIT 1;
  106. """)
  107. existing_app = cursor.fetchone()
  108. if existing_app:
  109. print(f"✓ 百宝箱应用 qwen-image-translate 已存在 (ID: {existing_app[0]})")
  110. return True
  111. # 插入应用记录
  112. cursor.execute("""
  113. INSERT INTO aigcspace.toolbox_apps (
  114. app_key, name, description, category, icon,
  115. is_new, is_hot, status, sort_order, version,
  116. created_at, updated_at
  117. ) VALUES (
  118. 'qwen-image-translate',
  119. '通义千问图像翻译',
  120. '支持多语种图像文字翻译,保持原图排版和风格',
  121. '图像处理',
  122. 'translate',
  123. true,
  124. true,
  125. 'active',
  126. 100,
  127. '1.0.0',
  128. NOW(),
  129. NOW()
  130. ) RETURNING id;
  131. """)
  132. app_id = cursor.fetchone()[0]
  133. print(f"✓ 百宝箱应用 qwen-image-translate 插入成功 (ID: {app_id})")
  134. return True
  135. except Exception as e:
  136. print(f"❌ 百宝箱应用插入失败: {e}")
  137. return False
  138. def verify_data(cursor):
  139. """验证数据是否正确插入"""
  140. try:
  141. print(f"\n📊 数据验证:")
  142. # 验证表是否创建
  143. cursor.execute("""
  144. SELECT EXISTS (
  145. SELECT FROM information_schema.tables
  146. WHERE table_schema = 'aigcspace'
  147. AND table_name = 'image_translation'
  148. );
  149. """)
  150. table_exists = cursor.fetchone()[0]
  151. print(f" ✓ image_translation 表: {'已创建' if table_exists else '❌ 未创建'}")
  152. # 验证模型配置
  153. cursor.execute("""
  154. SELECT m.id, m.title, mp.output_price
  155. FROM aigcspace.model m
  156. LEFT JOIN aigcspace.model_price mp ON m.id = mp.model_id
  157. WHERE m.title = 'qwen-mt-image';
  158. """)
  159. model_data = cursor.fetchone()
  160. if model_data:
  161. print(f" ✓ 模型配置: qwen-mt-image (ID: {model_data[0]}, 价格: {model_data[2]}元/张)")
  162. else:
  163. print(f" ❌ 模型配置未找到")
  164. # 验证百宝箱应用
  165. cursor.execute("""
  166. SELECT id, name, category, is_new, version, status
  167. FROM aigcspace.toolbox_apps
  168. WHERE app_key = 'qwen-image-translate';
  169. """)
  170. app_data = cursor.fetchone()
  171. if app_data:
  172. app_id, name, category, is_new, version, status = app_data
  173. new_tag = " [New]" if is_new else ""
  174. print(f" ✓ 百宝箱应用: {name}{new_tag} (版本: {version}, 状态: {status})")
  175. else:
  176. print(f" ❌ 百宝箱应用未找到")
  177. # 验证索引
  178. cursor.execute("""
  179. SELECT indexname FROM pg_indexes
  180. WHERE schemaname = 'aigcspace'
  181. AND tablename = 'image_translation';
  182. """)
  183. indexes = cursor.fetchall()
  184. print(f" ✓ 索引数量: {len(indexes)}")
  185. for idx in indexes:
  186. print(f" - {idx[0]}")
  187. return True
  188. except Exception as e:
  189. print(f"❌ 数据验证失败: {e}")
  190. return False
  191. def main():
  192. """主函数"""
  193. print("=" * 60)
  194. print("图像翻译模块数据库迁移脚本")
  195. print("=" * 60)
  196. # 获取迁移文件路径
  197. migrations_dir = Path(__file__).parent.parent / 'migrations'
  198. migration_file = migrations_dir / 'add_image_translation_table.sql'
  199. # 检查文件是否存在
  200. if not migration_file.exists():
  201. print(f"❌ 迁移文件不存在: {migration_file}")
  202. sys.exit(1)
  203. print(f"\n📁 找到迁移文件:")
  204. print(f" - {migration_file.name}")
  205. # 连接数据库
  206. print(f"\n🔌 连接数据库...")
  207. print(f" Host: {os.getenv('DB_HOST', 'localhost')}")
  208. print(f" Port: {os.getenv('DB_PORT', '5432')}")
  209. print(f" Database: {os.getenv('DB_NAME', 'aigcspace')}")
  210. print(f" User: {os.getenv('DB_USER', 'postgres')}")
  211. conn = get_db_connection()
  212. cursor = conn.cursor()
  213. print(f"✓ 数据库连接成功")
  214. # 执行迁移
  215. print(f"\n🚀 开始执行迁移...")
  216. # 1. 执行SQL文件(创建表)
  217. print(f"\n[1/3] 创建数据表...")
  218. if not execute_sql_file(cursor, migration_file):
  219. conn.rollback()
  220. cursor.close()
  221. conn.close()
  222. print(f"\n❌ 迁移失败,已回滚所有更改")
  223. sys.exit(1)
  224. # 提交事务
  225. conn.commit()
  226. print(f"\n✓ 所有迁移执行成功")
  227. # 验证数据
  228. verify_data(cursor)
  229. # 关闭连接
  230. cursor.close()
  231. conn.close()
  232. print(f"\n" + "=" * 60)
  233. print("✅ 图像翻译模块数据库迁移完成!")
  234. print("=" * 60)
  235. print(f"\n💡 下一步:")
  236. print(f" 1. 重启后端服务: cd backend && python main.py")
  237. print(f" 2. 访问百宝箱: http://localhost:5173/toolbox")
  238. print(f" 3. 点击「通义千问图像翻译」卡片的「立即使用」按钮")
  239. print(f" 4. 开始使用图像翻译功能")
  240. print()
  241. if __name__ == "__main__":
  242. try:
  243. main()
  244. except KeyboardInterrupt:
  245. print(f"\n\n⚠️ 用户中断执行")
  246. sys.exit(1)
  247. except Exception as e:
  248. print(f"\n\n❌ 执行过程中发生错误: {e}")
  249. import traceback
  250. traceback.print_exc()
  251. sys.exit(1)