新增多个启动脚本以支持不同服务的后台运行,优化对话到工单的处理逻辑,增加人力信息映射,调整日志记录机制以支持异步处理。
This commit is contained in:
@@ -33,6 +33,33 @@ logging.basicConfig(
|
||||
)
|
||||
logger = logging.getLogger("dialogue_to_workorder")
|
||||
|
||||
human_info={
|
||||
"1116":["夏剑媛", "储能"],
|
||||
"1201":["曹美芳", "配网"],
|
||||
"1202":["彭珊珊", "主网"],
|
||||
"1230":["龚青", "配网"],
|
||||
"1544":["黄婷", "主网"],
|
||||
"1546":["严琼辉", "配网"],
|
||||
"1552":["吴园妹", "主网"],
|
||||
"1555":["魏怡璠", "配网"],
|
||||
"1789":["冷琛", "主网"],
|
||||
"2142":["余国庆", "配网"],
|
||||
"2144":["卢光辉", "技改"],
|
||||
"2145":["万志星", "技改"],
|
||||
"2233":["徐雨萍", "主网"],
|
||||
"2262":["刘雨微", "主网"],
|
||||
"2591":["揭敏", "主网"],
|
||||
"3035":["杨玲", "主网"],
|
||||
"3416":["杨苏文", "配网"],
|
||||
"3417":["王琴", "配网"],
|
||||
"439":["赵莉", "技改"],
|
||||
"8340":["熊磊娇", "储能"],
|
||||
"8442":["胡月", "配网"],
|
||||
"8443":["杨淑玲", "主网"],
|
||||
"8555":["胡青艳", "主网"],
|
||||
"8762":["周丽华", "主网"],
|
||||
}
|
||||
|
||||
# ================ 模型定义 ================
|
||||
class UserQuestionAndSolution(BaseModel):
|
||||
user_question: str = Field(description="用户的核心问题")
|
||||
@@ -143,6 +170,7 @@ class DialogueToWorkorder:
|
||||
|
||||
def get_workorder_dict(self, rows):
|
||||
"""从会话行中提取工单基本信息"""
|
||||
# 预设字段
|
||||
workorder_dict = {}
|
||||
|
||||
# 创建时间
|
||||
@@ -158,6 +186,10 @@ class DialogueToWorkorder:
|
||||
sender_nickname = row['发送者昵称']
|
||||
if sender == "坐席" and pd.notna(sender_nickname) and str(sender_nickname).strip() != '':
|
||||
workorder_dict["处理坐席"] = sender_nickname
|
||||
sender_num = re.findall(r'客服(\d+)', sender_nickname)
|
||||
if len(sender_num) > 0 and sender_num[0] in human_info:
|
||||
workorder_dict["处理人"] = human_info[sender_num[0]][0]
|
||||
workorder_dict["处理技能组"] = human_info[sender_num[0]][1]
|
||||
break
|
||||
|
||||
# 访客昵称
|
||||
@@ -463,7 +495,28 @@ class DialogueToWorkorder:
|
||||
|
||||
|
||||
# 更新工单字典
|
||||
base_workorder_dict.update({
|
||||
# base_workorder_dict.update({
|
||||
# "产品线": product_line,
|
||||
# "产品名称": product_name,
|
||||
# "模块名称": module_name,
|
||||
# "客户问题": user_question_str,
|
||||
# "问题类型": problem_type,
|
||||
# "是否抱怨": "是" if is_dissatisfaction else '否',
|
||||
# "抱怨内容": dissatisfaction_reasoning if is_dissatisfaction else '',
|
||||
# "抱怨级别": dissatisfaction_level if is_dissatisfaction else '',
|
||||
# "是否投诉": "是" if is_complaint else '否',
|
||||
# "解决方案": solution_str
|
||||
# })
|
||||
# workorder_list.append(base_workorder_dict)
|
||||
for user_question in user_question_list:
|
||||
user_question_str = user_question.user_question
|
||||
solution_str = user_question.solution
|
||||
|
||||
# 创建新的工单字典,复制基本信息
|
||||
workorder_dict = base_workorder_dict.copy()
|
||||
|
||||
# 更新工单字典
|
||||
workorder_dict.update({
|
||||
"产品线": product_line,
|
||||
"产品名称": product_name,
|
||||
"模块名称": module_name,
|
||||
@@ -475,29 +528,9 @@ class DialogueToWorkorder:
|
||||
"是否投诉": "是" if is_complaint else '否',
|
||||
"解决方案": solution_str
|
||||
})
|
||||
workorder_list.append(base_workorder_dict)
|
||||
# for user_question in user_question_list:
|
||||
# user_question_str = user_question.user_question
|
||||
# solution_str = user_question.solution
|
||||
|
||||
# # 创建新的工单字典,复制基本信息
|
||||
# workorder_dict = base_workorder_dict.copy()
|
||||
|
||||
# # 更新工单字典
|
||||
# workorder_dict.update({
|
||||
# "产品线": product_line,
|
||||
# "产品名称": product_name,
|
||||
# "模块名称": module_name,
|
||||
# "客户问题": user_question_str,
|
||||
# "问题类型": problem_type,
|
||||
# "是否抱怨": "是" if is_dissatisfaction else '否',
|
||||
# "抱怨级别": dissatisfaction_level if is_dissatisfaction else '',
|
||||
# "是否投诉": "是" if is_complaint else '否',
|
||||
# "解决方案": (solution_str + '\n存在抱怨:' + dissatisfaction_reasoning) if is_dissatisfaction else solution_str
|
||||
# })
|
||||
|
||||
# # 将工单添加到列表中
|
||||
# workorder_list.append(workorder_dict)
|
||||
# 将工单添加到列表中
|
||||
workorder_list.append(workorder_dict)
|
||||
|
||||
return workorder_list
|
||||
|
||||
@@ -513,27 +546,32 @@ class DialogueToWorkorder:
|
||||
# 解析产品详情
|
||||
product_detail_dict = self.parse_product_detail_excel(product_detail_excel_path)
|
||||
|
||||
# 如果指定了时间范围,则过滤数据
|
||||
if start_date or end_date:
|
||||
# 确保创建时间列为日期时间类型
|
||||
if '创建时间' in df.columns:
|
||||
df['创建时间'] = pd.to_datetime(df['创建时间'], errors='coerce')
|
||||
|
||||
# 按时间范围过滤
|
||||
if start_date:
|
||||
start_date = pd.to_datetime(start_date)
|
||||
df = df[df['创建时间'] >= start_date]
|
||||
logger.info(f"过滤开始时间 {start_date},剩余数据行数: {len(df)}")
|
||||
|
||||
if end_date:
|
||||
end_date = pd.to_datetime(end_date)
|
||||
df = df[df['创建时间'] <= end_date]
|
||||
logger.info(f"过滤结束时间 {end_date},剩余数据行数: {len(df)}")
|
||||
else:
|
||||
logger.warning("数据中没有'创建时间'列,无法按时间范围过滤")
|
||||
|
||||
# 按会话ID分组
|
||||
conversation_dict = self.group_conversations_by_id(df)
|
||||
|
||||
# 如果指定了时间范围,则过滤数据
|
||||
if start_date or end_date:
|
||||
logging.info(f"过滤时间范围: {start_date} 至 {end_date}")
|
||||
# 将字符串日期转换为datetime对象
|
||||
start_date_dt = datetime.strptime(start_date, "%Y-%m-%d %H:%M:%S") if start_date else None
|
||||
end_date_dt = datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S") if end_date else None
|
||||
|
||||
new_conversation_dict = {}
|
||||
for conversation_id, conversation_rows in conversation_dict.items():
|
||||
# 获取会话创建时间并转换为datetime对象
|
||||
create_time_str = conversation_rows[0]["创建时间"]
|
||||
if isinstance(create_time_str, str):
|
||||
create_time_dt = datetime.strptime(create_time_str, "%Y-%m-%d %H:%M:%S")
|
||||
else:
|
||||
# 如果已经是datetime对象则直接使用
|
||||
create_time_dt = create_time_str
|
||||
|
||||
# 使用datetime对象进行比较
|
||||
if (start_date_dt and create_time_dt < start_date_dt) or (end_date_dt and create_time_dt > end_date_dt):
|
||||
continue
|
||||
new_conversation_dict[conversation_id] = conversation_rows
|
||||
conversation_dict = new_conversation_dict
|
||||
|
||||
logger.info(f"会话总数为 {len(conversation_dict)},处理全部会话")
|
||||
|
||||
# 使用线程池处理每个会话
|
||||
@@ -566,7 +604,7 @@ class DialogueToWorkorder:
|
||||
columns_order = [
|
||||
'工单编号', '产品线', '产品名称', '模块名称', '问题类型',
|
||||
'客户问题', '解决方案', '是否抱怨', "抱怨内容", '是否投诉', '抱怨级别',
|
||||
'会话id', '访客昵称', '处理坐席', '创建时间'
|
||||
'会话id', '访客昵称', '处理坐席', "处理人", "处理技能组",'创建时间'
|
||||
]
|
||||
|
||||
# 确保所有列都存在,如果不存在则添加空列
|
||||
@@ -615,6 +653,8 @@ class DialogueToWorkorder:
|
||||
'会话id': 9,
|
||||
'访客昵称': 9,
|
||||
'处理坐席': 9,
|
||||
'处理人': 9,
|
||||
'处理技能组': 9,
|
||||
'创建时间': 9
|
||||
}
|
||||
|
||||
@@ -640,9 +680,9 @@ def parse_arguments():
|
||||
help='产品详情Excel文件路径')
|
||||
parser.add_argument('--max_workers', type=int, default=16,
|
||||
help='并发处理线程数,默认为16')
|
||||
parser.add_argument('--start_date', type=str, required=False,default="2025-05-01 00:00:00",
|
||||
parser.add_argument('--start_date', type=str, required=False,default="2025-06-10 16:08:00",
|
||||
help='开始日期,格式为YYYY-MM-DD')
|
||||
parser.add_argument('--end_date', type=str, required=False,default="2025-05-24 23:59:59",
|
||||
parser.add_argument('--end_date', type=str, required=False,default="2025-06-30 23:59:59",
|
||||
help='结束日期,格式为YYYY-MM-DD')
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
Reference in New Issue
Block a user