idea_house.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. """
  2. idea库蓝图 - 使用 Coze API 分析数据字段的 Flask 蓝图
  3. """
  4. from flask import Blueprint, render_template, request, jsonify, session as flask_session
  5. import os
  6. import sys
  7. from cozepy import Coze, TokenAuth, Message, ChatStatus, MessageContentType
  8. from cozepy import COZE_CN_BASE_URL
  9. import json
  10. # 创建蓝图
  11. idea_house_bp = Blueprint('idea_house', __name__, url_prefix='/idea-house')
  12. @idea_house_bp.route('/')
  13. def idea_house():
  14. """idea库页面"""
  15. return render_template('idea_house.html')
  16. @idea_house_bp.route('/api/process-fields', methods=['POST'])
  17. def process_fields():
  18. """使用 Coze API 处理选定的数据字段"""
  19. try:
  20. # 从请求获取选定的字段
  21. data = request.get_json()
  22. selected_fields = data.get('selected_fields', {})
  23. coze_api_token = data.get('coze_api_token')
  24. workflow_id = data.get('workflow_id')
  25. dataset_description = data.get('dataset_description', '')
  26. print("=" * 60)
  27. print("🚀 COZE API 请求已启动")
  28. print("=" * 60)
  29. print(f"📋 选定字段数量: {len(selected_fields)}")
  30. print(f"🔑 API 令牌 (最后10位): ...{coze_api_token[-10:] if coze_api_token else '无'}")
  31. print(f"⚙️ 工作流 ID: {workflow_id}")
  32. print("=" * 60)
  33. if not selected_fields:
  34. print("❌ 错误: 未选择任何字段")
  35. return jsonify({'error': '未选择任何字段'}), 400
  36. if not coze_api_token:
  37. print("❌ 错误: 需要 Coze API 令牌")
  38. return jsonify({'error': '需要 Coze API 令牌'}), 400
  39. if not workflow_id:
  40. print("❌ 错误: 需要工作流 ID")
  41. return jsonify({'error': '需要工作流 ID'}), 400
  42. # 从选定字段准备输入字符串
  43. # 格式: "字段ID (描述, 单位)"
  44. input_lines = []
  45. for field_id, description in selected_fields.items():
  46. input_lines.append(f"{field_id} ({description})")
  47. input_string = "\n".join(input_lines)
  48. # 如果数据集描述可用,则附加
  49. if dataset_description:
  50. input_string = f"数据集描述: {dataset_description}\n\n选定字段:\n{input_string}"
  51. print("📤 准备 COZE API 请求:")
  52. print(f" 输入字符串: {input_string[:100]}..." if len(input_string) > 100 else f" 输入字符串: {input_string}")
  53. # 设置 Coze API
  54. coze_api_base = COZE_CN_BASE_URL
  55. print(f"🌐 使用 Coze API 基础 URL: {coze_api_base}")
  56. # 初始化 Coze 客户端
  57. print("🔧 初始化 Coze 客户端...")
  58. coze = Coze(auth=TokenAuth(token=coze_api_token), base_url=coze_api_base)
  59. # 准备参数
  60. parameters = {
  61. "input": input_string
  62. }
  63. print("📊 请求参数:")
  64. print(f" {json.dumps(parameters, indent=2)}")
  65. # 使用重试调用工作流
  66. workflow_result = None
  67. error_message = None
  68. print("🔄 开始带重试的工作流执行...")
  69. for attempt in range(3):
  70. try:
  71. print(f" 尝试 {attempt + 1}/3: 调用 Coze 工作流...")
  72. workflow = coze.workflows.runs.create(
  73. workflow_id=workflow_id,
  74. parameters=parameters
  75. )
  76. workflow_result = workflow
  77. print(f" ✅ 尝试 {attempt + 1} 成功!")
  78. print(f" 📥 工作流响应类型: {type(workflow_result)}")
  79. if hasattr(workflow_result, 'data'):
  80. print(f" 📥 响应数据长度: {len(str(workflow_result.data)) if workflow_result.data else 0}")
  81. break
  82. except Exception as e:
  83. error_message = f"尝试 {attempt + 1} 失败,错误: {str(e)}"
  84. print(f" ❌ {error_message}")
  85. continue
  86. if workflow_result is None:
  87. print("💥 所有重试后工作流执行失败")
  88. print(f" 最后错误: {error_message}")
  89. return jsonify({
  90. 'error': '3次尝试后运行工作流失败',
  91. 'details': error_message
  92. }), 500
  93. print("✅ 工作流执行成功")
  94. print("🔍 处理工作流结果...")
  95. # 处理结果
  96. try:
  97. # 尝试从工作流数据中提取输出
  98. if hasattr(workflow_result, 'data') and workflow_result.data:
  99. print(" 📊 找到工作流数据,正在处理...")
  100. # 如果是字符串,尝试评估数据
  101. try:
  102. result_data = eval(workflow_result.data) if isinstance(workflow_result.data, str) else workflow_result.data
  103. output = result_data.get('output', '')
  104. print(f" 📄 提取的输出长度: {len(str(output))}")
  105. except:
  106. # 如果评估失败,按原样使用数据
  107. output = str(workflow_result.data)
  108. print(f" 📄 使用原始数据作为输出 (长度: {len(output)})")
  109. else:
  110. output = "工作流未返回数据"
  111. print(" ⚠️ 工作流未返回数据")
  112. print("=" * 60)
  113. print("🎉 COZE API 请求成功完成")
  114. print(f"📊 最终输出预览: {str(output)[:150]}..." if len(str(output)) > 150 else f"📊 最终输出: {str(output)}")
  115. print("=" * 60)
  116. return jsonify({
  117. 'success': True,
  118. 'output': output,
  119. 'parameters': parameters,
  120. 'selected_fields': selected_fields
  121. })
  122. except Exception as parse_error:
  123. print(f"💥 解析工作流结果错误: {str(parse_error)}")
  124. print(f" 原始 workflow.data: {workflow_result.data if hasattr(workflow_result, 'data') else '无数据属性'}")
  125. return jsonify({
  126. 'error': '解析工作流结果时出错',
  127. 'details': str(parse_error),
  128. 'raw_data': str(workflow_result.data) if hasattr(workflow_result, 'data') else None
  129. }), 500
  130. except Exception as e:
  131. print(f"💥 处理字段错误: {str(e)}")
  132. print("=" * 60)
  133. return jsonify({'error': str(e)}), 500
  134. @idea_house_bp.route('/api/get-datafields-proxy', methods=['GET'])
  135. def get_datafields_proxy():
  136. """代理端点,从主应用的 BRAIN API 端点获取数据字段"""
  137. try:
  138. from flask import current_app
  139. # 使用测试客户端发出内部请求
  140. with current_app.test_client() as client:
  141. # 从原始请求复制头部
  142. headers = {
  143. 'Session-ID': request.headers.get('Session-ID') or flask_session.get('brain_session_id')
  144. }
  145. # 复制查询参数
  146. params = request.args.to_dict()
  147. # 向主应用的数据字段端点发出内部请求
  148. response = client.get('/api/datafields', headers=headers, query_string=params)
  149. # 返回响应数据和状态
  150. return response.get_json(), response.status_code
  151. except Exception as e:
  152. print(f"数据字段代理错误: {str(e)}")
  153. return jsonify({'error': str(e)}), 500
  154. @idea_house_bp.route('/api/get-dataset-description', methods=['GET'])
  155. def get_dataset_description():
  156. """代理端点,从主应用的 BRAIN API 端点获取数据集描述"""
  157. print("\n" + "="*60)
  158. print("🔍 数据集描述代理端点被调用")
  159. print("="*60)
  160. try:
  161. from flask import current_app
  162. # 使用测试客户端发出内部请求
  163. with current_app.test_client() as client:
  164. # 从原始请求复制头部
  165. headers = {
  166. 'Session-ID': request.headers.get('Session-ID') or flask_session.get('brain_session_id')
  167. }
  168. # 复制查询参数
  169. params = request.args.to_dict()
  170. print(f"📊 代理请求参数: {params}")
  171. print(f"📌 会话 ID: {headers.get('Session-ID')}")
  172. # 向主应用的数据集描述端点发出内部请求
  173. response = client.get('/api/dataset-description', headers=headers, query_string=params)
  174. print(f"📥 代理响应状态: {response.status_code}")
  175. # 返回响应数据和状态
  176. return response.get_json(), response.status_code
  177. except Exception as e:
  178. print(f"💥 数据集描述代理错误: {str(e)}")
  179. print("="*60 + "\n")
  180. return jsonify({'error': str(e)}), 500