修复AI建议逻辑和字段映射问题
- 修复AI建议基于问题描述而不是处理过程生成 - 修复工单详情页面显示逻辑 - 修复飞书时间字段处理(毫秒时间戳转换) - 优化字段映射和转换逻辑 - 添加飞书集成功能 - 改进对话历史合并功能 - 优化系统优化反馈机制
This commit is contained in:
@@ -8,6 +8,7 @@ from flask import Blueprint, request, jsonify
|
||||
from src.core.database import db_manager
|
||||
from src.core.models import Conversation
|
||||
from src.core.query_optimizer import query_optimizer
|
||||
from datetime import timedelta
|
||||
|
||||
conversations_bp = Blueprint('conversations', __name__, url_prefix='/api/conversations')
|
||||
|
||||
@@ -27,6 +28,10 @@ def get_conversations():
|
||||
user_id=user_id, date_filter=date_filter
|
||||
)
|
||||
|
||||
# 规范化:移除不存在的user_id字段,避免前端误用
|
||||
for conv in result.get('conversations', []):
|
||||
if 'user_id' in conv and conv['user_id'] is None:
|
||||
conv.pop('user_id', None)
|
||||
return jsonify(result)
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e)}), 500
|
||||
@@ -40,10 +45,11 @@ def get_conversation_detail(conversation_id):
|
||||
if not conv:
|
||||
return jsonify({"error": "对话不存在"}), 404
|
||||
|
||||
# Conversation模型没有user_id字段,这里用占位或由外层推断
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'id': conv.id,
|
||||
'user_id': conv.user_id,
|
||||
'user_id': None,
|
||||
'user_message': conv.user_message,
|
||||
'assistant_response': conv.assistant_response,
|
||||
'timestamp': conv.timestamp.isoformat() if conv.timestamp else None,
|
||||
@@ -88,3 +94,106 @@ def clear_all_conversations():
|
||||
return jsonify({"success": True, "message": "对话历史已清空"})
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
@conversations_bp.route('/migrate-merge', methods=['POST'])
|
||||
def migrate_merge_conversations():
|
||||
"""一次性迁移:将历史上拆分存储的用户/助手两条记录合并为一条
|
||||
规则:
|
||||
- 只处理一端为空的记录(user_only 或 assistant_only)
|
||||
- 优先将 user_only 与其后最近的 assistant_only 合并(同工单且5分钟内)
|
||||
- 若当前为 assistant_only 且前一条是 user_only 也合并到前一条
|
||||
- 合并后删除被吸收的那条记录
|
||||
- 可重复执行(幂等):已合并的不再满足“一端为空”的条件
|
||||
"""
|
||||
try:
|
||||
merged_pairs = 0
|
||||
deleted_rows = 0
|
||||
time_threshold_seconds = 300
|
||||
to_delete_ids = []
|
||||
with db_manager.get_session() as session:
|
||||
conversations = session.query(Conversation).order_by(Conversation.timestamp.asc(), Conversation.id.asc()).all()
|
||||
total = len(conversations)
|
||||
i = 0
|
||||
|
||||
def is_empty(text: str) -> bool:
|
||||
return (text is None) or (str(text).strip() == '')
|
||||
|
||||
while i < total:
|
||||
c = conversations[i]
|
||||
user_only = (not is_empty(c.user_message)) and is_empty(c.assistant_response)
|
||||
assistant_only = (not is_empty(c.assistant_response)) and is_empty(c.user_message)
|
||||
|
||||
if user_only:
|
||||
# 向后寻找匹配的assistant_only
|
||||
j = i + 1
|
||||
while j < total:
|
||||
n = conversations[j]
|
||||
# 跳过已经标记删除的
|
||||
if n.id in to_delete_ids:
|
||||
j += 1
|
||||
continue
|
||||
# 超过阈值不再尝试
|
||||
if c.timestamp and n.timestamp and (n.timestamp - c.timestamp).total_seconds() > time_threshold_seconds:
|
||||
break
|
||||
# 同工单或两者都为空均可
|
||||
same_wo = (c.work_order_id == n.work_order_id) or (c.work_order_id is None and n.work_order_id is None)
|
||||
if same_wo and (not is_empty(n.assistant_response)) and is_empty(n.user_message):
|
||||
# 合并
|
||||
c.assistant_response = n.assistant_response
|
||||
if c.response_time is None and c.timestamp and n.timestamp:
|
||||
try:
|
||||
c.response_time = max(0.0, (n.timestamp - c.timestamp).total_seconds() * 1000.0)
|
||||
except Exception:
|
||||
pass
|
||||
# 继承辅助信息
|
||||
if (not c.confidence_score) and n.confidence_score is not None:
|
||||
c.confidence_score = n.confidence_score
|
||||
if (not c.knowledge_used) and n.knowledge_used:
|
||||
c.knowledge_used = n.knowledge_used
|
||||
session.add(c)
|
||||
to_delete_ids.append(n.id)
|
||||
merged_pairs += 1
|
||||
break
|
||||
j += 1
|
||||
|
||||
elif assistant_only:
|
||||
# 向前与最近的 user_only 合并(如果尚未被其他合并吸收)
|
||||
j = i - 1
|
||||
while j >= 0:
|
||||
p = conversations[j]
|
||||
if p.id in to_delete_ids:
|
||||
j -= 1
|
||||
continue
|
||||
if p.timestamp and c.timestamp and (c.timestamp - p.timestamp).total_seconds() > time_threshold_seconds:
|
||||
break
|
||||
same_wo = (c.work_order_id == p.work_order_id) or (c.work_order_id is None and p.work_order_id is None)
|
||||
if same_wo and (not is_empty(p.user_message)) and is_empty(p.assistant_response):
|
||||
p.assistant_response = c.assistant_response
|
||||
if p.response_time is None and p.timestamp and c.timestamp:
|
||||
try:
|
||||
p.response_time = max(0.0, (c.timestamp - p.timestamp).total_seconds() * 1000.0)
|
||||
except Exception:
|
||||
pass
|
||||
if (not p.confidence_score) and c.confidence_score is not None:
|
||||
p.confidence_score = c.confidence_score
|
||||
if (not p.knowledge_used) and c.knowledge_used:
|
||||
p.knowledge_used = c.knowledge_used
|
||||
session.add(p)
|
||||
to_delete_ids.append(c.id)
|
||||
merged_pairs += 1
|
||||
break
|
||||
j -= 1
|
||||
|
||||
i += 1
|
||||
|
||||
if to_delete_ids:
|
||||
deleted_rows = session.query(Conversation).filter(Conversation.id.in_(to_delete_ids)).delete(synchronize_session=False)
|
||||
session.commit()
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'merged_pairs': merged_pairs,
|
||||
'deleted_rows': deleted_rows
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({"error": str(e)}), 500
|
||||
|
||||
Reference in New Issue
Block a user