Files
GraphRAG/graph/generator.py
T
2025-03-31 17:28:23 +08:00

125 lines
4.6 KiB
Python

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