更新了web方式查看products的效果
This commit is contained in:
@@ -322,27 +322,59 @@ class IntegratedProductSystem:
|
||||
logger.error(f"调用Ollama AI API时出错: {e}")
|
||||
return None
|
||||
|
||||
def parse_ai_response(self, response: str) -> Tuple[str, str, str]:
|
||||
"""解析AI响应内容"""
|
||||
def parse_ai_response(self, response: str) -> Tuple[str, str, str, int]:
|
||||
"""解析AI响应内容,提取产品名称、简介、难度描述和难度分数"""
|
||||
try:
|
||||
# 使用/分割响应内容
|
||||
parts = response.split('/')
|
||||
|
||||
product_name = ""
|
||||
product_intro = ""
|
||||
difficulty = ""
|
||||
difficulty_score = None
|
||||
|
||||
if len(parts) >= 3:
|
||||
product_name = parts[0].strip()
|
||||
product_intro = parts[1].strip()
|
||||
difficulty = parts[2].strip()
|
||||
|
||||
logger.info(f"解析结果: 名称='{product_name}', 简介='{product_intro[:30]}...', 难度='{difficulty}'")
|
||||
return product_name, product_intro, difficulty
|
||||
|
||||
# 从难度描述中提取分数
|
||||
import re
|
||||
# 尝试匹配数字分数
|
||||
score_match = re.search(r'\b(\d+)\b分|\b难度(\d+)\b|\b(\d+)\b', difficulty)
|
||||
if score_match:
|
||||
# 获取第一个匹配的数字
|
||||
for group in score_match.groups():
|
||||
if group:
|
||||
difficulty_score = int(group)
|
||||
break
|
||||
|
||||
# 如果没有提取到分数,根据关键词设置默认分数
|
||||
if difficulty_score is None:
|
||||
difficulty_lower = difficulty.lower()
|
||||
if any(keyword in difficulty_lower for keyword in ['高', '很难', '非常难', '复杂']):
|
||||
difficulty_score = 85
|
||||
elif any(keyword in difficulty_lower for keyword in ['中', '一般', '适中', '普通']):
|
||||
difficulty_score = 60
|
||||
elif any(keyword in difficulty_lower for keyword in ['低', '简单', '容易']):
|
||||
difficulty_score = 35
|
||||
else:
|
||||
difficulty_score = 50 # 默认中等难度
|
||||
|
||||
logger.info(f"提取到难度分数: {difficulty_score}")
|
||||
else:
|
||||
logger.warning(f"响应格式不符合预期: {response}")
|
||||
# 如果格式不符合,返回原始内容
|
||||
return "", response, ""
|
||||
difficulty = response
|
||||
difficulty_score = 50 # 默认中等难度
|
||||
|
||||
return product_name, product_intro, difficulty, difficulty_score
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"解析AI响应失败: {e}")
|
||||
return "", response, ""
|
||||
return "", response, "", 50
|
||||
|
||||
def check_product_exists_in_analysis(self, conn: sqlite3.Connection, original_name: str) -> bool:
|
||||
"""检查产品是否已存在于分析结果表中"""
|
||||
@@ -367,19 +399,23 @@ class IntegratedProductSystem:
|
||||
|
||||
def save_analysis_result(self, conn: sqlite3.Connection,
|
||||
original_id: int, original_name: str,
|
||||
product_name: str, difficulty: str, ai_response: str):
|
||||
"""保存分析结果到数据库"""
|
||||
product_name: str, difficulty: str, ai_response: str, difficulty_score: int = None):
|
||||
"""保存分析结果到数据库,包括难度分数"""
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 如果没有提供难度分数,设置默认值50
|
||||
if difficulty_score is None:
|
||||
difficulty_score = 50
|
||||
|
||||
cursor.execute("""
|
||||
INSERT INTO product_analysis
|
||||
(original_id, original_name, product_name, development_difficulty, ai_response)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
""", (original_id, original_name, product_name, difficulty, ai_response))
|
||||
(original_id, original_name, product_name, development_difficulty, difficulty_score, ai_response)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
""", (original_id, original_name, product_name, difficulty, difficulty_score, ai_response))
|
||||
|
||||
conn.commit()
|
||||
logger.success(f"保存分析结果成功: {product_name}")
|
||||
logger.success(f"保存分析结果成功: {product_name}, 难度分数: {difficulty_score}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"保存分析结果失败: {e}")
|
||||
@@ -435,11 +471,11 @@ class IntegratedProductSystem:
|
||||
logger.info(f"API调用成功,正在处理数据...")
|
||||
|
||||
# 解析响应
|
||||
product_name, product_intro, difficulty = self.parse_ai_response(ai_response)
|
||||
product_name, product_intro, difficulty, difficulty_score = self.parse_ai_response(ai_response)
|
||||
|
||||
# 保存结果(不再保存product_intro,避免与ai_response重复)
|
||||
self.save_analysis_result(conn, original_id, name,
|
||||
product_name, difficulty, ai_response)
|
||||
product_name, difficulty, ai_response, difficulty_score)
|
||||
success_count += 1
|
||||
|
||||
# 显示完成状态
|
||||
@@ -549,8 +585,86 @@ class IntegratedProductSystem:
|
||||
except Exception as e:
|
||||
logger.error(f"显示抓取结果失败: {e}")
|
||||
|
||||
def analyze_missing_scores(self):
|
||||
"""分析并补充缺失难度分数的产品"""
|
||||
logger.info("=== 开始分析缺失难度分数的产品 ===")
|
||||
|
||||
conn = None
|
||||
try:
|
||||
# 连接数据库
|
||||
conn = self.connect_to_database()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 查询缺失难度分数的产品
|
||||
cursor.execute("""
|
||||
SELECT pa.id, p.name, p.introduction, pa.ai_response
|
||||
FROM product_analysis pa
|
||||
JOIN products p ON pa.original_id = p.id
|
||||
WHERE pa.difficulty_score IS NULL OR pa.difficulty_score = ''
|
||||
""")
|
||||
|
||||
products_with_missing_scores = cursor.fetchall()
|
||||
logger.info(f"找到 {len(products_with_missing_scores)} 个缺失难度分数的产品")
|
||||
|
||||
if not products_with_missing_scores:
|
||||
logger.info("没有发现缺失难度分数的产品")
|
||||
return
|
||||
|
||||
# 为每个缺失分数的产品分析并更新分数
|
||||
updated_count = 0
|
||||
for i, (analysis_id, name, introduction, ai_response) in enumerate(products_with_missing_scores, 1):
|
||||
logger.info(f"处理缺失分数的产品 {i}/{len(products_with_missing_scores)}: {name}")
|
||||
|
||||
# 如果已有AI响应,从响应中重新提取分数
|
||||
difficulty_score = None
|
||||
if ai_response:
|
||||
try:
|
||||
_, _, _, difficulty_score = self.parse_ai_response(ai_response)
|
||||
logger.info(f"从现有AI响应中提取分数: {difficulty_score}")
|
||||
except Exception as e:
|
||||
logger.error(f"从现有响应提取分数失败: {e}")
|
||||
|
||||
# 如果无法从现有响应提取,重新调用API
|
||||
if difficulty_score is None:
|
||||
logger.info(f"重新调用API分析产品: {name}")
|
||||
ai_response = self.call_ollama_ai_api(name, introduction)
|
||||
if ai_response:
|
||||
_, _, _, difficulty_score = self.parse_ai_response(ai_response)
|
||||
# 更新AI响应
|
||||
cursor.execute("""
|
||||
UPDATE product_analysis
|
||||
SET ai_response = ?
|
||||
WHERE id = ?
|
||||
""", (ai_response, analysis_id))
|
||||
|
||||
# 更新难度分数
|
||||
if difficulty_score is not None:
|
||||
cursor.execute("""
|
||||
UPDATE product_analysis
|
||||
SET difficulty_score = ?
|
||||
WHERE id = ?
|
||||
""", (difficulty_score, analysis_id))
|
||||
conn.commit()
|
||||
updated_count += 1
|
||||
logger.success(f"成功更新产品 '{name}' 的难度分数为 {difficulty_score}")
|
||||
else:
|
||||
logger.warning(f"无法为产品 '{name}' 确定难度分数")
|
||||
|
||||
# 避免API调用过于频繁
|
||||
if i < len(products_with_missing_scores):
|
||||
time.sleep(2)
|
||||
|
||||
logger.success(f"缺失分数分析完成! 成功更新 {updated_count} 个产品的难度分数")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"分析缺失分数过程中出错: {e}")
|
||||
finally:
|
||||
if conn:
|
||||
conn.close()
|
||||
logger.info("数据库连接已关闭")
|
||||
|
||||
async def run_full_workflow_async(self, max_products=None, analyze_only=False):
|
||||
"""异步运行完整工作流程:抓取+分析"""
|
||||
"""异步运行完整工作流程:抓取+分析+补充缺失分数"""
|
||||
logger.info("=== 开始全功能产品系统工作流程 ===")
|
||||
|
||||
# 初始化数据库
|
||||
@@ -567,6 +681,10 @@ class IntegratedProductSystem:
|
||||
logger.info("步骤2: 开始AI分析产品数据...")
|
||||
self.analyze_products(max_products)
|
||||
|
||||
# 步骤3: 分析并补充缺失的难度分数
|
||||
logger.info("步骤3: 开始分析并补充缺失的难度分数...")
|
||||
self.analyze_missing_scores()
|
||||
|
||||
logger.success("=== 全功能产品系统工作流程完成 ===")
|
||||
|
||||
def run_full_workflow(self, max_products=None, analyze_only=False):
|
||||
|
||||
Reference in New Issue
Block a user