更新对话转工单处理逻辑,增强用户问题和解决方案提取功能,添加槽位填充支持,调整最大工作线程数为10,优化意图识别API,重排序匹配术语,改进数据模型以支持软件名称枚举,提升代码结构和可读性。

This commit is contained in:
2025-06-03 10:35:25 +08:00
parent d4ff7b6fad
commit 38b6f66925
8 changed files with 160 additions and 92 deletions
+44 -21
View File
@@ -148,6 +148,40 @@ class IntentRecognizer:
except Exception as e:
raise RuntimeError(f"无法解析LLM关键词提取响应: {e}") from e
def rerank_matched_terms(self, query_key: str, matched_terms: set, top_k: int = 2) -> List[Term]:
"""
对召回的专业术语进行重排序,按与用户查询的相关性排序
Args:
query: 用户查询
matched_terms: 匹配到的专业术语集合
query_keys: 用户查询中提取的关键词列表
Returns:
重排序后的专业术语列表
"""
if not matched_terms:
return []
try:
# 将每个术语转换为可用于重排序的文本表示
term_texts = ["名称:" + term.name + "|" + "同义词:" + ";".join(term.synonymous) + "|" + "描述:" + term.description for term in matched_terms]
# 使用重排序模型
xinference_reranker = SiliconFlowReRankerModel()
rerank_results = xinference_reranker.rerank(query_key, term_texts, top_k=top_k)
# 将matched_terms转换为列表以便按索引访问
matched_terms_list = list(matched_terms)
# 根据重排序结果获取排序后的术语列表
reranked_terms = [matched_terms_list[result["index"]] for result in rerank_results if result["score"] >= 0.6]
return reranked_terms
except Exception as e:
return list(matched_terms)
def match_keywords(self, query: str) -> Tuple[TermList, List[str]]:
"""
从用户问题中匹配关键词,结合LLM提取和向量检索
@@ -158,7 +192,6 @@ class IntentRecognizer:
Returns:
匹配到的关键词列表
"""
matched_terms = set() # 存储匹配到的Term对象
query_keys=[]
# 步骤2: 使用LLM提取查询中的关键词
try:
@@ -168,12 +201,13 @@ class IntentRecognizer:
except Exception as e:
raise RuntimeError(f"LLM关键词提取失败: {e}") from e
matched_terms = [] # 存储匹配到的Term对象
# 步骤3: 使用向量检索找到相似的专业名词
try:
# 对matched_terms中的每个关键字进行向量检索
for current_key in query_keys:
vector_results = self.noun_retriever.query(current_key, top_k=3, use_intersection=True)
current_key_terms = set()
# 添加向量检索结果
for result in vector_results:
term = Term(
@@ -181,18 +215,12 @@ class IntentRecognizer:
synonymous=result.get('synonymous', []),
description=result.get('description', '')
)
matched_terms.add(term)
current_key_terms.add(term)
reranked_terms = self.rerank_matched_terms(current_key, current_key_terms)
matched_terms.extend(reranked_terms)
except Exception as e:
raise RuntimeError(f"向量检索关键词时出错: {e}") from e
if len(matched_terms) != 0:
txts = ["名称:" + term.name + "|" + "同义词:" + ";".join(term.synonymous) + "|" + "描述:" + term.description for term in matched_terms]
# txts = [term.name for term in matched_terms]
xinference_reranker = SiliconFlowReRankerModel()
rerank_results = xinference_reranker.rerank(query, txts, top_k=5)
matched_terms_list = list(matched_terms)
matched_terms = [matched_terms_list[result["index"]] for result in rerank_results]
# 提取所有Term对象的名称并排序
# 将set类型的matched_terms转换为TermList类型
term_list = TermList(terms=list(matched_terms))
@@ -295,7 +323,7 @@ class IntentRecognizer:
# rewrite = QueryRewrite(rewrite=query)
return classification, keywords_terms, rewrite, query_keys
def fill_slots(self, query: str, classification: Classification, keywords: TermList) -> Dict[str, Any]:
def fill_slots(self, query: str, classification: Classification) -> Dict[str, Any]:
"""
根据分类结果对问题进行槽位填充
@@ -313,7 +341,7 @@ class IntentRecognizer:
return {"error": "未找到匹配的槽位模型"}
# 使用LLM进行槽位填充
filled_slots = self._fill_slots_with_llm(query, classification, keywords, slot_model)
filled_slots = self._fill_slots_with_llm(query, classification, slot_model)
# 检查必填槽位是否都已填充
is_complete, missing_slots = filled_slots.check_required_slots()
@@ -349,7 +377,7 @@ class IntentRecognizer:
return DataProblem
# 安装下载注册
elif classification.vertical_classification == "安装下载":
elif classification.vertical_classification == "安装下载注册":
if classification.sub_classification == "后缀名咨询":
return FileExtensionConsulting
elif classification.sub_classification == "软件锁类":
@@ -361,14 +389,13 @@ class IntentRecognizer:
return None
def _fill_slots_with_llm(self, query: str, classification: Classification, keywords: TermList, slot_model_class: type) -> Any:
def _fill_slots_with_llm(self, query: str, classification: Classification, slot_model_class: type) -> Any:
"""
使用LLM进行槽位填充
Args:
query: 用户原始问题
classification: 意图分类结果
keywords: 匹配的关键词列表
slot_model_class: 槽位模型类
Returns:
@@ -377,15 +404,11 @@ class IntentRecognizer:
# 准备提示词
slot_parser = PydanticOutputParser(pydantic_object=slot_model_class)
model_schema = json.dumps(slot_model_class.model_json_schema(), ensure_ascii=False)
terms_dict = [term.model_dump() for term in keywords.terms]
keywords_str = json.dumps(terms_dict, ensure_ascii=False)
formatted_prompt = slot_filling_prompt.format(
query=query,
vertical_classification=classification.vertical_classification,
sub_classification=classification.sub_classification,
keywords=keywords_str,
model_schema=model_schema,
output_format=slot_parser.get_format_instructions()
)
@@ -417,7 +440,7 @@ class IntentRecognizer:
# 如果是有效分类,进行槽位填充
slot_filling_result = {}
if classification.vertical_classification not in ["其他", "闲聊"] and classification.sub_classification not in ["其他", "闲聊"]:
slot_filling_result = self.fill_slots(rewrite.rewrite, classification, keywords)
slot_filling_result = self.fill_slots(rewrite.rewrite, classification)
return {
"classification": classification.model_dump(),