删除多余代码
This commit is contained in:
@@ -11,6 +11,7 @@ import logging
|
||||
import os
|
||||
import asyncio
|
||||
from langchain.output_parsers import PydanticOutputParser
|
||||
from langchain_core.output_parsers import JsonOutputParser
|
||||
import json
|
||||
from typing import List, Tuple, Dict, Any, Optional
|
||||
import re
|
||||
@@ -23,11 +24,6 @@ from .PromptTemplates import (classification_prompt, query_rewrite_prompt_pro,
|
||||
slot_filling_prompt, step_back_prompt,
|
||||
follow_up_questions_prompt, hyde_prompt, multi_questions_prompt)
|
||||
|
||||
from .Multi_PromptTemplates import (
|
||||
intent_and_slot_prompt, output_example,
|
||||
generate_slot_mapping_doc
|
||||
)
|
||||
|
||||
from .DataModels import (
|
||||
Classification, QueryRewrite, Term, TermList,
|
||||
SoftwareFunctionSlots, SoftwareTroubleShootingSlots, ProfessionalConsultingSlots,
|
||||
@@ -197,7 +193,7 @@ class AsyncIntentRecognizer:
|
||||
|
||||
return filtered_tokens
|
||||
|
||||
async def _extract_keywords_with_llm_async(self, query: str, use_jieba: bool = False) -> List[Term]:
|
||||
async def _extract_keywords_async(self, query: str, use_jieba: bool = False) -> List[Term]:
|
||||
"""
|
||||
异步使用LLM从用户查询中提取专业关键词
|
||||
|
||||
@@ -289,7 +285,7 @@ class AsyncIntentRecognizer:
|
||||
# 步骤1: 使用LLM提取查询中的关键词
|
||||
try:
|
||||
llm_start_time = time.time()
|
||||
extracted_terms = await self._extract_keywords_with_llm_async(query, use_jieba)
|
||||
extracted_terms = await self._extract_keywords_async(query, use_jieba)
|
||||
for term in extracted_terms:
|
||||
query_keys.append(term.name)
|
||||
llm_end_time = time.time()
|
||||
@@ -328,7 +324,8 @@ class AsyncIntentRecognizer:
|
||||
|
||||
# 合并所有结果
|
||||
for result in keyword_results:
|
||||
matched_terms.extend(result)
|
||||
if len(result) > 0:
|
||||
matched_terms.extend(result)
|
||||
|
||||
vector_end_time = time.time()
|
||||
vector_time = vector_end_time - vector_start_time
|
||||
@@ -383,26 +380,6 @@ class AsyncIntentRecognizer:
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"解析问题改写结果时出错: {e}") from e
|
||||
|
||||
def _judge_define_suffix(self, input_str: str) -> Tuple[bool, List[str]]:
|
||||
"""
|
||||
判断输入字符串是否包含定义的后缀,并返回所有匹配到的后缀名列表
|
||||
|
||||
Args:
|
||||
input_str: 输入字符串
|
||||
|
||||
Returns:
|
||||
Tuple[bool, List[str]]: (是否包含定义的后缀, 匹配到的后缀名列表)
|
||||
"""
|
||||
|
||||
# 构建正则表达式模式,匹配大小写不敏感且前面可能带有.
|
||||
pattern = r'(?:\.?)(' + '|'.join(re.escape(field.get('name')) for field in self._suffix_keywords) + r')'
|
||||
|
||||
# 使用 re.IGNORECASE 标志来忽略大小写,findall找到所有匹配
|
||||
matches = re.finditer(pattern, input_str, re.IGNORECASE)
|
||||
matched_suffixes = [match.group(1) for match in matches]
|
||||
|
||||
return bool(matched_suffixes), matched_suffixes
|
||||
|
||||
def _process_lock_related_query(self, query: str) -> str:
|
||||
"""
|
||||
特殊处理锁相关咨询
|
||||
@@ -786,7 +763,8 @@ class AsyncIntentRecognizer:
|
||||
# 解析JSON响应
|
||||
try:
|
||||
wiki_names = []
|
||||
json_response = json.loads(response.content)
|
||||
json_parser = JsonOutputParser()
|
||||
json_response = json_parser.parse(response.content)
|
||||
for match in json_response:
|
||||
wiki_names.append(match["content"])
|
||||
logging.debug(f"软件文档匹配耗时: {end_time - start_time:.2f}秒")
|
||||
@@ -838,97 +816,4 @@ class AsyncIntentRecognizer:
|
||||
except Exception as e:
|
||||
# 如果解析失败,返回原始查询作为唯一子问题
|
||||
logging.error(f"异步多角度问题生成失败: {e}", exc_info=True)
|
||||
return MultiQuestions(original_query=query, sub_questions=[query])
|
||||
|
||||
async def _process_intent_and_slot_async(self, user_input: str, conversation_context: str = "",
|
||||
chat_history: List[Dict[str, str]] = None,
|
||||
previous_slots: Dict[str, Any] = None) -> Dict[str, Any]:
|
||||
"""
|
||||
异步使用统一提示词同时进行意图识别和槽位填充
|
||||
|
||||
Args:
|
||||
user_input: 当前用户输入
|
||||
conversation_context: 会话背景信息
|
||||
chat_history: 历史对话记录,格式为[{"role": "user", "content": "..."}, {"role": "assistant", "content": "..."}]
|
||||
previous_slots: 历史槽位信息
|
||||
|
||||
Returns:
|
||||
包含意图分类和槽位填充结果的字典
|
||||
"""
|
||||
# 初始化默认值
|
||||
if chat_history is None:
|
||||
chat_history = []
|
||||
|
||||
if previous_slots is None:
|
||||
previous_slots = {}
|
||||
|
||||
# 生成槽位映射文档
|
||||
slot_mapping_doc = generate_slot_mapping_doc()
|
||||
|
||||
# 准备提示词
|
||||
parser = PydanticOutputParser(pydantic_object=IntentAndSlotResult)
|
||||
formatted_prompt = intent_and_slot_prompt.format(
|
||||
conversation_context=conversation_context,
|
||||
chat_history=json.dumps(chat_history, ensure_ascii=False),
|
||||
previous_slots=json.dumps(previous_slots, ensure_ascii=False),
|
||||
user_input=user_input,
|
||||
slot_mapping_doc=slot_mapping_doc,
|
||||
output_format=parser.get_format_instructions(),
|
||||
classification_info=classification_info
|
||||
)
|
||||
|
||||
# 异步调用LLM
|
||||
llm_start_time = time.time()
|
||||
response = await self._llm.invoke_async(formatted_prompt + output_example, False)
|
||||
llm_end_time = time.time()
|
||||
llm_time = llm_end_time - llm_start_time
|
||||
|
||||
try:
|
||||
# 解析LLM响应为JSON
|
||||
response.content = response.content.strip()
|
||||
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
|
||||
result_json = parser.parse(clean_output)
|
||||
classification = result_json.classification
|
||||
slot_filling = result_json.slots
|
||||
is_complete, missing_slots = slot_filling.check_required_slots()
|
||||
expected_slot_model = self._get_slot_model(classification)
|
||||
|
||||
# 添加容错处理,发生概率较低,但仍需处理
|
||||
if expected_slot_model is None:
|
||||
# 添加容错处理,应对LLM返回错误分类信息,一级分类跟二级分类错乱
|
||||
# 重新分类
|
||||
classification = await self._classify_intent_async(user_input, conversation_context, chat_history, previous_slots)
|
||||
fill_slots = await self._fill_slots_async(user_input, classification, conversation_context, chat_history, previous_slots)
|
||||
|
||||
result = {
|
||||
"classification": classification.model_dump(),
|
||||
"slot_filling": fill_slots
|
||||
}
|
||||
logging.warning(f"异步重新分类与槽点填充")
|
||||
return result
|
||||
elif expected_slot_model.__name__ != type(slot_filling).__name__:
|
||||
# 添加容错处理,应对LLM槽位与分类不匹配。重新填充槽位
|
||||
slot_filling = await self._fill_slots_async(user_input, classification, conversation_context, chat_history, previous_slots)
|
||||
result = {
|
||||
"classification": classification.model_dump(),
|
||||
"slot_filling": slot_filling
|
||||
}
|
||||
logging.warning(f"异步重新填充槽点")
|
||||
return result
|
||||
|
||||
logging.info(f"异步意图识别+槽位LLM调用耗时: {llm_time:.2f}秒")
|
||||
|
||||
# 构建最终结果
|
||||
result = {
|
||||
"classification": classification.model_dump(),
|
||||
"slot_filling": {
|
||||
"is_complete": is_complete,
|
||||
"missing_slots": missing_slots,
|
||||
"filled_data": slot_filling.model_dump()
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"异步process_intent_and_slot error:{e}") from e
|
||||
return MultiQuestions(original_query=query, sub_questions=[query])
|
||||
Reference in New Issue
Block a user