更新对话转工单处理逻辑,优化用户问题和解决方案提取功能,调整LLM参数,增强错误处理机制,改进多线程处理效率,更新测试用例以支持新功能,提升代码可读性和结构。

This commit is contained in:
2025-06-04 17:37:47 +08:00
parent 0e396e8b67
commit 01dc1c3c91
2 changed files with 147 additions and 66 deletions
+43 -21
View File
@@ -11,12 +11,13 @@ from langchain.output_parsers import PydanticOutputParser
from rag2_0.tool.ModelTool import OpenAiLLM
from dotenv import load_dotenv
import openpyxl
import re
load_dotenv()
# ================ 模型定义 ================
class UserQuestionAndSolution(BaseModel):
user_question: str = Field(description="客户问题")
user_question: str = Field(description="用户的核心问题")
solution: str = Field(description="坐席提供的解决方案")
class UserQuestionAndSolutionList(BaseModel):
@@ -90,7 +91,8 @@ class DialogueToWorkorder:
# 初始化LLM模型
self.llm_params = llm_params or {
"temperature": 0.2,
"model": os.getenv("LLM_MODEL_NAME"),
"top_p":0.95,
"model": "deepseek-ai/DeepSeek-R1",
"api_key": os.getenv("OPENAI_API_KEY"),
"base_url": os.getenv("OPENAI_API_BASE")
}
@@ -207,18 +209,21 @@ class DialogueToWorkorder:
"""分析用户问题和解决方案"""
dialogue_str = self.get_dialogue_str(conversation_rows)
prompt = """请从以下电力造价相关的客服对话记录中,识别并总结用户提出的问题及对应坐席提供的解决方案。(注意指代消除)
1、理解对话记录,总结用户在此次对话中提出的核心诉求(希望解决的问题)。以用户的角度总结
2、根据用户提出的诉求,分析坐席提供的解决方法(比如:1、引导用户xxxx。2、告诉用户xxxxx)。以坐席的角度直接总结解决方案(不要出现"坐席"""等字样)
3、使用json格式输出(多个用户诉求采用数组格式输出):
prompt = """请从以下电力造价相关的客服对话记录中,识别并总结用户提出的核心问题及对应坐席提供的解决方案。(注意指代消除)
1、理解对话记录,总结用户在此次对话中提出的核心问题,以用户的角度总结核心问题(可根据上下文完善问题内容)
2、根据用户提出的问题,分析坐席提供的解决方法(比如:1、引导用户xxxx。2、告诉用户xxxxx)。以坐席的角度直接总结完整的解决方案或应对措施(不要出现"坐席"""等字样)
3、提炼访客独立的核心问题(以访客的角度总结核心问题),核心问题衍生、细化后的请求合并到对应的核心问题中。不要单独列出衍生、细化后的请求。
4、使用json格式输出(多个用户问题采用标准json数组格式输出):
{output_format}
输出示例:
```json
{{
"user_question": "软件打开报错",
"solution": "通过远程引导解决"
"user_question": "技改软件打开报错",
"solution": "1、告知报错原因 2、通过远程辅助解决"
}}
```
=======对话记录如下所示=======
{dialogue_str}
============================
@@ -227,22 +232,38 @@ class DialogueToWorkorder:
llm_prompt = prompt.format(output_format=output_format, dialogue_str=dialogue_str)
response = self.llm.invoke(user_prompt=llm_prompt)
if 'reasoning_content' not in response.model_extra and self.llm._model == 'deepseek-ai/DeepSeek-R1':
print("deepseek-ai/DeepSeek-R1 解析失败")
try:
if response.content.count('user_question') == 1:
user_question_and_solution = self.user_question_and_solution_parser.parse(response.content)
return [user_question_and_solution]
else:
raise Exception("解析失败")
array_pattern = r'\[\s*(\{[\s\S]*?\}(?:\s*,\s*\{[\s\S]*?\})*)\s*\]'
array_match = re.search(array_pattern, response.content)
if array_match:
# 找到了JSON数组
json_array_str = '[' + array_match.group(1) + ']'
# 尝试解析JSON
json_objects = json.loads(json_array_str)
user_question_and_solution_list = []
for obj in json_objects:
user_question = obj.get('user_question', '')
solution = obj.get('solution', '')
user_question_and_solution_list.append(
UserQuestionAndSolution(user_question=user_question, solution=solution)
)
if user_question_and_solution_list:
return user_question_and_solution_list
raise Exception("解析失败") # 如果之前没有return 触发异常重新提取
except Exception as e:
output_format = self.user_question_and_solution_list_parser.get_format_instructions()
llm_prompt = prompt.format(output_format=output_format, dialogue_str=dialogue_str)
response = self.llm.invoke(user_prompt=llm_prompt)
user_question_and_solution = self.user_question_and_solution_list_parser.parse(response.content)
return user_question_and_solution.user_question_list
user_question_and_solution_temp = self.user_question_and_solution_list_parser.parse(response.content)
return user_question_and_solution_temp.user_question_list
return [user_question_and_solution]
@@ -348,15 +369,14 @@ class DialogueToWorkorder:
dialogue_str = self.get_dialogue_str(conversation_rows)
prompt = f"""
请根据以下对话记录分析访客情绪是否对博微软件或者坐席服务存在明显抱怨,并按照以下结构输出JSON格式分析结果:
请根据以下对话记录分析访客情绪是否对软件或者坐席服务存在明显抱怨,并按照以下结构输出JSON格式分析结果:
1. 抱怨识别:判断访客是否对博微软件功能或者坐席服务存在抱怨或不满
1. 抱怨识别:判断访客是否对软件功能或者坐席服务存在明显抱怨或不满
2. 抱怨分级(如存在抱怨):
- 一般抱怨:明确表达出对博微软件功能或者坐席服务存在不满
- 中等抱怨:明确表达出对博微软件功能或者坐席服务存在不满,语气较为强烈
- 严重抱怨:对博微软件功能或者坐席服务使用激烈言辞
- 普通抱怨:明确表达出对软件功能或者坐席服务存在不满
- 严重抱怨:明确表达出对软件功能或者坐席服务存在不满,语气较为强烈
3. 投诉倾向:是否明确/暗示将进行投诉
4. 抱怨对象:坐席服务态度/业务能力 或 博微功能问题(注意忽略对非博微软件或坐席的抱怨)
4. 抱怨对象:坐席服务态度/业务能力 或 软件功能问题(注意忽略对非软件或坐席的抱怨)
示例输出:
{{
@@ -384,6 +404,8 @@ class DialogueToWorkorder:
def process_conversation(self, conversation_id, conversation_rows, product_detail_dict):
"""处理单个会话的函数,用于多线程并发"""
# if conversation_id!="b157aa91-3acb-11f0-a191-4fb224ef4b40":
# return []
# 获取工单基本信息
base_workorder_dict = self.get_workorder_dict(conversation_rows)
# 分析用户问题和解决方案