LLM输出的内容先通过正则清理多余内容
This commit is contained in:
@@ -132,9 +132,48 @@ class QueryRewrite(BaseModel):
|
||||
"rewrite": "问题改写"
|
||||
}
|
||||
字段说明:
|
||||
rewrite 类型:str 描述:问题改写之后的内容
|
||||
"rewrite" 类型:str 描述:问题改写之后的内容
|
||||
"""
|
||||
|
||||
|
||||
# 意图优化环节数据模型
|
||||
class StepBackPrompt(BaseModel):
|
||||
"""后退提示数据模型"""
|
||||
original_query: str = Field(description="原始查询")
|
||||
can_use_back_prompt: bool = Field(description="原始查询是否可以进行后退提示(true/false),如果原始查询没有限定词或其他限定词语,则不能进行后退提示")
|
||||
step_back_query: List[str] = Field(description="后退提示生成的抽象查询(多个)")
|
||||
|
||||
@classmethod
|
||||
def get_format_instructions(cls):
|
||||
return """
|
||||
格式如下,必须严格以纯JSON格式输出
|
||||
{
|
||||
"original_query": "原始查询",
|
||||
"can_use_back_prompt": "原始查询是否可以进行后退提示(true/false),如果原始查询没有限定词或其他限定词语,则不能进行后退提示",
|
||||
"step_back_query": "后退提示生成的抽象查询(多个)"
|
||||
}
|
||||
字段说明:
|
||||
"original_query" 类型:str 描述:用户输入的原始查询
|
||||
"can_use_back_prompt" 类型:bool 描述:原始查询是否可以进行后退提示(true/false),如果原始查询没有限定词或其他限定词语,则不能进行后退提示
|
||||
"step_back_query" 类型:list[str] 描述:后退提示生成的抽象查询(多个)
|
||||
"""
|
||||
|
||||
|
||||
class FollowUpQuestions(BaseModel):
|
||||
"""后续问题数据模型"""
|
||||
original_query: str = Field(description="原始查询")
|
||||
follow_up_query: str = Field(description="基于历史对话生成的独立问题")
|
||||
|
||||
class HypotheticalDocument(BaseModel):
|
||||
"""假设文档数据模型"""
|
||||
original_query: str = Field(description="原始查询")
|
||||
hypothetical_answer: str = Field(description="假设性回答")
|
||||
|
||||
class MultiQuestions(BaseModel):
|
||||
"""多问题查询数据模型"""
|
||||
original_query: str = Field(description="原始查询")
|
||||
sub_questions: List[str] = Field(description="从不同角度生成的子问题列表")
|
||||
|
||||
##########################槽位模型###########################
|
||||
class SlotBase(BaseModel):
|
||||
"""槽位基础模型"""
|
||||
@@ -329,41 +368,3 @@ class IntentAndSlotResult(BaseModel):
|
||||
ProblemDiagnosisSlots,
|
||||
OtherSlots
|
||||
]
|
||||
|
||||
# 意图优化环节数据模型
|
||||
class StepBackPrompt(BaseModel):
|
||||
"""后退提示数据模型"""
|
||||
original_query: str = Field(description="原始查询")
|
||||
can_use_back_prompt: bool = Field(description="原始查询是否可以进行后退提示(true/false),如果原始查询没有限定词或其他限定词语,则不能进行后退提示")
|
||||
step_back_query: List[str] = Field(description="后退提示生成的抽象查询(多个)")
|
||||
|
||||
@classmethod
|
||||
def get_format_instructions(cls):
|
||||
return """
|
||||
格式如下,必须严格以纯JSON格式输出
|
||||
{
|
||||
"original_query": "原始查询",
|
||||
"can_use_back_prompt": "原始查询是否可以进行后退提示(true/false),如果原始查询没有限定词或其他限定词语,则不能进行后退提示",
|
||||
"step_back_query": "后退提示生成的抽象查询(多个)"
|
||||
}
|
||||
字段说明:
|
||||
original_query 类型:str 描述:用户输入的原始查询
|
||||
can_use_back_prompt 类型:bool 描述:原始查询是否可以进行后退提示(true/false),如果原始查询没有限定词或其他限定词语,则不能进行后退提示
|
||||
step_back_query 类型:List[str] 描述:后退提示生成的抽象查询(多个)
|
||||
"""
|
||||
|
||||
|
||||
class FollowUpQuestions(BaseModel):
|
||||
"""后续问题数据模型"""
|
||||
original_query: str = Field(description="原始查询")
|
||||
follow_up_query: str = Field(description="基于历史对话生成的独立问题")
|
||||
|
||||
class HypotheticalDocument(BaseModel):
|
||||
"""假设文档数据模型"""
|
||||
original_query: str = Field(description="原始查询")
|
||||
hypothetical_answer: str = Field(description="假设性回答")
|
||||
|
||||
class MultiQuestions(BaseModel):
|
||||
"""多问题查询数据模型"""
|
||||
original_query: str = Field(description="原始查询")
|
||||
sub_questions: List[str] = Field(description="从不同角度生成的子问题列表")
|
||||
@@ -170,6 +170,24 @@ class AsyncIntentRecognizer:
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"加载后缀关键词失败: {e}") from e
|
||||
|
||||
def _clean_llm_json(self, content: str) -> str:
|
||||
"""
|
||||
统一清洗LLM返回的JSON字符串:
|
||||
1) 去首尾空白
|
||||
2) 去除<think>…</think>段
|
||||
3) 通过第一个"{"与最后一个"}"裁剪内容,移除首尾多余字符
|
||||
4) 压缩所有空白字符
|
||||
"""
|
||||
content = content.strip()
|
||||
content = re.sub(r'<think>.*?</think>', '', content, flags=re.DOTALL)
|
||||
# 裁剪到最外层花括号范围
|
||||
start = content.find('{')
|
||||
end = content.rfind('}')
|
||||
if start != -1 and end != -1 and start < end:
|
||||
content = content[start:end+1]
|
||||
content = re.sub(r'\s+', '', content)
|
||||
return content
|
||||
|
||||
async def _classify_intent_async(self, query: str, conversation_context: str = "",
|
||||
chat_history: List[Dict[str, str]] = None,
|
||||
previous_slots: Dict[str, Any] = None) -> Classification:
|
||||
@@ -194,13 +212,11 @@ class AsyncIntentRecognizer:
|
||||
# 解析输出
|
||||
try:
|
||||
# 异步调用LLM
|
||||
response = await self._llm.ainvoke(formatted_prompt, response_format={"type": "json_object"}, extra_body={"enable_thinking": False})
|
||||
# response = await self._llm.ainvoke(formatted_prompt, extra_body={"enable_thinking": False})
|
||||
# response = await self._llm.ainvoke(formatted_prompt, response_format={"type": "json_object"}, extra_body={"enable_thinking": False})
|
||||
response = await self._llm.ainvoke(formatted_prompt, response_format={"type": "json_object"})
|
||||
|
||||
# 尝试直接解析JSON响应
|
||||
response.content = response.content.strip()
|
||||
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
|
||||
clean_output = re.sub(r'\s+', '', clean_output)
|
||||
clean_output = self._clean_llm_json(response.content)
|
||||
parsed_output = classification_parser.parse(clean_output)
|
||||
|
||||
# 计算并打印耗时
|
||||
@@ -264,13 +280,11 @@ class AsyncIntentRecognizer:
|
||||
formatted_prompt = formatted_prompt.replace("{output_format}", terms_list_parser.get_format_instructions())
|
||||
|
||||
# 异步调用LLM
|
||||
response = await self._llm.ainvoke(formatted_prompt, response_format={"type": "json_object"}, extra_body={"enable_thinking": False})
|
||||
# response = await self._llm.ainvoke(formatted_prompt, extra_body={"enable_thinking": False})
|
||||
# response = await self._llm.ainvoke(formatted_prompt, response_format={"type": "json_object"}, extra_body={"enable_thinking": False})
|
||||
response = await self._llm.ainvoke(formatted_prompt, response_format={"type": "json_object"})
|
||||
|
||||
# 尝试使用Pydantic解析器解析TermList
|
||||
response.content = response.content.strip()
|
||||
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
|
||||
clean_output = re.sub(r'\s+', '', clean_output)
|
||||
clean_output = self._clean_llm_json(response.content)
|
||||
parsed_output = terms_list_parser.parse(clean_output)
|
||||
return parsed_output.terms
|
||||
|
||||
@@ -341,20 +355,16 @@ class AsyncIntentRecognizer:
|
||||
1、请从当前提问内容中提取电力造价行中定额编码、定额名称、清单编码、清单名称
|
||||
2、请勿随机编造,如果没有提取到内容返回空的JSON
|
||||
3、返回结果为json格式,必须严格以纯JSON格式输出
|
||||
```json
|
||||
{{
|
||||
"dinge_info_list":{{"dinge_code_list":["xxxx","xxxx"], "dinge_name_list":["xxxx","xxxx"]}},
|
||||
"qingdan_info":{{"qingdan_code_list":["xxxx","xxxx"], "qingdan_name_list":["xxxx","xxxx"]}}
|
||||
}}
|
||||
```json
|
||||
"""
|
||||
|
||||
try:
|
||||
response = await self._llm.ainvoke(prompt, response_format={"type": "json_object"}, extra_body={"enable_thinking": False})
|
||||
# response = await self._llm.ainvoke(prompt, extra_body={"enable_thinking": False})
|
||||
response.content = response.content.strip()
|
||||
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
|
||||
clean_output = re.sub(r'\s+', '', clean_output)
|
||||
# response = await self._llm.ainvoke(prompt, response_format={"type": "json_object"}, extra_body={"enable_thinking": False})
|
||||
response = await self._llm.ainvoke(prompt, response_format={"type": "json_object"})
|
||||
clean_output = self._clean_llm_json(response.content)
|
||||
parsed_output = JsonOutputParser().parse(clean_output)
|
||||
|
||||
# 计算并打印耗时
|
||||
@@ -393,11 +403,9 @@ class AsyncIntentRecognizer:
|
||||
# 解析输出
|
||||
try:
|
||||
# 异步调用LLM
|
||||
response = await self._llm.ainvoke(formatted_prompt,response_format={"type": "json_object"}, extra_body={"enable_thinking": False})
|
||||
# response = await self._llm.ainvoke(formatted_prompt, extra_body={"enable_thinking": False})
|
||||
response.content = response.content.strip()
|
||||
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
|
||||
clean_output = re.sub(r'\s+', '', clean_output)
|
||||
# response = await self._llm.ainvoke(formatted_prompt,response_format={"type": "json_object"}, extra_body={"enable_thinking": False})
|
||||
response = await self._llm.ainvoke(formatted_prompt,response_format={"type": "json_object"})
|
||||
clean_output = self._clean_llm_json(response.content)
|
||||
parsed_output = query_rewrite_parser.parse(clean_output)
|
||||
end_time = time.time()
|
||||
process_time=end_time-start_time
|
||||
@@ -642,9 +650,7 @@ class AsyncIntentRecognizer:
|
||||
# 异步调用LLM
|
||||
response = await self._llm.ainvoke(formatted_prompt,response_format={"type": "json_object"}, extra_body={"enable_thinking": False})
|
||||
# response = await self._llm.ainvoke(formatted_prompt, extra_body={"enable_thinking": False})
|
||||
response.content = response.content.strip()
|
||||
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
|
||||
clean_output = re.sub(r'\s+', '', clean_output)
|
||||
clean_output = self._clean_llm_json(response.content)
|
||||
# 尝试解析LLM响应
|
||||
parsed_output = slot_parser.parse(clean_output)
|
||||
return parsed_output
|
||||
@@ -677,22 +683,18 @@ class AsyncIntentRecognizer:
|
||||
|
||||
try:
|
||||
# 异步调用LLM
|
||||
response = await self._llm.ainvoke(formatted_prompt, response_format={"type": "json_object"}, extra_body={"enable_thinking": False})
|
||||
# response = await self._llm.ainvoke(formatted_prompt, extra_body={"enable_thinking": False})
|
||||
# response = await self._llm.ainvoke(formatted_prompt, response_format={"type": "json_object"}, extra_body={"enable_thinking": False})
|
||||
response = await self._llm.ainvoke(formatted_prompt, response_format={"type": "json_object"})
|
||||
|
||||
# 解析输出
|
||||
response.content = response.content.strip()
|
||||
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
|
||||
clean_output = re.sub(r'\s+', '', clean_output)
|
||||
clean_output = self._clean_llm_json(response.content)
|
||||
parsed_output = step_back_parser.parse(clean_output)
|
||||
step_back_end_time = time.time()
|
||||
step_back_time = step_back_end_time - step_back_start_time
|
||||
logging.info(f"后退提示生成耗时统计 - 总耗时: {step_back_time:.2f}秒")
|
||||
return parsed_output
|
||||
except Exception as e:
|
||||
# 如果解析失败,返回原始查询作为后退提示
|
||||
logging.error(f"后退提示生成失败: {e}", exc_info=True)
|
||||
return StepBackPrompt(original_query=query, can_use_back_prompt=False, step_back_query=[query])
|
||||
raise RuntimeError(f"解析后退提示结果时出错: {e}") from e
|
||||
|
||||
async def _find_matching_software_docs_async(self, query: str, soft_name: str,
|
||||
chat_history: List[Dict[str, str]] = None,
|
||||
@@ -739,7 +741,8 @@ class AsyncIntentRecognizer:
|
||||
try:
|
||||
# 异步调用LLM
|
||||
start_time = time.time()
|
||||
response = await self._llm.ainvoke(prompt, response_format={"type": "json_object"}, extra_body={"enable_thinking": False})
|
||||
# response = await self._llm.ainvoke(prompt, response_format={"type": "json_object"}, extra_body={"enable_thinking": False})
|
||||
response = await self._llm.ainvoke(prompt, response_format={"type": "json_object"})
|
||||
end_time = time.time()
|
||||
|
||||
# 解析JSON响应
|
||||
|
||||
Reference in New Issue
Block a user