from typing import List, Dict, Any # from llm import llm as llm_model from utils.llm import search_llm as llm_model from utils.prompt import RESPONSE_TEMPLATE import time import logging import sys # 配置日志 logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[logging.StreamHandler(sys.stdout)] ) logger = logging.getLogger("ResponseGenerator") class ResponseGenerator: def __init__(self): """初始化响应生成器,使用自定义的llm模型""" logger.info("ResponseGenerator初始化完成") def generate_response(self, query: str, retrieved_info: List[Dict[str, Any]], nlu_data: Dict = None) -> str: """ 生成响应 参数: query: 用户查询 retrieved_info: 检索到的信息 nlu_data: 意图识别和槽位提取的结果 返回: 生成的响应 """ # 如果没有检索到信息,返回默认回答 if not retrieved_info: logger.warning("没有检索到相关信息,返回默认回答") return "抱歉,我没有找到与您问题相关的信息。请尝试使用其他关键词或更具体的问题。" # 构建提示 logger.info("开始构建提示") prompt = self._build_prompt(query, retrieved_info, nlu_data) logger.info(f"提示构建完成,长度: {len(prompt)}") # 调用自定义LLM模型生成回答 logger.info("开始调用LLM模型生成回答") start_time = time.time() try: # 添加超时处理 response = llm_model.invoke(prompt) logger.info(f"LLM响应完成,耗时: {time.time() - start_time:.2f}秒") # 检查响应是否为空 if not response or not response.strip(): logger.error("LLM返回了空响应") return "抱歉,生成回答时出现了问题。请稍后再试。" return response except Exception as e: logger.error(f"调用LLM模型时出错: {str(e)}") return f"抱歉,生成回答时出现了错误: {str(e)}" def _build_prompt(self, query: str, retrieved_info: List[Dict[str, Any]], nlu_data: Dict = None) -> str: """ 构建提示 参数: query: 用户查询 retrieved_info: 检索到的信息 nlu_data: 意图识别和槽位提取的结果 返回: 构建的提示 """ context_parts = [] for info in retrieved_info: node = info.get("node", {}) text = info.get("text", "") node_type = node.get("labels", [""])[0] if "labels" in node else "" name = node.get("original_name", "") or node.get("display_name", "") description = node.get("描述", "") if node_type == "功能名称": context_parts.append(f"功能: {name}\n描述: {description}") else: context_parts.append(f"{node_type}: {name}") context = "\n\n".join(context_parts) # 添加意图和槽位信息 intent_info = "" if nlu_data and '意图' in nlu_data: intent_data = nlu_data['意图'] # 获取一级意图 first_intent = "未知" if '一级意图' in intent_data and 'name' in intent_data['一级意图']: first_intent = intent_data['一级意图']['name'] # 获取二级意图 second_intent = "未知" if '二级意图' in intent_data and 'name' in intent_data['二级意图']: second_intent = intent_data['二级意图']['name'] intent_info = f"用户一级意图: {first_intent}\n用户二级意图: {second_intent}\n" # 添加槽位信息 if '二级意图' in intent_data and 'slot_lv2' in intent_data['二级意图']: slots = intent_data['二级意图']['slot_lv2'] if slots: intent_info += "提取的槽位:\n" for slot_name, slot_value in slots.items(): if slot_value and slot_value != '未知': intent_info += f"- {slot_name}: {slot_value}\n" prompt = RESPONSE_TEMPLATE.format( intent_info=intent_info, context=context, query=query ) return prompt